This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Vadim Yanitskiy axilirator at gmail.comIn 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 <axilirator at gmail.com> --- 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); -- 2.7.4