mme: handle malformed CreateSessionResponse without aborting

Replace fatal asserts in mme_s11_handle_create_session_response() with
validation and a unified failure path.

- Reject malformed/invalid IEs (Cause, TEID, PAA, AMBR, Bearer QoS)
  instead of aborting the MME process
- Fix Bearer QoS length handling: treat mismatch as invalid IE and fail
  gracefully
- Consolidate error handling via mme_s11_create_session_fail() and goto fail

This prevents remote crashes triggered by malformed GTPv2-C
CreateSessionResponse messages on S11.

Issues: #4284
This commit is contained in:
Sukchan Lee 2026-03-01 19:37:04 +09:00
parent bd5f9b567d
commit fba2cbd29d

View file

@ -173,12 +173,47 @@ void mme_s11_handle_echo_response(
/* Not Implemented */ /* Not Implemented */
} }
static void mme_s11_create_session_fail(
enb_ue_t *enb_ue, mme_ue_t *mme_ue,
int create_action, uint8_t fail_cause,
const char *reason)
{
int r;
ogs_assert(mme_ue);
if (reason)
ogs_error("[%s] CreateSessionResponse failure: %s [Cause:%d]",
mme_ue->imsi_bcd, reason, fail_cause);
else
ogs_error("[%s] CreateSessionResponse failure [Cause:%d]",
mme_ue->imsi_bcd, fail_cause);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
r = nas_eps_send_attach_reject(enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE,
OGS_NAS_ESM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else if (create_action == OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE) {
r = nas_eps_send_tau_reject(enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
if (enb_ue)
mme_send_delete_session_or_mme_ue_context_release(enb_ue, mme_ue);
else
ogs_error("No S1 Context");
}
void mme_s11_handle_create_session_response( void mme_s11_handle_create_session_response(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid, ogs_gtp_xact_t *xact, mme_ue_t *mme_ue_from_teid,
ogs_gtp2_create_session_response_t *rsp) ogs_gtp2_create_session_response_t *rsp)
{ {
int i, r, rv; int i, r, rv;
uint8_t cause_value = OGS_GTP2_CAUSE_UNDEFINED_VALUE; uint8_t fail_cause = OGS_GTP2_CAUSE_REQUEST_REJECTED_REASON_NOT_SPECIFIED;
uint8_t session_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE; uint8_t session_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE;
uint8_t bearer_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE; uint8_t bearer_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE;
ogs_gtp2_f_teid_t *sgw_s11_teid = NULL; ogs_gtp2_f_teid_t *sgw_s11_teid = NULL;
@ -196,6 +231,7 @@ void mme_s11_handle_create_session_response(
ogs_gtp2_ambr_t *ambr = NULL; ogs_gtp2_ambr_t *ambr = NULL;
uint16_t decoded = 0; uint16_t decoded = 0;
int create_action = 0; int create_action = 0;
const char *fail_reason = NULL;
ogs_assert(rsp); ogs_assert(rsp);
@ -206,6 +242,7 @@ void mme_s11_handle_create_session_response(
********************/ ********************/
ogs_assert(xact); ogs_assert(xact);
create_action = xact->create_action; create_action = xact->create_action;
sess = mme_sess_find_by_id(OGS_POINTER_TO_UINT(xact->data)); sess = mme_sess_find_by_id(OGS_POINTER_TO_UINT(xact->data));
if (sess) if (sess)
mme_ue = mme_ue_find_by_id(sess->mme_ue_id); mme_ue = mme_ue_find_by_id(sess->mme_ue_id);
@ -231,63 +268,64 @@ void mme_s11_handle_create_session_response(
ogs_error("MME-UE Context has already been removed"); ogs_error("MME-UE Context has already been removed");
return; return;
} }
source_ue = sgw_ue_find_by_id(mme_ue->sgw_ue_id); source_ue = sgw_ue_find_by_id(mme_ue->sgw_ue_id);
ogs_assert(source_ue); if (!source_ue) {
fail_reason = "No SGW UE Context";
fail_cause = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
goto fail;
}
if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) { if (create_action == OGS_GTP_CREATE_IN_PATH_SWITCH_REQUEST) {
target_ue = sgw_ue_find_by_id(source_ue->target_ue_id); target_ue = sgw_ue_find_by_id(source_ue->target_ue_id);
ogs_assert(target_ue); if (!target_ue) {
fail_reason = "No target SGW UE Context";
fail_cause = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
goto fail;
}
} else { } else {
target_ue = source_ue; target_ue = source_ue;
ogs_assert(target_ue);
} }
/************************ /************************
* Getting Cause Value * Getting Cause Value
************************/ ************************/
if (rsp->cause.presence && rsp->cause.data) { if (rsp->cause.presence == 0) {
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
fail_reason = "Mandatory IE missing";
goto fail;
}
if (rsp->cause.data) {
ogs_gtp2_cause_t *cause = rsp->cause.data; ogs_gtp2_cause_t *cause = rsp->cause.data;
ogs_assert(cause); ogs_assert(cause);
session_cause = cause->value; session_cause = cause->value;
} else {
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
fail_reason = "Invalid Cause IE";
goto fail;
} }
/************************ /************************
* Check MME-UE Context * Check MME-UE Context
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!mme_ue_from_teid) { if (!mme_ue_from_teid) {
ogs_error("[%s] No Context in TEID [Cause:%d]", ogs_error("[%s] No Context in TEID [Cause:%d]",
mme_ue->imsi_bcd, session_cause); mme_ue->imsi_bcd, session_cause);
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; fail_cause = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} fail_reason = "No Context in TEID";
goto fail;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
ogs_error("[%s] Attach reject [Cause:%d]",
mme_ue->imsi_bcd, session_cause);
r = nas_eps_send_attach_reject(enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE,
OGS_NAS_ESM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
if (enb_ue)
mme_send_delete_session_or_mme_ue_context_release(enb_ue, mme_ue);
else
ogs_error("No S1 Context");
return;
} }
/***************************************** /*****************************************
* Check Mandatory/Conditional IE Missing * Check Mandatory/Conditional IE Missing
*****************************************/ *****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
if (rsp->sender_f_teid_for_control_plane.presence == 0) { if (rsp->sender_f_teid_for_control_plane.presence == 0) {
ogs_error("[%s] No S11 TEID [Cause:%d]", ogs_error("[%s] No S11 TEID [Cause:%d]",
mme_ue->imsi_bcd, session_cause); mme_ue->imsi_bcd, session_cause);
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; fail_cause = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
fail_reason = "Conditional IE missing";
goto fail;
} }
switch (create_action) { switch (create_action) {
@ -295,65 +333,40 @@ void mme_s11_handle_create_session_response(
/* No need for PAA or S5C TEID in PathSwitchRequest */ /* No need for PAA or S5C TEID in PathSwitchRequest */
break; break;
case OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE: case OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE:
/* No need for PAA or S5C TEID in 2G->4G mobility, it was already provided by SGSN peer */ /* 2G->4G mobility: PAA/S5C TEID may already exist from SGSN */
break; break;
default: default:
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) { if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) {
ogs_error("[%s] No S5C TEID [Cause:%d]", ogs_error("[%s] No S5C TEID [Cause:%d]",
mme_ue->imsi_bcd, session_cause); mme_ue->imsi_bcd, session_cause);
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; fail_cause = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
fail_reason = "Conditional IE missing";
goto fail;
} }
if (rsp->pdn_address_allocation.presence == 0) { if (rsp->pdn_address_allocation.presence == 0) {
ogs_error("[%s] No PDN Address Allocation [Cause:%d]", ogs_error("[%s] No PDN Address Allocation [Cause:%d]",
mme_ue->imsi_bcd, session_cause); mme_ue->imsi_bcd, session_cause);
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING; fail_cause = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
fail_reason = "Conditional IE missing";
goto fail;
} }
} }
if (rsp->cause.presence == 0) {
ogs_error("[%s] No Cause [VALUE:%d]", mme_ue->imsi_bcd, session_cause);
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (rsp->pdn_address_allocation.presence) { if (rsp->pdn_address_allocation.presence) {
if (rsp->pdn_address_allocation.len < OGS_PAA_IPV4_LEN || if (rsp->pdn_address_allocation.len < OGS_PAA_IPV4_LEN ||
rsp->pdn_address_allocation.len > OGS_PAA_IPV4V6_LEN) { rsp->pdn_address_allocation.len > OGS_PAA_IPV4V6_LEN) {
ogs_error("Invalid PAA IE [Length:%d]", ogs_error("Invalid PAA IE [Length:%d]",
rsp->pdn_address_allocation.len); rsp->pdn_address_allocation.len);
cause_value = OGS_GTP2_CAUSE_INVALID_LENGTH; fail_cause = OGS_GTP2_CAUSE_INVALID_LENGTH;
fail_reason = "Invalid Length";
goto fail;
} }
} }
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) {
ogs_error("[%s] Attach reject [Cause:%d]",
mme_ue->imsi_bcd, session_cause);
r = nas_eps_send_attach_reject(enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE,
OGS_NAS_ESM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else if (create_action == OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE) {
ogs_error("[%s] TAU reject [Cause:%d]",
mme_ue->imsi_bcd, session_cause);
r = nas_eps_send_tau_reject(enb_ue, mme_ue,
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
if (enb_ue)
mme_send_delete_session_or_mme_ue_context_release(enb_ue, mme_ue);
else
ogs_error("No S1 Context");
return;
}
/******************** /********************
* Check Cause Value * Check Cause Value
********************/ ********************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
for (i = 0; i < OGS_BEARER_PER_UE; i++) { for (i = 0; i < OGS_BEARER_PER_UE; i++) {
ogs_gtp2_cause_t *cause = NULL; ogs_gtp2_cause_t *cause = NULL;
@ -361,28 +374,15 @@ void mme_s11_handle_create_session_response(
break; break;
} }
cause = rsp->bearer_contexts_created[i].cause.data; cause = rsp->bearer_contexts_created[i].cause.data;
if (cause == NULL) { ogs_assert(cause);
ogs_error("No Cause Data");
continue;
}
bearer_cause = cause->value; bearer_cause = cause->value;
if (bearer_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { if (bearer_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("[%s] GTP Bearer Cause [VALUE:%d]", ogs_error("[%s] GTP Bearer Cause [VALUE:%d]",
mme_ue->imsi_bcd, bearer_cause); mme_ue->imsi_bcd, bearer_cause);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { fail_cause = bearer_cause;
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); fail_reason = "Bearer Context not accepted";
r = nas_eps_send_attach_reject(enb_ue, mme_ue, goto fail;
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE,
OGS_NAS_ESM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
if (enb_ue)
mme_send_delete_session_or_mme_ue_context_release(
enb_ue, mme_ue);
else
ogs_error("No S1 Context");
return;
} }
} }
@ -393,75 +393,80 @@ void mme_s11_handle_create_session_response(
session_cause != session_cause !=
OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY) { OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY) {
ogs_error("[%s] GTP Cause [VALUE:%d]", mme_ue->imsi_bcd, session_cause); ogs_error("[%s] GTP Cause [VALUE:%d]", mme_ue->imsi_bcd, session_cause);
if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { fail_cause = session_cause;
ogs_error("[%s] Attach reject", mme_ue->imsi_bcd); fail_reason = "Session Cause not accepted";
r = nas_eps_send_attach_reject(enb_ue, mme_ue, goto fail;
OGS_NAS_EMM_CAUSE_NETWORK_FAILURE,
OGS_NAS_ESM_CAUSE_NETWORK_FAILURE);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
if (enb_ue)
mme_send_delete_session_or_mme_ue_context_release(enb_ue, mme_ue);
else
ogs_error("No S1 Context");
return;
} }
/******************** /********************
* Check ALL Context * Check ALL Context
********************/ ********************/
ogs_assert(sess);
session = sess->session; session = sess->session;
ogs_assert(session); if (!session) {
fail_cause = OGS_GTP2_CAUSE_SYSTEM_FAILURE;
ogs_assert(mme_ue); fail_reason = "No Session";
ogs_assert(source_ue); goto fail;
ogs_assert(target_ue); }
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, target_ue->sgw_s11_teid); mme_ue->mme_s11_teid, target_ue->sgw_s11_teid);
for (i = 0; i < OGS_BEARER_PER_UE; i++) { for (i = 0; i < OGS_BEARER_PER_UE; i++) {
if (rsp->bearer_contexts_created[i].presence == 0) { if (rsp->bearer_contexts_created[i].presence == 0)
break; break;
}
if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) { if (rsp->bearer_contexts_created[i].eps_bearer_id.presence == 0) {
ogs_error("No EPS Bearer ID"); ogs_error("No EPS Bearer ID");
break; fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
fail_reason = "Missing EPS Bearer ID";
goto fail;
} }
if (rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.presence == 0) { if (rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.presence == 0) {
ogs_error("No SGW-S1U TEID"); ogs_error("No SGW-S1U TEID");
break; fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
fail_reason = "Missing SGW-S1U TEID";
goto fail;
} }
if (rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence == 0) { if (rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.presence == 0) {
ogs_error("No PGW-S5U TEID"); ogs_error("No PGW-S5U TEID");
break; fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
fail_reason = "Missing PGW-S5U TEID";
goto fail;
} }
/* EPS Bearer ID */ /* EPS Bearer ID */
bearer = mme_bearer_find_by_ue_ebi(mme_ue, bearer = mme_bearer_find_by_ue_ebi(mme_ue,
rsp->bearer_contexts_created[i].eps_bearer_id.u8); rsp->bearer_contexts_created[i].eps_bearer_id.u8);
if (!bearer) { if (!bearer) {
if (enb_ue) ogs_error("[%s] Unknown EPS Bearer ID [%u]",
mme_send_delete_session_or_mme_ue_context_release( mme_ue->imsi_bcd,
enb_ue, mme_ue); rsp->bearer_contexts_created[i].eps_bearer_id.u8);
else fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
ogs_error("No S1 Context"); fail_reason = "Unknown EPS Bearer ID";
return; goto fail;
} }
/* Data Plane(UL) : SGW-S1U */ /* Data Plane(UL) : SGW-S1U */
sgw_s1u_teid = rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.data; sgw_s1u_teid = rsp->bearer_contexts_created[i].s1_u_enodeb_f_teid.data;
ogs_assert(sgw_s1u_teid);
bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid); bearer->sgw_s1u_teid = be32toh(sgw_s1u_teid->teid);
ogs_assert(OGS_OK == if (OGS_OK !=
ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip)); ogs_gtp2_f_teid_to_ip(sgw_s1u_teid, &bearer->sgw_s1u_ip)) {
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
fail_reason = "Invalid SGW-S1U TEID";
goto fail;
}
/* Data Plane(UL) : PGW-S5U */ /* Data Plane(UL) : PGW-S5U */
pgw_s5u_teid = rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data; pgw_s5u_teid = rsp->bearer_contexts_created[i].s5_s8_u_sgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
bearer->pgw_s5u_teid = be32toh(pgw_s5u_teid->teid); bearer->pgw_s5u_teid = be32toh(pgw_s5u_teid->teid);
ogs_assert(OGS_OK == if (OGS_OK !=
ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &bearer->pgw_s5u_ip)); ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &bearer->pgw_s5u_ip)) {
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
fail_reason = "Invalid PGW-S5U TEID";
goto fail;
}
ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d] PGW_S5U_TEID[%d]", ogs_debug(" ENB_S1U_TEID[%d] SGW_S1U_TEID[%d] PGW_S5U_TEID[%d]",
bearer->enb_s1u_teid, bearer->sgw_s1u_teid, bearer->pgw_s5u_teid); bearer->enb_s1u_teid, bearer->sgw_s1u_teid, bearer->pgw_s5u_teid);
@ -471,12 +476,20 @@ void mme_s11_handle_create_session_response(
OGS_FSM_TRAN(&bearer->sm, esm_state_active); OGS_FSM_TRAN(&bearer->sm, esm_state_active);
} }
/* Bearer Level QoS */ /* Bearer QoS */
if (rsp->bearer_contexts_created[0].bearer_level_qos.presence) { if (rsp->bearer_contexts_created[0].bearer_level_qos.presence) {
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos, decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&rsp->bearer_contexts_created[0].bearer_level_qos); &rsp->bearer_contexts_created[0].bearer_level_qos);
ogs_assert(decoded == if (decoded != rsp->bearer_contexts_created[0].bearer_level_qos.len) {
rsp->bearer_contexts_created[0].bearer_level_qos.len); ogs_error("[%s] Invalid Bearer QoS IE length [%u], decoded [%u]",
mme_ue->imsi_bcd,
rsp->bearer_contexts_created[0].bearer_level_qos.len,
decoded);
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
fail_reason = "Invalid Bearer QoS IE length";
goto fail;
}
session->qos.index = bearer_qos.qci; session->qos.index = bearer_qos.qci;
session->qos.arp.priority_level = bearer_qos.priority_level; session->qos.arp.priority_level = bearer_qos.priority_level;
session->qos.arp.pre_emption_capability = session->qos.arp.pre_emption_capability =
@ -487,14 +500,20 @@ void mme_s11_handle_create_session_response(
/* Control Plane(UL) : SGW-S11 */ /* Control Plane(UL) : SGW-S11 */
sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data;
ogs_assert(sgw_s11_teid);
target_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid); target_ue->sgw_s11_teid = be32toh(sgw_s11_teid->teid);
/* Control Plane(UL) : PGW-S5C */ /* Control Plane(UL) : PGW-S5C */
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence) { if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence) {
pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data; pgw_s5c_teid = rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.data;
ogs_assert(pgw_s5c_teid);
sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid); sess->pgw_s5c_teid = be32toh(pgw_s5c_teid->teid);
ogs_assert(OGS_OK == if (OGS_OK !=
ogs_gtp2_f_teid_to_ip(pgw_s5c_teid, &sess->pgw_s5c_ip)); ogs_gtp2_f_teid_to_ip(pgw_s5c_teid, &sess->pgw_s5c_ip)) {
fail_cause = OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
fail_reason = "Invalid S5C TEID";
goto fail;
}
} }
/* PDN Addresss Allocation */ /* PDN Addresss Allocation */
@ -519,7 +538,7 @@ void mme_s11_handle_create_session_response(
#endif #endif
} }
/* ePCO */ /* ePCO/PCO */
if (rsp->extended_protocol_configuration_options.presence) { if (rsp->extended_protocol_configuration_options.presence) {
OGS_TLV_STORE_DATA(&sess->pgw_epco, OGS_TLV_STORE_DATA(&sess->pgw_epco,
&rsp->extended_protocol_configuration_options); &rsp->extended_protocol_configuration_options);
@ -530,23 +549,10 @@ void mme_s11_handle_create_session_response(
&rsp->protocol_configuration_options); &rsp->protocol_configuration_options);
} }
/* Bearer QoS */
if (rsp->bearer_contexts_created[0].bearer_level_qos.presence) {
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
&rsp->bearer_contexts_created[0].bearer_level_qos);
ogs_assert(rsp->bearer_contexts_created[0].bearer_level_qos.len ==
decoded);
session->qos.index = bearer_qos.qci;
session->qos.arp.priority_level = bearer_qos.priority_level;
session->qos.arp.pre_emption_capability =
bearer_qos.pre_emption_capability;
session->qos.arp.pre_emption_vulnerability =
bearer_qos.pre_emption_vulnerability;
}
/* AMBR */ /* AMBR */
if (rsp->aggregate_maximum_bit_rate.presence) { if (rsp->aggregate_maximum_bit_rate.presence) {
ambr = rsp->aggregate_maximum_bit_rate.data; ambr = rsp->aggregate_maximum_bit_rate.data;
ogs_assert(ambr);
session->ambr.downlink = be32toh(ambr->downlink) * 1000; session->ambr.downlink = be32toh(ambr->downlink) * 1000;
session->ambr.uplink = be32toh(ambr->uplink) * 1000; session->ambr.uplink = be32toh(ambr->uplink) * 1000;
} }
@ -564,7 +570,13 @@ void mme_s11_handle_create_session_response(
ogs_expect(r == OGS_OK); ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR); ogs_assert(r != OGS_ERROR);
} else { } else {
ogs_assert(OGS_OK == sgsap_send_location_update_request(mme_ue)); if (OGS_OK != sgsap_send_location_update_request(mme_ue)) {
ogs_error("[%s] sgsap_send_location_update_request() failed",
mme_ue->imsi_bcd);
fail_cause = OGS_GTP2_CAUSE_SYSTEM_FAILURE;
fail_reason = "SGs location update failed";
goto fail;
}
} }
} else if (create_action == OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE) { } else if (create_action == OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE) {
@ -591,6 +603,14 @@ void mme_s11_handle_create_session_response(
ogs_fatal("Invalid Create Session Action[%d]", create_action); ogs_fatal("Invalid Create Session Action[%d]", create_action);
ogs_assert_if_reached(); ogs_assert_if_reached();
} }
return;
fail:
mme_s11_create_session_fail(enb_ue, mme_ue,
create_action, fail_cause, fail_reason);
return;
} }
void mme_s11_handle_modify_bearer_response( void mme_s11_handle_modify_bearer_response(