Compare commits

...

5 Commits

Author SHA1 Message Date
Matej Gradisar 24b9150c15 [SMF] Check config file for overlapping UE subnets for subnets with no DNN 2024-02-28 12:06:02 +00:00
Sukchan Lee 4d7f2fb661 [SMF] Memory leak in Handling APCO IE (#3010) 2024-02-28 20:51:20 +09:00
Pau Espin 32de75b1a5 [SMF] Setup Gy session when creating UE session over S2b interface
So far the Gy session creation triggered by S2b interface (ePDG) was not
implemented. Fix it.
2024-02-28 11:42:33 +00:00
Pau Espin 4aaac999f7 [SMF] Handle APCO IE in S2b GTPv2C CreateSessionRequest/Response
This IE is used by UEs registering through S2b interface (ePDG) to
obtain DNS and P-CSCF server address information.
2024-02-28 11:40:31 +00:00
Sukchan Lee 0dd2ad6557 [MME] Added log messages to find memory problem 2024-02-27 21:16:50 +09:00
22 changed files with 162 additions and 90 deletions

View File

@ -1,4 +1,4 @@
/*
/* 3GPP TS 29.273 section 9
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
@ -35,7 +35,8 @@ extern struct dict_object *ogs_diam_s6b_application;
extern struct dict_object *ogs_diam_s6b_mip6_feature_vector;
typedef struct ogs_diam_s6b_message_s {
#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 1
#define OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION 1
#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 2
uint16_t cmd_code;
uint32_t result_code;
uint32_t *err;

View File

@ -154,7 +154,9 @@ static int ogs_pfcp_check_subnet_overlapping(void)
ogs_list_for_each(&self.subnet_list, subnet){
for (next_subnet = ogs_list_next(subnet); (next_subnet);
next_subnet = ogs_list_next(next_subnet)) {
if (strcmp(subnet->dnn, next_subnet->dnn) == 0 &&
if ((strlen(subnet->dnn) == 0 ||
strlen(next_subnet->dnn) == 0 ||
(strcmp(subnet->dnn, next_subnet->dnn)) == 0) &&
subnet->gw.family == next_subnet->gw.family) {
uint32_t *addr1 = subnet->sub.sub;
uint32_t *addr2 = next_subnet->sub.sub;

View File

@ -43,14 +43,10 @@ int ogs_sctp_recvdata(ogs_sock_t *sock, void *msg, size_t len,
} else if (flags & MSG_EOR) {
break;
} else {
if (ogs_socket_errno != OGS_EAGAIN) {
ogs_fatal("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)",
size, errno, strerror(errno), flags);
ogs_assert_if_reached();
} else {
ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)",
size, errno, strerror(errno), flags);
}
ogs_fatal("ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)",
size, errno, strerror(errno), flags);
ogs_fatal("Probably MME might be crashed");
ogs_assert_if_reached();
}
} while(1);

View File

@ -54,9 +54,9 @@ int emm_handle_attach_request(mme_ue_t *mme_ue,
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
MME_UE_LIST_CHECK;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
ogs_assert(enb_ue);
@ -270,9 +270,9 @@ int emm_handle_attach_complete(
struct tm gmt, local;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_info(" IMSI[%s]", mme_ue->imsi_bcd);
MME_UE_LIST_CHECK;
ogs_gettimeofday(&tv);
ogs_gmtime(tv.tv_sec, &gmt);
@ -823,7 +823,7 @@ int emm_handle_security_mode_complete(mme_ue_t *mme_ue,
ogs_nas_mobile_identity_t *imeisv = &security_mode_complete->imeisv;
ogs_assert(mme_ue);
MME_UE_LIST_CHECK;
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
if (security_mode_complete->presencemask &
OGS_NAS_EPS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT) {

View File

@ -933,6 +933,7 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
mme_ue = e->mme_ue;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
switch (e->id) {
case OGS_FSM_ENTRY_SIG:
@ -954,7 +955,6 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
authentication_response_parameter;
ogs_debug("Authentication response");
MME_UE_LIST_CHECK;
ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd);
CLEAR_MME_UE_TIMER(mme_ue->t3460);

View File

@ -36,13 +36,12 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
mme_sess_t *sess = NULL;
uint8_t security_protected_required = 0;
MME_UE_LIST_CHECK;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_assert(req);
@ -182,11 +181,10 @@ int esm_handle_information_response(mme_sess_t *sess,
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_assert(rsp);
MME_UE_LIST_CHECK;
if (rsp->presencemask &
OGS_NAS_EPS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) {
sess->session = mme_session_find_by_apn(

View File

@ -89,6 +89,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e)
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
switch (e->id) {
case OGS_FSM_ENTRY_SIG:
@ -183,7 +184,6 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e)
break;
case OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
ogs_debug("Activate default EPS bearer context accept");
MME_UE_LIST_CHECK;
ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]",
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
/* Check if Initial Context Setup Response or

View File

@ -4394,7 +4394,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
sess->mme_ue ? sess->mme_ue->imsi_bcd : "Unknown",
sess->mme_ue);
}
MME_UE_LIST_CHECK;
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
}
if (!sess) {
@ -4408,7 +4408,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
ogs_debug("[%s:%p]",
sess->mme_ue ? sess->mme_ue->imsi_bcd : "Unknown",
sess->mme_ue);
MME_UE_LIST_CHECK;
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
} else {
sess->pti = pti;
ogs_debug("[%s:%p]", mme_ue->imsi_bcd, mme_ue);
@ -4418,7 +4418,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
ogs_debug("[%s:%p]",
sess->mme_ue ? sess->mme_ue->imsi_bcd : "Unknown",
sess->mme_ue);
MME_UE_LIST_CHECK;
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
}
} else {

View File

@ -148,52 +148,43 @@ typedef struct mme_context_s {
#define MME_UE_CHECK(level, __mME) \
do { \
ogs_log_message(level, 0, "IMSI [%s] NAS-EPS Type[%d]", \
(__mME) ? (__mME)->imsi_bcd : "No MME_UE", \
(__mME) ? (__mME)->nas_eps.type : 0); \
ogs_log_message(level, 0, "mme_ue[%p:%p]", \
sgw_ue_t *__sGW = (((mme_ue_t *)__mME)->sgw_ue); \
mme_sess_t *__sESS = NULL; \
mme_bearer_t *__bEARER = NULL; \
\
ogs_log_message(level, 0, "MME-UE Context Memory[%p:%p]", \
(__mME), mme_ue_cycle((__mME))); \
ogs_log_message(level, 0, "SGW-UE Context Memory[%p:%p]", \
(__sGW), sgw_ue_cycle((__sGW))); \
ogs_log_message(level, 0, \
"IMSI [%s] NAS-EPS Type[%d]", \
(__mME) ? ((mme_ue_t *)__mME)->imsi_bcd : "No MME_UE", \
(__mME) ? ((mme_ue_t *)__mME)->nas_eps.type : 0); \
ogs_log_message(level, 0, \
"MME_S11_TEID[%d] SGW_S11_TEID[%d]", \
(__mME) ? ((mme_ue_t *)__mME)->mme_s11_teid : 0, \
(__sGW) ? (__sGW)->sgw_s11_teid : 0); \
if (!mme_ue_cycle(__mME)) { \
ogs_log_message(level, 0, \
"MME-UE Context has already been removed"); \
break; \
} \
ogs_list_for_each(&((mme_ue_t *)__mME)->sess_list, (__sESS)) { \
ogs_log_message(level, 0, "SESS(%p) [%s:%d]", (__sESS), \
(__sESS)->session ? (__sESS)->session->name : "Unknown", \
(__sESS)->pti); \
ogs_list_for_each(&(__sESS)->bearer_list, (__bEARER)) { \
ogs_log_message(level, 0, \
"BEARER(%p) [%d] ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", \
(__bEARER), (__bEARER)->ebi, \
(__bEARER)->enb_s1u_teid, (__bEARER)->sgw_s1u_teid); \
ogs_assert((__bEARER)->sess == (__sESS)); \
ogs_assert((__bEARER)->mme_ue == (__mME)); \
} \
ogs_assert((__sESS)->mme_ue == (__mME)); \
} \
} while(0)
#define MME_UE_LIST_CHECK \
if (ogs_log_get_domain_level(OGS_LOG_DOMAIN) >= OGS_LOG_TRACE) { \
mme_ue_t *mme_ue = NULL; \
sgw_ue_t *sgw_ue = NULL; \
enb_ue_t *enb_ue = NULL; \
mme_sess_t *sess = NULL; \
mme_bearer_t *bearer = NULL; \
ogs_list_for_each(&mme_self()->mme_ue_list, mme_ue) { \
ogs_trace("MME_UE(%p:%p) [%s] MME_S11_TEID[%d]", \
mme_ue, mme_ue_cycle(mme_ue), \
mme_ue->imsi_bcd, mme_ue->mme_s11_teid); \
if (mme_ue->sgw_ue) { \
sgw_ue = mme_ue->sgw_ue; \
ogs_trace("SGW_UE(%p) MME_UE(%p) SGW_S11_TEID[%d]", \
sgw_ue, mme_ue, sgw_ue->sgw_s11_teid); \
} \
if (mme_ue->enb_ue) { \
enb_ue = mme_ue->enb_ue; \
ogs_trace("ENB_UE(%p) MME_UE(%p) " \
"[ENB_UE_S1AP_ID:%d MME_UE_S1AP_ID:%d]", \
enb_ue, enb_ue->mme_ue, \
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); \
} \
ogs_list_for_each(&mme_ue->sess_list, sess) { \
ogs_trace("SESS(%p) [%s:%d]", sess, \
sess->session ? sess->session->name : "Unknown", \
sess->pti); \
ogs_assert(sess->mme_ue == mme_ue); \
ogs_list_for_each(&sess->bearer_list, bearer) { \
ogs_trace("BEARER(%p) [%d] " \
"ENB_S1U_TEID[%d] SGW_S1U_TEID[%d]", \
bearer, bearer->ebi, \
bearer->enb_s1u_teid, bearer->sgw_s1u_teid); \
ogs_assert(bearer->sess == sess); \
ogs_assert(bearer->mme_ue == mme_ue); \
} \
} \
} \
}
ogs_list_t mme_ue_list;
ogs_hash_t *enb_addr_hash; /* hash table for ENB Address */

View File

@ -347,6 +347,7 @@ int mme_gtp_send_delete_session_request(
}
xact->delete_action = action;
xact->local_teid = mme_ue->gn.mme_gn_teid;
ogs_debug("delete_session_request - xact:%p, sess:%p", xact, sess);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
@ -364,6 +365,7 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action)
ogs_assert(sgw_ue);
ogs_assert(action);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_list_for_each_safe(&mme_ue->sess_list, next_sess, sess) {
if (MME_HAVE_SGW_S1U_PATH(sess)) {
mme_gtp_send_delete_session_request(sgw_ue, sess, action);

View File

@ -479,14 +479,19 @@ ogs_pkbuf_t *mme_s11_build_delete_session_request(
mme_bearer_t *bearer = NULL;
mme_ue_t *mme_ue = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
sgw_ue = mme_ue->sgw_ue;
ogs_assert(sgw_ue);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
ogs_debug("Delete Session Request");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp2_message_t));

View File

@ -103,7 +103,6 @@ void mme_s11_handle_create_session_response(
ogs_assert(rsp);
ogs_debug("Create Session Response");
MME_UE_LIST_CHECK;
/********************
* Check Transaction
@ -112,6 +111,8 @@ void mme_s11_handle_create_session_response(
create_action = xact->create_action;
sess = xact->data;
ogs_assert(sess);
MME_UE_CHECK(OGS_LOG_DEBUG, sess->mme_ue);
mme_ue = mme_ue_cycle(sess->mme_ue);
rv = ogs_gtp_xact_commit(xact);
@ -480,13 +481,14 @@ void mme_s11_handle_modify_bearer_response(
ogs_assert(rsp);
ogs_debug("Modify Bearer Response");
MME_UE_LIST_CHECK;
/********************
* Check Transaction
********************/
ogs_assert(xact);
modify_action = xact->modify_action;
MME_UE_CHECK(OGS_LOG_DEBUG, xact->data);
mme_ue = mme_ue_cycle(xact->data);
rv = ogs_gtp_xact_commit(xact);
@ -592,7 +594,6 @@ void mme_s11_handle_delete_session_response(
ogs_assert(rsp);
ogs_debug("Delete Session Response");
MME_UE_LIST_CHECK;
/********************
* Check Transaction
@ -602,6 +603,9 @@ void mme_s11_handle_delete_session_response(
ogs_assert(action);
sess = xact->data;
ogs_assert(sess);
ogs_debug("delete_session_response - xact:%p, sess:%p", xact, sess);
MME_UE_CHECK(OGS_LOG_DEBUG, sess->mme_ue);
mme_ue = mme_ue_cycle(sess->mme_ue);
rv = ogs_gtp_xact_commit(xact);
@ -1244,7 +1248,6 @@ void mme_s11_handle_release_access_bearers_response(
ogs_assert(rsp);
ogs_debug("Release Access Bearers Response");
MME_UE_LIST_CHECK;
/********************
* Check Transaction
@ -1252,6 +1255,8 @@ void mme_s11_handle_release_access_bearers_response(
ogs_assert(xact);
action = xact->release_action;
ogs_assert(action);
MME_UE_CHECK(OGS_LOG_DEBUG, xact->data);
mme_ue = mme_ue_cycle(xact->data);
rv = ogs_gtp_xact_commit(xact);

View File

@ -255,7 +255,6 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
mme_ue = mme_ue_find_by_message(&nas_message);
if (!mme_ue) {
mme_ue = mme_ue_add(enb_ue);
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
if (mme_ue == NULL) {
r = s1ap_send_ue_context_release_command(enb_ue,
S1AP_Cause_PR_misc,
@ -267,6 +266,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
return;
}
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_assert(ECM_IDLE(mme_ue));
} else {
/* Here, if the MME_UE Context is found,

View File

@ -404,7 +404,6 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_assert(InitialUEMessage);
ogs_info("InitialUEMessage");
MME_UE_LIST_CHECK;
for (i = 0; i < InitialUEMessage->protocolIEs.list.count; i++) {
ie = InitialUEMessage->protocolIEs.list.array[i];
@ -486,6 +485,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
ogs_info("Unknown UE by S_TMSI[G:%d,C:%d,M_TMSI:0x%x]",
nas_guti.mme_gid, nas_guti.mme_code, nas_guti.m_tmsi);
} else {
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_info(" S_TMSI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]",
mme_ue->current.guti.mme_gid,
mme_ue->current.guti.mme_code,
@ -524,13 +524,15 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
} else {
ogs_error("Known UE ENB_UE_S1AP_ID[%d] [%p:%p]",
(int)*ENB_UE_S1AP_ID, enb_ue, enb_ue->mme_ue);
if (enb_ue->mme_ue)
if (enb_ue->mme_ue) {
MME_UE_CHECK(OGS_LOG_DEBUG, enb_ue->mme_ue);
ogs_error(" S_TMSI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]",
enb_ue->mme_ue->current.guti.mme_gid,
enb_ue->mme_ue->current.guti.mme_code,
enb_ue->mme_ue->current.guti.m_tmsi,
MME_UE_HAVE_IMSI(enb_ue->mme_ue)
? enb_ue->mme_ue->imsi_bcd : "Unknown");
}
}
if (!NAS_PDU) {
@ -625,7 +627,6 @@ void s1ap_handle_uplink_nas_transport(
ogs_assert(UplinkNASTransport);
ogs_debug("UplinkNASTransport");
MME_UE_LIST_CHECK;
for (i = 0; i < UplinkNASTransport->protocolIEs.list.count; i++) {
ie = UplinkNASTransport->protocolIEs.list.array[i];
@ -768,6 +769,7 @@ void s1ap_handle_uplink_nas_transport(
if (enb_ue->mme_ue) {
mme_ue_t *mme_ue = enb_ue->mme_ue;
MME_UE_CHECK(OGS_LOG_DEBUG, enb_ue->mme_ue);
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_eps_tai_t));
memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
mme_ue->ue_location_timestamp = ogs_time_now();
@ -808,7 +810,6 @@ void s1ap_handle_ue_capability_info_indication(
ogs_assert(UECapabilityInfoIndication);
ogs_debug("UECapabilityInfoIndication");
MME_UE_LIST_CHECK;
for (i = 0; i < UECapabilityInfoIndication->protocolIEs.list.count; i++) {
ie = UECapabilityInfoIndication->protocolIEs.list.array[i];
@ -874,6 +875,7 @@ void s1ap_handle_ue_capability_info_indication(
if (enb_ue->mme_ue) {
ogs_assert(UERadioCapability);
MME_UE_CHECK(OGS_LOG_DEBUG, enb_ue->mme_ue);
OGS_ASN_STORE_DATA(&enb_ue->mme_ue->ueRadioCapability,
UERadioCapability);
}
@ -907,7 +909,6 @@ void s1ap_handle_initial_context_setup_response(
ogs_assert(InitialContextSetupResponse);
ogs_debug("InitialContextSetupResponse");
MME_UE_LIST_CHECK;
for (i = 0; i < InitialContextSetupResponse->protocolIEs.list.count; i++) {
ie = InitialContextSetupResponse->protocolIEs.list.array[i];
@ -978,6 +979,7 @@ void s1ap_handle_initial_context_setup_response(
return;
}
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
if (E_RABSetupListCtxtSURes) {
int uli_presence = 0;
@ -2062,7 +2064,6 @@ void s1ap_handle_e_rab_modification_indication(
ogs_assert(E_RABModificationIndication);
ogs_info("E_RABModificationIndication");
MME_UE_LIST_CHECK;
for (i = 0; i < E_RABModificationIndication->protocolIEs.list.count; i++) {
ie = E_RABModificationIndication->protocolIEs.list.array[i];
@ -2142,6 +2143,7 @@ void s1ap_handle_e_rab_modification_indication(
return;
}
MME_UE_CHECK(OGS_LOG_DEBUG, mme_ue);
ogs_list_init(&mme_ue->bearer_to_modify_list);
for (i = 0; i < E_RABToBeModifiedListBearerModInd->list.count; i++) {

View File

@ -1682,6 +1682,7 @@ void smf_sess_remove(smf_sess_t *sess)
ogs_fsm_fini(&sess->sm, &e);
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_pco);
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_apco);
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_epco);
OGS_TLV_CLEAR_DATA(&sess->gtp.user_location_information);
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_timezone);

View File

@ -228,6 +228,8 @@ typedef struct smf_sess_s {
uint32_t gx_cca_init_err; /* Gx CCA RXed error code */
bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */
uint32_t gy_cca_init_err; /* Gy CCA RXed error code */
bool s6b_aar_in_flight; /* Waiting for S6B AAR */
uint32_t s6b_aaa_err; /* S6B AAA RXed error code */
bool gx_ccr_term_in_flight; /* Waiting for Gx CCA */
uint32_t gx_cca_term_err; /* Gx CCA RXed error code */
bool gy_ccr_term_in_flight; /* Waiting for Gy CCA */
@ -333,6 +335,7 @@ typedef struct smf_sess_s {
struct {
uint8_t version; /* GTPC version */
ogs_tlv_octet_t ue_pco;
ogs_tlv_octet_t ue_apco;
ogs_tlv_octet_t ue_epco;
ogs_tlv_octet_t user_location_information;
ogs_tlv_octet_t ue_timezone;

View File

@ -182,8 +182,10 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
switch (e->h.id) {
case OGS_FSM_ENTRY_SIG:
/* reset state: */
sess->sm_data.s6b_aar_in_flight = false;
sess->sm_data.gx_ccr_init_in_flight = false;
sess->sm_data.gy_ccr_init_in_flight = false;
sess->sm_data.s6b_aaa_err = ER_DIAMETER_SUCCESS;
sess->sm_data.gx_cca_init_err = ER_DIAMETER_SUCCESS;
sess->sm_data.gy_cca_init_err = ER_DIAMETER_SUCCESS;
break;
@ -229,7 +231,9 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
break;
case OGS_GTP2_RAT_TYPE_WLAN:
smf_s6b_send_aar(sess, e->gtp_xact);
sess->sm_data.s6b_aar_in_flight = true;
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
/* Gx/Gy Init Req is done after s6b AAR + AAA */
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
@ -327,6 +331,7 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
ogs_diam_s6b_message_t *s6b_message = NULL;
ogs_diam_gy_message_t *gy_message = NULL;
ogs_diam_gx_message_t *gx_message = NULL;
uint32_t diam_err;
@ -340,6 +345,22 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
ogs_assert(sess);
switch (e->h.id) {
case SMF_EVT_S6B_MESSAGE:
s6b_message = e->s6b_message;
ogs_assert(s6b_message);
switch(s6b_message->cmd_code) {
case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION:
sess->sm_data.s6b_aar_in_flight = false;
sess->sm_data.s6b_aaa_err = s6b_message->result_code;
if (s6b_message->result_code == ER_DIAMETER_SUCCESS) {
send_ccr_init_req_gx_gy(sess, e);
return;
}
goto test_can_proceed;
}
break;
case SMF_EVT_GX_MESSAGE:
gx_message = e->gx_message;
ogs_assert(gx_message);
@ -382,9 +403,12 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
test_can_proceed:
/* First wait for both Gx and Gy requests to be done: */
if (!sess->sm_data.gx_ccr_init_in_flight &&
if (!sess->sm_data.s6b_aar_in_flight &&
!sess->sm_data.gx_ccr_init_in_flight &&
!sess->sm_data.gy_ccr_init_in_flight) {
diam_err = ER_DIAMETER_SUCCESS;
if (sess->sm_data.s6b_aaa_err != ER_DIAMETER_SUCCESS)
diam_err = sess->sm_data.s6b_aaa_err;
if (sess->sm_data.gx_cca_init_err != ER_DIAMETER_SUCCESS)
diam_err = sess->sm_data.gx_cca_init_err;
if (sess->sm_data.gy_cca_init_err != ER_DIAMETER_SUCCESS)

View File

@ -47,6 +47,8 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
int len;
uint8_t pco_buf[OGS_MAX_PCO_LEN];
int16_t pco_len;
uint8_t apco_buf[OGS_MAX_PCO_LEN];
int16_t apco_len;
uint8_t *epco_buf = NULL;
int16_t epco_len;
@ -145,6 +147,17 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
rsp->protocol_configuration_options.len = pco_len;
}
/* APCO */
if (sess->gtp.ue_apco.presence &&
sess->gtp.ue_apco.len && sess->gtp.ue_apco.data) {
apco_len = smf_pco_build(
apco_buf, sess->gtp.ue_apco.data, sess->gtp.ue_apco.len);
ogs_assert(apco_len > 0);
rsp->additional_protocol_configuration_options.presence = 1;
rsp->additional_protocol_configuration_options.data = apco_buf;
rsp->additional_protocol_configuration_options.len = apco_len;
}
/* ePCO */
if (sess->gtp.ue_epco.presence &&
sess->gtp.ue_epco.len && sess->gtp.ue_epco.data) {

View File

@ -378,6 +378,12 @@ uint8_t smf_s5c_handle_create_session_request(
&req->protocol_configuration_options);
}
/* APCO */
if (req->additional_protocol_configuration_options.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.ue_apco,
&req->additional_protocol_configuration_options);
}
/* Set User Location Information */
if (req->user_location_information.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.user_location_information,
@ -452,6 +458,8 @@ uint8_t smf_s5c_handle_delete_session_request(
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_pco);
}
/* APCO not present in Session deletion procedure, hence no need to clear it here. */
if (req->extended_protocol_configuration_options.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.ue_epco,
&req->extended_protocol_configuration_options);

View File

@ -1,4 +1,4 @@
/*
/* 3GPP TS 29.273 section 9
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
@ -344,11 +344,11 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
unsigned long dur;
int error = 0;
int new;
int result_code = 0;
int exp_result_code = 0;
smf_sess_t *sess = NULL;
ogs_gtp_xact_t *xact = NULL;
smf_event_t *e = NULL;
ogs_diam_s6b_message_t *s6b_message = NULL;
ogs_debug("[AA-Answer]");
@ -374,15 +374,20 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
xact = sess_data->xact;
ogs_assert(xact);
s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t));
ogs_assert(s6b_message);
/* Set Session Termination Command */
s6b_message->cmd_code = OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION;
/* Value of Result Code */
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
result_code = hdr->avp_value->i32;
if (result_code != ER_DIAMETER_SUCCESS) {
ogs_error("Result Code: %d", result_code);
s6b_message->result_code = hdr->avp_value->i32;
if (s6b_message->result_code != ER_DIAMETER_SUCCESS) {
ogs_error("Result Code: %d", s6b_message->result_code);
error++;
}
} else {
@ -397,8 +402,8 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0);
exp_result_code = hdr->avp_value->i32;
ogs_error("Experimental Result Code: %d", exp_result_code);
s6b_message->result_code = hdr->avp_value->i32;
ogs_error("Experimental Result Code: %d", s6b_message->result_code);
}
} else {
ogs_error("no Result-Code");
@ -431,9 +436,22 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
error++;
}
if (!error) {
smf_gx_send_ccr(sess, xact,
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
e = smf_event_new(SMF_EVT_S6B_MESSAGE);
ogs_assert(e);
if (error && s6b_message->result_code == ER_DIAMETER_SUCCESS)
s6b_message->result_code = error;
e->sess = sess;
e->gtp_xact = xact;
e->s6b_message = s6b_message;
ret = ogs_queue_push(ogs_app()->queue, e);
if (ret != OGS_OK) {
ogs_error("ogs_queue_push() failed:%d", (int)ret);
ogs_free(s6b_message);
ogs_event_free(e);
} else {
ogs_pollset_notify(ogs_app()->pollset);
}
/* Free the message */

View File

@ -365,6 +365,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_assert(sess);
switch(s6b_message->cmd_code) {
case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION:
case OGS_DIAM_S6B_CMD_SESSION_TERMINATION:
ogs_fsm_dispatch(&sess->sm, e);
break;

View File

@ -45,6 +45,8 @@ void test_s2b_handle_create_session_response(
cause_value = cause->value;
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
} else if (cause_value ==
OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_NETWORK_PREFERENCE) {
} else {
ogs_error("GTP Failed [CAUSE:%d]", cause_value);
return;