sgsn: Integrate subscriber handling into the SGSN

This commit adds a new authorization policy 'remote' and uses
the subscriber cache for authorization when this policy is being used.

Note that there is no remote backend implemented yet. After the
IMSI/IMEI have been acquired, a request would be sent to the remote
peer. The attach/auth-ciph procedure continues when authorization
info has been received from the peer. This means, that
gprs_subscr_update() must be called then to tell the GMM layer
that it can proceed. A later commit will add VTY commands to do this
manually.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 71cd742..525bfab 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -187,6 +187,14 @@
 		osmo_timer_del(&mm->timer);
 	}
 
+	/* Detach from subscriber which is possibly freed then */
+	if (mm->subscr) {
+		struct gsm_subscriber *subscr =  mm->subscr;
+		mm->subscr = NULL;
+		subscr->mm = NULL;
+		gprs_subscr_delete(subscr);
+	}
+
 	/* Unlink from global list of MM contexts */
 	llist_del(&mm->list);
 
@@ -455,7 +463,24 @@
 void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
 				 struct gsm_subscriber *subscr)
 {
-	OSMO_ASSERT(mmctx);
+	if (!mmctx && subscr && strlen(subscr->imsi) > 0) {
+		mmctx = sgsn_mm_ctx_by_imsi(subscr->imsi);
+		OSMO_ASSERT(!mmctx || !mmctx->subscr || mmctx->subscr == subscr);
+	}
+
+	if (!mmctx) {
+		LOGP(DMM, LOGL_INFO,
+		     "Subscriber data update for unregistered MM context, IMSI %s\n",
+		     subscr->imsi);
+		return;
+	}
+
+	LOGMMCTXP(LOGL_INFO, mmctx, "Subscriber data update");
+
+	if (!subscr->mm && !mmctx->subscr) {
+		mmctx->subscr =	subscr_get(subscr);
+		mmctx->subscr->mm = mmctx;
+	}
 
 	sgsn_auth_update(mmctx);
 }