aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-11-11 14:47:38 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-12-09 09:48:25 +0100
commit98647ca0ef59430f3cd7ddb7530d85db7fa2688f (patch)
treec4676ca922ee92c013d5ee9be406f4624851bed4 /openbsc
parentbe2c8d9358084092281e7d02dc7ae0b7e4c0b4f8 (diff)
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
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gprs_gmm.h1
-rw-r--r--openbsc/src/gprs/gprs_gmm.c27
-rw-r--r--openbsc/src/gprs/sgsn_auth.c5
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c117
-rw-r--r--openbsc/tests/sgsn/sgsn_test.ok1
5 files changed, 150 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
index e22706b84..02030b075 100644
--- a/openbsc/include/openbsc/gprs_gmm.h
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -15,6 +15,7 @@ int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg);
void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx);
void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx);
+void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx);
int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 60a17ce95..4f19454a6 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -756,6 +756,33 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx)
}
}
+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 071bdab84..1f11948f1 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -184,7 +184,10 @@ void sgsn_auth_update(struct sgsn_mm_ctx *mmctx)
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;
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index 981a557ce..26d81a7f1 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -734,6 +734,122 @@ static void test_gmm_reject(void)
}
/*
+ * Test cancellation of attached MM contexts
+ */
+static void test_gmm_cancel(void)
+{
+ struct gprs_ra_id raid = { 0, };
+ struct sgsn_mm_ctx *ctx = NULL;
+ struct sgsn_mm_ctx *ictx;
+ uint32_t ptmsi1;
+ uint32_t foreign_tlli;
+ uint32_t local_tlli = 0;
+ struct gprs_llc_lle *lle;
+ const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
+
+ /* DTAP - Attach Request */
+ /* The P-TMSI is not known by the SGSN */
+ static const unsigned char attach_req[] = {
+ 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
+ 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
+ 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
+ 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
+ 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
+ };
+
+ /* DTAP - Identity Response IMEI */
+ static const unsigned char ident_resp_imei[] = {
+ 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
+ 0x56
+ };
+
+ /* DTAP - Identity Response IMSI */
+ static const unsigned char ident_resp_imsi[] = {
+ 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
+ 0x54
+ };
+
+ /* DTAP - Attach Complete */
+ static const unsigned char attach_compl[] = {
+ 0x08, 0x03
+ };
+
+ printf("Testing cancellation\n");
+
+ sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
+
+ /* reset the PRNG used by sgsn_alloc_ptmsi */
+ srand(1);
+
+ ptmsi1 = sgsn_alloc_ptmsi();
+ OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
+
+ /* reset the PRNG, so that the same P-TMSI sequence will be generated
+ * again */
+ srand(1);
+
+ foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
+
+ /* Create a LLE/LLME */
+ OSMO_ASSERT(count(gprs_llme_list()) == 0);
+ lle = gprs_lle_get_or_create(foreign_tlli, 3);
+ OSMO_ASSERT(count(gprs_llme_list()) == 1);
+
+ /* inject the attach request */
+ send_0408_message(lle->llme, foreign_tlli,
+ attach_req, ARRAY_SIZE(attach_req));
+
+ ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
+ OSMO_ASSERT(ctx != NULL);
+ OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
+
+ /* we expect an identity request (IMEI) */
+ OSMO_ASSERT(sgsn_tx_counter == 1);
+
+ /* inject the identity response (IMEI) */
+ send_0408_message(ctx->llme, foreign_tlli,
+ ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
+
+ /* we expect an identity request (IMSI) */
+ OSMO_ASSERT(sgsn_tx_counter == 1);
+
+ /* inject the identity response (IMSI) */
+ send_0408_message(ctx->llme, foreign_tlli,
+ ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
+
+ /* check that the MM context has not been removed due to a failed
+ * authorization */
+ OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
+
+ OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
+
+ /* we expect an attach accept/reject */
+ OSMO_ASSERT(sgsn_tx_counter == 1);
+
+ /* this has been randomly assigned by the SGSN */
+ local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
+
+ /* inject the attach complete */
+ send_0408_message(ctx->llme, local_tlli,
+ attach_compl, ARRAY_SIZE(attach_compl));
+
+ OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
+
+ /* we don't expect a response */
+ OSMO_ASSERT(sgsn_tx_counter == 0);
+
+ /* cancel */
+ gsm0408_gprs_access_cancelled(ctx);
+
+ /* verify that things are gone */
+ OSMO_ASSERT(count(gprs_llme_list()) == 0);
+ ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
+ OSMO_ASSERT(!ictx);
+
+ sgsn->cfg.auth_policy = saved_auth_policy;
+}
+
+/*
* Test the dynamic allocation of P-TMSIs
*/
static void test_gmm_ptmsi_allocation(void)
@@ -997,6 +1113,7 @@ int main(int argc, char **argv)
test_gmm_attach_acl();
test_gmm_attach_subscr();
test_gmm_reject();
+ test_gmm_cancel();
test_gmm_ptmsi_allocation();
printf("Done\n");
return 0;
diff --git a/openbsc/tests/sgsn/sgsn_test.ok b/openbsc/tests/sgsn/sgsn_test.ok
index 86dd0a211..4b061a5f9 100644
--- a/openbsc/tests/sgsn/sgsn_test.ok
+++ b/openbsc/tests/sgsn/sgsn_test.ok
@@ -13,6 +13,7 @@ Testing GMM reject
- Routing Area Update Request (valid)
- Routing Area Update Request (invalid type)
- Routing Area Update Request (invalid CAP length)
+Testing cancellation
Testing P-TMSI allocation
- sgsn_alloc_ptmsi
- Repeated Attach Request