working state up to location update and classmark inquiry

diff --git a/src/abis_rsl.c b/src/abis_rsl.c
index 54b7069..9c1c293 100644
--- a/src/abis_rsl.c
+++ b/src/abis_rsl.c
@@ -374,7 +374,7 @@
 	dh->chan_nr = RSL_CHAN_PCH_AGCH;
 
 	msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
-	msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len, ms_ident);
+	msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
 	msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
 
 	msg->trx = bts->c0;
diff --git a/src/bsc_hack.c b/src/bsc_hack.c
index b9b9f8b..2838ff8 100644
--- a/src/bsc_hack.c
+++ b/src/bsc_hack.c
@@ -30,7 +30,10 @@
 #define _GNU_SOURCE
 #include <getopt.h>
 
+#include <openbsc/db.h>
+#include <openbsc/timer.h>
 #include <openbsc/gsm_data.h>
+#include <openbsc/gsm_04_08.h>
 #include <openbsc/select.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/abis_nm.h>
@@ -631,6 +634,74 @@
 	}
 }
 
+static struct timer_list pag_timer;
+
+/* handles uppercase decimal and hexadecimal */
+static u_int8_t char2bcd(char c)
+{
+	if (c <= '9')
+		return c - '0';
+	else
+		return c - 'A';
+}
+
+static int string_to_mi(u_int8_t *mi, const char *string,
+			u_int8_t type)
+{
+	u_int8_t *cur = mi+3;
+
+	mi[0] = GSM48_IE_MOBILE_ID;
+	//mi[1] = TMSI_LEN;
+	mi[2] = type & GSM_MI_TYPE_MASK;
+
+	if (strlen(string) & 0x01)
+		mi[2] |= char2bcd(*string++) << 4;
+	else
+		mi[2] |= 0xf0;
+
+	while (*string && *(string+1))
+		*cur++ = char2bcd(*string++) | (char2bcd(*string++) << 4);
+
+	mi[1] = cur - mi;
+
+	return cur - mi;
+}
+
+static const char *nokia_imsi = "7240311131388";
+static const char *rokr_imsi = "4660198001300";
+
+void pag_timer_cb(void *data)
+{
+	struct gsm_bts *bts = &gsmnet->bts[0];
+	u_int8_t mi[128];
+	struct gsm_subscriber _subscr, *subscr = &_subscr;
+	unsigned int paging_group, mi_len;
+	u_int64_t num_imsi;
+	const char *imsi = nokia_imsi;
+
+	printf("FEUER\n");
+
+#if 1
+	memset(subscr, 0, sizeof(*subscr));
+	strcpy(subscr->imsi, imsi);
+	db_get_subscriber(GSM_SUBSCRIBER_IMSI, subscr);
+	if (!subscr) 
+		return;
+
+	mi_len = generate_mid_from_tmsi(mi, strtoul(subscr->tmsi, NULL, 10));
+#else
+	mi_len = string_to_mi(mi, imsi, GSM_MI_TYPE_IMSI);
+#endif
+
+	num_imsi = strtoull(imsi, NULL, 10);
+	paging_group = get_paging_group(num_imsi, 1, 3);
+
+	for (paging_group = 0; paging_group < 3; paging_group++)
+		rsl_paging_cmd(bts, paging_group, mi_len, mi, RSL_CHANNEED_TCH_F);
+
+	schedule_timer(&pag_timer, 10, 0);
+}
+
 int main(int argc, char **argv)
 {
 	/* parse options */
@@ -650,6 +721,9 @@
 
 	bootstrap_network();
 
+	pag_timer.cb = pag_timer_cb;
+	schedule_timer(&pag_timer, 10, 0);
+
 	while (1) {
 		bsc_select_main();
 	}
diff --git a/src/db_test.c b/src/db_test.c
index 27ddbab..0367ce2 100644
--- a/src/db_test.c
+++ b/src/db_test.c
@@ -21,6 +21,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <malloc.h>
 
 int main() {
 
diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 9a6212d..3902d94 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -97,15 +97,19 @@
 	lai48->lac = htons(lac);
 }
 
-#define TMSI_LEN	4
+#define TMSI_LEN	5
 #define MID_TMSI_LEN	(TMSI_LEN + 2)
 
-static void generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
+int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
 {
+	u_int32_t *tptr = &buf[3];
+
 	buf[0] = GSM48_IE_MOBILE_ID;
 	buf[1] = TMSI_LEN;
 	buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
-	*((u_int32_t *) &buf[3]) = htonl(tmsi);
+	*tptr = htonl(tmsi);
+
+	return 7;
 }
 
 static struct msgb *gsm48_msgb_alloc(void)
@@ -256,11 +260,12 @@
 		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);
+			tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
 			return gsm0408_loc_upd_acc(msg->lchan, tmsi);
 		}
 		break;
 	case GSM_MI_TYPE_IMEI:
+	case GSM_MI_TYPE_IMEISV:
 		/* update subscribe <-> IMEI mapping */
 		if (lchan->subscr)
 			db_subscriber_assoc_imei(lchan->subscr, mi_string);
@@ -269,6 +274,15 @@
 	return 0;
 }
 
+
+static void loc_upd_rej_cb(void *data)
+{
+	struct gsm_lchan *lchan = data;
+
+	gsm0408_loc_upd_rej(lchan, 0x16);
+	rsl_chan_release(lchan);
+}
+
 #define MI_SIZE 32
 /* Chapter 9.2.15 */
 static int mm_rx_loc_upd_req(struct msgb *msg)
@@ -277,6 +291,7 @@
 	struct gsm_bts *bts = msg->trx->bts;
 	struct gsm48_loc_upd_req *lu;
 	struct gsm_subscriber *subscr;
+	struct gsm_lchan *lchan = msg->lchan;
 	u_int8_t mi_type;
 	u_int32_t tmsi;
 	char mi_string[MI_SIZE];
@@ -292,18 +307,18 @@
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
 		/* we always want the IMEI, too */
-		rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMEISV);
+		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
 		/* look up subscriber based on IMSI */
 		subscr = db_create_subscriber(mi_string);
 		break;
 	case GSM_MI_TYPE_TMSI:
 		/* we always want the IMEI, too */
-		rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMEISV);
+		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
 		/* look up the subscriber based on TMSI, request IMSI if it fails */
 		subscr = subscr_get_by_tmsi(lu->mi);
 		if (!subscr) {
 			/* send IDENTITY REQUEST message to get IMSI */
-			rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMSI);
+			rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
 		}
 		break;
 	case GSM_MI_TYPE_IMEI:
@@ -316,20 +331,22 @@
 		break;
 	}
 
+	lchan->subscr = subscr;
+
 	if (!subscr || !subscr->authorized) {
 		/* 0x16 is congestion */
-		gsm0408_loc_upd_rej(msg->lchan, 0x16);
-		rsl_chan_release(msg->lchan);
-		return -EINVAL;
+		lchan->timer.cb = loc_upd_rej_cb;
+		lchan->timer.data = lchan;
+		schedule_timer(&lchan->timer, 1, 0);
+		return 0;
 	}
 
 	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, tmsi);
+	tmsi = strtoul(subscr->tmsi, NULL, 10);
+
+	return gsm0408_loc_upd_acc(lchan, tmsi);
 }
 
 static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)