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(-) 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(+) 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(-) 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 7dd2eed6d3426ce27dc168e46a4db8b705608de4 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 4 Apr 2016 15:30:53 +0200 Subject: Ignore vty test byproducts --- openbsc/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 28fdcc8c4..bae3b6522 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -90,3 +90,5 @@ tests/testsuite.log src/openbsc.cfg* +writtenconfig/ +gtphub_restart_count -- cgit v1.2.3 From de392254ff05a5304ef0bbd351314d74b2ffd1e3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 1 Apr 2016 19:44:00 +0200 Subject: subscr: Add testcase creating an already created subscriber Add testcase to issue the subscriber create twice. db_create_subscriber in db.c will first try to find the subscriber and if it exists, it will update the "updated" column in the database. Related: OS Issue #1657 --- openbsc/tests/vty_test_runner.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 8db0825e3..ecf5204a4 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -307,6 +307,42 @@ class TestVTYNITB(TestVTYGenericBSC): if classNum != 10: self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1) + def testSubscriberCreateDeleteTwice(self): + """ + OS#1657 indicates that there might be an issue creating the + same subscriber twice. This test will use the VTY command to + create a subscriber and then issue a second create command + with the same IMSI. The test passes if the VTY continues to + respond to VTY commands. + """ + self.vty.enable() + + imsi = "204300854013739" + + # Initially we don't have this subscriber + self.vty.verify('show subscriber imsi '+imsi, ['% No subscriber found for imsi '+imsi]) + + # Lets create one + res = self.vty.command('subscriber create imsi '+imsi) + self.assert_(res.find(" IMSI: "+imsi) > 0) + # And now create one again. + res2 = self.vty.command('subscriber create imsi '+imsi) + self.assert_(res2.find(" IMSI: "+imsi) > 0) + self.assertEqual(res, res2) + + # Verify it has been created + res = self.vty.command('show subscriber imsi '+imsi) + self.assert_(res.find(" IMSI: "+imsi) > 0) + + # Delete it + res = self.vty.command('subscriber delete imsi '+imsi) + self.assert_(res != "") + + # Now it should not be there anymore + res = self.vty.command('show subscriber imsi '+imsi) + self.assert_(res != '% No subscriber found for imsi '+imsi) + + def testSubscriberCreateDelete(self): self.vty.enable() -- 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 +++++++++++----- openbsc/tests/db/db_test.c | 6 +++++- 3 files changed, 18 insertions(+), 14 deletions(-) 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. */ diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index a02d1f801..fb159a5b1 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -1,5 +1,5 @@ /* (C) 2008 by Jan Luebbe - * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009-2016 by Holger Hans Peter Freyther * (C) 2014 by Alexander Chemeris * All Rights Reserved * @@ -246,6 +246,10 @@ int main() SUBSCR_PUT(alice_db); SUBSCR_PUT(alice); + /* create it again and see it fails */ + alice = db_create_subscriber(alice_imsi); + OSMO_ASSERT(!alice); + test_sms(); test_sms_migrate(); -- 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(-) 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 ++++++++++++++++++++++++++++++++++++-- openbsc/tests/ctrl_test_runner.py | 27 +++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) 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); diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py index 21850e348..7a126437c 100644 --- a/openbsc/tests/ctrl_test_runner.py +++ b/openbsc/tests/ctrl_test_runner.py @@ -469,6 +469,33 @@ class TestCtrlNITB(TestCtrlBase): self.assertEquals(r['var'], 'number-of-bts') self.assertEquals(r['value'], '1') + def testSubscriberAddWithKi(self): + """Test that we can set the algorithm to none, xor, comp128v1""" + + r = self.do_set('subscriber-modify-v1', '2620345,445566') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,xor') + self.assertEquals(r['mtype'], 'ERROR') + self.assertEquals(r['error'], 'Value failed verification.') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,comp128v1,00112233445566778899AABBCCDDEEFF') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + + r = self.do_set('subscriber-modify-v1', '2620345,445566,none') + self.assertEquals(r['mtype'], 'SET_REPLY') + self.assertEquals(r['var'], 'subscriber-modify-v1') + self.assertEquals(r['value'], 'OK') + def testSubscriberAddRemove(self): r = self.do_set('subscriber-modify-v1', '2620345,445566') self.assertEquals(r['mtype'], 'SET_REPLY') -- 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(+) 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(+) 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(-) 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(-) 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/include/openbsc/bsc_nat.h | 3 ++- openbsc/src/osmo-bsc_nat/bsc_nat_utils.c | 7 +++++-- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 14 ++++---------- openbsc/tests/bsc-nat/bsc_nat_test.c | 14 +++++++------- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 309adb1ba..c5fefe172 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -320,7 +320,8 @@ struct bsc_nat_ussd_con { }; /* create and init the structures */ -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 *bsc_config_num(struct bsc_nat *nat, int num); struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len); void bsc_config_free(struct bsc_config *); 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; diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index a4b313c91..a405763bc 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -316,7 +316,7 @@ static void test_contrack() printf("Testing connection tracking.\n"); nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - con->cfg = bsc_config_alloc(nat, "foo"); + con->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(con->cfg, 23); bsc_config_add_lac(con->cfg, 49); bsc_config_add_lac(con->cfg, 42); @@ -434,7 +434,7 @@ static void test_paging(void) nat = bsc_nat_alloc(); con = bsc_connection_alloc(nat); - cfg = bsc_config_alloc(nat, "unknown"); + cfg = bsc_config_alloc(nat, "unknown", 0); con->cfg = cfg; bsc_config_add_lac(cfg, 23); con->authenticated = 1; @@ -476,7 +476,7 @@ static void test_mgcp_allocations(void) nat->mgcp_cfg->trunk.number_endpoints = 64; bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc->cfg->max_endpoints = 60; bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x22; @@ -522,7 +522,7 @@ static void test_mgcp_ass_tracking(void) mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 2323); bsc->last_endpoint = 0x1e; con.bsc = bsc; @@ -874,7 +874,7 @@ static void test_cr_filter() struct bsc_nat *nat = bsc_nat_alloc(); struct bsc_connection *bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 1234); bsc->cfg->acc_lst_name = "bsc"; nat->acc_lst_name = "nat"; @@ -953,7 +953,7 @@ static void test_dt_filter() struct bsc_connection *bsc = bsc_connection_alloc(nat); struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); bsc_config_add_lac(bsc->cfg, 23); con->bsc = bsc; @@ -1525,7 +1525,7 @@ static void test_nat_extract_lac() /* initialize the testcase */ nat = bsc_nat_alloc(); bsc = bsc_connection_alloc(nat); - bsc->cfg = bsc_config_alloc(nat, "foo"); + bsc->cfg = bsc_config_alloc(nat, "foo", 0); memset(&con, 0, sizeof(con)); con.bsc = bsc; -- cgit v1.2.3 From a47b4019900afbf89144d9e9ff9f62ae5d994cea Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 13 Apr 2016 19:03:38 -0400 Subject: jenkins: Add the build script from jenkins here This can be used to replicate a build issue more easily. --- contrib/jenkins.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 contrib/jenkins.sh diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh new file mode 100755 index 000000000..bde117c06 --- /dev/null +++ b/contrib/jenkins.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -ex + +rm -rf deps/install +mkdir deps || true +export LD_LIBRARY_PATH=$PWD/deps/install/lib +cd deps +osmo-deps.sh libosmocore + +cd libosmocore +autoreconf --install --force +./configure --prefix=$PWD/../install +$MAKE $PARALLEL_MAKE install + + +cd ../ +osmo-deps.sh libosmo-abis +cd libosmo-abis +autoreconf --install --force +PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install +PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install + +cd ../ +osmo-deps.sh libosmo-netif +cd libosmo-netif +autoreconf --install --force +PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install +PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install + +cd ../ +osmo-deps.sh libosmo-sccp +cd libosmo-sccp +autoreconf --install --force +PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install +PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install + +cd ../ +osmo-deps.sh libsmpp34 +cd libsmpp34 +autoreconf --install --force +./configure --prefix=$PWD/../install +$MAKE install + +cd ../ +osmo-deps.sh openggsn +cd openggsn +autoreconf --install --force +PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install +PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install + +cd ../../openbsc +autoreconf --install --force +PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig ./configure --enable-osmo-bsc --enable-nat $SMPP $MGCP --enable-vty-tests --enable-external-tests +PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig $MAKE $PARALLEL_MAKE +PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig LD_LIBRARY_PATH=$PWD/../deps/install/lib $MAKE check +PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig LD_LIBRARY_PATH=$PWD/../deps/install/lib $MAKE distcheck -- cgit v1.2.3 From 70cf7290da7cfca796eed8ffbd143073d9418dd2 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 13 Apr 2016 11:36:38 +0200 Subject: vty_test_runner: update ipa sending code Factor out 2, add 3 functions. Those functions are simple wrappers around hex strings specific to IPA protocol. Not all of them are utilized at the moment but they were checked with wireshark while working on the tests. It might come in handy if we'd like to further expand related test harness in future. The same goes for optional verbosity argument which is not used right now but will be handy for future debugging. --- openbsc/tests/vty_test_runner.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index ecf5204a4..d57412989 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -736,13 +736,13 @@ class TestVTYNAT(TestVTYGenericBSC): self.assertEqual(data, "\x00\x01\xfe\x04") print "Going to send ID_RESP response" - res = ussdSocket.send("\x00\x07\xfe\x05\x00\x04\x01\x6b\x65\x79") + res = ipa_send_resp(ussdSocket, "\x6b\x65\x79") self.assertEqual(res, 10) # initiating PING/PONG cycle to know, that the ID_RESP message has been processed print "Going to send PING request" - res = ussdSocket.send("\x00\x01\xfe\x00") + res = ipa_send_ping(ussdSocket) self.assertEqual(res, 4) print "Expecting PONG response" @@ -1007,6 +1007,31 @@ def add_nat_test(suite, workdir): test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT) suite.addTest(test) +def ipa_send_pong(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PONG!" + return x.send("\x00\x01\xfe\x01") + +def ipa_send_ping(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: PING?" + return x.send("\x00\x01\xfe\x00") + +def ipa_send_ack(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID ACK" + return x.send("\x00\x01\xfe\x06") + +def ipa_send_reset(x, verbose = False): + if (verbose): + print "\tBSC -> NAT: RESET" + return x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20") + +def ipa_send_resp(x, tk, verbose = False): + if (verbose): + print "\tBSC -> NAT: IPA ID RESP" + return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) + def add_bsc_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")): print("Skipping the BSC test") -- 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/doc/examples/osmo-bsc_nat/bscs.config | 13 ++++++ openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg | 8 +--- openbsc/include/openbsc/bsc_nat.h | 5 +++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 5 ++- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 49 ++++++++++++++++++++-- 5 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 openbsc/doc/examples/osmo-bsc_nat/bscs.config diff --git a/openbsc/doc/examples/osmo-bsc_nat/bscs.config b/openbsc/doc/examples/osmo-bsc_nat/bscs.config new file mode 100644 index 000000000..176debe42 --- /dev/null +++ b/openbsc/doc/examples/osmo-bsc_nat/bscs.config @@ -0,0 +1,13 @@ +nat + bsc 0 + token lol + location_area_code 1234 + description bsc + max-endpoints 32 + paging forbidden 0 + bsc 1 + token wat + location_area_code 5678 + description bsc + max-endpoints 32 + paging forbidden 0 diff --git a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg index 737d10474..2e00bc2c3 100644 --- a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg +++ b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg @@ -62,11 +62,5 @@ nat timeout ping 20 timeout pong 5 ip-dscp 0 + bscs-config-file bscs.config access-list bla imsi-allow ^11$ - - bsc 0 - token bla - location_area_code 1234 - description bsc - max-endpoints 32 - paging forbidden 0 diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index c5fefe172..5ccc02e18 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -264,6 +264,11 @@ struct bsc_nat { struct bsc_endpoint *bsc_endpoints; + /* path to file with BSC config */ + char *include_file; + char *include_base; + char *resolved_path; + /* filter */ char *acc_lst_name; 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/include/openbsc/bsc_nat.h | 5 ++ openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 29 ++++++++ openbsc/tests/vty_test_runner.py | 120 ++++++++++++++++++++++++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index 5ccc02e18..94ab0e5ff 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -35,6 +35,7 @@ #include #include +#include #define DIR_BSC 1 #define DIR_MSC 2 @@ -164,6 +165,10 @@ struct bsc_config { /* audio handling */ int max_endpoints; + /* used internally for reload handling */ + bool remove; + bool token_updated; + /* backpointer */ struct bsc_nat *nat; 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; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index d57412989..59fdd2f93 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -620,12 +620,61 @@ class TestVTYBSC(TestVTYGenericBSC): class TestVTYNAT(TestVTYGenericBSC): def vty_command(self): - return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-c", + return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c", "doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"] def vty_app(self): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") + def testBSCreload(self): + # use separate ip to avoid interference with other tests + ip = "127.0.0.4" + self.vty.enable() + bscs1 = self.vty.command("show bscs-config") + nat_bsc_reload(self) + bscs2 = self.vty.command("show bscs-config") + # check that multiple calls to bscs-config-file give the same result + self.assertEquals(bscs1, bscs2) + + # add new bsc + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 5") + self.vty.command("token key") + self.vty.command("location_area_code 666") + self.vty.command("end") + + # update bsc token + self.vty.command("configure terminal") + self.vty.command("nat") + self.vty.command("bsc 1") + self.vty.command("token xyu") + self.vty.command("end") + + nat_msc_ip(self, ip) + msc = nat_msc_test(self, ip) + b0 = nat_bsc_sock_test(0, "lol") + b1 = nat_bsc_sock_test(1, "xyu") + b2 = nat_bsc_sock_test(5, "key") + + self.assertEquals("3 BSCs configured", self.vty.command("show nat num-bscs-configured")) + self.assertTrue(3 == nat_bsc_num_con(self)) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + + nat_bsc_reload(self) + bscs2 = self.vty.command("show bscs-config") + # check that the reset to initial config succeeded + self.assertEquals(bscs1, bscs2) + + self.assertEquals("2 BSCs configured", self.vty.command("show nat num-bscs-configured")) + self.assertTrue(1 == nat_bsc_num_con(self)) + rem = self.vty.command("show bsc connections").split(' ') + # remaining connection is for BSC0 + self.assertEquals('0', rem[2]) + # remaining connection is authorized + self.assertEquals('1', rem[4]) + self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection")) + def testVtyTree(self): self.vty.enable() self.assertTrue(self.vty.verify('configure terminal', [''])) @@ -1032,6 +1081,75 @@ def ipa_send_resp(x, tk, verbose = False): print "\tBSC -> NAT: IPA ID RESP" return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk) +def nat_bsc_reload(x): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("bscs-config-file bscs.config") + x.vty.command("end") + +def nat_msc_ip(x, ip): + x.vty.command("configure terminal") + x.vty.command("nat") + x.vty.command("msc ip " + ip) + x.vty.command("end") + +def data2str(d): + return "".join("{:02x}".format(ord(c)) for c in d) + +def nat_msc_test(x, ip, verbose = False): + msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + msc.settimeout(32) + msc.bind((ip, 5000)) + msc.listen(5) + if (verbose): + print "MSC is ready at " + ip + while "MSC is connected: 0" == x.vty.command("show msc connection"): + conn, addr = msc.accept() + if (verbose): + print "MSC got connection from ", addr + return conn + +def ipa_handle_small(x, verbose = False): + s = data2str(x.recv(4)) + if "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PING?" + ipa_send_pong(x, verbose) + elif "0001fe06" == s: + if (verbose): + print "\tBSC <- NAT: IPA ID ACK" + ipa_send_ack(x, verbose) + elif "0001fe00" == s: + if (verbose): + print "\tBSC <- NAT: PONG!" + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def ipa_handle_resp(x, tk, verbose = False): + s = data2str(x.recv(38)) + if "0023fe040108010701020103010401050101010011" in s: + ipa_send_resp(x, tk, verbose) + else: + if (verbose): + print "\tBSC <- NAT: ", s + +def nat_bsc_num_con(x): + return len(x.vty.command("show bsc connections").split('\n')) + +def nat_bsc_sock_test(nr, tk, verbose = False): + bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + bsc.bind(('127.0.0.1' + str(nr), 0)) + bsc.connect(('127.0.0.1', 5000)) + if (verbose): + print "BSC%d " %nr + print "\tconnected to %s:%d" % bsc.getpeername() + ipa_handle_small(bsc, verbose) + ipa_handle_resp(bsc, tk, verbose) + bsc.recv(27) # MGCP msg + ipa_handle_small(bsc, verbose) + return bsc + def add_bsc_test(suite, workdir): if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")): print("Skipping the BSC test") -- cgit v1.2.3 From f1a61bb99f13b054d912f47dac90a15b2cf56651 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 08:50:25 -0400 Subject: nat/vty: Don't assume one can magically add IPv4 addresses to lo Don't assume that one can just bind to a local address that has not been configured. Remove the unspecific comment as I don't know to which other tests it is referred to. This should fix: ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 655, in testBSCreload msc = nat_msc_test(self, ip) File "./vty_test_runner.py", line 1102, in nat_msc_test msc.bind((ip, 5000)) File "", line 1, in bind error: [Errno 99] Cannot assign requested address ---------------------------------------------------------------------- --- openbsc/tests/vty_test_runner.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 59fdd2f93..11b788bcc 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -627,8 +627,7 @@ class TestVTYNAT(TestVTYGenericBSC): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") def testBSCreload(self): - # use separate ip to avoid interference with other tests - ip = "127.0.0.4" + ip = "127.0.0.1" self.vty.enable() bscs1 = self.vty.command("show bscs-config") nat_bsc_reload(self) -- cgit v1.2.3 From 44ed4979c9fc6143023aad796cfd8628b08fc47a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 10:05:13 -0400 Subject: nat/vty: Use different port for the mock MSC Update the comment to reflect that the NAT itself will bind to port 5000 and then the mock MSC will fail to bind to it. Try to move the mock MSC to another port. Could fix: ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 654, in testBSCreload msc = nat_msc_test(self, ip) File "./vty_test_runner.py", line 1101, in nat_msc_test msc.bind((ip, 5000)) File "", line 1, in bind error: [Errno 98] Address already in use ---------------------------------------------------------------------- --- openbsc/tests/vty_test_runner.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 11b788bcc..a4cfb607f 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -627,7 +627,10 @@ class TestVTYNAT(TestVTYGenericBSC): return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat") def testBSCreload(self): + # Use different port for the mock msc to avoid clashing with + # the osmo-bsc_nat itself ip = "127.0.0.1" + port = 5001 self.vty.enable() bscs1 = self.vty.command("show bscs-config") nat_bsc_reload(self) @@ -650,8 +653,8 @@ class TestVTYNAT(TestVTYGenericBSC): self.vty.command("token xyu") self.vty.command("end") - nat_msc_ip(self, ip) - msc = nat_msc_test(self, ip) + nat_msc_ip(self, ip, port) + msc = nat_msc_test(self, ip, port) b0 = nat_bsc_sock_test(0, "lol") b1 = nat_bsc_sock_test(1, "xyu") b2 = nat_bsc_sock_test(5, "key") @@ -1086,19 +1089,20 @@ def nat_bsc_reload(x): x.vty.command("bscs-config-file bscs.config") x.vty.command("end") -def nat_msc_ip(x, ip): +def nat_msc_ip(x, ip, port): x.vty.command("configure terminal") x.vty.command("nat") x.vty.command("msc ip " + ip) + x.vty.command("msc port " + port) x.vty.command("end") def data2str(d): return "".join("{:02x}".format(ord(c)) for c in d) -def nat_msc_test(x, ip, verbose = False): +def nat_msc_test(x, ip, port, verbose = False): msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) msc.settimeout(32) - msc.bind((ip, 5000)) + msc.bind((ip, port)) msc.listen(5) if (verbose): print "MSC is ready at " + ip -- cgit v1.2.3 From 84ae27e7314ad1743c8fbdb2feae372122355066 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 10:40:06 -0400 Subject: nat/vty: Convert into str for the VTY command ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 656, in testBSCreload nat_msc_ip(self, ip, port) File "./vty_test_runner.py", line 1096, in nat_msc_ip x.vty.command("msc port " + port) TypeError: cannot concatenate 'str' and 'int' objects ---------------------------------------------------------------------- --- openbsc/tests/vty_test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index a4cfb607f..f56b5764b 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -1093,7 +1093,7 @@ def nat_msc_ip(x, ip, port): x.vty.command("configure terminal") x.vty.command("nat") x.vty.command("msc ip " + ip) - x.vty.command("msc port " + port) + x.vty.command("msc port " + str(port)) x.vty.command("end") def data2str(d): -- cgit v1.2.3 From e98c9c7136e2612cedf87105eafe12fedff1f9a0 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 10:58:58 -0400 Subject: nat/vty: And move to a different port.. --- openbsc/tests/vty_test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index f56b5764b..3c2c233ed 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -630,7 +630,7 @@ class TestVTYNAT(TestVTYGenericBSC): # Use different port for the mock msc to avoid clashing with # the osmo-bsc_nat itself ip = "127.0.0.1" - port = 5001 + port = 5522 self.vty.enable() bscs1 = self.vty.command("show bscs-config") nat_bsc_reload(self) -- cgit v1.2.3 From 2abf2b072d7616ffa760461b6d6bd44a28490066 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 21:13:51 -0400 Subject: nat/vty: Remove second assumption about lo and binding If we want to separate the BSCs we should separate based on the source port and not the source ip (at least in the current test setup). Fixes: ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 658, in testBSCreload b0 = nat_bsc_sock_test(0, "lol") File "./vty_test_runner.py", line 1145, in nat_bsc_sock_test bsc.bind(('127.0.0.1' + str(nr), 0)) File "", line 1, in bind error: [Errno 99] Cannot assign requested address ---------------------------------------------------------------------- --- openbsc/tests/vty_test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 3c2c233ed..a767ff075 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -1142,7 +1142,7 @@ def nat_bsc_num_con(x): def nat_bsc_sock_test(nr, tk, verbose = False): bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - bsc.bind(('127.0.0.1' + str(nr), 0)) + bsc.bind(('127.0.0.1', 0)) bsc.connect(('127.0.0.1', 5000)) if (verbose): print "BSC%d " %nr -- cgit v1.2.3 From 8bb6204d50373ad99b769f8cf42850ae30551c08 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 14 Apr 2016 21:40:04 -0400 Subject: nat/vty: Fix construct not working with python 2.6 Use the simpler approach and just call encode('hex') on the str and then convert it to lower case to keep the tests working. reproduce: Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> d = '\0\0' >>> d '\x00\x00' >>> "".join("{:02x}".format(ord(c)) for c in d) Traceback (most recent call last): File "", line 1, in File "", line 1, in ValueError: zero length field name in format fixes: ====================================================================== ERROR: testBSCreload (__main__.TestVTYNAT) ---------------------------------------------------------------------- Traceback (most recent call last): File "./vty_test_runner.py", line 658, in testBSCreload b0 = nat_bsc_sock_test(0, "lol") File "./vty_test_runner.py", line 1150, in nat_bsc_sock_test ipa_handle_small(bsc, verbose) File "./vty_test_runner.py", line 1116, in ipa_handle_small s = data2str(x.recv(4)) File "./vty_test_runner.py", line 1100, in data2str return "".join("{:02x}".format(ord(c)) for c in d) File "./vty_test_runner.py", line 1100, in return "".join("{:02x}".format(ord(c)) for c in d) ValueError: zero length field name in format ---------------------------------------------------------------------- --- openbsc/tests/vty_test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index a767ff075..143ba5d00 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -1097,7 +1097,7 @@ def nat_msc_ip(x, ip, port): x.vty.command("end") def data2str(d): - return "".join("{:02x}".format(ord(c)) for c in d) + return d.encode('hex').lower() def nat_msc_test(x, ip, port, verbose = False): msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -- 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(-) 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(+) 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 c9ac20ea43e0107c293b5d3f5c90076963e95059 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 14 Apr 2016 15:21:33 +0200 Subject: gbproxy_test: assert msg allocation (CID #57873) --- openbsc/tests/gbproxy/gbproxy_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 0ba827f76..96a68b0e5 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -1293,6 +1293,7 @@ static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, stru } msg = gprs_ns_msgb_alloc(); + OSMO_ASSERT(msg); memmove(msg->data, data, data_len); msg->l2h = msg->data; msgb_put(msg, data_len); -- 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/include/openbsc/rest_octets.h | 3 ++- openbsc/src/libbsc/bsc_init.c | 1 + openbsc/src/libbsc/rest_octets.c | 9 +++++++++ openbsc/src/libbsc/system_information.c | 8 +++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index 963b010c9..9560b14c5 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -43,7 +43,8 @@ struct gsm48_si_ro_info { present:1; } scheduling; struct gsm48_si3_gprs_ind gprs_ind; - + /* SI 3 specific */ + uint8_t si2quater_indicator; /* SI 4 specific */ struct gsm48_lsa_params lsa_params; uint16_t cell_id; 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/include/openbsc/abis_rsl.h | 1 + openbsc/src/libbsc/abis_rsl.c | 2 -- openbsc/src/libbsc/system_information.c | 37 +++++++++++++++++---------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index b27595e4a..100a6d11f 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -31,6 +31,7 @@ struct gsm_lchan; struct gsm_subscriber; struct gsm_bts_trx_ts; +#define GSM48_LEN2PLEN(a) (((a) << 2) | 1) int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data, int len); 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/include/openbsc/gsm_data_shared.h | 5 + openbsc/include/openbsc/rest_octets.h | 5 + 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 + openbsc/tests/gsm0408/Makefile.am | 3 +- openbsc/tests/gsm0408/gsm0408_test.c | 69 +++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 8 ++ 10 files changed, 391 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 000207dd9..cbc0c77f0 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -105,6 +105,7 @@ struct gsm_abis_mo { #define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) +#define MAX_EARFCN_LIST 512 /* is the data link established? who established it? */ #define LCHAN_SAPI_UNUSED 0 @@ -715,12 +716,16 @@ struct gsm_bts { struct bitvec neigh_list; struct bitvec cell_alloc; struct bitvec si5_neigh_list; + struct bitvec si2quater_na_list; + struct osmo_earfcn_si2q si2quater_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ uint8_t neigh_list[1024/8]; uint8_t cell_alloc[1024/8]; /* If the user wants a different neighbor list in SI5 than in SI2 */ uint8_t si5_neigh_list[1024/8]; + uint8_t meas_bw_list[MAX_EARFCN_LIST]; + uint16_t earfcn_list[MAX_EARFCN_LIST]; } data; } si_common; diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index 9560b14c5..fd5ec6a74 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -1,10 +1,15 @@ #ifndef _REST_OCTETS_H #define _REST_OCTETS_H +#include #include +#include /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); +int rest_octets_si2quater(uint8_t *data, + const struct osmo_earfcn_si2q *e, bool uarfcn, + bool earfcn); struct gsm48_si_selection_params { uint16_t penalty_time:5, 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); diff --git a/openbsc/tests/gsm0408/Makefile.am b/openbsc/tests/gsm0408/Makefile.am index 1c29ece12..ee04102bb 100644 --- a/openbsc/tests/gsm0408/Makefile.am +++ b/openbsc/tests/gsm0408/Makefile.am @@ -7,6 +7,7 @@ EXTRA_DIST = gsm0408_test.ok gsm0408_test_SOURCES = gsm0408_test.c gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libtrau/libtrau.a \ $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) -ldbi diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 781ef6147..d6abce61c 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -29,7 +29,11 @@ #include #include #include +#include +#include + #include +#include #define COMPARE(result, op, value) \ if (!((result) op (value))) {\ @@ -79,6 +83,70 @@ static void test_location_area_identifier(void) COMPARE(lai48.lac, ==, htons(0x000f)); } +static inline void add_arfcn_b(struct osmo_earfcn_si2q *e, uint16_t earfcn, + uint8_t bw) +{ + int r = osmo_earfcn_add(e, earfcn, bw); + if (r) + printf("failed to add EARFCN %u: %s\n", earfcn, strerror(r)); + else + printf("added EARFCN %u - ", earfcn); +} + +static inline void gen(struct gsm_bts *bts) +{ + int r = gsm_generate_si(bts, SYSINFO_TYPE_2quater); + if (r > 0) + printf("generated SI2quater: [%d] %s\n", r, + osmo_hexdump(bts->si_buf[SYSINFO_TYPE_2quater], r)); + else + printf("failed to generate SI2quater: %s\n", strerror(-r)); +} + +static inline void test_si2q(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = gsm_network_init(1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater generation:\n"); + + if (!network) + exit(1); + bts = gsm_bts_alloc(network); + + 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 = 5; + + osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1917, 1); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1932, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1937, 2); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1945, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1965, + OSMO_EARFCN_MEAS_INVALID); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1967, 4); + gen(bts); + + add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1982, 3); + gen(bts); +} + static void test_mi_functionality(void) { const char *imsi_odd = "987654321098763"; @@ -486,6 +554,7 @@ int main(int argc, char **argv) test_range_encoding(); test_gsm411_rp_ref_wrap(); + test_si2q(); printf("Done.\n"); return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 058563aab..59319bfeb 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -62,4 +62,12 @@ testing RP-Reference wrap Allocated reference: 255 Allocated reference: 0 Allocated reference: 1 +Testing SYSINFO_TYPE_2quater generation: +added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b +added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b +added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c c8 28 0b 2b 2b 2b +added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b +added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory +added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory Done. -- 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(-) 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 3a434f8e8c63b9340a8daf165c520caa52cba241 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 16 Apr 2016 15:53:58 -0400 Subject: nat/ussd: Add an example of the USSD gateway side-channel This adds a very basic, use once example in python on how to connect and deal with the app specific payload and messages. The code is not complete as the invokeId should be patched according to the initial invoke. This excercise is left to future readers of that code. --- openbsc/contrib/nat/ussd_example.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 openbsc/contrib/nat/ussd_example.py diff --git a/openbsc/contrib/nat/ussd_example.py b/openbsc/contrib/nat/ussd_example.py new file mode 100644 index 000000000..8f7a58d3f --- /dev/null +++ b/openbsc/contrib/nat/ussd_example.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python2.7 + +""" +AGPLv3+ 2016 Copyright Holger Hans Peter Freyther + +Example of how to connect to the USSD side-channel and how to respond +with a fixed message. +""" + +import socket +import struct + +ussdSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +ussdSocket.connect(('127.0.0.1', 5001)) + +def send_dt1(dstref, data): + dlen = struct.pack('B', len(data)).encode('hex') + hex = '06' + dstref.encode('hex') + '00' + '01' + dlen + data.encode('hex') + pdata = hex.decode('hex') + out = struct.pack('>HB', len(pdata), 0xfd) + pdata + ussdSocket.send(out) + +def send_rel(srcref, dstref): + hex = '04' + dstref.encode('hex') + srcref.encode('hex') + '000100' + pdata = hex.decode('hex') + out = struct.pack('>HB', len(pdata), 0xfd) + pdata + ussdSocket.send(out) + +def recv_one(): + plen = ussdSocket.recv(3) + (plen,ptype) = struct.unpack(">HB", plen) + data = ussdSocket.recv(plen) + + return ptype, data + +# Assume this is the ID request +data = ussdSocket.recv(4) +ussdSocket.send("\x00\x08\xfe\x05\x00" + "\x05\x01" + "ussd") +# ^len ^len of tag ... and ignore + +# Expect a fake message. see struct ipac_msgt_sccp_state +ptype, data = recv_one() +print("%d %s" % (ptype, data.encode('hex'))) +(srcref, dstref, transid, invokeid) = struct.unpack("<3s3sBB", data[1:9]) +print("New transID %d invoke %d" % (transid, invokeid)) + +# Expect a the invocation.. todo.. extract invoke id +ptype, data = recv_one() +print("%d %s" % (ptype, data.encode('hex'))) + +# Reply with BSSAP + GSM 04.08 + MAP portion +# 00 == invoke id 0f == DCS +res = "01002a9b2a0802e1901c22a220020100301b02013b301604010f041155e7d2f9bc3a41412894991c06a9c9a713" +send_dt1(dstref, res.decode('hex')) + +clear = "000420040109" +send_dt1(dstref, clear.decode('hex')) + +# should be the clear complete +send_rel(srcref, dstref) + +# Give it some time to handle connection shutdown properly +print("Gracefully sleeping") +import time +time.sleep(3) -- 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(-) 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 ++-- openbsc/tests/vty_test_runner.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) 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; } diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 143ba5d00..7f64a80d3 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -231,6 +231,20 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(self.vty.node(), 'config-mncc-int') + def testSi2Q(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("bts 0") + before = self.vty.command("show running-config") + self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2") + self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3") + self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11") + self.vty.command("si2quater neighbor-list del earfcn 1911") + self.vty.command("si2quater neighbor-list del earfcn 1924") + self.vty.command("si2quater neighbor-list del earfcn 2111") + self.assertEquals(before, self.vty.command("show running-config")) + def testEnableDisablePeriodicLU(self): self.vty.enable() self.vty.command("configure terminal") -- cgit v1.2.3 From 27c3e76aa7e0912d3404b96a4a043e7208044d0f Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 20 Apr 2016 15:57:12 +0200 Subject: Cleanup shared data structure * remove unused variable. * lower max number of (e|u)arfcns to more realistic value. --- openbsc/include/openbsc/gsm_data_shared.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index cbc0c77f0..52e480583 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -105,7 +105,7 @@ struct gsm_abis_mo { #define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) -#define MAX_EARFCN_LIST 512 +#define MAX_EARFCN_LIST 32 /* is the data link established? who established it? */ #define LCHAN_SAPI_UNUSED 0 @@ -716,7 +716,6 @@ struct gsm_bts { struct bitvec neigh_list; struct bitvec cell_alloc; struct bitvec si5_neigh_list; - struct bitvec si2quater_na_list; struct osmo_earfcn_si2q si2quater_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ -- 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/include/openbsc/gsm_data_shared.h | 3 + openbsc/include/openbsc/rest_octets.h | 8 +- openbsc/include/openbsc/system_information.h | 9 +- openbsc/src/libbsc/bsc_vty.c | 53 ++++++++++ openbsc/src/libbsc/rest_octets.c | 91 ++++++++++++++---- openbsc/src/libbsc/system_information.c | 139 ++++++++++++++++++++++++++- openbsc/tests/gsm0408/gsm0408_test.c | 75 +++++++++++---- openbsc/tests/gsm0408/gsm0408_test.ok | 14 ++- openbsc/tests/vty_test_runner.py | 23 +++++ 9 files changed, 369 insertions(+), 46 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 52e480583..8658fe717 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -717,6 +717,7 @@ struct gsm_bts { struct bitvec cell_alloc; struct bitvec si5_neigh_list; struct osmo_earfcn_si2q si2quater_neigh_list; + size_t uarfcn_length; /* index for uarfcn and scramble lists */ struct { /* bitmask large enough for all possible ARFCN's */ uint8_t neigh_list[1024/8]; @@ -725,6 +726,8 @@ struct gsm_bts { uint8_t si5_neigh_list[1024/8]; uint8_t meas_bw_list[MAX_EARFCN_LIST]; uint16_t earfcn_list[MAX_EARFCN_LIST]; + uint16_t uarfcn_list[MAX_EARFCN_LIST]; + uint16_t scramble_list[MAX_EARFCN_LIST]; } data; } si_common; diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h index fd5ec6a74..32b996317 100644 --- a/openbsc/include/openbsc/rest_octets.h +++ b/openbsc/include/openbsc/rest_octets.h @@ -5,11 +5,13 @@ #include #include +#define SI2Q_MAX_LEN 160 +#define SI2Q_MIN_LEN 18 + /* generate SI1 rest octets */ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net); -int rest_octets_si2quater(uint8_t *data, - const struct osmo_earfcn_si2q *e, bool uarfcn, - bool earfcn); +int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e, + const uint16_t *u, const uint16_t *sc, size_t u_len); struct gsm48_si_selection_params { uint16_t penalty_time:5, diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index 6a5684821..ecc696422 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -6,5 +6,12 @@ struct gsm_bts; int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type); - +uint16_t encode_fdd(uint16_t scramble, bool diversity); +unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len); +unsigned earfcn_size(const struct osmo_earfcn_si2q *e); +unsigned range1024_p(unsigned n); +unsigned range512_q(unsigned m); +int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); +int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, + bool diversity); #endif 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; diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index d6abce61c..2d91b68f0 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -103,11 +103,55 @@ static inline void gen(struct gsm_bts *bts) printf("failed to generate SI2quater: %s\n", strerror(-r)); } -static inline void test_si2q(void) +static inline void test_si2q_u(void) { struct gsm_bts *bts; struct gsm_network *network = gsm_network_init(1, 1, NULL); - printf("Testing SYSINFO_TYPE_2quater generation:\n"); + printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n"); + + if (!network) + exit(1); + bts = gsm_bts_alloc(network); + + bts_uarfcn_add(bts, 1982, 13, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 44, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 61, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 89, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 113, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 123, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 56, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 72, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 223, 1); + gen(bts); + + bts_uarfcn_add(bts, 1982, 14, 0); + gen(bts); + + bts_uarfcn_add(bts, 1982, 88, 0); + gen(bts); +} + +static inline void test_si2q_e(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = gsm_network_init(1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n"); if (!network) exit(1); @@ -230,11 +274,7 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, f0, &f0_included); memset(w, 0, sizeof(w)); - rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); - if (rc != 0) { - printf("Cannot compute range W(k), rc = %d\n", rc); - return 1; - } + range_enc_arfcns(range, arfcns, arfcns_used, w, 0); if (!silent) fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", @@ -243,24 +283,20 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, /* Select the range and the amount of bits needed */ switch (range) { case ARFCN_RANGE_128: - rc = range_enc_range128(chan_list, f0, w); + range_enc_range128(chan_list, f0, w); break; case ARFCN_RANGE_256: - rc = range_enc_range256(chan_list, f0, w); + range_enc_range256(chan_list, f0, w); break; case ARFCN_RANGE_512: - rc = range_enc_range512(chan_list, f0, w); + range_enc_range512(chan_list, f0, w); break; case ARFCN_RANGE_1024: - rc = range_enc_range1024(chan_list, f0, f0_included, w); + range_enc_range1024(chan_list, f0, f0_included, w); break; default: return 1; }; - if (rc != 0) { - printf("Cannot encode range, rc = %d\n", rc); - return 1; - } if (!silent) printf("chan_list = %s\n", @@ -471,8 +507,7 @@ static void test_print_encoding() break; } - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); + range_enc_range512(chan_list, (1 << 9) | 0x96, w); printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); } @@ -496,8 +531,7 @@ static void test_si_range_helpers() printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1); VERIFY(i, ==, 0); - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); + range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { printf("w[%d]=%d\n", i, ws[i]); @@ -554,7 +588,8 @@ int main(int argc, char **argv) test_range_encoding(); test_gsm411_rp_ref_wrap(); - test_si2q(); + test_si2q_e(); + test_si2q_u(); printf("Done.\n"); return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 59319bfeb..565eac672 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -62,7 +62,7 @@ testing RP-Reference wrap Allocated reference: 255 Allocated reference: 0 Allocated reference: 1 -Testing SYSINFO_TYPE_2quater generation: +Testing SYSINFO_TYPE_2quater EARFCN generation: added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b @@ -70,4 +70,16 @@ added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1 added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory +Testing SYSINFO_TYPE_2quater UARFCN generation: +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 10 99 64 00 0b 2b 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 14 1a 1f 00 44 b2 00 03 2b 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 18 58 12 f0 84 86 59 00 03 2b 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 20 58 2e f0 f2 04 86 59 00 03 2b 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 28 58 2e 22 f2 4e 84 86 59 00 03 2b 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 00 03 2b 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b +failed to generate SI2quater: Cannot allocate memory +failed to generate SI2quater: Cannot allocate memory Done. diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 7f64a80d3..c0888559e 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -244,6 +244,29 @@ class TestVTYNITB(TestVTYGenericBSC): self.vty.command("si2quater neighbor-list del earfcn 1924") self.vty.command("si2quater neighbor-list del earfcn 2111") self.assertEquals(before, self.vty.command("show running-config")) + self.vty.command("si2quater neighbor-list add uarfcn 1976 13 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 38 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 44 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 120 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 140 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 163 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 166 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 217 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 224 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 225 1") + self.vty.command("si2quater neighbor-list add uarfcn 1976 226 1") + self.vty.command("si2quater neighbor-list del uarfcn 1976 13") + self.vty.command("si2quater neighbor-list del uarfcn 1976 38") + self.vty.command("si2quater neighbor-list del uarfcn 1976 44") + self.vty.command("si2quater neighbor-list del uarfcn 1976 120") + self.vty.command("si2quater neighbor-list del uarfcn 1976 140") + self.vty.command("si2quater neighbor-list del uarfcn 1976 163") + self.vty.command("si2quater neighbor-list del uarfcn 1976 166") + self.vty.command("si2quater neighbor-list del uarfcn 1976 217") + self.vty.command("si2quater neighbor-list del uarfcn 1976 224") + self.vty.command("si2quater neighbor-list del uarfcn 1976 225") + self.vty.command("si2quater neighbor-list del uarfcn 1976 226") + self.assertEquals(before, self.vty.command("show running-config")) def testEnableDisablePeriodicLU(self): self.vty.enable() -- 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/include/openbsc/system_information.h | 1 + openbsc/src/libbsc/bsc_vty.c | 23 +++++++----- openbsc/src/libbsc/system_information.c | 21 ++++++++++- openbsc/tests/gsm0408/gsm0408_test.c | 52 +++++++++++----------------- openbsc/tests/gsm0408/gsm0408_test.ok | 5 +-- 5 files changed, 60 insertions(+), 42 deletions(-) diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index ecc696422..7e3ceaa29 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -11,6 +11,7 @@ unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len); unsigned earfcn_size(const struct osmo_earfcn_si2q *e); unsigned range1024_p(unsigned n); unsigned range512_q(unsigned m); +bool si2q_size_check(const struct gsm_bts *bts); int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity); 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, diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 2d91b68f0..92626670c 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -103,6 +103,16 @@ static inline void gen(struct gsm_bts *bts) printf("failed to generate SI2quater: %s\n", strerror(-r)); } +static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, + uint16_t scramble, bool diversity) +{ + int r = bts_uarfcn_add(bts, arfcn, scramble, diversity); + if (r < 0) + printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r)); + else + gen(bts); +} + static inline void test_si2q_u(void) { struct gsm_bts *bts; @@ -113,37 +123,17 @@ static inline void test_si2q_u(void) exit(1); bts = gsm_bts_alloc(network); - bts_uarfcn_add(bts, 1982, 13, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 44, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 61, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 89, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 113, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 123, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 56, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 72, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 223, 1); - gen(bts); - - bts_uarfcn_add(bts, 1982, 14, 0); - gen(bts); - - bts_uarfcn_add(bts, 1982, 88, 0); + _bts_uarfcn_add(bts, 1982, 13, 1); + _bts_uarfcn_add(bts, 1982, 44, 0); + _bts_uarfcn_add(bts, 1982, 61, 1); + _bts_uarfcn_add(bts, 1982, 89, 1); + _bts_uarfcn_add(bts, 1982, 113, 0); + _bts_uarfcn_add(bts, 1982, 123, 0); + _bts_uarfcn_add(bts, 1982, 56, 1); + _bts_uarfcn_add(bts, 1982, 72, 1); + _bts_uarfcn_add(bts, 1982, 223, 1); + _bts_uarfcn_add(bts, 1982, 14, 0); + _bts_uarfcn_add(bts, 1982, 88, 0); gen(bts); } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 565eac672..7b7a2cc76 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -80,6 +80,7 @@ generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b -failed to generate SI2quater: Cannot allocate memory -failed to generate SI2quater: Cannot allocate memory +failed to add UARFCN to SI2quater: No space left on device +failed to add UARFCN to SI2quater: No space left on device +generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b Done. -- 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(-) 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(+) 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(-) 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(-) 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(-) 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/include/openbsc/gprs_gsup_messages.h | 4 +-- openbsc/include/openbsc/gsm_data.h | 5 ++-- 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 ++-- openbsc/tests/mm_auth/mm_auth_test.c | 6 ++-- openbsc/tests/sgsn/sgsn_test.c | 2 +- 12 files changed, 69 insertions(+), 70 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index 8cbc809f7..66a75a801 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -104,8 +104,8 @@ struct gprs_gsup_message { enum gprs_gsup_cancel_type cancel_type; int pdp_info_compl; int freeze_ptmsi; - struct gsm_auth_tuple auth_tuples[GPRS_GSUP_MAX_NUM_AUTH_INFO]; - size_t num_auth_tuples; + struct osmo_auth_vector auth_vectors[GPRS_GSUP_MAX_NUM_AUTH_INFO]; + size_t num_auth_vectors; struct gprs_gsup_pdp_info pdp_infos[GPRS_GSUP_MAX_NUM_PDP_INFO]; size_t num_pdp_infos; const uint8_t *msisdn_enc; diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6d7aba358..f229e7499 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -5,6 +5,7 @@ #include #include +#include #include @@ -47,9 +48,7 @@ struct gsm_auth_info { struct gsm_auth_tuple { int use_count; int key_seq; - uint8_t rand[16]; - uint8_t sres[4]; - uint8_t kc[8]; + struct osmo_auth_vector vec; }; #define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */ 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); } diff --git a/openbsc/tests/mm_auth/mm_auth_test.c b/openbsc/tests/mm_auth/mm_auth_test.c index 34d96f187..b8777a8c5 100644 --- a/openbsc/tests/mm_auth/mm_auth_test.c +++ b/openbsc/tests/mm_auth/mm_auth_test.c @@ -26,9 +26,9 @@ static char *auth_tuple_str(struct gsm_auth_tuple *atuple) print2buf("gsm_auth_tuple {\n"); print2buf(" .use_count = %d\n", atuple->use_count); print2buf(" .key_seq = %d\n", atuple->key_seq); - print2buf(" .rand = %s\n", osmo_hexdump(atuple->rand, sizeof(atuple->rand))); - print2buf(" .sres = %s\n", osmo_hexdump(atuple->sres, sizeof(atuple->sres))); - print2buf(" .kc = %s\n", osmo_hexdump(atuple->kc, sizeof(atuple->kc))); + print2buf(" .rand = %s\n", osmo_hexdump(atuple->vec.rand, sizeof(atuple->vec.rand))); + print2buf(" .sres = %s\n", osmo_hexdump(atuple->vec.sres, sizeof(atuple->vec.sres))); + print2buf(" .kc = %s\n", osmo_hexdump(atuple->vec.kc, sizeof(atuple->vec.kc))); print2buf("}\n"); #undef print2buf diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 1acd6f2f8..fe41e759b 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -1132,7 +1132,7 @@ static void test_gmm_attach_subscr_fake_auth(void) int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx) { struct gsm_auth_tuple at = { - .sres = {0x51, 0xe5, 0x51, 0xe5}, + .vec.sres = {0x51, 0xe5, 0x51, 0xe5}, .key_seq = 0 }; -- 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/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/gprs_gsup_messages.h | 3 +- openbsc/include/openbsc/gsm_04_08_gprs.h | 397 --------------------------- openbsc/include/openbsc/oap_messages.h | 2 +- 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 +- openbsc/tests/gbproxy/gbproxy_test.c | 2 +- openbsc/tests/oap/Makefile.am | 1 - openbsc/tests/sgsn/Makefile.am | 1 - openbsc/tests/sgsn/sgsn_test.c | 1 - 21 files changed, 14 insertions(+), 557 deletions(-) delete mode 100644 openbsc/include/openbsc/gsm_04_08_gprs.h delete mode 100644 openbsc/src/gprs/gsm_04_08_gprs.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index d42f775d9..631a74e5e 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -8,7 +8,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ vty.h socket.h e1_config.h trau_upqueue.h token_auth.h \ handover_decision.h rrlp.h \ crc24.h gprs_llc.h gprs_gmm.h \ - gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \ + gb_proxy.h gprs_sgsn.h sgsn.h \ auth.h osmo_msc.h bsc_msc.h bsc_nat.h \ osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h \ osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \ diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index 66a75a801..c4e97570c 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -22,8 +22,7 @@ #pragma once #include -#include -#include +#include /* Needed for GSM_IMSI_LENGTH: */ #include diff --git a/openbsc/include/openbsc/gsm_04_08_gprs.h b/openbsc/include/openbsc/gsm_04_08_gprs.h deleted file mode 100644 index f35d11b60..000000000 --- a/openbsc/include/openbsc/gsm_04_08_gprs.h +++ /dev/null @@ -1,397 +0,0 @@ -#ifndef _GSM48_GPRS_H -#define _GSM48_GPRS_H - -#include -#include - -/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */ -#define GSM48_MT_GMM_ATTACH_REQ 0x01 -#define GSM48_MT_GMM_ATTACH_ACK 0x02 -#define GSM48_MT_GMM_ATTACH_COMPL 0x03 -#define GSM48_MT_GMM_ATTACH_REJ 0x04 -#define GSM48_MT_GMM_DETACH_REQ 0x05 -#define GSM48_MT_GMM_DETACH_ACK 0x06 - -#define GSM48_MT_GMM_RA_UPD_REQ 0x08 -#define GSM48_MT_GMM_RA_UPD_ACK 0x09 -#define GSM48_MT_GMM_RA_UPD_COMPL 0x0a -#define GSM48_MT_GMM_RA_UPD_REJ 0x0b - -#define GSM48_MT_GMM_PTMSI_REALL_CMD 0x10 -#define GSM48_MT_GMM_PTMSI_REALL_COMPL 0x11 -#define GSM48_MT_GMM_AUTH_CIPH_REQ 0x12 -#define GSM48_MT_GMM_AUTH_CIPH_RESP 0x13 -#define GSM48_MT_GMM_AUTH_CIPH_REJ 0x14 -#define GSM48_MT_GMM_ID_REQ 0x15 -#define GSM48_MT_GMM_ID_RESP 0x16 -#define GSM48_MT_GMM_STATUS 0x20 -#define GSM48_MT_GMM_INFO 0x21 - -/* Table 10.4a, GPRS Session Management (GSM) */ -#define GSM48_MT_GSM_ACT_PDP_REQ 0x41 -#define GSM48_MT_GSM_ACT_PDP_ACK 0x42 -#define GSM48_MT_GSM_ACT_PDP_REJ 0x43 -#define GSM48_MT_GSM_REQ_PDP_ACT 0x44 -#define GSM48_MT_GSM_REQ_PDP_ACT_REJ 0x45 -#define GSM48_MT_GSM_DEACT_PDP_REQ 0x46 -#define GSM48_MT_GSM_DEACT_PDP_ACK 0x47 -#define GSM48_MT_GSM_ACT_AA_PDP_REQ 0x50 -#define GSM48_MT_GSM_ACT_AA_PDP_ACK 0x51 -#define GSM48_MT_GSM_ACT_AA_PDP_REJ 0x52 -#define GSM48_MT_GSM_DEACT_AA_PDP_REQ 0x53 -#define GSM48_MT_GSM_DEACT_AA_PDP_ACK 0x54 -#define GSM48_MT_GSM_STATUS 0x55 - -/* Chapter 10.5.5.2 / Table 10.5.135 */ -#define GPRS_ATT_T_ATTACH 1 -#define GPRS_ATT_T_ATT_WHILE_IMSI 2 -#define GPRS_ATT_T_COMBINED 3 - -extern const struct value_string *gprs_att_t_strs; - -/* Chapter 10.5.5.5 / Table 10.5.138 */ -#define GPRS_DET_T_MO_GPRS 1 -#define GPRS_DET_T_MO_IMSI 2 -#define GPRS_DET_T_MO_COMBINED 3 -/* Network to MS direction */ -#define GPRS_DET_T_MT_REATT_REQ 1 -#define GPRS_DET_T_MT_REATT_NOTREQ 2 -#define GPRS_DET_T_MT_IMSI 3 - -extern const struct value_string *gprs_det_t_mo_strs; -extern const struct value_string *gprs_det_t_mt_strs; - -/* Chapter 10.5.5.18 / Table 105.150 */ -#define GPRS_UPD_T_RA 0 -#define GPRS_UPD_T_RA_LA 1 -#define GPRS_UPD_T_RA_LA_IMSI_ATT 2 -#define GPRS_UPD_T_PERIODIC 3 - -extern const struct value_string *gprs_upd_t_strs; - -enum gsm48_gprs_ie_mm { - GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */ - GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */ - GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */ - GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */ - GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */ - GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */ - GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */ - GSM48_IE_GMM_CAUSE = 0x25, /* 10.5.5.14 */ - GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */ - GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */ - GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */ - GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */ - GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */ -}; - -enum gsm48_gprs_ie_sm { - GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */ - GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */ - GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */ - GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */ - GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */ - GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */ - GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */ - GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */ - GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */ - - /* Fake IEs that are not present on the Layer3 air interface, - * but which we use to simplify internal APIs */ - OSMO_IE_GSM_REQ_QOS = 0xfd, - OSMO_IE_GSM_REQ_PDP_ADDR = 0xfe, - OSMO_IE_GSM_SUB_QOS = 0xff, -}; - -/* Chapter 9.4.15 / Table 9.4.15 */ -struct gsm48_ra_upd_ack { - uint8_t force_stby:4, /* 10.5.5.7 */ - upd_result:4; /* 10.5.5.17 */ - uint8_t ra_upd_timer; /* 10.5.7.3 */ - struct gsm48_ra_id ra_id; /* 10.5.5.15 */ - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 10.5.7.3 */ -enum gsm48_gprs_tmr_unit { - GPRS_TMR_2SECONDS = 0 << 5, - GPRS_TMR_MINUTE = 1 << 5, - GPRS_TMR_6MINUTE = 2 << 5, - GPRS_TMR_DEACTIVATED = 7 << 5, -}; - -#define GPRS_TMR_UNIT_MASK (7 << 5) -#define GPRS_TMR_FACT_MASK ((1 << 5)-1) - -/* Chapter 9.4.2 / Table 9.4.2 */ -struct gsm48_attach_ack { - uint8_t att_result:4, /* 10.5.5.7 */ - force_stby:4; /* 10.5.5.1 */ - uint8_t ra_upd_timer; /* 10.5.7.3 */ - uint8_t radio_prio; /* 10.5.7.2 */ - struct gsm48_ra_id ra_id; /* 10.5.5.15 */ - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 9.4.9 / Table 9.4.9 */ -struct gsm48_auth_ciph_req { - uint8_t ciph_alg:4, /* 10.5.5.3 */ - imeisv_req:4; /* 10.5.5.10 */ - uint8_t force_stby:4, /* 10.5.5.7 */ - ac_ref_nr:4; /* 10.5.5.19 */ - uint8_t data[0]; -} __attribute__((packed)); -/* optional: TV RAND, TV CKSN */ - -struct gsm48_auth_ciph_resp { - uint8_t ac_ref_nr:4, - spare:4; - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 9.5.1 / Table 9.5.1 */ -struct gsm48_act_pdp_ctx_req { - uint8_t req_nsapi; - uint8_t req_llc_sapi; - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 10.5.5.14 / Table 10.5.147 */ -enum gsm48_gmm_cause { - GMM_CAUSE_IMSI_UNKNOWN = 0x02, - GMM_CAUSE_ILLEGAL_MS = 0x03, - GMM_CAUSE_ILLEGAL_ME = 0x06, - GMM_CAUSE_GPRS_NOTALLOWED = 0x07, - GMM_CAUSE_GPRS_OTHER_NOTALLOWED = 0x08, - GMM_CAUSE_MS_ID_NOT_DERIVED = 0x09, - GMM_CAUSE_IMPL_DETACHED = 0x0a, - GMM_CAUSE_PLMN_NOTALLOWED = 0x0b, - GMM_CAUSE_LA_NOTALLOWED = 0x0c, - GMM_CAUSE_ROAMING_NOTALLOWED = 0x0d, - GMM_CAUSE_NO_GPRS_PLMN = 0x0e, - GMM_CAUSE_MSC_TEMP_NOTREACH = 0x10, - GMM_CAUSE_NET_FAIL = 0x11, - GMM_CAUSE_CONGESTION = 0x16, - GMM_CAUSE_SEM_INCORR_MSG = 0x5f, - GMM_CAUSE_INV_MAND_INFO = 0x60, - GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61, - GMM_CAUSE_MSGT_INCOMP_P_STATE = 0x62, - GMM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63, - GMM_CAUSE_COND_IE_ERR = 0x64, - GMM_CAUSE_MSG_INCOMP_P_STATE = 0x65, - GMM_CAUSE_PROTO_ERR_UNSPEC = 0x6f, -}; - -extern const struct value_string *gsm48_gmm_cause_names; - -/* Chapter 10.4.6.6 / Table 10.5.157 */ -enum gsm48_gsm_cause { - GSM_CAUSE_INSUFF_RSRC = 0x1a, - GSM_CAUSE_MISSING_APN = 0x1b, - GSM_CAUSE_UNKNOWN_PDP = 0x1c, - GSM_CAUSE_AUTH_FAILED = 0x1d, - GSM_CAUSE_ACT_REJ_GGSN = 0x1e, - GSM_CAUSE_ACT_REJ_UNSPEC = 0x1f, - GSM_CAUSE_SERV_OPT_NOTSUPP = 0x20, - GSM_CAUSE_REQ_SERV_OPT_NOTSUB = 0x21, - GSM_CAUSE_SERV_OPT_TEMP_OOO = 0x22, - GSM_CAUSE_NSAPI_IN_USE = 0x23, - GSM_CAUSE_DEACT_REGULAR = 0x24, - GSM_CAUSE_QOS_NOT_ACCEPTED = 0x25, - GSM_CAUSE_NET_FAIL = 0x26, - GSM_CAUSE_REACT_RQD = 0x27, - GSM_CAUSE_FEATURE_NOTSUPP = 0x28, - GSM_CAUSE_INVALID_TRANS_ID = 0x51, - GSM_CAUSE_SEM_INCORR_MSG = 0x5f, - GSM_CAUSE_INV_MAND_INFO = 0x60, - GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61, - GSM_CAUSE_MSGT_INCOMP_P_STATE = 0x62, - GSM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63, - GSM_CAUSE_COND_IE_ERR = 0x64, - GSM_CAUSE_MSG_INCOMP_P_STATE = 0x65, - GSM_CAUSE_PROTO_ERR_UNSPEC = 0x6f, -}; - -extern const struct value_string *gsm48_gsm_cause_names; - -/* Section 6.1.2.2: Session management states on the network side */ -enum gsm48_pdp_state { - PDP_S_INACTIVE, - PDP_S_ACTIVE_PENDING, - PDP_S_ACTIVE, - PDP_S_INACTIVE_PENDING, - PDP_S_MODIFY_PENDING, -}; - -/* Table 10.5.155/3GPP TS 24.008 */ -enum gsm48_pdp_type_org { - PDP_TYPE_ORG_ETSI = 0x00, - PDP_TYPE_ORG_IETF = 0x01, -}; -enum gsm48_pdp_type_nr { - PDP_TYPE_N_ETSI_RESERVED = 0x00, - PDP_TYPE_N_ETSI_PPP = 0x01, - PDP_TYPE_N_IETF_IPv4 = 0x21, - PDP_TYPE_N_IETF_IPv6 = 0x57, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_reliab_class { - GSM48_QOS_RC_LLC_ACK_RLC_ACK_DATA_PROT = 2, - GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT = 3, - GSM48_QOS_RC_LLC_UN_RLC_UN_PROT_DATA = 4, - GSM48_QOS_RC_LLC_UN_RLC_UN_DATA_UN = 5, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_preced_class { - GSM48_QOS_PC_HIGH = 1, - GSM48_QOS_PC_NORMAL = 2, - GSM48_QOS_PC_LOW = 3, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_peak_tput { - GSM48_QOS_PEAK_TPUT_1000bps = 1, - GSM48_QOS_PEAK_TPUT_2000bps = 2, - GSM48_QOS_PEAK_TPUT_4000bps = 3, - GSM48_QOS_PEAK_TPUT_8000bps = 4, - GSM48_QOS_PEAK_TPUT_16000bps = 5, - GSM48_QOS_PEAK_TPUT_32000bps = 6, - GSM48_QOS_PEAK_TPUT_64000bps = 7, - GSM48_QOS_PEAK_TPUT_128000bps = 8, - GSM48_QOS_PEAK_TPUT_256000bps = 9, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_mean_tput { - GSM48_QOS_MEAN_TPUT_100bph = 1, - GSM48_QOS_MEAN_TPUT_200bph = 2, - GSM48_QOS_MEAN_TPUT_500bph = 3, - GSM48_QOS_MEAN_TPUT_1000bph = 4, - GSM48_QOS_MEAN_TPUT_2000bph = 5, - GSM48_QOS_MEAN_TPUT_5000bph = 6, - GSM48_QOS_MEAN_TPUT_10000bph = 7, - GSM48_QOS_MEAN_TPUT_20000bph = 8, - GSM48_QOS_MEAN_TPUT_50000bph = 9, - GSM48_QOS_MEAN_TPUT_100kbph = 10, - GSM48_QOS_MEAN_TPUT_200kbph = 11, - GSM48_QOS_MEAN_TPUT_500kbph = 0xc, - GSM48_QOS_MEAN_TPUT_1Mbph = 0xd, - GSM48_QOS_MEAN_TPUT_2Mbph = 0xe, - GSM48_QOS_MEAN_TPUT_5Mbph = 0xf, - GSM48_QOS_MEAN_TPUT_10Mbph = 0x10, - GSM48_QOS_MEAN_TPUT_20Mbph = 0x11, - GSM48_QOS_MEAN_TPUT_50Mbph = 0x12, - GSM48_QOS_MEAN_TPUT_BEST_EFFORT = 0x1f, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_err_sdu { - GSM48_QOS_ERRSDU_NODETECT = 1, - GSM48_QOS_ERRSDU_YES = 2, - GSM48_QOS_ERRSDU_NO = 3, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_deliv_order { - GSM48_QOS_DO_ORDERED = 1, - GSM48_QOS_DO_UNORDERED = 2, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_traf_class { - GSM48_QOS_TC_CONVERSATIONAL = 1, - GSM48_QOS_TC_STREAMING = 2, - GSM48_QOS_TC_INTERACTIVE = 3, - GSM48_QOS_TC_BACKGROUND = 4, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_max_sdu_size { - /* values below in 10 octet granularity */ - GSM48_QOS_MAXSDU_1502 = 0x97, - GSM48_QOS_MAXSDU_1510 = 0x98, - GSM48_QOS_MAXSDU_1520 = 0x99, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_max_bitrate { - GSM48_QOS_MBRATE_1k = 0x01, - GSM48_QOS_MBRATE_63k = 0x3f, - GSM48_QOS_MBRATE_64k = 0x40, - GSM48_QOS_MBRATE_568k = 0x7f, - GSM48_QOS_MBRATE_576k = 0x80, - GSM48_QOS_MBRATE_8640k = 0xfe, - GSM48_QOS_MBRATE_0k = 0xff, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_resid_ber { - GSM48_QOS_RBER_5e_2 = 0x01, - GSM48_QOS_RBER_1e_2 = 0x02, - GSM48_QOS_RBER_5e_3 = 0x03, - GSM48_QOS_RBER_4e_3 = 0x04, - GSM48_QOS_RBER_1e_3 = 0x05, - GSM48_QOS_RBER_1e_4 = 0x06, - GSM48_QOS_RBER_1e_5 = 0x07, - GSM48_QOS_RBER_1e_6 = 0x08, - GSM48_QOS_RBER_6e_8 = 0x09, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -enum gsm48_qos_sdu_err { - GSM48_QOS_SERR_1e_2 = 0x01, - GSM48_QOS_SERR_7e_2 = 0x02, - GSM48_QOS_SERR_1e_3 = 0x03, - GSM48_QOS_SERR_1e_4 = 0x04, - GSM48_QOS_SERR_1e_5 = 0x05, - GSM48_QOS_SERR_1e_6 = 0x06, - GSM48_QOS_SERR_1e_1 = 0x07, -}; - -/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ -struct gsm48_qos { - /* octet 3 */ - uint8_t reliab_class:3; - uint8_t delay_class:3; - uint8_t spare:2; - /* octet 4 */ - uint8_t preced_class:3; - uint8_t spare2:1; - uint8_t peak_tput:4; - /* octet 5 */ - uint8_t mean_tput:5; - uint8_t spare3:3; - /* octet 6 */ - uint8_t deliv_err_sdu:3; - uint8_t deliv_order:2; - uint8_t traf_class:3; - /* octet 7 */ - uint8_t max_sdu_size; - /* octet 8 */ - uint8_t max_bitrate_up; - /* octet 9 */ - uint8_t max_bitrate_down; - /* octet 10 */ - uint8_t sdu_err_ratio:4; - uint8_t resid_ber:4; - /* octet 11 */ - uint8_t handling_prio:2; - uint8_t xfer_delay:6; - /* octet 12 */ - uint8_t guar_bitrate_up; - /* octet 13 */ - uint8_t guar_bitrate_down; - /* octet 14 */ - uint8_t src_stats_desc:4; - uint8_t sig_ind:1; - uint8_t spare5:3; - /* octet 15 */ - uint8_t max_bitrate_down_ext; - /* octet 16 */ - uint8_t guar_bitrate_down_ext; -}; - - -#endif /* _GSM48_GPRS_H */ diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h index a7a254c2e..b7f4ccada 100644 --- a/openbsc/include/openbsc/oap_messages.h +++ b/openbsc/include/openbsc/oap_messages.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include /* Some numbers are out of sequence because (so far) they match gprs_gsup_iei. 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 diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 96a68b0e5..a2ff95b1d 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/openbsc/tests/oap/Makefile.am b/openbsc/tests/oap/Makefile.am index 3a76b11ad..538e1787e 100644 --- a/openbsc/tests/oap/Makefile.am +++ b/openbsc/tests/oap/Makefile.am @@ -15,7 +15,6 @@ oap_test_LDADD = \ $(top_builddir)/src/gprs/oap.o \ $(top_builddir)/src/gprs/oap_messages.o \ $(top_builddir)/src/gprs/gprs_utils.o \ - $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index d432fb139..aebcf0105 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -27,7 +27,6 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/gprs_gsup_client.o \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ - $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ $(top_builddir)/src/gprs/gprs_gb_parse.o \ $(top_builddir)/src/gprs/oap.o \ $(top_builddir)/src/gprs/oap_messages.o \ diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index fe41e759b..94c277f55 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -32,7 +32,6 @@ #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/include/openbsc/gprs_gsup_messages.h | 7 ++++--- openbsc/include/openbsc/gprs_sgsn.h | 7 +++---- openbsc/include/openbsc/gsm_subscriber.h | 7 +++---- openbsc/include/openbsc/ipaccess.h | 3 ++- 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 +- openbsc/tests/gtphub/gtphub_test.c | 2 +- 12 files changed, 25 insertions(+), 22 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h index c4e97570c..fe8bef555 100644 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ b/openbsc/include/openbsc/gprs_gsup_messages.h @@ -22,9 +22,10 @@ #pragma once #include +#include +#include #include -/* Needed for GSM_IMSI_LENGTH: */ -#include +#include #define GPRS_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ #define GPRS_GSUP_MAX_NUM_AUTH_INFO 5 @@ -98,7 +99,7 @@ struct gprs_gsup_pdp_info { struct gprs_gsup_message { enum gprs_gsup_message_type message_type; - char imsi[GSM_IMSI_LENGTH]; + char imsi[GSM23003_IMSI_MAX_DIGITS+2]; enum gsm48_gmm_cause cause; enum gprs_gsup_cancel_type cancel_type; int pdp_info_compl; diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h index 49d5407f5..898b7a514 100644 --- a/openbsc/include/openbsc/gprs_sgsn.h +++ b/openbsc/include/openbsc/gprs_sgsn.h @@ -9,11 +9,10 @@ #include #include +#include #include -#define GSM_IMSI_LENGTH 17 -#define GSM_IMEI_LENGTH 17 #define GSM_EXTENSION_LENGTH 15 #define GSM_APN_LENGTH 102 @@ -98,12 +97,12 @@ struct sgsn_ggsn_lookup { struct sgsn_mm_ctx { struct llist_head list; - char imsi[GSM_IMSI_LENGTH]; + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; enum gprs_mm_state mm_state; uint32_t p_tmsi; uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */ uint32_t p_tmsi_sig; - char imei[GSM_IMEI_LENGTH]; + char imei[GSM23003_IMEISV_NUM_DIGITS+1]; /* Opt: Software Version Numbber / TS 23.195 */ char msisdn[GSM_EXTENSION_LENGTH]; struct gprs_ra_id ra; diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 7d6c776bc..9df989a79 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -3,9 +3,8 @@ #include "gsm_data.h" #include +#include -#define GSM_IMEI_LENGTH 17 -#define GSM_IMSI_LENGTH 17 #define GSM_NAME_LENGTH 160 #define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */ @@ -32,7 +31,7 @@ struct gsm_subscriber_group { struct gsm_equipment { long long unsigned int id; - char imei[GSM_IMEI_LENGTH]; + char imei[GSM23003_IMEISV_NUM_DIGITS+1]; char name[GSM_NAME_LENGTH]; struct gsm48_classmark1 classmark1; @@ -45,7 +44,7 @@ struct gsm_equipment { struct gsm_subscriber { struct gsm_subscriber_group *group; long long unsigned int id; - char imsi[GSM_IMSI_LENGTH]; + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; uint32_t tmsi; uint16_t lac; char name[GSM_NAME_LENGTH]; diff --git a/openbsc/include/openbsc/ipaccess.h b/openbsc/include/openbsc/ipaccess.h index 38151c477..82e89c27d 100644 --- a/openbsc/include/openbsc/ipaccess.h +++ b/openbsc/include/openbsc/ipaccess.h @@ -5,13 +5,14 @@ #include "gsm_subscriber.h" #include #include +#include struct ipac_msgt_sccp_state { uint8_t src_ref[3]; uint8_t dst_ref[3]; uint8_t trans_id; uint8_t invoke_id; - char imsi[GSM_IMSI_LENGTH]; + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; uint8_t data[0]; } __attribute__((packed)); 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); diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c index 8ce83c82e..e24967b85 100644 --- a/openbsc/tests/gtphub/gtphub_test.c +++ b/openbsc/tests/gtphub/gtphub_test.c @@ -388,7 +388,7 @@ static void test_expiry(void) #undef MAP3 } -char resolve_ggsn_got_imsi[GSM_IMSI_LENGTH]; +char resolve_ggsn_got_imsi[GSM23003_IMSI_MAX_DIGITS+1]; char resolve_ggsn_got_ni[GSM_APN_LENGTH]; struct osmo_sockaddr resolved_ggsn_addr; -- 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/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/gprs_gsup_messages.h | 119 -------- openbsc/include/openbsc/osmo_gsup_messages.h | 120 ++++++++ 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 +++++++++++++++++++++++++++ 7 files changed, 584 insertions(+), 583 deletions(-) delete mode 100644 openbsc/include/openbsc/gprs_gsup_messages.h create mode 100644 openbsc/include/openbsc/osmo_gsup_messages.h delete mode 100644 openbsc/src/gprs/gprs_gsup_messages.c create mode 100644 openbsc/src/gprs/osmo_gsup_messages.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 631a74e5e..8a31fe5a9 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -15,7 +15,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ bss.h gsm_data_shared.h ipaccess.h mncc_int.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h utils.h \ - gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ + gprs_gb_parse.h smpp.h meas_feed.h osmo_gsup_messages.h \ gprs_gsup_client.h bsc_msg_filter.h \ oap.h oap_messages.h \ gtphub.h diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h deleted file mode 100644 index fe8bef555..000000000 --- a/openbsc/include/openbsc/gprs_gsup_messages.h +++ /dev/null @@ -1,119 +0,0 @@ -/* GPRS Subscriber Update Protocol message encoder/decoder */ - -/* (C) 2014 by Sysmocom s.f.m.c. GmbH - * 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 . - * - */ -#pragma once - -#include -#include -#include -#include -#include - -#define GPRS_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ -#define GPRS_GSUP_MAX_NUM_AUTH_INFO 5 -#define GPRS_GSUP_MAX_MSISDN_LEN 9 - -#define GPRS_GSUP_PDP_TYPE_SIZE 2 - -enum gprs_gsup_iei { - GPRS_GSUP_IMSI_IE = 0x01, - GPRS_GSUP_CAUSE_IE = 0x02, - GPRS_GSUP_AUTH_TUPLE_IE = 0x03, - GPRS_GSUP_PDP_INFO_COMPL_IE = 0x04, - GPRS_GSUP_PDP_INFO_IE = 0x05, - GPRS_GSUP_CANCEL_TYPE_IE = 0x06, - GPRS_GSUP_FREEZE_PTMSI_IE = 0x07, - GPRS_GSUP_MSISDN_IE = 0x08, - GPRS_GSUP_HLR_NUMBER_IE = 0x09, - GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10, - GPRS_GSUP_PDP_TYPE_IE = 0x11, - GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12, - GPRS_GSUP_PDP_QOS_IE = 0x13, - GPRS_GSUP_RAND_IE = 0x20, - GPRS_GSUP_SRES_IE = 0x21, - GPRS_GSUP_KC_IE = 0x22 -}; - -enum gprs_gsup_message_type { - GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, - GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, - GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110, - - GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST = 0b00001000, - GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR = 0b00001001, - GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT = 0b00001010, - - GPRS_GSUP_MSGT_PURGE_MS_REQUEST = 0b00001100, - GPRS_GSUP_MSGT_PURGE_MS_ERROR = 0b00001101, - GPRS_GSUP_MSGT_PURGE_MS_RESULT = 0b00001110, - - GPRS_GSUP_MSGT_INSERT_DATA_REQUEST = 0b00010000, - GPRS_GSUP_MSGT_INSERT_DATA_ERROR = 0b00010001, - GPRS_GSUP_MSGT_INSERT_DATA_RESULT = 0b00010010, - - GPRS_GSUP_MSGT_DELETE_DATA_REQUEST = 0b00010100, - GPRS_GSUP_MSGT_DELETE_DATA_ERROR = 0b00010101, - GPRS_GSUP_MSGT_DELETE_DATA_RESULT = 0b00010110, - - GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST = 0b00011100, - GPRS_GSUP_MSGT_LOCATION_CANCEL_ERROR = 0b00011101, - GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT = 0b00011110, -}; - -#define GPRS_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00) -#define GPRS_GSUP_IS_MSGT_ERROR(msgt) (((msgt) & 0b00000011) == 0b01) -#define GPRS_GSUP_TO_MSGT_ERROR(msgt) (((msgt) & 0b11111100) | 0b01) - -enum gprs_gsup_cancel_type { - GPRS_GSUP_CANCEL_TYPE_UPDATE = 1, /* on wire: 0 */ - GPRS_GSUP_CANCEL_TYPE_WITHDRAW = 2, /* on wire: 1 */ -}; - -struct gprs_gsup_pdp_info { - unsigned int context_id; - int have_info; - uint16_t pdp_type; - const uint8_t *apn_enc; - size_t apn_enc_len; - const uint8_t *qos_enc; - size_t qos_enc_len; -}; - -struct gprs_gsup_message { - enum gprs_gsup_message_type message_type; - char imsi[GSM23003_IMSI_MAX_DIGITS+2]; - enum gsm48_gmm_cause cause; - enum gprs_gsup_cancel_type cancel_type; - int pdp_info_compl; - int freeze_ptmsi; - struct osmo_auth_vector auth_vectors[GPRS_GSUP_MAX_NUM_AUTH_INFO]; - size_t num_auth_vectors; - struct gprs_gsup_pdp_info pdp_infos[GPRS_GSUP_MAX_NUM_PDP_INFO]; - size_t num_pdp_infos; - const uint8_t *msisdn_enc; - size_t msisdn_enc_len; - const uint8_t *hlr_enc; - size_t hlr_enc_len; -}; - -int gprs_gsup_decode(const uint8_t *data, size_t data_len, - struct gprs_gsup_message *gsup_msg); -void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg); diff --git a/openbsc/include/openbsc/osmo_gsup_messages.h b/openbsc/include/openbsc/osmo_gsup_messages.h new file mode 100644 index 000000000..bdc46aaee --- /dev/null +++ b/openbsc/include/openbsc/osmo_gsup_messages.h @@ -0,0 +1,120 @@ +/* Osmocom Subscriber Update Protocol message encoder/decoder */ + +/* (C) 2014 by Sysmocom s.f.m.c. GmbH + * (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 . + * + */ +#pragma once + +#include +#include +#include +#include +#include + +#define OSMO_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ +#define OSMO_GSUP_MAX_NUM_AUTH_INFO 5 +#define OSMO_GSUP_MAX_MSISDN_LEN 9 + +#define OSMO_GSUP_PDP_TYPE_SIZE 2 + +enum osmo_gsup_iei { + OSMO_GSUP_IMSI_IE = 0x01, + OSMO_GSUP_CAUSE_IE = 0x02, + OSMO_GSUP_AUTH_TUPLE_IE = 0x03, + OSMO_GSUP_PDP_INFO_COMPL_IE = 0x04, + OSMO_GSUP_PDP_INFO_IE = 0x05, + OSMO_GSUP_CANCEL_TYPE_IE = 0x06, + OSMO_GSUP_FREEZE_PTMSI_IE = 0x07, + OSMO_GSUP_MSISDN_IE = 0x08, + OSMO_GSUP_HLR_NUMBER_IE = 0x09, + OSMO_GSUP_PDP_CONTEXT_ID_IE = 0x10, + OSMO_GSUP_PDP_TYPE_IE = 0x11, + OSMO_GSUP_ACCESS_POINT_NAME_IE = 0x12, + OSMO_GSUP_PDP_QOS_IE = 0x13, + OSMO_GSUP_RAND_IE = 0x20, + OSMO_GSUP_SRES_IE = 0x21, + OSMO_GSUP_KC_IE = 0x22, +}; + +enum osmo_gsup_message_type { + OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, + OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, + OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110, + + OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST = 0b00001000, + OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR = 0b00001001, + OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT = 0b00001010, + + OSMO_GSUP_MSGT_PURGE_MS_REQUEST = 0b00001100, + OSMO_GSUP_MSGT_PURGE_MS_ERROR = 0b00001101, + OSMO_GSUP_MSGT_PURGE_MS_RESULT = 0b00001110, + + OSMO_GSUP_MSGT_INSERT_DATA_REQUEST = 0b00010000, + OSMO_GSUP_MSGT_INSERT_DATA_ERROR = 0b00010001, + OSMO_GSUP_MSGT_INSERT_DATA_RESULT = 0b00010010, + + OSMO_GSUP_MSGT_DELETE_DATA_REQUEST = 0b00010100, + OSMO_GSUP_MSGT_DELETE_DATA_ERROR = 0b00010101, + OSMO_GSUP_MSGT_DELETE_DATA_RESULT = 0b00010110, + + OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST = 0b00011100, + OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR = 0b00011101, + OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT = 0b00011110, +}; + +#define OSMO_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00) +#define OSMO_GSUP_IS_MSGT_ERROR(msgt) (((msgt) & 0b00000011) == 0b01) +#define OSMO_GSUP_TO_MSGT_ERROR(msgt) (((msgt) & 0b11111100) | 0b01) + +enum osmo_gsup_cancel_type { + OSMO_GSUP_CANCEL_TYPE_UPDATE = 1, /* on wire: 0 */ + OSMO_GSUP_CANCEL_TYPE_WITHDRAW = 2, /* on wire: 1 */ +}; + +struct osmo_gsup_pdp_info { + unsigned int context_id; + int have_info; + uint16_t pdp_type; + const uint8_t *apn_enc; + size_t apn_enc_len; + const uint8_t *qos_enc; + size_t qos_enc_len; +}; + +struct osmo_gsup_message { + enum osmo_gsup_message_type message_type; + char imsi[GSM23003_IMSI_MAX_DIGITS+2]; + enum gsm48_gmm_cause cause; + enum osmo_gsup_cancel_type cancel_type; + int pdp_info_compl; + int freeze_ptmsi; + struct osmo_auth_vector auth_vectors[OSMO_GSUP_MAX_NUM_AUTH_INFO]; + size_t num_auth_vectors; + struct osmo_gsup_pdp_info pdp_infos[OSMO_GSUP_MAX_NUM_PDP_INFO]; + size_t num_pdp_infos; + const uint8_t *msisdn_enc; + size_t msisdn_enc_len; + const uint8_t *hlr_enc; + size_t hlr_enc_len; +}; + +int osmo_gsup_decode(const uint8_t *data, size_t data_len, + struct osmo_gsup_message *gsup_msg); +void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg); 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/include/openbsc/gprs_utils.h | 12 +++---- 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 +++---- 5 files changed, 92 insertions(+), 53 deletions(-) diff --git a/openbsc/include/openbsc/gprs_utils.h b/openbsc/include/openbsc/gprs_utils.h index 474eb45da..b5bee2b6a 100644 --- a/openbsc/include/openbsc/gprs_utils.h +++ b/openbsc/include/openbsc/gprs_utils.h @@ -42,15 +42,15 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len); int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi); void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi); -int gprs_shift_v_fixed(uint8_t **data, size_t *data_len, +int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, size_t len, uint8_t **value); -int gprs_match_tv_fixed(uint8_t **data, size_t *data_len, - uint8_t tag, size_t len, uint8_t **value); -int gprs_shift_tlv(uint8_t **data, size_t *data_len, +int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, + uint8_t tag, size_t len, uint8_t **value); +int osmo_shift_tlv(uint8_t **data, size_t *data_len, uint8_t *tag, uint8_t **value, size_t *value_len); -int gprs_match_tlv(uint8_t **data, size_t *data_len, +int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value, size_t *value_len); -int gprs_shift_lv(uint8_t **data, size_t *data_len, +int osmo_shift_lv(uint8_t **data, size_t *data_len, uint8_t **value, size_t *value_len); int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2); 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/include/openbsc/gprs_utils.h | 11 --- openbsc/src/gprs/gprs_utils.c | 173 ---------------------------------- openbsc/src/gprs/osmo_gsup_messages.c | 1 - 3 files changed, 185 deletions(-) diff --git a/openbsc/include/openbsc/gprs_utils.h b/openbsc/include/openbsc/gprs_utils.h index b5bee2b6a..603605c7a 100644 --- a/openbsc/include/openbsc/gprs_utils.h +++ b/openbsc/include/openbsc/gprs_utils.h @@ -42,15 +42,4 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len); int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi); void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi); -int osmo_shift_v_fixed(uint8_t **data, size_t *data_len, - size_t len, uint8_t **value); -int osmo_match_shift_tv_fixed(uint8_t **data, size_t *data_len, - uint8_t tag, size_t len, uint8_t **value); -int osmo_shift_tlv(uint8_t **data, size_t *data_len, - uint8_t *tag, uint8_t **value, size_t *value_len); -int osmo_match_shift_tlv(uint8_t **data, size_t *data_len, - uint8_t tag, uint8_t **value, size_t *value_len); -int osmo_shift_lv(uint8_t **data, size_t *data_len, - uint8_t **value, size_t *value_len); - int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2); 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/include/openbsc/osmo_gsup_messages.h | 7 +++++ openbsc/src/gprs/osmo_gsup_messages.c | 46 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/openbsc/include/openbsc/osmo_gsup_messages.h b/openbsc/include/openbsc/osmo_gsup_messages.h index bdc46aaee..4ccc029fc 100644 --- a/openbsc/include/openbsc/osmo_gsup_messages.h +++ b/openbsc/include/openbsc/osmo_gsup_messages.h @@ -51,6 +51,12 @@ enum osmo_gsup_iei { OSMO_GSUP_RAND_IE = 0x20, OSMO_GSUP_SRES_IE = 0x21, OSMO_GSUP_KC_IE = 0x22, + /* 3G support */ + OSMO_GSUP_IK_IE = 0x23, + OSMO_GSUP_CK_IE = 0x24, + OSMO_GSUP_AUTN_IE = 0x25, + OSMO_GSUP_AUTS_IE = 0x26, + OSMO_GSUP_RES_IE = 0x27, }; enum osmo_gsup_message_type { @@ -113,6 +119,7 @@ struct osmo_gsup_message { size_t msisdn_enc_len; const uint8_t *hlr_enc; size_t hlr_enc_len; + const uint8_t *auts; }; int osmo_gsup_decode(const uint8_t *data, size_t data_len, 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/include/openbsc/osmo_gsup_messages.h | 18 +++++++++++++++--- openbsc/src/gprs/osmo_gsup_messages.c | 10 ++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/openbsc/include/openbsc/osmo_gsup_messages.h b/openbsc/include/openbsc/osmo_gsup_messages.h index 4ccc029fc..8156b739b 100644 --- a/openbsc/include/openbsc/osmo_gsup_messages.h +++ b/openbsc/include/openbsc/osmo_gsup_messages.h @@ -1,11 +1,9 @@ /* Osmocom Subscriber Update Protocol message encoder/decoder */ -/* (C) 2014 by Sysmocom s.f.m.c. GmbH +/* (C) 2014 by Sysmocom s.f.m.c. GmbH, Author: Jacob Erlbeck * (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 @@ -28,12 +26,16 @@ #include #include +/*! Maximum nubmer of PDP inside \ref osmo_gsup_message */ #define OSMO_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ +/*! Maximum number of auth info inside \ref osmo_gsup_message */ #define OSMO_GSUP_MAX_NUM_AUTH_INFO 5 +/*! Maximum number of octets encoding MSISDN in BCD format */ #define OSMO_GSUP_MAX_MSISDN_LEN 9 #define OSMO_GSUP_PDP_TYPE_SIZE 2 +/*! Information Element Identifiers for GSUP IEs */ enum osmo_gsup_iei { OSMO_GSUP_IMSI_IE = 0x01, OSMO_GSUP_CAUSE_IE = 0x02, @@ -59,6 +61,7 @@ enum osmo_gsup_iei { OSMO_GSUP_RES_IE = 0x27, }; +/*! GSUP message type */ enum osmo_gsup_message_type { OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, @@ -94,16 +97,25 @@ enum osmo_gsup_cancel_type { OSMO_GSUP_CANCEL_TYPE_WITHDRAW = 2, /* on wire: 1 */ }; +/*! parsed/decoded PDP context information */ struct osmo_gsup_pdp_info { unsigned int context_id; int have_info; + /*! Type of PDP context */ uint16_t pdp_type; + /*! APN information, still in encoded form. Can be NULL if no + * APN information included */ const uint8_t *apn_enc; + /*! length (in octets) of apn_enc */ size_t apn_enc_len; + /*! QoS information, still in encoded form. Can be NULL if no + * QoS information included */ const uint8_t *qos_enc; + /*! length (in octets) of qos_enc */ size_t qos_enc_len; }; +/*! parsed/decoded GSUP protocol message */ struct osmo_gsup_message { enum osmo_gsup_message_type message_type; char imsi[GSM23003_IMSI_MAX_DIGITS+2]; 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/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/utils.h | 26 ---- 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 +- openbsc/tests/gprs/Makefile.am | 3 +- openbsc/tests/gprs/gprs_test.c | 243 +----------------------------------- openbsc/tests/gprs/gprs_test.ok | 1 - 10 files changed, 12 insertions(+), 339 deletions(-) delete mode 100644 openbsc/include/openbsc/utils.h delete mode 100644 openbsc/src/libcommon/utils.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 8a31fe5a9..893c7aa6e 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -14,7 +14,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \ bss.h gsm_data_shared.h ipaccess.h mncc_int.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ - osmux.h mgcp_transcode.h gprs_utils.h utils.h \ + osmux.h mgcp_transcode.h gprs_utils.h \ gprs_gb_parse.h smpp.h meas_feed.h osmo_gsup_messages.h \ gprs_gsup_client.h bsc_msg_filter.h \ oap.h oap_messages.h \ diff --git a/openbsc/include/openbsc/utils.h b/openbsc/include/openbsc/utils.h deleted file mode 100644 index d6054873b..000000000 --- a/openbsc/include/openbsc/utils.h +++ /dev/null @@ -1,26 +0,0 @@ -/* OpenBSC kitchen sink */ - -#pragma once - -#include -#include - -/* Compare count bytes of exp to rel. Return 0 if they are identical, 1 - * otherwise. Do not return a mismatch on the first mismatching byte, - * but always compare all bytes, regardless. The idea is that the amount of - * matching bytes cannot be inferred from the time the comparison took.*/ -int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count); - -/* This is like osmo_load64be_ext, except that if data_len is less than - * sizeof(uint64_t), the data is interpreted as the least significant bytes - * (osmo_load64be_ext loads them as the most significant bytes into the - * returned uint64_t). In this way, any integer size up to 64 bits can be - * decoded conveniently by using sizeof(), without the need to call specific - * numbered functions (osmo_load16, 32, ...). */ -uint64_t decode_big_endian(const uint8_t *data, size_t data_len); - -/* This is like osmo_store64be_ext, except that this returns a static buffer of - * the result (for convenience, but not threadsafe). If data_len is less than - * sizeof(uint64_t), only the least significant bytes of value are encoded. */ -uint8_t *encode_big_endian(uint64_t value, size_t data_len); - 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) diff --git a/openbsc/tests/gprs/Makefile.am b/openbsc/tests/gprs/Makefile.am index b57977b94..633c362f8 100644 --- a/openbsc/tests/gprs/Makefile.am +++ b/openbsc/tests/gprs/Makefile.am @@ -6,7 +6,6 @@ EXTRA_DIST = gprs_test.ok noinst_PROGRAMS = gprs_test gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c \ - $(top_srcdir)/src/gprs/gprs_gsup_messages.c \ - $(top_srcdir)/src/libcommon/utils.c + $(top_srcdir)/src/gprs/gprs_gsup_messages.c gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c index c78b98ab5..24e44cf3f 100644 --- a/openbsc/tests/gprs/gprs_test.c +++ b/openbsc/tests/gprs/gprs_test.c @@ -146,247 +146,7 @@ static void test_gsm_03_03_apn(void) } } -/* TODO: Move tlv testing to libosmocore */ -static void check_tlv_parse(uint8_t **data, size_t *data_len, - uint8_t exp_tag, size_t exp_len, const uint8_t *exp_val) -{ - uint8_t *value; - size_t value_len; - uint8_t tag; - int rc; - uint8_t *saved_data = *data; - size_t saved_data_len = *data_len; - - rc = gprs_match_tlv(data, data_len, exp_tag ^ 1, NULL, NULL); - OSMO_ASSERT(rc == 0); - - rc = gprs_match_tlv(data, data_len, exp_tag, &value, &value_len); - OSMO_ASSERT(rc == (int)value_len + 2); - OSMO_ASSERT(value_len == exp_len); - OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0); - - /* restore data/data_len */ - *data = saved_data; - *data_len = saved_data_len; - - rc = gprs_shift_tlv(data, data_len, &tag, &value, &value_len); - OSMO_ASSERT(rc == (int)value_len + 2); - OSMO_ASSERT(tag == exp_tag); - OSMO_ASSERT(value_len == exp_len); - OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0); -} - -static void check_tv_fixed_match(uint8_t **data, size_t *data_len, - uint8_t tag, size_t len, const uint8_t *exp_val) -{ - uint8_t *value; - int rc; - - rc = gprs_match_tv_fixed(data, data_len, tag ^ 1, len, NULL); - OSMO_ASSERT(rc == 0); - - rc = gprs_match_tv_fixed(data, data_len, tag, len, &value); - OSMO_ASSERT(rc == (int)len + 1); - OSMO_ASSERT(memcmp(value, exp_val, len) == 0); -} - -static void check_v_fixed_shift(uint8_t **data, size_t *data_len, - size_t len, const uint8_t *exp_val) -{ - uint8_t *value; - int rc; - - rc = gprs_shift_v_fixed(data, data_len, len, &value); - OSMO_ASSERT(rc == (int)len); - OSMO_ASSERT(memcmp(value, exp_val, len) == 0); -} - -static void check_lv_shift(uint8_t **data, size_t *data_len, - size_t exp_len, const uint8_t *exp_val) -{ - uint8_t *value; - size_t value_len; - int rc; - - rc = gprs_shift_lv(data, data_len, &value, &value_len); - OSMO_ASSERT(rc == (int)value_len + 1); - OSMO_ASSERT(value_len == exp_len); - OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0); -} - -static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len, - const uint8_t *test_data) -{ - uint8_t buf[300] = {0}; - - uint8_t *unchanged_ptr = buf - 1; - size_t unchanged_len = 0xdead; - size_t tmp_data_len = data_len; - uint8_t *value = unchanged_ptr; - size_t value_len = unchanged_len; - uint8_t *data = buf; - - OSMO_ASSERT(data_len <= sizeof(buf)); - - tlv_put(data, tag, len, test_data); - if (data_len < len + 2) { - OSMO_ASSERT(-1 == gprs_match_tlv(&data, &tmp_data_len, - tag, &value, &value_len)); - OSMO_ASSERT(tmp_data_len == 0); - OSMO_ASSERT(data == buf + data_len); - OSMO_ASSERT(value == unchanged_ptr); - OSMO_ASSERT(value_len == unchanged_len); - } else { - OSMO_ASSERT(0 <= gprs_match_tlv(&data, &tmp_data_len, - tag, &value, &value_len)); - OSMO_ASSERT(value != unchanged_ptr); - OSMO_ASSERT(value_len != unchanged_len); - } -} - -static void check_tv_fixed_match_data_len(size_t data_len, - uint8_t tag, size_t len, - const uint8_t *test_data) -{ - uint8_t buf[300] = {0}; - - uint8_t *unchanged_ptr = buf - 1; - size_t tmp_data_len = data_len; - uint8_t *value = unchanged_ptr; - uint8_t *data = buf; - - OSMO_ASSERT(data_len <= sizeof(buf)); - - tv_fixed_put(data, tag, len, test_data); - - if (data_len < len + 1) { - OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &tmp_data_len, - tag, len, &value)); - OSMO_ASSERT(tmp_data_len == 0); - OSMO_ASSERT(data == buf + data_len); - OSMO_ASSERT(value == unchanged_ptr); - } else { - OSMO_ASSERT(0 <= gprs_match_tv_fixed(&data, &tmp_data_len, - tag, len, &value)); - OSMO_ASSERT(value != unchanged_ptr); - } -} - -static void check_v_fixed_shift_data_len(size_t data_len, - size_t len, const uint8_t *test_data) -{ - uint8_t buf[300] = {0}; - - uint8_t *unchanged_ptr = buf - 1; - size_t tmp_data_len = data_len; - uint8_t *value = unchanged_ptr; - uint8_t *data = buf; - - OSMO_ASSERT(data_len <= sizeof(buf)); - - memcpy(data, test_data, len); - - if (data_len < len) { - OSMO_ASSERT(-1 == gprs_shift_v_fixed(&data, &tmp_data_len, - len, &value)); - OSMO_ASSERT(tmp_data_len == 0); - OSMO_ASSERT(data == buf + data_len); - OSMO_ASSERT(value == unchanged_ptr); - } else { - OSMO_ASSERT(0 <= gprs_shift_v_fixed(&data, &tmp_data_len, - len, &value)); - OSMO_ASSERT(value != unchanged_ptr); - } -} - -static void check_lv_shift_data_len(size_t data_len, - size_t len, const uint8_t *test_data) -{ - uint8_t buf[300] = {0}; - - uint8_t *unchanged_ptr = buf - 1; - size_t unchanged_len = 0xdead; - size_t tmp_data_len = data_len; - uint8_t *value = unchanged_ptr; - size_t value_len = unchanged_len; - uint8_t *data = buf; - - lv_put(data, len, test_data); - if (data_len < len + 1) { - OSMO_ASSERT(-1 == gprs_shift_lv(&data, &tmp_data_len, - &value, &value_len)); - OSMO_ASSERT(tmp_data_len == 0); - OSMO_ASSERT(data == buf + data_len); - OSMO_ASSERT(value == unchanged_ptr); - OSMO_ASSERT(value_len == unchanged_len); - } else { - OSMO_ASSERT(0 <= gprs_shift_lv(&data, &tmp_data_len, - &value, &value_len)); - OSMO_ASSERT(value != unchanged_ptr); - OSMO_ASSERT(value_len != unchanged_len); - } -} - -static void test_tlv_shift_functions() -{ - uint8_t test_data[1024]; - uint8_t buf[1024]; - uint8_t *data_end; - unsigned i, len; - uint8_t *data; - size_t data_len; - const uint8_t tag = 0x1a; - - printf("Test shift functions\n"); - - for (i = 0; i < ARRAY_SIZE(test_data); i++) - test_data[i] = (uint8_t)i; - - for (len = 0; len < 256; len++) { - const unsigned iterations = sizeof(buf) / (len + 2) / 4; - - memset(buf, 0xee, sizeof(buf)); - data_end = data = buf; - - for (i = 0; i < iterations; i++) { - data_end = tlv_put(data_end, tag, len, test_data); - data_end = tv_fixed_put(data_end, tag, len, test_data); - /* v_fixed_put */ - memcpy(data_end, test_data, len); - data_end += len; - data_end = lv_put(data_end, len, test_data); - } - - data_len = data_end - data; - OSMO_ASSERT(data_len <= sizeof(buf)); - - for (i = 0; i < iterations; i++) { - check_tlv_parse(&data, &data_len, tag, len, test_data); - check_tv_fixed_match(&data, &data_len, tag, len, test_data); - check_v_fixed_shift(&data, &data_len, len, test_data); - check_lv_shift(&data, &data_len, len, test_data); - } - - OSMO_ASSERT(data == data_end); - - /* Test at end of data */ - - OSMO_ASSERT(-1 == gprs_match_tlv(&data, &data_len, tag, NULL, NULL)); - OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &data_len, tag, len, NULL)); - OSMO_ASSERT((len ? -1 : 0) == gprs_shift_v_fixed(&data, &data_len, len, NULL)); - OSMO_ASSERT(-1 == gprs_shift_lv(&data, &data_len, NULL, NULL)); - - /* Test invalid data_len */ - for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) { - check_tlv_match_data_len(data_len, tag, len, test_data); - check_tv_fixed_match_data_len(data_len, tag, len, test_data); - check_v_fixed_shift_data_len(data_len, len, test_data); - check_lv_shift_data_len(data_len, len, test_data); - } - } -} - -/* Tests for gprs_gsup_messages.c */ +/* Tests for osmo_gsup_messages.c */ #define TEST_IMSI_IE 0x01, 0x08, 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5 #define TEST_IMSI_STR "123456789012345" @@ -705,7 +465,6 @@ int main(int argc, char **argv) test_8_4_2(); test_gsm_03_03_apn(); - test_tlv_shift_functions(); test_gsup_messages_dec_enc(); test_gprs_timer_enc_dec(); diff --git a/openbsc/tests/gprs/gprs_test.ok b/openbsc/tests/gprs/gprs_test.ok index cf710769e..688d44b24 100644 --- a/openbsc/tests/gprs/gprs_test.ok +++ b/openbsc/tests/gprs/gprs_test.ok @@ -13,7 +13,6 @@ N(U) = 511, V(UR) = 511 => new N(U) = 510, V(UR) = 511 => retransmit N(U) = 481, V(UR) = 511 => retransmit N(U) = 479, V(UR) = 511 => new -Test shift functions Test GSUP message decoding/encoding Testing Send Authentication Info Request Testing Send Authentication Info Error -- 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/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/osmo_gsup_messages.h | 139 -------- openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gprs_subscriber.c | 2 +- openbsc/src/gprs/osmo_gsup_messages.c | 472 --------------------------- openbsc/tests/gprs/Makefile.am | 3 +- openbsc/tests/gprs/gprs_test.c | 239 +------------- openbsc/tests/gprs/gprs_test.ok | 13 - openbsc/tests/sgsn/Makefile.am | 1 - openbsc/tests/sgsn/sgsn_test.c | 18 +- 10 files changed, 14 insertions(+), 877 deletions(-) delete mode 100644 openbsc/include/openbsc/osmo_gsup_messages.h delete mode 100644 openbsc/src/gprs/osmo_gsup_messages.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 893c7aa6e..c272b14de 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -15,7 +15,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ bss.h gsm_data_shared.h ipaccess.h mncc_int.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h \ - gprs_gb_parse.h smpp.h meas_feed.h osmo_gsup_messages.h \ + gprs_gb_parse.h smpp.h meas_feed.h \ gprs_gsup_client.h bsc_msg_filter.h \ oap.h oap_messages.h \ gtphub.h diff --git a/openbsc/include/openbsc/osmo_gsup_messages.h b/openbsc/include/openbsc/osmo_gsup_messages.h deleted file mode 100644 index 8156b739b..000000000 --- a/openbsc/include/openbsc/osmo_gsup_messages.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Osmocom Subscriber Update Protocol message encoder/decoder */ - -/* (C) 2014 by Sysmocom s.f.m.c. GmbH, Author: Jacob Erlbeck - * (C) 2016 by Harald Welte - * 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 . - * - */ -#pragma once - -#include -#include -#include -#include -#include - -/*! Maximum nubmer of PDP inside \ref osmo_gsup_message */ -#define OSMO_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */ -/*! Maximum number of auth info inside \ref osmo_gsup_message */ -#define OSMO_GSUP_MAX_NUM_AUTH_INFO 5 -/*! Maximum number of octets encoding MSISDN in BCD format */ -#define OSMO_GSUP_MAX_MSISDN_LEN 9 - -#define OSMO_GSUP_PDP_TYPE_SIZE 2 - -/*! Information Element Identifiers for GSUP IEs */ -enum osmo_gsup_iei { - OSMO_GSUP_IMSI_IE = 0x01, - OSMO_GSUP_CAUSE_IE = 0x02, - OSMO_GSUP_AUTH_TUPLE_IE = 0x03, - OSMO_GSUP_PDP_INFO_COMPL_IE = 0x04, - OSMO_GSUP_PDP_INFO_IE = 0x05, - OSMO_GSUP_CANCEL_TYPE_IE = 0x06, - OSMO_GSUP_FREEZE_PTMSI_IE = 0x07, - OSMO_GSUP_MSISDN_IE = 0x08, - OSMO_GSUP_HLR_NUMBER_IE = 0x09, - OSMO_GSUP_PDP_CONTEXT_ID_IE = 0x10, - OSMO_GSUP_PDP_TYPE_IE = 0x11, - OSMO_GSUP_ACCESS_POINT_NAME_IE = 0x12, - OSMO_GSUP_PDP_QOS_IE = 0x13, - OSMO_GSUP_RAND_IE = 0x20, - OSMO_GSUP_SRES_IE = 0x21, - OSMO_GSUP_KC_IE = 0x22, - /* 3G support */ - OSMO_GSUP_IK_IE = 0x23, - OSMO_GSUP_CK_IE = 0x24, - OSMO_GSUP_AUTN_IE = 0x25, - OSMO_GSUP_AUTS_IE = 0x26, - OSMO_GSUP_RES_IE = 0x27, -}; - -/*! GSUP message type */ -enum osmo_gsup_message_type { - OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100, - OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101, - OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110, - - OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST = 0b00001000, - OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR = 0b00001001, - OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT = 0b00001010, - - OSMO_GSUP_MSGT_PURGE_MS_REQUEST = 0b00001100, - OSMO_GSUP_MSGT_PURGE_MS_ERROR = 0b00001101, - OSMO_GSUP_MSGT_PURGE_MS_RESULT = 0b00001110, - - OSMO_GSUP_MSGT_INSERT_DATA_REQUEST = 0b00010000, - OSMO_GSUP_MSGT_INSERT_DATA_ERROR = 0b00010001, - OSMO_GSUP_MSGT_INSERT_DATA_RESULT = 0b00010010, - - OSMO_GSUP_MSGT_DELETE_DATA_REQUEST = 0b00010100, - OSMO_GSUP_MSGT_DELETE_DATA_ERROR = 0b00010101, - OSMO_GSUP_MSGT_DELETE_DATA_RESULT = 0b00010110, - - OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST = 0b00011100, - OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR = 0b00011101, - OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT = 0b00011110, -}; - -#define OSMO_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00) -#define OSMO_GSUP_IS_MSGT_ERROR(msgt) (((msgt) & 0b00000011) == 0b01) -#define OSMO_GSUP_TO_MSGT_ERROR(msgt) (((msgt) & 0b11111100) | 0b01) - -enum osmo_gsup_cancel_type { - OSMO_GSUP_CANCEL_TYPE_UPDATE = 1, /* on wire: 0 */ - OSMO_GSUP_CANCEL_TYPE_WITHDRAW = 2, /* on wire: 1 */ -}; - -/*! parsed/decoded PDP context information */ -struct osmo_gsup_pdp_info { - unsigned int context_id; - int have_info; - /*! Type of PDP context */ - uint16_t pdp_type; - /*! APN information, still in encoded form. Can be NULL if no - * APN information included */ - const uint8_t *apn_enc; - /*! length (in octets) of apn_enc */ - size_t apn_enc_len; - /*! QoS information, still in encoded form. Can be NULL if no - * QoS information included */ - const uint8_t *qos_enc; - /*! length (in octets) of qos_enc */ - size_t qos_enc_len; -}; - -/*! parsed/decoded GSUP protocol message */ -struct osmo_gsup_message { - enum osmo_gsup_message_type message_type; - char imsi[GSM23003_IMSI_MAX_DIGITS+2]; - enum gsm48_gmm_cause cause; - enum osmo_gsup_cancel_type cancel_type; - int pdp_info_compl; - int freeze_ptmsi; - struct osmo_auth_vector auth_vectors[OSMO_GSUP_MAX_NUM_AUTH_INFO]; - size_t num_auth_vectors; - struct osmo_gsup_pdp_info pdp_infos[OSMO_GSUP_MAX_NUM_PDP_INFO]; - size_t num_pdp_infos; - const uint8_t *msisdn_enc; - size_t msisdn_enc_len; - const uint8_t *hlr_enc; - size_t hlr_enc_len; - const uint8_t *auts; -}; - -int osmo_gsup_decode(const uint8_t *data, size_t data_len, - struct osmo_gsup_message *gsup_msg); -void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg); 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); - } -} diff --git a/openbsc/tests/gprs/Makefile.am b/openbsc/tests/gprs/Makefile.am index 633c362f8..902313f2a 100644 --- a/openbsc/tests/gprs/Makefile.am +++ b/openbsc/tests/gprs/Makefile.am @@ -5,7 +5,6 @@ EXTRA_DIST = gprs_test.ok noinst_PROGRAMS = gprs_test -gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c \ - $(top_srcdir)/src/gprs/gprs_gsup_messages.c +gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c index 24e44cf3f..ff7740494 100644 --- a/openbsc/tests/gprs/gprs_test.c +++ b/openbsc/tests/gprs/gprs_test.c @@ -5,17 +5,14 @@ #include #include -#include - #include #include +#include #define ASSERT_FALSE(x) if (x) { printf("Should have returned false.\n"); abort(); } #define ASSERT_TRUE(x) if (!x) { printf("Should have returned true.\n"); abort(); } -#define VERBOSE_FPRINTF(...) - /** * GSM 04.64 8.4.2 Receipt of unacknowledged information */ @@ -146,239 +143,6 @@ static void test_gsm_03_03_apn(void) } } -/* Tests for osmo_gsup_messages.c */ - -#define TEST_IMSI_IE 0x01, 0x08, 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5 -#define TEST_IMSI_STR "123456789012345" - -static void test_gsup_messages_dec_enc(void) -{ - int test_idx; - int rc; - uint8_t buf[1024]; - - static const uint8_t send_auth_info_req[] = { - 0x08, - TEST_IMSI_IE - }; - - static const uint8_t send_auth_info_err[] = { - 0x09, - TEST_IMSI_IE, - 0x02, 0x01, 0x07 /* GPRS no allowed */ - }; - - static const uint8_t send_auth_info_res[] = { - 0x0a, - TEST_IMSI_IE, - 0x03, 0x22, /* Auth tuple */ - 0x20, 0x10, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x21, 0x04, - 0x21, 0x22, 0x23, 0x24, - 0x22, 0x08, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x03, 0x22, /* Auth tuple */ - 0x20, 0x10, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, - 0x21, 0x04, - 0xa1, 0xa2, 0xa3, 0xa4, - 0x22, 0x08, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, - }; - - static const uint8_t update_location_req[] = { - 0x04, - TEST_IMSI_IE, - }; - - static const uint8_t update_location_err[] = { - 0x05, - TEST_IMSI_IE, - 0x02, 0x01, 0x07 /* GPRS no allowed */ - }; - - static const uint8_t update_location_res[] = { - 0x06, - TEST_IMSI_IE, - 0x08, 0x07, /* MSISDN of the subscriber */ - 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43, - 0x09, 0x07, /* HLR-Number of the subscriber */ - 0x91, 0x83, 0x52, 0x38, 0x48, 0x83, 0x93, - 0x04, 0x00, /* PDP info complete */ - 0x05, 0x15, - 0x10, 0x01, 0x01, - 0x11, 0x02, 0xf1, 0x21, /* IPv4 */ - 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n', - 0x13, 0x01, 0x02, - 0x05, 0x11, - 0x10, 0x01, 0x02, - 0x11, 0x02, 0xf1, 0x21, /* IPv4 */ - 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n', - }; - - static const uint8_t location_cancellation_req[] = { - 0x1c, - TEST_IMSI_IE, - 0x06, 0x01, 0x00, - }; - - static const uint8_t location_cancellation_err[] = { - 0x1d, - TEST_IMSI_IE, - 0x02, 0x01, 0x03 /* Illegal MS */ - }; - - static const uint8_t location_cancellation_res[] = { - 0x1e, - TEST_IMSI_IE, - }; - - static const uint8_t purge_ms_req[] = { - 0x0c, - TEST_IMSI_IE, - }; - - static const uint8_t purge_ms_err[] = { - 0x0d, - TEST_IMSI_IE, - 0x02, 0x01, 0x03, /* Illegal MS */ - }; - - static const uint8_t purge_ms_res[] = { - 0x0e, - TEST_IMSI_IE, - 0x07, 0x00, - }; - - static const struct test { - char *name; - const uint8_t *data; - size_t data_len; - } test_messages[] = { - {"Send Authentication Info Request", - send_auth_info_req, sizeof(send_auth_info_req)}, - {"Send Authentication Info Error", - send_auth_info_err, sizeof(send_auth_info_err)}, - {"Send Authentication Info Result", - send_auth_info_res, sizeof(send_auth_info_res)}, - {"Update Location Request", - update_location_req, sizeof(update_location_req)}, - {"Update Location Error", - update_location_err, sizeof(update_location_err)}, - {"Update Location Result", - update_location_res, sizeof(update_location_res)}, - {"Location Cancellation Request", - location_cancellation_req, sizeof(location_cancellation_req)}, - {"Location Cancellation Error", - location_cancellation_err, sizeof(location_cancellation_err)}, - {"Location Cancellation Result", - location_cancellation_res, sizeof(location_cancellation_res)}, - {"Purge MS Request", - purge_ms_req, sizeof(purge_ms_req)}, - {"Purge MS Error", - purge_ms_err, sizeof(purge_ms_err)}, - {"Purge MS Result", - purge_ms_res, sizeof(purge_ms_res)}, - }; - - printf("Test GSUP message decoding/encoding\n"); - - for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) { - const struct test *t = &test_messages[test_idx]; - struct gprs_gsup_message gm = {0}; - struct msgb *msg = msgb_alloc(4096, "gsup_test"); - - printf(" Testing %s\n", t->name); - - rc = gprs_gsup_decode(t->data, t->data_len, &gm); - OSMO_ASSERT(rc >= 0); - - gprs_gsup_encode(msg, &gm); - - fprintf(stderr, " generated message: %s\n", msgb_hexdump(msg)); - fprintf(stderr, " original message: %s\n", osmo_hexdump(t->data, t->data_len)); - fprintf(stderr, " IMSI: %s\n", gm.imsi); - OSMO_ASSERT(strcmp(gm.imsi, TEST_IMSI_STR) == 0); - OSMO_ASSERT(msgb_length(msg) == t->data_len); - OSMO_ASSERT(memcmp(msgb_data(msg), t->data, t->data_len) == 0); - - msgb_free(msg); - } - - /* simple truncation test */ - for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) { - int j; - const struct test *t = &test_messages[test_idx]; - int ie_end = t->data_len; - struct gprs_gsup_message gm = {0}; - int counter = 0; - int parse_err = 0; - - for (j = t->data_len - 1; j >= 0; --j) { - rc = gprs_gsup_decode(t->data, j, &gm); - counter += 1; - - VERBOSE_FPRINTF(stderr, - " partial message decoding: " - "orig_len = %d, trunc = %d, rc = %d, ie_end = %d\n", - t->data_len, j, rc, ie_end); - if (rc >= 0) { - VERBOSE_FPRINTF(stderr, - " remaing partial message: %s\n", - osmo_hexdump(t->data + j, ie_end - j)); - - OSMO_ASSERT(j <= ie_end - 2); - OSMO_ASSERT(t->data[j+0] <= GPRS_GSUP_KC_IE); - OSMO_ASSERT(t->data[j+1] <= ie_end - j - 2); - - ie_end = j; - } else { - parse_err += 1; - } - } - - fprintf(stderr, - " message %d: tested %d truncations, %d parse failures\n", - test_idx, counter, parse_err); - } - - /* message modification test (relies on ASAN or valgrind being used) */ - for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) { - int j; - const struct test *t = &test_messages[test_idx]; - struct gprs_gsup_message gm = {0}; - uint8_t val; - int counter = 0; - int parse_err = 0; - - OSMO_ASSERT(sizeof(buf) >= t->data_len); - - for (j = t->data_len - 1; j >= 0; --j) { - memcpy(buf, t->data, t->data_len); - val = 0; - do { - VERBOSE_FPRINTF(stderr, - "t = %d, len = %d, val = %d\n", - test_idx, j, val); - buf[j] = val; - rc = gprs_gsup_decode(buf, t->data_len, &gm); - counter += 1; - if (rc < 0) - parse_err += 1; - - val += 1; - } while (val != (uint8_t)256); - } - - fprintf(stderr, - " message %d: tested %d modifications, %d parse failures\n", - test_idx, counter, parse_err); - } -} - static void test_gprs_timer_enc_dec(void) { int i, u, secs, tmr; @@ -465,7 +229,6 @@ int main(int argc, char **argv) test_8_4_2(); test_gsm_03_03_apn(); - test_gsup_messages_dec_enc(); test_gprs_timer_enc_dec(); printf("Done.\n"); diff --git a/openbsc/tests/gprs/gprs_test.ok b/openbsc/tests/gprs/gprs_test.ok index 688d44b24..da7888c6a 100644 --- a/openbsc/tests/gprs/gprs_test.ok +++ b/openbsc/tests/gprs/gprs_test.ok @@ -13,18 +13,5 @@ N(U) = 511, V(UR) = 511 => new N(U) = 510, V(UR) = 511 => retransmit N(U) = 481, V(UR) = 511 => retransmit N(U) = 479, V(UR) = 511 => new -Test GSUP message decoding/encoding - Testing Send Authentication Info Request - Testing Send Authentication Info Error - Testing Send Authentication Info Result - Testing Update Location Request - Testing Update Location Error - Testing Update Location Result - Testing Location Cancellation Request - Testing Location Cancellation Error - Testing Location Cancellation Result - Testing Purge MS Request - Testing Purge MS Error - Testing Purge MS Result Test GPRS timer decoding/encoding Done. diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index aebcf0105..e3cec5086 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -23,7 +23,6 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/sgsn_libgtp.o \ $(top_builddir)/src/gprs/sgsn_auth.o \ $(top_builddir)/src/gprs/sgsn_ares.o \ - $(top_builddir)/src/gprs/gprs_gsup_messages.o \ $(top_builddir)/src/gprs/gprs_gsup_client.o \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 94c277f55..5cffff289 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -1266,13 +1266,13 @@ static void test_gmm_attach_subscr_gsup_auth(int retry) int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) { - struct gprs_gsup_message to_peer = {0}; - struct gprs_gsup_message from_peer = {0}; + struct osmo_gsup_message to_peer = {0}; + struct osmo_gsup_message from_peer = {0}; struct msgb *reply_msg; int rc; /* Simulate the GSUP peer */ - rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer); + rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer); OSMO_ASSERT(rc >= 0); OSMO_ASSERT(to_peer.imsi[0] != 0); strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi)); @@ -1281,16 +1281,16 @@ int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) msgb_free(msg); switch (to_peer.message_type) { - case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST: + case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: /* Send UPDATE_LOCATION_RESULT */ return my_subscr_request_update_gsup_auth(NULL); - case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: + case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: /* Send SEND_AUTH_INFO_RESULT */ return my_subscr_request_auth_info_gsup_auth(NULL); - case GPRS_GSUP_MSGT_PURGE_MS_REQUEST: - from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT; + case OSMO_GSUP_MSGT_PURGE_MS_REQUEST: + from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT; break; default: @@ -1308,7 +1308,7 @@ int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) reply_msg = gprs_gsup_msgb_alloc(); reply_msg->l2h = reply_msg->data; - gprs_gsup_encode(reply_msg, &from_peer); + osmo_gsup_encode(reply_msg, &from_peer); gprs_subscr_rx_gsup_message(reply_msg); msgb_free(reply_msg); -- 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/include/openbsc/oap_messages.h | 2 +- openbsc/src/gprs/oap.c | 2 ++ openbsc/src/gprs/oap_messages.c | 1 - openbsc/tests/oap/oap_test.c | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h index b7f4ccada..e76287bae 100644 --- a/openbsc/include/openbsc/oap_messages.h +++ b/openbsc/include/openbsc/oap_messages.h @@ -22,8 +22,8 @@ #pragma once #include +#include #include -#include /* Some numbers are out of sequence because (so far) they match gprs_gsup_iei. */ 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 diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c index 9a2063bdc..4ee5d4207 100644 --- a/openbsc/tests/oap/oap_test.c +++ b/openbsc/tests/oap/oap_test.c @@ -26,6 +26,7 @@ #include #include +#include static void test_oap_api(void) { -- 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/include/openbsc/oap.h | 4 ++-- openbsc/include/openbsc/oap_messages.h | 12 ++++++------ openbsc/src/gprs/oap.c | 14 +++++++------- openbsc/src/gprs/oap_messages.c | 6 +++--- openbsc/tests/oap/oap_test.c | 8 ++++---- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/openbsc/include/openbsc/oap.h b/openbsc/include/openbsc/oap.h index 2370cbe07..2206184d1 100644 --- a/openbsc/include/openbsc/oap.h +++ b/openbsc/include/openbsc/oap.h @@ -25,7 +25,7 @@ #include struct msgb; -struct oap_message; +struct osmo_oap_message; /* This is the config part for vty. It is essentially copied in oap_state, * where values are copied over once the config is considered valid. */ @@ -74,5 +74,5 @@ int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb * /* Allocate a msgb and in it, return the encoded oap_msg. Return NULL on * error. (Like oap_encode(), but also allocates a msgb.) * About the name: the idea is do_something(oap_encoded(my_struct)) */ -struct msgb *oap_encoded(const struct oap_message *oap_msg); +struct msgb *oap_encoded(const struct osmo_oap_message *oap_msg); diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h index e76287bae..496a6de88 100644 --- a/openbsc/include/openbsc/oap_messages.h +++ b/openbsc/include/openbsc/oap_messages.h @@ -36,7 +36,7 @@ enum oap_iei { OAP_CLIENT_ID_IE = 0x30, }; -enum oap_message_type { +enum osmo_oap_message_type { OAP_MSGT_REGISTER_REQUEST = 0b00000100, OAP_MSGT_REGISTER_ERROR = 0b00000101, OAP_MSGT_REGISTER_RESULT = 0b00000110, @@ -50,8 +50,8 @@ enum oap_message_type { OAP_MSGT_SYNC_RESULT = 0b00001110, }; -struct oap_message { - enum oap_message_type message_type; +struct osmo_oap_message { + enum osmo_oap_message_type message_type; enum gsm48_gmm_cause cause; uint16_t client_id; int rand_present; @@ -64,7 +64,7 @@ struct oap_message { uint8_t auts[16]; }; -int oap_decode(const uint8_t *data, size_t data_len, - struct oap_message *oap_msg); -void oap_encode(struct msgb *msg, const struct oap_message *oap_msg); +int osmo_oap_decode(const uint8_t *data, size_t data_len, + struct osmo_oap_message *oap_msg); +void osmo_oap_encode(struct msgb *msg, const struct osmo_oap_message *oap_msg); 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; diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c index 4ee5d4207..625d8d892 100644 --- a/openbsc/tests/oap/oap_test.c +++ b/openbsc/tests/oap/oap_test.c @@ -95,8 +95,8 @@ static void test_oap_api(void) printf(" - AUTN failures\n"); - struct oap_message oap_rx; - struct oap_message oap_tx; + struct osmo_oap_message oap_rx; + struct osmo_oap_message oap_tx; struct msgb *msg_rx; struct msgb *msg_tx; @@ -168,7 +168,7 @@ static void test_oap_api(void) /* Expect the challenge response in msg_tx */ OSMO_ASSERT(msg_tx); - OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(osmo_oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT); OSMO_ASSERT(strcmp("e2d05b598c61d9ba", osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres))) @@ -191,7 +191,7 @@ static void test_oap_api(void) OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); OSMO_ASSERT(state->registration_failures == 1); OSMO_ASSERT(msg_tx); - OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(osmo_oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST); OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE); msgb_free(msg_tx); -- 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(-) 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/include/openbsc/oap_messages.h | 4 ++-- openbsc/src/gprs/oap.c | 2 +- openbsc/src/gprs/oap_messages.c | 4 ++-- openbsc/tests/oap/oap_test.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h index 496a6de88..ecb66df34 100644 --- a/openbsc/include/openbsc/oap_messages.h +++ b/openbsc/include/openbsc/oap_messages.h @@ -64,7 +64,7 @@ struct osmo_oap_message { uint8_t auts[16]; }; -int osmo_oap_decode(const uint8_t *data, size_t data_len, - struct osmo_oap_message *oap_msg); +int osmo_oap_decode(struct osmo_oap_message *oap_msg, + const uint8_t *data, size_t data_len); void osmo_oap_encode(struct msgb *msg, const struct osmo_oap_message *oap_msg); 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; diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c index 625d8d892..339d77430 100644 --- a/openbsc/tests/oap/oap_test.c +++ b/openbsc/tests/oap/oap_test.c @@ -168,7 +168,7 @@ static void test_oap_api(void) /* Expect the challenge response in msg_tx */ OSMO_ASSERT(msg_tx); - OSMO_ASSERT(osmo_oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0); OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT); OSMO_ASSERT(strcmp("e2d05b598c61d9ba", osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres))) @@ -191,7 +191,7 @@ static void test_oap_api(void) OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); OSMO_ASSERT(state->registration_failures == 1); OSMO_ASSERT(msg_tx); - OSMO_ASSERT(osmo_oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0); OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST); OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE); msgb_free(msg_tx); -- 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(+) 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(+) 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 From cd5e52605cdb77bdc6f36fce81a6a1bac7fbda48 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 6 May 2016 13:46:21 +0200 Subject: sgsn_test: Adapt test case to now-existing InsertSubscriberData We recently implementd InsertSubscriberData in the SGSN, adapt the test to reflect that. --- openbsc/tests/sgsn/sgsn_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 5cffff289..afff30f32 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -610,8 +610,8 @@ static void test_subscriber_gsup(void) /* Inject InsertSubscrData GSUP message */ last_updated_subscr = NULL; rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req)); - OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL); - OSMO_ASSERT(last_updated_subscr == NULL); + OSMO_ASSERT(rc = -ENOTSUP); /* not connected */ + OSMO_ASSERT(last_updated_subscr == s1); /* Inject DeleteSubscrData GSUP message */ last_updated_subscr = NULL; -- cgit v1.2.3