* add database handling
* fix IMSI handling

diff --git a/src/abis_rsl.c b/src/abis_rsl.c
index 6071378..54b7069 100644
--- a/src/abis_rsl.c
+++ b/src/abis_rsl.c
@@ -610,9 +610,6 @@
 	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 @@
 	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 a8f5a89..b9b9f8b 100644
--- a/src/bsc_hack.c
+++ b/src/bsc_hack.c
@@ -636,6 +636,18 @@
 	/* 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 4ef5ff9..3ef8b4d 100644
--- a/src/chan_alloc.c
+++ b/src/chan_alloc.c
@@ -63,7 +63,25 @@
 	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 2e0042a..679899b 100644
--- a/src/db.c
+++ b/src/db.c
@@ -69,7 +69,7 @@
 		"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 @@
 
 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 @@
 		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 447c263..83399d0 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <netinet/in.h>
 
+#include <openbsc/db.h>
 #include <openbsc/msgb.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
@@ -98,15 +99,12 @@
 #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 @@
 }
 
 /* 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_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 @@
 	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 @@
 		/* 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 @@
 		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 6a67c49..fcf91ae 100644
--- a/src/gsm_subscriber.c
+++ b/src/gsm_subscriber.c
@@ -20,24 +20,63 @@
  *
  */
 
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 
 #include <openbsc/gsm_subscriber.h>
+#include <openbsc/db.h>
 
-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 fae6b0d..a8e5dca 100644
--- a/src/misdn.c
+++ b/src/misdn.c
@@ -286,8 +286,10 @@
 
 		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);