From c1c4a95f734b54496c07b4a40c2ab5643195087b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 5 Jul 2009 13:41:40 +0200 Subject: [PATCH 1/2] remove SI3 and SI4 rest octets As Dieter has pointed out, we currently send incorrect information in the rest octets, particularly about our GPRS capability. Since the format of the rest octets is highly complex, and we don't actually need any of those features yet, we might just fill them with padding. --- openbsc/src/bsc_hack.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 13438b9c..384da54b 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -696,14 +696,7 @@ SYSTEM INFORMATION TYPE 3 cell not barred for access call reestablishment not allowed Access Control Class = 0000 - SI 3 Rest Octets - Cell Bar Qualify (CBQ): 0 - Cell Reselect Offset = 0 dB - Temporary Offset = 0 dB - Penalty Time = 20 s - System Information 2ter Indicator (2TI): 0 = not available - Early Classmark Sending Control (ECSC): 0 = forbidden - Scheduling Information is not sent in SYSTEM INFORMATION TYPE 9 on the BCCH + SI 3 Rest Octets (not present) */ static u_int8_t si3[] = { /* header */0x49, 0x06, 0x1B, @@ -713,7 +706,7 @@ static u_int8_t si3[] = { /* option*/0x28, /* selection*/0x62, 0x00, /* rach */0xD5, 0x00, 0x00, - /* reset*/0x80, 0x00, 0x00, 0x2B + /* rest */ 0x2B, 0x2B, 0x2B, 0x2B }; /* @@ -734,24 +727,20 @@ SYSTEM INFORMATION TYPE 4 cell not barred for access call reestablishment not allowed Access Control Class = 0000 - Channel Description + CBCH Channel Description Type = SDCCH/4[2] Timeslot Number: 0 Training Sequence Code: 7h ARFCN: 1 - SI Rest Octets - Cell Bar Qualify (CBQ): 0 - Cell Reselect Offset = 0 dB - Temporary Offset = 0 dB - Penalty Time = 20 s + SI Rest Octets (not present) */ static u_int8_t si4[] = { /* header */0x41, 0x06, 0x1C, /* lai */0x00, 0xF1, 0x10, 0x00, 0x01, /* sel */0x62, 0x00, /* rach*/0xD5, 0x00, 0x00, - /* var */0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/, 0x80, 0x00, 0x00, - 0x2B, 0x2B, 0x2B + /* cbch chan desc */ 0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/, + /* rest octets */ 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B }; /* From f6845a7d9f67976b93aa1fecaf12dcf4f74f3b75 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 5 Jul 2009 14:08:13 +0200 Subject: [PATCH 2/2] Store classmark1/2/3 in equipment SQL table For further evaluation/analysis, this patch stores the classmark 1, 2 and 3 values of every equipment in the SQL database. We can use this non-volatile data to determine the supported features for each handset that we've ever seen on our network. --- openbsc/include/openbsc/gsm_subscriber.h | 25 +++++++++++----- openbsc/src/db.c | 38 ++++++++++++++++++++++++ openbsc/src/gsm_04_08.c | 21 ++++++------- 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index dc4f6d7a..4a231155 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -11,6 +11,18 @@ #define GSM_NAME_LENGTH 128 #define GSM_EXTENSION_LENGTH 128 +struct gsm_equipment { + long long unsigned int id; + char imei[GSM_IMEI_LENGTH]; + char name[GSM_NAME_LENGTH]; + + struct gsm48_classmark1 classmark1; + u_int8_t classmark2_len; + u_int8_t classmark2[3]; + u_int8_t classmark3_len; + u_int8_t classmark3[14]; +}; + struct gsm_subscriber { struct gsm_network *net; long long unsigned int id; @@ -21,18 +33,14 @@ struct gsm_subscriber { char extension[GSM_EXTENSION_LENGTH]; int authorized; + /* Every user can only have one equipment in use at any given + * point in time */ + struct gsm_equipment equipment; + /* for internal management */ int use_count; struct llist_head entry; - /* those are properties of the equipment, but they - * are applicable to the subscriber at the moment */ - struct gsm48_classmark1 classmark1; - u_int8_t classmark2_len; - u_int8_t classmark2[3]; - u_int8_t classmark3_len; - u_int8_t classmark3[14]; - /* pending requests */ int in_callback; struct llist_head requests; @@ -47,6 +55,7 @@ enum gsm_subscriber_field { enum gsm_subscriber_update_reason { GSM_SUBSCRIBER_UPDATE_ATTACHED, GSM_SUBSCRIBER_UPDATE_DETACHED, + GSM_SUBSCRIBER_UPDATE_EQUIPMENT, }; struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 600699ae..543f44ce 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -1,6 +1,7 @@ /* Simple HLR/VLR database backend using dbi */ /* (C) 2008 by Jan Luebbe * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009 by Harald Welte * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -59,6 +60,9 @@ static char *create_stmts[] = { "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " "name TEXT, " + "classmark1 NUMERIC, " + "classmark2 BLOB, " + "classmark3 BLOB, " "imei NUMERIC UNIQUE NOT NULL" ")", "CREATE TABLE IF NOT EXISTS EquipmentWatch (" @@ -288,6 +292,37 @@ int db_sync_subscriber(struct gsm_subscriber* subscriber) { return 0; } +int db_sync_equipment(struct gsm_equipment *equip) +{ + dbi_result result; + unsigned char *cm2, *cm3; + + dbi_conn_quote_binary_copy(conn, equip->classmark2, + equip->classmark2_len, &cm2); + dbi_conn_quote_binary_copy(conn, equip->classmark3, + equip->classmark3_len, &cm3); + + result = dbi_conn_queryf(conn, + "UPDATE Equipment SET " + "updated = datetime('now'), " + "classmark1 = %u, " + "classmark2 = %s, " + "classmark3 = %s " + "WHERE imei = '%s' ", + equip->classmark1, cm2, cm3, equip->imei); + + free(cm2); + free(cm3); + + if (!result) { + printf("DB: Failed to update Equipment\n"); + return -EIO; + } + + dbi_result_free(result); + return 0; +} + int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) { dbi_result result=NULL; char* tmsi_quoted; @@ -322,6 +357,9 @@ int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char imei[GSM_IM u_int64_t equipment_id, watch_id; dbi_result result; + strncpy(subscriber->equipment.imei, imei, + sizeof(subscriber->equipment.imei)-1), + result = dbi_conn_queryf(conn, "INSERT OR IGNORE INTO Equipment " "(imei, created, updated) " diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 2312e8ab..3e2d171e 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1469,8 +1469,9 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) subscr_put(subscr); } - subscr->classmark2_len = classmark2_len; - memcpy(subscr->classmark2, classmark2, classmark2_len); + subscr->equipment.classmark2_len = classmark2_len; + memcpy(subscr->equipment.classmark2, classmark2, classmark2_len); + db_sync_equipment(&subscr->equipment); return gsm48_tx_mm_serv_ack(msg->lchan); } @@ -1602,8 +1603,9 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) DEBUGP(DRR, "<- Channel was requested by %s\n", subscr->name ? subscr->name : subscr->imsi); - subscr->classmark2_len = *classmark2_lv; - memcpy(subscr->classmark2, classmark2_lv+1, *classmark2_lv); + subscr->equipment.classmark2_len = *classmark2_lv; + memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv); + db_sync_equipment(&subscr->equipment); if (!msg->lchan->subscr) { msg->lchan->subscr = subscr; @@ -1667,16 +1669,15 @@ static int gsm48_rx_rr_classmark(struct msgb *msg) DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len); } if (subscr) { - subscr->classmark2_len = cm2_len; - memcpy(subscr->classmark2, cm2, cm2_len); + subscr->equipment.classmark2_len = cm2_len; + memcpy(subscr->equipment.classmark2, cm2, cm2_len); if (cm3) { - subscr->classmark3_len = cm3_len; - memcpy(subscr->classmark3, cm3, cm3_len); + subscr->equipment.classmark3_len = cm3_len; + memcpy(subscr->equipment.classmark3, cm3, cm3_len); } + db_sync_equipment(&subscr->equipment); } - /* FIXME: store the classmark2/3 values with the equipment register */ - return 0; }