aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs/gprs_gmm.c26
-rw-r--r--tests/sgsn/sgsn_test.c17
-rw-r--r--tests/sgsn/sgsn_test.ok1
3 files changed, 43 insertions, 1 deletions
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index 358bff909..a18a54e1b 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -1616,6 +1616,19 @@ static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
}
}
+/* 3GPP TS 24.008 Section 4.7.13.4 Service request procedure not accepted by the
+ * network. Returns true if MS has active PDP contexts in pdp_status */
+bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len)
+{
+ size_t i;
+
+ for (i = 0; i < pdp_status_len; i++)
+ if (pdp_status[i] != 0)
+ return true;
+
+ return false;
+}
+
/* Chapter 9.4.14: Routing area update request */
static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
struct gprs_llc_llme *llme)
@@ -1896,12 +1909,23 @@ static int gsm48_rx_gmm_service_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
ctx->iu.service.type = service_type;
- /* TODO: Handle those only in case of accept? */
/* Look at PDP Context Status IE and see if MS's view of
* activated/deactivated NSAPIs agrees with our view */
if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
+ const size_t pdp_status_len = TLVP_LEN(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
+
process_ms_ctx_status(ctx, pdp_status);
+
+ /* 3GPP TS 24.008 Section 4.7.13.4 Service request procedure not
+ * accepted by the network. Cause #40. If MS has PDP Contexts in
+ * Active state in pdp_status but there is no PDP contexts on
+ * SGSN side then Reject with the cause will force the mobile to
+ * reset PDP contexts */
+ if (llist_empty(&ctx->pdp_list) && pdp_status_has_active_nsapis(pdp_status, pdp_status_len)) {
+ reject_cause = GMM_CAUSE_NO_PDP_ACTIVATED;
+ goto rejected;
+ }
}
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
index 614520600..23cb4fbc4 100644
--- a/tests/sgsn/sgsn_test.c
+++ b/tests/sgsn/sgsn_test.c
@@ -1575,6 +1575,22 @@ static void test_ggsn_selection(void)
cleanup_test();
}
+bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
+
+static void test_pdp_status_has_active_nsapis(void)
+{
+ const size_t pdp_status_len = 2;
+ const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
+ const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
+ const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
+
+ printf("Testing pdp_status_has_active_nsapis\n");
+
+ OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
+ OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
+ OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
+}
+
static struct log_info_cat gprs_categories[] = {
[DMM] = {
.name = "DMM",
@@ -1657,6 +1673,7 @@ int main(int argc, char **argv)
test_gmm_cancel();
test_apn_matching();
test_ggsn_selection();
+ test_pdp_status_has_active_nsapis();
printf("Done\n");
talloc_report_full(osmo_sgsn_ctx, stderr);
diff --git a/tests/sgsn/sgsn_test.ok b/tests/sgsn/sgsn_test.ok
index e7e7cf6e4..35b1d7bb7 100644
--- a/tests/sgsn/sgsn_test.ok
+++ b/tests/sgsn/sgsn_test.ok
@@ -24,4 +24,5 @@ Testing GMM reject
Testing cancellation
Testing APN matching
Testing GGSN selection
+Testing pdp_status_has_active_nsapis
Done