[tmsi] Make the tmsi a 4 octet number

tmsi is four octets long, there is no need to make it a string
and then jump through hoops to convert it to a number. Keep the database
using it as a string to benefit from the NULL handling of the db.

Introduce the reserved tmsi which has all bits set to 1 according
to GSM 03.03 ยง2.4 and start checking for it and make sure the db
code will never allocate such a tmsi.
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index 45c55af..270d4d9 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -376,7 +376,7 @@
 
 	string = dbi_result_get_string(result, "tmsi");
 	if (string)
-		strncpy(subscr->tmsi, string, GSM_TMSI_LENGTH);
+		subscr->tmsi = tmsi_from_string(string);
 
 	string = dbi_result_get_string(result, "name");
 	if (string)
@@ -388,7 +388,7 @@
 
 	subscr->lac = dbi_result_get_uint(result, "lac");
 	subscr->authorized = dbi_result_get_uint(result, "authorized");
-	printf("DB: Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %s, EXTEN '%s', LAC %hu, AUTH %u\n",
+	printf("DB: Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
 		subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
 		subscr->lac, subscr->authorized);
 	dbi_result_free(result);
@@ -400,12 +400,15 @@
 
 int db_sync_subscriber(struct gsm_subscriber* subscriber) {
 	dbi_result result;
+	char tmsi[14];
 	char *q_tmsi;
-	if (subscriber->tmsi[0])
+
+	if (subscriber->tmsi != GSM_RESERVED_TMSI) {
+		sprintf(tmsi, "%u", subscriber->tmsi);
 		dbi_conn_quote_string_copy(conn,
-				   subscriber->tmsi,
+				   tmsi,
 				   &q_tmsi);
-	else 
+	} else
 		q_tmsi = strdup("NULL");
 	result = dbi_conn_queryf(conn,
 		"UPDATE Subscriber "
@@ -475,10 +478,15 @@
 
 int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) {
 	dbi_result result=NULL;
+	char tmsi[14];
 	char* tmsi_quoted;
 	for (;;) {
-		sprintf(subscriber->tmsi, "%i", rand());
-		dbi_conn_quote_string_copy(conn, subscriber->tmsi, &tmsi_quoted);
+		subscriber->tmsi = rand();
+		if (subscriber->tmsi == GSM_RESERVED_TMSI)
+			continue;
+
+		sprintf(tmsi, "%u", subscriber->tmsi);
+		dbi_conn_quote_string_copy(conn, tmsi, &tmsi_quoted);
 		result = dbi_conn_queryf(conn,
 			"SELECT * FROM Subscriber "
 			"WHERE tmsi = %s ",
@@ -495,7 +503,7 @@
 		}
 		if (!dbi_result_next_row(result)) {
 			dbi_result_free(result);
-			printf("DB: Allocated TMSI %s for IMSI %s.\n", subscriber->tmsi, subscriber->imsi);
+			printf("DB: Allocated TMSI %u for IMSI %s.\n", subscriber->tmsi, subscriber->imsi);
 			return db_sync_subscriber(subscriber);
 		}
 		dbi_result_free(result);
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index d6fe09f..196fdca 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -291,15 +291,12 @@
 
 static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
 {
-	u_int32_t tmsi;
-
 	if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
 		int rc;
 
 		db_subscriber_alloc_tmsi(lchan->subscr);
-		tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
 		release_loc_updating_req(lchan);
-		rc = gsm0408_loc_upd_acc(msg->lchan, tmsi);
+		rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi);
 		/* call subscr_update after putting the loc_upd_acc
 		 * in the transmit queue, since S_SUBSCR_ATTACHED might
 		 * trigger further action like SMS delivery */
@@ -1054,7 +1051,8 @@
 		lchan->loc_operation->waiting_for_imei = 1;
 
 		/* look up the subscriber based on TMSI, request IMSI if it fails */
-		subscr = subscr_get_by_tmsi(bts->network, mi_string);
+		subscr = subscr_get_by_tmsi(bts->network,
+					    tmsi_from_string(mi_string));
 		if (!subscr) {
 			/* send IDENTITY REQUEST message to get IMSI */
 			rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
@@ -1352,7 +1350,8 @@
 	if (is_siemens_bts(bts))
 		send_siemens_mrpci(msg->lchan, classmark2-1);
 
-	subscr = subscr_get_by_tmsi(bts->network, mi_string);
+	subscr = subscr_get_by_tmsi(bts->network,
+				    tmsi_from_string(mi_string));
 
 	/* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
 	if (!subscr)
@@ -1389,7 +1388,8 @@
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_TMSI:
-		subscr = subscr_get_by_tmsi(bts->network, mi_string);
+		subscr = subscr_get_by_tmsi(bts->network,
+					    tmsi_from_string(mi_string));
 		break;
 	case GSM_MI_TYPE_IMSI:
 		subscr = subscr_get_by_imsi(bts->network, mi_string);
@@ -1495,7 +1495,8 @@
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_TMSI:
-		subscr = subscr_get_by_tmsi(bts->network, mi_string);
+		subscr = subscr_get_by_tmsi(bts->network,
+					    tmsi_from_string(mi_string));
 		break;
 	case GSM_MI_TYPE_IMSI:
 		subscr = subscr_get_by_imsi(bts->network, mi_string);
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index 84e14a0..a4e35c7 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -35,17 +35,19 @@
 extern struct llist_head *subscr_bsc_active_subscriber(void);
 
 struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
-					  const char *tmsi)
+					  u_int32_t tmsi)
 {
+	char tmsi_string[14];
 	struct gsm_subscriber *subscr;
 
 	/* we might have a record in memory already */
 	llist_for_each_entry(subscr, subscr_bsc_active_subscriber(), entry) {
-		if (strcmp(subscr->tmsi, tmsi) == 0)
+		if (tmsi == subscr->tmsi)
 			return subscr_get(subscr);
 	}
 
-	return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi);
+	sprintf(tmsi_string, "%u", tmsi);
+	return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string);
 }
 
 struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net,
diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c
index d6a179b..345544d 100644
--- a/openbsc/src/gsm_subscriber_base.c
+++ b/openbsc/src/gsm_subscriber_base.c
@@ -112,6 +112,7 @@
 	memset(s, 0, sizeof(*s));
 	llist_add_tail(&s->entry, &active_subscribers);
 	s->use_count = 1;
+	s->tmsi = GSM_RESERVED_TMSI;
 
 	INIT_LLIST_HEAD(&s->requests);
 
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index fd0611a..b855213 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -90,7 +90,6 @@
 static void page_ms(struct gsm_paging_request *request)
 {
 	u_int8_t mi[128];
-	unsigned long int tmsi;
 	unsigned int mi_len;
 	unsigned int page_group;
 
@@ -98,8 +97,7 @@
 		request->subscr->imsi);
 
 	page_group = calculate_group(request->bts, request->subscr);
-	tmsi = strtoul(request->subscr->tmsi, NULL, 10);
-	mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
+	mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi);
 	rsl_paging_cmd(request->bts, page_group, mi_len, mi,
 			request->chan_type);
 }
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index f75cfaf..00decd2 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -427,8 +427,8 @@
 			VTY_NEWLINE);
 	if (subscr->imsi)
 		vty_out(vty, "    IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
-	if (subscr->tmsi)
-		vty_out(vty, "    TMSI: %08X%s", atoi(subscr->tmsi),
+	if (subscr->tmsi != GSM_RESERVED_TMSI)
+		vty_out(vty, "    TMSI: %08X%s", subscr->tmsi,
 			VTY_NEWLINE);
 	vty_out(vty, "    Use count: %u%s", subscr->use_count, VTY_NEWLINE);
 }