diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-03-06 11:10:30 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2014-03-06 11:10:30 +0100 |
commit | 1a1463725bb6f3bb8435963eab3685220a2fbcca (patch) | |
tree | c7c5c45419708a154a589401ea939d34ee07caa4 /openbsc/src | |
parent | 93de8b259104aa05387e302a4ee6fd6f330bfee7 (diff) | |
parent | 4ecc6877a2a2fd3244979ec4a8d13a2862f5e6a4 (diff) |
Merge branch 'zecke/features/extended-control'
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/libbsc/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_ctrl_commands.c | 165 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_ctrl.c | 9 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c | 123 | ||||
-rw-r--r-- | openbsc/src/osmo-nitb/bsc_hack.c | 5 |
5 files changed, 283 insertions, 21 deletions
diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am index 42fabab6d..53300912c 100644 --- a/openbsc/src/libbsc/Makefile.am +++ b/openbsc/src/libbsc/Makefile.am @@ -22,5 +22,5 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \ bsc_api.c bsc_msc.c bsc_vty.c \ gsm_04_08_utils.c \ bsc_init.c bts_init.c bsc_rf_ctrl.c \ - arfcn_range_encode.c + arfcn_range_encode.c bsc_ctrl_commands.c diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c new file mode 100644 index 000000000..a137efac6 --- /dev/null +++ b/openbsc/src/libbsc/bsc_ctrl_commands.c @@ -0,0 +1,165 @@ +/* + * (C) 2013 by Holger Hans Peter Freyther + * (C) 2013 by sysmocom s.f.m.c. GmbH + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <openbsc/control_cmd.h> +#include <openbsc/ipaccess.h> +#include <openbsc/gsm_data.h> + +#define CTRL_CMD_VTY_STRING(cmdname, cmdstr, dtype, element) \ + CTRL_HELPER_GET_STRING(cmdname, dtype, element) \ + CTRL_HELPER_SET_STRING(cmdname, dtype, element) \ +static struct ctrl_cmd_element cmd_##cmdname = { \ + .name = cmdstr, \ + .param = NULL, \ + .get = get_##cmdname, \ + .set = set_##cmdname, \ + .verify = verify_vty_description_string, \ +} + +/** + * Check that there are no newlines or comments or other things + * that could make the VTY configuration unparsable. + */ +static int verify_vty_description_string(struct ctrl_cmd *cmd, + const char *value, void *data) +{ + int i; + const size_t len = strlen(value); + + for (i = 0; i < len; ++i) { + switch(value[i]) { + case '#': + case '\n': + case '\r': + cmd->reply = "String includes illegal character"; + return -1; + default: + break; + } + } + + return 0; +} + +CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999); +CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999); +CTRL_CMD_VTY_STRING(net_short_name, "short-name", struct gsm_network, name_short); +CTRL_CMD_VTY_STRING(net_long_name, "long-name", struct gsm_network, name_long); + +static int verify_net_apply_config(struct ctrl_cmd *cmd, const char *v, void *d) +{ + return 0; +} + +static int get_net_apply_config(struct ctrl_cmd *cmd, void *data) +{ + cmd->reply = "Write only attribute"; + return CTRL_CMD_ERROR; +} + +static int set_net_apply_config(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_network *net = cmd->node; + struct gsm_bts *bts; + + llist_for_each_entry(bts, &net->bts_list, list) { + if (!is_ipaccess_bts(bts)) + continue; + + ipaccess_drop_oml(bts); + } + + cmd->reply = "Tried to drop the BTS"; + return CTRL_CMD_REPLY; +} + +CTRL_CMD_DEFINE(net_apply_config, "apply-configuration"); + +static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d) +{ + char *tmp, *saveptr, *mcc, *mnc; + + tmp = talloc_strdup(cmd, value); + if (!tmp) + return 1; + + mcc = strtok_r(tmp, ",", &saveptr); + mnc = strtok_r(NULL, ",", &saveptr); + talloc_free(tmp); + + if (!mcc || !mnc) + return 1; + return 0; +} + +static int get_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data) +{ + cmd->reply = "Write only attribute"; + return CTRL_CMD_ERROR; +} + +static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data) +{ + struct gsm_network *net = cmd->node; + char *tmp, *saveptr, *mcc_str, *mnc_str; + int mcc, mnc; + + tmp = talloc_strdup(cmd, cmd->value); + if (!tmp) + goto oom; + + + mcc_str = strtok_r(tmp, ",", &saveptr); + mnc_str = strtok_r(NULL, ",", &saveptr); + + mcc = atoi(mcc_str); + mnc = atoi(mnc_str); + + talloc_free(tmp); + + if (net->network_code == mnc && net->country_code == mcc) { + cmd->reply = "Nothing changed"; + return CTRL_CMD_REPLY; + } + + net->network_code = mnc; + net->country_code = mcc; + + return set_net_apply_config(cmd, data); + +oom: + cmd->reply = "OOM"; + return CTRL_CMD_ERROR; +} +CTRL_CMD_DEFINE(net_mcc_mnc_apply, "mcc-mnc-apply"); + +int bsc_base_ctrl_cmds_install(void) +{ + int rc = 0; + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mnc); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_short_name); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_long_name); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_apply_config); + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_mcc_mnc_apply); + + return rc; +} diff --git a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c index 1d0e2aa01..e32218d0c 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c @@ -208,7 +208,11 @@ static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_con admin = osmo_bsc_rf_get_adminstate_name(osmo_bsc_rf_get_adminstate_by_bts(bts)); policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts)); - cmd->reply = talloc_asprintf_append(cmd->reply, ",%s,%s,%s", oper, admin, policy); + cmd->reply = talloc_asprintf_append(cmd->reply, + ",%s,%s,%s,%d,%d", + oper, admin, policy, + bts->network->country_code, + bts->network->network_code); osmo_bsc_send_trap(cmd, msc_con); talloc_free(cmd); @@ -605,6 +609,9 @@ int bsc_ctrl_cmds_install(struct gsm_network *net) { int rc; + rc = bsc_base_ctrl_cmds_install(); + if (rc) + goto end; rc = ctrl_cmd_install(CTRL_NODE_BTS, &cmd_bts_rf_state); if (rc) goto end; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c b/openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c index 6ff4541a0..2836a1956 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c @@ -186,6 +186,26 @@ static void ctrl_conn_closed_cb(struct ctrl_connection *connection) } } +static int extract_bsc_nr_variable(char *variable, unsigned int *nr, char **bsc_variable) +{ + char *nr_str, *tmp, *saveptr = NULL; + + tmp = strtok_r(variable, ".", &saveptr); + tmp = strtok_r(NULL, ".", &saveptr); + tmp = strtok_r(NULL, ".", &saveptr); + nr_str = strtok_r(NULL, ".", &saveptr); + if (!nr_str) + return 0; + *nr = atoi(nr_str); + + tmp = strtok_r(NULL, "\0", &saveptr); + if (!tmp) + return 0; + + *bsc_variable = tmp; + return 1; +} + static int forward_to_bsc(struct ctrl_cmd *cmd) { int ret = CTRL_CMD_HANDLED; @@ -193,24 +213,14 @@ static int forward_to_bsc(struct ctrl_cmd *cmd) struct bsc_connection *bsc; struct bsc_cmd_list *pending; unsigned int nr; - char *nr_str, *tmp, *saveptr = NULL; + char *bsc_variable; /* Skip over the beginning (bsc.) */ - tmp = strtok_r(cmd->variable, ".", &saveptr); - tmp = strtok_r(NULL, ".", &saveptr); - tmp = strtok_r(NULL, ".", &saveptr); - nr_str = strtok_r(NULL, ".", &saveptr); - if (!nr_str) { + if (!extract_bsc_nr_variable(cmd->variable, &nr, &bsc_variable)) { cmd->reply = "command incomplete"; goto err; } - nr = atoi(nr_str); - tmp = strtok_r(NULL, "\0", &saveptr); - if (!tmp) { - cmd->reply = "command incomplete"; - goto err; - } llist_for_each_entry(bsc, &g_nat->bsc_connections, list_entry) { if (!bsc->cfg) @@ -245,7 +255,7 @@ static int forward_to_bsc(struct ctrl_cmd *cmd) } talloc_free(bsc_cmd->variable); - bsc_cmd->variable = talloc_strdup(bsc_cmd, tmp); + bsc_cmd->variable = talloc_strdup(bsc_cmd, bsc_variable); if (!bsc_cmd->variable) { cmd->reply = "OOM"; goto err; @@ -274,8 +284,7 @@ static int forward_to_bsc(struct ctrl_cmd *cmd) err: ret = CTRL_CMD_ERROR; done: - if (bsc_cmd) - talloc_free(bsc_cmd); + talloc_free(bsc_cmd); return ret; } @@ -297,6 +306,74 @@ static int verify_fwd_cmd(struct ctrl_cmd *cmd, const char *value, void *data) return 0; } +static int extract_bsc_cfg_variable(struct ctrl_cmd *cmd, struct bsc_config **cfg, + char **bsc_variable) +{ + unsigned int nr; + + if (!extract_bsc_nr_variable(cmd->variable, &nr, bsc_variable)) { + cmd->reply = "command incomplete"; + return 0; + } + + *cfg = bsc_config_num(g_nat, nr); + if (!*cfg) { + cmd->reply = "Unknown BSC"; + return 0; + } + + return 1; +} + +CTRL_CMD_DEFINE(net_cfg_cmd, "net 0 bsc_cfg *"); +static int get_net_cfg_cmd(struct ctrl_cmd *cmd, void *data) +{ + char *bsc_variable; + struct bsc_config *bsc_cfg; + + if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable)) + return CTRL_CMD_ERROR; + + if (strcmp(bsc_variable, "access-list-name") == 0) { + cmd->reply = talloc_asprintf(cmd, "%s", + bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : ""); + return CTRL_CMD_REPLY; + } + + cmd->reply = "unknown command"; + return CTRL_CMD_ERROR; +} + +static int set_net_cfg_cmd(struct ctrl_cmd *cmd, void *data) +{ + char *bsc_variable; + struct bsc_config *bsc_cfg; + + if (!extract_bsc_cfg_variable(cmd, &bsc_cfg, &bsc_variable)) + return CTRL_CMD_ERROR; + + if (strcmp(bsc_variable, "access-list-name") == 0) { + bsc_replace_string(bsc_cfg, &bsc_cfg->acc_lst_name, cmd->value); + cmd->reply = talloc_asprintf(cmd, "%s", + bsc_cfg->acc_lst_name ? bsc_cfg->acc_lst_name : ""); + return CTRL_CMD_REPLY; + } else if (strcmp(bsc_variable, "no-access-list-name") == 0) { + talloc_free(bsc_cfg->acc_lst_name); + bsc_cfg->acc_lst_name = NULL; + cmd->reply = ""; + return CTRL_CMD_REPLY; + } + + cmd->reply = "unknown command"; + return CTRL_CMD_ERROR; +} + +static int verify_net_cfg_cmd(struct ctrl_cmd *cmd, const char *value, void *data) +{ + return 0; +} + + struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, int port) { struct ctrl_handle *ctrl; @@ -312,13 +389,21 @@ struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat, int port) rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_fwd_cmd); if (rc) { fprintf(stderr, "Failed to install the control command. Exiting.\n"); - osmo_fd_unregister(&ctrl->listen_fd); - close(ctrl->listen_fd.fd); - talloc_free(ctrl); - return NULL; + goto error; + } + rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_net_cfg_cmd); + if (rc) { + fprintf(stderr, "Failed to install the net cfg command. Exiting.\n"); + goto error; } g_nat = nat; return ctrl; + +error: + osmo_fd_unregister(&ctrl->listen_fd); + close(ctrl->listen_fd.fd); + talloc_free(ctrl); + return NULL; } diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c index 96ae0b833..d746bf14e 100644 --- a/openbsc/src/osmo-nitb/bsc_hack.c +++ b/openbsc/src/osmo-nitb/bsc_hack.c @@ -290,6 +290,11 @@ int main(int argc, char **argv) return -1; } + if (bsc_base_ctrl_cmds_install() != 0) { + printf("Failed to initialize the control commands. Exiting.\n"); + return -1; + } + /* seed the PRNG */ srand(time(NULL)); |