[AMF/MME] Add size validation for NGAP/S1AP IE fields to prevent crashes (#4087)

- Added explicit size checks for critical IE fields (PLMNIdentity, TAC,
  GTP-TEID, Cell-ID, UE security capability algorithms, etc.) before
  memcpy() operations.
- When size mismatch is detected, log an error and return an Error
  Indication (or Setup Failure) with appropriate protocol cause
  (semantic_error or message_not_compatible_with_receiver_state).
- Introduced s1ap_send_error_indication1(enb_ue_t *enb_ue, ...)
  as a helper for cases where ENB UE context is available directly.
  s1ap_send_error_indication2(mme_ue_t *mme_ue, ...) now delegates
  to the new function, reducing code duplication.
- Replaced ogs_assert() checks with graceful error handling paths
  to avoid abnormal process termination.

This improves robustness against malformed or non-compliant NGAP/S1AP
messages and prevents potential AMF/MME crashes.
This commit is contained in:
Sukchan Lee
2025-09-24 21:20:22 +09:00
parent 3978db2fa6
commit be765fe2b0
4 changed files with 557 additions and 40 deletions

View File

@@ -2944,6 +2944,56 @@ void ngap_handle_path_switch_request(
eUTRAintegrityProtectionAlgorithms =
&UESecurityCapabilities->eUTRAintegrityProtectionAlgorithms;
if (nRencryptionAlgorithms->size != sizeof(nr_ea)) {
ogs_error("Invalid nRencryptionAlgorithms->size = %d (expected %d)",
(int)nRencryptionAlgorithms->size,
(int)sizeof(nr_ea));
r = ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_protocol,
NGAP_CauseProtocol_message_not_compatible_with_receiver_state);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (nRintegrityProtectionAlgorithms->size != sizeof(nr_ia)) {
ogs_error("Invalid nRintegrityProtectionAlgorithms->size = %d "
"(expected %d)",
(int)nRintegrityProtectionAlgorithms->size,
(int)sizeof(nr_ia));
r = ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_protocol,
NGAP_CauseProtocol_message_not_compatible_with_receiver_state);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (eUTRAencryptionAlgorithms->size != sizeof(eutra_ea)) {
ogs_error("Invalid eUTRAencryptionAlgorithms->size = %d (expected %d)",
(int)eUTRAencryptionAlgorithms->size,
(int)sizeof(eutra_ea));
r = ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_protocol,
NGAP_CauseProtocol_message_not_compatible_with_receiver_state);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (eUTRAintegrityProtectionAlgorithms->size != sizeof(eutra_ia)) {
ogs_error("Invalid eUTRAintegrityProtectionAlgorithms->size = %d "
"(expected %d)",
(int)eUTRAintegrityProtectionAlgorithms->size,
(int)sizeof(eutra_ia));
r = ngap_send_error_indication(
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
NGAP_Cause_PR_protocol,
NGAP_CauseProtocol_message_not_compatible_with_receiver_state);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&nr_ea, nRencryptionAlgorithms->buf, sizeof(nr_ea));
nr_ea = be16toh(nr_ea);
nr_ea0 = amf_ue->ue_security_capability.nr_ea0;
@@ -4412,6 +4462,19 @@ void ngap_handle_ran_configuration_update(
&BroadcastPLMNItem->pLMNIdentity;
ogs_assert(pLMNIdentity);
if (pLMNIdentity->size != sizeof(ogs_plmn_id_t)) {
ogs_error("Invalid PLMNIdentity size = %d (expected %d)",
(int)pLMNIdentity->size,
(int)sizeof(ogs_plmn_id_t));
group = NGAP_Cause_PR_protocol;
cause = NGAP_CauseProtocol_semantic_error;
r = ngap_send_ran_configuration_update_failure(
gnb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
pLMNIdentity->buf, sizeof(ogs_plmn_id_t));
ogs_debug(" PLMN_ID[MCC:%d MNC:%d]",

View File

@@ -139,6 +139,19 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
return;
}
if (Global_ENB_ID->pLMNidentity.size != sizeof(enb->plmn_id)) {
ogs_error("Invalid PLMNIdentity size = %d (expected %d)",
(int)Global_ENB_ID->pLMNidentity.size,
(int)sizeof(enb->plmn_id));
group = S1AP_Cause_PR_misc;
cause = S1AP_CauseProtocol_semantic_error;
r = s1ap_send_s1_setup_failure(enb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (!SupportedTAs) {
ogs_error("No SupportedTAs");
group = S1AP_Cause_PR_misc;
@@ -193,6 +206,30 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
break;
}
if (tAC->size != sizeof(uint16_t)) {
ogs_error("Invalid tAC size = %d (expected %d)",
(int)tAC->size, (int)sizeof(uint16_t));
group = S1AP_Cause_PR_misc;
cause = S1AP_CauseProtocol_semantic_error;
r = s1ap_send_s1_setup_failure(enb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (pLMNidentity->size != sizeof(ogs_plmn_id_t)) {
ogs_error("Invalid pLMNidentity size = %d (expected %d)",
(int)pLMNidentity->size, (int)sizeof(ogs_plmn_id_t));
group = S1AP_Cause_PR_misc;
cause = S1AP_CauseProtocol_semantic_error;
r = s1ap_send_s1_setup_failure(enb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac,
tAC->buf, sizeof(uint16_t));
enb->supported_ta_list[enb->num_of_supported_ta_list].tac =
@@ -335,6 +372,31 @@ void s1ap_handle_enb_configuration_update(
break;
}
if (tAC->size != sizeof(uint16_t)) {
ogs_error("Invalid tAC size = %d (expected %d)",
(int)tAC->size, (int)sizeof(uint16_t));
group = S1AP_Cause_PR_misc;
cause = S1AP_CauseProtocol_semantic_error;
r = s1ap_send_s1_setup_failure(enb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (pLMNidentity->size != sizeof(ogs_plmn_id_t)) {
ogs_error("Invalid pLMNidentity size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(ogs_plmn_id_t));
group = S1AP_Cause_PR_misc;
cause = S1AP_CauseProtocol_semantic_error;
r = s1ap_send_s1_setup_failure(enb, group, cause);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb->supported_ta_list[
enb->num_of_supported_ta_list].tac,
tAC->buf, sizeof(uint16_t));
@@ -500,8 +562,30 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
nas_guti.mme_gid = served_gummei->mme_gid[0];
/* size must be 1 */
if (S_TMSI->mMEC.size != 1) {
ogs_error("Invalid S_TMSI->mMEC.size = %d (expected 1)",
(int)S_TMSI->mMEC.size);
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&nas_guti.mme_code, S_TMSI->mMEC.buf, S_TMSI->mMEC.size);
/* size must be 4 */
if (S_TMSI->m_TMSI.size != 4) {
ogs_error("Invalid S_TMSI->m_TMSI.size = %d (expected 4)",
(int)S_TMSI->m_TMSI.size);
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&nas_guti.m_tmsi, S_TMSI->m_TMSI.buf, S_TMSI->m_TMSI.size);
nas_guti.m_tmsi = be32toh(nas_guti.m_tmsi);
@@ -586,18 +670,61 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
}
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.tai.plmn_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(enb_ue->saved.tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.tai.plmn_id));
memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac));
enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.e_cgi.plmn_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
cell_ID = &EUTRAN_CGI->cell_ID;
ogs_assert(cell_ID);
if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) {
ogs_error("Invalid cell_ID->size = %d (expected %d)",
(int)cell_ID->size,
(int)sizeof(enb_ue->saved.e_cgi.cell_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.e_cgi.plmn_id));
memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf,
@@ -745,9 +872,26 @@ void s1ap_handle_uplink_nas_transport(
}
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(tai.plmn_id));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(tai.tac));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&tai.plmn_id, pLMNidentity->buf, sizeof(tai.plmn_id));
memcpy(&tai.tac, tAC->buf, sizeof(tai.tac));
tai.tac = be16toh(tai.tac);
@@ -767,9 +911,27 @@ void s1ap_handle_uplink_nas_transport(
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.e_cgi.plmn_id));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
cell_ID = &EUTRAN_CGI->cell_ID;
ogs_assert(cell_ID);
if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) {
ogs_error("Invalid cell_ID->size = %d (expected %d)",
(int)cell_ID->size,
(int)sizeof(enb_ue->saved.e_cgi.cell_id));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.e_cgi.plmn_id));
memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf,
@@ -777,9 +939,26 @@ void s1ap_handle_uplink_nas_transport(
enb_ue->saved.e_cgi.cell_id = (be32toh(enb_ue->saved.e_cgi.cell_id) >> 4);
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.tai.plmn_id));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(enb_ue->saved.tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.tai.plmn_id));
memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac));
@@ -1042,6 +1221,17 @@ void s1ap_handle_initial_context_setup_response(
return;
}
if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) {
ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)",
(int)e_rab->gTP_TEID.size,
(int)sizeof(bearer->enb_s1u_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
@@ -1576,8 +1766,19 @@ void s1ap_handle_e_rab_setup_response(
return;
}
if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) {
ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)",
(int)e_rab->gTP_TEID.size,
(int)sizeof(bearer->enb_s1u_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
rv = ogs_asn_BIT_STRING_to_ip(
&e_rab->transportLayerAddress, &bearer->enb_s1u_ip);
@@ -2222,6 +2423,17 @@ void s1ap_handle_e_rab_modification_indication(
return;
}
if (e_rab->dL_GTP_TEID.size != sizeof(bearer->enb_s1u_teid)) {
ogs_error("Invalid e_rab->dL_GTP_TEID.size = %d (expected %d)",
(int)e_rab->dL_GTP_TEID.size,
(int)sizeof(bearer->enb_s1u_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->dL_GTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
@@ -2317,7 +2529,47 @@ void s1ap_handle_enb_direct_information_transfer(
switch (RIMRoutingAddress->present) {
case S1AP_RIMRoutingAddress_PR_gERAN_Cell_ID:
geran_cell_id = RIMRoutingAddress->choice.gERAN_Cell_ID;
ogs_assert(geran_cell_id);
if (!geran_cell_id) {
ogs_error("No gERAN_Cell_ID");
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (geran_cell_id->lAI.pLMNidentity.size != sizeof(plmn_id)) {
ogs_error("Invalid geran_cell_id->lAI.pLMNidentity.size = %d "
"(expected %d)",
(int)geran_cell_id->lAI.pLMNidentity.size,
(int)sizeof(plmn_id));
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (geran_cell_id->lAI.lAC.size != sizeof(uint16_t)) {
ogs_error("Invalid geran_cell_id->lAI.lAC.size = %d "
"(expected %d)",
(int)geran_cell_id->lAI.lAC.size,
(int)sizeof(uint16_t));
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (geran_cell_id->cI.size != sizeof(uint16_t)) {
ogs_error("Invalid geran_cell_id->cI.size = %d "
"(expected %d)",
(int)geran_cell_id->cI.size,
(int)sizeof(uint16_t));
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&plmn_id, geran_cell_id->lAI.pLMNidentity.buf, sizeof(plmn_id));
ogs_nas_from_plmn_id(&rai.lai.nas_plmn_id, &plmn_id);
memcpy(&rai.lai.lac, geran_cell_id->lAI.lAC.buf, sizeof(uint16_t));
@@ -2508,9 +2760,26 @@ void s1ap_handle_path_switch_request(
}
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(tai.plmn_id));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(tai.tac));
r = s1ap_send_error_indication(enb, MME_UE_S1AP_ID, ENB_UE_S1AP_ID,
S1AP_Cause_PR_protocol, S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&tai.plmn_id, pLMNidentity->buf, sizeof(tai.plmn_id));
memcpy(&tai.tac, tAC->buf, sizeof(tai.tac));
tai.tac = be16toh(tai.tac);
@@ -2577,18 +2846,61 @@ void s1ap_handle_path_switch_request(
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.tai.plmn_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(enb_ue->saved.tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(enb_ue->saved.tai.tac));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.tai.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.tai.plmn_id));
memcpy(&enb_ue->saved.tai.tac, tAC->buf, sizeof(enb_ue->saved.tai.tac));
enb_ue->saved.tai.tac = be16toh(enb_ue->saved.tai.tac);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(enb_ue->saved.e_cgi.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(enb_ue->saved.e_cgi.plmn_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
cell_ID = &EUTRAN_CGI->cell_ID;
ogs_assert(cell_ID);
if (cell_ID->size != sizeof(enb_ue->saved.e_cgi.cell_id)) {
ogs_error("Invalid cell_ID->size = %d (expected %d)",
(int)cell_ID->size,
(int)sizeof(enb_ue->saved.e_cgi.cell_id));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&enb_ue->saved.e_cgi.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->saved.e_cgi.plmn_id));
memcpy(&enb_ue->saved.e_cgi.cell_id, cell_ID->buf,
@@ -2614,12 +2926,37 @@ void s1ap_handle_path_switch_request(
integrityProtectionAlgorithms =
&UESecurityCapabilities->integrityProtectionAlgorithms;
if (encryptionAlgorithms->size != sizeof(eea)) {
ogs_error("Invalid encryptionAlgorithms->size = %d (expected %d)",
(int)encryptionAlgorithms->size,
(int)sizeof(eea));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&eea, encryptionAlgorithms->buf, sizeof(eea));
eea = be16toh(eea);
eea0 = mme_ue->ue_network_capability.eea0;
mme_ue->ue_network_capability.eea = eea >> 9;
mme_ue->ue_network_capability.eea0 = eea0;
if (integrityProtectionAlgorithms->size != sizeof(eia)) {
ogs_error("Invalid integrityProtectionAlgorithms->size = %d "
"(expected %d)",
(int)integrityProtectionAlgorithms->size,
(int)sizeof(eia));
r = s1ap_send_error_indication1(
enb_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&eia, integrityProtectionAlgorithms->buf, sizeof(eia));
eia = be16toh(eia);
eia0 = mme_ue->ue_network_capability.eia0;
@@ -2670,6 +3007,17 @@ void s1ap_handle_path_switch_request(
return;
}
if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) {
ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)",
(int)e_rab->gTP_TEID.size,
(int)sizeof(bearer->enb_s1u_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = be32toh(bearer->enb_s1u_teid);
@@ -2771,6 +3119,30 @@ void s1ap_handle_enb_configuration_transfer(
ogs_s1ap_ENB_ID_to_uint32(
&targeteNB_ID->global_ENB_ID.eNB_ID, &target_enb_id);
if (sourceeNB_ID->selected_TAI.tAC.size != sizeof(source_tac)) {
ogs_error("Invalid sourceeNB_ID->selected_TAI.tAC.size = %d "
"(expected %d)",
(int)sourceeNB_ID->selected_TAI.tAC.size,
(int)sizeof(source_tac));
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_unknown_targetID);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
if (targeteNB_ID->selected_TAI.tAC.size != sizeof(target_tac)) {
ogs_error("Invalid targeteNB_ID->selected_TAI.tAC.size = %d "
"(expected %d)",
(int)targeteNB_ID->selected_TAI.tAC.size,
(int)sizeof(target_tac));
r = s1ap_send_error_indication(enb, NULL, NULL,
S1AP_Cause_PR_radioNetwork,
S1AP_CauseRadioNetwork_unknown_targetID);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&source_tac, sourceeNB_ID->selected_TAI.tAC.buf,
sizeof(source_tac));
source_tac = be16toh(source_tac);
@@ -3208,6 +3580,17 @@ void s1ap_handle_handover_request_ack(
return;
}
if (e_rab->gTP_TEID.size != sizeof(bearer->enb_s1u_teid)) {
ogs_error("Invalid e_rab->gTP_TEID.size = %d (expected %d)",
(int)e_rab->gTP_TEID.size,
(int)sizeof(bearer->enb_s1u_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->target_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->target_s1u_teid));
bearer->target_s1u_teid = be32toh(bearer->target_s1u_teid);
@@ -3225,8 +3608,17 @@ void s1ap_handle_handover_request_ack(
}
if (e_rab->dL_transportLayerAddress && e_rab->dL_gTP_TEID) {
ogs_assert(e_rab->dL_gTP_TEID->buf);
ogs_assert(e_rab->dL_transportLayerAddress->buf);
if (e_rab->dL_gTP_TEID->size != sizeof(bearer->enb_dl_teid)) {
ogs_error("Invalid e_rab->dL_gTP_TEID.size = %d (expected %d)",
(int)e_rab->dL_gTP_TEID->size,
(int)sizeof(bearer->enb_dl_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_dl_teid, e_rab->dL_gTP_TEID->buf,
sizeof(bearer->enb_dl_teid));
bearer->enb_dl_teid = be32toh(bearer->enb_dl_teid);
@@ -3245,8 +3637,17 @@ void s1ap_handle_handover_request_ack(
}
if (e_rab->uL_TransportLayerAddress && e_rab->uL_GTP_TEID) {
ogs_assert(e_rab->uL_GTP_TEID->buf);
ogs_assert(e_rab->uL_TransportLayerAddress->buf);
if (e_rab->uL_GTP_TEID->size != sizeof(bearer->enb_ul_teid)) {
ogs_error("Invalid e_rab->uL_GTP_TEID.size = %d (expected %d)",
(int)e_rab->uL_GTP_TEID->size,
(int)sizeof(bearer->enb_ul_teid));
r = s1ap_send_error_indication2(mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&bearer->enb_ul_teid, e_rab->uL_GTP_TEID->buf,
sizeof(bearer->enb_ul_teid));
bearer->enb_ul_teid = be32toh(bearer->enb_ul_teid);
@@ -3763,9 +4164,30 @@ void s1ap_handle_handover_notification(
CLEAR_MME_UE_TIMER(mme_ue->t_mobile_reachable);
pLMNidentity = &TAI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(target_ue->saved.tai.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(target_ue->saved.tai.plmn_id));
r = s1ap_send_error_indication2(
mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
tAC = &TAI->tAC;
ogs_assert(tAC && tAC->size == sizeof(uint16_t));
if (tAC->size != sizeof(target_ue->saved.tai.tac)) {
ogs_error("Invalid tAC->size = %d (expected %d)",
(int)tAC->size, (int)sizeof(target_ue->saved.tai.tac));
r = s1ap_send_error_indication2(
mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&target_ue->saved.tai.plmn_id, pLMNidentity->buf,
sizeof(target_ue->saved.tai.plmn_id));
memcpy(&target_ue->saved.tai.tac,
@@ -3773,9 +4195,31 @@ void s1ap_handle_handover_notification(
target_ue->saved.tai.tac = be16toh(target_ue->saved.tai.tac);
pLMNidentity = &EUTRAN_CGI->pLMNidentity;
ogs_assert(pLMNidentity && pLMNidentity->size == sizeof(ogs_plmn_id_t));
if (pLMNidentity->size != sizeof(target_ue->saved.e_cgi.plmn_id)) {
ogs_error("Invalid pLMNidentity->size = %d (expected %d)",
(int)pLMNidentity->size,
(int)sizeof(target_ue->saved.e_cgi.plmn_id));
r = s1ap_send_error_indication2(
mme_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
cell_ID = &EUTRAN_CGI->cell_ID;
ogs_assert(cell_ID);
if (cell_ID->size != sizeof(target_ue->saved.e_cgi.cell_id)) {
ogs_error("Invalid cell_ID->size = %d (expected %d)",
(int)cell_ID->size,
(int)sizeof(target_ue->saved.e_cgi.cell_id));
r = s1ap_send_error_indication1(
target_ue,
S1AP_Cause_PR_protocol,
S1AP_CauseProtocol_semantic_error);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
}
memcpy(&target_ue->saved.e_cgi.plmn_id, pLMNidentity->buf,
sizeof(target_ue->saved.e_cgi.plmn_id));
memcpy(&target_ue->saved.e_cgi.cell_id, cell_ID->buf,

View File

@@ -879,27 +879,16 @@ int s1ap_send_error_indication(
return rv;
}
int s1ap_send_error_indication2(
mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause)
int s1ap_send_error_indication1(
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause)
{
int rv;
mme_enb_t *enb;
enb_ue_t *enb_ue;
S1AP_MME_UE_S1AP_ID_t mme_ue_s1ap_id;
S1AP_ENB_UE_S1AP_ID_t enb_ue_s1ap_id;
if (!mme_ue) {
ogs_error("UE(mme-ue) context has already been removed");
return OGS_NOTFOUND;
}
enb_ue = enb_ue_find_by_id(mme_ue->enb_ue_id);
if (!enb_ue) {
ogs_error("S1 context has already been removed");
return OGS_NOTFOUND;
}
ogs_assert(enb_ue);
enb = mme_enb_find_by_id(enb_ue->enb_id);
if (!enb) {
ogs_error("eNB has already been removed");
@@ -916,6 +905,25 @@ int s1ap_send_error_indication2(
return rv;
}
int s1ap_send_error_indication2(
mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause)
{
enb_ue_t *enb_ue;
if (!mme_ue) {
ogs_error("UE(mme-ue) context has already been removed");
return OGS_NOTFOUND;
}
enb_ue = enb_ue_find_by_id(mme_ue->enb_ue_id);
if (!enb_ue) {
ogs_error("S1 context has already been removed");
return OGS_NOTFOUND;
}
return s1ap_send_error_indication1(enb_ue, group, cause);
}
int s1ap_send_s1_reset_ack(
mme_enb_t *enb,
S1AP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface)

View File

@@ -97,6 +97,8 @@ int s1ap_send_error_indication(
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
S1AP_Cause_PR group, long cause);
int s1ap_send_error_indication1(
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause);
int s1ap_send_error_indication2(
mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause);
int s1ap_send_s1_reset_ack(