From 4f7aa2d5b78b6827c11337bb49696ff963b326f2 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 5 Jul 2019 15:55:07 +0900 Subject: [PATCH] [SGsAP] Location Update Reject --- lib/nas/nas-types.h | 1 + src/mme/sgsap-handler.c | 97 ++++++++++++++--- src/mme/sgsap-handler.h | 1 + src/mme/sgsap-sm.c | 3 + src/mme/sgsap-types.h | 3 + tests/common/test-packet.c | 22 ++++ tests/common/test-packet.h | 1 + tests/csfb/csfb-test.c | 207 +++++++++++++++++++++++++++++++++---- 8 files changed, 302 insertions(+), 33 deletions(-) diff --git a/lib/nas/nas-types.h b/lib/nas/nas-types.h index 8f5ab37ea..dc3ca6962 100644 --- a/lib/nas/nas-types.h +++ b/lib/nas/nas-types.h @@ -377,6 +377,7 @@ ED3(uint8_t cn_specific_drx_cycle_length_coefficient_and_drx_value_for_s1_mode:4 * A.1 Causes related to UE identification */ #define EMM_CAUSE_IMSI_UNKNOWN_IN_HSS 2 #define EMM_CAUSE_ILLEGAL_UE 3 +#define EMM_CAUSE_IMSI_UNKNOWN_IN_VLR 4 #define EMM_CAUSE_ILLEGAL_ME 6 #define EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK 9 #define EMM_CAUSE_IMPLICITLY_DETACHED 10 diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 76a5e5560..36ddb73f6 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -58,13 +58,16 @@ void sgsap_handler_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) case SGSAP_IE_MOBILE_IDENTITY_TYPE: nas_mobile_identity_tmsi = iter->value; break; + default: + ogs_warn("Invalid Type [%d]", iter->type); + break; } iter = iter->next; } ogs_tlv_free_all(root); - ogs_assert(nas_mobile_identity_imsi && lai && nas_mobile_identity_tmsi); + ogs_assert(nas_mobile_identity_imsi && lai); ogs_assert(nas_mobile_identity_imsi_len == SGSAP_IE_IMSI_LEN); if (nas_mobile_identity_imsi->type == NAS_MOBILE_IDENTITY_IMSI) { @@ -73,24 +76,23 @@ void sgsap_handler_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) nas_imsi_to_bcd(nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, imsi_bcd); mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); - } else { - ogs_error("Not supported Identity type[%d]", - nas_mobile_identity_imsi->type); - goto error; - } + } else + ogs_assert_if_reached(); ogs_assert(mme_ue); - if (nas_mobile_identity_tmsi->type == NAS_MOBILE_IDENTITY_TMSI) { - mme_ue->p_tmsi = ntohl(nas_mobile_identity_tmsi->tmsi); - } else { - ogs_error("Not supported Identity type[%d]", - nas_mobile_identity_tmsi->type); - goto error; - } + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - ogs_debug(" IMSI[%s] P-TMSI[0x%08x]", - mme_ue->imsi_bcd, mme_ue->p_tmsi); + if (nas_mobile_identity_tmsi) { + if (nas_mobile_identity_tmsi->type == NAS_MOBILE_IDENTITY_TMSI) { + mme_ue->p_tmsi = ntohl(nas_mobile_identity_tmsi->tmsi); + } else { + ogs_error("Not supported Identity type[%d]", + nas_mobile_identity_tmsi->type); + goto error; + } + ogs_debug(" P-TMSI[0x%08x]", mme_ue->p_tmsi); + } nas_send_attach_accept(mme_ue); @@ -105,3 +107,68 @@ error: ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); } + +void sgsap_handler_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) +{ + ogs_tlv_t *root = NULL, *iter = NULL; + mme_ue_t *mme_ue = NULL; + enb_ue_t *enb_ue = NULL; + + nas_mobile_identity_imsi_t *nas_mobile_identity_imsi = NULL; + int nas_mobile_identity_imsi_len = 0; + nas_emm_cause_t emm_cause = 0; + + ogs_assert(vlr); + ogs_assert(pkbuf); + + ogs_warn("[SGSAP] LOCATION-UPDATE-REJECT"); + + ogs_pkbuf_pull(pkbuf, 1); + + root = ogs_tlv_parse_block(pkbuf->len, pkbuf->data, OGS_TLV_MODE_T1_L1); + ogs_assert(root); + + iter = root; + while (iter) { + switch (iter->type) { + case SGSAP_IE_IMSI_TYPE: + nas_mobile_identity_imsi = iter->value; + nas_mobile_identity_imsi_len = iter->length; + break; + case SGSAP_IE_LAI_TYPE: + break; + case SGSAP_IE_REJECT_CAUSE_TYPE: + emm_cause = *((uint8_t*)(iter->value)); + break; + default: + ogs_warn("Invalid Type [%d]", iter->type); + break; + } + iter = iter->next; + } + + ogs_tlv_free_all(root); + + ogs_assert(nas_mobile_identity_imsi && emm_cause); + ogs_assert(nas_mobile_identity_imsi_len == SGSAP_IE_IMSI_LEN); + + if (nas_mobile_identity_imsi->type == NAS_MOBILE_IDENTITY_IMSI) { + char imsi_bcd[MAX_IMSI_BCD_LEN+1]; + + nas_imsi_to_bcd(nas_mobile_identity_imsi, + nas_mobile_identity_imsi_len, imsi_bcd); + mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); + } else + ogs_assert_if_reached(); + + ogs_assert(mme_ue); + + ogs_debug(" IMSI[%s] CAUSE[%d]", mme_ue->imsi_bcd, emm_cause); + + enb_ue = mme_ue->enb_ue; + ogs_assert(enb_ue); + + nas_send_attach_reject(mme_ue, + emm_cause, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + mme_send_delete_session_or_ue_context_release(mme_ue, enb_ue); +} diff --git a/src/mme/sgsap-handler.h b/src/mme/sgsap-handler.h index 67fd6b821..dba9062b2 100644 --- a/src/mme/sgsap-handler.h +++ b/src/mme/sgsap-handler.h @@ -27,6 +27,7 @@ extern "C" { #endif void sgsap_handler_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); +void sgsap_handler_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf); #ifdef __cplusplus } diff --git a/src/mme/sgsap-sm.c b/src/mme/sgsap-sm.c index 52d0f024d..5009e9cfe 100644 --- a/src/mme/sgsap-sm.c +++ b/src/mme/sgsap-sm.c @@ -120,6 +120,9 @@ void sgsap_state_connected(ogs_fsm_t *s, mme_event_t *e) case SGSAP_LOCATION_UPDATE_ACCEPT: sgsap_handler_location_update_accept(vlr, pkbuf); break; + case SGSAP_LOCATION_UPDATE_REJECT: + sgsap_handler_location_update_reject(vlr, pkbuf); + break; default: ogs_warn("Not implemented(type:%d)", type); break; diff --git a/src/mme/sgsap-types.h b/src/mme/sgsap-types.h index 349c8ce20..530ee095e 100644 --- a/src/mme/sgsap-types.h +++ b/src/mme/sgsap-types.h @@ -28,6 +28,7 @@ extern "C" { #define SGSAP_SERVICE_REQUEST 6 #define SGSAP_LOCATION_UPDATE_REQUEST 9 #define SGSAP_LOCATION_UPDATE_ACCEPT 10 +#define SGSAP_LOCATION_UPDATE_REJECT 11 #define SGSAP_TMSI_REALLOCATION_COMPLETE 12 #define SGSAP_MO_CSFB_INDICIATION 24 @@ -43,6 +44,8 @@ extern "C" { #define SGSAP_IE_EPS_UPDATE_LEN 1 #define SGSAP_IE_MOBILE_IDENTITY_TYPE 14 #define SGSAP_IE_MOBILE_IDENTITY_LEN 5 +#define SGSAP_IE_REJECT_CAUSE_TYPE 15 +#define SGSAP_IE_REJECT_CAUSE_LEN 1 #define SGSAP_IE_SERVICE_INDICATOR_TYPE 32 #define SGSAP_IE_SERVICE_INDICATOR_LEN 1 #define SGSAP_IE_UE_EMM_MODE_TYPE 37 diff --git a/tests/common/test-packet.c b/tests/common/test-packet.c index 3b5881510..d2a52df0e 100644 --- a/tests/common/test-packet.c +++ b/tests/common/test-packet.c @@ -3023,3 +3023,25 @@ int testsgsap_location_update_accept(ogs_pkbuf_t **pkbuf, int i) return OGS_OK; } + +int testsgsap_location_update_reject(ogs_pkbuf_t **pkbuf, int i) +{ + char *payload[TESTS1AP_MAX_MESSAGE] = { + "0b01082926240000 1118930f01030405 09f1070926", + "", + "", + + }; + uint16_t len[TESTS1AP_MAX_MESSAGE] = { + 21, + 0, + 0, + }; + char hexbuf[MAX_SDU_LEN]; + + *pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); + ogs_pkbuf_put_data(*pkbuf, + OGS_HEX(payload[i], strlen(payload[i]), hexbuf), len[i]); + + return OGS_OK; +} diff --git a/tests/common/test-packet.h b/tests/common/test-packet.h index 9393dd074..4d214aff8 100644 --- a/tests/common/test-packet.h +++ b/tests/common/test-packet.h @@ -130,6 +130,7 @@ int testgtpu_build_ping(ogs_pkbuf_t **sendbuf, int testgtpu_build_slacc_rs(ogs_pkbuf_t **sendbuf, int i); int testsgsap_location_update_accept(ogs_pkbuf_t **pkbuf, int i); +int testsgsap_location_update_reject(ogs_pkbuf_t **pkbuf, int i); #ifdef __cplusplus } diff --git a/tests/csfb/csfb-test.c b/tests/csfb/csfb-test.c index 0df39ab1d..2b9b33686 100644 --- a/tests/csfb/csfb-test.c +++ b/tests/csfb/csfb-test.c @@ -16,7 +16,6 @@ static void test1_func(abts_case *tc, void *data) { int rv; ogs_socknode_t *s1ap; - ogs_socknode_t *gtpu; ogs_pkbuf_t *sendbuf; ogs_pkbuf_t *recvbuf; s1ap_message_t message; @@ -105,10 +104,6 @@ static void test1_func(abts_case *tc, void *data) s1ap = testenb_s1ap_client("127.0.0.1"); ABTS_PTR_NOTNULL(tc, s1ap); - /* eNB connects to SGW */ - gtpu = testenb_gtpu_server("127.0.0.5"); - ABTS_PTR_NOTNULL(tc, gtpu); - /* Send S1-Setup Reqeust */ rv = tests1ap_build_setup_req( &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x0019b0, 7, 901, 70, 2); @@ -145,6 +140,7 @@ static void test1_func(abts_case *tc, void *data) bson_destroy(doc); /* Send Attach Request */ + mme_self()->mme_ue_s1ap_id = 0; rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); ABTS_INT_EQUAL(tc, OGS_OK, rv); rv = testenb_s1ap_send(s1ap, sendbuf); @@ -263,17 +259,6 @@ static void test1_func(abts_case *tc, void *data) recvbuf->len) == 0); ogs_pkbuf_free(recvbuf); - /* Send GTP-U ICMP Packet */ - rv = testgtpu_build_ping(&sendbuf, "45.45.0.2", "45.45.0.1"); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - rv = testenb_gtpu_send(gtpu, sendbuf); - ABTS_INT_EQUAL(tc, OGS_OK, rv); - - /* Receive GTP-U ICMP Packet */ - recvbuf = testenb_gtpu_read(gtpu); - ABTS_PTR_NOTNULL(tc, recvbuf); - ogs_pkbuf_free(recvbuf); - /* Retreive M-TMSI */ enb_ue = enb_ue_find_by_mme_ue_s1ap_id(1); ogs_assert(enb_ue); @@ -344,9 +329,194 @@ static void test1_func(abts_case *tc, void *data) /* eNB disonncect from MME */ testenb_s1ap_close(s1ap); +} - /* eNB disonncect from SGW */ - testenb_gtpu_close(gtpu); +static void test2_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + s1ap_message_t message; + int i; + int msgindex = 18; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + uint32_t m_tmsi = 0; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"262420000118139\", " + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 0, " + "\"pre_emption_capability\" : 0" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"70D49A71DD1A2B806A25ABE0EF749F1E\", " + "\"opc\" : \"6F1BF53D624B3A43AF6592854E2444C7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"2374\" }, " + "\"rand\" : \"aa266700bc2887354e9f87368d5d0ae7\" " + "}, " + "\"__v\" : 0 " + "}"; + + /* eNB connects to MME */ + s1ap = testenb_s1ap_client("127.0.0.1"); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x0019b0, 7, 901, 70, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + rv = s1ap_decode_pdu(&message, recvbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + s1ap_free_pdu(&message); + ogs_pkbuf_free(recvbuf); + + collection = mongoc_client_get_collection( + context_self()->db.client, + context_self()->db.name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /********** Insert Subscriber in Database */ + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8("262420000118139")); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + /* Send Attach Request */ + mme_self()->mme_ue_s1ap_id = 0; + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity-Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Identity Response */ + rv = tests1ap_build_identity_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send ESM Information Response */ + rv = tests1ap_build_esm_information_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive SGsAP-Location-Update-Request */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send SGsAP-Location-Update-Reject */ + rv = testsgsap_location_update_reject(&sendbuf, 0); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testvlr_sgsap_send(sgsap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Attach Reject */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Receive UE Release Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Complete */ + rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8("262420000118139")); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); } abts_suite *test_csfb(abts_suite *suite) @@ -354,6 +524,7 @@ abts_suite *test_csfb(abts_suite *suite) suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); return suite; }