diff options
-rw-r--r-- | src/gprs/gprs_gmm.c | 26 | ||||
-rw-r--r-- | tests/sgsn/sgsn_test.c | 17 | ||||
-rw-r--r-- | tests/sgsn/sgsn_test.ok | 1 |
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 |