mirror of
https://github.com/open5gs/open5gs.git
synced 2025-11-01 12:33:41 +00:00
[AMF/MME] Fix security context restoration and state transition cleanup (#3756)
- Backup sensitive security context fields (e.g. xres, kasme, rand, autn, keys, counters) when transitioning from REGISTERED state. - Set the can_restore_security_context flag in common_register_state() based on whether the transition originates from a REGISTERED or de-registered state. - In emm_state_authentication(), restore the security context and revert to the REGISTERED state on authentication failure only if restoration is allowed; otherwise, transition to an exception state. - Remove the redundant unconditional state transition in the cleanup block to prevent overriding a valid restoration.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -2653,6 +2653,62 @@ uint8_t amf_selected_enc_algorithm(amf_ue_t *amf_ue)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backup the sensitive security context fields from the UE context */
|
||||
void amf_backup_security_context(amf_ue_t *amf_ue,
|
||||
amf_security_context_t *backup)
|
||||
{
|
||||
ogs_assert(amf_ue);
|
||||
ogs_assert(backup);
|
||||
|
||||
memcpy(&backup->ue_security_capability, &amf_ue->ue_security_capability,
|
||||
sizeof(backup->ue_security_capability));
|
||||
memcpy(&backup->ue_network_capability, &amf_ue->ue_network_capability,
|
||||
sizeof(backup->ue_network_capability));
|
||||
memcpy(backup->rand, amf_ue->rand, OGS_RAND_LEN);
|
||||
memcpy(backup->autn, amf_ue->autn, OGS_AUTN_LEN);
|
||||
memcpy(backup->xres_star, amf_ue->xres_star, OGS_MAX_RES_LEN);
|
||||
memcpy(backup->abba, amf_ue->abba, OGS_NAS_MAX_ABBA_LEN);
|
||||
backup->abba_len = amf_ue->abba_len;
|
||||
memcpy(backup->hxres_star, amf_ue->hxres_star, OGS_MAX_RES_LEN);
|
||||
memcpy(backup->kamf, amf_ue->kamf, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(backup->knas_int, amf_ue->knas_int, OGS_SHA256_DIGEST_SIZE/2);
|
||||
memcpy(backup->knas_enc, amf_ue->knas_enc, OGS_SHA256_DIGEST_SIZE/2);
|
||||
backup->dl_count = amf_ue->dl_count;
|
||||
backup->ul_count = amf_ue->ul_count.i32;
|
||||
memcpy(backup->kgnb, amf_ue->kgnb, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(backup->nh, amf_ue->nh, OGS_SHA256_DIGEST_SIZE);
|
||||
backup->selected_enc_algorithm = amf_ue->selected_enc_algorithm;
|
||||
backup->selected_int_algorithm = amf_ue->selected_int_algorithm;
|
||||
}
|
||||
|
||||
/* Restore the sensitive security context fields into the UE context */
|
||||
void amf_restore_security_context(amf_ue_t *amf_ue,
|
||||
const amf_security_context_t *backup)
|
||||
{
|
||||
ogs_assert(amf_ue);
|
||||
ogs_assert(backup);
|
||||
|
||||
memcpy(&amf_ue->ue_security_capability, &backup->ue_security_capability,
|
||||
sizeof(amf_ue->ue_security_capability));
|
||||
memcpy(&amf_ue->ue_network_capability, &backup->ue_network_capability,
|
||||
sizeof(amf_ue->ue_network_capability));
|
||||
memcpy(amf_ue->rand, backup->rand, OGS_RAND_LEN);
|
||||
memcpy(amf_ue->autn, backup->autn, OGS_AUTN_LEN);
|
||||
memcpy(amf_ue->xres_star, backup->xres_star, OGS_MAX_RES_LEN);
|
||||
memcpy(amf_ue->abba, backup->abba, OGS_NAS_MAX_ABBA_LEN);
|
||||
amf_ue->abba_len = backup->abba_len;
|
||||
memcpy(amf_ue->hxres_star, backup->hxres_star, OGS_MAX_RES_LEN);
|
||||
memcpy(amf_ue->kamf, backup->kamf, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(amf_ue->knas_int, backup->knas_int, OGS_SHA256_DIGEST_SIZE/2);
|
||||
memcpy(amf_ue->knas_enc, backup->knas_enc, OGS_SHA256_DIGEST_SIZE/2);
|
||||
amf_ue->dl_count = backup->dl_count;
|
||||
amf_ue->ul_count.i32 = backup->ul_count;
|
||||
memcpy(amf_ue->kgnb, backup->kgnb, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(amf_ue->nh, backup->nh, OGS_SHA256_DIGEST_SIZE);
|
||||
amf_ue->selected_enc_algorithm = backup->selected_enc_algorithm;
|
||||
amf_ue->selected_int_algorithm = backup->selected_int_algorithm;
|
||||
}
|
||||
|
||||
void amf_clear_subscribed_info(amf_ue_t *amf_ue)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -237,6 +237,67 @@ struct ran_ue_s {
|
||||
ogs_pool_id_t amf_ue_id;
|
||||
};
|
||||
|
||||
typedef struct amf_security_context_s {
|
||||
/* UE security capability info: supported security features. */
|
||||
ogs_nas_ue_security_capability_t ue_security_capability;
|
||||
/* UE network capability info: supported network features. */
|
||||
ogs_nas_ue_network_capability_t ue_network_capability;
|
||||
|
||||
/* Random challenge value */
|
||||
uint8_t rand[OGS_RAND_LEN];
|
||||
/* Authentication token */
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
/* Expected auth response. */
|
||||
uint8_t xres_star[OGS_MAX_RES_LEN];
|
||||
|
||||
/* NAS backoff parameter value. */
|
||||
uint8_t abba[OGS_NAS_MAX_ABBA_LEN];
|
||||
uint8_t abba_len;
|
||||
|
||||
/* Hash of XRES*. */
|
||||
uint8_t hxres_star[OGS_MAX_RES_LEN];
|
||||
/* Key for AMF derived from NAS key. */
|
||||
uint8_t kamf[OGS_SHA256_DIGEST_SIZE];
|
||||
|
||||
/* Integrity and ciphering keys */
|
||||
uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2];
|
||||
uint8_t knas_enc[OGS_SHA256_DIGEST_SIZE/2];
|
||||
/* Downlink counter */
|
||||
uint32_t dl_count;
|
||||
/* Uplink counter (24-bit stored in uint32_t) */
|
||||
uint32_t ul_count;
|
||||
/* gNB key derived from kasme */
|
||||
uint8_t kgnb[OGS_SHA256_DIGEST_SIZE];
|
||||
|
||||
/*
|
||||
* Next Hop Channing Counter
|
||||
*
|
||||
* Note that the "nhcc" field is not included in the backup
|
||||
* because it is a transient counter used only during next-hop key
|
||||
* derivation. In our design, only the persistent keying material
|
||||
* and related values that are required to recreate the security context
|
||||
* are backed up. The nhcc value is recalculated or updated dynamically
|
||||
* when the next hop key is derived (e.g. via ogs_kdf_nh_enb()),
|
||||
* so it is not necessary to store it in the backup.
|
||||
*
|
||||
* If there is a requirement to preserve the exact nhcc value across state
|
||||
* transitions, you could add it to the backup structure, but typically
|
||||
* it is treated as a computed, temporary value that can be reinitialized
|
||||
* safely without compromising the security context.
|
||||
* struct {
|
||||
* ED2(uint8_t nhcc_spare:5;,
|
||||
* uint8_t nhcc:3;)
|
||||
* };
|
||||
*/
|
||||
|
||||
/* Next hop key */
|
||||
uint8_t nh[OGS_SHA256_DIGEST_SIZE];
|
||||
|
||||
/* Selected algorithms (set by UDM/subscription) */
|
||||
uint8_t selected_enc_algorithm;
|
||||
uint8_t selected_int_algorithm;
|
||||
} amf_security_context_t;
|
||||
|
||||
struct amf_ue_s {
|
||||
ogs_sbi_object_t sbi;
|
||||
ogs_pool_id_t id;
|
||||
@@ -367,6 +428,12 @@ struct amf_ue_s {
|
||||
int security_context_available;
|
||||
int mac_failed;
|
||||
|
||||
/* flag: 1 = allow restoration of security context, 0 = disallow */
|
||||
bool can_restore_security_context;
|
||||
|
||||
/* Backup of security context fields */
|
||||
amf_security_context_t sec_backup;
|
||||
|
||||
/* Security Context */
|
||||
ogs_nas_ue_security_capability_t ue_security_capability;
|
||||
ogs_nas_ue_network_capability_t ue_network_capability;
|
||||
@@ -391,20 +458,29 @@ struct amf_ue_s {
|
||||
char *resource_uri;
|
||||
ogs_sbi_client_t *client;
|
||||
} confirmation_for_5g_aka;
|
||||
/* Random challenge value */
|
||||
uint8_t rand[OGS_RAND_LEN];
|
||||
/* Authentication token */
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
/* Expected auth response. */
|
||||
uint8_t xres_star[OGS_MAX_RES_LEN];
|
||||
|
||||
/* NAS backoff parameter value. */
|
||||
uint8_t abba[OGS_NAS_MAX_ABBA_LEN];
|
||||
uint8_t abba_len;
|
||||
|
||||
/* Hash of XRES*. */
|
||||
uint8_t hxres_star[OGS_MAX_RES_LEN];
|
||||
/* Key for AMF derived from NAS key. */
|
||||
uint8_t kamf[OGS_SHA256_DIGEST_SIZE];
|
||||
OpenAPI_auth_result_e auth_result;
|
||||
|
||||
/* Integrity and ciphering keys */
|
||||
uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2];
|
||||
uint8_t knas_enc[OGS_SHA256_DIGEST_SIZE/2];
|
||||
/* Downlink counter */
|
||||
uint32_t dl_count;
|
||||
/* Uplink counter (24-bit stored in uint32_t) */
|
||||
union {
|
||||
struct {
|
||||
ED3(uint8_t spare;,
|
||||
@@ -413,14 +489,17 @@ struct amf_ue_s {
|
||||
} __attribute__ ((packed));
|
||||
uint32_t i32;
|
||||
} ul_count;
|
||||
/* gNB key derived from kasme */
|
||||
uint8_t kgnb[OGS_SHA256_DIGEST_SIZE];
|
||||
|
||||
struct {
|
||||
ED2(uint8_t nhcc_spare:5;,
|
||||
uint8_t nhcc:3;) /* Next Hop Channing Counter */
|
||||
};
|
||||
/* Next hop key */
|
||||
uint8_t nh[OGS_SHA256_DIGEST_SIZE]; /* NH Security Key */
|
||||
|
||||
/* Selected algorithms (set by UDM/subscription) */
|
||||
/* defined in 'lib/nas/common/types.h'
|
||||
* #define OGS_NAS_SECURITY_ALGORITHMS_NEA0 0
|
||||
* #define OGS_NAS_SECURITY_ALGORITHMS_128_NEA1 1
|
||||
@@ -1006,6 +1085,11 @@ int amf_m_tmsi_free(amf_m_tmsi_t *tmsi);
|
||||
uint8_t amf_selected_int_algorithm(amf_ue_t *amf_ue);
|
||||
uint8_t amf_selected_enc_algorithm(amf_ue_t *amf_ue);
|
||||
|
||||
void amf_backup_security_context(
|
||||
amf_ue_t *amf_ue, amf_security_context_t *backup);
|
||||
void amf_restore_security_context(
|
||||
amf_ue_t *amf_ue, const amf_security_context_t *backup);
|
||||
|
||||
void amf_clear_subscribed_info(amf_ue_t *amf_ue);
|
||||
|
||||
bool amf_update_allowed_nssai(amf_ue_t *amf_ue);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -1279,6 +1279,16 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
|
||||
ogs_assert(amf_ue);
|
||||
}
|
||||
|
||||
/* If transition is from REGISTERED, allow restoration */
|
||||
if (state == GMM_COMMON_STATE_REGISTERED) {
|
||||
amf_ue->can_restore_security_context = 1;
|
||||
amf_backup_security_context(amf_ue, &amf_ue->sec_backup);
|
||||
} else if (state == GMM_COMMON_STATE_DEREGISTERED) {
|
||||
/* Transition from de-registered: do not restore */
|
||||
amf_ue->can_restore_security_context = 0;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
switch (e->h.id) {
|
||||
case AMF_EVENT_5GMM_MESSAGE:
|
||||
nas_message = e->nas.message;
|
||||
@@ -1726,10 +1736,11 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
amf_ue, &nas_message->gmm.authentication_response);
|
||||
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("gmm_handle_authentication_response() failed");
|
||||
r = nas_5gs_send_authentication_reject(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1740,7 +1751,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
authentication_failure_parameter;
|
||||
ogs_assert(authentication_failure_parameter);
|
||||
|
||||
ogs_debug("[%s] Authentication failure [%d]", amf_ue->suci,
|
||||
ogs_warn("[%s] Authentication failure [%d]", amf_ue->suci,
|
||||
authentication_failure->gmm_cause);
|
||||
|
||||
amf_metrics_inst_by_cause_add(authentication_failure->gmm_cause,
|
||||
@@ -1793,9 +1804,8 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
r = nas_5gs_send_authentication_reject(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
goto cleanup;
|
||||
|
||||
break;
|
||||
case OGS_NAS_5GS_REGISTRATION_REQUEST:
|
||||
ogs_warn("Registration request");
|
||||
gmm_cause = gmm_handle_registration_request(
|
||||
@@ -1807,8 +1817,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
r = nas_5gs_send_registration_reject(ran_ue, amf_ue, gmm_cause);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(s, gmm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r = amf_ue_sbi_discover_and_send(
|
||||
@@ -1846,7 +1855,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
r = nas_5gs_send_authentication_reject(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
goto cleanup;
|
||||
} else {
|
||||
amf_ue->t3560.retry_count++;
|
||||
r = nas_5gs_send_authentication_request(amf_ue);
|
||||
@@ -1879,12 +1888,12 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
amf_ue->suci, sbi_message->res_status);
|
||||
}
|
||||
|
||||
r = nas_5gs_send_gmm_reject_from_sbi(
|
||||
amf_ue, sbi_message->res_status);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
SWITCH(sbi_message->h.method)
|
||||
@@ -1897,7 +1906,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
r = nas_5gs_send_authentication_reject(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
CASE(OGS_SBI_HTTP_METHOD_PUT)
|
||||
@@ -1909,7 +1918,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
r = nas_5gs_send_authentication_reject(amf_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
goto cleanup;
|
||||
} else {
|
||||
amf_ue->selected_int_algorithm =
|
||||
amf_selected_int_algorithm(amf_ue);
|
||||
@@ -1923,8 +1932,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
"bypassed with NIA0",
|
||||
amf_ue->selected_enc_algorithm,
|
||||
amf_ue->selected_int_algorithm);
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_security_mode);
|
||||
@@ -2035,6 +2043,26 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e)
|
||||
ogs_error("Unknown event[%s]", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
if (amf_ue->can_restore_security_context) {
|
||||
/* If allowed, restore the security context */
|
||||
amf_restore_security_context(amf_ue, &amf_ue->sec_backup);
|
||||
|
||||
amf_ue->security_context_available = 1;
|
||||
amf_ue->mac_failed = 0;
|
||||
|
||||
OGS_FSM_TRAN(s, &gmm_state_registered);
|
||||
ogs_warn("[%s] Auth failure in registered trans; "
|
||||
"restoring context and going to REGISTERED.", amf_ue->supi);
|
||||
} else {
|
||||
/* Do not restore; transition to exception state */
|
||||
OGS_FSM_TRAN(s, &gmm_state_exception);
|
||||
ogs_warn("[%s] Auth failure in de-registered trans; "
|
||||
"no context restoration.", amf_ue->supi);
|
||||
}
|
||||
}
|
||||
|
||||
void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e)
|
||||
|
||||
@@ -379,6 +379,50 @@ int emm_handle_attach_complete(
|
||||
return r;
|
||||
}
|
||||
|
||||
int emm_handle_authentication_response(
|
||||
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
|
||||
ogs_nas_eps_authentication_response_t *authentication_response)
|
||||
{
|
||||
ogs_nas_authentication_response_parameter_t
|
||||
*authentication_response_parameter =
|
||||
&authentication_response->authentication_response_parameter;
|
||||
|
||||
ogs_assert(authentication_response);
|
||||
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(enb_ue);
|
||||
|
||||
ogs_debug("Authentication response");
|
||||
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
|
||||
|
||||
CLEAR_MME_UE_TIMER(mme_ue->t3460);
|
||||
|
||||
if (authentication_response_parameter->length == 0 ||
|
||||
memcmp(authentication_response_parameter->res, mme_ue->xres,
|
||||
authentication_response_parameter->length) != 0) {
|
||||
ogs_log_hexdump(OGS_LOG_WARN,
|
||||
authentication_response_parameter->res,
|
||||
authentication_response_parameter->length);
|
||||
ogs_log_hexdump(OGS_LOG_WARN,
|
||||
mme_ue->xres, OGS_MAX_RES_LEN);
|
||||
return OGS_ERROR;
|
||||
} else {
|
||||
mme_ue->selected_int_algorithm = mme_selected_int_algorithm(mme_ue);
|
||||
mme_ue->selected_enc_algorithm = mme_selected_enc_algorithm(mme_ue);
|
||||
|
||||
if (mme_ue->selected_int_algorithm ==
|
||||
OGS_NAS_SECURITY_ALGORITHMS_EIA0) {
|
||||
ogs_error("Encrypt[0x%x] can be skipped with EEA0, "
|
||||
"but Integrity[0x%x] cannot be bypassed with EIA0",
|
||||
mme_ue->selected_enc_algorithm,
|
||||
mme_ue->selected_int_algorithm);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int emm_handle_identity_response(
|
||||
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
|
||||
ogs_nas_eps_identity_response_t *identity_response)
|
||||
|
||||
@@ -33,6 +33,10 @@ int emm_handle_attach_complete(
|
||||
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
|
||||
ogs_nas_eps_attach_complete_t *attach_complete);
|
||||
|
||||
int emm_handle_authentication_response(
|
||||
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
|
||||
ogs_nas_eps_authentication_response_t *authentication_response);
|
||||
|
||||
int emm_handle_identity_response(
|
||||
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
|
||||
ogs_nas_eps_identity_response_t *identity_response);
|
||||
|
||||
108
src/mme/emm-sm.c
108
src/mme/emm-sm.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -304,6 +304,15 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
|
||||
mme_ue = mme_ue_find_by_id(e->mme_ue_id);
|
||||
ogs_assert(mme_ue);
|
||||
|
||||
/* If transition is from REGISTERED, allow restoration */
|
||||
if (state == EMM_COMMON_STATE_REGISTERED) {
|
||||
mme_ue->can_restore_security_context = 1;
|
||||
mme_backup_security_context(mme_ue, &mme_ue->sec_backup);
|
||||
} else if (state == EMM_COMMON_STATE_DEREGISTERED) {
|
||||
/* Transition from de-registered: do not restore */
|
||||
mme_ue->can_restore_security_context = 0;
|
||||
}
|
||||
|
||||
switch (e->id) {
|
||||
case MME_EVENT_EMM_MESSAGE:
|
||||
message = e->nas_message;
|
||||
@@ -1060,6 +1069,8 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
ogs_nas_eps_message_t *message = NULL;
|
||||
|
||||
ogs_nas_eps_authentication_failure_t *authentication_failure = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
@@ -1082,64 +1093,27 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
|
||||
switch (message->emm.h.message_type) {
|
||||
case OGS_NAS_EPS_AUTHENTICATION_RESPONSE:
|
||||
{
|
||||
ogs_nas_eps_authentication_response_t *authentication_response =
|
||||
&message->emm.authentication_response;
|
||||
ogs_nas_authentication_response_parameter_t
|
||||
*authentication_response_parameter =
|
||||
&authentication_response->
|
||||
authentication_response_parameter;
|
||||
|
||||
ogs_debug("Authentication response");
|
||||
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
|
||||
|
||||
CLEAR_MME_UE_TIMER(mme_ue->t3460);
|
||||
|
||||
if (authentication_response_parameter->length == 0 ||
|
||||
memcmp(authentication_response_parameter->res,
|
||||
mme_ue->xres,
|
||||
authentication_response_parameter->length) != 0) {
|
||||
ogs_log_hexdump(OGS_LOG_WARN,
|
||||
authentication_response_parameter->res,
|
||||
authentication_response_parameter->length);
|
||||
ogs_log_hexdump(OGS_LOG_WARN,
|
||||
mme_ue->xres, OGS_MAX_RES_LEN);
|
||||
rv = emm_handle_authentication_response(enb_ue, mme_ue,
|
||||
&message->emm.authentication_response);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("emm_handle_authentication_response() failed");
|
||||
r = nas_eps_send_authentication_reject(mme_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
} else {
|
||||
mme_ue->selected_int_algorithm =
|
||||
mme_selected_int_algorithm(mme_ue);
|
||||
mme_ue->selected_enc_algorithm =
|
||||
mme_selected_enc_algorithm(mme_ue);
|
||||
|
||||
if (mme_ue->selected_int_algorithm ==
|
||||
OGS_NAS_SECURITY_ALGORITHMS_EIA0) {
|
||||
ogs_error("Encrypt[0x%x] can be skipped with EEA0, "
|
||||
"but Integrity[0x%x] cannot be bypassed with EIA0",
|
||||
mme_ue->selected_enc_algorithm,
|
||||
mme_ue->selected_int_algorithm);
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
break;
|
||||
}
|
||||
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_security_mode);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_security_mode);
|
||||
break;
|
||||
}
|
||||
case OGS_NAS_EPS_AUTHENTICATION_FAILURE:
|
||||
{
|
||||
ogs_nas_eps_authentication_failure_t *authentication_failure =
|
||||
&message->emm.authentication_failure;
|
||||
authentication_failure = &message->emm.authentication_failure;
|
||||
ogs_nas_authentication_failure_parameter_t
|
||||
*authentication_failure_parameter =
|
||||
&authentication_failure->
|
||||
authentication_failure_parameter;
|
||||
|
||||
ogs_debug("Authentication failure");
|
||||
ogs_debug(" IMSI[%s] OGS_NAS_EMM_CAUSE[%d]", mme_ue->imsi_bcd,
|
||||
ogs_warn("Authentication failure");
|
||||
ogs_warn(" IMSI[%s] OGS_NAS_EMM_CAUSE[%d]", mme_ue->imsi_bcd,
|
||||
authentication_failure->emm_cause);
|
||||
|
||||
CLEAR_MME_UE_TIMER(mme_ue->t3460);
|
||||
@@ -1167,18 +1141,15 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
r = nas_eps_send_authentication_reject(mme_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
goto cleanup;
|
||||
|
||||
break;
|
||||
}
|
||||
case OGS_NAS_EPS_ATTACH_REQUEST:
|
||||
ogs_warn("[%s] Attach request", mme_ue->imsi_bcd);
|
||||
rv = emm_handle_attach_request(
|
||||
enb_ue, mme_ue, &message->emm.attach_request, e->pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("emm_handle_attach_request() failed");
|
||||
OGS_FSM_TRAN(s, emm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mme_s6a_send_air(enb_ue, mme_ue, NULL);
|
||||
@@ -1194,8 +1165,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
enb_ue, mme_ue, &message->emm.detach_request_from_ue);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("emm_handle_detach_request() failed");
|
||||
OGS_FSM_TRAN(s, emm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!MME_UE_HAVE_IMSI(mme_ue)) {
|
||||
@@ -1203,8 +1173,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_eps_send_service_reject(enb_ue, mme_ue,
|
||||
OGS_NAS_EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK));
|
||||
OGS_FSM_TRAN(s, &emm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) {
|
||||
@@ -1212,8 +1181,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_eps_send_service_reject(enb_ue, mme_ue,
|
||||
OGS_NAS_EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK));
|
||||
OGS_FSM_TRAN(s, &emm_state_exception);
|
||||
break;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1243,11 +1211,10 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
mme_timer_cfg(MME_TIMER_T3460)->max_count) {
|
||||
ogs_warn("Retransmission of IMSI[%s] failed. "
|
||||
"Stop retransmission", mme_ue->imsi_bcd);
|
||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||
|
||||
r = nas_eps_send_authentication_reject(mme_ue);
|
||||
ogs_expect(r == OGS_OK);
|
||||
ogs_assert(r != OGS_ERROR);
|
||||
goto cleanup;
|
||||
} else {
|
||||
mme_ue->t3460.retry_count++;
|
||||
r = nas_eps_send_authentication_request(mme_ue);
|
||||
@@ -1265,6 +1232,27 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
|
||||
ogs_error("Unknown event[%s]", mme_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
if (mme_ue->can_restore_security_context) {
|
||||
/* If allowed, restore the security context */
|
||||
mme_restore_security_context(mme_ue, &mme_ue->sec_backup);
|
||||
|
||||
mme_ue->security_context_available = 1;
|
||||
mme_ue->mac_failed = 0;
|
||||
|
||||
OGS_FSM_TRAN(s, &emm_state_registered);
|
||||
ogs_warn("[%s] Auth failure in registered trans; "
|
||||
"restoring context and going to REGISTERED.",
|
||||
mme_ue->imsi_bcd);
|
||||
} else {
|
||||
/* Do not restore; transition to exception state */
|
||||
OGS_FSM_TRAN(s, &emm_state_exception);
|
||||
ogs_warn("[%s] Auth failure in de-registered trans; "
|
||||
"no context restoration.", mme_ue->imsi_bcd);
|
||||
}
|
||||
}
|
||||
|
||||
void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -5030,6 +5030,82 @@ uint8_t mme_selected_enc_algorithm(mme_ue_t *mme_ue)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backup the sensitive security context fields from the UE context */
|
||||
void mme_backup_security_context(
|
||||
mme_ue_t *mme_ue, mme_security_context_t *backup)
|
||||
{
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(backup);
|
||||
|
||||
memcpy(&backup->ue_network_capability,
|
||||
&mme_ue->ue_network_capability,
|
||||
sizeof(backup->ue_network_capability));
|
||||
memcpy(&backup->ms_network_capability,
|
||||
&mme_ue->ms_network_capability,
|
||||
sizeof(backup->ms_network_capability));
|
||||
memcpy(&backup->ue_additional_security_capability,
|
||||
&mme_ue->ue_additional_security_capability,
|
||||
sizeof(backup->ue_additional_security_capability));
|
||||
memcpy(backup->xres, mme_ue->xres, OGS_MAX_RES_LEN);
|
||||
backup->xres_len = mme_ue->xres_len;
|
||||
memcpy(backup->kasme, mme_ue->kasme, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(backup->rand, mme_ue->rand, OGS_RAND_LEN);
|
||||
memcpy(backup->autn, mme_ue->autn, OGS_AUTN_LEN);
|
||||
memcpy(backup->knas_int, mme_ue->knas_int,
|
||||
OGS_SHA256_DIGEST_SIZE / 2);
|
||||
memcpy(backup->knas_enc, mme_ue->knas_enc,
|
||||
OGS_SHA256_DIGEST_SIZE / 2);
|
||||
backup->dl_count = mme_ue->dl_count;
|
||||
backup->ul_count = mme_ue->ul_count.i32;
|
||||
memcpy(backup->kenb, mme_ue->kenb, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(backup->hash_mme, mme_ue->hash_mme, OGS_HASH_MME_LEN);
|
||||
backup->nonceue = mme_ue->nonceue;
|
||||
backup->noncemme = mme_ue->noncemme;
|
||||
backup->gprs_ciphering_key_sequence_number =
|
||||
mme_ue->gprs_ciphering_key_sequence_number;
|
||||
memcpy(backup->nh, mme_ue->nh, OGS_SHA256_DIGEST_SIZE);
|
||||
backup->selected_enc_algorithm = mme_ue->selected_enc_algorithm;
|
||||
backup->selected_int_algorithm = mme_ue->selected_int_algorithm;
|
||||
}
|
||||
|
||||
/* Restore the sensitive security context fields into the UE context */
|
||||
void mme_restore_security_context(
|
||||
mme_ue_t *mme_ue, const mme_security_context_t *backup)
|
||||
{
|
||||
ogs_assert(mme_ue);
|
||||
ogs_assert(backup);
|
||||
|
||||
memcpy(&mme_ue->ue_network_capability,
|
||||
&backup->ue_network_capability,
|
||||
sizeof(mme_ue->ue_network_capability));
|
||||
memcpy(&mme_ue->ms_network_capability,
|
||||
&backup->ms_network_capability,
|
||||
sizeof(mme_ue->ms_network_capability));
|
||||
memcpy(&mme_ue->ue_additional_security_capability,
|
||||
&backup->ue_additional_security_capability,
|
||||
sizeof(mme_ue->ue_additional_security_capability));
|
||||
memcpy(mme_ue->xres, backup->xres, OGS_MAX_RES_LEN);
|
||||
mme_ue->xres_len = backup->xres_len;
|
||||
memcpy(mme_ue->kasme, backup->kasme, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(mme_ue->rand, backup->rand, OGS_RAND_LEN);
|
||||
memcpy(mme_ue->autn, backup->autn, OGS_AUTN_LEN);
|
||||
memcpy(mme_ue->knas_int, backup->knas_int,
|
||||
OGS_SHA256_DIGEST_SIZE / 2);
|
||||
memcpy(mme_ue->knas_enc, backup->knas_enc,
|
||||
OGS_SHA256_DIGEST_SIZE / 2);
|
||||
mme_ue->dl_count = backup->dl_count;
|
||||
mme_ue->ul_count.i32 = backup->ul_count;
|
||||
memcpy(mme_ue->kenb, backup->kenb, OGS_SHA256_DIGEST_SIZE);
|
||||
memcpy(mme_ue->hash_mme, backup->hash_mme, OGS_HASH_MME_LEN);
|
||||
mme_ue->nonceue = backup->nonceue;
|
||||
mme_ue->noncemme = backup->noncemme;
|
||||
mme_ue->gprs_ciphering_key_sequence_number =
|
||||
backup->gprs_ciphering_key_sequence_number;
|
||||
memcpy(mme_ue->nh, backup->nh, OGS_SHA256_DIGEST_SIZE);
|
||||
mme_ue->selected_enc_algorithm = backup->selected_enc_algorithm;
|
||||
mme_ue->selected_int_algorithm = backup->selected_int_algorithm;
|
||||
}
|
||||
|
||||
static void stats_add_enb_ue(void)
|
||||
{
|
||||
mme_metrics_inst_global_inc(MME_METR_GLOB_GAUGE_ENB_UE);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -342,6 +342,69 @@ struct sgw_ue_s {
|
||||
ogs_pool_id_t mme_ue_id;
|
||||
};
|
||||
|
||||
typedef struct mme_security_context_s {
|
||||
/* UE network capability info: supported network features. */
|
||||
ogs_nas_ue_network_capability_t ue_network_capability;
|
||||
/* MS network capability info: supported network features. */
|
||||
ogs_nas_ms_network_capability_t ms_network_capability;
|
||||
/* UE additional security capability: extra security features. */
|
||||
ogs_nas_ue_additional_security_capability_t
|
||||
ue_additional_security_capability;
|
||||
|
||||
/* Expected response and its length */
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
uint8_t xres_len;
|
||||
/* Derived key from HSS */
|
||||
uint8_t kasme[OGS_SHA256_DIGEST_SIZE];
|
||||
/* Random challenge value */
|
||||
uint8_t rand[OGS_RAND_LEN];
|
||||
/* Authentication token */
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
/* Integrity and ciphering keys */
|
||||
uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2];
|
||||
uint8_t knas_enc[OGS_SHA256_DIGEST_SIZE/2];
|
||||
/* Downlink counter */
|
||||
uint32_t dl_count;
|
||||
/* Uplink counter (24-bit stored in uint32_t) */
|
||||
uint32_t ul_count;
|
||||
/* eNB key derived from kasme */
|
||||
uint8_t kenb[OGS_SHA256_DIGEST_SIZE];
|
||||
/* Hash used for NAS message integrity */
|
||||
uint8_t hash_mme[OGS_HASH_MME_LEN];
|
||||
/* Nonces for resynchronization */
|
||||
uint32_t nonceue;
|
||||
uint32_t noncemme;
|
||||
/* GPRS ciphering key sequence number */
|
||||
uint8_t gprs_ciphering_key_sequence_number;
|
||||
|
||||
/*
|
||||
* Next Hop Channing Counter
|
||||
*
|
||||
* Note that the "nhcc" field is not included in the backup
|
||||
* because it is a transient counter used only during next-hop key
|
||||
* derivation. In our design, only the persistent keying material
|
||||
* and related values that are required to recreate the security context
|
||||
* are backed up. The nhcc value is recalculated or updated dynamically
|
||||
* when the next hop key is derived (e.g. via ogs_kdf_nh_enb()),
|
||||
* so it is not necessary to store it in the backup.
|
||||
*
|
||||
* If there is a requirement to preserve the exact nhcc value across state
|
||||
* transitions, you could add it to the backup structure, but typically
|
||||
* it is treated as a computed, temporary value that can be reinitialized
|
||||
* safely without compromising the security context.
|
||||
* struct {
|
||||
* ED2(uint8_t nhcc_spare:5;,
|
||||
* uint8_t nhcc:3;)
|
||||
* };
|
||||
*/
|
||||
|
||||
/* Next hop key */
|
||||
uint8_t nh[OGS_SHA256_DIGEST_SIZE];
|
||||
/* Selected algorithms (set by HSS/subscription) */
|
||||
uint8_t selected_enc_algorithm;
|
||||
uint8_t selected_int_algorithm;
|
||||
} mme_security_context_t;
|
||||
|
||||
struct mme_ue_s {
|
||||
ogs_lnode_t lnode;
|
||||
ogs_pool_id_t id;
|
||||
@@ -462,19 +525,32 @@ struct mme_ue_s {
|
||||
int security_context_available;
|
||||
int mac_failed;
|
||||
|
||||
/* flag: 1 = allow restoration of security context, 0 = disallow */
|
||||
bool can_restore_security_context;
|
||||
|
||||
/* Backup of security context fields */
|
||||
mme_security_context_t sec_backup;
|
||||
|
||||
/* Security Context */
|
||||
ogs_nas_ue_network_capability_t ue_network_capability;
|
||||
ogs_nas_ms_network_capability_t ms_network_capability;
|
||||
ogs_nas_ue_additional_security_capability_t
|
||||
ue_additional_security_capability;
|
||||
/* Expected response and its length */
|
||||
uint8_t xres[OGS_MAX_RES_LEN];
|
||||
uint8_t xres_len;
|
||||
/* Derived key from HSS */
|
||||
uint8_t kasme[OGS_SHA256_DIGEST_SIZE];
|
||||
/* Random challenge value */
|
||||
uint8_t rand[OGS_RAND_LEN];
|
||||
/* Authentication token */
|
||||
uint8_t autn[OGS_AUTN_LEN];
|
||||
/* Integrity and ciphering keys */
|
||||
uint8_t knas_int[OGS_SHA256_DIGEST_SIZE/2];
|
||||
uint8_t knas_enc[OGS_SHA256_DIGEST_SIZE/2];
|
||||
/* Downlink counter */
|
||||
uint32_t dl_count;
|
||||
/* Uplink counter (24-bit stored in i32) */
|
||||
union {
|
||||
struct {
|
||||
ED3(uint8_t spare;,
|
||||
@@ -483,17 +559,23 @@ struct mme_ue_s {
|
||||
} __attribute__ ((packed));
|
||||
uint32_t i32;
|
||||
} ul_count;
|
||||
/* eNB key derived from kasme */
|
||||
uint8_t kenb[OGS_SHA256_DIGEST_SIZE];
|
||||
/* Hash used for NAS message integrity */
|
||||
uint8_t hash_mme[OGS_HASH_MME_LEN];
|
||||
/* Nonces for resynchronization */
|
||||
uint32_t nonceue, noncemme;
|
||||
/* GPRS ciphering key sequence number */
|
||||
uint8_t gprs_ciphering_key_sequence_number;
|
||||
|
||||
struct {
|
||||
ED2(uint8_t nhcc_spare:5;,
|
||||
uint8_t nhcc:3;) /* Next Hop Channing Counter */
|
||||
};
|
||||
uint8_t nh[OGS_SHA256_DIGEST_SIZE]; /* NH Security Key */
|
||||
/* Next hop key */
|
||||
uint8_t nh[OGS_SHA256_DIGEST_SIZE];
|
||||
|
||||
/* Selected algorithms (set by HSS/subscription) */
|
||||
/* defined in 'nas_ies.h'
|
||||
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EEA1 1
|
||||
@@ -1133,6 +1215,11 @@ void mme_ebi_pool_clear(mme_ue_t *mme_ue);
|
||||
uint8_t mme_selected_int_algorithm(mme_ue_t *mme_ue);
|
||||
uint8_t mme_selected_enc_algorithm(mme_ue_t *mme_ue);
|
||||
|
||||
void mme_backup_security_context(
|
||||
mme_ue_t *mme_ue, mme_security_context_t *backup);
|
||||
void mme_restore_security_context(
|
||||
mme_ue_t *mme_ue, const mme_security_context_t *backup);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -345,11 +345,6 @@ static void test1_func(abts_case *tc, void *data)
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Receive UE Context Release Command */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Attach Request - No Integrity */
|
||||
sess->pdn_connectivity_param.eit = 1;
|
||||
sess->pdn_connectivity_param.pco = 1;
|
||||
@@ -407,17 +402,6 @@ static void test1_func(abts_case *tc, void *data)
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Receive UE Context Release Command */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send UE Context Release Complete */
|
||||
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/*
|
||||
* --- Immediately Re-attach Test ---
|
||||
*
|
||||
@@ -489,6 +473,30 @@ static void test1_func(abts_case *tc, void *data)
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Detach Request */
|
||||
emmbuf = testemm_build_detach_request(test_ue, 1, true, false);
|
||||
ABTS_PTR_NOTNULL(tc, emmbuf);
|
||||
sendbuf = test_s1ap_build_initial_ue_message(
|
||||
test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive OLD UE Context Release Command */
|
||||
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
|
||||
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
tests1ap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send OLD UE Context Release Complete */
|
||||
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testenb_s1ap_send(s1ap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
|
||||
|
||||
/* Receive UE Context Release Command */
|
||||
recvbuf = testenb_s1ap_read(s1ap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -34,6 +34,7 @@ static void test1_func(abts_case *tc, void *data)
|
||||
|
||||
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
|
||||
test_ue_t *test_ue = NULL;
|
||||
test_sess_t *sess = NULL;
|
||||
test_bearer_t *qos_flow = NULL;
|
||||
|
||||
bson_t *doc = NULL;
|
||||
@@ -72,7 +73,7 @@ static void test1_func(abts_case *tc, void *data)
|
||||
ABTS_PTR_NOTNULL(tc, gtpu);
|
||||
|
||||
/* Send NG-Setup Reqeust */
|
||||
sendbuf = testngap_build_ng_setup_request(0x4000, 27);
|
||||
sendbuf = testngap_build_ng_setup_request(0x4000, 22);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
@@ -88,6 +89,237 @@ static void test1_func(abts_case *tc, void *data)
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
|
||||
|
||||
/* Send Registration request */
|
||||
test_ue->registration_request_param.guti = 1;
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
test_ue->registration_request_param.gmm_capability = 1;
|
||||
test_ue->registration_request_param.s1_ue_network_capability = 1;
|
||||
test_ue->registration_request_param.requested_nssai = 1;
|
||||
test_ue->registration_request_param.last_visited_registered_tai = 1;
|
||||
test_ue->registration_request_param.ue_usage_setting = 1;
|
||||
nasbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, nasbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Identity request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Identity response */
|
||||
gmmbuf = testgmm_build_identity_response(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication response */
|
||||
gmmbuf = testgmm_build_authentication_response(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Security mode command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Security mode complete */
|
||||
gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive InitialContextSetupRequest +
|
||||
* Registration accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_InitialContextSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UERadioCapabilityInfoIndication */
|
||||
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send InitialContextSetupResponse */
|
||||
sendbuf = testngap_build_initial_context_setup_response(test_ue, false);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration complete */
|
||||
gmmbuf = testgmm_build_registration_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Configuration update command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send PDU session establishment request */
|
||||
sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5);
|
||||
ogs_assert(sess);
|
||||
|
||||
sess->ul_nas_transport_param.request_type =
|
||||
OGS_NAS_5GS_REQUEST_TYPE_INITIAL;
|
||||
sess->ul_nas_transport_param.dnn = 1;
|
||||
sess->ul_nas_transport_param.s_nssai = 0;
|
||||
|
||||
sess->pdu_session_establishment_param.ssc_mode = 1;
|
||||
sess->pdu_session_establishment_param.epco = 1;
|
||||
|
||||
gsmbuf = testgsm_build_pdu_session_establishment_request(sess);
|
||||
ABTS_PTR_NOTNULL(tc, gsmbuf);
|
||||
gmmbuf = testgmm_build_ul_nas_transport(sess,
|
||||
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send PDUSessionResourceSetupResponse */
|
||||
sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send UEContextReleaseRequest */
|
||||
sendbuf = testngap_build_ue_context_release_request(test_ue,
|
||||
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity,
|
||||
true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UEContextReleaseComplete */
|
||||
sendbuf = testngap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration request */
|
||||
memset(&test_ue->registration_request_param, 0,
|
||||
sizeof(test_ue->registration_request_param));
|
||||
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
test_ue->registration_request_param.gmm_capability = 1;
|
||||
test_ue->registration_request_param.s1_ue_network_capability = 1;
|
||||
test_ue->registration_request_param.requested_nssai = 1;
|
||||
test_ue->registration_request_param.last_visited_registered_tai = 1;
|
||||
test_ue->registration_request_param.ue_usage_setting = 1;
|
||||
nasbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, nasbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication failure - SYNCH failure */
|
||||
gmmbuf = testgmm_build_authentication_failure(
|
||||
test_ue, OGS_5GMM_CAUSE_SYNCH_FAILURE, 0x11223344);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication failure - MAC failure */
|
||||
gmmbuf = testgmm_build_authentication_failure(
|
||||
test_ue, OGS_5GMM_CAUSE_MAC_FAILURE, 0);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication reject */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send De-registration request */
|
||||
gmmbuf = testgmm_build_de_registration_request(test_ue, 1, true, true);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UEContextReleaseComplete */
|
||||
sendbuf = testngap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration request */
|
||||
memset(&test_ue->registration_request_param, 0,
|
||||
sizeof(test_ue->registration_request_param));
|
||||
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
@@ -137,50 +369,14 @@ static void test1_func(abts_case *tc, void *data)
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send Registration request */
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
/* Send UEContextReleaseRequest */
|
||||
sendbuf = testngap_build_ue_context_release_request(test_ue,
|
||||
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity,
|
||||
true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
|
||||
/* OLD Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send OLD UEContextReleaseComplete */
|
||||
sendbuf = testngap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
#endif
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication failure - MAC failure */
|
||||
gmmbuf = testgmm_build_authentication_failure(
|
||||
test_ue, OGS_5GMM_CAUSE_MAC_FAILURE, 0);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication reject */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
@@ -195,6 +391,8 @@ static void test1_func(abts_case *tc, void *data)
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
ogs_msleep(300);
|
||||
|
||||
/********** Remove Subscriber in Database */
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2025 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
@@ -650,17 +650,161 @@ static void test3_func(abts_case *tc, void *data)
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
#if 0 /* To reject UE registration */
|
||||
/********** Insert Subscriber in Database */
|
||||
doc = test_db_new_simple(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, doc);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
|
||||
#endif
|
||||
|
||||
/* Send Registration request */
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
test_ue->registration_request_param.gmm_capability = 1;
|
||||
test_ue->registration_request_param.s1_ue_network_capability = 1;
|
||||
test_ue->registration_request_param.requested_nssai = 1;
|
||||
test_ue->registration_request_param.last_visited_registered_tai = 1;
|
||||
test_ue->registration_request_param.ue_usage_setting = 1;
|
||||
nasbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, nasbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Authentication request */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Authentication response */
|
||||
gmmbuf = testgmm_build_authentication_response(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Security mode command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send Security mode complete */
|
||||
gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive InitialContextSetupRequest +
|
||||
* Registration accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_InitialContextSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UERadioCapabilityInfoIndication */
|
||||
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send InitialContextSetupResponse */
|
||||
sendbuf = testngap_build_initial_context_setup_response(test_ue, false);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send Registration complete */
|
||||
gmmbuf = testgmm_build_registration_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive Configuration update command */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
|
||||
/* Send PDU session establishment request */
|
||||
sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5);
|
||||
ogs_assert(sess);
|
||||
|
||||
sess->ul_nas_transport_param.request_type =
|
||||
OGS_NAS_5GS_REQUEST_TYPE_INITIAL;
|
||||
sess->ul_nas_transport_param.dnn = 1;
|
||||
sess->ul_nas_transport_param.s_nssai = 1;
|
||||
|
||||
sess->pdu_session_establishment_param.ssc_mode = 1;
|
||||
sess->pdu_session_establishment_param.epco = 1;
|
||||
|
||||
gsmbuf = testgsm_build_pdu_session_establishment_request(sess);
|
||||
ABTS_PTR_NOTNULL(tc, gsmbuf);
|
||||
gmmbuf = testgmm_build_ul_nas_transport(sess,
|
||||
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive PDUSessionResourceSetupRequest +
|
||||
* DL NAS transport +
|
||||
* PDU session establishment accept */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send PDUSessionResourceSetupResponse */
|
||||
sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Send De-registration request */
|
||||
gmmbuf = testgmm_build_de_registration_request(test_ue, 1, true, true);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Receive UEContextReleaseCommand */
|
||||
recvbuf = testgnb_ngap_read(ngap);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
testngap_recv(test_ue, recvbuf);
|
||||
ABTS_INT_EQUAL(tc,
|
||||
NGAP_ProcedureCode_id_UEContextRelease,
|
||||
test_ue->ngap_procedure_code);
|
||||
|
||||
/* Send UEContextReleaseComplete */
|
||||
sendbuf = testngap_build_ue_context_release_complete(test_ue);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
rv = testgnb_ngap_send(ngap, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/********** Remove Subscriber in Database */
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
|
||||
|
||||
/* Wait for removing subscriber */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Send Registration request */
|
||||
memset(&test_ue->registration_request_param, 0,
|
||||
sizeof(test_ue->registration_request_param));
|
||||
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
|
||||
ABTS_PTR_NOTNULL(tc, gmmbuf);
|
||||
|
||||
sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf,
|
||||
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
|
||||
ABTS_PTR_NOTNULL(tc, sendbuf);
|
||||
@@ -709,11 +853,6 @@ static void test3_func(abts_case *tc, void *data)
|
||||
|
||||
ogs_msleep(300);
|
||||
|
||||
#if 0 /* To reject UE registration */
|
||||
/********** Remove Subscriber in Database */
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
|
||||
#endif
|
||||
|
||||
/* gNB disonncect from UPF */
|
||||
testgnb_gtpu_close(gtpu);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user