diff --git a/lib/3gpp/3gpp_common.h b/lib/3gpp/3gpp_common.h index 41c0dbe27a..e0c17dcd03 100644 --- a/lib/3gpp/3gpp_common.h +++ b/lib/3gpp/3gpp_common.h @@ -77,7 +77,7 @@ typedef struct _paa_t { #define GTP_PDN_TYPE_IPV6 2 #define GTP_PDN_TYPE_BOTH 3 #define GTP_PDN_TYPE_NON_IP 4 -ED2(c_uint8_t spare:6;, +ED2(c_uint8_t spare:5;, c_uint8_t pdn_type:3;) union { c_uint32_t ipv4_addr;; diff --git a/lib/nas/nas_types.h b/lib/nas/nas_types.h index 55363b3221..5258b708a6 100644 --- a/lib/nas/nas_types.h +++ b/lib/nas/nas_types.h @@ -844,6 +844,7 @@ ED3(c_uint8_t type:4;, * M LV 2-14 */ typedef struct _nas_eps_quality_of_service_t { c_uint8_t length; + c_uint8_t qci; c_uint8_t ul_mbr; c_uint8_t dl_mbr; c_uint8_t ul_gbr; diff --git a/src/mme/emm_build.c b/src/mme/emm_build.c index 4ec62d1a97..3a601fd454 100644 --- a/src/mme/emm_build.c +++ b/src/mme/emm_build.c @@ -7,9 +7,11 @@ #include "nas_security.h" #include "emm_build.h" -status_t emm_build_attach_accept(pkbuf_t **pkbuf, mme_ue_t *ue) +status_t emm_build_attach_accept( + pkbuf_t **emmbuf, mme_ue_t *ue, pkbuf_t *esmbuf) { nas_message_t message; + nas_attach_accept_t *attach_accept = &message.emm.attach_accept; d_assert(ue, return CORE_ERROR, "Null param"); @@ -21,7 +23,10 @@ status_t emm_build_attach_accept(pkbuf_t **pkbuf, mme_ue_t *ue) message.emm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; message.emm.h.message_type = NAS_ATTACH_ACCEPT; - d_assert(nas_security_encode(pkbuf, ue, &message) == CORE_OK && *pkbuf,,); + attach_accept->esm_message_container.data = esmbuf->payload; + attach_accept->esm_message_container.len = esmbuf->len; + + d_assert(nas_security_encode(emmbuf, ue, &message) == CORE_OK && *emmbuf,,); return CORE_OK; } diff --git a/src/mme/emm_build.h b/src/mme/emm_build.h index 89e25c3cd6..106d590fc9 100644 --- a/src/mme/emm_build.h +++ b/src/mme/emm_build.h @@ -7,7 +7,8 @@ extern "C" { #endif /* __cplusplus */ -CORE_DECLARE(status_t) emm_build_attach_accept(pkbuf_t **pkbuf, mme_ue_t *ue); +CORE_DECLARE(status_t) emm_build_attach_accept( + pkbuf_t **emmbuf, mme_ue_t *ue, pkbuf_t *esmbuf); #ifdef __cplusplus } diff --git a/src/mme/emm_handler.c b/src/mme/emm_handler.c index bf7637c08c..19bf62e6cf 100644 --- a/src/mme/emm_handler.c +++ b/src/mme/emm_handler.c @@ -11,6 +11,10 @@ #include "nas_security.h" #include "nas_conv.h" #include "mme_s6a_handler.h" +#include "esm_build.h" +#include "emm_build.h" +#include "s1ap_build.h" +#include "s1ap_path.h" void emm_handle_esm_message_container( mme_ue_t *ue, nas_esm_message_container_t *esm_message_container) @@ -199,5 +203,28 @@ void emm_handle_authentication_response( void emm_handle_lo_create_session(mme_esm_t *esm) { + pkbuf_t *esmbuf = NULL, *emmbuf = NULL, *s1apbuf = NULL; + mme_ue_t *ue = NULL; + mme_enb_t *enb = NULL; + status_t rv; + + d_assert(esm, return, "Null param"); + ue = esm->ue; + d_assert(ue, return, "Null param"); + enb = ue->enb; + d_assert(ue->enb, return, "Null param"); + + rv = esm_build_activate_default_bearer_context(&esmbuf, esm); + d_assert(rv == CORE_OK, return, "esm build error"); + + rv = emm_build_attach_accept(&emmbuf, ue, esmbuf); + d_assert(rv == CORE_OK, return, "emm build error"); + pkbuf_free(esmbuf); + + rv = s1ap_build_initial_context_setup_request(&s1apbuf, esm, emmbuf); + d_assert(rv == CORE_OK, return, "emm build error"); + pkbuf_free(emmbuf); + + d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,,); } diff --git a/src/mme/esm_build.c b/src/mme/esm_build.c index 9b8b134c9c..f8d29c400e 100644 --- a/src/mme/esm_build.c +++ b/src/mme/esm_build.c @@ -34,20 +34,64 @@ status_t esm_build_activate_default_bearer_context( pkbuf_t **pkbuf, mme_esm_t *esm) { nas_message_t message; + nas_activate_default_eps_bearer_context_request_t + *activate_default_eps_bearer_context_request = + &message.esm.activate_default_eps_bearer_context_request; + nas_eps_quality_of_service_t *eps_qos = + &activate_default_eps_bearer_context_request->eps_qos; + nas_access_point_name_t *access_point_name = + &activate_default_eps_bearer_context_request->access_point_name; + nas_pdn_address_t *pdn_address = + &activate_default_eps_bearer_context_request->pdn_address; + nas_apn_aggregate_maximum_bit_rate_t *apn_ambr = + &activate_default_eps_bearer_context_request->apn_ambr; + nas_protocol_configuration_options_t *protocol_configuration_options = + &activate_default_eps_bearer_context_request + ->protocol_configuration_options; + mme_ue_t *ue = NULL; + pdn_t *pdn = NULL; d_assert(esm, return CORE_ERROR, "Null param"); ue = esm->ue; d_assert(ue, return CORE_ERROR, "Null param"); + pdn = esm->pdn; + d_assert(pdn, return CORE_ERROR, "Null param"); memset(&message, 0, sizeof(message)); - message.h.security_header_type = - NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; - message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM; - + message.esm.h.eps_bearer_identity = esm->ebi; message.esm.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_ESM; message.esm.h.procedure_transaction_identity = esm->pti; - message.esm.h.message_type = NAS_ESM_INFORMATION_REQUEST; + message.esm.h.message_type = + NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST; + + eps_qos->length = 5; + eps_qos->qci = pdn->qci; + eps_qos->ul_mbr = 0xff; + eps_qos->dl_mbr = 0xff; + eps_qos->ul_gbr = 0xff; + eps_qos->dl_gbr = 0xff; + + access_point_name->length = strlen(pdn->apn); + strcpy(access_point_name->apn, pdn->apn); + + pdn_address->length = PAA_IPV4_LEN; + memcpy(&pdn_address->paa, &pdn->paa, pdn_address->length); + + activate_default_eps_bearer_context_request->presencemask |= + NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APN_AMBR_PRESENT; + apn_ambr->length = 6; + apn_ambr->dl_apn_ambr_extended2 = 4; + apn_ambr->ul_apn_ambr_extended2 = 4; + + if (esm->pgw_pco_len) + { + activate_default_eps_bearer_context_request->presencemask |= + NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + protocol_configuration_options->length = esm->pgw_pco_len; + memcpy(protocol_configuration_options->buffer, + esm->pgw_pco, protocol_configuration_options->length); + } d_assert(nas_plain_encode(pkbuf, &message) == CORE_OK && *pkbuf,,); diff --git a/src/mme/mme_s11_handler.c b/src/mme/mme_s11_handler.c index a46efd47cb..5e1a33378e 100644 --- a/src/mme/mme_s11_handler.c +++ b/src/mme/mme_s11_handler.c @@ -17,6 +17,7 @@ void mme_s11_handle_create_session_response( gtp_f_teid_t *sgw_s1u_teid = NULL; mme_esm_t *esm = NULL; + pdn_t *pdn = NULL; d_assert(ue, return, "Null param"); d_assert(rsp, return, "Null param"); @@ -26,6 +27,11 @@ void mme_s11_handle_create_session_response( d_error("No GTP TEID"); return; } + if (rsp->pdn_address_allocation.presence == 0) + { + d_error("No PDN Address Allocation"); + return; + } if (rsp->bearer_contexts_created.presence == 0) { d_error("No Bearer"); @@ -45,12 +51,24 @@ void mme_s11_handle_create_session_response( esm = mme_esm_find_by_ebi( ue, rsp->bearer_contexts_created.eps_bearer_id.u8); d_assert(esm, return, "No ESM Context"); + pdn = esm->pdn; + d_assert(pdn, return, "No PDN Context"); /* Receive Control Plane(UL) : SGW-S11 */ sgw_s11_teid = rsp->sender_f_teid_for_control_plane.data; ue->sgw_s11_teid = ntohl(sgw_s11_teid->teid); ue->sgw_s11_addr = sgw_s11_teid->ipv4_addr; + memcpy(&pdn->paa, rsp->pdn_address_allocation.data, + rsp->pdn_address_allocation.len); + + if (rsp->protocol_configuration_options.presence) + { + esm->pgw_pco_len = rsp->protocol_configuration_options.len; + memcpy(esm->pgw_pco, rsp->protocol_configuration_options.data, + esm->pgw_pco_len); + } + /* Receive Data Plane(UL) : SGW-S1U */ sgw_s1u_teid = rsp->bearer_contexts_created.s1_u_enodeb_f_teid.data; esm->sgw_s1u_teid = ntohl(sgw_s1u_teid->teid); diff --git a/src/mme/s1ap_build.c b/src/mme/s1ap_build.c index 765e7f92b5..7e933c03a6 100644 --- a/src/mme/s1ap_build.c +++ b/src/mme/s1ap_build.c @@ -105,7 +105,37 @@ status_t s1ap_build_setup_failure(pkbuf_t **pkbuf, S1ap_Cause_t cause) return CORE_OK; } -status_t s1ap_build_initial_context_setup_request(pkbuf_t **pkbuf) +status_t s1ap_build_initial_context_setup_request( + pkbuf_t **s1apbuf, mme_esm_t *esm, pkbuf_t *emmbuf) { + int encoded; + s1ap_message_t message; + S1ap_DownlinkNASTransport_IEs_t *ies = + &message.s1ap_DownlinkNASTransport_IEs; + S1ap_NAS_PDU_t *nasPdu = &ies->nas_pdu; + mme_ue_t *ue = NULL; + + d_assert(emmbuf, return CORE_ERROR, "Null param"); + d_assert(esm, return CORE_ERROR, "Null param"); + ue = esm->ue; + d_assert(ue, return CORE_ERROR, "Null param"); + + memset(&message, 0, sizeof(s1ap_message_t)); + + ies->mme_ue_s1ap_id = ue->mme_ue_s1ap_id; + ies->eNB_UE_S1AP_ID = ue->enb_ue_s1ap_id; + + nasPdu->size = emmbuf->len; + nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t)); + memcpy(nasPdu->buf, emmbuf->payload, nasPdu->size); + + message.procedureCode = S1ap_ProcedureCode_id_downlinkNASTransport; + message.direction = S1AP_PDU_PR_initiatingMessage; + + encoded = s1ap_encode_pdu(s1apbuf, &message); + s1ap_free_pdu(&message); + + d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,); + return CORE_OK; } diff --git a/src/mme/s1ap_build.h b/src/mme/s1ap_build.h index 1367d57b86..c97ccd4bb5 100644 --- a/src/mme/s1ap_build.h +++ b/src/mme/s1ap_build.h @@ -2,6 +2,7 @@ #define __S1AP_BUILD_H__ #include "s1ap_message.h" +#include "mme_context.h" #ifdef __cplusplus extern "C" { @@ -10,8 +11,8 @@ extern "C" { CORE_DECLARE(status_t) s1ap_build_setup_rsp(pkbuf_t **pkbuf); CORE_DECLARE(status_t) s1ap_build_setup_failure( pkbuf_t **pkbuf, S1ap_Cause_t cause); -CORE_DECLARE(status_t) - s1ap_build_initial_context_setup_request(pkbuf_t **pkbuf); +CORE_DECLARE(status_t) s1ap_build_initial_context_setup_request( + pkbuf_t **s1apbuf, mme_esm_t *esm, pkbuf_t *emmbuf); #ifdef __cplusplus }