aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/src/gprs/gprs_gmm.c58
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c143
-rw-r--r--openbsc/tests/sgsn/sgsn_test.ok6
3 files changed, 198 insertions, 9 deletions
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index a966949a4..a2c30bee0 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -803,6 +803,8 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
char mi_string[GSM48_MI_SIZE];
struct gprs_ra_id ra_id;
uint16_t cid;
+ enum gsm48_gmm_cause reject_cause;
+ int rc;
LOGP(DMM, LOGL_INFO, "-> GMM ATTACH REQUEST ");
@@ -863,8 +865,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
#else
ctx = sgsn_mm_ctx_alloc(0, &ra_id);
- if (!ctx)
- return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_NET_FAIL);
+ if (!ctx) {
+ reject_cause = GMM_CAUSE_NET_FAIL;
+ goto rejected;
+ }
strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
#endif
}
@@ -891,7 +895,8 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
default:
LOGP(DMM, LOGL_NOTICE, "Rejecting ATTACH REQUEST with "
"MI type %u\n", mi_type);
- return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_MS_ID_NOT_DERIVED);
+ reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
+ goto rejected;
}
/* Update MM Context with currient RA and Cell ID */
ctx->ra = ra_id;
@@ -923,7 +928,22 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
err_inval:
LOGPC(DMM, LOGL_INFO, "\n");
- return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_SEM_INCORR_MSG);
+ reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
+
+rejected:
+ /* Send ATTACH REJECT */
+ LOGMMCTXP(LOGL_NOTICE, ctx,
+ "Rejecting Attach Request with cause '%s' (%d)\n",
+ get_value_string(gmm_cause_names, reject_cause), reject_cause);
+ rc = gsm48_tx_gmm_att_rej_oldmsg(msg, reject_cause);
+ if (ctx)
+ mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ");
+ else
+ /* TLLI unassignment */
+ gprs_llgmm_assign(llme, llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
+
+ return rc;
+
}
/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
@@ -1061,6 +1081,8 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
struct gprs_ra_id old_ra_id;
struct tlv_parsed tp;
uint8_t upd_type;
+ enum gsm48_gmm_cause reject_cause;
+ int rc;
/* Update Type 10.5.5.18 */
upd_type = *cur++ & 0x0f;
@@ -1074,8 +1096,10 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* MS Radio Access Capability 10.5.5.12a */
ms_ra_acc_cap_len = *cur++;
- if (ms_ra_acc_cap_len > 52)
- return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
+ if (ms_ra_acc_cap_len > 52) {
+ reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
+ goto rejected;
+ }
cur += ms_ra_acc_cap_len;
/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
@@ -1087,8 +1111,8 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
case GPRS_UPD_T_RA_LA:
case GPRS_UPD_T_RA_LA_IMSI_ATT:
LOGP(DMM, LOGL_NOTICE, "Update type %i unsupported in Mode III, is your SI13 corrupt?\n", upd_type);
- return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
- break;
+ reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
+ goto rejected;
case GPRS_UPD_T_RA:
case GPRS_UPD_T_PERIODIC:
break;
@@ -1104,7 +1128,8 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* The MS has to perform GPRS attach */
/* Device is still IMSI attached for CS but initiate GPRS ATTACH,
* see GSM 04.08, 4.7.5.1.4 and G.6 */
- return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_IMPL_DETACHED);
+ reject_cause = GMM_CAUSE_IMPL_DETACHED;
+ goto rejected;
}
/* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
@@ -1150,6 +1175,21 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* Send RA UPDATE ACCEPT */
return gsm48_tx_gmm_ra_upd_ack(mmctx);
+
+rejected:
+ /* Send RA UPDATE REJECT */
+ LOGMMCTXP(LOGL_NOTICE, mmctx,
+ "Rejecting RA Update Request with cause '%s' (%d)\n",
+ get_value_string(gmm_cause_names, reject_cause), reject_cause);
+ rc = gsm48_tx_gmm_ra_upd_rej(msg, reject_cause);
+ if (mmctx)
+ mm_ctx_cleanup_free(mmctx, "GPRS RA UPDATE REJ");
+ else
+ /* TLLI unassignment */
+ gprs_llgmm_assign(llme, llme->tlli, 0xffffffff, GPRS_ALGO_GEA0,
+ NULL);
+
+ return rc;
}
static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index 00259a571..1756888fe 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -404,6 +404,148 @@ static void test_gmm_attach(void)
sgsn_acl_del("123456789012345", &sgsn->cfg);
}
+/*
+ * Test the GMM Rejects
+ */
+static void test_gmm_reject(void)
+{
+ struct gprs_ra_id raid = { 0, };
+ struct sgsn_mm_ctx *ctx = NULL;
+ uint32_t foreign_tlli;
+ struct gprs_llc_lle *lle;
+ int idx;
+
+ /* DTAP - Attach Request */
+ /* Invalid MI length */
+ static const unsigned char attach_req_inv_mi_len[] = {
+ 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
+ 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 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 - Attach Request */
+ /* Invalid MI type (IMEI) */
+ static const unsigned char attach_req_inv_mi_type[] = {
+ 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
+ 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 - Routing Area Update Request */
+ static const unsigned char dtap_ra_upd_req[] = {
+ 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
+ 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
+ 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
+ 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
+ 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
+ 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
+ 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
+ };
+
+ /* DTAP - Routing Area Update Request */
+ /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
+ static const unsigned char dtap_ra_upd_req_inv_type[] = {
+ 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
+ 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
+ 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
+ 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
+ 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
+ 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
+ 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
+ };
+
+ /* DTAP - Routing Area Update Request */
+ /* Invalid cap length */
+ static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
+ 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
+ 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
+ 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
+ 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
+ 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
+ 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
+ };
+
+ struct test {
+ const char *title;
+ const unsigned char *msg;
+ unsigned msg_len;
+ unsigned num_resp;
+
+ };
+ static struct test tests[] = {
+ {
+ .title = "Attach Request (invalid MI length)",
+ .msg = attach_req_inv_mi_len,
+ .msg_len = sizeof(attach_req_inv_mi_len),
+ .num_resp = 1 /* Reject */
+
+ },
+ {
+ .title = "Attach Request (invalid MI type)",
+ .msg = attach_req_inv_mi_type,
+ .msg_len = sizeof(attach_req_inv_mi_type),
+ .num_resp = 1 /* Reject */
+ },
+ {
+ .title = "Routing Area Update Request (valid)",
+ .msg = dtap_ra_upd_req,
+ .msg_len = sizeof(dtap_ra_upd_req),
+ .num_resp = 2 /* XID Reset + Reject */
+ },
+ {
+ .title = "Routing Area Update Request (invalid type)",
+ .msg = dtap_ra_upd_req_inv_type,
+ .msg_len = sizeof(dtap_ra_upd_req_inv_type),
+ .num_resp = 1 /* Reject */
+ },
+ {
+ .title = "Routing Area Update Request (invalid CAP length)",
+ .msg = dtap_ra_upd_req_inv_cap_len,
+ .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
+ .num_resp = 1 /* Reject */
+ },
+ };
+
+ printf("Testing GMM reject\n");
+
+ /* reset the PRNG used by sgsn_alloc_ptmsi */
+ srand(1);
+
+ foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
+
+ OSMO_ASSERT(count(gprs_llme_list()) == 0);
+
+ for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
+ const struct test *test = &tests[idx];
+ printf(" - %s\n", test->title);
+
+ /* Create a LLE/LLME */
+ lle = gprs_lle_get_or_create(foreign_tlli, 3);
+ OSMO_ASSERT(count(gprs_llme_list()) == 1);
+
+ /* Inject the Request message */
+ send_0408_message(lle->llme, foreign_tlli,
+ test->msg, test->msg_len);
+
+ /* We expect a Reject message */
+ fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
+ sgsn_tx_counter, test->num_resp);
+ OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
+
+ /* verify that LLME/MM are removed */
+ ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
+ OSMO_ASSERT(ctx == NULL);
+ OSMO_ASSERT(count(gprs_llme_list()) == 0);
+ }
+}
+
static struct log_info_cat gprs_categories[] = {
[DMM] = {
.name = "DMM",
@@ -473,6 +615,7 @@ int main(int argc, char **argv)
test_gmm_detach_no_mmctx();
test_gmm_status_no_mmctx();
test_gmm_attach();
+ test_gmm_reject();
printf("Done\n");
return 0;
}
diff --git a/openbsc/tests/sgsn/sgsn_test.ok b/openbsc/tests/sgsn/sgsn_test.ok
index c03bb1edb..d3b333f8a 100644
--- a/openbsc/tests/sgsn/sgsn_test.ok
+++ b/openbsc/tests/sgsn/sgsn_test.ok
@@ -4,4 +4,10 @@ Testing GMM detach (power off)
Testing GMM detach (no MMCTX)
Testing GMM Status (no MMCTX)
Testing GMM attach
+Testing GMM reject
+ - Attach Request (invalid MI length)
+ - Attach Request (invalid MI type)
+ - Routing Area Update Request (valid)
+ - Routing Area Update Request (invalid type)
+ - Routing Area Update Request (invalid CAP length)
Done