diff --git a/include/openbsc/db.h b/include/openbsc/db.h index 9501ec8f3..d102dfe59 100644 --- a/include/openbsc/db.h +++ b/include/openbsc/db.h @@ -20,27 +20,17 @@ #ifndef _DB_H #define _DB_H -#include +#include -#define NUMBER_LENGTH 32 - -typedef struct { - uint64_t imsi; - uint64_t tmsi; - char number[NUMBER_LENGTH]; - uint16_t lac; -} db_subscriber; +#include int db_init(); int db_prepare(); int db_fini(); -int db_insert_imei(uint64_t imei); - -int db_insert_imsi(uint64_t imsi); -int db_imsi_set_tmsi(uint64_t imsi, uint64_t tmsi); -int db_imsi_set_lac(uint64_t imsi, uint16_t lac); -int db_imsi_get_subscriber(uint64_t imsi, db_subscriber* subscriber); -int db_tmsi_get_subscriber(uint64_t tmsi, db_subscriber* subscriber); +struct gsm_subscriber* db_create_subscriber(char imsi[GSM_IMSI_LENGTH]); +int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber); +int db_set_subscriber(struct gsm_subscriber* subscriber); +int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber); #endif /* _DB_H */ diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h index 5bdf57952..d2c0d4f71 100644 --- a/include/openbsc/gsm_subscriber.h +++ b/include/openbsc/gsm_subscriber.h @@ -4,13 +4,20 @@ #include #include "gsm_data.h" +#define GSM_IMSI_LENGTH 17 +#define GSM_TMSI_LENGTH 17 +#define GSM_NAME_LENGTH 128 + struct gsm_subscriber { - char *name; - u_int8_t tmsi[4]; + char imsi[GSM_IMSI_LENGTH]; + char tmsi[GSM_TMSI_LENGTH]; + u_int16_t lac; + char name[GSM_NAME_LENGTH]; }; -struct gsm_subscriber *subscr_get_by_tmsi(u_int8_t *tmsi); -struct gsm_subscriber *subscr_get_by_imsi(u_int8_t *imsi); -int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts); +enum gsm_subscriber_field { + GSM_SUBSCRIBER_IMSI, + GSM_SUBSCRIBER_TMSI, +}; #endif /* _GSM_SUBSCR_H */ diff --git a/src/Makefile.am b/src/Makefile.am index c2449bdba..1557a1a92 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,8 @@ AM_CFLAGS=-Wall sbin_PROGRAMS = bsc_hack db_test bsc_hack_SOURCES = bsc_hack.c misdn.c abis_rsl.c abis_nm.c gsm_04_08.c gsm_data.c \ - gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c + gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c db.c +bsc_hack_LDADD = -ldl -ldbi db_test_SOURCES = db_test.c db.c db_test_LDADD = -ldl -ldbi diff --git a/src/db.c b/src/db.c index 1c412c2f2..4ee00b3ea 100644 --- a/src/db.c +++ b/src/db.c @@ -20,198 +20,218 @@ #include #include +#include +#include #include dbi_conn conn; void db__error_func(dbi_conn conn, void* data) { - const char* msg; - dbi_conn_error(conn, &msg); - printf("DBI: %s\n", msg); + const char* msg; + dbi_conn_error(conn, &msg); + printf("DBI: %s\n", msg); } int db_init() { - dbi_initialize(NULL); - conn = dbi_conn_new("sqlite3"); - - dbi_conn_error_handler( conn, db__error_func, NULL ); + dbi_initialize(NULL); + conn = dbi_conn_new("sqlite3"); + if (conn==NULL) { + printf("DB: Failed to create connection.\n"); + return 1; + } - /* MySQL - dbi_conn_set_option(conn, "host", "localhost"); - dbi_conn_set_option(conn, "username", "your_name"); - dbi_conn_set_option(conn, "password", "your_password"); - dbi_conn_set_option(conn, "dbname", "your_dbname"); - dbi_conn_set_option(conn, "encoding", "UTF-8"); - */ + dbi_conn_error_handler( conn, db__error_func, NULL ); - /* SqLite 3 */ - dbi_conn_set_option(conn, "sqlite3_dbdir", "/tmp"); - dbi_conn_set_option(conn, "dbname", "hlr.sqlite3"); + /* MySQL + dbi_conn_set_option(conn, "host", "localhost"); + dbi_conn_set_option(conn, "username", "your_name"); + dbi_conn_set_option(conn, "password", "your_password"); + dbi_conn_set_option(conn, "dbname", "your_dbname"); + dbi_conn_set_option(conn, "encoding", "UTF-8"); + */ - if (dbi_conn_connect(conn) < 0) { - return 1; - } + /* SqLite 3 */ + dbi_conn_set_option(conn, "sqlite3_dbdir", "/tmp"); + dbi_conn_set_option(conn, "dbname", "hlr.sqlite3"); - return 0; + if (dbi_conn_connect(conn) < 0) { + return 1; + } + + return 0; } int db_prepare() { - dbi_result result; - result = dbi_conn_query(conn, - "CREATE TABLE IF NOT EXISTS Subscriber (" - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "imsi INTEGER UNIQUE NOT NULL, " - "tmsi INTEGER UNIQUE, " - "extension TEXT UNIQUE, " - "lac INTEGER" - ")" - ); - if (result==NULL) { - printf("DB: Failed to create Subscriber table.\n"); - return 1; - } - dbi_result_free(result); - result = dbi_conn_query(conn, - "CREATE TABLE IF NOT EXISTS Equipment (" - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "imei INTEGER UNIQUE NOT NULL" - ")" - ); - if (result==NULL) { - printf("DB: Failed to create Equipment table.\n"); - return 1; - } - dbi_result_free(result); - return 0; + dbi_result result; + result = dbi_conn_query(conn, + "CREATE TABLE IF NOT EXISTS Subscriber (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "imsi NUMERIC UNIQUE NOT NULL, " + "tmsi NUMERIC UNIQUE, " + "extension TEXT UNIQUE, " + "lac INTEGER" + ")" + ); + if (result==NULL) { + printf("DB: Failed to create Subscriber table.\n"); + return 1; + } + dbi_result_free(result); + result = dbi_conn_query(conn, + "CREATE TABLE IF NOT EXISTS Equipment (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "imei NUMERIC UNIQUE NOT NULL" + ")" + ); + if (result==NULL) { + printf("DB: Failed to create Equipment table.\n"); + return 1; + } + dbi_result_free(result); + return 0; } int db_fini() { - dbi_conn_close(conn); - dbi_shutdown(); + dbi_conn_close(conn); + dbi_shutdown(); + return 0; } -int db_insert_imei(uint64_t imei) { - dbi_result result; - result = dbi_conn_queryf(conn, - "INSERT OR IGNORE INTO Equipment " - "(imei) " - "VALUES " - "(%llu) ", - imei - ); - if (result==NULL) { - printf("DB: Failed to create Equipment by IMEI.\n"); - return 1; - } - dbi_result_free(result); - return 0; +int db_insert_imei(u_int64_t imei) { + dbi_result result; + result = dbi_conn_queryf(conn, + "INSERT OR IGNORE INTO Equipment " + "(imei) " + "VALUES " + "(%llu) ", + imei + ); + if (result==NULL) { + printf("DB: Failed to create Equipment by IMEI.\n"); + return 1; + } + dbi_result_free(result); + return 0; } -int db_insert_imsi(uint64_t imsi) { - dbi_result result; - result = dbi_conn_queryf(conn, - "INSERT OR IGNORE INTO Subscriber " - "(imsi) " - "VALUES " - "(%llu) ", - imsi - ); - if (result==NULL) { - printf("DB: Failed to create Subscriber by IMSI.\n"); - return 1; - } - dbi_result_free(result); - return 0; +struct gsm_subscriber* db_create_subscriber(char imsi[GSM_IMSI_LENGTH]) { + dbi_result result; + struct gsm_subscriber* subscriber; + subscriber = malloc(sizeof(*subscriber)); + if (!subscriber) + return NULL; + memset(subscriber, 0, sizeof(*subscriber)); + strncpy(subscriber->imsi, imsi, GSM_IMSI_LENGTH-1); + if (!db_get_subscriber(GSM_SUBSCRIBER_IMSI, subscriber)) { + return subscriber; + } + result = dbi_conn_queryf(conn, + "INSERT OR IGNORE INTO Subscriber " + "(imsi) " + "VALUES " + "(%s) ", + imsi + ); + if (result==NULL) { + printf("DB: Failed to create Subscriber by IMSI.\n"); + } + dbi_result_free(result); + printf("DB: New Subscriber: IMSI %s\n", subscriber->imsi); + return subscriber; } -int db_imsi_set_tmsi(uint64_t imsi, uint64_t tmsi) { - if (db_insert_imsi(imsi)) { - return 1; - } - dbi_result result; - result = dbi_conn_queryf(conn, - "UPDATE Subscriber " - "SET tmsi = %llu " - "WHERE imsi = %llu ", - tmsi, imsi - ); - if (result==NULL) { - printf("DB: Failed to update Subscriber with TMSI by IMSI.\n"); - return 1; - } - dbi_result_free(result); - return 0; +int db__parse_subscriber(dbi_result result, struct gsm_subscriber* subscriber) { + return 0; } -int db_imsi_set_lac(uint64_t imsi, uint16_t lac) { - if (db_insert_imsi(imsi)) { - return 1; - } - dbi_result result; - result = dbi_conn_queryf(conn, - "UPDATE Subscriber " - "SET lac = %u " - "WHERE imsi = %llu ", - lac, imsi - ); - if (result==NULL) { - printf("DB: Failed to update Subscriber with LAC by IMSI.\n"); - return 1; - } - dbi_result_free(result); - return 0; +int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber) { + dbi_result result; + switch (field) { + case GSM_SUBSCRIBER_IMSI: + result = dbi_conn_queryf(conn, + "SELECT * FROM Subscriber " + "WHERE imsi = %s ", + subscriber->imsi + ); + break; + case GSM_SUBSCRIBER_TMSI: + result = dbi_conn_queryf(conn, + "SELECT * FROM Subscriber " + "WHERE tmsi = %s ", + subscriber->tmsi + ); + break; + default: + printf("DB: Unknown query selector for Subscriber.\n"); + return 1; + } + if (result==NULL) { + printf("DB: Failed to query Subscriber.\n"); + return 1; + } + if (!dbi_result_next_row(result)) { + printf("DB: Failed to find the Subscriber.\n"); + dbi_result_free(result); + return 1; + } + strncpy(subscriber->imsi, dbi_result_get_string(result, "imsi"), GSM_IMSI_LENGTH); + strncpy(subscriber->tmsi, dbi_result_get_string(result, "tmsi"), GSM_TMSI_LENGTH); + // FIXME handle extension + subscriber->lac = dbi_result_get_uint(result, "lac"); + printf("DB: Found Subscriber: IMSI %s, TMSI %s, LAC %hu\n", subscriber->imsi, subscriber->tmsi, subscriber->lac); + dbi_result_free(result); + return 0; } -int db__parse_subscriber(dbi_result result, db_subscriber* subscriber) { - if (!dbi_result_first_row(result)) { - printf("DB: Failed to find Subscriber.\n"); - return 1; - } - subscriber->imsi = dbi_result_get_ulonglong(result, "imsi"); - subscriber->tmsi = dbi_result_get_ulonglong(result, "tmsi"); - // FIXME handle extension - subscriber->lac = dbi_result_get_uint(result, "lac"); - printf("DB: Subscriber: IMSI %llu, TMSI %llu, LAC %hu\n", subscriber->imsi, subscriber->tmsi, subscriber->lac); - return 0; +int db_set_subscriber(struct gsm_subscriber* subscriber) { + dbi_result result; + result = dbi_conn_queryf(conn, + "UPDATE Subscriber " + "SET tmsi = %s, lac = %i " + "WHERE imsi = %s ", + subscriber->tmsi, subscriber->lac, subscriber->imsi + ); + if (result==NULL) { + printf("DB: Failed to update Subscriber (by IMSI).\n"); + return 1; + } + dbi_result_free(result); + return 0; } -int db_imsi_get_subscriber(uint64_t imsi, db_subscriber* subscriber) { - dbi_result result; - result = dbi_conn_queryf(conn, - "SELECT * FROM Subscriber " - "WHERE imsi = %llu ", - imsi - ); - if (result==NULL) { - printf("DB: Failed to find Subscriber by IMSI.\n"); - return 1; - } - if (db__parse_subscriber(result, subscriber)) { - printf("DB: Failed to parse Subscriber.\n"); - dbi_result_free(result); - return 1; - } - dbi_result_free(result); - return 0; -} - -int db_tmsi_get_subscriber(uint64_t tmsi, db_subscriber* subscriber) { - dbi_result result; - result = dbi_conn_queryf(conn, - "SELECT * FROM Subscriber " - "WHERE tmsi = %llu ", - tmsi - ); - if (result==NULL) { - printf("DB: Failed to find Subscriber by TMSI.\n"); - return 1; - } - if (db__parse_subscriber(result, subscriber)) { - printf("DB: Failed to parse Subscriber.\n"); - dbi_result_free(result); - return 1; - } - dbi_result_free(result); - return 0; +int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) { + int error; + dbi_result result=NULL; + char* tmsi_quoted; + for (;;) { + sprintf(subscriber->tmsi, "%i", rand() % 1000000); // FIXME how many nibbles do we want for the tmsi? + result = dbi_conn_queryf(conn, + "SELECT * FROM Subscriber " + "WHERE tmsi = %s ", + subscriber->tmsi + ); + if (result==NULL) { + printf("DB: Failed to query Subscriber.\n"); + return 1; + } + printf("%s\n", subscriber->tmsi); + printf("count %llu\n", dbi_result_get_numrows(result)); + printf("curr %llu\n", dbi_result_get_currow(result)); + printf("next %llu\n", dbi_result_next_row(result)); + printf("count %llu\n", dbi_result_get_numrows(result)); + printf("curr %llu\n", dbi_result_get_currow(result)); + if (dbi_result_get_numrows(result)){ + dbi_result_free(result); + continue; + } + if (!dbi_result_next_row(result)) { + printf("curr %llu\n", dbi_result_get_currow(result)); + dbi_result_free(result); + printf("DB: Allocated TMSI %s for IMSI %s.\n", subscriber->tmsi, subscriber->imsi); + return db_set_subscriber(subscriber); + } + dbi_result_free(result); + } + return 0; } diff --git a/src/db_test.c b/src/db_test.c index ebfae2f5d..74d645f24 100644 --- a/src/db_test.c +++ b/src/db_test.c @@ -20,31 +20,46 @@ #include #include +#include int main() { - if (db_init()) { - printf("DB: Failed to init database. Please check the option settings.\n"); - return 1; - } - printf("DB: Database initialized.\n"); + if (db_init()) { + printf("DB: Failed to init database. Please check the option settings.\n"); + return 1; + } + printf("DB: Database initialized.\n"); - if (db_prepare()) { - printf("DB: Failed to prepare database.\n"); - return 1; - } - printf("DB: Database prepared.\n"); + if (db_prepare()) { + printf("DB: Failed to prepare database.\n"); + return 1; + } + printf("DB: Database prepared.\n"); - db_insert_imsi(3243245432351LLU); - db_insert_imsi(3243245432352LLU); - db_imsi_set_tmsi(3243245432345LLU, 99999999LLU); - db_imsi_set_lac(3243245432345LLU, 42); + struct gsm_subscriber *alice = NULL; - db_subscriber alice; - db_imsi_get_subscriber(3243245432345LLU, &alice); - db_tmsi_get_subscriber(99999999LLU, &alice); + alice = db_create_subscriber("3243245432345"); + db_subscriber_alloc_tmsi(alice); + alice->lac=42; + db_set_subscriber(alice); + db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice); + free(alice); - db_fini(); + alice = db_create_subscriber("3693245423445"); + db_subscriber_alloc_tmsi(alice); + alice->lac=42; + db_set_subscriber(alice); + db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice); + free(alice); - return 0; + alice = db_create_subscriber("9993245423445"); + db_subscriber_alloc_tmsi(alice); + alice->lac=42; + db_set_subscriber(alice); + db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice); + free(alice); + + db_fini(); + + return 0; }