sgsn: Add gsm0408_gprs_access_cancelled

This function is called to delete an established MM context
silently without invoking a detach procedure.

It is called when a subscriber is cancelled by the HLR. This
generally happens, when an MS has moved to another routing area and
has to use another SGSN.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 60a17ce..4f19454 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -756,6 +756,33 @@
 	}
 }
 
+void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *ctx)
+{
+	switch (ctx->mm_state) {
+#if 0
+	case GMM_COMMON_PROC_INIT:
+		LOGP(DMM, LOGL_NOTICE,
+		     "Cancelled, rejecting ATTACH REQUEST, IMSI=%s\n",
+		     ctx->imsi);
+		gsm48_tx_gmm_att_rej(ctx, GMM_CAUSE_IMPL_DETACHED);
+		break;
+	case GMM_REGISTERED_NORMAL:
+	case GMM_REGISTERED_SUSPENDED:
+		LOGP(DMM, LOGL_NOTICE,
+		     "Cancelled, detaching, IMSI=%s\n",
+		     ctx->imsi);
+		gsm48_tx_gmm_detach_req(
+			ctx, GPRS_DET_T_MT_REATT_NOTREQ, GMM_CAUSE_IMPL_DETACHED);
+		break;
+#endif
+	default:
+		LOGP(DMM, LOGL_INFO,
+		     "Cancelled, deleting context, IMSI=%s\n",
+		     ctx->imsi);
+	}
+	mm_ctx_cleanup_free(ctx, "access cancelled");
+}
+
 /* Parse Chapter 9.4.13 Identity Response */
 static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
 {
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index 071bdab..1f11948 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -184,7 +184,10 @@
 		gsm0408_gprs_access_granted(mmctx);
 		break;
 	case SGSN_AUTH_REJECTED:
-		gsm0408_gprs_access_denied(mmctx);
+		if (subscr && (subscr->flags & GPRS_SUBSCRIBER_CANCELLED) != 0)
+			gsm0408_gprs_access_cancelled(mmctx);
+		else
+			gsm0408_gprs_access_denied(mmctx);
 		break;
 	default:
 		break;