aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-03-06 11:10:30 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-03-06 11:10:30 +0100
commit1a1463725bb6f3bb8435963eab3685220a2fbcca (patch)
treec7c5c45419708a154a589401ea939d34ee07caa4 /openbsc/src
parent93de8b259104aa05387e302a4ee6fd6f330bfee7 (diff)
parent4ecc6877a2a2fd3244979ec4a8d13a2862f5e6a4 (diff)
Merge branch 'zecke/features/extended-control'
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/libbsc/Makefile.am2
-rw-r--r--openbsc/src/libbsc/bsc_ctrl_commands.c165
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_ctrl.c9
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_ctrl.c123
-rw-r--r--openbsc/src/osmo-nitb/bsc_hack.c5
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));