sgsn: Add SGSN_ERROR_CAUSE_NONE and use it instead of 0

Currently an error_cause of 0 is being used to indicate normal
operation. Albeit this is not a defined GMM cause, the value is not
explicitly reserved.

This commit adds the macro SGSN_ERROR_CAUSE_NONE and uses it for
initialisation (instead of relying on talloc_zero) and comparisons.
The value is set to -1 to be on the safe side. The VTY code is
updated to set the error_cause when using the
'update-subscriber imsi IMSI update-location-result CAUSE' command.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 25810ab..00cf5cc 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -288,6 +288,8 @@
 	enum sgsn_subscriber_proc blocked_by;
 };
 
+#define SGSN_ERROR_CAUSE_NONE (-1)
+
 #define LOGGSUBSCRP(level, subscr, fmt, args...) \
 	LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
 	     (subscr) ? (subscr)->imsi : "---", \
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 8b7cc9f..32fb8e4 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -654,7 +654,7 @@
 
 void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
 {
-	if (gmm_cause == 0)
+	if (gmm_cause == SGSN_ERROR_CAUSE_NONE)
 		gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;
 
 	switch (ctx->mm_state) {
@@ -690,7 +690,7 @@
 
 void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *ctx, int gmm_cause)
 {
-	if (gmm_cause != 0) {
+	if (gmm_cause != SGSN_ERROR_CAUSE_NONE) {
 		LOGMMCTXP(LOGL_INFO, ctx,
 			  "Cancelled with cause '%s' (%d), deleting context\n",
 			  get_value_string(gsm48_gmm_cause_names, gmm_cause),
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index a30729d..5bde6a0 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -167,6 +167,8 @@
 
 	sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
 
+	sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
+
 	for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
 	     sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
 
@@ -292,7 +294,7 @@
 	}
 
 	sdata->auth_triplets_updated = 1;
-	sdata->error_cause = 0;
+	sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
 
 	gprs_subscr_update_auth_info(subscr);
 
@@ -322,7 +324,7 @@
 	}
 
 	subscr->authorized = 1;
-	subscr->sgsn_data->error_cause = 0;
+	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
 
 	subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
 
@@ -451,7 +453,7 @@
 	LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
 
 	/* Force silent cancellation */
-	subscr->sgsn_data->error_cause = 0;
+	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
 	gprs_subscr_put_and_cancel(subscr_get(subscr));
 
 	return 0;
@@ -500,7 +502,7 @@
 	gsup_reply.message_type = GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT;
 	gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
 
-	subscr->sgsn_data->error_cause = 0;
+	subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
 	gprs_subscr_put_and_cancel(subscr_get(subscr));
 
 	return 0;
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index 41f7c41..d77a021 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -257,7 +257,9 @@
 		gsm0408_gprs_access_granted(mmctx);
 		break;
 	case SGSN_AUTH_REJECTED:
-		gmm_cause = subscr ? subscr->sgsn_data->error_cause : 0;
+		gmm_cause =
+			subscr ? subscr->sgsn_data->error_cause :
+			SGSN_ERROR_CAUSE_NONE;
 
 		if (subscr && (subscr->flags & GPRS_SUBSCRIBER_CANCELLED) != 0)
 			gsm0408_gprs_access_cancelled(mmctx, gmm_cause);
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index ef4c8d8..84fd5ef 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -644,15 +644,29 @@
 
 	struct gsm_subscriber *subscr;
 
+	const struct value_string cause_mapping[] = {
+		{ GMM_CAUSE_NET_FAIL,		"system-failure" },
+		{ GMM_CAUSE_INV_MAND_INFO,	"data-missing" },
+		{ GMM_CAUSE_PROTO_ERR_UNSPEC,   "unexpected-data-value" },
+		{ GMM_CAUSE_IMSI_UNKNOWN,       "unknown-subscriber" },
+		{ GMM_CAUSE_GPRS_NOTALLOWED,    "roaming-not-allowed" },
+		{ 0, NULL }
+	};
+
 	subscr = gprs_subscr_get_by_imsi(imsi);
 	if (!subscr) {
 		vty_out(vty, "%% unable to get subscriber record for %s\n", imsi);
 		return CMD_WARNING;
 	}
-	if (strcmp(ret_code_str, "ok") == 0)
+
+	if (strcmp(ret_code_str, "ok") == 0) {
+		subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
 		subscr->authorized = 1;
-	else
+	} else {
+		subscr->sgsn_data->error_cause =
+			get_string_value(cause_mapping, ret_code_str);
 		subscr->authorized = 0;
+	}
 
 	gprs_subscr_update(subscr);