From patchwork Sun Mar 27 12:17:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Yanitskiy X-Patchwork-Id: 602352 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.osmocom.org (lists.osmocom.org [IPv6:2a01:4f8:191:444b::2:7]) by ozlabs.org (Postfix) with ESMTP id 3qXwzb74Ggz9s4x for ; Sun, 27 Mar 2016 23:18:03 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=NIHU/oEt; dkim-atps=neutral Received: from lists.osmocom.org (lists.osmocom.org [144.76.43.76]) by lists.osmocom.org (Postfix) with ESMTP id B95241B140; Sun, 27 Mar 2016 12:18:00 +0000 (UTC) X-Original-To: openbsc@lists.osmocom.org Delivered-To: openbsc@lists.osmocom.org Received: from mail-lf0-x244.google.com (mail-lf0-x244.google.com [IPv6:2a00:1450:4010:c07::244]) by lists.osmocom.org (Postfix) with ESMTP id 1D5B71B139 for ; Sun, 27 Mar 2016 12:17:57 +0000 (UTC) Received: by mail-lf0-x244.google.com with SMTP id s192so1256526lfs.0 for ; Sun, 27 Mar 2016 05:17:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+aEHzdi15Az8aKWA3QJg8ecyKdk7/IN28eVxurIDVgI=; b=NIHU/oEto2frY6IxMfQxGcHMJthoSMlKseDgnJ7yH5A2uFryMYeoWo9isfNd5QRWUg 5D4acLrJEGXBYVMfprDRnrpHA3CkP+v93S4j2jEew6zRaDoldYq4cTw9xlW8Zn0uPRXO ZJlVKbdMBr8rcrW4eTd8TtT06QCoUdlJXcf+nlDXs9vvBTfNjJ0FaWJDNRgNKVJNZCYY +KoFjUyeRB8S02nAGBMv3byMyz5gaDaBubl3J4prnvtRvKfHWy9kPOOleidKCTH8yn7L 4kufZmACc5G3BrRB90qD/DCrf8XF8DxdB8U7I4CFQxF4gBRfpW/ROcGNjxV1/fo/QRfl xVbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+aEHzdi15Az8aKWA3QJg8ecyKdk7/IN28eVxurIDVgI=; b=O+RqF1rC2NKup90EuxWoADsi0Wu8wYoG8HOjKvFmhkQN18EHJkxndIyDIMG7v4V312 nhsHlJ2G/lfDT0d464bGOHJgvrrFb4m+ZRSeoavqw3LiUpCBFeWaDpIcBFIqUK5+qOoV tAlRwz6i8+KLpZL21QCQqEBz1ujXNovQeDns94Tyj7LjHb9Ylx7/gMvZAE7NgEssNBS7 74hwMRJtceQCU5Ia9Y0QSQ6n5W2oSIoLIxE/gOO1JactOM/NgPDA5KKihpyBojeCfBDa BCMLdAxQoBf2ZzsBeewEMA9KMznh4BWqdy4RoksVvL70vzK2WRblbI0Asj5ONRhmgVVU h8qA== X-Gm-Message-State: AD7BkJJfMyGGhbquIF0YwagAE9uND9co97kMGaSOJuS9eSols/gmTXDtyIAy5rrYhmT5kA== X-Received: by 10.25.127.216 with SMTP id a207mr8979140lfd.116.1459081077432; Sun, 27 Mar 2016 05:17:57 -0700 (PDT) Received: from localhost.localdomain ([212.164.216.34]) by smtp.gmail.com with ESMTPSA id jb5sm3499383lbc.8.2016.03.27.05.17.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 27 Mar 2016 05:17:56 -0700 (PDT) From: Vadim Yanitskiy To: laforge@gnumonks.org, holger@freyther.de Subject: [PATCH] move to hex TMSI representation Date: Sun, 27 Mar 2016 18:17:10 +0600 Message-Id: <1459081030-23070-1-git-send-email-axilirator@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: X-BeenThere: openbsc@lists.osmocom.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Development of OpenBSC, OsmoBSC, OsmoNITB, OsmoCSCN" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Vadim Yanitskiy , openbsc@lists.osmocom.org Errors-To: openbsc-bounces@lists.osmocom.org Sender: "OpenBSC" In OpenBSC, we traditionally displayed a TMSI in its integer representation, which is quite unusual in the telecom world. A TMSI is normally printed as a series of 8 hex digits. This patch aligns OpenBSC with the telecom industry standard. - Use hex representation in VTY - Increased DB SCHEMA_REVISION - Implemented DB migration code Signed-off-by: Vadim Yanitskiy --- openbsc/include/openbsc/gsm_subscriber.h | 6 +- openbsc/src/libcommon/gsm_subscriber_base.c | 5 +- openbsc/src/libmsc/db.c | 96 ++++++++++++++++++++++++++--- openbsc/src/libmsc/gsm_04_08.c | 30 +++------ openbsc/src/libmsc/gsm_subscriber.c | 10 ++- openbsc/src/libmsc/vty_interface_layer3.c | 2 +- openbsc/src/osmo-bsc/osmo_bsc_filter.c | 2 +- openbsc/src/osmo-bsc/osmo_bsc_vty.c | 4 +- openbsc/tests/db/db_test.c | 4 +- openbsc/tests/gsm0408/gsm0408_test.c | 2 +- 10 files changed, 115 insertions(+), 46 deletions(-) diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 7d6c776..de80530 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -14,7 +14,7 @@ #define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001 /* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */ -#define tmsi_from_string(str) strtoul(str, NULL, 10) +#define tmsi_from_string(str) strtoul(str + 2, NULL, 16) #define GSM_SUBSCRIBER_NO_EXPIRATION 0x0 @@ -93,7 +93,7 @@ struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp, const char *imsi); struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp, - uint32_t tmsi); + const char *tmsi); struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp, const char *imsi); struct gsm_subscriber *subscr_get_by_extension(struct gsm_subscriber_group *sgrp, @@ -104,7 +104,7 @@ struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp, const char *imsi); int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason); struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_subscriber_group *sgrp, - uint32_t tmsi); + const char *tmsi); struct gsm_subscriber *subscr_active_by_imsi(struct gsm_subscriber_group *sgrp, const char *imsi); diff --git a/openbsc/src/libcommon/gsm_subscriber_base.c b/openbsc/src/libcommon/gsm_subscriber_base.c index a455824..c7fb831 100644 --- a/openbsc/src/libcommon/gsm_subscriber_base.c +++ b/openbsc/src/libcommon/gsm_subscriber_base.c @@ -118,12 +118,13 @@ struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp, } struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_subscriber_group *sgrp, - uint32_t tmsi) + const char *tmsi) { struct gsm_subscriber *subscr; + uint8_t tmsi_val = tmsi_from_string(tmsi); llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (subscr->tmsi == tmsi && subscr->group == sgrp) + if (subscr->tmsi == tmsi_val && subscr->group == sgrp) return subscr_get(subscr); } diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 0935fc5..56b5a08 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -47,7 +47,7 @@ static char *db_basename = NULL; static char *db_dirname = NULL; static dbi_conn conn; -#define SCHEMA_REVISION "4" +#define SCHEMA_REVISION "5" enum { SCHEMA_META, @@ -212,6 +212,7 @@ static int update_db_revision_2(void) } dbi_result_free(result); + LOGP(DDB, LOGL_NOTICE, "Migration complete.\n"); return 0; } @@ -357,6 +358,7 @@ static int update_db_revision_3(void) else dbi_result_free(result); + LOGP(DDB, LOGL_NOTICE, "Migration complete.\n"); return 0; rollback: @@ -369,6 +371,77 @@ rollback: return -EINVAL; } +static int update_db_revision_4(void) +{ + dbi_result select; + dbi_result update; + long long unsigned int id; + const char *tmsi_old; + uint32_t tmsi_new; + + LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 4\n"); + + /* Cycle through old TMSIs and convert them to the new format */ + select = dbi_conn_query(conn, "SELECT * FROM Subscriber"); + if (!select) { + LOGP(DDB, LOGL_ERROR, + "Failed fetch subscriber data the old Subscriber table " + "(upgrade from rev 4).\n"); + return -EINVAL; + } + + while (dbi_result_next_row(select)) { + /* Fetch the subscriber ID */ + id = dbi_result_get_ulonglong(select, "id"); + + /* Fetch an old TMSI value */ + tmsi_old = dbi_result_get_string(select, "tmsi"); + tmsi_new = atoi(tmsi_old); + + if (tmsi_new <= 0) { + LOGP(DDB, LOGL_ERROR, + "Failed to convert an old TMSI '%s', ignoring " + "(upgrade from rev 4).\n", tmsi_old); + continue; + } + + /* Update old TMSI */ + update = dbi_conn_queryf(conn, + "UPDATE Subscriber " + "SET tmsi = '0x%08x' " + "WHERE id = %llu", + tmsi_new, id); + + if (!update) { + LOGP(DDB, LOGL_ERROR, + "Failed update subscriber's TMSI " + "(upgrade from rev 4).\n"); + + dbi_result_free(select); + return -EINVAL; + } + + dbi_result_free(update); + } + dbi_result_free(select); + + /* We're done. Bump DB Meta revision to 5 */ + update = dbi_conn_query(conn, + "UPDATE Meta " + "SET value = '5' " + "WHERE key = 'revision'"); + if (!update) { + LOGP(DDB, LOGL_ERROR, + "Failed to update DB schema revision " + "(upgrade from rev 4).\n"); + return -EINVAL; + } + + dbi_result_free(update); + LOGP(DDB, LOGL_NOTICE, "Migration complete.\n"); + return 0; +} + static int check_db_revision(void) { dbi_result result; @@ -400,6 +473,12 @@ static int check_db_revision(void) dbi_result_free(result); return -EINVAL; } + } else if (!strcmp(rev_s, "4")) { + if (update_db_revision_4()) { + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%s'.\n", rev_s); + dbi_result_free(result); + return -EINVAL; + } } else if (!strcmp(rev_s, SCHEMA_REVISION)) { /* everything is fine */ } else { @@ -893,9 +972,10 @@ struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, subscr->id = dbi_result_get_ulonglong(result, "id"); db_set_from_query(subscr, result); - DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n", - subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension, - subscr->lac, subscr->authorized); + DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', " + "TMSI 0x%08x, EXTEN '%s', LAC %hu, AUTH %u\n", + subscr->id, subscr->imsi, subscr->name, subscr->tmsi, + subscr->extension, subscr->lac, subscr->authorized); dbi_result_free(result); get_equipment_by_subscr(subscr); @@ -935,7 +1015,7 @@ int db_subscriber_update(struct gsm_subscriber *subscr) int db_sync_subscriber(struct gsm_subscriber *subscriber) { dbi_result result; - char tmsi[14]; + char tmsi[11]; char *q_tmsi, *q_name, *q_extension; dbi_conn_quote_string_copy(conn, @@ -944,7 +1024,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber) subscriber->extension, &q_extension); if (subscriber->tmsi != GSM_RESERVED_TMSI) { - sprintf(tmsi, "%u", subscriber->tmsi); + sprintf(tmsi, "0x%08x", subscriber->tmsi); dbi_conn_quote_string_copy(conn, tmsi, &q_tmsi); @@ -1194,7 +1274,7 @@ int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsi int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber) { dbi_result result = NULL; - char tmsi[14]; + char tmsi[11]; char *tmsi_quoted; for (;;) { @@ -1205,7 +1285,7 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber) if (subscriber->tmsi == GSM_RESERVED_TMSI) continue; - sprintf(tmsi, "%u", subscriber->tmsi); + sprintf(tmsi, "0x%08x", subscriber->tmsi); dbi_conn_quote_string_copy(conn, tmsi, &tmsi_quoted); result = dbi_conn_queryf(conn, "SELECT * FROM Subscriber " diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 1524ec4..c9f1b66 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -653,8 +653,7 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb case GSM_MI_TYPE_TMSI: DEBUGPC(DMM, "\n"); /* look up the subscriber based on TMSI, request IMSI if it fails */ - subscr = subscr_get_by_tmsi(bts->network->subscr_group, - tmsi_from_string(mi_string)); + subscr = subscr_get_by_tmsi(bts->network->subscr_group, mi_string); if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ mm_tx_identity_req(conn, GSM_MI_TYPE_IMSI); @@ -972,20 +971,15 @@ static int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct m if (mi_type == GSM_MI_TYPE_IMSI) { DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n", - req->cm_service_type, gsm48_mi_type_name(mi_type), - mi_string); - subscr = subscr_get_by_imsi(bts->network->subscr_group, - mi_string); + req->cm_service_type, gsm48_mi_type_name(mi_type), mi_string); + subscr = subscr_get_by_imsi(bts->network->subscr_group, mi_string); } else if (mi_type == GSM_MI_TYPE_TMSI) { DEBUGPC(DMM, "serv_type=0x%02x MI(%s)=%s\n", - req->cm_service_type, gsm48_mi_type_name(mi_type), - mi_string); - subscr = subscr_get_by_tmsi(bts->network->subscr_group, - tmsi_from_string(mi_string)); + req->cm_service_type, gsm48_mi_type_name(mi_type), mi_string); + subscr = subscr_get_by_tmsi(bts->network->subscr_group, mi_string); } else { DEBUGPC(DMM, "mi_type is not expected: %d\n", mi_type); - return gsm48_tx_mm_serv_rej(conn, - GSM48_REJECT_INCORRECT_MESSAGE); + return gsm48_tx_mm_serv_rej(conn, GSM48_REJECT_INCORRECT_MESSAGE); } osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, (classmark2 + classmark2_len)); @@ -1038,13 +1032,11 @@ static int gsm48_rx_mm_imsi_detach_ind(struct gsm_subscriber_connection *conn, s switch (mi_type) { case GSM_MI_TYPE_TMSI: DEBUGPC(DMM, "\n"); - subscr = subscr_get_by_tmsi(bts->network->subscr_group, - tmsi_from_string(mi_string)); + subscr = subscr_get_by_tmsi(bts->network->subscr_group, mi_string); break; case GSM_MI_TYPE_IMSI: DEBUGPC(DMM, "\n"); - subscr = subscr_get_by_imsi(bts->network->subscr_group, - mi_string); + subscr = subscr_get_by_imsi(bts->network->subscr_group, mi_string); break; case GSM_MI_TYPE_IMEI: case GSM_MI_TYPE_IMEISV: @@ -1189,12 +1181,10 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_get_by_tmsi(bts->network->subscr_group, - tmsi_from_string(mi_string)); + subscr = subscr_get_by_tmsi(bts->network->subscr_group, mi_string); break; case GSM_MI_TYPE_IMSI: - subscr = subscr_get_by_imsi(bts->network->subscr_group, - mi_string); + subscr = subscr_get_by_imsi(bts->network->subscr_group, mi_string); break; } diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 57c10cf..d9761d9 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -46,7 +46,6 @@ extern struct llist_head *subscr_bsc_active_subscribers(void); int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq, gsm_cbfn *cb, void *cb_data); - /* * Struct for pending channel requests. This is managed in the * llist_head requests of each subscriber. The reference counting @@ -212,19 +211,18 @@ struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgr } struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp, - uint32_t tmsi) + const char *tmsi) { - char tmsi_string[14]; struct gsm_subscriber *subscr; + uint32_t tmsi_val = tmsi_from_string(tmsi); /* we might have a record in memory already */ llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) { - if (tmsi == subscr->tmsi) + if (tmsi_val == subscr->tmsi) return subscr_get(subscr); } - sprintf(tmsi_string, "%u", tmsi); - return get_subscriber(sgrp, GSM_SUBSCRIBER_TMSI, tmsi_string); + return get_subscriber(sgrp, GSM_SUBSCRIBER_TMSI, tmsi); } struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp, diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index f49c53a..19c15e1 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -189,7 +189,7 @@ static struct gsm_subscriber *get_subscr_by_argv(struct gsm_network *gsmnet, else if (!strcmp(type, "imsi")) return subscr_get_by_imsi(gsmnet->subscr_group, id); else if (!strcmp(type, "tmsi")) - return subscr_get_by_tmsi(gsmnet->subscr_group, atoi(id)); + return subscr_get_by_tmsi(gsmnet->subscr_group, id); else if (!strcmp(type, "id")) return subscr_get_by_id(gsmnet->subscr_group, atoi(id)); diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c index 14e0b71..88db15e 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c @@ -79,7 +79,7 @@ static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn switch (mi_type) { case GSM_MI_TYPE_TMSI: subscr = subscr_active_by_tmsi(conn->bts->network->subscr_group, - tmsi_from_string(mi_string)); + mi_string); break; case GSM_MI_TYPE_IMSI: subscr = subscr_active_by_imsi(conn->bts->network->subscr_group, diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c index e623c9c..d871f01 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c @@ -43,7 +43,7 @@ static struct osmo_bsc_data *osmo_bsc_data(struct vty *vty) static struct osmo_msc_data *osmo_msc_data(struct vty *vty) { - return vty->index; + return osmo_msc_data_find(bsc_gsmnet, (int) vty->index); } static struct cmd_node bsc_node = { @@ -70,7 +70,7 @@ DEFUN(cfg_net_msc, cfg_net_msc_cmd, return CMD_WARNING; } - vty->index = msc; + vty->index = (void *) index; vty->node = MSC_NODE; return CMD_SUCCESS; } diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index a02d1f8..faea820 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -200,7 +200,7 @@ int main() alice->lac=42; db_sync_subscriber(alice); /* Get by TMSI */ - snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi); + snprintf(scratch_str, sizeof(scratch_str), "0x%08x", alice->tmsi); alice_db = db_get_subscriber(GSM_SUBSCRIBER_TMSI, scratch_str); COMPARE(alice, alice_db); SUBSCR_PUT(alice_db); @@ -227,7 +227,7 @@ int main() db_subscriber_assoc_imei(alice, "1234567890"); db_subscriber_assoc_imei(alice, "6543560920"); /* Get by TMSI */ - snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi); + snprintf(scratch_str, sizeof(scratch_str), "0x%08x", alice->tmsi); alice_db = db_get_subscriber(GSM_SUBSCRIBER_TMSI, scratch_str); COMPARE(alice, alice_db); SUBSCR_PUT(alice_db); diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 781ef61..8ed57ca 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -93,7 +93,7 @@ static void test_mi_functionality(void) /* tmsi code */ mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi); gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len - 2); - COMPARE((uint32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi); + COMPARE((uint32_t)tmsi_from_string(mi_parsed), ==, tmsi); /* imsi code */ mi_len = gsm48_generate_mid_from_imsi(mi, imsi_odd);