From 75a983fab09567a59bcacf67416942f35cffe254 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 27 Dec 2008 21:34:06 +0000 Subject: [PATCH] * add database handling * fix IMSI handling --- src/abis_rsl.c | 6 ++--- src/bsc_hack.c | 12 +++++++++ src/chan_alloc.c | 20 ++++++++++++++- src/db.c | 15 ++++++++--- src/gsm_04_08.c | 41 ++++++++++++++++++++++-------- src/gsm_subscriber.c | 59 ++++++++++++++++++++++++++++++++++++-------- src/misdn.c | 2 ++ 7 files changed, 128 insertions(+), 27 deletions(-) diff --git a/src/abis_rsl.c b/src/abis_rsl.c index 60713785b..54b706936 100644 --- a/src/abis_rsl.c +++ b/src/abis_rsl.c @@ -610,9 +610,6 @@ static int rsl_rx_chan_rqd(struct msgb *msg) arfcn = lchan->ts->trx->arfcn; subch = lchan->nr; - DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %u\n", - arfcn, ts_number, subch, lchan->type); - rsl_chan_activate_lchan(lchan, 0x00, rqd_ta); /* create IMMEDIATE ASSIGN 04.08 messge */ @@ -631,6 +628,9 @@ static int rsl_rx_chan_rqd(struct msgb *msg) ia.timing_advance = rqd_ta; ia.mob_alloc_len = 0; + DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %u chan_nr=0x%02x\n", + arfcn, ts_number, subch, lchan->type, ia.chan_desc.chan_nr); + /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */ return rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia); } diff --git a/src/bsc_hack.c b/src/bsc_hack.c index a8f5a8962..b9b9f8beb 100644 --- a/src/bsc_hack.c +++ b/src/bsc_hack.c @@ -636,6 +636,18 @@ int main(int argc, char **argv) /* parse options */ handle_options(argc, argv); + 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"); + bootstrap_network(); while (1) { diff --git a/src/chan_alloc.c b/src/chan_alloc.c index 4ef5ff902..3ef8b4d24 100644 --- a/src/chan_alloc.c +++ b/src/chan_alloc.c @@ -63,7 +63,25 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts, int i, j; for (i = 0; i < bts->num_trx; i++) { struct gsm_bts_trx *trx = &bts->trx[i]; - for (j = 0; j < 8; j++) { + int from, to; + + /* the following constraints are pure policy, + * no requirement to put this restriction in place */ + switch (pchan) { + case GSM_PCHAN_CCCH: + case GSM_PCHAN_CCCH_SDCCH4: + from = 0; to = 0; + break; + case GSM_PCHAN_SDCCH8_SACCH8C: + from = 1; to = 1; + break; + case GSM_PCHAN_TCH_F: + case GSM_PCHAN_TCH_H: + from = 2; to = 7; + break; + } + + for (j = from; j <= to; j++) { struct gsm_bts_trx_ts *ts = &trx->ts[j]; if (ts->pchan == GSM_PCHAN_NONE) { ts->pchan = pchan; diff --git a/src/db.c b/src/db.c index 2e0042a6e..679899b4b 100644 --- a/src/db.c +++ b/src/db.c @@ -69,7 +69,7 @@ int db_prepare() { "created TIMESTAMP NOT NULL, " "updated TIMESTAMP NOT NULL, " "imsi NUMERIC UNIQUE NOT NULL, " - "tmsi NUMERIC UNIQUE, " + "tmsi TEXT UNIQUE, " "extension TEXT UNIQUE, " "lac INTEGER NOT NULL DEFAULT 0, " "authorized INTEGER NOT NULL DEFAULT 0" @@ -146,6 +146,8 @@ struct gsm_subscriber* db_create_subscriber(char imsi[GSM_IMSI_LENGTH]) { int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber) { dbi_result result; + char *string; + switch (field) { case GSM_SUBSCRIBER_IMSI: result = dbi_conn_queryf(conn, @@ -174,9 +176,16 @@ int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* su dbi_result_free(result); return 1; } + memset(subscriber, 0, sizeof(*subscriber)); subscriber->id = dbi_result_get_ulonglong(result, "id"); - strncpy(subscriber->imsi, dbi_result_get_string(result, "imsi"), GSM_IMSI_LENGTH); - strncpy(subscriber->tmsi, dbi_result_get_string(result, "tmsi"), GSM_TMSI_LENGTH); + string = dbi_result_get_string(result, "imsi"); + if (string) + strncpy(subscriber->imsi, string, GSM_IMSI_LENGTH); + + string = dbi_result_get_string(result, "tmsi"); + if (string) + strncpy(subscriber->tmsi, string, GSM_TMSI_LENGTH); + // FIXME handle extension subscriber->lac = dbi_result_get_uint(result, "lac"); subscriber->authorized = dbi_result_get_uint(result, "authorized"); diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c index 447c2631e..83399d021 100644 --- a/src/gsm_04_08.c +++ b/src/gsm_04_08.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -98,15 +99,12 @@ static void generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc, #define TMSI_LEN 4 #define MID_TMSI_LEN (TMSI_LEN + 2) -static void generate_mid_from_tmsi(u_int8_t *buf, u_int8_t *tmsi_bcd) +static void generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi) { buf[0] = GSM48_IE_MOBILE_ID; buf[1] = MID_TMSI_LEN; buf[2] = 0xf0 | GSM_MI_TYPE_TMSI; - buf[3] = tmsi_bcd[0]; - buf[4] = tmsi_bcd[1]; - buf[5] = tmsi_bcd[2]; - buf[6] = tmsi_bcd[3]; + *((u_int32_t *) &buf[3]) = htonl(tmsi); } static struct msgb *gsm48_msgb_alloc(void) @@ -144,7 +142,7 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) } /* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */ -int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int8_t *tmsi) +int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi) { struct gsm_bts *bts = lchan->ts->trx->bts; struct msgb *msg = gsm48_msgb_alloc(); @@ -241,14 +239,33 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type) static int mm_rx_id_resp(struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); + struct gsm_lchan *lchan = msg->lchan; u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK; char mi_string[MI_SIZE]; + u_int32_t tmsi; mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]); DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n", mi_type, mi_string); - /* FIXME: update subscribe <-> IMEI mapping */ + switch (mi_type) { + case GSM_MI_TYPE_IMSI: + if (!lchan->subscr) + lchan->subscr = db_create_subscriber(mi_string); + if (lchan->subscr && lchan->subscr->authorized) { + /* FIXME: check if we've recently received UPDATE REQUEST */ + db_subscriber_alloc_tmsi(lchan->subscr); + tmsi = strtoul(lchan->subscr->tmsi, NULL, 16); + return gsm0408_loc_upd_acc(msg->lchan, tmsi); + } + break; + case GSM_MI_TYPE_IMEI: + /* update subscribe <-> IMEI mapping */ + if (lchan->subscr) + db_subscriber_assoc_imei(lchan->subscr, mi_string); + break; + } + return 0; } #define MI_SIZE 32 @@ -260,6 +277,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) struct gsm48_loc_upd_req *lu; struct gsm_subscriber *subscr; u_int8_t mi_type; + u_int32_t tmsi; char mi_string[MI_SIZE]; int rc; @@ -275,7 +293,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) /* we always want the IMEI, too */ rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMEISV); /* look up subscriber based on IMSI */ - subscr = subscr_get_by_imsi(lu->mi); + subscr = db_create_subscriber(mi_string); break; case GSM_MI_TYPE_TMSI: /* we always want the IMEI, too */ @@ -297,17 +315,20 @@ static int mm_rx_loc_upd_req(struct msgb *msg) break; } - if (!subscr) { + if (!subscr || !subscr->authorized) { /* 0x16 is congestion */ gsm0408_loc_upd_rej(msg->lchan, 0x16); rsl_chan_release(msg->lchan); return -EINVAL; } + db_subscriber_alloc_tmsi(subscr); + msg->lchan->subscr = subscr; subscr_update(subscr, bts); + tmsi = strtoul(subscr->tmsi, NULL, 16); - return gsm0408_loc_upd_acc(msg->lchan, subscr->tmsi); + return gsm0408_loc_upd_acc(msg->lchan, tmsi); } static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan) diff --git a/src/gsm_subscriber.c b/src/gsm_subscriber.c index 6a67c49e3..fcf91ae51 100644 --- a/src/gsm_subscriber.c +++ b/src/gsm_subscriber.c @@ -20,24 +20,63 @@ * */ +#include +#include +#include +#include #include +#include -static struct gsm_subscriber subscr = { - .name = "Test User 1", - .tmsi = { 0x22, 0x33, 0x44, 0x55 }, -}; - -struct gsm_subscriber *subscr_get_by_tmsi(u_int8_t *tmsi) +struct gsm_subscriber *subscr_alloc(void) { - return &subscr; + struct gsm_subscriber *s; + + s = malloc(sizeof(struct gsm_subscriber)); + if (!s) + return NULL; + + memset(s, 0, sizeof(*s)); + + return s; } -struct gsm_subscriber *subscr_get_by_imsi(u_int8_t *imsi) + +void subscr_free(struct gsm_subscriber *subscr) { - return &subscr; + free(subscr); +} + +struct gsm_subscriber *subscr_get_by_tmsi(char *tmsi) +{ + struct gsm_subscriber *subscr = subscr_alloc(); + + strncpy(subscr->tmsi, tmsi, sizeof(subscr->tmsi)); + subscr->tmsi[sizeof(subscr->tmsi)-1] = '\0'; + + if (db_get_subscriber(GSM_SUBSCRIBER_TMSI, subscr) != 0) { + subscr_free(subscr); + subscr = NULL; + } + + return subscr; +} + +struct gsm_subscriber *subscr_get_by_imsi(char *imsi) +{ + struct gsm_subscriber *subscr = subscr_alloc(); + + strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)); + subscr->imsi[sizeof(subscr->imsi)-1] = '\0'; + + if (db_get_subscriber(GSM_SUBSCRIBER_IMSI, subscr) != 0) { + subscr_free(subscr); + subscr = NULL; + } + + return subscr; } int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts) { - return 0; + return db_set_subscriber(s); } diff --git a/src/misdn.c b/src/misdn.c index fae6b0ddc..a8e5dca9b 100644 --- a/src/misdn.c +++ b/src/misdn.c @@ -286,8 +286,10 @@ static int handle_tsX_read(struct bsc_fd *bfd) msg->l2h = msg->data + MISDN_HEADER_LEN; +#if 0 fprintf(stdout, "BCHAN RX: "); hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN); +#endif if (!e1h->ts2_fd) e1h->ts2_fd = open("/tmp/ts2.dump", O_WRONLY|O_APPEND|O_CREAT, 0660);