sgsn: Put SGSN related subscriber data into separate struct

There will be an increasing number of SGSN related fields per
subscriber. Instead of extending gsm_subscriber accordingly, a single
struct sgsn_subscriber_data object is assigned to it. The talloc
context used to allocated that object is the subscr object itself.
Therefore it will be freed automatically along with the subscr
object.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index b135813..464982e 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -271,6 +271,7 @@
 };
 
 struct sgsn_subscriber_data {
+	struct sgsn_mm_ctx *mm;
 	enum sgsn_auth_state auth_state;
 };
 
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 195fa0f..290cc44 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -20,6 +20,7 @@
 
 struct vty;
 struct sgsn_mm_ctx;
+struct sgsn_subscriber_data;
 
 struct gsm_subscriber_group {
 	struct gsm_network *net;
@@ -69,7 +70,7 @@
 	struct llist_head requests;
 
 	/* GPRS/SGSN related fields */
-	struct sgsn_mm_ctx *mm;
+	struct sgsn_subscriber_data *sgsn_data;
 };
 
 enum gsm_subscriber_field {
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 525bfab..d5c02fd 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -191,7 +191,7 @@
 	if (mm->subscr) {
 		struct gsm_subscriber *subscr =  mm->subscr;
 		mm->subscr = NULL;
-		subscr->mm = NULL;
+		subscr->sgsn_data->mm = NULL;
 		gprs_subscr_delete(subscr);
 	}
 
@@ -477,9 +477,9 @@
 
 	LOGMMCTXP(LOGL_INFO, mmctx, "Subscriber data update");
 
-	if (!subscr->mm && !mmctx->subscr) {
+	if (!subscr->sgsn_data->mm && !mmctx->subscr) {
 		mmctx->subscr =	subscr_get(subscr);
-		mmctx->subscr->mm = mmctx;
+		mmctx->subscr->sgsn_data->mm = mmctx;
 	}
 
 	sgsn_auth_update(mmctx);
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 78fa3e1..cf0af90 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -33,6 +33,15 @@
 {
 }
 
+static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
+{
+	struct sgsn_subscriber_data *sdata;
+
+	sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
+
+	return sdata;
+}
+
 struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
 {
 	struct gsm_subscriber *subscr;
@@ -41,6 +50,9 @@
 	if (!subscr)
 		return NULL;
 
+	if (!subscr->sgsn_data)
+		subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
+
 	subscr->keep_in_ram = 1;
 
 	return subscr;
@@ -53,10 +65,10 @@
 
 void gprs_subscr_delete(struct gsm_subscriber *subscr)
 {
-	if (subscr->mm) {
-		subscr_put(subscr->mm->subscr);
-		subscr->mm->subscr = NULL;
-		subscr->mm = NULL;
+	if (subscr->sgsn_data->mm) {
+		subscr_put(subscr->sgsn_data->mm->subscr);
+		subscr->sgsn_data->mm->subscr = NULL;
+		subscr->sgsn_data->mm = NULL;
 	}
 
 	if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
@@ -80,19 +92,19 @@
 {
 	/* TODO: Implement remote query to MSC, ... */
 
-	LOGMMCTXP(LOGL_INFO, subscr->mm,
+	LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
 		  "subscriber data is not available (remote query NYI)\n");
 	return -ENOTSUP;
 }
 
 void gprs_subscr_update(struct gsm_subscriber *subscr)
 {
-	LOGMMCTXP(LOGL_DEBUG, subscr->mm, "Updating subscriber data\n");
+	LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
 
 	subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_PENDING;
 	subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
 
-	sgsn_update_subscriber_data(subscr->mm, subscr);
+	sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
 }
 
 int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx)
@@ -130,7 +142,7 @@
 	if (need_update) {
 		subscr->flags |= GPRS_SUBSCRIBER_UPDATE_PENDING;
 		if (!mmctx->subscr) {
-			subscr->mm = mmctx;
+			subscr->sgsn_data->mm = mmctx;
 			mmctx->subscr = subscr_get(subscr);
 		}