[#263] map S6a diameter codes to EMM codes
This commit is contained in:
parent
a622feac84
commit
f3ccd71db0
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue