From 3a38ee6c3d9985200b10229b27f3b9ae9edd50ae Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 14:27:29 +0100 Subject: abis: Send the message without enforcing to wait for a response The user might issue restarts while no BTS is connected and we should not block the abis queue because of these messages. --- openbsc/src/libbsc/abis_nm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c index c05e2f94f..3afc4c497 100644 --- a/openbsc/src/libbsc/abis_nm.c +++ b/openbsc/src/libbsc/abis_nm.c @@ -2598,7 +2598,7 @@ int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx) fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC, trx->bts->nr, trx->nr, 0xff); - return abis_nm_sendmsg(trx->bts, msg); + return abis_nm_sendmsg_direct(trx->bts, msg); } int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class, -- cgit v1.2.3 From 740e65fb7bd1516117cd23c7b524976548e1a397 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 13:45:23 +0100 Subject: bsc: Add code to send ip.access reboot command to nanoBTS The nanoBTS continues to be buggy and seems to have broken BSSGP when changing SIs across new OML connections. Add an easy command to force the reboot of the system through OML. --- openbsc/src/libbsc/bsc_vty.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 7fdee054c..29f2501f8 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -3596,6 +3596,44 @@ DEFUN(drop_bts, return CMD_SUCCESS; } +DEFUN(restart_bts, restart_bts_cmd, + "restart-bts <0-65535>", + "Restart ip.access nanoBTS through OML\n" + "BTS Number\n") +{ + struct gsm_network *gsmnet; + struct gsm_bts_trx *trx; + struct gsm_bts *bts; + unsigned int bts_nr; + + gsmnet = gsmnet_from_vty(vty); + + bts_nr = atoi(argv[0]); + if (bts_nr >= gsmnet->num_bts) { + vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s", + gsmnet->num_bts, bts_nr, VTY_NEWLINE); + return CMD_WARNING; + } + + bts = gsm_bts_num(gsmnet, bts_nr); + if (!bts) { + vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE); + return CMD_WARNING; + } + + if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) { + vty_out(vty, "This command only works for ipaccess nanoBTS.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* go from last TRX to c0 */ + llist_for_each_entry_reverse(trx, &bts->trx_list, list) + abis_nm_ipaccess_restart(trx); + + return CMD_SUCCESS; +} + DEFUN(smscb_cmd, smscb_cmd_cmd, "bts <0-255> smscb-command <1-4> HEXSTRING", "BTS related commands\n" "BTS Number\n" @@ -3895,6 +3933,7 @@ int bsc_vty_init(const struct log_info *cat) install_element(TS_NODE, &cfg_ts_e1_subslot_cmd); install_element(ENABLE_NODE, &drop_bts_cmd); + install_element(ENABLE_NODE, &restart_bts_cmd); install_element(ENABLE_NODE, &pdch_act_cmd); install_element(ENABLE_NODE, &smscb_cmd_cmd); -- cgit v1.2.3 From c6a65511f326340783f0e837c6eb58b0cf2c6abc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 16 Mar 2016 15:27:38 +0100 Subject: bsc: Add parameter to restart a bts The ip.access nanoBTS seems to have severe issues with BSSGP when changing the country code and/or network code. It is unlikely that the proprietary code is getting fixed so we extend the parameter for the apply-configuration command to carry the 'restart' param. --- openbsc/src/libbsc/bsc_ctrl_commands.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c index b6b1c9a8b..7e8479734 100644 --- a/openbsc/src/libbsc/bsc_ctrl_commands.c +++ b/openbsc/src/libbsc/bsc_ctrl_commands.c @@ -90,7 +90,17 @@ static int set_net_apply_config(struct ctrl_cmd *cmd, void *data) if (!is_ipaccess_bts(bts)) continue; - ipaccess_drop_oml(bts); + /* + * The ip.access nanoBTS seems to be unrelaible on BSSGP + * so let's us just reboot it. For the sysmoBTS we can just + * restart the process as all state is gone. + */ + if (!is_sysmobts_v2(bts) && strcmp(cmd->value, "restart") == 0) { + struct gsm_bts_trx *trx; + llist_for_each_entry_reverse(trx, &bts->trx_list, list) + abis_nm_ipaccess_restart(trx); + } else + ipaccess_drop_oml(bts); } cmd->reply = "Tried to drop the BTS"; -- cgit v1.2.3 From 2826df56b2af5a6a0f20e5a9bcf1d50a1130f0ba Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 1 Apr 2016 20:21:03 +0200 Subject: subscr: Make db_create_subscriber fail on duplicates The issue of db_create_subscriber updating an already existing subscr is that the same subscriber will then have two entries in the active subscribers list. In general this will break assumptions that a subscr can be compared by comparing the pointer. In the case of the VTY this was not an issue as the created subscr was immediately destroyed again but it is better to avoid this problem. Change the VTY command to find the subscriber and then call sync to have the updated time set. The side-effect is we will now have two queries for the subscriber. Once through subscr_get_by_imsi and once through db_create_subscriber. Change the db_create_subscriber to fail if a subscriber already exists, and add a testcase for this behavior and do not updated the 'updated' timestamp of an already existing subscriber. Add a testcase for this behavior. Related: OS Issue #1657 --- openbsc/src/libmsc/db.c | 10 ++-------- openbsc/src/libmsc/vty_interface_layer3.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 0935fc54d..17bea2470 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -508,14 +508,8 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi) /* Is this subscriber known in the db? */ subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi); if (subscr) { - result = dbi_conn_queryf(conn, - "UPDATE Subscriber set updated = datetime('now') " - "WHERE imsi = %s " , imsi); - if (!result) - LOGP(DDB, LOGL_ERROR, "failed to update timestamp\n"); - else - dbi_result_free(result); - return subscr; + subscr_put(subscr); + return NULL; } subscr = subscr_alloc(); diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index f49c53a08..790fedf39 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -236,11 +236,17 @@ DEFUN(subscriber_create, struct gsm_network *gsmnet = gsmnet_from_vty(vty); struct gsm_subscriber *subscr; - subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]); - if (!subscr) { - vty_out(vty, "%% No subscriber created for IMSI %s%s", - argv[0], VTY_NEWLINE); - return CMD_WARNING; + subscr = subscr_get_by_imsi(gsmnet->subscr_group, argv[0]); + if (subscr) + db_sync_subscriber(subscr); + else { + subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]); + + if (!subscr) { + vty_out(vty, "%% No subscriber created for IMSI %s%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } } /* Show info about the created subscriber. */ -- cgit v1.2.3 From adb86759daa80a484eef4b5a24bc0ce0de0a0763 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 1 Apr 2016 20:31:11 +0200 Subject: db: If creating a subscriber in the db fails, return NULL We should not return a subscriber in case it was not written to the database. Instead free the memory allocated and return NULL. Callers in gsm_04_08.c are prepared to have the creation fail. Related: OS Issue #1657 --- openbsc/src/libmsc/db.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 17bea2470..267b5ef41 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -523,8 +523,11 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi) "(%s, datetime('now'), datetime('now')) ", imsi ); - if (!result) + if (!result) { LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n"); + subscr_put(subscr); + return NULL; + } subscr->id = dbi_conn_sequence_last(conn, NULL); strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); dbi_result_free(result); -- cgit v1.2.3 From 9bcb1a56cbec710cbfa49ae6623c10595eab08ec Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 6 Apr 2016 22:41:12 +0200 Subject: ctrl: Extend ctrl command to optionally handle alg+ki Extend the existing ctrl command to be able to specify the algorithm and Ki. In contrast to the VTY no size check is done. Together with the VTY this code only supports a small part of what is supported by libosmocore. The algorithm and ki are considered optional but if a valid algorithm other than "none" is passed, a KI must be passed as well. Extend the test coverage by passing the potential values. It is not verified that the KI/algorithm is stored. --- openbsc/src/libmsc/ctrl_commands.c | 60 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c index e48c6a3e1..9ac39de95 100644 --- a/openbsc/src/libmsc/ctrl_commands.c +++ b/openbsc/src/libmsc/ctrl_commands.c @@ -24,9 +24,25 @@ #include #include +static bool alg_supported(const char *alg) +{ + /* + * TODO: share this with the vty_interface and extend to all + * algorithms supported by libosmocore now. Make it table based + * as well. + */ + if (strcasecmp(alg, "none") == 0) + return true; + if (strcasecmp(alg, "xor") == 0) + return true; + if (strcasecmp(alg, "comp128v1") == 0) + return true; + return false; +} + static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, void *d) { - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; int rc = 0; tmp = talloc_strdup(cmd, value); @@ -35,6 +51,8 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); if (!imsi || !msisdn) rc = 1; @@ -42,6 +60,12 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi rc = 1; else if (strlen(msisdn) >= GSM_EXTENSION_LENGTH) rc = 1; + else if (alg) { + if (!alg_supported(alg)) + rc = 1; + else if (strcasecmp(alg, "none") != 0 && !ki) + rc = 1; + } talloc_free(tmp); return rc; @@ -56,7 +80,7 @@ static int get_subscriber_modify(struct ctrl_cmd *cmd, void *data) static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) { struct gsm_network *net = cmd->node; - char *tmp, *imsi, *msisdn, *saveptr = NULL; + char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL; struct gsm_subscriber* subscr; int rc; @@ -66,6 +90,8 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) imsi = strtok_r(tmp, ",", &saveptr); msisdn = strtok_r(NULL, ",", &saveptr); + alg = strtok_r(NULL, ",", &saveptr); + ki = strtok_r(NULL, ",", &saveptr); subscr = subscr_get_by_imsi(net->subscr_group, imsi); if (!subscr) @@ -80,6 +106,36 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data) /* put it back to the db */ rc = db_sync_subscriber(subscr); db_subscriber_update(subscr); + + /* handle optional ciphering */ + if (alg) { + if (strcasecmp(alg, "none") == 0) + db_sync_authinfo_for_subscr(NULL, subscr); + else { + struct gsm_auth_info ainfo = { 0, }; + /* the verify should make sure that this is okay */ + OSMO_ASSERT(alg); + OSMO_ASSERT(ki); + + if (strcasecmp(alg, "xor") == 0) + ainfo.auth_algo = AUTH_ALGO_XOR; + else if (strcasecmp(alg, "comp128v1") == 0) + ainfo.auth_algo = AUTH_ALGO_COMP128v1; + + rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); + if (rc < 0) { + subscr_put(subscr); + talloc_free(tmp); + cmd->reply = "Failed to parse KI"; + return CTRL_CMD_ERROR; + } + + ainfo.a3a8_ki_len = rc; + db_sync_authinfo_for_subscr(&ainfo, subscr); + rc = 0; + } + db_sync_lastauthtuple_for_subscr(NULL, subscr); + } subscr_put(subscr); talloc_free(tmp); -- cgit v1.2.3 From 687f048ab04ed135eeb11deb29e6b4cb9727c27d Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 8 Apr 2016 11:52:34 +0200 Subject: Fix segfault with broken config Fixes OS#1691 --- openbsc/src/libbsc/bsc_init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 859d9998f..713109c23 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -373,6 +373,9 @@ static int bootstrap_bts(struct gsm_bts *bts) { int i, n; + if (!bts->model) + return -EFAULT; + if (bts->model->start && !bts->model->started) { int ret = bts->model->start(bts->network); if (ret < 0) -- cgit v1.2.3 From e5686f21d64c804db825b0baa8d1285250d9d650 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 6 Apr 2016 17:25:44 +0200 Subject: NAT: vty command to display number of BSCs Add command 'show nat num-bscs-configured' to display number of configured BSCs. Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index cd8293cc9..5af6d9743 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -204,6 +204,14 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", return CMD_SUCCESS; } +DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat num-bscs-configured", + SHOW_STR "Display NAT configuration details\n" + "BSCs-related\n") +{ + vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE); + return CMD_SUCCESS; +} + DEFUN(show_bsc, show_bsc_cmd, "show bsc connections", SHOW_STR BSC_STR "All active connections\n") @@ -1169,6 +1177,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* show commands */ install_element_ve(&show_sccp_cmd); install_element_ve(&show_bsc_cmd); + install_element_ve(&show_nat_bsc_cmd); install_element_ve(&show_bsc_cfg_cmd); install_element_ve(&show_stats_cmd); install_element_ve(&show_stats_lac_cmd); -- cgit v1.2.3 From f220b52df3e15e25dcbb329c76c646f77ec3b506 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 6 Apr 2016 17:52:38 +0200 Subject: NAT: extend debug output for ipaccess errors --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index cacb9199d..ab82adf17 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1320,8 +1320,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd) bsc->cfg ? bsc->cfg->nr : -1); else LOGP(DNAT, LOGL_ERROR, - "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n", - bsc->cfg ? bsc->cfg->nr : -1, ret); + "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n", + bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret)); bsc_close_connection(bsc); return -1; -- cgit v1.2.3 From 7a301d357612347723e59c7f16a97227814d406e Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 7 Apr 2016 11:38:52 +0200 Subject: Remove trivial wrapper function Rename gsm48_tx_chan_mode_modify() to gsm48_lchan_modify() and remove corresponding wrapper code. --- openbsc/src/libbsc/gsm_04_08_utils.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 8c6dbef9b..635665a3d 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -463,7 +463,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, /* * fill the channel information element, this code * should probably be shared with rsl_rx_chan_rqd(), - * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5 + * gsm48_lchan_modify(). But beware that 10.5.2.5 * 10.5.2.5.a have slightly different semantic for * the chan_desc. But as long as multi-slot configurations * are not used we seem to be fine. @@ -488,7 +488,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, } /* 9.1.5 Channel mode modify: Modify the mode on the MS side */ -int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) +int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode) { struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -513,17 +513,6 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode) return gsm48_sendmsg(msg); } -int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode) -{ - int rc; - - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); - if (rc < 0) - return rc; - - return rc; -} - int gsm48_rx_rr_modif_ack(struct msgb *msg) { int rc; -- cgit v1.2.3 From 714b170f895dfdc2f0d725ab110baf3dc14ef874 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 7 Apr 2016 12:27:11 +0200 Subject: NAT: allow allocating BSC in arbitrary order Check for existing BSC before allocating new one. Track number of remaining BSCs on deallocation. Explicitly use BSC number in allocation function. --- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 7 +++++-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 14 ++++---------- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c index cc7d44287..37b01e314 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c @@ -155,14 +155,15 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat) return con; } -struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token) +struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, + unsigned int number) { struct bsc_config *conf = talloc_zero(nat, struct bsc_config); if (!conf) return NULL; conf->token = talloc_strdup(conf, token); - conf->nr = nat->num_bsc; + conf->nr = number; conf->nat = nat; conf->max_endpoints = 32; conf->paging_group = PAGIN_GROUP_UNASSIGNED; @@ -205,6 +206,8 @@ void bsc_config_free(struct bsc_config *cfg) llist_del(&cfg->entry); rate_ctr_group_free(cfg->stats.ctrg); talloc_free(cfg); + cfg->nat->num_bsc--; + OSMO_ASSERT(cfg->nat->num_bsc >= 0) } static void _add_lac(void *ctx, struct llist_head *list, int _lac) diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 5af6d9743..4348d6fb8 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -799,17 +799,11 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "BSC configuration\n" "Identifier of the BSC\n") { int bsc_nr = atoi(argv[0]); - struct bsc_config *bsc; + struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr); - if (bsc_nr > _nat->num_bsc) { - vty_out(vty, "%% The next unused BSC number is %u%s", - _nat->num_bsc, VTY_NEWLINE); - return CMD_WARNING; - } else if (bsc_nr == _nat->num_bsc) { - /* allocate a new one */ - bsc = bsc_config_alloc(_nat, "unknown"); - } else - bsc = bsc_config_num(_nat, bsc_nr); + /* allocate a new one */ + if (!bsc) + bsc = bsc_config_alloc(_nat, "unknown", bsc_nr); if (!bsc) return CMD_WARNING; -- cgit v1.2.3 From 82f5ecde6a10c3c22980822a892a3fb5c69acf4f Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 12 Apr 2016 16:59:25 +0200 Subject: NAT: move BSC config into separate file Introduce new configuration option bscs-config-file which includes BSC configuration from the given file. Both absolute and relative (to the main config file) paths are supported. Add 'show bscs-config' command to display current BSC configuration. Note: it is still possible to have BSC configuration in the main file (provided proper index number is used) and in runtime but BSC configuration is no longer saved automatically. The management of included configuration file is left to external tools. Update configuration examples. Fixes: OS#1669 Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 5 +++- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 49 +++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index ab82adf17..f433324f8 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -34,6 +34,7 @@ #include #include #include +#include #define _GNU_SOURCE #include @@ -1626,6 +1627,8 @@ int main(int argc, char **argv) local_addr.s_addr = INADDR_ANY; handle_options(argc, argv); + nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file)); + rate_ctr_init(tall_bsc_ctx); osmo_stats_init(tall_bsc_ctx); @@ -1651,7 +1654,7 @@ int main(int argc, char **argv) /* seed the PRNG */ srand(time(NULL)); - + LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path); /* * Setup the MGCP code.. diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 4348d6fb8..b7b49e63a 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -96,6 +96,8 @@ static int config_write_nat(struct vty *vty) vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE); vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE); vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE); + if (_nat->include_file) + vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE); if (_nat->token) vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE); vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE); @@ -181,6 +183,14 @@ static int config_write_bsc(struct vty *vty) return CMD_SUCCESS; } +DEFUN(show_bscs, show_bscs_cmd, "show bscs-config", + SHOW_STR "Show configured BSCs\n" + "Both from included file and vty\n") +{ + vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path, + VTY_NEWLINE); + return config_write_bsc(vty); +} DEFUN(show_sccp, show_sccp_cmd, "show sccp connections", SHOW_STR "Display information about SCCP\n" @@ -495,6 +505,34 @@ DEFUN(cfg_nat_acc_lst_name, return CMD_SUCCESS; } +DEFUN(cfg_nat_include, + cfg_nat_include_cmd, + "bscs-config-file NAME", + "Set the filename of the BSC configuration to include.\n" + "The filename to be included.") +{ + char *path; + int rc; + + if ('/' == argv[0][0]) + bsc_replace_string(_nat, &_nat->resolved_path, argv[0]); + else { + path = talloc_asprintf(_nat, "%s/%s", _nat->include_base, + argv[0]); + bsc_replace_string(_nat, &_nat->resolved_path, path); + talloc_free(path); + } + + rc = vty_read_config_file(_nat->resolved_path, NULL); + if (rc < 0) { + vty_out(vty, "Failed to parse the config file %s: %s%s", + _nat->resolved_path, strerror(-rc), VTY_NEWLINE); + return CMD_WARNING; + } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_nat_no_acc_lst_name, cfg_nat_no_acc_lst_name_cmd, "no access-list-name", @@ -865,8 +903,11 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>", /* verify that the LACs are unique */ llist_for_each_entry(tmp, &_nat->bsc_configs, entry) { if (bsc_config_handles_lac(tmp, lac)) { - vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE); - return CMD_ERR_INCOMPLETE; + if (tmp->nr != conf->nr) { + vty_out(vty, "%% LAC %d is already used.%s", lac, + VTY_NEWLINE); + return CMD_ERR_INCOMPLETE; + } } } @@ -1179,6 +1220,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element_ve(&show_msc_cmd); install_element_ve(&test_regex_cmd); install_element_ve(&show_bsc_mgcp_cmd); + install_element_ve(&show_bscs_cmd); install_element_ve(&show_bar_lst_cmd); install_element_ve(&show_prefix_tree_cmd); install_element_ve(&show_ussd_connection_cmd); @@ -1200,6 +1242,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd); install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd); install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd); + install_element(NAT_NODE, &cfg_nat_include_cmd); install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd); install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd); @@ -1236,7 +1279,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat) /* BSC subgroups */ install_element(NAT_NODE, &cfg_bsc_cmd); - install_node(&bsc_node, config_write_bsc); + install_node(&bsc_node, NULL); vty_install_default(NAT_BSC_NODE); install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd); install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd); -- cgit v1.2.3 From 4936448761a6ca42ab661d130f5202dfdabca426 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 13 Apr 2016 11:36:39 +0200 Subject: NAT: reload BSCs config dynamically Add vty tests for BSC configuration reloading. Load BSCs configuration on bscs-config-file command: * remove all runtime configured BSC not in the config file * close connections to all BSC with updated token value Fixes: OS#1670 Sponsored-by: On-Waves ehf --- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index b7b49e63a..55f3dbf4f 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -39,6 +39,7 @@ #include #include +#include static struct bsc_nat *_nat; @@ -513,6 +514,8 @@ DEFUN(cfg_nat_include, { char *path; int rc; + struct bsc_config *cf1, *cf2; + struct bsc_connection *con1, *con2; if ('/' == argv[0][0]) bsc_replace_string(_nat, &_nat->resolved_path, argv[0]); @@ -523,13 +526,32 @@ DEFUN(cfg_nat_include, talloc_free(path); } + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + cf1->remove = true; + cf1->token_updated = false; + } + rc = vty_read_config_file(_nat->resolved_path, NULL); if (rc < 0) { vty_out(vty, "Failed to parse the config file %s: %s%s", _nat->resolved_path, strerror(-rc), VTY_NEWLINE); return CMD_WARNING; } + bsc_replace_string(_nat, &_nat->include_file, argv[0]); + + llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections, + list_entry) { + if (con1->cfg) + if (con1->cfg->token_updated || con1->cfg->remove) + bsc_close_connection(con1); + } + + llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) { + if (cf1->remove) + bsc_config_free(cf1); + } + return CMD_SUCCESS; } @@ -846,6 +868,7 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", if (!bsc) return CMD_WARNING; + bsc->remove = false; vty->index = bsc; vty->node = NAT_BSC_NODE; @@ -858,6 +881,12 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", { struct bsc_config *conf = vty->index; + if (strncmp(conf->token, argv[0], 128) != 0) { + vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0], + VTY_NEWLINE); + conf->token_updated = true; + } + bsc_replace_string(conf, &conf->token, argv[0]); return CMD_SUCCESS; } -- cgit v1.2.3 From 312bf6ce8bc56f88e49e8118f519494e71a4289a Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 14 Apr 2016 15:21:31 +0200 Subject: gtphub_unmap_header_tei(): don't dereference unmapped_tei arg if not present (CID #57687) --- openbsc/src/gprs/gtphub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index e8bd3aee7..58300ea13 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -1434,14 +1434,16 @@ static int gtphub_unmap_header_tei(struct gtphub_peer_port **to_port_p, p->header_tei_rx, gtphub_port_str(from_port)); return -1; } - OSMO_ASSERT(*unmapped_from_tun); + + if (unmapped_from_tun) { + OSMO_ASSERT(*unmapped_from_tun); + LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n", + gtphub_tunnel_str(*unmapped_from_tun)); + } uint32_t unmapped_tei = to->tei_orig; set_tei(p, unmapped_tei); - LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n", - gtphub_tunnel_str(*unmapped_from_tun)); - /* May be NULL for an invalidated tunnel. */ *to_port_p = to->peer; -- cgit v1.2.3 From a6e81a09861645dc9e8a6aa44a6a1d43bd70dcb7 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 14 Apr 2016 15:21:32 +0200 Subject: bsc_nat: forward_sccp_to_msc(): assert con presence (CID #57872) --- openbsc/src/osmo-bsc_nat/bsc_nat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index f433324f8..efae54f02 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -1153,6 +1153,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg) if (!create_sccp_src_ref(bsc, parsed)) goto exit2; con = patch_sccp_src_ref_to_msc(msg, parsed, bsc); + OSMO_ASSERT(con); con->msc_con = bsc->nat->msc_con; con_msc = con->msc_con; con->filter_state.con_type = con_type; -- cgit v1.2.3 From f3f3505f493f63e9e79c72e407907783913b9c9c Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:44 +0200 Subject: Add SI2quater support to SI3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advertise SI2 quater presence and location (if available) using SI3 according to 3GPP TS 44.018 § 10.5.2.34 --- openbsc/src/libbsc/bsc_init.c | 1 + openbsc/src/libbsc/rest_octets.c | 9 +++++++++ openbsc/src/libbsc/system_information.c | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 713109c23..fd8dd6677 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -140,6 +140,7 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) gen_si[n_si++] = SYSINFO_TYPE_2; gen_si[n_si++] = SYSINFO_TYPE_2bis; gen_si[n_si++] = SYSINFO_TYPE_2ter; + gen_si[n_si++] = SYSINFO_TYPE_2quater; gen_si[n_si++] = SYSINFO_TYPE_3; gen_si[n_si++] = SYSINFO_TYPE_4; diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 4545794a9..83cf2ec1f 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -129,6 +129,15 @@ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3) /* GPRS Indicator */ append_gprs_ind(&bv, &si3->gprs_ind); + /* 3G Early Classmark Sending Restriction controlled by + * early_cm_ctrl above */ + bitvec_set_bit(&bv, H); + + if (si3->si2quater_indicator) { + bitvec_set_bit(&bv, H); /* indicator struct present */ + bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */ + } + bitvec_spare_padding(&bv, (bv.data_len*8)-1); return bv.data_len; } diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 1ee9d41c2..62ee30659 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -510,6 +510,7 @@ static struct gsm48_si_ro_info si_info = { .ra_colour = 0, .present = 1, }, + .si2quater_indicator = 0, .lsa_params = { .present = 0, }, @@ -545,7 +546,12 @@ static int generate_si3(uint8_t *output, struct gsm_bts *bts) } else { si_info.si2ter_indicator = 0; } - + if ((bts->si_valid & (1 << SYSINFO_TYPE_2quater))) { + LOGP(DRR, LOGL_INFO, "SI 2quater is included.\n"); + si_info.si2quater_indicator = 1; + } else { + si_info.si2quater_indicator = 0; + } /* SI3 Rest Octets (10.5.2.34), containing CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME Power Offset, 2ter Indicator, Early Classmark Sending, -- cgit v1.2.3 From 5fa7e36bbc100c5cec4542280ca717ae4800b316 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:45 +0200 Subject: Refactor SI-related code Move define to header file. Use inline functions where appropriate. Change int variables which are used as boolean into actual bool to make code easier to follow. --- openbsc/src/libbsc/abis_rsl.c | 2 -- openbsc/src/libbsc/system_information.c | 37 +++++++++++++++++---------------- 2 files changed, 19 insertions(+), 20 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 8e9258ca5..df7678832 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1332,8 +1332,6 @@ static void t3109_expired(void *data) rsl_rf_chan_release(lchan, 1, SACCH_NONE); } -#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) - /* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */ static int rsl_send_imm_ass_rej(struct gsm_bts *bts, unsigned int num_req_refs, diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 62ee30659..5490c8361 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -67,8 +68,8 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, - const int pgsm, const int arfcn) +static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, + const bool pgsm, const int arfcn) { if (bts->force_combined_si) return !bis && !ter; @@ -135,9 +136,9 @@ static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn) } /* generate a variable bitmap */ -static int enc_freq_lst_var_bitmap(uint8_t *chan_list, +static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int min, int pgsm) + bool bis, bool ter, int min, bool pgsm) { int i; @@ -164,9 +165,9 @@ static int enc_freq_lst_var_bitmap(uint8_t *chan_list, } /* generate a frequency list with the range 512 format */ -static int enc_freq_lst_range(uint8_t *chan_list, +static inline int enc_freq_lst_range(uint8_t *chan_list, struct bitvec *bv, const struct gsm_bts *bts, - int bis, int ter, int pgsm) + bool bis, bool ter, bool pgsm) { int arfcns[RANGE_ENC_MAX_ARFCNS]; int w[RANGE_ENC_MAX_ARFCNS]; @@ -226,15 +227,15 @@ static int enc_freq_lst_range(uint8_t *chan_list, /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, - const struct gsm_bts *bts, int bis, int ter) + const struct gsm_bts *bts, bool bis, bool ter) { - int i, rc, min = -1, max = -1, pgsm = 0, arfcns = 0; - + int i, rc, min = -1, max = -1, arfcns = 0; + bool pgsm = false; memset(chan_list, 0, 16); if (bts->band == GSM_BAND_900 && bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124) - pgsm = 1; + pgsm = true; /* P-GSM-only handsets only support 'bit map 0 format' */ if (!bis && !ter && pgsm) { chan_list[0] = 0; @@ -327,12 +328,12 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, } /* then we generate a GSM 04.08 frequency list from the bitvec */ - return bitvec2freq_list(chan_list, bv, bts, 0, 0); + return bitvec2freq_list(chan_list, bv, bts, false, false); } /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts, - int si5, int bis, int ter) + bool si5, bool bis, bool ter) { struct gsm_bts *cur_bts; struct bitvec *bv; @@ -422,7 +423,7 @@ static int generate_si2(uint8_t *output, struct gsm_bts *bts) si2->header.skip_indicator = 0; si2->header.system_information = GSM48_MT_RR_SYSINFO_2; - rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0, 0, 0); + rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, false, false, false); if (rc < 0) return rc; list_arfcn(si2->bcch_frequency_list, 0xce, @@ -448,7 +449,7 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts) si2b->header.skip_indicator = 0; si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis; - rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, 0, 1, 0); + rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, false, true, false); if (rc < 0) return rc; n = list_arfcn(si2b->bcch_frequency_list, 0xce, @@ -482,7 +483,7 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) si2t->header.skip_indicator = 0; si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter; - rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, 0, 0, 1); + rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, false, false, true); if (rc < 0) return rc; n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e, @@ -630,7 +631,7 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts) si5->rr_protocol_discriminator = GSM48_PDISC_RR; si5->skip_indicator = 0; si5->system_information = GSM48_MT_RR_SYSINFO_5; - rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1, 0, 0); + rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, true, false, false); if (rc < 0) return rc; list_arfcn(si5->bcch_frequency_list, 0xce, @@ -665,7 +666,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts) si5b->rr_protocol_discriminator = GSM48_PDISC_RR; si5b->skip_indicator = 0; si5b->system_information = GSM48_MT_RR_SYSINFO_5bis; - rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, 1, 1, 0); + rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, true, true, false); if (rc < 0) return rc; n = list_arfcn(si5b->bcch_frequency_list, 0xce, @@ -709,7 +710,7 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts) si5t->rr_protocol_discriminator = GSM48_PDISC_RR; si5t->skip_indicator = 0; si5t->system_information = GSM48_MT_RR_SYSINFO_5ter; - rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, 1, 0, 1); + rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, true, false, true); if (rc < 0) return rc; n = list_arfcn(si5t->bcch_frequency_list, 0x8e, -- cgit v1.2.3 From 59a1bf3dae0d0a9e914d3c615c6aa7fc8955d7b5 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 15 Apr 2016 16:04:46 +0200 Subject: Add basic SI2quater support * support for sending arbitrary static SI2quater. * vty interface for neightbor EARFCNs specific to SI2quater. * dynamic generation of SI2quater messages. * unit test for SI2quater messages. Fixes: OS#1630 --- openbsc/src/libbsc/bsc_init.c | 6 +- openbsc/src/libbsc/bsc_vty.c | 71 ++++++++++++ openbsc/src/libbsc/rest_octets.c | 200 ++++++++++++++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 23 ++++ openbsc/src/libcommon/gsm_data.c | 5 + 5 files changed, 302 insertions(+), 3 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index fd8dd6677..fea65629f 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -192,9 +192,9 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx) return 0; err_out: - LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u, most likely " - "a problem with neighbor cell list generation\n", - get_value_string(osmo_sitype_strs, i), bts->nr); + LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>," + "most likely a problem with neighbor cell list generation\n", + get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc)); return rc; } diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 29f2501f8..9634508e1 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -692,6 +692,21 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < MAX_EARFCN_LIST; i++) { + if (bts->si_common.si2quater_neigh_list.arfcn[i] != + OSMO_EARFCN_INVALID) { + vty_out(vty, " si2quater neighbor-list add earfcn %u threshold %u", + bts->si_common.si2quater_neigh_list.arfcn[i], + bts->si_common.si2quater_neigh_list.thresh_hi); + if (bts->si_common.si2quater_neigh_list.meas_bw[i] != + OSMO_EARFCN_MEAS_INVALID) + vty_out(vty, " %u", + bts->si_common.si2quater_neigh_list.meas_bw[i]); + + vty_out(vty, "%s", VTY_NEWLINE); + } + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2743,6 +2758,60 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, + "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " + "[<0-255>]", "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" + "threshold high bits\n" "measurement bandwidth\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[0]); + uint8_t meas = OSMO_EARFCN_MEAS_INVALID, thresh = atoi(argv[1]); + int r; + + if (3 == argc) + meas = atoi(argv[2]); + + r = osmo_earfcn_add(e, arfcn, meas); + + if (r < 0) { + vty_out(vty, "Unable to add arfcn %u: %s%s", arfcn, strerror(r), + VTY_NEWLINE); + return CMD_WARNING; + } + + if (e->thresh_hi && thresh != e->thresh_hi) + vty_out(vty, "Warning: multiple thresholds are not supported, " + "overriding previous threshold %u%s", + e->thresh_hi, VTY_NEWLINE); + + e->thresh_hi = thresh; + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, + "si2quater neighbor-list del earfcn <1900-2200>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "EARFCN of neighbor\n") +{ + struct gsm_bts *bts = vty->index; + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + uint16_t arfcn = atoi(argv[1]); + int r = osmo_earfcn_del(e, arfcn); + if (r < 0) { + vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, + strerror(r), VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3873,6 +3942,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd); install_element(BTS_NODE, &cfg_bts_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 83cf2ec1f..113af5ca9 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -24,10 +24,15 @@ #include #include #include +#include +#include #include #include #include +#include + +#define SI2Q_MAX_LEN 160 /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -53,6 +58,201 @@ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) return bv.data_len; } +/* Append Repeated E-UTRAN Neighbour Cell to bitvec: + * see 3GPP TS 44.018 Table 10.5.2.33b.1 + */ +static inline void append_eutran_neib_cell(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + unsigned i; + for (i = 0; i < e->length; i++) { + if (e->arfcn[i] != OSMO_EARFCN_INVALID) { + bitvec_set_bit(bv, 1); /* EARFCN: */ + bitvec_set_uint(bv, e->arfcn[i], 16); + + if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i]) + bitvec_set_bit(bv, 0); + else { + /* Measurement Bandwidth: 9.1.54 */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->meas_bw[i], 3); + } + } + } + + /* stop bit - end of EARFCN + Measurement Bandwidth sequence */ + bitvec_set_bit(bv, 0); + + if (e->prio_valid) { + /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->prio, 3); + } else + bitvec_set_bit(bv, 0); + + /* THRESH_E-UTRAN_high */ + bitvec_set_uint(bv, e->thresh_hi, 5); + + if (e->thresh_lo_valid) { + /* THRESH_E-UTRAN_low: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->thresh_lo, 5); + } else + bitvec_set_bit(bv, 0); + + if (e->qrxlm_valid) { + /* E-UTRAN_QRXLEVMIN: */ + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, e->qrxlm, 5); + } else + bitvec_set_bit(bv, 0); +} + +static inline int append_earfcn_size(const struct osmo_earfcn_si2q *e) +{ + if (!e) + return -EFAULT; + /* account for all the constant bits */ + return 25 + osmo_earfcn_bit_size(e); +} + +static inline void append_earfcn(struct bitvec *bv, + const struct osmo_earfcn_si2q *e) +{ + /* Additions in Rel-5: */ + bitvec_set_bit(bv, H); + /* No 3G Additional Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-6: */ + bitvec_set_bit(bv, H); + /* 3G_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-7: */ + bitvec_set_bit(bv, H); + /* No 700_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* No 810_REPORTING_OFFSET */ + bitvec_set_bit(bv, 0); + /* Additions in Rel-8: */ + bitvec_set_bit(bv, H); + + /* Priority and E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* No Serving Cell Priority Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No 3G Priority Parameters Description */ + bitvec_set_bit(bv, 0); + /* E-UTRAN Parameters Description */ + bitvec_set_bit(bv, 1); + + /* E-UTRAN_CCN_ACTIVE */ + bitvec_set_bit(bv, 0); + /* E-UTRAN_Start: 9.1.54 */ + bitvec_set_bit(bv, 1); + /* E-UTRAN_Stop: 9.1.54 */ + bitvec_set_bit(bv, 1); + + /* No E-UTRAN Measurement Parameters Descr. */ + bitvec_set_bit(bv, 0); + /* No GPRS E-UTRAN Measurement Param. Descr. */ + bitvec_set_bit(bv, 0); + + /* Note: each of next 3 "repeated" structures might be repeated any + (0, 1, 2...) times - we only support 1 and 0 */ + + /* Repeated E-UTRAN Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* Note: we don't support different EARFCN arrays each with different + priority, threshold etc. */ + append_eutran_neib_cell(bv, e); + + /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */ + bitvec_set_bit(bv, 0); + + /* Note: following 2 repeated structs are not supported ATM */ + /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */ + bitvec_set_bit(bv, 0); + /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */ + bitvec_set_bit(bv, 0); + + /* Priority and E-UTRAN Parameters Description ends here */ + /* No 3G CSG Description */ + bitvec_set_bit(bv, 0); + /* No E-UTRAN CSG Description */ + bitvec_set_bit(bv, 0); + /* No Additions in Rel-9: */ + bitvec_set_bit(bv, L); +} + +/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */ +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + bool uarfcn, bool earfcn) +{ + int rc; + struct bitvec bv; + bv.data = data; + bv.data_len = 20; + bitvec_zero(&bv); + + /* BA_IND */ + bitvec_set_bit(&bv, 1); + /* 3G_BA_IND */ + bitvec_set_bit(&bv, 1); + /* MP_CHANGE_MARK */ + bitvec_set_bit(&bv, 0); + + /* we do not support multiple si2quater messages at the moment: */ + /* SI2quater_INDEX */ + bitvec_set_uint(&bv, 0, 4); + /* SI2quater_COUNT */ + bitvec_set_uint(&bv, 0, 4); + + /* No Measurement_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_Real Time Difference Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_BSIC Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_REPORT PRIORITY Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_MEASUREMENT_Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No NC Measurement Parameters */ + bitvec_set_bit(&bv, 0); + /* No extension (length) */ + bitvec_set_bit(&bv, 0); + + if (uarfcn) { + + } else { /* No 3G Neighbour Cell Description */ + bitvec_set_bit(&bv, 0); + } + + /* No 3G Measurement Parameters Description */ + bitvec_set_bit(&bv, 0); + /* No GPRS_3G_MEASUREMENT Parameters Descr. */ + bitvec_set_bit(&bv, 0); + + if (earfcn) { + rc = append_earfcn_size(e); + if (rc < 0) + return rc; + if (rc + bv.cur_bit > SI2Q_MAX_LEN) + return -ENOMEM; + append_earfcn(&bv, e); + } else { + /* No Additions in Rel-5: */ + bitvec_set_bit(&bv, L); + } + + bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); + return bv.data_len; +} + /* Append selection parameters to bitvec */ static void append_selection_params(struct bitvec *bv, const struct gsm48_si_selection_params *sp) diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 5490c8361..43a492af1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -494,6 +494,28 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts) return sizeof(*si2t); } +static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) +{ + int rc; + struct gsm48_system_information_type_2quater *si2q = + (struct gsm48_system_information_type_2quater *) output; + + memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); + + si2q->header.l2_plen = GSM48_LEN2PLEN(22); + si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR; + si2q->header.skip_indicator = 0; + si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; + + rc = rest_octets_si2quater(si2q->rest_octets, + &bts->si_common.si2quater_neigh_list, false, + true); + if (rc < 0) + return rc; + + return sizeof(*si2q) + rc; +} + static struct gsm48_si_ro_info si_info = { .selection_params = { .present = 0, @@ -831,6 +853,7 @@ static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = { [SYSINFO_TYPE_2] = &generate_si2, [SYSINFO_TYPE_2bis] = &generate_si2bis, [SYSINFO_TYPE_2ter] = &generate_si2ter, + [SYSINFO_TYPE_2quater] = &generate_si2quater, [SYSINFO_TYPE_3] = &generate_si3, [SYSINFO_TYPE_4] = &generate_si4, [SYSINFO_TYPE_5] = &generate_si5, diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 16035edcc..242c014db 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -315,6 +315,11 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ bts->neigh_list_manual_mode = 0; bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */ bts->si_common.cell_sel_par.rxlev_acc_min = 0; + bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list; + bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list; + bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST; + bts->si_common.si2quater_neigh_list.thresh_hi = 0; + osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); bts->si_common.neigh_list.data = bts->si_common.data.neigh_list; bts->si_common.neigh_list.data_len = sizeof(bts->si_common.data.neigh_list); -- cgit v1.2.3 From e43f8e040029a1bd72f23e139a787225ae2686a6 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 16 Apr 2016 12:52:55 -0400 Subject: nat/vty: Do not print token update statement On start this would print one line per BSC and this doesn't add a lot of value. Let's just remove this logging message. --- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 55f3dbf4f..3708bc2f1 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -881,11 +881,8 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", { struct bsc_config *conf = vty->index; - if (strncmp(conf->token, argv[0], 128) != 0) { - vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0], - VTY_NEWLINE); + if (strncmp(conf->token, argv[0], 128) != 0) conf->token_updated = true; - } bsc_replace_string(conf, &conf->token, argv[0]); return CMD_SUCCESS; -- cgit v1.2.3 From 36212f28501e36fed43edb579a9abd6b7adc0f27 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 12:06:05 +0200 Subject: Fix documentation for command parameters --- openbsc/src/libbsc/bsc_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 9634508e1..3a699c4ab 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2797,7 +2797,8 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" - "EARFCN of neighbor\n") + "EARFCN of neighbor\n" + "EARFCN\n") { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; -- cgit v1.2.3 From 0c1bc26b644c2ea7832afd615e9269095921c159 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 12:06:06 +0200 Subject: Fix earfcn deletion * fix typo in arg index * fix sign in error reporting * add vty test --- openbsc/src/libbsc/bsc_vty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 3a699c4ab..85b8394b1 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2802,11 +2802,11 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, { struct gsm_bts *bts = vty->index; struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; - uint16_t arfcn = atoi(argv[1]); + uint16_t arfcn = atoi(argv[0]); int r = osmo_earfcn_del(e, arfcn); if (r < 0) { vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn, - strerror(r), VTY_NEWLINE); + strerror(-r), VTY_NEWLINE); return CMD_WARNING; } -- cgit v1.2.3 From 26679e0475593aca645c7029e1aad899da73217a Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 15:57:13 +0200 Subject: Add basic UARFCN support * add data structures, generation functions * vty interface for neightbor UARFCNs specific to SI2quater * vty test * unit test Fixes: OS#1666 --- openbsc/src/libbsc/bsc_vty.c | 53 ++++++++++++ openbsc/src/libbsc/rest_octets.c | 91 ++++++++++++++++----- openbsc/src/libbsc/system_information.c | 139 +++++++++++++++++++++++++++++++- 3 files changed, 262 insertions(+), 21 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 85b8394b1..cc4686577 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -707,6 +707,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) } } + for (i = 0; i < bts->si_common.uarfcn_length; i++) { + vty_out(vty, " si2quater neighbor-list add uarfcn %u %u %u%s", + bts->si_common.data.uarfcn_list[i], + bts->si_common.data.scramble_list[i] & ~(1 << 9), + (bts->si_common.data.scramble_list[i] >> 9) & 1, + VTY_NEWLINE); + } + vty_out(vty, " codec-support fr"); if (bts->codec.hr) vty_out(vty, " hr"); @@ -2813,6 +2821,49 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, + "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" + "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" + "diversity bit\n") +{ + struct gsm_bts *bts = vty->index; + uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]); + + switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) { + case -ENOMEM: + vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " + "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -EADDRINUSE: + vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", + arfcn, scramble, VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, + "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "SI2quater Neighbor List\n" + "SI2quater Neighbor List\n" + "Delete from SI2quater manual neighbor list\n" + "UARFCN of neighbor\n" + "UARFCN\n" + "scrambling code\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) { + vty_out(vty, "Unable to delete uarfcn: pair not found%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, "si5 neighbor-list (add|del) arfcn <0-1023>", "SI5 Neighbor List\n" @@ -3945,6 +3996,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd); install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_add_cmd); + install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_del_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index 113af5ca9..b59430bcc 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -31,8 +31,7 @@ #include #include #include - -#define SI2Q_MAX_LEN 160 +#include /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net) @@ -108,14 +107,6 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, bitvec_set_bit(bv, 0); } -static inline int append_earfcn_size(const struct osmo_earfcn_si2q *e) -{ - if (!e) - return -EFAULT; - /* account for all the constant bits */ - return 25 + osmo_earfcn_bit_size(e); -} - static inline void append_earfcn(struct bitvec *bv, const struct osmo_earfcn_si2q *e) { @@ -188,11 +179,62 @@ static inline void append_earfcn(struct bitvec *bv, bitvec_set_bit(bv, L); } +static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u, + const uint16_t *sc, size_t length) +{ + int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length]; + uint8_t chan_list[16] = {0}; + + /* 3G Neighbour Cell Description */ + bitvec_set_bit(bv, 1); + /* No Index_Start_3G */ + bitvec_set_bit(bv, 0); + /* No Absolute_Index_Start_EMR */ + bitvec_set_bit(bv, 0); + + /* UTRAN FDD Description */ + bitvec_set_bit(bv, 1); + /* No Bandwidth_FDD */ + bitvec_set_bit(bv, 0); + + memset(w, 0, sizeof(w)); + for (i = 0; i < length; i++) + a[i] = sc[i]; + + /* Note: we do not support repeating Neighbour Cells ATM */ + /* Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 1); + + /* FDD-ARFCN */ + bitvec_set_bit(bv, 0); + /* Note: we do not support multiple UARFCN values ATM: */ + bitvec_set_uint(bv, u[0], 14); + + arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc); + range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0); + range_enc_range1024(chan_list, 0, f0_inc, w); + + /* FDD_Indic0: parameter value '0000000000' is not a member of the set */ + bitvec_set_bit(bv, f0_inc); + /* NR_OF_FDD_CELLS */ + bitvec_set_uint(bv, length, 5); + + i = bv->cur_bit; + bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list); + bv->cur_bit = i + range1024_p(length); + + /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */ + bitvec_set_bit(bv, 0); + + /* UTRAN TDD Description */ + bitvec_set_bit(bv, 0); +} + /* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, - bool uarfcn, bool earfcn) + const uint16_t *u, const uint16_t *sc, size_t u_len) { - int rc; + unsigned sz; struct bitvec bv; bv.data = data; bv.data_len = 20; @@ -226,8 +268,17 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No extension (length) */ bitvec_set_bit(&bv, 0); - if (uarfcn) { - + if (u_len) { + sz = uarfcn_size(u, sc, u_len); + /* Even if we do not append EARFCN we still need to set 3 bits */ + if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add UARFCNs bits, current %u + required %u + " + "reminder %u > max %u\n", bv.cur_bit, sz, 3, + SI2Q_MAX_LEN); + return -ENOMEM; + } + append_uarfcn(&bv, u, sc, u_len); } else { /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); } @@ -237,12 +288,14 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, /* No GPRS_3G_MEASUREMENT Parameters Descr. */ bitvec_set_bit(&bv, 0); - if (earfcn) { - rc = append_earfcn_size(e); - if (rc < 0) - return rc; - if (rc + bv.cur_bit > SI2Q_MAX_LEN) + if (e) { + sz = earfcn_size(e); + if (sz + bv.cur_bit > SI2Q_MAX_LEN) { + LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to " + "add EARFCNs bits, current %u + required %u > max " + "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN); return -ENOMEM; + } append_earfcn(&bv, e); } else { /* No Additions in Rel-5: */ diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 43a492af1..8952534c1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,6 +68,139 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +unsigned range1024_p(unsigned n) +{ + switch (n) { + case 0: return 0; + case 1: return 10; + case 2: return 19; + case 3: return 28; + case 4: return 36; + case 5: return 44; + case 6: return 52; + case 7: return 60; + case 8: return 67; + case 9: return 74; + case 10: return 81; + case 11: return 88; + case 12: return 95; + case 13: return 102; + case 14: return 109; + case 15: return 116; + case 16: return 122; + default: return 0; + } +} + +/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */ +unsigned range512_q(unsigned m) +{ + switch (m) { + case 0: return 0; + case 1: return 9; + case 2: return 17; + case 3: return 25; + case 4: return 32; + case 5: return 39; + case 6: return 46; + case 7: return 53; + case 8: return 59; + case 9: return 65; + case 10: return 71; + case 11: return 77; + case 12: return 83; + case 13: return 89; + case 14: return 95; + case 15: return 101; + case 16: return 106; + case 17: return 111; + case 18: return 116; + case 19: return 121; + case 20: return 126; + default: return 0; + } +} + +unsigned earfcn_size(const struct osmo_earfcn_si2q *e) +{ + /* account for all the constant bits in append_earfcn() */ + return 25 + osmo_earfcn_bit_size(e); +} + +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) +{ + /*account for all the constant bits in append_uarfcn() */ + return 29 + range1024_p(u_len); +} + +/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ +uint16_t encode_fdd(uint16_t scramble, bool diversity) +{ + if (diversity) + return scramble | (1 << 9); + return scramble; +} + +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble) +{ + uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true), + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length, i; + for (i = 0; i < len; i++) { + if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) { + /* we rely on the assumption that (uarfcn, scramble) + tuple is unique in the lists */ + if (i != len - 1) { /* move the tail if necessary */ + memmove(ual + i, ual + i + 1, 2 * (len - i + 1)); + memmove(scl + i, scl + i + 1, 2 * (len - i + 1)); + } + break; + } + } + + if (i == len) + return -EINVAL; + + bts->si_common.uarfcn_length--; + return 0; +} + +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity) +{ + size_t len = bts->si_common.uarfcn_length, i, k; + uint16_t scr, chk, + *ual = bts->si_common.data.uarfcn_list, + *scl = bts->si_common.data.scramble_list, + scramble1 = encode_fdd(scramble, true), + scramble0 = encode_fdd(scramble, false); + + scr = diversity ? scramble1 : scramble0; + chk = diversity ? scramble0 : scramble1; + + if (len == MAX_EARFCN_LIST) + return -ENOMEM; + + for (i = 0, k = 0; i < len; i++) { + if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i])) + return -EADDRINUSE; + if (scr > scl[i]) + k = i + 1; + } + /* we keep lists sorted by scramble code: + insert into appropriate position and move the tail */ + if (len - k) { + memmove(ual + k + 1, ual + k, (len - k) * 2); + memmove(scl + k + 1, scl + k, (len - k) * 2); + } + ual[k] = arfcn; + scl[k] = scr; + bts->si_common.uarfcn_length++; + return 0; +} + static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, const bool pgsm, const int arfcn) { @@ -508,8 +641,10 @@ static int generate_si2quater(uint8_t *output, struct gsm_bts *bts) si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; rc = rest_octets_si2quater(si2q->rest_octets, - &bts->si_common.si2quater_neigh_list, false, - true); + &bts->si_common.si2quater_neigh_list, + bts->si_common.data.uarfcn_list, + bts->si_common.data.scramble_list, + bts->si_common.uarfcn_length); if (rc < 0) return rc; -- cgit v1.2.3 From aafff96c4060e9bf6ceb9dee9652a91d293a6e1e Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 15:57:14 +0200 Subject: Add vty check for max si2quater size Explicitly check if added (U|E)ARFCN will fit into available si2quater message. --- openbsc/src/libbsc/bsc_vty.c | 23 +++++++++++++++-------- openbsc/src/libbsc/system_information.c | 21 ++++++++++++++++++++- 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index cc4686577..e81308b30 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2789,15 +2789,19 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, VTY_NEWLINE); return CMD_WARNING; } + if (si2q_size_check(bts)) { + if (e->thresh_hi && thresh != e->thresh_hi) + vty_out(vty, "Warning: multiple thresholds are not " + "supported, overriding previous threshold %u%s", + e->thresh_hi, VTY_NEWLINE); - if (e->thresh_hi && thresh != e->thresh_hi) - vty_out(vty, "Warning: multiple thresholds are not supported, " - "overriding previous threshold %u%s", - e->thresh_hi, VTY_NEWLINE); - - e->thresh_hi = thresh; - - return CMD_SUCCESS; + e->thresh_hi = thresh; + return CMD_SUCCESS; + } + vty_out(vty, "Warning: not enough space in si2quater for a given arfcn%s" + , VTY_NEWLINE); + osmo_earfcn_del(e, arfcn); + return CMD_WARNING; } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, @@ -2835,6 +2839,9 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, case -ENOMEM: vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + case -ENOSPC: + vty_out(vty, "Warning: not enough space in si2quater for a " + "given arfcn%s", VTY_NEWLINE); case -EADDRINUSE: vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE); diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 8952534c1..3b0f889a1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -134,6 +134,20 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len) return 29 + range1024_p(u_len); } +bool si2q_size_check(const struct gsm_bts *bts) +{ + const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + const uint16_t *u = bts->si_common.data.uarfcn_list, + *sc = bts->si_common.data.scramble_list; + size_t len = bts->si_common.uarfcn_length; + unsigned e_sz = e ? earfcn_size(e) : 1, + u_sz = len ? uarfcn_size(u, sc, len) : 1; + /* 2 bits are used in between UARFCN and EARFCN structs */ + if (SI2Q_MIN_LEN + u_sz + 2 + e_sz > SI2Q_MAX_LEN) + return false; + return true; +} + /* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ uint16_t encode_fdd(uint16_t scramble, bool diversity) { @@ -198,7 +212,12 @@ int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, ual[k] = arfcn; scl[k] = scr; bts->si_common.uarfcn_length++; - return 0; + + if (si2q_size_check(bts)) + return 0; + + bts_uarfcn_del(bts, arfcn, scramble); + return -ENOSPC; } static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter, -- cgit v1.2.3 From 8db12e42638483adb2feaf42cfd163dfe1fa973c Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 18 Apr 2016 23:11:18 +0200 Subject: Add extra debug output with channel mode and type This provides helpful information for debugging internal MNCC handler. --- openbsc/src/libbsc/bsc_api.c | 6 ++++-- openbsc/src/libmsc/gsm_04_08.c | 23 ++++++++++++++++++----- openbsc/src/libmsc/mncc_builtin.c | 3 ++- openbsc/src/osmo-nitb/bsc_hack.c | 4 +++- 4 files changed, 27 insertions(+), 9 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index e6d820d7e..b8b596782 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -393,11 +393,13 @@ int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, in if (handle_new_assignment(conn, chan_mode, full_rate) != 0) goto error; } else { - LOGP(DMSC, LOGL_NOTICE, - "Sending ChanModify for speech %d %d\n", chan_mode, full_rate); if (chan_mode == GSM48_CMODE_SPEECH_AMR) handle_mr_config(conn, conn->lchan, full_rate); + LOGP(DMSC, LOGL_NOTICE, + "Sending ChanModify for speech: %s on channel %s\n", + get_value_string(gsm48_chan_mode_names, chan_mode), + get_value_string(gsm_chan_t_names, conn->lchan->type)); gsm48_lchan_modify(conn->lchan, chan_mode); } diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec44f..7b78d48e2 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -1598,11 +1599,15 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; + enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; int rc; - DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n", - bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr); + DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " + "(bts=%u,trx=%u,ts=%u,%s)\n", + bts->nr, lchan->ts->trx->nr, lchan->ts->nr, + get_value_string(gsm_chan_t_names, lt), + remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr, + get_value_string(gsm_chan_t_names, rt)); if (bts->type != remote_bts->type) { LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n"); @@ -2999,6 +3004,7 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) struct gsm_bts *bts; struct gsm_lchan *lchan; struct gsm_trans *trans; + enum gsm48_chan_mode m; /* Find callref */ trans = trans_find_by_callref(net, callref); @@ -3038,8 +3044,11 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref) */ if (lchan->tch_mode == GSM48_CMODE_SIGN) { trans->conn->mncc_rtp_create_pending = 1; - return gsm0808_assign_req(trans->conn, - mncc_codec_for_mode(lchan->type), + m = mncc_codec_for_mode(lchan->type); + LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, m), + get_value_string(gsm_chan_t_names, lchan->type)); + return gsm0808_assign_req(trans->conn, m, lchan->type != GSM_LCHAN_TCH_H); } @@ -3068,6 +3077,10 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg) } lchan = trans->conn->lchan; + LOGP(DMNCC, LOGL_DEBUG, "RTP connect: codec=%s, chan_type=%s\n", + get_value_string(gsm48_chan_mode_names, + mncc_codec_for_mode(lchan->type)), + get_value_string(gsm_chan_t_names, lchan->type)); /* TODO: Check if payload_msg_type is compatible with what we have */ if (rtp->payload_type != lchan->abis_ip.rtp_payload) { diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c index 77df6fba3..ee98d2dd9 100644 --- a/openbsc/src/libmsc/mncc_builtin.c +++ b/openbsc/src/libmsc/mncc_builtin.c @@ -138,7 +138,8 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type, memset(&mncc, 0, sizeof(struct gsm_mncc)); mncc.callref = call->callref; mncc.lchan_mode = determine_lchan_mode(setup); - DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", call->callref); + DEBUGP(DMNCC, "(call %x) Modify channel mode: %s\n", call->callref, + get_value_string(gsm48_chan_mode_names, mncc.lchan_mode)); mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc); /* send setup to remote */ diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c index dffe642b8..0b360dcf6 100644 --- a/openbsc/src/osmo-nitb/bsc_hack.c +++ b/openbsc/src/osmo-nitb/bsc_hack.c @@ -288,8 +288,10 @@ int main(int argc, char **argv) rc = bsc_bootstrap_network(mncc_sock_from_cc, config_file); if (rc >= 0) mncc_sock_init(bsc_gsmnet, mncc_sock_path); - } else + } else { + DEBUGP(DMNCC, "Using internal MNCC handler.\n"); rc = bsc_bootstrap_network(int_mncc_recv, config_file); + } if (rc < 0) exit(1); #ifdef BUILD_SMPP -- cgit v1.2.3 From e01f5050efbc3828defa2df9b789624854297663 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 23 Apr 2016 18:00:18 +0200 Subject: Add missing include --- openbsc/src/libbsc/rest_octets.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index b59430bcc..aa286e578 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 299a9994656e97defea85689467e61ba34e8577e Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 28 Apr 2016 17:51:15 +0200 Subject: Fix comment typo --- openbsc/src/libbsc/system_information.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 3b0f889a1..0d96621b2 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -68,7 +68,7 @@ static int is_dcs_net(const struct gsm_bts *bts) return 1; } -/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ +/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */ unsigned range1024_p(unsigned n) { switch (n) { -- cgit v1.2.3 From 35697b9a109f08791c00dbb1a8dfaaaff29a8a80 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 29 Apr 2016 12:51:31 +0200 Subject: Adjust si2quater ranges Change ranges of arguments for si2quater neighbor lists to proper values according to 3GPP spec. --- openbsc/src/libbsc/bsc_vty.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index e81308b30..b928738c6 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2766,9 +2766,10 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } + DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, - "si2quater neighbor-list add earfcn <1900-2200> threshold <0-1000> " - "[<0-255>]", "SI2quater Neighbor List\n" + "si2quater neighbor-list add earfcn <0-65535> threshold <0-31> " + "[<0-7>]", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n" "threshold high bits\n" "measurement bandwidth\n") @@ -2805,7 +2806,7 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, } DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, - "si2quater neighbor-list del earfcn <1900-2200>", + "si2quater neighbor-list del earfcn <0-65535>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" @@ -2826,7 +2827,7 @@ DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, - "si2quater neighbor-list add uarfcn <1900-2200> <0-511> <0-1>", + "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n" "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n" @@ -2852,7 +2853,7 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, } DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd, - "si2quater neighbor-list del uarfcn <1900-2200> <0-511>", + "si2quater neighbor-list del uarfcn <0-16383> <0-511>", "SI2quater Neighbor List\n" "SI2quater Neighbor List\n" "Delete from SI2quater manual neighbor list\n" -- cgit v1.2.3 From 3ffce19cb4929c907460753d302e4720558cc6d2 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 25 Apr 2016 15:22:00 +0200 Subject: Disconnect calls with incompatible channel types / modes In case both TCH/H and TCH/F or different codecs are configured and internal MNCC handler is used we might end up in a situation where call legs with incompatible channel types or codecs would be connected resulting in a broken audio. Disconnect such calls with appropriate error message. Fixes: OS#1663 --- openbsc/src/libmsc/gsm_04_08.c | 46 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 7b78d48e2..05cb88679 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1600,6 +1600,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts; enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type; + enum gsm48_chan_mode lm = lchan->tch_mode, rm = remote_lchan->tch_mode; int rc; DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and " @@ -1614,6 +1615,22 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) return -EINVAL; } + if (lt != rt) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel types: local = %s, remote = %s\n", + get_value_string(gsm_chan_t_names, lt), + get_value_string(gsm_chan_t_names, rt)); + return -EBADSLT; + } + + if (lm != rm) { + LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different" + " channel modes: local = %s, remote = %s\n", + get_value_string(gsm48_chan_mode_names, lm), + get_value_string(gsm48_chan_mode_names, rm)); + return -EMEDIUMTYPE; + } + // todo: map between different bts types switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: @@ -1851,6 +1868,30 @@ static void gsm48_cc_timeout(void *arg) } +/* disconnect both calls from the bridge */ +static inline void disconnect_bridge(struct gsm_network *net, + struct gsm_mncc_bridge *bridge, int err) +{ + struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]); + struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]); + struct gsm_mncc mx_rel; + if (!trans0 || !trans1) + return; + + DEBUGP(DCC, "Failed to bridge TCH for calls %x <-> %x :: %s \n", + trans0->callref, trans1->callref, strerror(err)); + + memset(&mx_rel, 0, sizeof(struct gsm_mncc)); + mncc_set_cause(&mx_rel, GSM48_CAUSE_LOC_INN_NET, + GSM48_CC_CAUSE_CHAN_UNACCEPT); + + mx_rel.callref = trans0->callref; + gsm48_cc_tx_disconnect(trans0, &mx_rel); + + mx_rel.callref = trans1->callref; + gsm48_cc_tx_disconnect(trans1, &mx_rel); +} + static void gsm48_start_cc_timer(struct gsm_trans *trans, int current, int sec, int micro) { @@ -3221,7 +3262,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) /* handle special messages */ switch(msg_type) { case MNCC_BRIDGE: - return tch_bridge(net, arg); + rc = tch_bridge(net, arg); + if (rc < 0) + disconnect_bridge(net, arg, -rc); + return rc; case MNCC_FRAME_DROP: return tch_recv_mncc(net, data->callref, 0); case MNCC_FRAME_RECV: -- cgit v1.2.3 From 121e9a4164e65dfb68b2bf09297a8537a2f659c5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 20 Apr 2016 13:13:19 +0200 Subject: Start to use struct osmo_auth_vector from gsm_auth_tuple Rather than having a 'private' structure for kc, sres and rand, we now finally (with 4 years delay) use osmo_auth_vector from libosmogsm, which encapsulates authentication vectors that can be either GSM triplets or UMTS quintuples or a combination of both. gsm_auth_tuple becomes a wrapper around osmo_auth_vector, adding use_count and key_seq to it. key_seq is no longer initialized inside gprs_gsup_messages.c, as there is no CKSN / key_seq inside the message anyway. If a usre of the code needs key_seq, they need to manage it themselves. --- openbsc/src/gprs/gprs_gmm.c | 12 +++++---- openbsc/src/gprs/gprs_gsup_messages.c | 43 ++++++++++++++----------------- openbsc/src/gprs/gprs_subscriber.c | 13 +++++----- openbsc/src/gprs/sgsn_vty.c | 12 ++++----- openbsc/src/libmsc/auth.c | 8 +++--- openbsc/src/libmsc/db.c | 18 ++++++------- openbsc/src/libmsc/gsm_04_08.c | 10 +++---- openbsc/src/libmsc/vty_interface_layer3.c | 6 ++--- 8 files changed, 61 insertions(+), 61 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index 5f0a5fda1..6b6e741fa 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -512,9 +512,9 @@ static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx, at = &ctx->auth_triplet; - if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->sres) || - memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->sres, - sizeof(at->sres)) != 0) { + if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->vec.sres) || + memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->vec.sres, + sizeof(at->vec.sres)) != 0) { LOGMMCTXP(LOGL_NOTICE, ctx, "Received SRES doesn't match\n"); rc = gsm48_tx_gmm_auth_ciph_rej(ctx); @@ -637,7 +637,8 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx) struct gsm_auth_tuple *at = &ctx->auth_triplet; mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360); - return gsm48_tx_gmm_auth_ciph_req(ctx, at->rand, at->key_seq, + return gsm48_tx_gmm_auth_ciph_req(ctx, at->vec.rand, + at->key_seq, GPRS_ALGO_GEA0); } @@ -1468,7 +1469,8 @@ static void mmctx_timer_cb(void *_mm) } at = &mm->auth_triplet; - gsm48_tx_gmm_auth_ciph_req(mm, at->rand, at->key_seq, GPRS_ALGO_GEA0); + gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq, + GPRS_ALGO_GEA0); osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0); break; case 3370: /* waiting for IDENTITY RESPONSE */ diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index 07485f7f9..0b1dc9b00 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -3,6 +3,7 @@ /* * (C) 2014 by Sysmocom s.f.m.c. GmbH * (C) 2015 by Holger Hans Peter Freyther + * (C) 2016 by Harald Welte * All Rights Reserved * * Author: Jacob Erlbeck @@ -82,7 +83,7 @@ static int decode_pdp_info(uint8_t *data, size_t data_len, } static int decode_auth_info(uint8_t *data, size_t data_len, - struct gsm_auth_tuple *auth_tuple) + struct osmo_auth_vector *auth_vector) { int rc; uint8_t tag; @@ -100,24 +101,24 @@ static int decode_auth_info(uint8_t *data, size_t data_len, switch (iei) { case GPRS_GSUP_RAND_IE: - if (value_len != sizeof(auth_tuple->rand)) + if (value_len != sizeof(auth_vector->rand)) goto parse_error; - memcpy(auth_tuple->rand, value, value_len); + memcpy(auth_vector->rand, value, value_len); break; case GPRS_GSUP_SRES_IE: - if (value_len != sizeof(auth_tuple->sres)) + if (value_len != sizeof(auth_vector->sres)) goto parse_error; - memcpy(auth_tuple->sres, value, value_len); + memcpy(auth_vector->sres, value, value_len); break; case GPRS_GSUP_KC_IE: - if (value_len != sizeof(auth_tuple->kc)) + if (value_len != sizeof(auth_vector->kc)) goto parse_error; - memcpy(auth_tuple->kc, value, value_len); + memcpy(auth_vector->kc, value, value_len); break; default: @@ -149,7 +150,7 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, uint8_t *value; size_t value_len; static const struct gprs_gsup_pdp_info empty_pdp_info = {0}; - static const struct gsm_auth_tuple empty_auth_info = {0}; + static const struct osmo_auth_vector empty_auth_info = {0}; static const struct gprs_gsup_message empty_gsup_message = {0}; *gsup_msg = empty_gsup_message; @@ -183,7 +184,7 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, while (data_len > 0) { enum gprs_gsup_iei iei; struct gprs_gsup_pdp_info pdp_info; - struct gsm_auth_tuple auth_info; + struct osmo_auth_vector auth_info; rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); if (rc < 0) @@ -252,7 +253,7 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, break; case GPRS_GSUP_AUTH_TUPLE_IE: - if (gsup_msg->num_auth_tuples >= GPRS_GSUP_MAX_NUM_AUTH_INFO) { + if (gsup_msg->num_auth_vectors >= GPRS_GSUP_MAX_NUM_AUTH_INFO) { LOGP(DGPRS, LOGL_ERROR, "GSUP IE type %d (AUTH_INFO) max exceeded\n", iei); @@ -260,13 +261,12 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, } auth_info = empty_auth_info; - auth_info.key_seq = gsup_msg->num_auth_tuples; rc = decode_auth_info(value, value_len, &auth_info); if (rc < 0) return rc; - gsup_msg->auth_tuples[gsup_msg->num_auth_tuples++] = + gsup_msg->auth_vectors[gsup_msg->num_auth_vectors++] = auth_info; break; @@ -325,7 +325,7 @@ static void encode_pdp_info(struct msgb *msg, enum gprs_gsup_iei iei, } static void encode_auth_info(struct msgb *msg, enum gprs_gsup_iei iei, - const struct gsm_auth_tuple *auth_tuple) + const struct osmo_auth_vector *auth_vector) { uint8_t *len_field; size_t old_len; @@ -334,13 +334,13 @@ static void encode_auth_info(struct msgb *msg, enum gprs_gsup_iei iei, old_len = msgb_length(msg); msgb_tlv_put(msg, GPRS_GSUP_RAND_IE, - sizeof(auth_tuple->rand), auth_tuple->rand); + sizeof(auth_vector->rand), auth_vector->rand); msgb_tlv_put(msg, GPRS_GSUP_SRES_IE, - sizeof(auth_tuple->sres), auth_tuple->sres); + sizeof(auth_vector->sres), auth_vector->sres); msgb_tlv_put(msg, GPRS_GSUP_KC_IE, - sizeof(auth_tuple->kc), auth_tuple->kc); + sizeof(auth_vector->kc), auth_vector->kc); /* Update length field */ *len_field = msgb_length(msg) - old_len; @@ -406,14 +406,11 @@ void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg } } - for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) { - const struct gsm_auth_tuple *auth_info; + for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { + const struct osmo_auth_vector *auth_vector; - auth_info = &gsup_msg->auth_tuples[idx]; + auth_vector = &gsup_msg->auth_vectors[idx]; - if (auth_info->key_seq == GSM_KEY_SEQ_INVAL) - continue; - - encode_auth_info(msg, GPRS_GSUP_AUTH_TUPLE_IE, auth_info); + encode_auth_info(msg, GPRS_GSUP_AUTH_TUPLE_IE, auth_vector); } } diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 3467293be..678c1de6a 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -199,18 +199,18 @@ static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr, struct sgsn_subscriber_data *sdata = subscr->sgsn_data; LOGGSUBSCRP(LOGL_INFO, subscr, - "Got SendAuthenticationInfoResult, num_auth_tuples = %zu\n", - gsup_msg->num_auth_tuples); + "Got SendAuthenticationInfoResult, num_auth_vectors = %zu\n", + gsup_msg->num_auth_vectors); - if (gsup_msg->num_auth_tuples > 0) { + if (gsup_msg->num_auth_vectors > 0) { memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets)); for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++) sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL; } - for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) { - size_t key_seq = gsup_msg->auth_tuples[idx].key_seq; + for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { + size_t key_seq = idx; LOGGSUBSCRP(LOGL_DEBUG, subscr, "Adding auth tuple, cksn = %zu\n", key_seq); if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) { @@ -219,7 +219,8 @@ static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr, key_seq); continue; } - sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx]; + sdata->auth_triplets[key_seq].vec = gsup_msg->auth_vectors[idx]; + sdata->auth_triplets[key_seq].key_seq = key_seq; } sdata->auth_triplets_updated = 1; diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 3f6116393..50f0e8f6e 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -613,11 +613,11 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, vty_out(vty, " seq # : %d, ", at->key_seq); vty_out(vty, " RAND : %s, ", - osmo_hexdump(at->rand, sizeof(at->rand))); + osmo_hexdump(at->vec.rand, sizeof(at->vec.rand))); vty_out(vty, " SRES : %s, ", - osmo_hexdump(at->sres, sizeof(at->sres))); + osmo_hexdump(at->vec.sres, sizeof(at->vec.sres))); vty_out(vty, " Kc : %s%s", - osmo_hexdump(at->kc, sizeof(at->kc)), + osmo_hexdump(at->vec.kc, sizeof(at->vec.kc)), VTY_NEWLINE); } @@ -704,17 +704,17 @@ DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd, OSMO_ASSERT(subscr->sgsn_data); - if (osmo_hexparse(sres_str, &at.sres[0], sizeof(at.sres)) < 0) { + if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) { vty_out(vty, "%% invalid SRES value '%s'%s", sres_str, VTY_NEWLINE); goto failed; } - if (osmo_hexparse(rand_str, &at.rand[0], sizeof(at.rand)) < 0) { + if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) { vty_out(vty, "%% invalid RAND value '%s'%s", rand_str, VTY_NEWLINE); goto failed; } - if (osmo_hexparse(kc_str, &at.kc[0], sizeof(at.kc)) < 0) { + if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) { vty_out(vty, "%% invalid Kc value '%s'%s", kc_str, VTY_NEWLINE); goto failed; diff --git a/openbsc/src/libmsc/auth.c b/openbsc/src/libmsc/auth.c index f30d56dce..9191ae8b3 100644 --- a/openbsc/src/libmsc/auth.c +++ b/openbsc/src/libmsc/auth.c @@ -54,9 +54,9 @@ _use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple) } for (i=0; i<4; i++) - atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i]; + atuple->vec.sres[i] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i]; for (i=4; i<12; i++) - atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i]; + atuple->vec.kc[i-4] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i]; return 0; } @@ -71,7 +71,7 @@ _use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple) return -1; } - comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc); + comp128(ainfo->a3a8_ki, atuple->vec.rand, atuple->vec.sres, atuple->vec.kc); return 0; } @@ -122,7 +122,7 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple, } atuple->use_count = 1; - if (RAND_bytes(atuple->rand, sizeof(atuple->rand)) != 1) { + if (RAND_bytes(atuple->vec.rand, sizeof(atuple->vec.rand)) != 1) { LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n"); return AUTH_ERROR; } diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 267b5ef41..a23ec89ae 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -700,25 +700,25 @@ int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple, atuple->key_seq = dbi_result_get_ulonglong(result, "key_seq"); len = dbi_result_get_field_length(result, "rand"); - if (len != sizeof(atuple->rand)) + if (len != sizeof(atuple->vec.rand)) goto err_size; blob = dbi_result_get_binary(result, "rand"); - memcpy(atuple->rand, blob, len); + memcpy(atuple->vec.rand, blob, len); len = dbi_result_get_field_length(result, "sres"); - if (len != sizeof(atuple->sres)) + if (len != sizeof(atuple->vec.sres)) goto err_size; blob = dbi_result_get_binary(result, "sres"); - memcpy(atuple->sres, blob, len); + memcpy(atuple->vec.sres, blob, len); len = dbi_result_get_field_length(result, "kc"); - if (len != sizeof(atuple->kc)) + if (len != sizeof(atuple->vec.kc)) goto err_size; blob = dbi_result_get_binary(result, "kc"); - memcpy(atuple->kc, blob, len); + memcpy(atuple->vec.kc, blob, len); dbi_result_free(result); @@ -759,11 +759,11 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple, /* Update / Insert */ dbi_conn_quote_binary_copy(conn, - atuple->rand, sizeof(atuple->rand), &rand_str); + atuple->vec.rand, sizeof(atuple->vec.rand), &rand_str); dbi_conn_quote_binary_copy(conn, - atuple->sres, sizeof(atuple->sres), &sres_str); + atuple->vec.sres, sizeof(atuple->vec.sres), &sres_str); dbi_conn_quote_binary_copy(conn, - atuple->kc, sizeof(atuple->kc), &kc_str); + atuple->vec.kc, sizeof(atuple->vec.kc), &kc_str); if (!upd) { result = dbi_conn_queryf(conn, diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 05cb88679..f02f784fe 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -234,11 +234,11 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, /* Then do whatever is needed ... */ if (rc == AUTH_DO_AUTH_THEN_CIPH) { /* Start authentication */ - return gsm48_tx_mm_auth_req(conn, op->atuple.rand, op->atuple.key_seq); + return gsm48_tx_mm_auth_req(conn, op->atuple.vec.rand, op->atuple.key_seq); } else if (rc == AUTH_DO_CIPH) { /* Start ciphering directly */ return gsm0808_cipher_mode(conn, net->a5_encryption, - op->atuple.kc, 8, 0); + op->atuple.vec.kc, 8, 0); } return -EINVAL; /* not reached */ @@ -1102,12 +1102,12 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct } /* Validate SRES */ - if (memcmp(conn->sec_operation->atuple.sres, ar->sres,4)) { + if (memcmp(conn->sec_operation->atuple.vec.sres, ar->sres,4)) { int rc; gsm_cbfn *cb = conn->sec_operation->cb; DEBUGPC(DMM, "Invalid (expected %s)\n", - osmo_hexdump(conn->sec_operation->atuple.sres, 4)); + osmo_hexdump(conn->sec_operation->atuple.vec.sres, 4)); if (cb) cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED, @@ -1122,7 +1122,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct /* Start ciphering */ return gsm0808_cipher_mode(conn, net->a5_encryption, - conn->sec_operation->atuple.kc, 8, 0); + conn->sec_operation->atuple.vec.kc, 8, 0); } /* Receive a GSM 04.08 Mobility Management (MM) message */ diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index 790fedf39..4c2088a0f 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -94,13 +94,13 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr) vty_out(vty, " seq # : %d%s", atuple.key_seq, VTY_NEWLINE); vty_out(vty, " RAND : %s%s", - osmo_hexdump(atuple.rand, sizeof(atuple.rand)), + osmo_hexdump(atuple.vec.rand, sizeof(atuple.vec.rand)), VTY_NEWLINE); vty_out(vty, " SRES : %s%s", - osmo_hexdump(atuple.sres, sizeof(atuple.sres)), + osmo_hexdump(atuple.vec.sres, sizeof(atuple.vec.sres)), VTY_NEWLINE); vty_out(vty, " Kc : %s%s", - osmo_hexdump(atuple.kc, sizeof(atuple.kc)), + osmo_hexdump(atuple.vec.kc, sizeof(atuple.vec.kc)), VTY_NEWLINE); } -- cgit v1.2.3 From 53373bca8f9fe79ca981f9fc1ef644586bd5c3b2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 20 Apr 2016 17:11:43 +0200 Subject: move gsm_04_08_gprs.h to libosmocore This requres the corresponding commit in libosmocore. --- openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gb_proxy.c | 2 +- openbsc/src/gprs/gb_proxy_patch.c | 1 - openbsc/src/gprs/gb_proxy_peer.c | 1 - openbsc/src/gprs/gprs_gb_parse.c | 2 +- openbsc/src/gprs/gprs_gmm.c | 2 +- openbsc/src/gprs/gprs_sgsn.c | 2 +- openbsc/src/gprs/gprs_subscriber.c | 1 + openbsc/src/gprs/gprs_utils.c | 2 +- openbsc/src/gprs/gsm_04_08_gprs.c | 141 ------------------------------------- openbsc/src/gprs/sgsn_auth.c | 2 +- openbsc/src/gprs/sgsn_libgtp.c | 2 +- openbsc/src/gprs/sgsn_vty.c | 2 +- 13 files changed, 10 insertions(+), 152 deletions(-) delete mode 100644 openbsc/src/gprs/gsm_04_08_gprs.c (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f406dd795..104bd296b 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -27,7 +27,7 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ gprs_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ - gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c \ + sgsn_cdr.c sgsn_ares.c \ oap.c oap_messages.c osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 6e6b03b86..111f05208 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -48,7 +48,7 @@ #include #include -#include +#include #include #include diff --git a/openbsc/src/gprs/gb_proxy_patch.c b/openbsc/src/gprs/gb_proxy_patch.c index c1d2497db..7bddc4494 100644 --- a/openbsc/src/gprs/gb_proxy_patch.c +++ b/openbsc/src/gprs/gb_proxy_patch.c @@ -23,7 +23,6 @@ #include #include -#include #include #include diff --git a/openbsc/src/gprs/gb_proxy_peer.c b/openbsc/src/gprs/gb_proxy_peer.c index c2cdd0e67..5365ff0fa 100644 --- a/openbsc/src/gprs/gb_proxy_peer.c +++ b/openbsc/src/gprs/gb_proxy_peer.c @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/openbsc/src/gprs/gprs_gb_parse.c b/openbsc/src/gprs/gprs_gb_parse.c index 63ac9028d..5ec3cf6ea 100644 --- a/openbsc/src/gprs/gprs_gb_parse.c +++ b/openbsc/src/gprs/gprs_gb_parse.c @@ -19,12 +19,12 @@ */ #include +#include #include #include -#include #include #include diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index 6b6e741fa..2bbc5ff34 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -46,7 +47,6 @@ #include #include #include -#include #include #include #include diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index b7bda49ba..65f789d6d 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -29,12 +29,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 678c1de6a..5b0bf398c 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -20,6 +20,7 @@ * */ +#include #include #include diff --git a/openbsc/src/gprs/gprs_utils.c b/openbsc/src/gprs/gprs_utils.c index 895a03384..64bfd743d 100644 --- a/openbsc/src/gprs/gprs_utils.c +++ b/openbsc/src/gprs/gprs_utils.c @@ -20,11 +20,11 @@ * */ #include -#include #include #include +#include #include #include diff --git a/openbsc/src/gprs/gsm_04_08_gprs.c b/openbsc/src/gprs/gsm_04_08_gprs.c deleted file mode 100644 index 3ae50e26c..000000000 --- a/openbsc/src/gprs/gsm_04_08_gprs.c +++ /dev/null @@ -1,141 +0,0 @@ -/* (C) 2009-2010 by Harald Welte - * (C) 2010 by On-Waves - * (C) 2014-2015 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 . - * - */ - - -#include - -#include - -/* Protocol related stuff, should go into libosmocore */ - -/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */ -const struct value_string gsm48_gmm_cause_names_[] = { - { GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown in HLR" }, - { GMM_CAUSE_ILLEGAL_MS, "Illegal MS" }, - { GMM_CAUSE_ILLEGAL_ME, "Illegal ME" }, - { GMM_CAUSE_GPRS_NOTALLOWED, "GPRS services not allowed" }, - { GMM_CAUSE_GPRS_OTHER_NOTALLOWED, - "GPRS services and non-GPRS services not allowed" }, - { GMM_CAUSE_MS_ID_NOT_DERIVED, - "MS identity cannot be derived by the network" }, - { GMM_CAUSE_IMPL_DETACHED, "Implicitly detached" }, - { GMM_CAUSE_PLMN_NOTALLOWED, "PLMN not allowed" }, - { GMM_CAUSE_LA_NOTALLOWED, "Location Area not allowed" }, - { GMM_CAUSE_ROAMING_NOTALLOWED, - "Roaming not allowed in this location area" }, - { GMM_CAUSE_NO_GPRS_PLMN, - "GPRS services not allowed in this PLMN" }, - { GMM_CAUSE_MSC_TEMP_NOTREACH, "MSC temporarily not reachable" }, - { GMM_CAUSE_NET_FAIL, "Network failure" }, - { GMM_CAUSE_CONGESTION, "Congestion" }, - { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" }, - { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" }, - { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL, - "Message type non-existant or not implemented" }, - { GMM_CAUSE_MSGT_INCOMP_P_STATE, - "Message type not compatible with protocol state" }, - { GMM_CAUSE_IE_NOTEXIST_NOTIMPL, - "Information element non-existent or not implemented" }, - { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" }, - { GMM_CAUSE_MSG_INCOMP_P_STATE, - "Message not compatible with protocol state " }, - { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" }, - { 0, NULL } -}; - -const struct value_string *gsm48_gmm_cause_names = gsm48_gmm_cause_names_; - -/* 10.5.6.6 SM Cause / Table 10.5.157 */ -const struct value_string gsm48_gsm_cause_names_[] = { - { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" }, - { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" }, - { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" }, - { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" }, - { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" }, - { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" }, - { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" }, - { GSM_CAUSE_REQ_SERV_OPT_NOTSUB, - "Requested service option not subscribed" }, - { GSM_CAUSE_SERV_OPT_TEMP_OOO, - "Service option temporarily out of order" }, - { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" }, - { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" }, - { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" }, - { GSM_CAUSE_NET_FAIL, "Network Failure" }, - { GSM_CAUSE_REACT_RQD, "Reactivation required" }, - { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " }, - { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" }, - { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" }, - { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" }, - { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL, - "Message type non-existant or not implemented" }, - { GSM_CAUSE_MSGT_INCOMP_P_STATE, - "Message type not compatible with protocol state" }, - { GSM_CAUSE_IE_NOTEXIST_NOTIMPL, - "Information element non-existent or not implemented" }, - { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" }, - { GSM_CAUSE_MSG_INCOMP_P_STATE, - "Message not compatible with protocol state " }, - { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" }, - { 0, NULL } -}; - -const struct value_string *gsm48_gsm_cause_names = gsm48_gsm_cause_names_; - -/* 10.5.5.2 */ -const struct value_string gprs_att_t_strs_[] = { - { GPRS_ATT_T_ATTACH, "GPRS attach" }, - { GPRS_ATT_T_ATT_WHILE_IMSI, "GPRS attach while IMSI attached" }, - { GPRS_ATT_T_COMBINED, "Combined GPRS/IMSI attach" }, - { 0, NULL } -}; - -const struct value_string *gprs_att_t_strs = gprs_att_t_strs_; - -const struct value_string gprs_upd_t_strs_[] = { - { GPRS_UPD_T_RA, "RA updating" }, - { GPRS_UPD_T_RA_LA, "combined RA/LA updating" }, - { GPRS_UPD_T_RA_LA_IMSI_ATT, "combined RA/LA updating + IMSI attach" }, - { GPRS_UPD_T_PERIODIC, "periodic updating" }, - { 0, NULL } -}; - -const struct value_string *gprs_upd_t_strs = gprs_upd_t_strs_; - -/* 10.5.5.5 */ -const struct value_string gprs_det_t_mo_strs_[] = { - { GPRS_DET_T_MO_GPRS, "GPRS detach" }, - { GPRS_DET_T_MO_IMSI, "IMSI detach" }, - { GPRS_DET_T_MO_COMBINED, "Combined GPRS/IMSI detach" }, - { 0, NULL } -}; - -const struct value_string *gprs_det_t_mo_strs = gprs_det_t_mo_strs_; - -const struct value_string gprs_det_t_mt_strs_[] = { - { GPRS_DET_T_MT_REATT_REQ, "re-attach required" }, - { GPRS_DET_T_MT_REATT_NOTREQ, "re-attach not required" }, - { GPRS_DET_T_MT_IMSI, "IMSI detach (after VLR failure)" }, - { 0, NULL } -}; - -const struct value_string *gprs_det_t_mt_strs = gprs_det_t_mt_strs_; - diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c index b83294d30..f0c4316c0 100644 --- a/openbsc/src/gprs/sgsn_auth.c +++ b/openbsc/src/gprs/sgsn_auth.c @@ -19,11 +19,11 @@ * */ +#include #include #include #include #include -#include #include const struct value_string auth_state_names[] = { diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c index aff2f91a1..aaf7e7aa7 100644 --- a/openbsc/src/gprs/sgsn_libgtp.c +++ b/openbsc/src/gprs/sgsn_libgtp.c @@ -38,8 +38,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 50f0e8f6e..f16c95ad4 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -27,13 +27,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include -- cgit v1.2.3 From d3fa84dbba3b67cdbe2d8c789b2833b5ddf42068 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 20 Apr 2016 17:50:17 +0200 Subject: use new libosmocore gsm_23_003.h for IMEI/IMSI length ... rather than our private definitions everwhere. As an added benefit, gprs_gsup_messages.h is now free of any header dependencies within openbsc. --- openbsc/src/gprs/gprs_gsup_messages.c | 1 + openbsc/src/gprs/gprs_subscriber.c | 5 +++-- openbsc/src/gprs/gtphub_ares.c | 2 +- openbsc/src/libcommon/gsm_subscriber_base.c | 2 +- openbsc/src/libmsc/ctrl_commands.c | 2 +- openbsc/src/libmsc/db.c | 7 ++++--- openbsc/src/osmo-bsc_nat/bsc_ussd.c | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index 0b1dc9b00..b3c8dab5f 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -31,6 +31,7 @@ #include #include +#include #include diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 5b0bf398c..648f91204 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -757,8 +757,9 @@ struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mm } if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) { - strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1); - subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0; + strncpy(subscr->equipment.imei, mmctx->imei, + sizeof(subscr->equipment.imei)-1); + subscr->equipment.imei[sizeof(subscr->equipment.imei)-1] = 0; } if (subscr->lac != mmctx->ra.lac) diff --git a/openbsc/src/gprs/gtphub_ares.c b/openbsc/src/gprs/gtphub_ares.c index 947f2ddd5..667013b8b 100644 --- a/openbsc/src/gprs/gtphub_ares.c +++ b/openbsc/src/gprs/gtphub_ares.c @@ -55,7 +55,7 @@ struct ggsn_lookup { struct gtphub *hub; - char imsi_str[GSM_IMSI_LENGTH]; + char imsi_str[GSM23003_IMSI_MAX_DIGITS+1]; char apn_ni_str[GSM_APN_LENGTH]; char apn_oi_str[GSM_APN_LENGTH]; int have_3dig_mnc; diff --git a/openbsc/src/libcommon/gsm_subscriber_base.c b/openbsc/src/libcommon/gsm_subscriber_base.c index a455824a3..50f411888 100644 --- a/openbsc/src/libcommon/gsm_subscriber_base.c +++ b/openbsc/src/libcommon/gsm_subscriber_base.c @@ -112,7 +112,7 @@ struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp, if (!subscr) return NULL; - strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); + strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1); subscr->group = sgrp; return subscr; } diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c index 9ac39de95..0d6a37c96 100644 --- a/openbsc/src/libmsc/ctrl_commands.c +++ b/openbsc/src/libmsc/ctrl_commands.c @@ -56,7 +56,7 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi if (!imsi || !msisdn) rc = 1; - else if (strlen(imsi) >= GSM_IMSI_LENGTH) + else if (strlen(imsi) > GSM23003_IMSI_MAX_DIGITS) rc = 1; else if (strlen(msisdn) >= GSM_EXTENSION_LENGTH) rc = 1; diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index a23ec89ae..e5017ae7b 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -529,7 +530,7 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi) return NULL; } subscr->id = dbi_conn_sequence_last(conn, NULL); - strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); + strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1); dbi_result_free(result); LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi); db_subscriber_alloc_exten(subscr); @@ -803,7 +804,7 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result) const char *string; string = dbi_result_get_string(result, "imsi"); if (string) - strncpy(subscr->imsi, string, GSM_IMSI_LENGTH-1); + strncpy(subscr->imsi, string, sizeof(subscr->imsi)-1); string = dbi_result_get_string(result, "tmsi"); if (string) @@ -1317,7 +1318,7 @@ int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t *token return 0; } -int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IMEI_LENGTH]) +int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM23003_IMEISV_NUM_DIGITS]) { unsigned long long equipment_id, watch_id; dbi_result result; diff --git a/openbsc/src/osmo-bsc_nat/bsc_ussd.c b/openbsc/src/osmo-bsc_nat/bsc_ussd.c index e0809059a..2f68381ac 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_ussd.c +++ b/openbsc/src/osmo-bsc_nat/bsc_ussd.c @@ -400,7 +400,7 @@ int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parse if (parsed->bssap != BSSAP_MSG_DTAP) return 0; - if (strlen(con->filter_state.imsi) >= GSM_IMSI_LENGTH) + if (strlen(con->filter_state.imsi) > GSM23003_IMSI_MAX_DIGITS) return 0; hdr48 = bsc_unpack_dtap(parsed, msg, &len); -- cgit v1.2.3 From 28903a99eae60cee616901fd3863960b1321ff54 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 14:53:43 +0200 Subject: Rename gprs_gsup_* to osmo_gsup_* This is a preparation to move the related code to libosmocore, whilst at the same time generalizing it from GPRS Subscriber Update Protocol to the Osmocom Generic Subscriber Update Protoco. --- openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gprs_gsup_messages.c | 417 ---------------------------------- openbsc/src/gprs/gprs_subscriber.c | 90 ++++---- openbsc/src/gprs/osmo_gsup_messages.c | 417 ++++++++++++++++++++++++++++++++++ 4 files changed, 463 insertions(+), 463 deletions(-) delete mode 100644 openbsc/src/gprs/gprs_gsup_messages.c create mode 100644 openbsc/src/gprs/osmo_gsup_messages.c (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 104bd296b..7889d5fd9 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -26,7 +26,7 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ - gprs_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ + osmo_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ sgsn_cdr.c sgsn_ares.c \ oap.c oap_messages.c osmo_sgsn_LDADD = \ diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c deleted file mode 100644 index b3c8dab5f..000000000 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ /dev/null @@ -1,417 +0,0 @@ -/* GPRS Subscriber Update Protocol message encoder/decoder */ - -/* - * (C) 2014 by Sysmocom s.f.m.c. GmbH - * (C) 2015 by Holger Hans Peter Freyther - * (C) 2016 by Harald Welte - * All Rights Reserved - * - * Author: Jacob Erlbeck - * - * 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 . - * - */ - -#include - -#include -#include -#include - -#include -#include -#include - -#include - -static int decode_pdp_info(uint8_t *data, size_t data_len, - struct gprs_gsup_pdp_info *pdp_info) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - - /* specific parts */ - while (data_len > 0) { - enum gprs_gsup_iei iei; - - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case GPRS_GSUP_PDP_CONTEXT_ID_IE: - pdp_info->context_id = decode_big_endian(value, value_len); - break; - - case GPRS_GSUP_PDP_TYPE_IE: - pdp_info->pdp_type = - decode_big_endian(value, value_len) & 0x0fff; - break; - - case GPRS_GSUP_ACCESS_POINT_NAME_IE: - pdp_info->apn_enc = value; - pdp_info->apn_enc_len = value_len; - break; - - case GPRS_GSUP_PDP_QOS_IE: - pdp_info->qos_enc = value; - pdp_info->qos_enc_len = value_len; - break; - - default: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d not expected in PDP info\n", iei); - continue; - } - } - - return 0; -} - -static int decode_auth_info(uint8_t *data, size_t data_len, - struct osmo_auth_vector *auth_vector) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - enum gprs_gsup_iei iei; - - /* specific parts */ - while (data_len > 0) { - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case GPRS_GSUP_RAND_IE: - if (value_len != sizeof(auth_vector->rand)) - goto parse_error; - - memcpy(auth_vector->rand, value, value_len); - break; - - case GPRS_GSUP_SRES_IE: - if (value_len != sizeof(auth_vector->sres)) - goto parse_error; - - memcpy(auth_vector->sres, value, value_len); - break; - - case GPRS_GSUP_KC_IE: - if (value_len != sizeof(auth_vector->kc)) - goto parse_error; - - memcpy(auth_vector->kc, value, value_len); - break; - - default: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d not expected in PDP info\n", iei); - continue; - } - } - - return 0; - -parse_error: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len); - - return -1; -} - -int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, - struct gprs_gsup_message *gsup_msg) -{ - int rc; - uint8_t tag; - /* the shift/match functions expect non-const pointers, but we'll - * either copy the data or cast pointers back to const before returning - * them - */ - uint8_t *data = (uint8_t *)const_data; - uint8_t *value; - size_t value_len; - static const struct gprs_gsup_pdp_info empty_pdp_info = {0}; - static const struct osmo_auth_vector empty_auth_info = {0}; - static const struct gprs_gsup_message empty_gsup_message = {0}; - - *gsup_msg = empty_gsup_message; - - /* generic part */ - rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); - if (rc < 0) - return -GMM_CAUSE_INV_MAND_INFO; - - gsup_msg->message_type = decode_big_endian(value, 1); - - rc = gprs_match_tlv(&data, &data_len, GPRS_GSUP_IMSI_IE, - &value, &value_len); - - if (rc <= 0) - return -GMM_CAUSE_INV_MAND_INFO; - - if (value_len * 2 + 1 > sizeof(gsup_msg->imsi)) - return -GMM_CAUSE_INV_MAND_INFO; - - /* Note that gsm48_decode_bcd_number expects the number of encoded IMSI - * octets in the first octet. By coincidence (the TLV encoding) the byte - * before the value part already contains this length so we can use it - * here. - */ - OSMO_ASSERT(value[-1] == value_len); - gsm48_decode_bcd_number(gsup_msg->imsi, sizeof(gsup_msg->imsi), - value - 1, 0); - - /* specific parts */ - while (data_len > 0) { - enum gprs_gsup_iei iei; - struct gprs_gsup_pdp_info pdp_info; - struct osmo_auth_vector auth_info; - - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case GPRS_GSUP_IMSI_IE: - case GPRS_GSUP_PDP_TYPE_IE: - case GPRS_GSUP_ACCESS_POINT_NAME_IE: - case GPRS_GSUP_RAND_IE: - case GPRS_GSUP_SRES_IE: - case GPRS_GSUP_KC_IE: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d not expected (ignored)\n", iei); - continue; - - case GPRS_GSUP_CAUSE_IE: - gsup_msg->cause = decode_big_endian(value, value_len); - break; - - case GPRS_GSUP_CANCEL_TYPE_IE: - gsup_msg->cancel_type = - decode_big_endian(value, value_len) + 1; - break; - - case GPRS_GSUP_PDP_INFO_COMPL_IE: - gsup_msg->pdp_info_compl = 1; - break; - - case GPRS_GSUP_FREEZE_PTMSI_IE: - gsup_msg->freeze_ptmsi = 1; - break; - - case GPRS_GSUP_PDP_CONTEXT_ID_IE: - /* When these IE appear in the top-level part of the - * message, they are used by Delete Subscr Info to delete - * single entries. We don't have an extra list for - * these but use the PDP info list instead */ - - /* fall through */ - - case GPRS_GSUP_PDP_INFO_IE: - if (gsup_msg->num_pdp_infos >= GPRS_GSUP_MAX_NUM_PDP_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (PDP_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_COND_IE_ERR; - } - - pdp_info = empty_pdp_info; - - if (iei == GPRS_GSUP_PDP_INFO_IE) { - rc = decode_pdp_info(value, value_len, &pdp_info); - if (rc < 0) - return rc; - pdp_info.have_info = 1; - } else { - pdp_info.context_id = - decode_big_endian(value, value_len); - } - - gsup_msg->pdp_infos[gsup_msg->num_pdp_infos++] = - pdp_info; - break; - - case GPRS_GSUP_AUTH_TUPLE_IE: - if (gsup_msg->num_auth_vectors >= GPRS_GSUP_MAX_NUM_AUTH_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (AUTH_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_INV_MAND_INFO; - } - - auth_info = empty_auth_info; - - rc = decode_auth_info(value, value_len, &auth_info); - if (rc < 0) - return rc; - - gsup_msg->auth_vectors[gsup_msg->num_auth_vectors++] = - auth_info; - break; - - case GPRS_GSUP_MSISDN_IE: - gsup_msg->msisdn_enc = value; - gsup_msg->msisdn_enc_len = value_len; - break; - - case GPRS_GSUP_HLR_NUMBER_IE: - gsup_msg->hlr_enc = value; - gsup_msg->hlr_enc_len = value_len; - break; - - default: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d unknown\n", iei); - continue; - } - } - - return 0; -} - -static void encode_pdp_info(struct msgb *msg, enum gprs_gsup_iei iei, - const struct gprs_gsup_pdp_info *pdp_info) -{ - uint8_t *len_field; - size_t old_len; - uint8_t u8; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - u8 = pdp_info->context_id; - msgb_tlv_put(msg, GPRS_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8); - - if (pdp_info->pdp_type) { - msgb_tlv_put(msg, GPRS_GSUP_PDP_TYPE_IE, - GPRS_GSUP_PDP_TYPE_SIZE, - encode_big_endian(pdp_info->pdp_type | 0xf000, - GPRS_GSUP_PDP_TYPE_SIZE)); - } - - if (pdp_info->apn_enc) { - msgb_tlv_put(msg, GPRS_GSUP_ACCESS_POINT_NAME_IE, - pdp_info->apn_enc_len, pdp_info->apn_enc); - } - - if (pdp_info->qos_enc) { - msgb_tlv_put(msg, GPRS_GSUP_PDP_QOS_IE, - pdp_info->qos_enc_len, pdp_info->qos_enc); - } - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -static void encode_auth_info(struct msgb *msg, enum gprs_gsup_iei iei, - const struct osmo_auth_vector *auth_vector) -{ - uint8_t *len_field; - size_t old_len; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - msgb_tlv_put(msg, GPRS_GSUP_RAND_IE, - sizeof(auth_vector->rand), auth_vector->rand); - - msgb_tlv_put(msg, GPRS_GSUP_SRES_IE, - sizeof(auth_vector->sres), auth_vector->sres); - - msgb_tlv_put(msg, GPRS_GSUP_KC_IE, - sizeof(auth_vector->kc), auth_vector->kc); - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg) -{ - uint8_t u8; - int idx; - uint8_t bcd_buf[GSM48_MI_SIZE] = {0}; - size_t bcd_len; - - /* generic part */ - OSMO_ASSERT(gsup_msg->message_type); - msgb_v_put(msg, gsup_msg->message_type); - - bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, - gsup_msg->imsi); - - OSMO_ASSERT(bcd_len > 1); - - /* Note that gsm48_encode_bcd_number puts the length into the first - * octet. Since msgb_tlv_put will add this length byte, we'll have to - * skip it */ - msgb_tlv_put(msg, GPRS_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); - - /* specific parts */ - if (gsup_msg->msisdn_enc) - msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE, - gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); - if (gsup_msg->hlr_enc) - msgb_tlv_put(msg, GPRS_GSUP_HLR_NUMBER_IE, - gsup_msg->hlr_enc_len, gsup_msg->hlr_enc); - - if ((u8 = gsup_msg->cause)) - msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8); - - if ((u8 = gsup_msg->cancel_type)) { - u8 -= 1; - msgb_tlv_put(msg, GPRS_GSUP_CANCEL_TYPE_IE, sizeof(u8), &u8); - } - - if (gsup_msg->pdp_info_compl) - msgb_tlv_put(msg, GPRS_GSUP_PDP_INFO_COMPL_IE, 0, &u8); - - if (gsup_msg->freeze_ptmsi) - msgb_tlv_put(msg, GPRS_GSUP_FREEZE_PTMSI_IE, 0, &u8); - - for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) { - const struct gprs_gsup_pdp_info *pdp_info; - - pdp_info = &gsup_msg->pdp_infos[idx]; - - if (pdp_info->context_id == 0) - continue; - - if (pdp_info->have_info) { - encode_pdp_info(msg, GPRS_GSUP_PDP_INFO_IE, pdp_info); - } else { - u8 = pdp_info->context_id; - msgb_tlv_put(msg, GPRS_GSUP_PDP_CONTEXT_ID_IE, - sizeof(u8), &u8); - } - } - - for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { - const struct osmo_auth_vector *auth_vector; - - auth_vector = &gsup_msg->auth_vectors[idx]; - - encode_auth_info(msg, GPRS_GSUP_AUTH_TUPLE_IE, auth_vector); - } -} diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 648f91204..d9bc10a18 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -159,14 +159,14 @@ void gprs_subscr_cancel(struct gsm_subscriber *subscr) } static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { struct msgb *msg = gprs_gsup_msgb_alloc(); if (strlen(gsup_msg->imsi) == 0 && subscr) strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1); - gprs_gsup_encode(msg, gsup_msg); + osmo_gsup_encode(msg, gsup_msg); LOGGSUBSCRP(LOGL_INFO, subscr, "Sending GSUP, will send: %s\n", msgb_hexdump(msg)); @@ -180,21 +180,21 @@ static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr, } static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_orig, + struct osmo_gsup_message *gsup_orig, enum gsm48_gmm_cause cause) { - struct gprs_gsup_message gsup_reply = {0}; + struct osmo_gsup_message gsup_reply = {0}; strncpy(gsup_reply.imsi, gsup_orig->imsi, sizeof(gsup_reply.imsi) - 1); gsup_reply.cause = cause; gsup_reply.message_type = - GPRS_GSUP_TO_MSGT_ERROR(gsup_orig->message_type); + OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type); return gprs_subscr_tx_gsup_message(subscr, &gsup_reply); } static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { unsigned idx; struct sgsn_subscriber_data *sdata = subscr->sgsn_data; @@ -261,7 +261,7 @@ static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id( static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { struct sgsn_subscriber_data *sdata = subscr->sgsn_data; unsigned idx; @@ -298,7 +298,7 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, } for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) { - struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx]; + struct osmo_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx]; size_t ctx_id = pdp_info->context_id; struct sgsn_subscriber_pdp_data *pdp_data; @@ -338,7 +338,7 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, } static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { gprs_subscr_gsup_insert_data(subscr, gsup_msg); @@ -368,7 +368,7 @@ static int check_cause(int cause) } static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { unsigned idx; struct sgsn_subscriber_data *sdata = subscr->sgsn_data; @@ -421,7 +421,7 @@ static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr, } static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { int cause_err; @@ -467,9 +467,9 @@ static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr, } static int gprs_subscr_handle_gsup_purge_no_subscr( - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { - if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) { + if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) { LOGGSUPP(LOGL_NOTICE, gsup_msg, "Purge MS has failed with cause '%s' (%d)\n", get_value_string(gsm48_gmm_cause_names, gsup_msg->cause), @@ -482,7 +482,7 @@ static int gprs_subscr_handle_gsup_purge_no_subscr( } static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n"); @@ -494,7 +494,7 @@ static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr, } static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { LOGGSUBSCRP(LOGL_NOTICE, subscr, "Purge MS has failed with cause '%s' (%d)\n", @@ -527,17 +527,17 @@ static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr, } static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr, - struct gprs_gsup_message *gsup_msg) + struct osmo_gsup_message *gsup_msg) { - struct gprs_gsup_message gsup_reply = {0}; + struct osmo_gsup_message gsup_reply = {0}; int is_update_procedure = !gsup_msg->cancel_type || - gsup_msg->cancel_type == GPRS_GSUP_CANCEL_TYPE_UPDATE; + gsup_msg->cancel_type == OSMO_GSUP_CANCEL_TYPE_UPDATE; LOGGSUBSCRP(LOGL_INFO, subscr, "Cancelling MS subscriber (%s)\n", is_update_procedure ? "update procedure" : "subscription withdraw"); - gsup_reply.message_type = GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT; + gsup_reply.message_type = OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT; gprs_subscr_tx_gsup_message(subscr, &gsup_reply); if (is_update_procedure) @@ -554,16 +554,16 @@ static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr, return 0; } -static int gprs_subscr_handle_unknown_imsi(struct gprs_gsup_message *gsup_msg) +static int gprs_subscr_handle_unknown_imsi(struct osmo_gsup_message *gsup_msg) { - if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) { + if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) { gprs_subscr_tx_gsup_error_reply(NULL, gsup_msg, GMM_CAUSE_IMSI_UNKNOWN); LOGP(DGPRS, LOGL_NOTICE, "Unknown IMSI %s, discarding GSUP request " "of type 0x%02x\n", gsup_msg->imsi, gsup_msg->message_type); - } else if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) { + } else if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) { LOGP(DGPRS, LOGL_NOTICE, "Unknown IMSI %s, discarding GSUP error " "of type 0x%02x, cause '%s' (%d)\n", @@ -586,10 +586,10 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) size_t data_len = msgb_l2len(msg); int rc = 0; - struct gprs_gsup_message gsup_msg = {0}; + struct osmo_gsup_message gsup_msg = {0}; struct gsm_subscriber *subscr; - rc = gprs_gsup_decode(data, data_len, &gsup_msg); + rc = osmo_gsup_decode(data, data_len, &gsup_msg); if (rc < 0) { LOGP(DGPRS, LOGL_ERROR, "decoding GSUP message fails with error '%s' (%d)\n", @@ -600,21 +600,21 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) if (!gsup_msg.imsi[0]) { LOGP(DGPRS, LOGL_ERROR, "Missing IMSI in GSUP message\n"); - if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type)) + if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type)) gprs_subscr_tx_gsup_error_reply(NULL, &gsup_msg, GMM_CAUSE_INV_MAND_INFO); return -GMM_CAUSE_INV_MAND_INFO; } - if (!gsup_msg.cause && GPRS_GSUP_IS_MSGT_ERROR(gsup_msg.message_type)) + if (!gsup_msg.cause && OSMO_GSUP_IS_MSGT_ERROR(gsup_msg.message_type)) gsup_msg.cause = GMM_CAUSE_NET_FAIL; subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi); if (!subscr) { switch (gsup_msg.message_type) { - case GPRS_GSUP_MSGT_PURGE_MS_RESULT: - case GPRS_GSUP_MSGT_PURGE_MS_ERROR: + case OSMO_GSUP_MSGT_PURGE_MS_RESULT: + case OSMO_GSUP_MSGT_PURGE_MS_ERROR: return gprs_subscr_handle_gsup_purge_no_subscr(&gsup_msg); default: return gprs_subscr_handle_unknown_imsi(&gsup_msg); @@ -625,36 +625,36 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) "Received GSUP message of type 0x%02x\n", gsup_msg.message_type); switch (gsup_msg.message_type) { - case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST: + case OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST: rc = gprs_subscr_handle_loc_cancel_req(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT: + case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR: + case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT: + case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR: + case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR: rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_PURGE_MS_ERROR: + case OSMO_GSUP_MSGT_PURGE_MS_ERROR: rc = gprs_subscr_handle_gsup_purge_err(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_PURGE_MS_RESULT: + case OSMO_GSUP_MSGT_PURGE_MS_RESULT: rc = gprs_subscr_handle_gsup_purge_res(subscr, &gsup_msg); break; - case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST: - case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST: + case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: + case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST: LOGGSUBSCRP(LOGL_ERROR, subscr, "Rx GSUP message type %d not yet implemented\n", gsup_msg.message_type); @@ -667,7 +667,7 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) LOGGSUBSCRP(LOGL_ERROR, subscr, "Rx GSUP message type %d not valid at SGSN\n", gsup_msg.message_type); - if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type)) + if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type)) gprs_subscr_tx_gsup_error_reply( subscr, &gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL); rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; @@ -682,11 +682,11 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) int gprs_subscr_purge(struct gsm_subscriber *subscr) { struct sgsn_subscriber_data *sdata = subscr->sgsn_data; - struct gprs_gsup_message gsup_msg = {0}; + struct osmo_gsup_message gsup_msg = {0}; LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n"); - gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST; + gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_REQUEST; /* Provide the HLR number in case it is known */ gsup_msg.hlr_enc_len = sdata->hlr_len; @@ -697,23 +697,23 @@ int gprs_subscr_purge(struct gsm_subscriber *subscr) int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr) { - struct gprs_gsup_message gsup_msg = {0}; + struct osmo_gsup_message gsup_msg = {0}; LOGGSUBSCRP(LOGL_INFO, subscr, "subscriber auth info is not available\n"); - gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST; + gsup_msg.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST; return gprs_subscr_tx_gsup_message(subscr, &gsup_msg); } int gprs_subscr_location_update(struct gsm_subscriber *subscr) { - struct gprs_gsup_message gsup_msg = {0}; + struct osmo_gsup_message gsup_msg = {0}; LOGGSUBSCRP(LOGL_INFO, subscr, "subscriber data is not available\n"); - gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST; + gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST; return gprs_subscr_tx_gsup_message(subscr, &gsup_msg); } diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c new file mode 100644 index 000000000..00ada5b24 --- /dev/null +++ b/openbsc/src/gprs/osmo_gsup_messages.c @@ -0,0 +1,417 @@ +/* Osmocom Subscriber Update Protocol message encoder/decoder */ + +/* + * (C) 2014 by Sysmocom s.f.m.c. GmbH + * (C) 2015 by Holger Hans Peter Freyther + * (C) 2016 by Harald Welte + * All Rights Reserved + * + * Author: Jacob Erlbeck + * + * 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 . + * + */ + +#include + +#include +//#include +#include + +#include +#include +#include + +#include + +static int decode_pdp_info(uint8_t *data, size_t data_len, + struct osmo_gsup_pdp_info *pdp_info) +{ + int rc; + uint8_t tag; + uint8_t *value; + size_t value_len; + + /* specific parts */ + while (data_len > 0) { + enum osmo_gsup_iei iei; + + rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + if (rc < 0) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + iei = tag; + + switch (iei) { + case OSMO_GSUP_PDP_CONTEXT_ID_IE: + pdp_info->context_id = decode_big_endian(value, value_len); + break; + + case OSMO_GSUP_PDP_TYPE_IE: + pdp_info->pdp_type = + decode_big_endian(value, value_len) & 0x0fff; + break; + + case OSMO_GSUP_ACCESS_POINT_NAME_IE: + pdp_info->apn_enc = value; + pdp_info->apn_enc_len = value_len; + break; + + case OSMO_GSUP_PDP_QOS_IE: + pdp_info->qos_enc = value; + pdp_info->qos_enc_len = value_len; + break; + + default: + LOGP(DGPRS, LOGL_ERROR, + "GSUP IE type %d not expected in PDP info\n", iei); + continue; + } + } + + return 0; +} + +static int decode_auth_info(uint8_t *data, size_t data_len, + struct osmo_auth_vector *auth_vector) +{ + int rc; + uint8_t tag; + uint8_t *value; + size_t value_len; + enum osmo_gsup_iei iei; + + /* specific parts */ + while (data_len > 0) { + rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + if (rc < 0) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + iei = tag; + + switch (iei) { + case OSMO_GSUP_RAND_IE: + if (value_len != sizeof(auth_vector->rand)) + goto parse_error; + + memcpy(auth_vector->rand, value, value_len); + break; + + case OSMO_GSUP_SRES_IE: + if (value_len != sizeof(auth_vector->sres)) + goto parse_error; + + memcpy(auth_vector->sres, value, value_len); + break; + + case OSMO_GSUP_KC_IE: + if (value_len != sizeof(auth_vector->kc)) + goto parse_error; + + memcpy(auth_vector->kc, value, value_len); + break; + + default: + LOGP(DGPRS, LOGL_ERROR, + "GSUP IE type %d not expected in PDP info\n", iei); + continue; + } + } + + return 0; + +parse_error: + LOGP(DGPRS, LOGL_ERROR, + "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len); + + return -1; +} + +int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, + struct osmo_gsup_message *gsup_msg) +{ + int rc; + uint8_t tag; + /* the shift/match functions expect non-const pointers, but we'll + * either copy the data or cast pointers back to const before returning + * them + */ + uint8_t *data = (uint8_t *)const_data; + uint8_t *value; + size_t value_len; + static const struct osmo_gsup_pdp_info empty_pdp_info = {0}; + static const struct osmo_auth_vector empty_auth_info = {0}; + static const struct osmo_gsup_message empty_gsup_message = {0}; + + *gsup_msg = empty_gsup_message; + + /* generic part */ + rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); + if (rc < 0) + return -GMM_CAUSE_INV_MAND_INFO; + + gsup_msg->message_type = decode_big_endian(value, 1); + + rc = gprs_match_tlv(&data, &data_len, OSMO_GSUP_IMSI_IE, + &value, &value_len); + + if (rc <= 0) + return -GMM_CAUSE_INV_MAND_INFO; + + if (value_len * 2 + 1 > sizeof(gsup_msg->imsi)) + return -GMM_CAUSE_INV_MAND_INFO; + + /* Note that gsm48_decode_bcd_number expects the number of encoded IMSI + * octets in the first octet. By coincidence (the TLV encoding) the byte + * before the value part already contains this length so we can use it + * here. + */ + OSMO_ASSERT(value[-1] == value_len); + gsm48_decode_bcd_number(gsup_msg->imsi, sizeof(gsup_msg->imsi), + value - 1, 0); + + /* specific parts */ + while (data_len > 0) { + enum osmo_gsup_iei iei; + struct osmo_gsup_pdp_info pdp_info; + struct osmo_auth_vector auth_info; + + rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + if (rc < 0) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + iei = tag; + + switch (iei) { + case OSMO_GSUP_IMSI_IE: + case OSMO_GSUP_PDP_TYPE_IE: + case OSMO_GSUP_ACCESS_POINT_NAME_IE: + case OSMO_GSUP_RAND_IE: + case OSMO_GSUP_SRES_IE: + case OSMO_GSUP_KC_IE: + LOGP(DGPRS, LOGL_NOTICE, + "GSUP IE type %d not expected (ignored)\n", iei); + continue; + + case OSMO_GSUP_CAUSE_IE: + gsup_msg->cause = decode_big_endian(value, value_len); + break; + + case OSMO_GSUP_CANCEL_TYPE_IE: + gsup_msg->cancel_type = + decode_big_endian(value, value_len) + 1; + break; + + case OSMO_GSUP_PDP_INFO_COMPL_IE: + gsup_msg->pdp_info_compl = 1; + break; + + case OSMO_GSUP_FREEZE_PTMSI_IE: + gsup_msg->freeze_ptmsi = 1; + break; + + case OSMO_GSUP_PDP_CONTEXT_ID_IE: + /* When these IE appear in the top-level part of the + * message, they are used by Delete Subscr Info to delete + * single entries. We don't have an extra list for + * these but use the PDP info list instead */ + + /* fall through */ + + case OSMO_GSUP_PDP_INFO_IE: + if (gsup_msg->num_pdp_infos >= OSMO_GSUP_MAX_NUM_PDP_INFO) { + LOGP(DGPRS, LOGL_ERROR, + "GSUP IE type %d (PDP_INFO) max exceeded\n", + iei); + return -GMM_CAUSE_COND_IE_ERR; + } + + pdp_info = empty_pdp_info; + + if (iei == OSMO_GSUP_PDP_INFO_IE) { + rc = decode_pdp_info(value, value_len, &pdp_info); + if (rc < 0) + return rc; + pdp_info.have_info = 1; + } else { + pdp_info.context_id = + decode_big_endian(value, value_len); + } + + gsup_msg->pdp_infos[gsup_msg->num_pdp_infos++] = + pdp_info; + break; + + case OSMO_GSUP_AUTH_TUPLE_IE: + if (gsup_msg->num_auth_vectors >= OSMO_GSUP_MAX_NUM_AUTH_INFO) { + LOGP(DGPRS, LOGL_ERROR, + "GSUP IE type %d (AUTH_INFO) max exceeded\n", + iei); + return -GMM_CAUSE_INV_MAND_INFO; + } + + auth_info = empty_auth_info; + + rc = decode_auth_info(value, value_len, &auth_info); + if (rc < 0) + return rc; + + gsup_msg->auth_vectors[gsup_msg->num_auth_vectors++] = + auth_info; + break; + + case OSMO_GSUP_MSISDN_IE: + gsup_msg->msisdn_enc = value; + gsup_msg->msisdn_enc_len = value_len; + break; + + case OSMO_GSUP_HLR_NUMBER_IE: + gsup_msg->hlr_enc = value; + gsup_msg->hlr_enc_len = value_len; + break; + + default: + LOGP(DGPRS, LOGL_NOTICE, + "GSUP IE type %d unknown\n", iei); + continue; + } + } + + return 0; +} + +static void encode_pdp_info(struct msgb *msg, enum osmo_gsup_iei iei, + const struct osmo_gsup_pdp_info *pdp_info) +{ + uint8_t *len_field; + size_t old_len; + uint8_t u8; + + len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; + old_len = msgb_length(msg); + + u8 = pdp_info->context_id; + msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8); + + if (pdp_info->pdp_type) { + msgb_tlv_put(msg, OSMO_GSUP_PDP_TYPE_IE, + OSMO_GSUP_PDP_TYPE_SIZE, + encode_big_endian(pdp_info->pdp_type | 0xf000, + OSMO_GSUP_PDP_TYPE_SIZE)); + } + + if (pdp_info->apn_enc) { + msgb_tlv_put(msg, OSMO_GSUP_ACCESS_POINT_NAME_IE, + pdp_info->apn_enc_len, pdp_info->apn_enc); + } + + if (pdp_info->qos_enc) { + msgb_tlv_put(msg, OSMO_GSUP_PDP_QOS_IE, + pdp_info->qos_enc_len, pdp_info->qos_enc); + } + + /* Update length field */ + *len_field = msgb_length(msg) - old_len; +} + +static void encode_auth_info(struct msgb *msg, enum osmo_gsup_iei iei, + const struct osmo_auth_vector *auth_vector) +{ + uint8_t *len_field; + size_t old_len; + + len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; + old_len = msgb_length(msg); + + msgb_tlv_put(msg, OSMO_GSUP_RAND_IE, + sizeof(auth_vector->rand), auth_vector->rand); + + msgb_tlv_put(msg, OSMO_GSUP_SRES_IE, + sizeof(auth_vector->sres), auth_vector->sres); + + msgb_tlv_put(msg, OSMO_GSUP_KC_IE, + sizeof(auth_vector->kc), auth_vector->kc); + + /* Update length field */ + *len_field = msgb_length(msg) - old_len; +} + +void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) +{ + uint8_t u8; + int idx; + uint8_t bcd_buf[GSM48_MI_SIZE] = {0}; + size_t bcd_len; + + /* generic part */ + OSMO_ASSERT(gsup_msg->message_type); + msgb_v_put(msg, gsup_msg->message_type); + + bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, + gsup_msg->imsi); + + OSMO_ASSERT(bcd_len > 1); + + /* Note that gsm48_encode_bcd_number puts the length into the first + * octet. Since msgb_tlv_put will add this length byte, we'll have to + * skip it */ + msgb_tlv_put(msg, OSMO_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); + + /* specific parts */ + if (gsup_msg->msisdn_enc) + msgb_tlv_put(msg, OSMO_GSUP_MSISDN_IE, + gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); + if (gsup_msg->hlr_enc) + msgb_tlv_put(msg, OSMO_GSUP_HLR_NUMBER_IE, + gsup_msg->hlr_enc_len, gsup_msg->hlr_enc); + + if ((u8 = gsup_msg->cause)) + msgb_tlv_put(msg, OSMO_GSUP_CAUSE_IE, sizeof(u8), &u8); + + if ((u8 = gsup_msg->cancel_type)) { + u8 -= 1; + msgb_tlv_put(msg, OSMO_GSUP_CANCEL_TYPE_IE, sizeof(u8), &u8); + } + + if (gsup_msg->pdp_info_compl) + msgb_tlv_put(msg, OSMO_GSUP_PDP_INFO_COMPL_IE, 0, &u8); + + if (gsup_msg->freeze_ptmsi) + msgb_tlv_put(msg, OSMO_GSUP_FREEZE_PTMSI_IE, 0, &u8); + + for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) { + const struct osmo_gsup_pdp_info *pdp_info; + + pdp_info = &gsup_msg->pdp_infos[idx]; + + if (pdp_info->context_id == 0) + continue; + + if (pdp_info->have_info) { + encode_pdp_info(msg, OSMO_GSUP_PDP_INFO_IE, pdp_info); + } else { + u8 = pdp_info->context_id; + msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, + sizeof(u8), &u8); + } + } + + for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { + const struct osmo_auth_vector *auth_vector; + + auth_vector = &gsup_msg->auth_vectors[idx]; + + encode_auth_info(msg, OSMO_GSUP_AUTH_TUPLE_IE, auth_vector); + } +} -- cgit v1.2.3 From 842674b8b3d245a2eecb352eb89609ed44cb0832 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 15:14:01 +0200 Subject: rename gprs_shift_*() to osmo_shift_*() This rename is the first step of moving the associated functions into libosmocore. Also, rename gprs_match_* to osmo_match_shift_* to indicate that it is not just matching the TLV, but also shifting the data portion. --- openbsc/src/gprs/gprs_gb_parse.c | 56 ++++++++++++++++---------------- openbsc/src/gprs/gprs_utils.c | 61 ++++++++++++++++++++++++++++------- openbsc/src/gprs/oap_messages.c | 4 +-- openbsc/src/gprs/osmo_gsup_messages.c | 12 +++---- 4 files changed, 86 insertions(+), 47 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gprs_gb_parse.c b/openbsc/src/gprs/gprs_gb_parse.c index 5ec3cf6ea..f11d93aef 100644 --- a/openbsc/src/gprs/gprs_gb_parse.c +++ b/openbsc/src/gprs/gprs_gb_parse.c @@ -38,7 +38,7 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len, parse_ctx->llc_msg_name = "ATTACH_REQ"; /* Skip MS network capability */ - if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || value_len < 1 || value_len > 8) /* invalid */ return 0; @@ -46,10 +46,10 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len, /* Skip Attach type */ /* Skip Ciphering key sequence number */ /* Skip DRX parameter */ - gprs_shift_v_fixed(&data, &data_len, 3, NULL); + osmo_shift_v_fixed(&data, &data_len, 3, NULL); /* Get Mobile identity */ - if (gprs_shift_lv(&data, &data_len, &value, &value_len) <= 0 || + if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 || value_len < 5 || value_len > 8) /* invalid */ return 0; @@ -61,7 +61,7 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len, parse_ctx->imsi_len = value_len; } - if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) return 0; parse_ctx->old_raid_enc = value; @@ -82,21 +82,21 @@ static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len, /* Skip Periodic RA update timer */ /* Skip Radio priority for SMS */ /* Skip Spare half octet */ - gprs_shift_v_fixed(&data, &data_len, 3, NULL); + osmo_shift_v_fixed(&data, &data_len, 3, NULL); - if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) return 0; parse_ctx->raid_enc = value; /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */ - gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */ - gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL); + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL); /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */ - if (gprs_match_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, + if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0 && gprs_is_mi_tmsi(value, value_len)) parse_ctx->new_ptmsi_enc = value + 1; @@ -111,7 +111,7 @@ static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len, parse_ctx->llc_msg_name = "ATTACH_REJ"; /* GMM cause */ - if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) return 0; parse_ctx->invalidate_tlli = 1; @@ -132,7 +132,7 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len, /* Skip spare half octet */ /* Get Detach type */ - if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) /* invalid */ return 0; @@ -150,7 +150,7 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len, parse_ctx->invalidate_tlli = 1; /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */ - if (gprs_match_tlv(&data, &data_len, + if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0) { if (gprs_is_mi_tmsi(value, value_len)) @@ -170,9 +170,9 @@ static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len, /* Skip Update type */ /* Skip GPRS ciphering key sequence number */ - gprs_shift_v_fixed(&data, &data_len, 1, NULL); + osmo_shift_v_fixed(&data, &data_len, 1, NULL); - if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) return 0; parse_ctx->old_raid_enc = value; @@ -190,14 +190,14 @@ static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len, parse_ctx->llc_msg_name = "RA_UPD_REJ"; /* GMM cause */ - if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) return 0; cause = value[0]; /* Force to standby, 1/2 */ /* spare bits, 1/2 */ - if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) return 0; force_standby = (value[0] & 0x07) == 0x01; @@ -221,18 +221,18 @@ static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len, /* Skip Force to standby */ /* Skip Update result */ /* Skip Periodic RA update timer */ - gprs_shift_v_fixed(&data, &data_len, 2, NULL); + osmo_shift_v_fixed(&data, &data_len, 2, NULL); - if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) return 0; parse_ctx->raid_enc = value; /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */ - gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */ - if (gprs_match_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, + if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0 && gprs_is_mi_tmsi(value, value_len)) parse_ctx->new_ptmsi_enc = value + 1; @@ -252,11 +252,11 @@ static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len, "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n"); /* Allocated P-TMSI */ - if (gprs_shift_lv(&data, &data_len, &value, &value_len) > 0 && + if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 && gprs_is_mi_tmsi(value, value_len)) parse_ctx->new_ptmsi_enc = value + 1; - if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) return 0; parse_ctx->raid_enc = value; @@ -273,7 +273,7 @@ static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len, parse_ctx->llc_msg_name = "ID_RESP"; /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */ - if (gprs_shift_lv(&data, &data_len, &value, &value_len) <= 0 || + if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 || value_len < 1 || value_len > 9) /* invalid */ return 0; @@ -299,22 +299,22 @@ static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len, /* Skip Requested NSAPI */ /* Skip Requested LLC SAPI */ - gprs_shift_v_fixed(&data, &data_len, 2, NULL); + osmo_shift_v_fixed(&data, &data_len, 2, NULL); /* Skip Requested QoS (support 04.08 and 24.008) */ - if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || value_len < 4 || value_len > 14) /* invalid */ return 0; /* Skip Requested PDP address */ - if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || value_len < 2 || value_len > 18) /* invalid */ return 0; /* Access point name */ - old_len = gprs_match_tlv(&data, &data_len, + old_len = osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GSM_APN, &value, &value_len); if (old_len > 0 && value_len >=1 && value_len <= 100) { @@ -332,7 +332,7 @@ int gprs_gb_parse_dtap(uint8_t *data, size_t data_len, uint8_t pdisc; uint8_t msg_type; - if (gprs_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0) + if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0) return 0; parse_ctx->g48_hdr = g48h; diff --git a/openbsc/src/gprs/gprs_utils.c b/openbsc/src/gprs/gprs_utils.c index 64bfd743d..7ed8c3f19 100644 --- a/openbsc/src/gprs/gprs_utils.c +++ b/openbsc/src/gprs/gprs_utils.c @@ -268,8 +268,15 @@ void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi) /* TODO: Move shift functions to libosmocore */ -int gprs_shift_v_fixed(uint8_t **data, size_t *data_len, - size_t len, uint8_t **value) +/*! Advance the data pointer, subtract length and assign value pointer + * \param data pointer to the pointer to data + * \param data_len pointer to size_t containing \arg data length + * \param[in] len the length that we expect the fixed IE to hav + * \param[out] value pointer to pointer of value part of IE + * \returns length of IE value; negative in case of error + */ +int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, + size_t len, uint8_t **value) { if (len > *data_len) goto fail; @@ -288,9 +295,17 @@ fail: return -1; } -int gprs_match_tv_fixed(uint8_t **data, size_t *data_len, - uint8_t tag, size_t len, - uint8_t **value) +/*! Match tag, check length and assign value pointer + * \param data pointer to the pointer to data + * \param data_len pointer to size_t containing \arg data length + * \param[in] tag the tag (IEI) that we expect at \arg data + * \param[in] len the length that we expect the fixed IE to have + * \param[out] value pointer to pointer of value part of IE + * \returns length of IE value; negative in case of error + */ +int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, + uint8_t tag, size_t len, + uint8_t **value) { size_t ie_len; @@ -318,15 +333,24 @@ fail: return -1; } -int gprs_match_tlv(uint8_t **data, size_t *data_len, - uint8_t expected_tag, uint8_t **value, size_t *value_len) +/*! Verify TLV header and advance data / subtract length + * \param data pointer to the pointer to data + * \param data_len pointer to size_t containing \arg data length + * \param[in] expected_tag the tag (IEI) that we expect at \arg data + * \param[out] value pointer to pointer of value part of IE + * \param[out] value_len pointer to length of \arg value + * \returns length of IE value; negative in case of error + */ +int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, + uint8_t expected_tag, uint8_t **value, + size_t *value_len) { int rc; uint8_t tag; uint8_t *old_data = *data; size_t old_data_len = *data_len; - rc = gprs_shift_tlv(data, data_len, &tag, value, value_len); + rc = osmo_shift_tlv(data, data_len, &tag, value, value_len); if (rc > 0 && tag != expected_tag) { *data = old_data; @@ -337,7 +361,15 @@ int gprs_match_tlv(uint8_t **data, size_t *data_len, return rc; } -int gprs_shift_tlv(uint8_t **data, size_t *data_len, +/*! Extract TLV and advance data pointer + subtract length + * \param data pointer to the pointer to data + * \param data_len pointer to size_t containing \arg data lengt + * \param[out] tag extract the tag (IEI) at start of \arg data + * \param[out] value extracted pointer to value part of TLV + * \param[out] value_len extracted length of \arg value + * \returns number of bytes subtracted + */ +int osmo_shift_tlv(uint8_t **data, size_t *data_len, uint8_t *tag, uint8_t **value, size_t *value_len) { size_t len; @@ -370,8 +402,15 @@ fail: return -1; } -int gprs_shift_lv(uint8_t **data, size_t *data_len, - uint8_t **value, size_t *value_len) +/*! Extract LV and advance data pointer + subtract length + * \param data pointer to the pointer to data + * \param data_len pointer to size_t containing \arg data lengt + * \param[out] value extracted pointer to value part of TLV + * \param[out] value_len extracted length of \arg value + * \returns number of bytes subtracted + */ +int osmo_shift_lv(uint8_t **data, size_t *data_len, + uint8_t **value, size_t *value_len) { size_t len; size_t ie_len; diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c index eb520532a..49b54e439 100644 --- a/openbsc/src/gprs/oap_messages.c +++ b/openbsc/src/gprs/oap_messages.c @@ -48,7 +48,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len, memset(oap_msg, 0, sizeof(*oap_msg)); /* message type */ - rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); + rc = osmo_shift_v_fixed(&data, &data_len, 1, &value); if (rc < 0) return -GMM_CAUSE_INV_MAND_INFO; oap_msg->message_type = decode_big_endian(value, 1); @@ -57,7 +57,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len, while (data_len > 0) { enum oap_iei iei; - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); if (rc < 0) return -GMM_CAUSE_PROTO_ERR_UNSPEC; diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c index 00ada5b24..94eae35b9 100644 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ b/openbsc/src/gprs/osmo_gsup_messages.c @@ -26,7 +26,7 @@ #include #include -//#include +#include #include #include @@ -47,7 +47,7 @@ static int decode_pdp_info(uint8_t *data, size_t data_len, while (data_len > 0) { enum osmo_gsup_iei iei; - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); if (rc < 0) return -GMM_CAUSE_PROTO_ERR_UNSPEC; @@ -94,7 +94,7 @@ static int decode_auth_info(uint8_t *data, size_t data_len, /* specific parts */ while (data_len > 0) { - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); if (rc < 0) return -GMM_CAUSE_PROTO_ERR_UNSPEC; @@ -157,13 +157,13 @@ int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, *gsup_msg = empty_gsup_message; /* generic part */ - rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); + rc = osmo_shift_v_fixed(&data, &data_len, 1, &value); if (rc < 0) return -GMM_CAUSE_INV_MAND_INFO; gsup_msg->message_type = decode_big_endian(value, 1); - rc = gprs_match_tlv(&data, &data_len, OSMO_GSUP_IMSI_IE, + rc = osmo_match_shift_tlv(&data, &data_len, OSMO_GSUP_IMSI_IE, &value, &value_len); if (rc <= 0) @@ -187,7 +187,7 @@ int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, struct osmo_gsup_pdp_info pdp_info; struct osmo_auth_vector auth_info; - rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); if (rc < 0) return -GMM_CAUSE_PROTO_ERR_UNSPEC; -- cgit v1.2.3 From 85234a32db7ab91f9361d4a54bea9523e2c7a5b9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 15:20:51 +0200 Subject: move osmo_shift_* / osmo_match_shift_* to libosmogsm --- openbsc/src/gprs/gprs_utils.c | 173 ---------------------------------- openbsc/src/gprs/osmo_gsup_messages.c | 1 - 2 files changed, 174 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gprs_utils.c b/openbsc/src/gprs/gprs_utils.c index 7ed8c3f19..64ed9788d 100644 --- a/openbsc/src/gprs/gprs_utils.c +++ b/openbsc/src/gprs/gprs_utils.c @@ -266,179 +266,6 @@ void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi) *tmsi = ntohl(tmsi_be); } -/* TODO: Move shift functions to libosmocore */ - -/*! Advance the data pointer, subtract length and assign value pointer - * \param data pointer to the pointer to data - * \param data_len pointer to size_t containing \arg data length - * \param[in] len the length that we expect the fixed IE to hav - * \param[out] value pointer to pointer of value part of IE - * \returns length of IE value; negative in case of error - */ -int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, - size_t len, uint8_t **value) -{ - if (len > *data_len) - goto fail; - - if (value) - *value = *data; - - *data += len; - *data_len -= len; - - return len; - -fail: - *data += *data_len; - *data_len = 0; - return -1; -} - -/*! Match tag, check length and assign value pointer - * \param data pointer to the pointer to data - * \param data_len pointer to size_t containing \arg data length - * \param[in] tag the tag (IEI) that we expect at \arg data - * \param[in] len the length that we expect the fixed IE to have - * \param[out] value pointer to pointer of value part of IE - * \returns length of IE value; negative in case of error - */ -int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, - uint8_t tag, size_t len, - uint8_t **value) -{ - size_t ie_len; - - if (*data_len == 0) - goto fail; - - if ((*data)[0] != tag) - return 0; - - if (len > *data_len - 1) - goto fail; - - if (value) - *value = *data + 1; - - ie_len = len + 1; - *data += ie_len; - *data_len -= ie_len; - - return ie_len; - -fail: - *data += *data_len; - *data_len = 0; - return -1; -} - -/*! Verify TLV header and advance data / subtract length - * \param data pointer to the pointer to data - * \param data_len pointer to size_t containing \arg data length - * \param[in] expected_tag the tag (IEI) that we expect at \arg data - * \param[out] value pointer to pointer of value part of IE - * \param[out] value_len pointer to length of \arg value - * \returns length of IE value; negative in case of error - */ -int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, - uint8_t expected_tag, uint8_t **value, - size_t *value_len) -{ - int rc; - uint8_t tag; - uint8_t *old_data = *data; - size_t old_data_len = *data_len; - - rc = osmo_shift_tlv(data, data_len, &tag, value, value_len); - - if (rc > 0 && tag != expected_tag) { - *data = old_data; - *data_len = old_data_len; - return 0; - } - - return rc; -} - -/*! Extract TLV and advance data pointer + subtract length - * \param data pointer to the pointer to data - * \param data_len pointer to size_t containing \arg data lengt - * \param[out] tag extract the tag (IEI) at start of \arg data - * \param[out] value extracted pointer to value part of TLV - * \param[out] value_len extracted length of \arg value - * \returns number of bytes subtracted - */ -int osmo_shift_tlv(uint8_t **data, size_t *data_len, - uint8_t *tag, uint8_t **value, size_t *value_len) -{ - size_t len; - size_t ie_len; - - if (*data_len < 2) - goto fail; - - len = (*data)[1]; - if (len > *data_len - 2) - goto fail; - - if (tag) - *tag = (*data)[0]; - if (value) - *value = *data + 2; - if (value_len) - *value_len = len; - - ie_len = len + 2; - - *data += ie_len; - *data_len -= ie_len; - - return ie_len; - -fail: - *data += *data_len; - *data_len = 0; - return -1; -} - -/*! Extract LV and advance data pointer + subtract length - * \param data pointer to the pointer to data - * \param data_len pointer to size_t containing \arg data lengt - * \param[out] value extracted pointer to value part of TLV - * \param[out] value_len extracted length of \arg value - * \returns number of bytes subtracted - */ -int osmo_shift_lv(uint8_t **data, size_t *data_len, - uint8_t **value, size_t *value_len) -{ - size_t len; - size_t ie_len; - - if (*data_len < 1) - goto fail; - - len = (*data)[0]; - if (len > *data_len - 1) - goto fail; - - if (value) - *value = *data + 1; - if (value_len) - *value_len = len; - - ie_len = len + 1; - *data += ie_len; - *data_len -= ie_len; - - return ie_len; - -fail: - *data += *data_len; - *data_len = 0; - return -1; -} - int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2) { diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c index 94eae35b9..773588b63 100644 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ b/openbsc/src/gprs/osmo_gsup_messages.c @@ -26,7 +26,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 7ca035decaaed460e66286868b1f14ccd3e00013 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 15:36:08 +0200 Subject: gsup_messages: Add UMTS AKA related encoding/decoding support --- openbsc/src/gprs/osmo_gsup_messages.c | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c index 773588b63..e820b5a17 100644 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ b/openbsc/src/gprs/osmo_gsup_messages.c @@ -90,6 +90,7 @@ static int decode_auth_info(uint8_t *data, size_t data_len, uint8_t *value; size_t value_len; enum osmo_gsup_iei iei; + uint8_t presence = 0; /* specific parts */ while (data_len > 0) { @@ -105,6 +106,7 @@ static int decode_auth_info(uint8_t *data, size_t data_len, goto parse_error; memcpy(auth_vector->rand, value, value_len); + presence |= (1 << 0); break; case OSMO_GSUP_SRES_IE: @@ -112,6 +114,7 @@ static int decode_auth_info(uint8_t *data, size_t data_len, goto parse_error; memcpy(auth_vector->sres, value, value_len); + presence |= (1 << 1); break; case OSMO_GSUP_KC_IE: @@ -119,6 +122,35 @@ static int decode_auth_info(uint8_t *data, size_t data_len, goto parse_error; memcpy(auth_vector->kc, value, value_len); + presence |= (1 << 2); + break; + + case OSMO_GSUP_IK_IE: + if (value_len != sizeof(auth_vector->ik)) + goto parse_error; + memcpy(auth_vector->ik, value, value_len); + presence |= (1 << 4); + break; + + case OSMO_GSUP_CK_IE: + if (value_len != sizeof(auth_vector->ck)) + goto parse_error; + memcpy(auth_vector->ck, value, value_len); + presence |= (1 << 5); + break; + + case OSMO_GSUP_AUTN_IE: + if (value_len != sizeof(auth_vector->autn)) + goto parse_error; + memcpy(auth_vector->autn, value, value_len); + presence |= (1 << 6); + break; + case OSMO_GSUP_RES_IE: + if (value_len > sizeof(auth_vector->res)) + goto parse_error; + memcpy(auth_vector->res, value, value_len); + auth_vector->res_len = value_len; + presence |= (1 << 7); break; default: @@ -128,6 +160,11 @@ static int decode_auth_info(uint8_t *data, size_t data_len, } } + if (presence & 0x07) + auth_vector->auth_types |= OSMO_AUTH_TYPE_GSM; + if (presence & 0xf0) + auth_vector->auth_types |= OSMO_AUTH_TYPE_UMTS; + return 0; parse_error: @@ -270,6 +307,15 @@ int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, auth_info; break; + case OSMO_GSUP_AUTS_IE: + if (value_len != 16) { + LOGP(DGPRS, LOGL_ERROR, + "AUTS length != 16 received\n"); + return -GMM_CAUSE_COND_IE_ERR; + } + gsup_msg->auts = value; + break; + case OSMO_GSUP_MSISDN_IE: gsup_msg->msisdn_enc = value; gsup_msg->msisdn_enc_len = value_len; -- cgit v1.2.3 From eff215a8bb766e62a02bcc0f4334470a53475001 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 16:01:15 +0200 Subject: osmo_gsup_messge.[ch] documentation update (doxygen) --- openbsc/src/gprs/osmo_gsup_messages.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c index e820b5a17..430cba750 100644 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ b/openbsc/src/gprs/osmo_gsup_messages.c @@ -174,6 +174,12 @@ parse_error: return -1; } +/*! Decode (parse) a GSUP message + * \param[in] const_data input data to be parsed + * \param[in] data_len length of input (\a const_data) + * \param[out] gsup_msg callee-allocated output data structure + * \returns 0 on success; negative otherwise + */ int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, struct osmo_gsup_message *gsup_msg) { @@ -392,6 +398,10 @@ static void encode_auth_info(struct msgb *msg, enum osmo_gsup_iei iei, *len_field = msgb_length(msg) - old_len; } +/*! Encode a GSUP message + * \param[out] msg message buffer to which encoded message is written + * \param[in] gsup_msg \ref osmo_gsup_message data to be encoded + */ void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) { uint8_t u8; -- cgit v1.2.3 From 50f1c0af567423b6ade9a84aaa5197ecf6237819 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 19:01:26 +0200 Subject: move utils.h functions to libosmocore This needs the corresponding commit in libosmocore which imports the related functions --- openbsc/src/gprs/oap.c | 4 +-- openbsc/src/gprs/oap_messages.c | 9 +++--- openbsc/src/libcommon/Makefile.am | 2 +- openbsc/src/libcommon/utils.c | 58 -------------------------------------- openbsc/src/osmo-bsc_nat/bsc_nat.c | 3 +- 5 files changed, 9 insertions(+), 67 deletions(-) delete mode 100644 openbsc/src/libcommon/utils.c (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c index 1426702dd..f5d7a9570 100644 --- a/openbsc/src/gprs/oap.c +++ b/openbsc/src/gprs/oap.c @@ -20,10 +20,10 @@ * */ +#include #include #include -#include #include #include @@ -103,7 +103,7 @@ static int oap_evaluate_challenge(const struct oap_state *state, return -3; } - if (constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { + if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { LOGP(DGPRS, LOGL_ERROR, "OAP: AUTN mismatch!\n"); LOGP(DGPRS, LOGL_INFO, "OAP: AUTN from server: %s\n", osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c index 49b54e439..d5750a612 100644 --- a/openbsc/src/gprs/oap_messages.c +++ b/openbsc/src/gprs/oap_messages.c @@ -20,11 +20,11 @@ * */ +#include #include #include #include -#include #include #include @@ -51,7 +51,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len, rc = osmo_shift_v_fixed(&data, &data_len, 1, &value); if (rc < 0) return -GMM_CAUSE_INV_MAND_INFO; - oap_msg->message_type = decode_big_endian(value, 1); + oap_msg->message_type = osmo_decode_big_endian(value, 1); /* specific parts */ while (data_len > 0) { @@ -72,7 +72,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len, return -GMM_CAUSE_PROTO_ERR_UNSPEC; } - oap_msg->client_id = decode_big_endian(value, value_len); + oap_msg->client_id = osmo_decode_big_endian(value, value_len); if (oap_msg->client_id == 0) { LOGP(DGPRS, LOGL_NOTICE, @@ -159,7 +159,8 @@ void oap_encode(struct msgb *msg, const struct oap_message *oap_msg) if (oap_msg->client_id > 0) msgb_tlv_put(msg, OAP_CLIENT_ID_IE, sizeof(oap_msg->client_id), - encode_big_endian(oap_msg->client_id, sizeof(oap_msg->client_id))); + osmo_encode_big_endian(oap_msg->client_id, + sizeof(oap_msg->client_id))); if (oap_msg->rand_present) msgb_tlv_put(msg, OAP_RAND_IE, sizeof(oap_msg->rand), oap_msg->rand); diff --git a/openbsc/src/libcommon/Makefile.am b/openbsc/src/libcommon/Makefile.am index 84c754452..75f40eea7 100644 --- a/openbsc/src/libcommon/Makefile.am +++ b/openbsc/src/libcommon/Makefile.am @@ -6,4 +6,4 @@ noinst_LIBRARIES = libcommon.a libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c \ gsm_data_shared.c socket.c talloc_ctx.c \ - gsm_subscriber_base.c utils.c + gsm_subscriber_base.c diff --git a/openbsc/src/libcommon/utils.c b/openbsc/src/libcommon/utils.c deleted file mode 100644 index c47dcaee2..000000000 --- a/openbsc/src/libcommon/utils.c +++ /dev/null @@ -1,58 +0,0 @@ -/* OpenBSC kitchen sink */ - -/* (C) 2015 by sysmocom s.m.f.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 . - * - */ - -#include -#include -#include - -/* Wishful thinking to generate a constant time compare */ -int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count) -{ - int x = 0, i; - - for (i = 0; i < count; ++i) - x |= exp[i] ^ rel[i]; - - /* if x is zero, all data was identical */ - return x? 1 : 0; -} - - -uint64_t decode_big_endian(const uint8_t *data, size_t data_len) -{ - uint64_t value = 0; - - while (data_len > 0) { - value = (value << 8) + *data; - data += 1; - data_len -= 1; - } - - return value; -} - -uint8_t *encode_big_endian(uint64_t value, size_t data_len) -{ - static uint8_t buf[sizeof(uint64_t)]; - OSMO_ASSERT(data_len <= ARRAY_SIZE(buf)); - osmo_store64be_ext(value, buf, data_len); - return buf; -} - diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index efae54f02..f20b2486f 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -1023,7 +1022,7 @@ static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, cons return 0; } - return constant_time_cmp(vec.res, key, 8) == 0; + return osmo_constant_time_cmp(vec.res, key, 8) == 0; } static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc) -- cgit v1.2.3 From 23d77d56ea47bbb971bf2fc5d93d6ae2d7d30f03 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2016 19:07:34 +0200 Subject: Move osmo_gsup_messages.[ch] to libosmocore This requires the corresponding commit in libosmocore. --- openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gprs_subscriber.c | 2 +- openbsc/src/gprs/osmo_gsup_messages.c | 472 ---------------------------------- 3 files changed, 2 insertions(+), 474 deletions(-) delete mode 100644 openbsc/src/gprs/osmo_gsup_messages.c (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 7889d5fd9..6dc7e1634 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -26,7 +26,7 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ - osmo_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ + gprs_utils.c gprs_gsup_client.c \ sgsn_cdr.c sgsn_ares.c \ oap.c oap_messages.c osmo_sgsn_LDADD = \ diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index d9bc10a18..f5a5937a0 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -21,13 +21,13 @@ */ #include +#include #include #include #include #include #include -#include #include #include diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c deleted file mode 100644 index 430cba750..000000000 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ /dev/null @@ -1,472 +0,0 @@ -/* Osmocom Subscriber Update Protocol message encoder/decoder */ - -/* - * (C) 2014 by Sysmocom s.f.m.c. GmbH - * (C) 2015 by Holger Hans Peter Freyther - * (C) 2016 by Harald Welte - * All Rights Reserved - * - * Author: Jacob Erlbeck - * - * 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 . - * - */ - -#include - -#include -#include - -#include -#include -#include - -#include - -static int decode_pdp_info(uint8_t *data, size_t data_len, - struct osmo_gsup_pdp_info *pdp_info) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - - /* specific parts */ - while (data_len > 0) { - enum osmo_gsup_iei iei; - - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_PDP_CONTEXT_ID_IE: - pdp_info->context_id = decode_big_endian(value, value_len); - break; - - case OSMO_GSUP_PDP_TYPE_IE: - pdp_info->pdp_type = - decode_big_endian(value, value_len) & 0x0fff; - break; - - case OSMO_GSUP_ACCESS_POINT_NAME_IE: - pdp_info->apn_enc = value; - pdp_info->apn_enc_len = value_len; - break; - - case OSMO_GSUP_PDP_QOS_IE: - pdp_info->qos_enc = value; - pdp_info->qos_enc_len = value_len; - break; - - default: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d not expected in PDP info\n", iei); - continue; - } - } - - return 0; -} - -static int decode_auth_info(uint8_t *data, size_t data_len, - struct osmo_auth_vector *auth_vector) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - enum osmo_gsup_iei iei; - uint8_t presence = 0; - - /* specific parts */ - while (data_len > 0) { - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_RAND_IE: - if (value_len != sizeof(auth_vector->rand)) - goto parse_error; - - memcpy(auth_vector->rand, value, value_len); - presence |= (1 << 0); - break; - - case OSMO_GSUP_SRES_IE: - if (value_len != sizeof(auth_vector->sres)) - goto parse_error; - - memcpy(auth_vector->sres, value, value_len); - presence |= (1 << 1); - break; - - case OSMO_GSUP_KC_IE: - if (value_len != sizeof(auth_vector->kc)) - goto parse_error; - - memcpy(auth_vector->kc, value, value_len); - presence |= (1 << 2); - break; - - case OSMO_GSUP_IK_IE: - if (value_len != sizeof(auth_vector->ik)) - goto parse_error; - memcpy(auth_vector->ik, value, value_len); - presence |= (1 << 4); - break; - - case OSMO_GSUP_CK_IE: - if (value_len != sizeof(auth_vector->ck)) - goto parse_error; - memcpy(auth_vector->ck, value, value_len); - presence |= (1 << 5); - break; - - case OSMO_GSUP_AUTN_IE: - if (value_len != sizeof(auth_vector->autn)) - goto parse_error; - memcpy(auth_vector->autn, value, value_len); - presence |= (1 << 6); - break; - case OSMO_GSUP_RES_IE: - if (value_len > sizeof(auth_vector->res)) - goto parse_error; - memcpy(auth_vector->res, value, value_len); - auth_vector->res_len = value_len; - presence |= (1 << 7); - break; - - default: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d not expected in PDP info\n", iei); - continue; - } - } - - if (presence & 0x07) - auth_vector->auth_types |= OSMO_AUTH_TYPE_GSM; - if (presence & 0xf0) - auth_vector->auth_types |= OSMO_AUTH_TYPE_UMTS; - - return 0; - -parse_error: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len); - - return -1; -} - -/*! Decode (parse) a GSUP message - * \param[in] const_data input data to be parsed - * \param[in] data_len length of input (\a const_data) - * \param[out] gsup_msg callee-allocated output data structure - * \returns 0 on success; negative otherwise - */ -int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, - struct osmo_gsup_message *gsup_msg) -{ - int rc; - uint8_t tag; - /* the shift/match functions expect non-const pointers, but we'll - * either copy the data or cast pointers back to const before returning - * them - */ - uint8_t *data = (uint8_t *)const_data; - uint8_t *value; - size_t value_len; - static const struct osmo_gsup_pdp_info empty_pdp_info = {0}; - static const struct osmo_auth_vector empty_auth_info = {0}; - static const struct osmo_gsup_message empty_gsup_message = {0}; - - *gsup_msg = empty_gsup_message; - - /* generic part */ - rc = osmo_shift_v_fixed(&data, &data_len, 1, &value); - if (rc < 0) - return -GMM_CAUSE_INV_MAND_INFO; - - gsup_msg->message_type = decode_big_endian(value, 1); - - rc = osmo_match_shift_tlv(&data, &data_len, OSMO_GSUP_IMSI_IE, - &value, &value_len); - - if (rc <= 0) - return -GMM_CAUSE_INV_MAND_INFO; - - if (value_len * 2 + 1 > sizeof(gsup_msg->imsi)) - return -GMM_CAUSE_INV_MAND_INFO; - - /* Note that gsm48_decode_bcd_number expects the number of encoded IMSI - * octets in the first octet. By coincidence (the TLV encoding) the byte - * before the value part already contains this length so we can use it - * here. - */ - OSMO_ASSERT(value[-1] == value_len); - gsm48_decode_bcd_number(gsup_msg->imsi, sizeof(gsup_msg->imsi), - value - 1, 0); - - /* specific parts */ - while (data_len > 0) { - enum osmo_gsup_iei iei; - struct osmo_gsup_pdp_info pdp_info; - struct osmo_auth_vector auth_info; - - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_IMSI_IE: - case OSMO_GSUP_PDP_TYPE_IE: - case OSMO_GSUP_ACCESS_POINT_NAME_IE: - case OSMO_GSUP_RAND_IE: - case OSMO_GSUP_SRES_IE: - case OSMO_GSUP_KC_IE: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d not expected (ignored)\n", iei); - continue; - - case OSMO_GSUP_CAUSE_IE: - gsup_msg->cause = decode_big_endian(value, value_len); - break; - - case OSMO_GSUP_CANCEL_TYPE_IE: - gsup_msg->cancel_type = - decode_big_endian(value, value_len) + 1; - break; - - case OSMO_GSUP_PDP_INFO_COMPL_IE: - gsup_msg->pdp_info_compl = 1; - break; - - case OSMO_GSUP_FREEZE_PTMSI_IE: - gsup_msg->freeze_ptmsi = 1; - break; - - case OSMO_GSUP_PDP_CONTEXT_ID_IE: - /* When these IE appear in the top-level part of the - * message, they are used by Delete Subscr Info to delete - * single entries. We don't have an extra list for - * these but use the PDP info list instead */ - - /* fall through */ - - case OSMO_GSUP_PDP_INFO_IE: - if (gsup_msg->num_pdp_infos >= OSMO_GSUP_MAX_NUM_PDP_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (PDP_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_COND_IE_ERR; - } - - pdp_info = empty_pdp_info; - - if (iei == OSMO_GSUP_PDP_INFO_IE) { - rc = decode_pdp_info(value, value_len, &pdp_info); - if (rc < 0) - return rc; - pdp_info.have_info = 1; - } else { - pdp_info.context_id = - decode_big_endian(value, value_len); - } - - gsup_msg->pdp_infos[gsup_msg->num_pdp_infos++] = - pdp_info; - break; - - case OSMO_GSUP_AUTH_TUPLE_IE: - if (gsup_msg->num_auth_vectors >= OSMO_GSUP_MAX_NUM_AUTH_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (AUTH_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_INV_MAND_INFO; - } - - auth_info = empty_auth_info; - - rc = decode_auth_info(value, value_len, &auth_info); - if (rc < 0) - return rc; - - gsup_msg->auth_vectors[gsup_msg->num_auth_vectors++] = - auth_info; - break; - - case OSMO_GSUP_AUTS_IE: - if (value_len != 16) { - LOGP(DGPRS, LOGL_ERROR, - "AUTS length != 16 received\n"); - return -GMM_CAUSE_COND_IE_ERR; - } - gsup_msg->auts = value; - break; - - case OSMO_GSUP_MSISDN_IE: - gsup_msg->msisdn_enc = value; - gsup_msg->msisdn_enc_len = value_len; - break; - - case OSMO_GSUP_HLR_NUMBER_IE: - gsup_msg->hlr_enc = value; - gsup_msg->hlr_enc_len = value_len; - break; - - default: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d unknown\n", iei); - continue; - } - } - - return 0; -} - -static void encode_pdp_info(struct msgb *msg, enum osmo_gsup_iei iei, - const struct osmo_gsup_pdp_info *pdp_info) -{ - uint8_t *len_field; - size_t old_len; - uint8_t u8; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - u8 = pdp_info->context_id; - msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8); - - if (pdp_info->pdp_type) { - msgb_tlv_put(msg, OSMO_GSUP_PDP_TYPE_IE, - OSMO_GSUP_PDP_TYPE_SIZE, - encode_big_endian(pdp_info->pdp_type | 0xf000, - OSMO_GSUP_PDP_TYPE_SIZE)); - } - - if (pdp_info->apn_enc) { - msgb_tlv_put(msg, OSMO_GSUP_ACCESS_POINT_NAME_IE, - pdp_info->apn_enc_len, pdp_info->apn_enc); - } - - if (pdp_info->qos_enc) { - msgb_tlv_put(msg, OSMO_GSUP_PDP_QOS_IE, - pdp_info->qos_enc_len, pdp_info->qos_enc); - } - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -static void encode_auth_info(struct msgb *msg, enum osmo_gsup_iei iei, - const struct osmo_auth_vector *auth_vector) -{ - uint8_t *len_field; - size_t old_len; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - msgb_tlv_put(msg, OSMO_GSUP_RAND_IE, - sizeof(auth_vector->rand), auth_vector->rand); - - msgb_tlv_put(msg, OSMO_GSUP_SRES_IE, - sizeof(auth_vector->sres), auth_vector->sres); - - msgb_tlv_put(msg, OSMO_GSUP_KC_IE, - sizeof(auth_vector->kc), auth_vector->kc); - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -/*! Encode a GSUP message - * \param[out] msg message buffer to which encoded message is written - * \param[in] gsup_msg \ref osmo_gsup_message data to be encoded - */ -void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) -{ - uint8_t u8; - int idx; - uint8_t bcd_buf[GSM48_MI_SIZE] = {0}; - size_t bcd_len; - - /* generic part */ - OSMO_ASSERT(gsup_msg->message_type); - msgb_v_put(msg, gsup_msg->message_type); - - bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, - gsup_msg->imsi); - - OSMO_ASSERT(bcd_len > 1); - - /* Note that gsm48_encode_bcd_number puts the length into the first - * octet. Since msgb_tlv_put will add this length byte, we'll have to - * skip it */ - msgb_tlv_put(msg, OSMO_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); - - /* specific parts */ - if (gsup_msg->msisdn_enc) - msgb_tlv_put(msg, OSMO_GSUP_MSISDN_IE, - gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); - if (gsup_msg->hlr_enc) - msgb_tlv_put(msg, OSMO_GSUP_HLR_NUMBER_IE, - gsup_msg->hlr_enc_len, gsup_msg->hlr_enc); - - if ((u8 = gsup_msg->cause)) - msgb_tlv_put(msg, OSMO_GSUP_CAUSE_IE, sizeof(u8), &u8); - - if ((u8 = gsup_msg->cancel_type)) { - u8 -= 1; - msgb_tlv_put(msg, OSMO_GSUP_CANCEL_TYPE_IE, sizeof(u8), &u8); - } - - if (gsup_msg->pdp_info_compl) - msgb_tlv_put(msg, OSMO_GSUP_PDP_INFO_COMPL_IE, 0, &u8); - - if (gsup_msg->freeze_ptmsi) - msgb_tlv_put(msg, OSMO_GSUP_FREEZE_PTMSI_IE, 0, &u8); - - for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) { - const struct osmo_gsup_pdp_info *pdp_info; - - pdp_info = &gsup_msg->pdp_infos[idx]; - - if (pdp_info->context_id == 0) - continue; - - if (pdp_info->have_info) { - encode_pdp_info(msg, OSMO_GSUP_PDP_INFO_IE, pdp_info); - } else { - u8 = pdp_info->context_id; - msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, - sizeof(u8), &u8); - } - } - - for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { - const struct osmo_auth_vector *auth_vector; - - auth_vector = &gsup_msg->auth_vectors[idx]; - - encode_auth_info(msg, OSMO_GSUP_AUTH_TUPLE_IE, auth_vector); - } -} -- cgit v1.2.3 From 31760a1f6089fb59475ba79faa3eb97e4cf00f68 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 27 Apr 2016 15:17:14 +0200 Subject: oap_message.h: Remove dependency to openbsc include This is a first step to moving oap_messages.h to libosmocore --- openbsc/src/gprs/oap.c | 2 ++ openbsc/src/gprs/oap_messages.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c index f5d7a9570..eb0dd19d1 100644 --- a/openbsc/src/gprs/oap.c +++ b/openbsc/src/gprs/oap.c @@ -20,6 +20,8 @@ * */ +#include + #include #include diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c index d5750a612..ccb3c81a2 100644 --- a/openbsc/src/gprs/oap_messages.c +++ b/openbsc/src/gprs/oap_messages.c @@ -24,7 +24,6 @@ #include #include -#include #include #include -- cgit v1.2.3 From 564c06525b9acb3f4b90d4c92970e7d9cc5b1d8e Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 27 Apr 2016 18:14:14 +0200 Subject: OAP: use osmo_oap_ prefix for OAP, rather than plain oap_ this is in preparation of moving related code to libosmocore. --- openbsc/src/gprs/oap.c | 14 +++++++------- openbsc/src/gprs/oap_messages.c | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c index eb0dd19d1..0b8f48260 100644 --- a/openbsc/src/gprs/oap.c +++ b/openbsc/src/gprs/oap.c @@ -119,11 +119,11 @@ static int oap_evaluate_challenge(const struct oap_state *state, return 0; } -struct msgb *oap_encoded(const struct oap_message *oap_msg) +struct msgb *oap_encoded(const struct osmo_oap_message *oap_msg) { struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); OSMO_ASSERT(msg); - oap_encode(msg, oap_msg); + osmo_oap_encode(msg, oap_msg); return msg; } @@ -136,7 +136,7 @@ static struct msgb* oap_msg_register(uint16_t client_id) return NULL; } - struct oap_message oap_msg = {0}; + struct osmo_oap_message oap_msg = {0}; oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; oap_msg.client_id = client_id; return oap_encoded(&oap_msg); @@ -157,7 +157,7 @@ int oap_register(struct oap_state *state, struct msgb **msg_tx) * On error, return NULL. */ static struct msgb* oap_msg_challenge_response(uint8_t *xres) { - struct oap_message oap_reply = {0}; + struct osmo_oap_message oap_reply = {0}; oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); @@ -166,7 +166,7 @@ static struct msgb* oap_msg_challenge_response(uint8_t *xres) } static int handle_challenge(struct oap_state *state, - struct oap_message *oap_rx, + struct osmo_oap_message *oap_rx, struct msgb **msg_tx) { int rc; @@ -209,11 +209,11 @@ int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb * size_t data_len = msgb_l2len(msg_rx); int rc = 0; - struct oap_message oap_msg = {0}; + struct osmo_oap_message oap_msg = {0}; OSMO_ASSERT(data); - rc = oap_decode(data, data_len, &oap_msg); + rc = osmo_oap_decode(data, data_len, &oap_msg); if (rc < 0) { LOGP(DGPRS, LOGL_ERROR, "Decoding OAP message failed with error '%s' (%d)\n", diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c index ccb3c81a2..53ea9ac84 100644 --- a/openbsc/src/gprs/oap_messages.c +++ b/openbsc/src/gprs/oap_messages.c @@ -31,8 +31,8 @@ #include -int oap_decode(const uint8_t *const_data, size_t data_len, - struct oap_message *oap_msg) +int osmo_oap_decode(const uint8_t *const_data, size_t data_len, + struct osmo_oap_message *oap_msg) { int rc; uint8_t tag; @@ -144,7 +144,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len, return 0; } -void oap_encode(struct msgb *msg, const struct oap_message *oap_msg) +void osmo_oap_encode(struct msgb *msg, const struct osmo_oap_message *oap_msg) { uint8_t u8; -- cgit v1.2.3 From d8aa412c46638abea05488ebb2e9d70ca7fd628a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 27 Apr 2016 18:17:26 +0200 Subject: OAP: Various coding style fixes * we always declare stack variables at the top of the function / block * 'switch' is not a function, so there's space ahead of the opening ( --- openbsc/src/gprs/oap.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c index 0b8f48260..a9fee566b 100644 --- a/openbsc/src/gprs/oap.c +++ b/openbsc/src/gprs/oap.c @@ -71,12 +71,19 @@ static int oap_evaluate_challenge(const struct oap_state *state, const uint8_t *rx_autn, uint8_t *tx_xres) { + struct osmo_auth_vector vec; + + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_UMTS, + .algo = OSMO_AUTH_ALG_MILENAGE, + }; + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k) == sizeof(state->secret_k), _secret_k_size_match); osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc) == sizeof(state->secret_opc), _secret_opc_size_match); - switch(state->state) { + switch (state->state) { case OAP_UNINITIALIZED: case OAP_DISABLED: return -1; @@ -84,13 +91,6 @@ static int oap_evaluate_challenge(const struct oap_state *state, break; } - struct osmo_auth_vector vec; - - struct osmo_sub_auth_data auth = { - .type = OSMO_AUTH_TYPE_UMTS, - .algo = OSMO_AUTH_ALG_MILENAGE, - }; - memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf)); @@ -131,12 +131,13 @@ struct msgb *oap_encoded(const struct osmo_oap_message *oap_msg) * On error, return NULL. */ static struct msgb* oap_msg_register(uint16_t client_id) { + struct osmo_oap_message oap_msg = {0}; + if (client_id < 1) { LOGP(DGPRS, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); return NULL; } - struct osmo_oap_message oap_msg = {0}; oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; oap_msg.client_id = client_id; return oap_encoded(&oap_msg); @@ -170,6 +171,8 @@ static int handle_challenge(struct oap_state *state, struct msgb **msg_tx) { int rc; + uint8_t xres[8]; + if (!(oap_rx->rand_present && oap_rx->autn_present)) { LOGP(DGPRS, LOGL_ERROR, "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", @@ -178,7 +181,6 @@ static int handle_challenge(struct oap_state *state, goto failure; } - uint8_t xres[8]; rc = oap_evaluate_challenge(state, oap_rx->rand, oap_rx->autn, @@ -203,13 +205,12 @@ failure: int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb **msg_tx) { - *msg_tx = NULL; - uint8_t *data = msgb_l2(msg_rx); size_t data_len = msgb_l2len(msg_rx); + struct osmo_oap_message oap_msg = {0}; int rc = 0; - struct osmo_oap_message oap_msg = {0}; + *msg_tx = NULL; OSMO_ASSERT(data); -- cgit v1.2.3 From 5d547a4358edbd18744d1996d6ecb40328f09061 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 27 Apr 2016 18:21:16 +0200 Subject: osmo_oap_decode(): Use common argument ordering In general, if a function generates output data like a msgb (or in this case filling an osmo_oap_message structure), the output argument precedes the source. This is what we use all over libosmo*, and it is modelled after memcpy(), where dst is the first argument, before src. Let's align osmo_oap_decode(). Intestingly, osmo_oap_encode was already correct, so the encode/decode functions used different conventions before. --- openbsc/src/gprs/oap.c | 2 +- openbsc/src/gprs/oap_messages.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c index a9fee566b..c7c97774d 100644 --- a/openbsc/src/gprs/oap.c +++ b/openbsc/src/gprs/oap.c @@ -214,7 +214,7 @@ int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb * OSMO_ASSERT(data); - rc = osmo_oap_decode(data, data_len, &oap_msg); + rc = osmo_oap_decode(&oap_msg, data, data_len); if (rc < 0) { LOGP(DGPRS, LOGL_ERROR, "Decoding OAP message failed with error '%s' (%d)\n", diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c index 53ea9ac84..d81723fd6 100644 --- a/openbsc/src/gprs/oap_messages.c +++ b/openbsc/src/gprs/oap_messages.c @@ -31,8 +31,8 @@ #include -int osmo_oap_decode(const uint8_t *const_data, size_t data_len, - struct osmo_oap_message *oap_msg) +int osmo_oap_decode(struct osmo_oap_message *oap_msg, + const uint8_t *const_data, size_t data_len) { int rc; uint8_t tag; -- cgit v1.2.3 From 5f2524fe3d7242530f2088635df03df297862da0 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 5 May 2016 18:25:12 +0200 Subject: sgsn/GSUP: Support MAP-style nested LU/ISD The existing GSUP code expected the subscriber data to be piggy-backed onto the location update response, rather than a separate (and nested) insert subscriber data request/response phase. With this patch we should now support both the nested as well as the piggy-backed version. --- openbsc/src/gprs/gprs_subscriber.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index f5a5937a0..71f5ff188 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -340,6 +340,9 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr, struct osmo_gsup_message *gsup_msg) { + /* contrary to MAP, we allow piggy-backing subscriber data onto + * the UPDATE LOCATION RESULT, and don't mandate the use of a + * separate nested INSERT SUBSCRIBER DATA transaction */ gprs_subscr_gsup_insert_data(subscr, gsup_msg); subscr->authorized = 1; @@ -351,6 +354,22 @@ static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr, return 0; } +static int gprs_subscr_handle_gsup_isd_req(struct gsm_subscriber *subscr, + struct osmo_gsup_message *gsup_msg) +{ + struct osmo_gsup_message gsup_reply = {0}; + + gprs_subscr_gsup_insert_data(subscr, gsup_msg); + + subscr->authorized = 1; + subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE; + subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE; + gprs_subscr_update(subscr); + + gsup_reply.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT; + return gprs_subscr_tx_gsup_message(subscr, &gsup_reply); +} + static int check_cause(int cause) { switch (cause) { @@ -654,6 +673,9 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg) break; case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: + rc = gprs_subscr_handle_gsup_isd_req(subscr, &gsup_msg); + break; + case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST: LOGGSUBSCRP(LOGL_ERROR, subscr, "Rx GSUP message type %d not yet implemented\n", -- cgit v1.2.3 From 7c55ede8b12faf1420b25ba30b5a22467fb2445c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 5 May 2016 18:31:37 +0200 Subject: Add human-readable name of SGSN_AUTH_AUTHENTICATE In commit 4adb136da63a1d3ed523ad85e12fd99fc62f5701 we introduced a new authentication state SGSN_AUTH_AUTHENTICATE, but we didn't add that to auth_state_names[] resulting in log messages printing it abut 'unknown 0x1' rather than something more useful. --- openbsc/src/gprs/sgsn_auth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc/src') diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c index f0c4316c0..4b69a0d10 100644 --- a/openbsc/src/gprs/sgsn_auth.c +++ b/openbsc/src/gprs/sgsn_auth.c @@ -30,6 +30,7 @@ const struct value_string auth_state_names[] = { { SGSN_AUTH_ACCEPTED, "accepted"}, { SGSN_AUTH_REJECTED, "rejected"}, { SGSN_AUTH_UNKNOWN, "unknown"}, + { SGSN_AUTH_AUTHENTICATE, "authenticate" }, { 0, NULL } }; -- cgit v1.2.3