diff --git a/cmake_targets/tools/epc.conf.in b/cmake_targets/tools/epc.conf.in index 1bd779549221b3372d02b56b1fab64d6e3ae239b..88864a7aab490b4da80da9a3048738226b347b91 100755 --- a/cmake_targets/tools/epc.conf.in +++ b/cmake_targets/tools/epc.conf.in @@ -61,7 +61,7 @@ MME : # TA (mcc.mnc:tracking area code) DEFAULT = 208.34:0 # max values = 999.999:65535 # maximum of 32 values, comma separated - PLMN = ( + TAI_LIST = ( {MCC="208" ; MNC="95"; TAC = "1"; } # YOUR PLMN CONFIG HERE ); }; @@ -124,8 +124,8 @@ P-GW = }; #WARNING DNS ARE HARDCODED IN openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c:305 - DEFAULT_DNS_1_IPV4_ADDRESS = "192.168.12.100"; # YOUR NETWORK CONFIG HERE - DEFAULT_DNS_2_IPV4_ADDRESS = "192.168.106.12"; # YOUR NETWORK CONFIG HERE + DEFAULT_DNS_IPV4_ADDRESS = "192.168.106.12"; # YOUR NETWORK CONFIG HERE + DEFAULT_DNS_SEC_IPV4_ADDRESS = "192.168.12.100"; # YOUR NETWORK CONFIG HERE }; diff --git a/cmake_targets/tools/epc.local.enb.conf.in b/cmake_targets/tools/epc.local.enb.conf.in index 7d1a5dd4762ed139864a7a2678b53f6bd03100ec..d715cd62b5adf2c413d2a2d9517fc2f2904214c8 100755 --- a/cmake_targets/tools/epc.local.enb.conf.in +++ b/cmake_targets/tools/epc.local.enb.conf.in @@ -61,9 +61,8 @@ MME : # TA (mcc.mnc:tracking area code) DEFAULT = 208.34:0 # max values = 999.999:65535 # maximum of 32 values, comma separated - PLMN = ( - {MCC="208" ; MNC="95"; TAC = "1"; }, # YOUR PLMN CONFIG HERE - {MCC="208" ; MNC="10"; TAC = "1"; } # YOUR PLMN CONFIG HERE + TAI_LIST = ( + {MCC="208" ; MNC="95"; TAC = "1"; } # YOUR PLMN CONFIG HERE ); }; @@ -125,8 +124,8 @@ P-GW = }; #WARNING DNS ARE HARDCODED IN openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c:305 - DEFAULT_DNS_1_IPV4_ADDRESS = "192.168.12.100"; # YOUR NETWORK CONFIG HERE - DEFAULT_DNS_2_IPV4_ADDRESS = "192.168.106.12"; # YOUR NETWORK CONFIG HERE + DEFAULT_DNS_IPV4_ADDRESS = "192.168.106.12"; # YOUR NETWORK CONFIG HERE + DEFAULT_DNS_SEC_IPV4_ADDRESS = "192.168.12.100"; # YOUR NETWORK CONFIG HERE }; diff --git a/openair-cn/COMMON/ip_forward_messages_types.h b/openair-cn/COMMON/ip_forward_messages_types.h index 89ca43d715111066e488231aa2041220cc35c738..40db8d5c388e66457b487024b4b03849f1a1ffc1 100755 --- a/openair-cn/COMMON/ip_forward_messages_types.h +++ b/openair-cn/COMMON/ip_forward_messages_types.h @@ -57,6 +57,7 @@ typedef struct { ebi_t eps_bearer_id; ///< EPS bearer identifier pdn_type_t pdn_type; ///< PDN Type PAA_t paa; ///< PDN Address Allocation + pco_flat_t pco; ///< Protocol configuration options } SGICreateEndpointResp; typedef struct { diff --git a/openair-cn/COMMON/nas_messages_types.h b/openair-cn/COMMON/nas_messages_types.h index 7e5b49f22880505b499cf120b13fc16092b6b752..6c03d25252ced5f6d0a4563cbb8095eed3fae914 100644 --- a/openair-cn/COMMON/nas_messages_types.h +++ b/openair-cn/COMMON/nas_messages_types.h @@ -177,6 +177,7 @@ typedef struct nas_pdn_connectivity_req_s { char imsi[16]; uint8_t imsi_length; network_qos_t qos; + pco_flat_t pco; OctetString apn; OctetString pdn_addr; int pdn_type; @@ -189,6 +190,7 @@ typedef struct nas_pdn_connectivity_rsp_s { int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry unsigned ue_id; // nas ref network_qos_t qos; + pco_flat_t pco; OctetString apn; OctetString pdn_addr; int pdn_type; diff --git a/openair-cn/COMMON/sgw_lite_messages_types.h b/openair-cn/COMMON/sgw_lite_messages_types.h index 178618423b3aeb7bdcbfe2046ae7b3317945ab81..f83015b6bb9fdb6f85391541d40b17215f0e3da1 100644 --- a/openair-cn/COMMON/sgw_lite_messages_types.h +++ b/openair-cn/COMMON/sgw_lite_messages_types.h @@ -55,6 +55,10 @@ /** @struct SgwCreateSessionRequest * @brief Create Session Request * + * Spec 3GPP TS 29.274, Universal Mobile Telecommunications System (UMTS); + * LTE; 3GPP Evolved Packet System (EPS); + * Evolved General Packet Radio Service (GPRS); + * Tunnelling Protocol for Control plane (GTPv2-C); Stage 3 * The Create Session Request will be sent on S11 interface as * part of these procedures: * - E-UTRAN Initial Attach @@ -250,7 +254,8 @@ typedef struct SgwCreateSessionRequest_s { ///< RAU/TAU/HO procedures with SGW change to identify the ///< default bearer of the PDN Connection - // PCO protocol_configuration_options ///< This IE is not applicable to TAU/RAU/Handover. If + pco_flat_t pco; /// PCO protocol_configuration_options + ///< This IE is not applicable to TAU/RAU/Handover. If ///< MME/SGSN receives PCO from UE (during the attach ///< procedures), the MME/SGSN shall forward the PCO IE to ///< SGW. The SGW shall also forward it to PGW. @@ -413,7 +418,9 @@ typedef struct SgwCreateSessionResponse_s { ///< Gn/Gp SGSN to S4-SGSN/MME RAU/TAU procedure to ///< identify the default bearer the PGW selects for the PDN ///< Connection. - // PCO protocol_configuration_options ///< This IE is not applicable for TAU/RAU/Handover. If PGW + + pco_flat_t pco;// PCO protocol_configuration_options + ///< This IE is not applicable for TAU/RAU/Handover. If PGW ///< decides to return PCO to the UE, PGW shall send PCO to ///< SGW. If SGW receives the PCO IE, SGW shall forward it ///< MME/SGSN. diff --git a/openair-cn/MME_APP/mme_app_bearer.c b/openair-cn/MME_APP/mme_app_bearer.c index e28f40b00917850a3c5403f66c2eaef65b2ee34c..fd909b198ef93c77c3aef673c4033f39b6025d41 100644 --- a/openair-cn/MME_APP/mme_app_bearer.c +++ b/openair-cn/MME_APP/mme_app_bearer.c @@ -43,6 +43,7 @@ #include "mme_app_extern.h" #include "mme_app_ue_context.h" #include "mme_app_defs.h" +#include "sgw_lite_ie_defs.h" #include "secu_defs.h" @@ -246,6 +247,13 @@ mme_app_send_s11_create_session_req( } } + if ((ue_context_pP->pending_pdn_connectivity_req_pco.length >= PCO_MIN_LENGTH) && (ue_context_pP->pending_pdn_connectivity_req_pco.length <= PCO_MAX_LENGTH)) { + memcpy(&session_request_p->pco.byte[0], + &ue_context_pP->pending_pdn_connectivity_req_pco.byte[0], + ue_context_pP->pending_pdn_connectivity_req_pco.length); + session_request_p->pco.length = ue_context_pP->pending_pdn_connectivity_req_pco.length; + } + config_read_lock(&mme_config); session_request_p->peer_ip = mme_config.ipv4.sgw_ip_address_for_S11; config_unlock(&mme_config); @@ -321,6 +329,11 @@ mme_app_handle_nas_pdn_connectivity_req( ue_context_p->pending_pdn_connectivity_req_pti = nas_pdn_connectivity_req_pP->pti; ue_context_p->pending_pdn_connectivity_req_ue_id = nas_pdn_connectivity_req_pP->ue_id; + memcpy(&ue_context_p->pending_pdn_connectivity_req_pco.byte[0], + &nas_pdn_connectivity_req_pP->pco.byte[0], + nas_pdn_connectivity_req_pP->pco.length); + ue_context_p->pending_pdn_connectivity_req_pco.length = nas_pdn_connectivity_req_pP->pco.length; + memcpy(&ue_context_p->pending_pdn_connectivity_req_qos, &nas_pdn_connectivity_req_pP->qos, sizeof(network_qos_t)); @@ -759,6 +772,11 @@ mme_app_handle_create_sess_resp( NAS_PDN_CONNECTIVITY_RSP(message_p).ambr.br_dl = ue_context_p->subscribed_ambr.br_dl; + memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).pco.byte[0], + &create_sess_resp_pP->pco.byte[0], + create_sess_resp_pP->pco.length); + NAS_PDN_CONNECTIVITY_RSP(message_p).pco.length = create_sess_resp_pP->pco.length; + MSC_LOG_TX_MESSAGE( MSC_MMEAPP_MME, MSC_NAS_MME, diff --git a/openair-cn/MME_APP/mme_app_ue_context.h b/openair-cn/MME_APP/mme_app_ue_context.h index 6ac65697baa4f28c19a5c43f341555c8cac4cfcb..5c876ed2784175e4e02b8e857b87e64e21b67323 100644 --- a/openair-cn/MME_APP/mme_app_ue_context.h +++ b/openair-cn/MME_APP/mme_app_ue_context.h @@ -177,6 +177,7 @@ typedef struct ue_context_s { int pending_pdn_connectivity_req_pti; unsigned pending_pdn_connectivity_req_ue_id; network_qos_t pending_pdn_connectivity_req_qos; + pco_flat_t pending_pdn_connectivity_req_pco; void *pending_pdn_connectivity_req_proc_data; int pending_pdn_connectivity_req_request_type; diff --git a/openair-cn/NAS/EURECOM-NAS/src/api/mme/mme_api.h b/openair-cn/NAS/EURECOM-NAS/src/api/mme/mme_api.h index dc3a603fcf1b6999ada3cfdb673e980e0bed4e42..4614da420b516fe5c756455dfd5836a1057c8594 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/api/mme/mme_api.h +++ b/openair-cn/NAS/EURECOM-NAS/src/api/mme/mme_api.h @@ -99,6 +99,8 @@ typedef struct mme_api_emm_config_s { */ typedef struct mme_api_esm_config_s { mme_api_feature_t features; /* Supported features */ + uint8_t dns_prim_ipv4[4]; /* Network byte order */ + uint8_t dns_sec_ipv4[4]; /* Network byte order */ } mme_api_esm_config_t; /****************************************************************************/ diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c index cea1945847b547f753746db6385ee84a49b820e3..a0b202142a9851fa95d95c97bc41b4131c259b9e 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c +++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c @@ -160,12 +160,12 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid, GUTI_t *guti, imsi_t *imsi, imei_t *imei, int eea, int eia, int ucs2, int uea, int uia, int gea, int umts_present, int gprs_present, - const OctetString *esm_msg); + const OctetString *esm_msg_pP); /* * Internal data used for attach procedure */ -typedef struct { +typedef struct attach_data_s { unsigned int ueid; /* UE identifier */ #define ATTACH_COUNTER_MAX 5 unsigned int retransmission_count; /* Retransmission counter */ @@ -405,7 +405,7 @@ int emm_proc_attach_request(void *args) ** the MME (GUTI reallocation) ** ** n_eplmns: Number of equivalent PLMNs ** ** eplmns: List of equivalent PLMNs ** - ** esm_msg: Activate default EPS bearer context re- ** + ** esm_msg_pP: Activate default EPS bearer context re- ** ** quest ESM message ** ** Others: None ** ** ** @@ -417,7 +417,7 @@ int emm_proc_attach_request(void *args) int emm_proc_attach_accept(long t3412, long t3402, long t3423, int n_tais, tai_t *tai, GUTI_t *guti, int n_eplmns, plmn_t *eplmn, - const OctetString *esm_msg) + const OctetString *esm_msg_pP) { LOG_FUNC_IN; @@ -495,7 +495,7 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ; esm_sap.is_standalone = FALSE; - esm_sap.recv = esm_msg; + esm_sap.recv = esm_msg_pP; rc = esm_sap_send(&esm_sap); if ( (rc != RETURNerror) && (esm_sap.err == ESM_SAP_SUCCESS) ) { @@ -561,7 +561,7 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, ** ** ** Inputs: emm_cause: EMM cause indicating why the network re- ** ** jected the attach request ** - ** esm_msg: PDN connectivity reject ESM message ** + ** esm_msg_pP: PDN connectivity reject ESM message ** ** Others: None ** ** ** ** Outputs: None ** @@ -569,7 +569,7 @@ int emm_proc_attach_accept(long t3412, long t3402, long t3423, ** Others: _emm_data, _emm_attach_data, T3410 ** ** ** ***************************************************************************/ -int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg) +int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg_pP) { LOG_FUNC_IN; @@ -754,11 +754,11 @@ int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg) /* * Notify ESM that the network rejected connectivity to the PDN */ - if (esm_msg != NULL) { + if (esm_msg_pP != NULL) { esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; esm_sap.is_standalone = FALSE; - esm_sap.recv = esm_msg; + esm_sap.recv = esm_msg_pP; rc = esm_sap_send(&esm_sap); } @@ -1067,7 +1067,7 @@ int emm_proc_attach_set_detach(void) ** the UE is registered to ** ** eea: Supported EPS encryption algorithms ** ** eia: Supported EPS integrity algorithms ** - ** esm_msg: PDN connectivity request ESM message ** + ** esm_msg_pP: PDN connectivity request ESM message ** ** Others: _emm_data ** ** ** ** Outputs: None ** @@ -1086,7 +1086,7 @@ int emm_proc_attach_request( tai_t *tai, int eea, int eia, int ucs2, int uea, int uia, int gea, int umts_present, int gprs_present, - const OctetString *esm_msg) + const OctetString *esm_msg_pP) { LOG_FUNC_IN; @@ -1168,7 +1168,7 @@ int emm_proc_attach_request( rc = emm_proc_attach_request(ueid, type, native_ksi, ksi, native_guti, guti, imsi, imei, tai, eea, eia, ucs2, uea, uia, gea, - umts_present, gprs_present, esm_msg); + umts_present, gprs_present, esm_msg_pP); } LOG_FUNC_RETURN(rc); @@ -1221,7 +1221,7 @@ int emm_proc_attach_request( /* Update the EMM context with the current attach procedure parameters */ rc = _emm_attach_update(*emm_ctx, ueid, type, ksi, guti, imsi, imei, - eea, eia, ucs2, uea, uia, gea, umts_present, gprs_present, esm_msg); + eea, eia, ucs2, uea, uia, gea, umts_present, gprs_present, esm_msg_pP); if (rc != RETURNok) { LOG_TRACE(WARNING, "EMM-PROC - Failed to update EMM context"); @@ -1301,7 +1301,7 @@ int emm_proc_attach_reject(unsigned int ueid, int emm_cause) ** the GUTI sent in the ATTACH ACCEPT message as valid. ** ** ** ** Inputs: ueid: UE lower layer identifier ** - ** esm_msg: Activate default EPS bearer context accept ** + ** esm_msg_pP: Activate default EPS bearer context accept ** ** ESM message ** ** Others: _emm_data ** ** ** @@ -1310,7 +1310,7 @@ int emm_proc_attach_reject(unsigned int ueid, int emm_cause) ** Others: _emm_data, T3450 ** ** ** ***************************************************************************/ -int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg) +int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg_pP) { emm_data_context_t *emm_ctx = NULL; int rc = RETURNerror; @@ -1364,7 +1364,7 @@ int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg) esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_CNF; esm_sap.is_standalone = FALSE; esm_sap.ueid = ueid; - esm_sap.recv = esm_msg; + esm_sap.recv = esm_msg_pP; esm_sap.ctx = emm_ctx; rc = esm_sap_send(&esm_sap); } else { @@ -2384,71 +2384,75 @@ static int _emm_attach_accept(emm_data_context_t *emm_ctx, attach_data_t *data) emm_sap_t emm_sap; int rc; - /* - * Notify EMM-AS SAP that Attach Accept message together with an Activate - * Default EPS Bearer Context Request message has to be sent to the UE - */ + // may be caused by timer not stopped when deleted context + if (emm_ctx) { + /* + * Notify EMM-AS SAP that Attach Accept message together with an Activate + * Default EPS Bearer Context Request message has to be sent to the UE + */ - emm_sap.primitive = EMMAS_ESTABLISH_CNF; - emm_sap.u.emm_as.u.establish.ueid = emm_ctx->ueid; - - if (emm_ctx->guti_is_new && emm_ctx->old_guti) { - /* Implicit GUTI reallocation; - * include the new assigned GUTI in the Attach Accept message */ - LOG_TRACE(INFO,"EMM-PROC - Implicit GUTI reallocation, include the new assigned GUTI in the Attach Accept message"); - emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->old_guti; - emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; - } else if (emm_ctx->guti_is_new && emm_ctx->guti) { - /* include the new assigned GUTI in the Attach Accept message */ - LOG_TRACE(INFO,"EMM-PROC - Include the new assigned GUTI in the Attach Accept message"); - emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->guti; - emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; - } else { - emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->guti; + emm_sap.primitive = EMMAS_ESTABLISH_CNF; + emm_sap.u.emm_as.u.establish.ueid = emm_ctx->ueid; + + if (emm_ctx->guti_is_new && emm_ctx->old_guti) { + /* Implicit GUTI reallocation; + * include the new assigned GUTI in the Attach Accept message */ + LOG_TRACE(INFO,"EMM-PROC - Implicit GUTI reallocation, include the new assigned GUTI in the Attach Accept message"); + emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->old_guti; + emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; + } else if (emm_ctx->guti_is_new && emm_ctx->guti) { + /* include the new assigned GUTI in the Attach Accept message */ + LOG_TRACE(INFO,"EMM-PROC - Include the new assigned GUTI in the Attach Accept message"); + emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->guti; + emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; + } else { + emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->guti; #warning "TEST LG FORCE GUTI IE IN ATTACH ACCEPT" - emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; - //emm_sap.u.emm_as.u.establish.new_guti = NULL; - } + emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti; + //emm_sap.u.emm_as.u.establish.new_guti = NULL; + } - emm_sap.u.emm_as.u.establish.n_tacs = emm_ctx->n_tacs; - emm_sap.u.emm_as.u.establish.tac = emm_ctx->tac; - emm_sap.u.emm_as.u.establish.NASinfo = EMM_AS_NAS_INFO_ATTACH; - /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_sap.u.emm_as.u.establish.sctx, + emm_sap.u.emm_as.u.establish.n_tacs = emm_ctx->n_tacs; + emm_sap.u.emm_as.u.establish.tac = emm_ctx->tac; + emm_sap.u.emm_as.u.establish.NASinfo = EMM_AS_NAS_INFO_ATTACH; + /* Setup EPS NAS security data */ + emm_as_set_security_data(&emm_sap.u.emm_as.u.establish.sctx, emm_ctx->security, FALSE, TRUE); - LOG_TRACE(INFO,"EMM-PROC - encryption = 0x%X ", emm_sap.u.emm_as.u.establish.encryption); - LOG_TRACE(INFO,"EMM-PROC - integrity = 0x%X ", emm_sap.u.emm_as.u.establish.integrity); - emm_sap.u.emm_as.u.establish.encryption = emm_ctx->security->selected_algorithms.encryption; - emm_sap.u.emm_as.u.establish.integrity = emm_ctx->security->selected_algorithms.integrity; - LOG_TRACE(INFO,"EMM-PROC - encryption = 0x%X (0x%X)", + LOG_TRACE(INFO,"EMM-PROC - encryption = 0x%X ", emm_sap.u.emm_as.u.establish.encryption); + LOG_TRACE(INFO,"EMM-PROC - integrity = 0x%X ", emm_sap.u.emm_as.u.establish.integrity); + emm_sap.u.emm_as.u.establish.encryption = emm_ctx->security->selected_algorithms.encryption; + emm_sap.u.emm_as.u.establish.integrity = emm_ctx->security->selected_algorithms.integrity; + LOG_TRACE(INFO,"EMM-PROC - encryption = 0x%X (0x%X)", emm_sap.u.emm_as.u.establish.encryption, emm_ctx->security->selected_algorithms.encryption); - LOG_TRACE(INFO,"EMM-PROC - integrity = 0x%X (0x%X)", + LOG_TRACE(INFO,"EMM-PROC - integrity = 0x%X (0x%X)", emm_sap.u.emm_as.u.establish.integrity, emm_ctx->security->selected_algorithms.integrity); /* Get the activate default EPS bearer context request message to * transfer within the ESM container of the attach accept message */ - emm_sap.u.emm_as.u.establish.NASmsg = data->esm_msg; - LOG_TRACE(INFO,"EMM-PROC - NASmsg src size = %d NASmsg dst size = %d ", + emm_sap.u.emm_as.u.establish.NASmsg = data->esm_msg; + LOG_TRACE(INFO,"EMM-PROC - NASmsg src size = %d NASmsg dst size = %d ", data->esm_msg.length, emm_sap.u.emm_as.u.establish.NASmsg.length); - rc = emm_sap_send(&emm_sap); + rc = emm_sap_send(&emm_sap); - if (rc != RETURNerror) { - if (T3450.id != NAS_TIMER_INACTIVE_ID) { - /* Re-start T3450 timer */ - T3450.id = nas_timer_restart(T3450.id); - } else { - /* Start T3450 timer */ - T3450.id = nas_timer_start(T3450.sec, _emm_attach_t3450_handler, data); - } + if (rc != RETURNerror) { + if (T3450.id != NAS_TIMER_INACTIVE_ID) { + /* Re-start T3450 timer */ + T3450.id = nas_timer_restart(T3450.id); + } else { + /* Start T3450 timer */ + T3450.id = nas_timer_start(T3450.sec, _emm_attach_t3450_handler, data); + } - LOG_TRACE(INFO,"EMM-PROC - Timer T3450 (%d) expires in %ld seconds", + LOG_TRACE(INFO,"EMM-PROC - Timer T3450 (%d) expires in %ld seconds", T3450.id, T3450.sec); + } + } else { + LOG_TRACE(WARNING,"EMM-PROC - emm_ctx NULL"); } - LOG_FUNC_RETURN (rc); } @@ -2601,7 +2605,7 @@ static int _emm_attach_have_changed(const emm_data_context_t *ctx, ** imei: The IMEI provided by the UE ** ** eea: Supported EPS encryption algorithms ** ** eia: Supported EPS integrity algorithms ** - ** esm_msg: ESM message contained with the attach re- ** + ** esm_msg_pP: ESM message contained with the attach re- ** ** quest ** ** Others: None ** ** ** @@ -2615,7 +2619,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid, GUTI_t *guti, imsi_t *imsi, imei_t *imei, int eea, int eia, int ucs2, int uea, int uia, int gea, int umts_present, int gprs_present, - const OctetString *esm_msg) + const OctetString *esm_msg_pP) { int mnc_length; LOG_FUNC_IN; @@ -2743,20 +2747,25 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid, } /* The ESM message contained within the attach request */ - if (esm_msg->length > 0) { - if (ctx->esm_msg.length == 0) { - ctx->esm_msg.value = (uint8_t *)malloc(esm_msg->length); + if (esm_msg_pP->length > 0) { + if (ctx->esm_msg.value != NULL) { + free(ctx->esm_msg.value); + ctx->esm_msg.value = NULL; + ctx->esm_msg.length = 0; } + ctx->esm_msg.value = (uint8_t *)malloc(esm_msg_pP->length); + if (ctx->esm_msg.value != NULL) { - strncpy((char *)ctx->esm_msg.value, - (char *)esm_msg->value, esm_msg->length); + memcpy((char *)ctx->esm_msg.value, + (char *)esm_msg_pP->value, esm_msg_pP->length); + } else { LOG_FUNC_RETURN (RETURNerror); } } - ctx->esm_msg.length = esm_msg->length; + ctx->esm_msg.length = esm_msg_pP->length; /* Attachment indicator */ ctx->is_attached = FALSE; diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h index f1eb78d5173792410a189d10fa25bee8b7d0a667..844aaaa9c7858e4113bef5521763553e95212bcb 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h +++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h @@ -399,7 +399,7 @@ typedef struct emm_data_context_s { * Structure of the EMM data * ------------------------- */ -typedef struct { +typedef struct emm_data_s { /* * MME configuration * ----------------- diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h index ddc98e9b4ccce51df88881a3443dd0f16ee9ada6..e2e0a773f8af9a275e45a4a972c6d51ec894fe34 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h +++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h @@ -58,7 +58,7 @@ Description Defines the EMM primitives available at the EMMAS Service /* * EMMAS-SAP primitives */ -typedef enum { +typedef enum emm_as_primitive_u { _EMMAS_START = 200, _EMMAS_SECURITY_REQ, /* EMM->AS: Security request */ _EMMAS_SECURITY_IND, /* AS->EMM: Security indication */ @@ -80,7 +80,7 @@ typedef enum { } emm_as_primitive_t; /* Data used to setup EPS NAS security */ -typedef struct { +typedef struct emm_as_security_data_s { UInt8_t is_new; /* New security data indicator */ #define EMM_AS_NO_KEY_AVAILABLE 0xff UInt8_t ksi; /* NAS key set identifier */ @@ -98,7 +98,7 @@ typedef struct { * EMMAS primitive for security * ---------------------------- */ -typedef struct { +typedef struct emm_as_security_s { UInt32_t ueid; /* UE lower layer identifier */ const GUTI_t *guti; /* GUTI temporary mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ @@ -144,7 +144,7 @@ typedef struct { * EMMAS primitive for connection establishment * -------------------------------------------- */ -typedef struct { +typedef struct emm_as_EPS_identity_s { const GUTI_t *guti; /* The GUTI, if valid */ const tai_t *tai; /* The last visited registered Tracking * Area Identity, if available */ @@ -152,7 +152,7 @@ typedef struct { const imei_t *imei; /* UE's IMEI for emergency bearer services */ } emm_as_EPS_identity_t; -typedef struct { +typedef struct emm_as_establish_s { UInt32_t ueid; /* UE lower layer identifier */ emm_as_EPS_identity_t UEid; /* UE's EPS mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ @@ -184,7 +184,7 @@ typedef struct { * EMMAS primitive for connection release * -------------------------------------- */ -typedef struct { +typedef struct emm_as_release_s { UInt32_t ueid; /* UE lower layer identifier */ const GUTI_t *guti; /* GUTI temporary mobile identity */ #define EMM_AS_CAUSE_AUTHENTICATION 0x01 /* Authentication failure */ @@ -196,7 +196,7 @@ typedef struct { * EMMAS primitive for data transfer * --------------------------------- */ -typedef struct { +typedef struct emm_as_data_s { UInt32_t ueid; /* UE lower layer identifier */ const GUTI_t *guti; /* GUTI temporary mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ @@ -213,13 +213,13 @@ typedef struct { * EMMAS primitive for paging * -------------------------- */ -typedef struct {} emm_as_page_t; +typedef struct emm_as_page_s {} emm_as_page_t; /* * EMMAS primitive for status indication * ------------------------------------- */ -typedef struct { +typedef struct emm_as_status_s { UInt32_t ueid; /* UE lower layer identifier */ const GUTI_t *guti; /* GUTI temporary mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ @@ -230,7 +230,7 @@ typedef struct { * EMMAS primitive for cell information * ------------------------------------ */ -typedef struct { +typedef struct emm_as_cell_info_s { UInt8_t found; /* Indicates whether a suitable cell is found */ #define EMM_AS_PLMN_LIST_SIZE 6 PLMN_LIST_T(EMM_AS_PLMN_LIST_SIZE) plmnIDs; @@ -245,7 +245,7 @@ typedef struct { * Structure of EMMAS-SAP primitive * -------------------------------- */ -typedef struct { +typedef struct emm_as_s { emm_as_primitive_t primitive; union { emm_as_security_t security; diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c index abb2d3e1ffb9a6594ed49d16fdb97ba0fb151c35..3c9bf936f7b6369e7c006c9b4e41445cf480c0d9 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c +++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c @@ -181,19 +181,26 @@ static int _emm_cn_deregister_ue(const UInt32_t ue_id) static int _emm_cn_pdn_connectivity_res(const emm_cn_pdn_res_t *msg_pP) { - int rc = RETURNok; - struct emm_data_context_s *emm_ctx_p = NULL; - esm_proc_pdn_type_t esm_pdn_type = ESM_PDN_TYPE_IPV4; - esm_proc_data_t *esm_proc_data_p = NULL; - ESM_msg esm_msg; - EpsQualityOfService qos; - OctetString rsp = { 0, NULL}; - int is_standalone = 0; // warning hardcoded - int triggered_by_ue = 1; // warning hardcoded - attach_data_t *data_p = NULL; - int esm_cause = ESM_CAUSE_SUCCESS; - int pid = 0; - unsigned int new_ebi = 0; + int rc = RETURNok; + struct emm_data_context_s *emm_ctx_p = NULL; + esm_proc_pdn_type_t esm_pdn_type = ESM_PDN_TYPE_IPV4; + esm_proc_data_t *esm_proc_data_p = NULL; + ESM_msg esm_msg; + EpsQualityOfService qos; + ProtocolConfigurationOptions pco; + unsigned int pco_in_index = 0; + signed int length_in_pco = 0; + uint16_t pi_or_ci = 0; // protocol identifier or container identifier; + uint8_t length_pi_or_ci = 0; + + OctetString rsp = { 0, NULL}; + int is_standalone = 0; // warning hardcoded + int triggered_by_ue = 1; // warning hardcoded + attach_data_t *data_p = NULL; + int esm_cause = ESM_CAUSE_SUCCESS; + int pid = 0; + unsigned int new_ebi = 0; + LOG_FUNC_IN; emm_ctx_p = emm_data_context_get(&_emm_data, msg_pP->ue_id); @@ -247,7 +254,44 @@ static int _emm_cn_pdn_connectivity_res(const emm_cn_pdn_res_t *msg_pP) qos.bitRatesExt.guarBitRateForUL = 0; qos.bitRatesExt.guarBitRateForDL = 0; + //-------------------------------------------------------------------------- + // PCO processing + //-------------------------------------------------------------------------- + memset(&pco, 0, sizeof(ProtocolConfigurationOptions)); + length_in_pco = msg_pP->pco.byte[1]; + if ((length_in_pco+1+1) != msg_pP->pco.length) { + LOG_TRACE(WARNING, "PCO: mismatch in lengths length_pco+1+1 %u != msg_pP->pco.length %u\n", + length_in_pco+1+1, msg_pP->pco.length); + } + pco.configurationprotol = msg_pP->pco.byte[2] & 0x07; + + for (int i = 0; i < msg_pP->pco.length; i++) { + LOG_TRACE(WARNING, "EMMCN_PDN_CONNECTIVITY_RES.pco.byte[%u] = 0x%x", i, msg_pP->pco.byte[i]); + } + + if ((length_in_pco > 0) && (msg_pP->pco.byte[2] & 0x80)) { + pco_in_index = PCO_MIN_LENGTH; + while (length_in_pco >= 3) { + pi_or_ci = (((uint16_t)msg_pP->pco.byte[pco_in_index]) << 8) | (uint16_t)msg_pP->pco.byte[pco_in_index+1]; + pco_in_index += 2; + length_pi_or_ci = msg_pP->pco.byte[pco_in_index++]; + pco.protocolid[pco.num_protocol_id_or_container_id] = pi_or_ci; + pco.lengthofprotocolid[pco.num_protocol_id_or_container_id] = length_pi_or_ci; + pco.protocolidcontents[pco.num_protocol_id_or_container_id].value = malloc(length_pi_or_ci); + pco.protocolidcontents[pco.num_protocol_id_or_container_id].length = length_pi_or_ci; + memcpy(pco.protocolidcontents[pco.num_protocol_id_or_container_id].value, + &msg_pP->pco.byte[pco_in_index], + length_pi_or_ci); + + LOG_TRACE(WARNING, "PCO: Found pi_or_ci 0x%x length %u content %s\n", + pi_or_ci, length_pi_or_ci, dump_octet_string(&pco.protocolidcontents[pco.num_protocol_id_or_container_id])); + pco.num_protocol_id_or_container_id++; + pco_in_index += length_pi_or_ci; + + length_in_pco = length_in_pco - (length_pi_or_ci + 2 + 1); + } // while (length_in_pco >= 3) { + } // if ((length_in_pco > 0) && (msg_pP->pco.byte[2] & 0x80)) { /*************************************************************************/ /* CODE THAT WAS IN esm_recv.c/esm_recv_pdn_connectivity_request() */ /*************************************************************************/ @@ -294,6 +338,7 @@ static int _emm_cn_pdn_connectivity_res(const emm_cn_pdn_res_t *msg_pP) new_ebi, //msg_pP->ebi, &esm_msg.activate_default_eps_bearer_context_request, &msg_pP->apn, + &pco, esm_pdn_type, &msg_pP->pdn_addr, &qos, diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h index 865bc0e0124234c7a9bdfc6a5c7892a54364911e..139e8f17bb0fe208c6d152346438c65186a0da74 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h +++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h @@ -165,7 +165,7 @@ typedef enum { /* * Structure of EPS Mobility Management primitive */ -typedef struct { +typedef struct emm_sap_s { emm_primitive_t primitive; union { emm_reg_t emm_reg; /* EMMREG-SAP primitives */ diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h index 47185972542e3ab96523b4a258b9a5dccfade6b6..1e5b9cfc2ca37d5dc9a903600721f39821d66270 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esmData.h @@ -96,7 +96,7 @@ typedef enum { #ifdef NAS_MME /* ESM message timer retransmission data */ -typedef struct { +typedef struct esm_ebr_timer_data_s { void *ctx; unsigned int ueid; /* Lower layers UE identifier */ unsigned int ebi; /* EPS bearer identity */ @@ -110,7 +110,7 @@ typedef struct { * EPS bearer context data * ----------------------- */ -typedef struct { +typedef struct esm_ebr_context_s { unsigned char ebi; /* EPS bearer identity */ esm_ebr_state status; /* EPS bearer context status */ #ifdef NAS_UE @@ -125,7 +125,7 @@ typedef struct { #endif } esm_ebr_context_t; -typedef struct { +typedef struct esm_ebr_data_s { unsigned char index; /* Index of the next EPS bearer context * identity to be used */ #define ESM_EBR_DATA_SIZE (ESM_EBI_MAX - ESM_EBI_MIN + 1) @@ -147,7 +147,7 @@ typedef struct { * butes. An EPS bearer corresponds to one Quality of Service policy * applied within the EPC and E-UTRAN. */ -typedef struct { +typedef struct esm_bearer_s { int bid; /* Identifier of the EPS bearer */ unsigned int ebi; /* EPS bearer identity */ network_qos_t qos; /* EPS bearer level QoS parameters */ @@ -161,7 +161,7 @@ typedef struct { * one IPv4 address and/or one IPv6 prefix and a PDN represented by * an Access Point Name (APN). */ -typedef struct { +typedef struct esm_pdn_s { unsigned int pti; /* Identity of the procedure transaction executed * to activate the PDN connection entry */ int is_emergency; /* Emergency bearer services indicator */ @@ -234,7 +234,7 @@ typedef esm_data_context_t esm_data_t; * Structure of the ESM data * ------------------------- */ -typedef struct { +typedef struct esm_data_s { /* * MME configuration * ----------------- diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h index e44379a4df6ec7292c048902e60b668baf9e0dac..8749c8018bc6fae6bd41cab6e281a15cc9a74d11 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/esm_proc.h @@ -49,6 +49,7 @@ Description Defines the EPS Session Management procedures executed at #include "networkDef.h" #include "OctetString.h" #include "emmData.h" +#include "ProtocolConfigurationOptions.h" /****************************************************************************/ /********************* G L O B A L C O N S T A N T S *******************/ @@ -103,6 +104,8 @@ typedef network_qos_t esm_proc_qos_t; /* Traffic Flow Template for packet filtering */ typedef network_tft_t esm_proc_tft_t; +typedef ProtocolConfigurationOptions esm_proc_pco_t; + /* PDN connection and EPS bearer context data */ typedef struct { OctetString apn; @@ -110,6 +113,7 @@ typedef struct { OctetString pdn_addr; esm_proc_qos_t qos; esm_proc_tft_t tft; + esm_proc_pco_t pco; } esm_proc_data_t; /****************************************************************************/ diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c b/openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c index 578f53f75a5f515f7e32e65e764df4620a10ba0a..3dec0a429a6a1292e629cb679d32c69e566e377f 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.c @@ -297,7 +297,7 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear encoded += encode_result; } -#if 1 /* LW: force Protocol Configuration Options to be included in the ESM message */ +#if 0 /* LW: force Protocol Configuration Options to be included in the ESM message */ { #define CONFIGURATION_PROTOCOL_PPP 0 diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c index a3f1b719c73dff1c066bda84283e3ac4b1dac596..ab584aa4f30fc3dd8a8553528fc4c4a3a5745085 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_recv.c @@ -735,6 +735,7 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi, unsigned int *new_ebi, void *data) { int esm_cause = ESM_CAUSE_SUCCESS; + uint8_t i; LOG_FUNC_IN; @@ -823,6 +824,13 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi, */ //TODO: rc = esm_proc_information_request(); } + esm_data->pco = msg->protocolconfigurationoptions; + for (i = 0; i < msg->protocolconfigurationoptions.num_protocol_id_or_container_id; i++) { + DUP_OCTET_STRING(msg->protocolconfigurationoptions.protocolidcontents[i], esm_data->pco.protocolidcontents[i]); + esm_data->pco.protocolid[i] = msg->protocolconfigurationoptions.protocolid[i]; + esm_data->pco.lengthofprotocolid[i] = msg->protocolconfigurationoptions.lengthofprotocolid[i]; + } + #if defined(ORIGINAL_CODE) /* Execute the PDN connectivity procedure requested by the UE */ diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h index e77cf15da76013b90c649d188d55e85ba65ee5c6..46017a96fc77f93096f3845239d33480af8eafe1 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_sapDef.h @@ -59,7 +59,7 @@ Description Defines the ESM Service Access Point that provides EPS * EPS Session Management primitives * --------------------------------- */ -typedef enum { +typedef enum esm_primitive_s { ESM_START = 0, /* Procedures related to EPS bearer contexts (initiated by the network) */ ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ, @@ -107,14 +107,14 @@ typedef enum { * ESM primitive for activate EPS default bearer context procedure * --------------------------------------------------------------- */ -typedef struct { +typedef struct esm_activate_eps_default_bearer_context_s { } esm_activate_eps_default_bearer_context_t; /* * ESM primitive for PDN connectivity procedure * -------------------------------------------- */ -typedef struct { +typedef struct esm_pdn_connectivity_s { int cid; /* PDN connection local identifier */ int is_defined; /* Indicates whether a PDN context has been defined * for the specified APN */ @@ -129,7 +129,7 @@ typedef struct { * ESM primitive for PDN disconnect procedure * ------------------------------------------ */ -typedef struct { +typedef struct esm_pdn_disconnect_s { int cid; /* PDN connection local identifier */ } esm_pdn_disconnect_t; @@ -137,7 +137,7 @@ typedef struct { * ESM primitive for deactivate EPS bearer context procedure * --------------------------------------------------------- */ -typedef struct { +typedef struct esm_eps_bearer_context_deactivate_s { #define ESM_SAP_ALL_EBI 0xff unsigned int ebi; /* EPS bearer identity of the EPS bearer context * to be deactivated */ @@ -154,20 +154,20 @@ typedef union { esm_eps_bearer_context_deactivate_t eps_bearer_context_deactivate; } esm_sap_data_t; -typedef struct { +typedef struct esm_sap_s { esm_primitive_t primitive; /* ESM-SAP primitive to process */ int is_standalone; /* Indicates whether the ESM message handled * within this primitive has to be sent/received * standalone or together within an EMM related * message */ #if defined(NAS_MME) - emm_data_context_t *ctx; /* UE context */ + emm_data_context_t *ctx; /* UE context */ #endif - unsigned int ueid; /* Local UE identifier */ - esm_sap_error_t err; /* ESM-SAP error code */ - const OctetString *recv; /* Encoded ESM message received */ - OctetString send; /* Encoded ESM message to be sent */ - esm_sap_data_t data; /* ESM message data parameters */ + unsigned int ueid; /* Local UE identifier */ + esm_sap_error_t err; /* ESM-SAP error code */ + const OctetString *recv; /* Encoded ESM message received */ + OctetString send; /* Encoded ESM message to be sent */ + esm_sap_data_t data; /* ESM message data parameters */ } esm_sap_t; /****************************************************************************/ diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.c b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.c index c7f58eaf526730429888636b00bf1ad2fff8fe7d..485b3e19e0e3c121a8e245cb0fa1499564809df5 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.c +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.c @@ -555,6 +555,7 @@ int esm_send_activate_default_eps_bearer_context_request(int pti, int ebi, activate_default_eps_bearer_context_request_msg *msg, const OctetString *apn, + const ProtocolConfigurationOptions *pco, int pdn_type, const OctetString *pdn_addr, const EpsQualityOfService *qos, @@ -615,6 +616,12 @@ int esm_send_activate_default_eps_bearer_context_request(int pti, msg->esmcause = esm_cause; } + if (pco != NULL) { + msg->presencemask |= + ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; + msg->protocolconfigurationoptions = *pco; + } + #warning "TEST LG FORCE APN-AMBR" LOG_TRACE(INFO, "ESM-SAP - FORCE APN-AMBR"); msg->presencemask |= diff --git a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.h b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.h index 87abe596d8d2b85810c6d1f91c6272797997903e..552227a2c6a78ff172a1737f7447b1bc4c259672 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.h +++ b/openair-cn/NAS/EURECOM-NAS/src/esm/sap/esm_send.h @@ -159,8 +159,8 @@ int esm_send_pdn_disconnect_reject(int pti, pdn_disconnect_reject_msg *msg, */ int esm_send_activate_default_eps_bearer_context_request(int pti, int ebi, activate_default_eps_bearer_context_request_msg *msg, const OctetString *apn, - int pdn_type, const OctetString *pdn_addr, const EpsQualityOfService *qos, - int esm_cause); + const ProtocolConfigurationOptions *pco, int pdn_type, const OctetString *pdn_addr, + const EpsQualityOfService *qos, int esm_cause); int esm_send_activate_dedicated_eps_bearer_context_request(int pti, int ebi, activate_dedicated_eps_bearer_context_request_msg *msg, int linked_ebi, diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/EsmMessageContainer.c b/openair-cn/NAS/EURECOM-NAS/src/ies/EsmMessageContainer.c index 507a01f2f841b302e650e8e38d717d2b6d9595e0..edb4cef9d89071e971bc36620f6e7974e50599d6 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/ies/EsmMessageContainer.c +++ b/openair-cn/NAS/EURECOM-NAS/src/ies/EsmMessageContainer.c @@ -54,6 +54,7 @@ int decode_esm_message_container(EsmMessageContainer *esmmessagecontainer, uint8 CHECK_LENGTH_DECODER(len - decoded, ielen); + if ((decode_result = decode_octet_string(&esmmessagecontainer->esmmessagecontainercontents, ielen, buffer + decoded, len - decoded)) < 0) { LOG_FUNC_RETURN(decode_result); } else { diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.c b/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.c index ebdafdf66cb6a1269ef02ef66ebb4419e08e2a25..dc17201da0dc79f782253d0769bb404ed6c3c75f 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.c +++ b/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.c @@ -64,16 +64,23 @@ int decode_protocol_configuration_options(ProtocolConfigurationOptions *protocol decoded++; //IES_DECODE_U16(protocolconfigurationoptions->protocolid, *(buffer + decoded)); + protocolconfigurationoptions->num_protocol_id_or_container_id = 0; while ((len - decoded) > 0) { - IES_DECODE_U16(buffer, decoded, protocolconfigurationoptions->protocolid); - DECODE_U8(buffer + decoded, protocolconfigurationoptions->lengthofprotocolid, decoded); - - if ((decode_result = decode_octet_string(&protocolconfigurationoptions->protocolidcontents, - protocolconfigurationoptions->lengthofprotocolid, buffer + decoded, len - decoded)) < 0) { - return decode_result; + IES_DECODE_U16(buffer, decoded, protocolconfigurationoptions->protocolid[protocolconfigurationoptions->num_protocol_id_or_container_id]); + DECODE_U8(buffer + decoded, protocolconfigurationoptions->lengthofprotocolid[protocolconfigurationoptions->num_protocol_id_or_container_id], decoded); + + if (protocolconfigurationoptions->lengthofprotocolid[protocolconfigurationoptions->num_protocol_id_or_container_id] > 0) { + if ((decode_result = decode_octet_string(&protocolconfigurationoptions->protocolidcontents[protocolconfigurationoptions->num_protocol_id_or_container_id], + protocolconfigurationoptions->lengthofprotocolid[protocolconfigurationoptions->num_protocol_id_or_container_id], buffer + decoded, len - decoded)) < 0) { + return decode_result; + } else { + decoded += decode_result; + } } else { - decoded += decode_result; + protocolconfigurationoptions->protocolidcontents[protocolconfigurationoptions->num_protocol_id_or_container_id].length = 0; + protocolconfigurationoptions->protocolidcontents[protocolconfigurationoptions->num_protocol_id_or_container_id].value = NULL; } + protocolconfigurationoptions->num_protocol_id_or_container_id += 1; } #if defined (NAS_DEBUG) @@ -84,6 +91,7 @@ int decode_protocol_configuration_options(ProtocolConfigurationOptions *protocol int encode_protocol_configuration_options(ProtocolConfigurationOptions *protocolconfigurationoptions, uint8_t iei, uint8_t *buffer, uint32_t len) { uint8_t *lenPtr; + uint8_t num_protocol_id_or_container_id = 0; uint32_t encoded = 0; int encode_result; /* Checking IEI and pointer */ @@ -102,21 +110,29 @@ int encode_protocol_configuration_options(ProtocolConfigurationOptions *protocol *(buffer + encoded) = 0x00 | (1 << 7) | (protocolconfigurationoptions->configurationprotol & 0x7); encoded++; - IES_ENCODE_U16(buffer, encoded, protocolconfigurationoptions->protocolid); - *(buffer + encoded) = protocolconfigurationoptions->lengthofprotocolid; - encoded++; - if ((encode_result = encode_octet_string(&protocolconfigurationoptions->protocolidcontents, buffer + encoded, len - encoded)) < 0) - return encode_result; - else - encoded += encode_result; + while (num_protocol_id_or_container_id < protocolconfigurationoptions->num_protocol_id_or_container_id) { + + IES_ENCODE_U16(buffer, encoded, protocolconfigurationoptions->protocolid[num_protocol_id_or_container_id]); + *(buffer + encoded) = protocolconfigurationoptions->lengthofprotocolid[num_protocol_id_or_container_id]; + encoded++; + if ((encode_result = encode_octet_string(&protocolconfigurationoptions->protocolidcontents[num_protocol_id_or_container_id], + buffer + encoded, + len - encoded)) < 0) + return encode_result; + else + encoded += encode_result; + + num_protocol_id_or_container_id += 1; + } *lenPtr = encoded - 1 - ((iei > 0) ? 1 : 0); return encoded; } void dump_protocol_configuration_options_xml(ProtocolConfigurationOptions *protocolconfigurationoptions, uint8_t iei) { + int i; printf("<Protocol Configuration Options>\n"); if (iei > 0) @@ -124,9 +140,13 @@ void dump_protocol_configuration_options_xml(ProtocolConfigurationOptions *proto printf(" <IEI>0x%X</IEI>\n", iei); printf(" <Configuration protol>%u</Configuration protol>\n", protocolconfigurationoptions->configurationprotol); - printf(" <Protocol ID>%u</Protocol ID>\n", protocolconfigurationoptions->protocolid); - printf(" <Length of protocol ID>%u</Length of protocol ID>\n", protocolconfigurationoptions->lengthofprotocolid); - printf("%s",dump_octet_string_xml(&protocolconfigurationoptions->protocolidcontents)); + i = 0; + while (i < protocolconfigurationoptions->num_protocol_id_or_container_id) { + printf(" <Protocol ID>%u</Protocol ID>\n", protocolconfigurationoptions->protocolid[i]); + printf(" <Length of protocol ID>%u</Length of protocol ID>\n", protocolconfigurationoptions->lengthofprotocolid[i]); + printf(" %s",dump_octet_string_xml(&protocolconfigurationoptions->protocolidcontents[i])); + i++; + } printf("</Protocol Configuration Options>\n"); } diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.h b/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.h index f73f4be832a84fba3e077d6505fa8a4644849a70..bd59d2c4accc7c42780d2890593a7a09afd57465 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.h +++ b/openair-cn/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.h @@ -38,6 +38,10 @@ #define PROTOCOL_CONFIGURATION_OPTIONS_MINIMUM_LENGTH 3 #define PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_LENGTH 253 +// arbitrary value, theoricaly can be greater than defined (250/3) +#define PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_PROTOCOL_ID_OR_CONTAINER_ID 16 + + /* 3GPP TS 24.008 Table 10.5.154 * MS to network table */ @@ -58,10 +62,11 @@ typedef enum ProtocolConfigurationOptionsList_ids_tag { */ typedef struct ProtocolConfigurationOptions_tag { - uint8_t configurationprotol:3; - uint16_t protocolid; - uint8_t lengthofprotocolid; - OctetString protocolidcontents; + uint8_t configurationprotol:3; + uint8_t num_protocol_id_or_container_id; + uint16_t protocolid[PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_PROTOCOL_ID_OR_CONTAINER_ID]; + uint8_t lengthofprotocolid[PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_PROTOCOL_ID_OR_CONTAINER_ID]; + OctetString protocolidcontents[PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_PROTOCOL_ID_OR_CONTAINER_ID]; } ProtocolConfigurationOptions; int encode_protocol_configuration_options(ProtocolConfigurationOptions *protocolconfigurationoptions, uint8_t iei, uint8_t *buffer, uint32_t len); diff --git a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.c b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.c index 9b29ab02dd7f717e1c19457295c2871501d2b2cc..fd16e270144e7d9719cc6cd00b49807101d31f38 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.c +++ b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.c @@ -48,7 +48,6 @@ OctetString* dup_octet_string(OctetString *octetstring) memcpy(os_p->value, octetstring->value, octetstring->length); os_p->value[octetstring->length] = '\0'; } - return os_p; } @@ -57,7 +56,6 @@ void free_octet_string(OctetString *octetstring) { if (octetstring) { if (octetstring->value) free(octetstring->value); - octetstring->value = NULL; octetstring->length = 0; free(octetstring); @@ -67,9 +65,17 @@ void free_octet_string(OctetString *octetstring) int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t buflen) { - CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, octetstring->length, buflen); - memcpy((void*)buffer, (void*)octetstring->value, octetstring->length); - return octetstring->length; + if (octetstring != NULL) { + if ((octetstring->value != NULL) && (octetstring->length > 0)) { + CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, octetstring->length, buflen); + memcpy((void*)buffer, (void*)octetstring->value, octetstring->length); + return octetstring->length; + } else { + return 0; + } + } else { + return 0; + } } int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen) @@ -77,11 +83,15 @@ int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buff if (buflen < pdulen) return -1; - octetstring->length = pdulen; - octetstring->value = malloc(sizeof(uint8_t) * (pdulen+1)); - memcpy((void*)octetstring->value, (void*)buffer, pdulen); - octetstring->value[pdulen] = '\0'; - return octetstring->length; + if ((octetstring != NULL) && (buffer!= NULL)) { + octetstring->length = pdulen; + octetstring->value = malloc(sizeof(uint8_t) * (pdulen+1)); + memcpy((void*)octetstring->value, (void*)buffer, pdulen); + octetstring->value[pdulen] = '\0'; + return octetstring->length; + } else { + return -1; + } } char* dump_octet_string_xml( const OctetString * const octetstring) @@ -89,15 +99,19 @@ char* dump_octet_string_xml( const OctetString * const octetstring) int i; int remaining_size = DUMP_OUTPUT_SIZE; int size = 0; - size = snprintf(_dump_output, remaining_size, "<Length>%u</Length>\n\t<values>", octetstring->length); - remaining_size -= size; + int size_print = 0; + + size_print = snprintf(_dump_output, remaining_size, "<Length>%u</Length>\n\t<values>", octetstring->length); + size += size_print; + remaining_size -= size_print; for (i = 0; i < octetstring->length; i++) { - size +=snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]); - remaining_size -= size; + size_print = snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]); + size += size_print; + remaining_size -= size_print; } - size +=snprintf(&_dump_output[size], remaining_size, "</values>\n"); + size_print = snprintf(&_dump_output[size], remaining_size, "</values>\n"); return _dump_output; } @@ -106,10 +120,12 @@ char* dump_octet_string( const OctetString * const octetstring) int i; int remaining_size = DUMP_OUTPUT_SIZE; int size = 0; + int size_print = 0; for (i = 0; i < octetstring->length; i++) { - size +=snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]); - remaining_size -= size; + size_print = snprintf(&_dump_output[size], remaining_size, "0x%x ", octetstring->value[i]); + size += size_print; + remaining_size -= size_print; } return _dump_output; diff --git a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h index c7f564a3b68b0b063d5eaba6a81de5c441b8ffaa..15cd8f6823bec27a52793670e5b3fa6e9710c14d 100644 --- a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h +++ b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h @@ -46,19 +46,19 @@ typedef struct OctetString_tag { } while (0); -#define DUP_OCTET_STRING(oCTETsTRINGoRIG,oCTETsTRINGcOPY) \ - do { \ - if ((oCTETsTRINGoRIG).value == NULL) { \ - (oCTETsTRINGcOPY).length = 0; \ - (oCTETsTRINGcOPY).value = NULL; \ - break; \ - } \ - (oCTETsTRINGcOPY).length = strlen((const char*)(oCTETsTRINGoRIG).value);\ - assert((oCTETsTRINGoRIG).length == (oCTETsTRINGcOPY).length); \ - (oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length); \ - memcpy((oCTETsTRINGcOPY).value, \ - (oCTETsTRINGoRIG).value, \ - (oCTETsTRINGoRIG).length); \ +#define DUP_OCTET_STRING(oCTETsTRINGoRIG,oCTETsTRINGcOPY) \ + do { \ + if ((oCTETsTRINGoRIG).value == NULL) { \ + (oCTETsTRINGcOPY).length = 0; \ + (oCTETsTRINGcOPY).value = NULL; \ + break; \ + } \ + (oCTETsTRINGcOPY).length = (oCTETsTRINGoRIG).length; \ + (oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length+1); \ + (oCTETsTRINGcOPY).value[(oCTETsTRINGoRIG).length] = '\0'; \ + memcpy((oCTETsTRINGcOPY).value, \ + (oCTETsTRINGoRIG).value, \ + (oCTETsTRINGoRIG).length); \ } while (0); OctetString* dup_octet_string(OctetString*octetstring); diff --git a/openair-cn/NAS/nas_itti_messaging.h b/openair-cn/NAS/nas_itti_messaging.h index b9d422a6134afe9e5e02a7f35c3b9a383e51b306..522b88e5e69068df4cf31f42911d1a6f8dd8268e 100644 --- a/openair-cn/NAS/nas_itti_messaging.h +++ b/openair-cn/NAS/nas_itti_messaging.h @@ -68,6 +68,8 @@ static inline void nas_itti_pdn_connectivity_req( esm_proc_pdn_request_t request_typeP) { MessageDef *message_p = NULL; + uint8_t i; + uint8_t index; AssertFatal(imsi_pP != NULL, "imsi_pP param is NULL"); AssertFatal(proc_data_pP != NULL, "proc_data_pP param is NULL"); @@ -125,6 +127,30 @@ static inline void nas_itti_pdn_connectivity_req( NAS_PDN_CONNECTIVITY_REQ(message_p).request_type = request_typeP; + if (proc_data_pP->pco.num_protocol_id_or_container_id <= PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_PROTOCOL_ID_OR_CONTAINER_ID) { + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[0] = ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_PROTOCOL_CONFIGURATION_OPTIONS_IEI; + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[1] = 1 + 3 * proc_data_pP->pco.num_protocol_id_or_container_id; + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[2] = 0x80; // do it fast + i = 0; + index = 3; + while (( i < proc_data_pP->pco.num_protocol_id_or_container_id) && + ((index + proc_data_pP->pco.protocolidcontents[i].length) <= PROTOCOL_CONFIGURATION_OPTIONS_MAXIMUM_LENGTH)){ + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[1] += proc_data_pP->pco.lengthofprotocolid[i]; + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[index++] = (proc_data_pP->pco.protocolid[i] >> 8); + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[index++] = (proc_data_pP->pco.protocolid[i] & 0x00FF); + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[index++] = proc_data_pP->pco.lengthofprotocolid[i]; + if (proc_data_pP->pco.lengthofprotocolid[i] > 0) { + memcpy( &NAS_PDN_CONNECTIVITY_REQ(message_p).pco.byte[index], + proc_data_pP->pco.protocolidcontents[i].value, + proc_data_pP->pco.lengthofprotocolid[i]); + index += proc_data_pP->pco.lengthofprotocolid[i]; + } + i++; + } + NAS_PDN_CONNECTIVITY_REQ(message_p).pco.length = index; + } + + MSC_LOG_TX_MESSAGE( MSC_NAS_MME, MSC_MMEAPP_MME, diff --git a/openair-cn/SGW-LITE/sgw_lite_handlers.c b/openair-cn/SGW-LITE/sgw_lite_handlers.c index f26d2c66d0398f8a370e290e625f142a35038677..7e97ac8f60ad21ee6d42d10c49dd045e06eb7aca 100644 --- a/openair-cn/SGW-LITE/sgw_lite_handlers.c +++ b/openair-cn/SGW-LITE/sgw_lite_handlers.c @@ -52,6 +52,7 @@ #include "sgw_lite_handlers.h" #include "sgw_lite_context_manager.h" #include "sgw_lite.h" +#include "sgw_lite_ie_defs.h" #include "pgw_lite_paa.h" #include "spgw_config.h" @@ -243,6 +244,9 @@ sgw_lite_handle_sgi_endpoint_created( MessageDef *message_p = NULL; hashtable_rc_t hash_rc; + + + SPGW_APP_DEBUG("Rx SGI_CREATE_ENDPOINT_RESPONSE,Context: S11 teid %u, SGW S1U teid %u EPS bearer id %u\n", resp_pP->context_teid, resp_pP->sgw_S1u_teid, resp_pP->eps_bearer_id); hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_pP->context_teid, (void**)&new_bearer_ctxt_info_p); @@ -298,6 +302,11 @@ sgw_lite_handle_sgi_endpoint_created( memcpy(&create_session_response_p->paa, &resp_pP->paa, sizeof(PAA_t)); + + memcpy(&create_session_response_p->pco, + &resp_pP->pco, + sizeof(pco_flat_t)); + /* Set the Cause information from bearer context created. * "Request accepted" is returned when the GTPv2 entity has accepted a control plane request. */ @@ -357,6 +366,33 @@ sgw_lite_handle_gtpv1uCreateTunnelResp( hashtable_rc_t hash_rc; struct in_addr inaddr ; struct in6_addr in6addr = IN6ADDR_ANY_INIT; + SGICreateEndpointResp sgi_create_endpoint_resp; + + unsigned int pco_in_index = 0; + unsigned int pco_out_index = 0; + signed int length_in_pco = 0; + uint16_t pi_or_ci = 0; // protocol identifier or container identifier; + uint8_t length_pi_or_ci = 0; + uint8_t length_out_pi_or_ci = 0; + + uint16_t ipcp_length = 0; + uint16_t ipcp_out_length = 0; + signed int ipcp_remaining_length = 0; + uint8_t ipcp_option = 0; + uint8_t ipcp_option_length = 0; + uint8_t ipcp_code = 0; + uint8_t ipcp_out_code = IPCP_CODE_CONFIGURE_ACK; + uint8_t ipcp_identifier = 0; + uint32_t ipcp_dns_prim_ipv4_addr = 0xFFFFFFFF; + uint32_t ipcp_dns_sec_ipv4_addr = 0xFFFFFFFF; + uint32_t ipcp_out_dns_prim_ipv4_addr = 0xFFFFFFFF; + uint32_t ipcp_out_dns_sec_ipv4_addr = 0xFFFFFFFF; + pco_flat_t *in_pco_p = NULL; + pco_flat_t out_pco ; + + uint8_t address_allocation_via_nas_signalling = FALSE; + uint8_t address_allocation_via_dhcpv4 = FALSE; + #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; @@ -390,9 +426,173 @@ sgw_lite_handle_gtpv1uCreateTunnelResp( sgw_lite_display_s11_bearer_context_information_mapping(); - SGICreateEndpointResp sgi_create_endpoint_resp; - memset(&sgi_create_endpoint_resp, 0, sizeof(SGICreateEndpointResp)); + + + //-------------------------------------------------------------------------- + // PCO processing + //-------------------------------------------------------------------------- + in_pco_p = &new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.saved_message.pco; + + length_in_pco = in_pco_p->byte[1]; + if ((length_in_pco+1+1) != in_pco_p->length) { + SPGW_APP_DEBUG("PCO: mismatch in lengths length_pco+1+1 %u != in_pco_p->length %u\n", + length_in_pco+1+1, in_pco_p->length); + } + sgi_create_endpoint_resp.pco.byte[0] = in_pco_p->byte[0]; + pco_out_index = 2; + + if ((length_in_pco > 0) && (in_pco_p->byte[2] & 0x80)) { + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = in_pco_p->byte[2]; + + pco_in_index = PCO_MIN_LENGTH; + while (length_in_pco >= 3) { + SPGW_APP_DEBUG("PCO: Protocol identifier in length_in_pco %d\n", length_in_pco); + pi_or_ci = (((uint16_t)in_pco_p->byte[pco_in_index]) << 8) | (uint16_t)in_pco_p->byte[pco_in_index+1]; + pco_in_index += 2; + length_pi_or_ci = in_pco_p->byte[pco_in_index++]; + switch (pi_or_ci) { + case PCO_PI_LCP: + case PCO_PI_PAP: + case PCO_PI_CHAP: + pco_in_index += length_pi_or_ci; + SPGW_APP_WARN("PCO: Protocol identifier 0x%X not supported now\n", pi_or_ci); + break; + + case PCO_PI_IPCP: + ipcp_code = in_pco_p->byte[pco_in_index++]; + ipcp_identifier = in_pco_p->byte[pco_in_index++]; + ipcp_length = (((uint16_t)in_pco_p->byte[pco_in_index]) << 8) | ((uint16_t)in_pco_p->byte[pco_in_index+1]); + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP (0x%x) code 0x%x identifier 0x%x length %u\n", + pi_or_ci, ipcp_code, ipcp_identifier, ipcp_length); + pco_in_index += 2; + ipcp_remaining_length = ipcp_length - 1 - 1 - 2; + ipcp_out_length = 1 + 1 + 2; + + // Protocol Id: Internet Protocol Control Protocol ... + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(pi_or_ci >> 8); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(pi_or_ci & 0x00FF); + + while (ipcp_remaining_length >= 2) { + ipcp_option = in_pco_p->byte[pco_in_index]; + ipcp_option_length = in_pco_p->byte[pco_in_index+1]; + ipcp_remaining_length = ipcp_remaining_length - ipcp_option_length; + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP ipcp_option %u ipcp_option_length %u ipcp_remaining_length %u pco_in_index %u\n", + ipcp_option, ipcp_option_length, ipcp_remaining_length, pco_in_index); + + switch (ipcp_option) { + case IPCP_OPTION_PRIMARY_DNS_SERVER_IP_ADDRESS: + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option PRIMARY_DNS_SERVER_IP_ADDRESS length %u\n", ipcp_option_length); + if (ipcp_option_length >= 6) { + ipcp_dns_prim_ipv4_addr = (((uint32_t)in_pco_p->byte[pco_in_index+2]) << 24 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+3]) << 16 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+4]) << 8 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+5]) ); + + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_prim_ipv4_addr 0x%x\n", ipcp_dns_prim_ipv4_addr); + if ((ipcp_dns_prim_ipv4_addr == 0) || + (spgw_config.pgw_config.ipv4.default_dns_v4 != ipcp_dns_prim_ipv4_addr)){ + ipcp_out_code = IPCP_CODE_CONFIGURE_NACK; + ipcp_out_dns_prim_ipv4_addr = spgw_config.pgw_config.ipv4.default_dns_v4; + } else { + ipcp_out_dns_prim_ipv4_addr = ipcp_dns_prim_ipv4_addr; + } + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_prim_ipv4_addr 0x%x\n", ipcp_out_dns_prim_ipv4_addr); + } else { + ipcp_out_code = IPCP_CODE_CONFIGURE_NACK;// not sure + } + ipcp_out_length += 6; + break; + case IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS: + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option SECONDARY_DNS_SERVER_IP_ADDRESS length %u\n", ipcp_option_length); + if (ipcp_option_length >= 6) { + ipcp_dns_sec_ipv4_addr = (((uint32_t)in_pco_p->byte[pco_in_index+2]) << 24 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+3]) << 16 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+4]) << 8 ) | + (((uint32_t)in_pco_p->byte[pco_in_index+5]) ); + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_dns_sec_ipv4_addr 0x%x\n", ipcp_dns_sec_ipv4_addr); + if ((ipcp_dns_prim_ipv4_addr == 0) || + (spgw_config.pgw_config.ipv4.default_dns_sec_v4 != ipcp_dns_sec_ipv4_addr)){ + ipcp_out_code = IPCP_CODE_CONFIGURE_NACK; + ipcp_out_dns_sec_ipv4_addr = spgw_config.pgw_config.ipv4.default_dns_sec_v4; + } else { + ipcp_out_dns_sec_ipv4_addr = ipcp_dns_sec_ipv4_addr; + } + SPGW_APP_DEBUG("PCO: Protocol identifier IPCP option SECONDARY_DNS_SERVER_IP_ADDRESS ipcp_out_dns_sec_ipv4_addr 0x%x\n", ipcp_out_dns_sec_ipv4_addr); + } else { + ipcp_out_code = IPCP_CODE_CONFIGURE_NACK; // not sure + } + ipcp_out_length += 6; + break; + default: + SPGW_APP_WARN("PCO: Protocol identifier IPCP option 0x%04X unknown\n", ipcp_option); + } + pco_in_index += ipcp_option_length; + } + // ... continuing Protocol Id: Internet Protocol Control Protocol + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = ipcp_out_length; // option length + + break; + + case PCO_CI_P_CSCF_IPV6_ADDRESS_REQUEST: + case PCO_CI_DNS_SERVER_IPV6_ADDRESS_REQUEST: + case PCO_CI_MS_SUPPORT_OF_NETWORK_REQUESTED_BEARER_CONTROL_INDICATOR: + case PCO_CI_DSMIPV6_HOME_AGENT_ADDRESS_REQUEST: + case PCO_CI_DSMIPV6_HOME_NETWORK_PREFIX_REQUEST: + case PCO_CI_DSMIPV6_IPV4_HOME_AGENT_ADDRESS_REQUEST: + case PCO_CI_P_CSCF_IPV4_ADDRESS_REQUEST: + case PCO_CI_MSISDN_REQUEST: + case PCO_CI_IFOM_SUPPORT_REQUEST: + pco_in_index += length_pi_or_ci; + SPGW_APP_WARN("PCO: Container identifier 0x%X not supported now\n", pi_or_ci); + break; + + case PCO_CI_DNS_SERVER_IPV4_ADDRESS_REQUEST: + // PPP IP Control Protocol + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = ipcp_out_code; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = ipcp_identifier; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(ipcp_out_length >> 8); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(ipcp_out_length & 0x00FF); + + if (ipcp_out_dns_prim_ipv4_addr != 0xFFFFFFFF) { + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = IPCP_OPTION_PRIMARY_DNS_SERVER_IP_ADDRESS; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = 6; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(ipcp_out_dns_prim_ipv4_addr & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_prim_ipv4_addr >> 8 ) & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_prim_ipv4_addr >> 16 ) & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_prim_ipv4_addr >> 24 ) & 0x000000FF); + } + if (ipcp_out_dns_sec_ipv4_addr != 0xFFFFFFFF) { + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = 6; + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)(ipcp_out_dns_sec_ipv4_addr & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 8 ) & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 16 ) & 0x000000FF); + sgi_create_endpoint_resp.pco.byte[pco_out_index++] = (uint8_t)((ipcp_out_dns_sec_ipv4_addr >> 24 ) & 0x000000FF); + } + break; + + case PCO_CI_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING: + address_allocation_via_nas_signalling = TRUE; + break; + + case PCO_CI_IPV4_ADDRESS_ALLOCATION_VIA_DHCPV4: + address_allocation_via_dhcpv4 = TRUE; + break; + + case PCO_CI_IPV4_LINK_MTU_REQUEST: + SPGW_APP_WARN("PCO: Container identifier IPV4_LINK_MTU_REQUEST TODO\n"); + break; + } + length_in_pco = length_in_pco - (length_pi_or_ci + 2 + 1); + SPGW_APP_DEBUG("PCO: Protocol identifier out length_in_pco %d\n", length_in_pco); + } // while (length_in_pco >= 3) { + } // if ((length_in_pco > 0) && (in_pco_p->byte[2] & 0x80)) { + sgi_create_endpoint_resp.pco.length = pco_out_index; + sgi_create_endpoint_resp.pco.byte[1] = pco_out_index - 2; + //-------------------------------------------------------------------------- + + // IP forward will forward packets to this teid sgi_create_endpoint_resp.context_teid = endpoint_created_pP->context_teid; sgi_create_endpoint_resp.sgw_S1u_teid = endpoint_created_pP->S1u_teid; @@ -418,11 +618,15 @@ sgw_lite_handle_gtpv1uCreateTunnelResp( break; case IPv4: - if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) { - IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_resp.paa.ipv4_address); - } else { - SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4\n"); - } + if (address_allocation_via_nas_signalling == TRUE) { + if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) { + IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_resp.paa.ipv4_address); + } else { + SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4\n"); + } + } /*else { + // TODO + }*/ break; @@ -457,7 +661,7 @@ sgw_lite_handle_gtpv1uCreateTunnelResp( sgi_create_endpoint_resp.status = SGI_STATUS_OK; sgw_lite_handle_sgi_endpoint_created(&sgi_create_endpoint_resp); - } else { + } else { // if (hash_rc == HASH_TABLE_OK) { SPGW_APP_DEBUG("Rx SGW_S1U_ENDPOINT_CREATED, Context: teid %u NOT FOUND\n", endpoint_created_pP->context_teid); message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_CREATE_SESSION_RESPONSE); diff --git a/openair-cn/SGW-LITE/sgw_lite_ie_defs.h b/openair-cn/SGW-LITE/sgw_lite_ie_defs.h index 7e95a583988cc3760edc49337ed1c8e5a0237019..68683272fbcabed97cf0be98c114c3c4f2542923 100644 --- a/openair-cn/SGW-LITE/sgw_lite_ie_defs.h +++ b/openair-cn/SGW-LITE/sgw_lite_ie_defs.h @@ -99,6 +99,66 @@ typedef struct { uint8_t ipv6_prefix_length; } PAA_t; +/* Protocol configuration options from ts124008*/ +#define PCO_MIN_LENGTH 3 +#define PCO_MAX_LENGTH 253 +#define PCO_CONFIGURATION_PROTOCOL_PPP_FOR_USE_WITH_IP_PDP_TYPE_OR_IP_PDN_TYPE 000b + +#define PCO_PI_LCP (0xC021) +#define PCO_PI_PAP (0xC023) +#define PCO_PI_CHAP (0xC223) +#define PCO_PI_IPCP (0x8021) + +#define IPCP_CODE_CONFIGURE_REQUEST (0x01) +#define IPCP_CODE_CONFIGURE_ACK (0x02) +#define IPCP_CODE_CONFIGURE_NACK (0x03) +#define IPCP_CODE_CONFIGURE_REJECT (0x04) +#define IPCP_CODE_TERMINATE_REQUEST (0x05) +#define IPCP_CODE_TERMINATE_ACK (0x06) +#define IPCP_CODE_REJECT (0x07) + +#define IPCP_OPTION_PRIMARY_DNS_SERVER_IP_ADDRESS (0x81) +#define IPCP_OPTION_SECONDARY_DNS_SERVER_IP_ADDRESS (0x83) + +/* CONTAINER IDENTIFIER MS to network direction:*/ +#define PCO_CI_P_CSCF_IPV6_ADDRESS_REQUEST (0x0001) +#define PCO_CI_DNS_SERVER_IPV6_ADDRESS_REQUEST (0x0003) +#define PCO_CI_MS_SUPPORT_OF_NETWORK_REQUESTED_BEARER_CONTROL_INDICATOR (0x0005) +#define PCO_CI_DSMIPV6_HOME_AGENT_ADDRESS_REQUEST (0x0007) +#define PCO_CI_DSMIPV6_HOME_NETWORK_PREFIX_REQUEST (0x0008) +#define PCO_CI_DSMIPV6_IPV4_HOME_AGENT_ADDRESS_REQUEST (0x0009) +#define PCO_CI_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING (0x000A) +#define PCO_CI_IPV4_ADDRESS_ALLOCATION_VIA_DHCPV4 (0x000B) +#define PCO_CI_P_CSCF_IPV4_ADDRESS_REQUEST (0x000C) +#define PCO_CI_DNS_SERVER_IPV4_ADDRESS_REQUEST (0x000D) +#define PCO_CI_MSISDN_REQUEST (0x000E) +#define PCO_CI_IFOM_SUPPORT_REQUEST (0x000F) +#define PCO_CI_IPV4_LINK_MTU_REQUEST (0x0010) + +/* CONTAINER IDENTIFIER Network to MS direction:*/ +#define PCO_CI_P_CSCF_IPV6_ADDRESS (0x0001) +#define PCO_CI_IM_CN_SUBSYSTEM_SIGNALING_FLAG (0x0002) +#define PCO_CI_DNS_SERVER_IPV6_ADDRESS (0x0003) +#define PCO_CI_POLICY_CONTROL_REJECTION_CODE (0x0004) +#define PCO_CI_SELECTED_BEARER_CONTROL_MODE (0x0005) +#define PCO_CI_DSMIPV6_HOME_AGENT_ADDRESS (0x0007) +#define PCO_CI_DSMIPV6_HOME_NETWORK_PREFIX (0x0008) +#define PCO_CI_DSMIPV6_IPV4_HOME_AGENT_ADDRESS (0x0009) +#define PCO_CI_P_CSCF_IPV4_ADDRESS (0x000C) +#define PCO_CI_DNS_SERVER_IPV4_ADDRESS (0x000D) +#define PCO_CI_MSISDN (0x000E) +#define PCO_CI_IFOM_SUPPORT (0x000F) +#define PCO_CI_IPV4_LINK_MTU (0x0010) + +/* Both directions:*/ +#define PCO_CI_IM_CN_SUBSYSTEM_SIGNALING_FLAG (0x0002) + +typedef struct pco_flat_s{ + uint8_t byte[PCO_MAX_LENGTH]; + uint8_t length; +} pco_flat_t; + + #define IMSI(imsi) \ (imsi)->digit[0], \ (imsi)->digit[1], \ diff --git a/openair-cn/SGW-LITE/spgw_config.c b/openair-cn/SGW-LITE/spgw_config.c index b7b1d9725e5508f4ef21a88a30cc0a6859447050..731f775ef8189a45b3f71cb796409d17e24dc1ad 100755 --- a/openair-cn/SGW-LITE/spgw_config.c +++ b/openair-cn/SGW-LITE/spgw_config.c @@ -576,15 +576,19 @@ int spgw_config_init(char* lib_config_file_name_pP, spgw_config_t* config_pP) } if( - config_setting_lookup_string(subsetting, + config_setting_lookup_string(setting_pgw, PGW_CONFIG_STRING_DEFAULT_DNS_IPV4_ADDRESS, (const char **)&pgw_default_dns_ipv4_address) - && config_setting_lookup_string(subsetting, + && config_setting_lookup_string(setting_pgw, PGW_CONFIG_STRING_DEFAULT_DNS_SEC_IPV4_ADDRESS, (const char **)&pgw_default_dns_sec_ipv4_address)) { config_pP->pgw_config.ipv4.pgw_interface_name_for_S5_S8 = strdup(pgw_interface_name_for_S5_S8); IPV4_STR_ADDR_TO_INT_NWBO ( pgw_default_dns_ipv4_address, config_pP->pgw_config.ipv4.default_dns_v4, "BAD IPv4 ADDRESS FORMAT FOR DEFAULT DNS !\n" ) IPV4_STR_ADDR_TO_INT_NWBO ( pgw_default_dns_sec_ipv4_address, config_pP->pgw_config.ipv4.default_dns_sec_v4, "BAD IPv4 ADDRESS FORMAT FOR DEFAULT DNS SEC!\n" ) + SPGW_APP_INFO("Parsing configuration file default primary DNS IPv4 address: %x\n", + config_pP->pgw_config.ipv4.default_dns_v4); + SPGW_APP_INFO("Parsing configuration file default secondary DNS IPv4 address: %x\n", + config_pP->pgw_config.ipv4.default_dns_sec_v4); } else { SPGW_APP_WARN("NO DNS CONFIGURATION FOUND\n"); } diff --git a/openair-cn/UTILS/mme_config.c b/openair-cn/UTILS/mme_config.c index 818880c03a07e2a794f554b6b9bd328c8c244705..15eb3bd8189fbe6a969801648f2b400e890b98b6 100644 --- a/openair-cn/UTILS/mme_config.c +++ b/openair-cn/UTILS/mme_config.c @@ -367,7 +367,7 @@ static int config_parse_file(mme_config_t *mme_config_p) } } - subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_PLMN); + subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_TAI_LIST); if (subsetting != NULL) { num = config_setting_length(subsetting); diff --git a/openair-cn/UTILS/mme_config.h b/openair-cn/UTILS/mme_config.h index 449ad0f4342827e5c6702fc7de6a8c00de4e81bf..36ce25b169bf3a6889bae219c2cfc36c1b770cb2 100644 --- a/openair-cn/UTILS/mme_config.h +++ b/openair-cn/UTILS/mme_config.h @@ -62,7 +62,7 @@ #define MME_CONFIG_STRING_GUMMEI_CONFIG "GUMMEI" #define MME_CONFIG_STRING_MME_CODE "MME_CODE" #define MME_CONFIG_STRING_MME_GID "MME_GID" -#define MME_CONFIG_STRING_PLMN "PLMN" +#define MME_CONFIG_STRING_TAI_LIST "TAI_LIST" #define MME_CONFIG_STRING_MCC "MCC" #define MME_CONFIG_STRING_MNC "MNC" #define MME_CONFIG_STRING_TAC "TAC"