incorporated all comments. * improved comment * just talloc_free(NULL) * don't break ctrl_interface_setup() API * L_CTRL_NODE
Neels Hofmeyr (3): vty: add bind command for telnet vty line add ctrl_interface_setup_dynip() for bind address vty: add ctrl section for Control interface bind address
include/Makefile.am | 3 +- include/osmocom/ctrl/control_if.h | 4 ++ include/osmocom/ctrl/control_vty.h | 9 ++++ include/osmocom/vty/command.h | 2 +- include/osmocom/vty/vty.h | 3 ++ src/ctrl/Makefile.am | 4 ++ src/ctrl/control_if.c | 10 ++++- src/ctrl/control_vty.c | 90 ++++++++++++++++++++++++++++++++++++++ src/vty/vty.c | 28 ++++++++++++ 9 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 include/osmocom/ctrl/control_vty.h create mode 100644 src/ctrl/control_vty.c
Add VTY command line vty bind A.B.C.D
The command merely stores the configured IP-address, which can then be used by the calling main program to set the telnet port of the VTY line. (Commits in openbsc and osmo-iuh will follow up on this.)
Add function vty_get_bind_addr() to publish the address in the vty.h API.
Add static vty_bind_addr to store.
For allocation/freeing reasons, a NULL address defaults to 127.0.0.1.
BTW, I decided against allowing keywords 'any' and 'localhost' in place of an actual IP address to make sure a written config is always identical to the parsed config. --- include/osmocom/vty/vty.h | 3 +++ src/vty/vty.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+)
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h index 3684397..43cb0cf 100644 --- a/include/osmocom/vty/vty.h +++ b/include/osmocom/vty/vty.h @@ -186,6 +186,9 @@ void *vty_current_index(struct vty *); int vty_current_node(struct vty *vty); int vty_go_parent(struct vty *vty);
+/* Return IP address passed to the 'line vty'/'bind' command, or "127.0.0.1" */ +const char *vty_get_bind_addr(void); + extern void *tall_vty_ctx;
extern struct cmd_element cfg_description_cmd; diff --git a/src/vty/vty.c b/src/vty/vty.c index 5bcbe4a..a4630fb 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -75,6 +75,12 @@ vector Vvty_serv_thread;
char *vty_cwd = NULL;
+/* IP address passed to the 'line vty'/'bind' command. + * Setting the default as vty_bind_addr = "127.0.0.1" doesn't allow freeing, so + * use NULL and VTY_BIND_ADDR_DEFAULT instead. */ +static const char *vty_bind_addr = NULL; +#define VTY_BIND_ADDR_DEFAULT "127.0.0.1" + /* Configure lock. */ static int vty_config;
@@ -1585,6 +1591,23 @@ DEFUN(no_vty_login, return CMD_SUCCESS; }
+/* vty bind */ +DEFUN(vty_bind, vty_bind_cmd, "bind A.B.C.D", + "Accept VTY telnet connections on local interface\n" + "Local interface IP address (default: " VTY_BIND_ADDR_DEFAULT ")\n") +{ + talloc_free((void*)vty_bind_addr); + vty_bind_addr = talloc_strdup(tall_vty_ctx, argv[0]); + return CMD_SUCCESS; +} + +const char *vty_get_bind_addr(void) +{ + if (!vty_bind_addr) + return VTY_BIND_ADDR_DEFAULT; + return vty_bind_addr; +} + DEFUN(service_advanced_vty, service_advanced_vty_cmd, "service advanced-vty", @@ -1654,6 +1677,10 @@ static int vty_config_write(struct vty *vty) if (!password_check) vty_out(vty, " no login%s", VTY_NEWLINE);
+ /* bind */ + if (vty_bind_addr) + vty_out(vty, " bind %s%s", vty_bind_addr, VTY_NEWLINE); + vty_out(vty, "!%s", VTY_NEWLINE);
return CMD_SUCCESS; @@ -1757,6 +1784,7 @@ void vty_init(struct vty_app_info *app_info) vty_install_default(VTY_NODE); install_element(VTY_NODE, &vty_login_cmd); install_element(VTY_NODE, &no_vty_login_cmd); + install_element(VTY_NODE, &vty_bind_cmd); }
/*! \brief Read the configuration file using the VTY code
Make the ctrl interface bind address configurable, so that it may be made available on other addresses than 127.0.0.1. The specific aim is to allow running multiple osmo-nitbs alongside each other (commits in openbsc follow). --- include/osmocom/ctrl/control_if.h | 4 ++++ src/ctrl/control_if.c | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/include/osmocom/ctrl/control_if.h b/include/osmocom/ctrl/control_if.h index 00caacc..181c60a 100644 --- a/include/osmocom/ctrl/control_if.h +++ b/include/osmocom/ctrl/control_if.h @@ -22,5 +22,9 @@ struct ctrl_handle { int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd); struct ctrl_handle *ctrl_interface_setup(void *data, uint16_t port, ctrl_cmd_lookup lookup); +struct ctrl_handle *ctrl_interface_setup_dynip(void *data, + const char *bind_addr, + uint16_t port, + ctrl_cmd_lookup lookup);
int ctrl_cmd_handle(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void *data); diff --git a/src/ctrl/control_if.c b/src/ctrl/control_if.c index 18e695d..bde245d 100644 --- a/src/ctrl/control_if.c +++ b/src/ctrl/control_if.c @@ -673,6 +673,14 @@ static int verify_counter(struct ctrl_cmd *cmd, const char *value, void *data) struct ctrl_handle *ctrl_interface_setup(void *data, uint16_t port, ctrl_cmd_lookup lookup) { + return ctrl_interface_setup_dynip(data, "127.0.0.1", port, lookup); +} + +struct ctrl_handle *ctrl_interface_setup_dynip(void *data, + const char *bind_addr, + uint16_t port, + ctrl_cmd_lookup lookup) +{ int ret; struct ctrl_handle *ctrl;
@@ -693,7 +701,7 @@ struct ctrl_handle *ctrl_interface_setup(void *data, uint16_t port, ctrl->listen_fd.cb = listen_fd_cb; ctrl->listen_fd.data = ctrl; ret = osmo_sock_init_ofd(&ctrl->listen_fd, AF_INET, SOCK_STREAM, IPPROTO_TCP, - "127.0.0.1", port, OSMO_SOCK_F_BIND); + bind_addr, port, OSMO_SOCK_F_BIND); if (ret < 0) goto err_vec;
This may seem like overkill for a mere const char * config item, but it makes the Control interface VTY commands reusable in any main() scope (inspired by libosmo-abis' VTY config).
Add API functions ctrl_vty_init() and ctrl_vty_get_bind_addr(), in new files src/ctrl/control_vty.c and include/osmocom/ctrl/control_vty.h, compiled and/or installed dependent on ENABLE_VTY.
Using these functions allows configuring a static const char* with the VTY commands
ctrl bind A.B.C.D
which callers shall subsequently use to bind the Control interface to a specific local interface address, by passing the return value of ctrl_vty_get_bind_addr() to control_interface_setup().
Add CTRL_NODE to enum node_type, "eating" RESERVED4_NODE to heed that comment on avoiding ABI changes. --- include/Makefile.am | 3 +- include/osmocom/ctrl/control_vty.h | 9 ++++ include/osmocom/vty/command.h | 2 +- src/ctrl/Makefile.am | 4 ++ src/ctrl/control_vty.c | 90 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 include/osmocom/ctrl/control_vty.h create mode 100644 src/ctrl/control_vty.c
diff --git a/include/Makefile.am b/include/Makefile.am index a965fb9..ac22ee6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -117,7 +117,8 @@ nobase_include_HEADERS += \ osmocom/vty/telnet_interface.h \ osmocom/vty/vector.h \ osmocom/vty/vty.h \ - osmocom/vty/ports.h + osmocom/vty/ports.h \ + osmocom/ctrl/control_vty.h endif
noinst_HEADERS = \ diff --git a/include/osmocom/ctrl/control_vty.h b/include/osmocom/ctrl/control_vty.h new file mode 100644 index 0000000..d0ef69f --- /dev/null +++ b/include/osmocom/ctrl/control_vty.h @@ -0,0 +1,9 @@ +#pragma once + +/* Add the 'ctrl' section to VTY, containing the 'bind' command. */ +int ctrl_vty_init(void *ctx); + +/* Obtain the IP address configured by the 'ctrl'/'bind A.B.C.D' VTY command. + * This should be fed to ctrl_interface_setup() once the configuration has been + * read. */ +const char *ctrl_vty_get_bind_addr(void); diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h index 2078e1b..9a02575 100644 --- a/include/osmocom/vty/command.h +++ b/include/osmocom/vty/command.h @@ -83,6 +83,7 @@ enum node_type { L_IPA_NODE, /*!< \brief IPA proxying commands in libosmo-abis. */ L_NS_NODE, /*!< \brief NS node in libosmo-gb. */ L_BSSGP_NODE, /*!< \brief BSSGP node in libosmo-gb. */ + L_CTRL_NODE, /*!< \brief Control interface node. */
/* * When adding new nodes to the libosmocore project, these nodes can be @@ -91,7 +92,6 @@ enum node_type { RESERVED1_NODE, /*!< \brief Reserved for later extensions */ RESERVED2_NODE, /*!< \brief Reserved for later extensions */ RESERVED3_NODE, /*!< \brief Reserved for later extensions */ - RESERVED4_NODE, /*!< \brief Reserved for later extensions */
_LAST_OSMOVTY_NODE }; diff --git a/src/ctrl/Makefile.am b/src/ctrl/Makefile.am index e6ccafb..b4a3da4 100644 --- a/src/ctrl/Makefile.am +++ b/src/ctrl/Makefile.am @@ -13,3 +13,7 @@ libosmoctrl_la_LIBADD = \ $(top_builddir)/src/libosmocore.la \ $(top_builddir)/src/gsm/libosmogsm.la \ $(top_builddir)/src/vty/libosmovty.la + +if ENABLE_VTY +libosmoctrl_la_SOURCES += control_vty.c +endif diff --git a/src/ctrl/control_vty.c b/src/ctrl/control_vty.c new file mode 100644 index 0000000..ca1cbd9 --- /dev/null +++ b/src/ctrl/control_vty.c @@ -0,0 +1,90 @@ +/* VTY configuration for Control interface + * + * (C) 2016 by sysmocom s.m.f.c GmbH info@sysmocom.de + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdlib.h> +#include <talloc.h> +#include <osmocom/ctrl/control_vty.h> +#include <osmocom/vty/command.h> + +static void *ctrl_vty_ctx = NULL; +static const char *ctrl_vty_bind_addr = NULL; + +DEFUN(cfg_ctrl_bind_addr, + cfg_ctrl_bind_addr_cmd, + "bind A.B.C.D", + "Set bind address to listen for Control connections\n" + "Local IP address (default 127.0.0.1)\n") +{ + if (ctrl_vty_bind_addr) { + talloc_free((void*)ctrl_vty_bind_addr); + ctrl_vty_bind_addr = NULL; + } + ctrl_vty_bind_addr = talloc_strdup(ctrl_vty_ctx, argv[0]); + return CMD_SUCCESS; +} + +const char *ctrl_vty_get_bind_addr(void) +{ + if (!ctrl_vty_bind_addr) + return "127.0.0.1"; + return ctrl_vty_bind_addr; +} + +struct cmd_node ctrl_node = { + L_CTRL_NODE, + "%s(config-ctrl)# ", + 1, +}; + +DEFUN(cfg_ctrl, + cfg_ctrl_cmd, + "ctrl", "Configure the Control Interface") +{ + vty->index = NULL; + vty->node = L_CTRL_NODE; + + return CMD_SUCCESS; +} + +static int config_write_ctrl(struct vty *vty) +{ + /* So far there's only one element. Omit the entire section if the bind + * element is omitted. */ + if (!ctrl_vty_bind_addr) + return CMD_SUCCESS; + + vty_out(vty, "ctrl%s", VTY_NEWLINE); + vty_out(vty, " bind %s%s", ctrl_vty_bind_addr, VTY_NEWLINE); + + return CMD_SUCCESS; +} + +int ctrl_vty_init(void *ctx) +{ + ctrl_vty_ctx = ctx; + install_element(CONFIG_NODE, &cfg_ctrl_cmd); + install_node(&ctrl_node, config_write_ctrl); + + install_element(L_CTRL_NODE, &cfg_ctrl_bind_addr_cmd); + return 0; +} +