sgsn: Refactor sgsn_auth to separate request and authorization

Currently the authorization is done in sgsn_auth_request for ACL
based authorization. This doesn't match the way remote authorization
would work, so that there is a second call to sgsn_auth_state already
present in sgsn_auth_update.

This patch removes the autorization check completely from
sgsn_auth_request which in turn calls sgsn_auth_update directly now.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 0cb7220..ac78a16 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -269,6 +269,7 @@
 
 struct sgsn_config;
 struct sgsn_instance;
+extern const struct value_string *sgsn_auth_state_names;
 
 void sgsn_auth_init(struct sgsn_instance *sgi);
 struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, struct sgsn_config *cfg);
@@ -278,11 +279,10 @@
 int sgsn_auth_request(struct sgsn_mm_ctx *mm, struct sgsn_config *cfg);
 enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm,
 				     struct sgsn_config *cfg);
-void sgsn_auth_update(struct sgsn_mm_ctx *mm, struct sgsn_subscriber_data *sd);
+void sgsn_auth_update(struct sgsn_mm_ctx *mm, struct sgsn_instance *sgi);
 
 /* Called on subscriber data updates */
-void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
-				 struct sgsn_subscriber_data *sd);
+void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
 
 int gprs_sndcp_vty_init(void);
 struct sgsn_instance;
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index afd3bbb..48fb29d 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -644,7 +644,7 @@
 
 	if (ctx->auth_state == SGSN_AUTH_UNKNOWN) {
 		/* Request authorization, this leads to a call to
-		 * sgsn_update_subscriber_data which in turn calls
+		 * sgsn_auth_update which in turn calls
 		 * gsm0408_gprs_access_granted or gsm0408_gprs_access_denied */
 
 		sgsn_auth_request(ctx, &sgsn->cfg);
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index daf9483..9fc4b86 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -451,11 +451,9 @@
 	return gsm0408_gprs_force_reattach_oldmsg(oldmsg);
 }
 
-void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
-				 struct sgsn_subscriber_data *sd)
+void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
 {
 	OSMO_ASSERT(mmctx);
 
-	if (sd->auth_state != mmctx->auth_state)
-		sgsn_auth_update(mmctx, sd);
+	sgsn_auth_update(mmctx, sgsn);
 }
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index d2d4913..0407e9e 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -32,6 +32,8 @@
 	{ 0, NULL }
 };
 
+const struct value_string *sgsn_auth_state_names = auth_state_names;
+
 void sgsn_auth_init(struct sgsn_instance *sgi)
 {
 	INIT_LLIST_HEAD(&sgi->cfg.imsi_acl);
@@ -125,29 +127,37 @@
 
 int sgsn_auth_request(struct sgsn_mm_ctx *mmctx, struct sgsn_config *cfg)
 {
-	struct sgsn_subscriber_data sd = {0};
+	/* TODO: Add remote subscriber update requests here */
 
-	sd.auth_state = sgsn_auth_state(mmctx, cfg);
+	sgsn_auth_update(mmctx, sgsn);
 
-	if (sd.auth_state == SGSN_AUTH_UNKNOWN) {
-		LOGMMCTXP(LOGL_ERROR, mmctx,
-			  "Missing information, authorization not possible\n");
-		sd.auth_state = SGSN_AUTH_REJECTED;
-	}
-
-	/* This will call sgsn_auth_update if auth_state has changed */
-	sgsn_update_subscriber_data(mmctx, &sd);
 	return 0;
 }
 
-void sgsn_auth_update(struct sgsn_mm_ctx *mmctx, struct sgsn_subscriber_data *sd)
+void sgsn_auth_update(struct sgsn_mm_ctx *mmctx, struct sgsn_instance *sgi)
 {
-	LOGMMCTXP(LOGL_INFO, mmctx, "Got authorization update: state %s\n",
-		  get_value_string(auth_state_names, sd->auth_state));
+	enum sgsn_auth_state auth_state;
 
-	mmctx->auth_state = sd->auth_state;
+	LOGMMCTXP(LOGL_DEBUG, mmctx, "Updating authorization\n");
 
-	switch (sd->auth_state) {
+	auth_state = sgsn_auth_state(mmctx, &sgi->cfg);
+	if (auth_state == SGSN_AUTH_UNKNOWN) {
+		/* Reject requests since remote updates are NYI */
+		LOGMMCTXP(LOGL_ERROR, mmctx,
+			  "Missing information, authorization not possible\n");
+		auth_state = SGSN_AUTH_REJECTED;
+	}
+
+	if (mmctx->auth_state == auth_state)
+		return;
+
+	LOGMMCTXP(LOGL_INFO, mmctx, "Got authorization update: state %s -> %s\n",
+		  get_value_string(sgsn_auth_state_names, mmctx->auth_state),
+		  get_value_string(sgsn_auth_state_names, auth_state));
+
+	mmctx->auth_state = auth_state;
+
+	switch (auth_state) {
 	case SGSN_AUTH_ACCEPTED:
 		gsm0408_gprs_access_granted(mmctx);
 		break;