diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index dc4f6d7a6..4a2311555 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 600699ae7..543f44ce2 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 2312e8abe..3e2d171ea 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; }