diff --git a/lib/include/srslte/asn1/liblte_mme.h b/lib/include/srslte/asn1/liblte_mme.h index 15799f7ca..e730ec822 100644 --- a/lib/include/srslte/asn1/liblte_mme.h +++ b/lib/include/srslte/asn1/liblte_mme.h @@ -3752,6 +3752,10 @@ typedef struct{ uint8 proc_transaction_id; }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT; // Functions +LIBLTE_ERROR_ENUM srslte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + uint8 sec_hdr_type, + uint32 count, + LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, @@ -3782,6 +3786,8 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN LIBLTE_BYTE_MSG_STRUCT *msg); LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp); +LIBLTE_ERROR_ENUM srslte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp); /********************************************************************* Message Name: ESM Status diff --git a/lib/src/asn1/liblte_mme.cc b/lib/src/asn1/liblte_mme.cc index 4447b001f..54c6eb5ba 100644 --- a/lib/src/asn1/liblte_mme.cc +++ b/lib/src/asn1/liblte_mme.cc @@ -7063,7 +7063,6 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT return(err); } - /********************************************************************* Message Name: Identity Response @@ -7101,6 +7100,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_M return(err); } + LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ID_RESPONSE_MSG_STRUCT *id_resp) { @@ -9845,6 +9845,64 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_request_msg(LI return(err); } +/********************************************************************* + Message Name: ESM Information Request + + Description: Sent by the network to the UE to request the UE to + provide ESM information, i.e. protocol configuration + options or APN or both. This function is being added + to support encryption and integrety protection on + ESM information transfer. + + Document Reference: 24.301 v10.2.0 Section 8.3.13 +*********************************************************************/ +LIBLTE_ERROR_ENUM srslte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req, + uint8 sec_hdr_type, + uint32 count, + LIBLTE_BYTE_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(esm_info_req != NULL && + msg != NULL) + { + + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) + { + // Protocol Discriminator and Security Header Type + *msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // MAC will be filled in later + msg_ptr += 4; + + // Sequence Number + *msg_ptr = count & 0xFF; + msg_ptr++; + } + // Protocol Discriminator and EPS Bearer ID + *msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); + msg_ptr++; + + // Procedure Transaction ID + *msg_ptr = esm_info_req->proc_transaction_id; + msg_ptr++; + + // Message Type + *msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST; + msg_ptr++; + + // Fill in the number of bytes used + msg->N_bytes = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} + + /********************************************************************* Message Name: ESM Information Request @@ -9863,6 +9921,7 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INF if(esm_info_req != NULL && msg != NULL) { + // Protocol Discriminator and EPS Bearer ID *msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT); msg_ptr++; @@ -9883,6 +9942,9 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INF return(err); } + + + LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT *esm_info_req) { @@ -9963,6 +10025,62 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN return(err); } +LIBLTE_ERROR_ENUM srslte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + uint8 sec_hdr_type; + + if(msg != NULL && + esm_info_resp != NULL) + { + + // Security Header Type + sec_hdr_type = (msg->msg[0] & 0xF0) >> 4; + if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) + { + msg_ptr++; + }else{ + msg_ptr += 7; + } + // EPS Bearer ID + esm_info_resp->eps_bearer_id = (*msg_ptr >> 4); + msg_ptr++; + + // Procedure Transaction ID + esm_info_resp->proc_transaction_id = *msg_ptr; + msg_ptr++; + + // Skip Message Type + msg_ptr++; + + // Access Point Name + if(LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_access_point_name_ie(&msg_ptr, &esm_info_resp->apn); + esm_info_resp->apn_present = true; + }else{ + esm_info_resp->apn_present = false; + } + + // Protocol Configuration Options + if(LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) + { + msg_ptr++; + liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &esm_info_resp->protocol_cnfg_opts); + esm_info_resp->protocol_cnfg_opts_present = true; + }else{ + esm_info_resp->protocol_cnfg_opts_present = false; + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} + LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg, LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp) { diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3190488d7..7654fe06a 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -89,6 +89,7 @@ public: void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); bool pack_esm_information_request(srslte::byte_buffer_t* reply_msg, srsepc::ue_ctx_t* ue_ctx); + bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx); void print_enb_ctx_info(const enb_ctx_t &enb_ctx); diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 2ca8a8b78..6ad87981c 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -95,6 +95,7 @@ typedef struct{ bool ms_network_cap_present; LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; bool eit; + uint8_t procedure_transaction_id; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e729699f3..745797f50 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -378,7 +378,7 @@ s1ap::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT *ini } //FIXME use this info uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - uint8_t proc_transaction_id = pdn_con_req.proc_transaction_id; //TODO: Transaction ID unused + ue_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; //Save whether ESM information transfer is necessary ue_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; @@ -473,12 +473,17 @@ s1ap::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT return true; //no need for reply. FIXME this should be better structured... break; case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); - return true; //no need for reply. FIXME this should be better structured... + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + handle_nas_attach_complete(nas_msg, reply_msg, ue_ctx); + return true; //no need for reply. FIXME this should be better structured... break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + handle_esm_information_response(nas_msg,reply_msg,ue_ctx); + return true; default: - m_s1ap_log->info("Unhandled NAS message 0x%x\n", msg_type ); + m_s1ap_log->warning("Unhandled NAS message 0x%x\n", msg_type ); + m_s1ap_log->console("Unhandled NAS message 0x%x\n", msg_type ); return false; //FIXME (nas_msg deallocate needs to be called) } @@ -611,15 +616,17 @@ s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *u uint8 eps_bearer_id; uint8 proc_transaction_id; }LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT;*/ - uint8_t sec_hdr_type=3; + esm_info_req.eps_bearer_id=0; + esm_info_req.proc_transaction_id = ue_ctx->procedure_transaction_id; + uint8_t sec_hdr_type=2; ue_ctx->security_ctxt.dl_nas_count++; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_esm_information_request_msg(&esm_info_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type,ue_ctx->security_ctxt.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { - m_s1ap_log->error("Error packing Athentication Reject\n"); - m_s1ap_log->console("Error packing Athentication Reject\n"); + m_s1ap_log->error("Error packing ESM information request\n"); + m_s1ap_log->console("Error packing ESM information request\n"); return false; } @@ -657,6 +664,47 @@ s1ap::pack_esm_information_request(srslte::byte_buffer_t *reply_msg, ue_ctx_t *u return true; } + +bool +s1ap::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, srslte::byte_buffer_t *reply_msg, ue_ctx_t* ue_ctx) +{ + LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; + /* + typedef struct{ + LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn; + LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT protocol_cnfg_opts; + uint8 eps_bearer_id; + uint8 proc_transaction_id; + bool apn_present; + bool protocol_cnfg_opts_present; + }LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT;*/ + //Get NAS authentication response + LIBLTE_ERROR_ENUM err = srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &esm_info_resp); + if(err != LIBLTE_SUCCESS){ + m_s1ap_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); + return false; + } + m_s1ap_log->info("ESM Info: EPS bearer id %d\n",esm_info_resp.eps_bearer_id); + if(esm_info_resp.apn_present) + { + m_s1ap_log->info("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + m_s1ap_log->console("ESM Info: APN %s\n",esm_info_resp.eps_bearer_id); + } + /* + m_pool->deallocate(nas_buffer); + ssize_t n_sent = sctp_send(m_s1mme,reply_msg->msg, reply_msg->N_bytes, &ue_ctx->enb_sri, 0); + if(n_sent == -1) + { + m_s1ap_log->error("Failed to send NAS Attach Request"); + return false; + } + */ + + //FIXME The packging of GTP-C messages is not ready. + //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. + m_mme_gtpc->send_create_session_request(ue_ctx->imsi, ue_ctx->mme_ue_s1ap_id); + return true; +} bool s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) { @@ -692,8 +740,8 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; //Set UE-AMBR - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=4294967295;//2^32-1 - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=4294967295;//FIXME Get UE-AMBR from HSS + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=1000000000;//2^32-1 + in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=1000000000;//FIXME Get UE-AMBR from HSS //Setup eRAB context in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; @@ -721,9 +769,26 @@ s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte: memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); //Set UE security capabilities and k_enb - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[0] = 0; //EEA0 - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 - + for(int i = 0; i<16; i++) + { + if(ue_ctx->ue_network_cap.eea[i] == true) + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported + } + if(ue_ctx->ue_network_cap.eia[i] == true) + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported + } + else + { + in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported + } + // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 + } uint8_t key_enb[32]; liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.dl_nas_count, key_enb); liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index b70b9a61b..9dd1666d1 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -476,7 +476,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.tai_list.N_tais = 1; attach_accept.tai_list.tai[0].mcc = 1; attach_accept.tai_list.tai[0].mnc = 1; - attach_accept.tai_list.tai[0].tac = 1; + attach_accept.tai_list.tai[0].tac = 7; //Make sure all unused options are set to false attach_accept.guti_present=false; @@ -507,10 +507,10 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE act_def_eps_bearer_context_req.eps_qos.mbr_dl_ext = 250; //FIXME check //set apn //act_def_eps_bearer_context_req.apn - std::string apn("internet"); + std::string apn("test123"); act_def_eps_bearer_context_req.apn.apn = apn; //FIXME - act_def_eps_bearer_context_req.proc_transaction_id = 1; //FIXME + act_def_eps_bearer_context_req.proc_transaction_id = ue_ctx->procedure_transaction_id; //FIXME //Make sure unused options are set to false @@ -536,7 +536,7 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE bool br_ext_present; }LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT; */ - uint8_t sec_hdr_type =3; + uint8_t sec_hdr_type =2; ue_ctx->security_ctxt.dl_nas_count++; liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, ue_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);