[#263] map S6a diameter codes to EMM codes

This commit is contained in:
Sukchan Lee 2019-11-18 10:20:48 +09:00
parent a622feac84
commit f3ccd71db0
6 changed files with 76 additions and 33 deletions

View File

@ -168,6 +168,8 @@ typedef struct ogs_diam_s6a_message_s {
#define OGS_DIAM_S6A_ERROR_EQUIPMENT_UNKNOWN 5422
#define OGS_DIAM_S6A_ERROR_UNKOWN_SERVING_NODE 5423
uint32_t result_code;
uint32_t *err;
uint32_t *exp_err;
ogs_diam_s6a_aia_message_t aia_message;
ogs_diam_s6a_ula_message_t ula_message;

View File

@ -129,18 +129,16 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
if (!MME_UE_HAVE_IMSI(mme_ue)) {
ogs_warn("[EMM] Service request : Unknown UE");
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) {
ogs_warn("No Security Context : IMSI[%s]", mme_ue->imsi_bcd);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
@ -217,9 +215,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
if (!MME_UE_HAVE_IMSI(mme_ue)) {
ogs_warn("[EMM] Extended Service request : Unknown UE");
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
@ -399,27 +396,24 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
if (!MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_warn("No P-TMSI : UE[%s]", mme_ue->imsi_bcd);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, emm_state_exception);
break;
}
if (!SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
ogs_warn("No PDN Connection : UE[%s]", mme_ue->imsi_bcd);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, emm_state_exception);
break;
}
if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) {
ogs_warn("No Security Context : IMSI[%s]", mme_ue->imsi_bcd);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
@ -441,9 +435,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
} else {
ogs_warn(" Unknown CSFB Service Type[%d]",
mme_ue->nas_eps.service.service_type);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
@ -468,9 +461,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
} else {
ogs_warn(" Unknown CSFB Service Type[%d]",
mme_ue->nas_eps.service.service_type);
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}
@ -681,9 +673,8 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
if (message->emm.h.security_header_type
== OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) {
ogs_debug("[EMM] Service request");
rv = nas_send_service_reject(mme_ue,
nas_send_service_reject(mme_ue,
EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED);
ogs_assert(rv == OGS_OK);
OGS_FSM_TRAN(s, &emm_state_exception);
return;
}

View File

@ -245,6 +245,7 @@ static void mme_s6a_aia_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
s6a_message->result_code = hdr->avp_value->i32;
s6a_message->err = &s6a_message->result_code;
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
} else {
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
@ -256,6 +257,7 @@ static void mme_s6a_aia_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avpch, &hdr);
ogs_assert(ret == 0);
s6a_message->result_code = hdr->avp_value->i32;
s6a_message->exp_err = &s6a_message->result_code;
ogs_debug(" Experimental Result Code: %d",
s6a_message->result_code);
}
@ -618,6 +620,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
s6a_message->result_code = hdr->avp_value->i32;
s6a_message->err = &s6a_message->result_code;
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
} else {
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
@ -630,6 +633,7 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avpch, &hdr);
ogs_assert(ret == 0);
s6a_message->result_code = hdr->avp_value->i32;
s6a_message->exp_err = &s6a_message->result_code;
ogs_debug(" Experimental Result Code: %d",
s6a_message->result_code);
}

View File

@ -33,6 +33,51 @@
#include "mme-s6a-handler.h"
#include "mme-path.h"
/* 3GPP TS 29.272 Annex A; Table !.a:
* Mapping from S6a error codes to NAS Cause Codes */
static uint8_t emm_cause_from_diameter(
const uint32_t *dia_err, const uint32_t *dia_exp_err)
{
if (dia_exp_err) {
switch (*dia_exp_err) {
case OGS_DIAM_S6A_ERROR_USER_UNKNOWN: /* 5001 */
return EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED;
case OGS_DIAM_S6A_ERROR_UNKNOWN_EPS_SUBSCRIPTION: /* 5420 */
/* FIXME: Error diagnostic? */
return EMM_CAUSE_NO_SUITABLE_CELLS_IN_TRACKING_AREA;
case OGS_DIAM_S6A_ERROR_RAT_NOT_ALLOWED: /* 5421 */
return EMM_CAUSE_ROAMING_NOT_ALLOWED_IN_THIS_TRACKING_AREA;
case OGS_DIAM_S6A_ERROR_ROAMING_NOT_ALLOWED: /* 5004 */
return EMM_CAUSE_PLMN_NOT_ALLOWED;
//return EMM_CAUSE_EPS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN; (ODB_HPLMN_APN)
//return EMM_CAUSE_ESM_FAILURE; (ODB_ALL_APN)
case OGS_DIAM_S6A_AUTHENTICATION_DATA_UNAVAILABLE: /* 4181 */
return EMM_CAUSE_NETWORK_FAILURE;
}
}
if (dia_err) {
switch (*dia_err) {
case ER_DIAMETER_AUTHORIZATION_REJECTED: /* 5003 */
case ER_DIAMETER_UNABLE_TO_DELIVER: /* 3002 */
case ER_DIAMETER_REALM_NOT_SERVED: /* 3003 */
return EMM_CAUSE_NO_SUITABLE_CELLS_IN_TRACKING_AREA;
case ER_DIAMETER_UNABLE_TO_COMPLY: /* 5012 */
case ER_DIAMETER_INVALID_AVP_VALUE: /* 5004 */
case ER_DIAMETER_AVP_UNSUPPORTED: /* 5001 */
case ER_DIAMETER_MISSING_AVP: /* 5005 */
case ER_DIAMETER_RESOURCES_EXCEEDED: /* 5006 */
case ER_DIAMETER_AVP_OCCURS_TOO_MANY_TIMES: /* 5009 */
default: /* FIXME: only permanent */
return EMM_CAUSE_NETWORK_FAILURE;
}
}
ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe "
"network failure",
dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1);
return EMM_CAUSE_SEVERE_NETWORK_FAILURE;
}
void mme_state_initial(ogs_fsm_t *s, mme_event_t *e)
{
mme_sm_debug(e);
@ -352,11 +397,17 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
if (s6a_message->result_code != ER_DIAMETER_SUCCESS) {
enb_ue_t *enb_ue = NULL;
rv = nas_send_attach_reject(mme_ue,
EMM_CAUSE_IMSI_UNKNOWN_IN_HSS,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
ogs_assert(rv == OGS_OK);
ogs_warn("EMM_CAUSE : IMSI Unknown in HSS");
/* Unfortunately fd doesn't distinguish
* between result-code and experimental-result-code.
*
* However, e.g. 5004 has different meaning
* if used in result-code than in experimental-result-code */
uint8_t emm_cause = emm_cause_from_diameter(
s6a_message->err, s6a_message->exp_err);
nas_send_attach_reject(mme_ue,
emm_cause, ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
ogs_warn("EMM_CAUSE : %d", emm_cause);
enb_ue = mme_ue->enb_ue;
ogs_assert(enb_ue);

View File

@ -114,7 +114,7 @@ int nas_send_attach_accept(mme_ue_t *mme_ue)
return OGS_OK;
}
int nas_send_attach_reject(mme_ue_t *mme_ue,
void nas_send_attach_reject(mme_ue_t *mme_ue,
ogs_nas_emm_cause_t emm_cause, ogs_nas_esm_cause_t esm_cause)
{
int rv;
@ -136,8 +136,6 @@ int nas_send_attach_reject(mme_ue_t *mme_ue,
ogs_assert(rv == OGS_OK && emmbuf);
rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf);
ogs_assert(rv == OGS_OK);
return rv;
}
int nas_send_identity_request(mme_ue_t *mme_ue)
@ -289,9 +287,8 @@ int nas_send_pdn_connectivity_reject(
} else {
/* During the UE-attach process, we'll send Attach-Reject
* with pyggybacking PDN-connectivity-Reject */
rv = nas_send_attach_reject(mme_ue,
nas_send_attach_reject(mme_ue,
EMM_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED, esm_cause);
ogs_assert(rv == OGS_OK);
}
return OGS_OK;
@ -494,7 +491,7 @@ int nas_send_tau_reject(mme_ue_t *mme_ue, ogs_nas_emm_cause_t emm_cause)
return OGS_OK;
}
int nas_send_service_reject(mme_ue_t *mme_ue,
void nas_send_service_reject(mme_ue_t *mme_ue,
ogs_nas_emm_cause_t emm_cause)
{
int rv;
@ -508,8 +505,6 @@ int nas_send_service_reject(mme_ue_t *mme_ue,
rv = nas_send_to_downlink_nas_transport(mme_ue, emmbuf);
ogs_assert(rv == OGS_OK);
return OGS_OK;
}
int nas_send_cs_service_notification(mme_ue_t *mme_ue)

View File

@ -32,7 +32,7 @@ int nas_send_emm_to_esm(
int nas_send_to_downlink_nas_transport(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf);
int nas_send_attach_accept(mme_ue_t *mme_ue);
int nas_send_attach_reject(mme_ue_t *mme_ue,
void nas_send_attach_reject(mme_ue_t *mme_ue,
ogs_nas_emm_cause_t emm_cause, ogs_nas_esm_cause_t esm_cause);
int nas_send_identity_request(mme_ue_t *mme_ue);
@ -58,7 +58,7 @@ int nas_send_deactivate_bearer_context_request(mme_bearer_t *bearer);
int nas_send_tau_accept(mme_ue_t *mme_ue, S1AP_ProcedureCode_t procedureCode);
int nas_send_tau_reject(mme_ue_t *mme_ue, ogs_nas_esm_cause_t emm_cause);
int nas_send_service_reject(mme_ue_t *mme_ue, ogs_nas_emm_cause_t emm_cause);
void nas_send_service_reject(mme_ue_t *mme_ue, ogs_nas_emm_cause_t emm_cause);
int nas_send_cs_service_notification(mme_ue_t *mme_ue);
int nas_send_downlink_nas_transport(