Changing the way that ECM context is stored to keep uplink teids active when the context is release.

master
Pedro Alvarez 7 years ago
parent be09457ccb
commit be84ee854a

@ -66,7 +66,7 @@ public:
int get_s1_mme();
void delete_enb_ctx(int32_t assoc_id);
void delete_ues_in_enb(uint16_t enb_id);
void release_ues_ecm_ctx_in_enb(uint16_t enb_id);
bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri);
bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri);
@ -81,16 +81,20 @@ public:
enb_ctx_t* find_enb_ctx(uint16_t enb_id);
void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri);
ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id);
void add_new_ue_ctx(const ue_ctx_t &ue_ctx);
ue_ctx_t* find_ue_ctx_from_imsi(uint64_t imsi);
ue_ctx_t* find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id);
void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx);
void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx);
ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi);
ue_ecm_ctx_t* find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id);
bool delete_ue_emm_ctx(uint64_t imsi);
bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id);
void delete_ues_ecm_ctx_in_enb(uint16_t enb_id);
//ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id);
//void add_new_ue_ctx(const ue_ctx_t &ue_ctx);
//void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx);
//void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx);
//ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi);
//ue_ecm_ctx_t* find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id);
//bool delete_ue_emm_ctx(uint64_t imsi);
//bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id);
//void delete_ues_ecm_ctx_in_enb(uint16_t enb_id);
void store_tmp_ue_emm_ctx(const ue_emm_ctx_t &ue_ecm_ctx);
bool get_tmp_ue_emm_ctx(uint32_t mme_ue_s1ap_id, ue_emm_ctx_t* ue_emm_ptr);
@ -122,9 +126,13 @@ private:
std::map<int32_t, uint16_t> m_sctp_to_enb_id;
std::map<uint16_t,std::set<uint32_t> > m_enb_id_to_ue_ids;
std::map<uint64_t, ue_emm_ctx_t*> m_imsi_to_ue_emm_ctx;
std::map<uint32_t, ue_ecm_ctx_t*> m_mme_ue_s1ap_id_to_ue_ecm_ctx;
std::map<int32_t,ue_emm_ctx_t*> m_mme_ue_s1ap_id_to_tmp_ue_emm_ctx;
std::map<uint64_t, ue_ctx_t*> m_imsi_to_ue_ctx;
std::map<uint32_t, ue_ctx_t*> m_mme_ue_s1ap_id_to_ue_ctx;
//std::map<uint64_t, ue_emm_ctx_t*> m_imsi_to_ue_emm_ctx;
//std::map<uint32_t, ue_ecm_ctx_t*> m_mme_ue_s1ap_id_to_ue_ecm_ctx;
//std::map<int32_t,ue_emm_ctx_t*> m_mme_ue_s1ap_id_to_tmp_ue_emm_ctx;
uint32_t m_next_mme_ue_s1ap_id;
uint32_t m_next_m_tmsi;

@ -122,7 +122,7 @@ typedef struct{
LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap;
bool ms_network_cap_present;
LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap;
} eps_security_ctx_t;
} eps_sec_ctx_t;
typedef struct{
enum erab_state state;
@ -135,7 +135,7 @@ typedef struct{
typedef struct{
uint64_t imsi;
LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti;
eps_security_ctx_t security_ctxt;
eps_sec_ctx_t security_ctxt;
uint8_t procedure_transaction_id;
emm_state_t state;
uint32_t mme_ue_s1ap_id;
@ -156,7 +156,9 @@ typedef struct{
typedef struct{
ue_emm_ctx_t emm_ctx;
eps_sec_ctx_t sec_ctx;
ue_ecm_ctx_t ecm_ctx;
erab_ctx_t erabs_ctx[MAX_ERABS_PER_UE];
} ue_ctx_t;
}//namespace
#endif

@ -72,14 +72,14 @@ public:
srslte::byte_buffer_t *reply_buffer,
bool* reply_flag,
struct sctp_sndrcvinfo *enb_sri);
bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag);
bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag);
bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag);
bool handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag);
bool integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu);
bool short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu);
@ -94,7 +94,7 @@ public:
bool pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *ue_ecm_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer);
bool pack_identity_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id);
bool pack_emm_information(ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg);
bool pack_emm_information(ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg);
bool pack_service_reject(srslte::byte_buffer_t *reply_msg, uint8_t emm_cause, uint32_t enb_ue_s1ap_id);
void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req);

@ -214,16 +214,13 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu)
}
//Save create session response info to E-RAB context
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(imsi);
if(emm_ctx == NULL){
m_mme_gtpc_log->error("Could not find UE EMM context\n");
return;
}
ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id);
if(ecm_ctx == NULL){
m_mme_gtpc_log->error("Could not find UE ECM context\n");
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(imsi);
if(ue_ctx == NULL){
m_mme_gtpc_log->error("Could not find UE context\n");
return;
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Save SGW ctrl F-TEID in GTP-C context
std::map<uint64_t,struct gtpc_ctx>::iterator it_g = m_imsi_to_gtpc_ctx.find(imsi);

@ -113,18 +113,17 @@ s1ap::stop()
{
m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id);
m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id);
delete_ues_ecm_ctx_in_enb(enb_it->second->enb_id);
delete enb_it->second;
m_active_enbs.erase(enb_it++);
}
std::map<uint64_t,ue_emm_ctx_t*>::iterator ue_it = m_imsi_to_ue_emm_ctx.begin();
while(ue_it!=m_imsi_to_ue_emm_ctx.end())
std::map<uint64_t,ue_ctx_t*>::iterator ue_it = m_imsi_to_ue_ctx.begin();
while(ue_it!=m_imsi_to_ue_ctx.end())
{
m_s1ap_log->info("Deleting UE EMM context. IMSI: %015lu\n", ue_it->first);
m_s1ap_log->console("Deleting UE EMM context. IMSI: %015lu\n", ue_it->first);
delete ue_it->second;
m_imsi_to_ue_emm_ctx.erase(ue_it++);
m_imsi_to_ue_ctx.erase(ue_it++);
}
//Cleanup message handlers
s1ap_mngmt_proc::cleanup();
@ -336,7 +335,7 @@ s1ap::delete_enb_ctx(int32_t assoc_id)
m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id);
//Delete connected UEs ctx
delete_ues_ecm_ctx_in_enb(enb_id);
release_ues_ecm_ctx_in_enb(enb_id);
//Delete eNB
delete it_ctx->second;
@ -348,20 +347,89 @@ s1ap::delete_enb_ctx(int32_t assoc_id)
//UE Context Management
void
s1ap::add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx)
s1ap::add_new_ue_ctx(const ue_ctx_t &ue_ctx)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator emm_ctx_it = m_imsi_to_ue_emm_ctx.find(ue_emm_ctx.imsi);
if(emm_ctx_it != m_imsi_to_ue_emm_ctx.end())
std::map<uint64_t, ue_ctx_t*>::iterator ctx_it = m_imsi_to_ue_ctx.find(ue_ctx.emm_ctx.imsi);
if(ctx_it != m_imsi_to_ue_ctx.end())
{
m_s1ap_log->warning("EMM Context already exists. Replacing EMM Context\n");
delete emm_ctx_it->second;
m_imsi_to_ue_emm_ctx.erase(emm_ctx_it);
m_s1ap_log->warning("UE Context already exists. Replacing UE Context\n");
delete ctx_it->second;
m_imsi_to_ue_ctx.erase(ctx_it);
}
std::map<uint32_t,uint64_t>::iterator imsi_it = m_mme_ue_s1ap_id_to_imsi.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id);
if(imsi_it != m_mme_ue_s1ap_id_to_imsi.end())
{
m_s1ap_log->warning("MME UE S1AP Id already exists, replacing it.\n");
m_mme_ue_s1ap_id_to_imsi.erase(imsi_it);
}
ue_emm_ctx_t *ue_ptr = new ue_emm_ctx_t;
memcpy(ue_ptr,&ue_emm_ctx,sizeof(ue_emm_ctx));
//This map will store UEs EMM context
m_imsi_to_ue_emm_ctx.insert(std::pair<uint64_t,ue_emm_ctx_t*>(ue_ptr->imsi,ue_ptr));
ue_ctx_t *new_ctx = new ue_ctx_t;
memcpy(new_ctx, &ue_ctx,sizeof(ue_ctx));
//This map will store UEs context
m_imsi_to_ue_ctx.insert(std::pair<uint64_t,ue_ctx_t*>(new_ctx->emm_ctx.imsi,new_ctx));
m_mme_ue_s1ap_id_to_imsi.insert(std::pair<uint32_t,uint64_t>(ue_ctx.ecm_ctx.mme_ue_s1ap_id,ue_ctx.emm_ctx.imsi));
//Store which enb currently holds the UE
std::map<int32_t,uint16_t>::iterator it_enb = m_sctp_to_enb_id.find(new_ctx->ecm_ctx.enb_sri.sinfo_assoc_id);
uint16_t enb_id = it_enb->second;
std::map<uint16_t,std::set<uint32_t> >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id);
if(it_ue_id==m_enb_id_to_ue_ids.end())
{
m_s1ap_log->error("Could not find eNB's UEs\n");
return;
}
it_ue_id->second.insert(new_ctx->ecm_ctx.mme_ue_s1ap_id);
return;
}
bool
s1ap::add_ue_ctx_to_imsi_map(const ue_ctx_t *ue_ctx)
{
std::map<uint64_t, ue_ctx_t*>::iterator ctx_it = m_imsi_to_ue_ctx.find(ue_ctx->emm_ctx.imsi);
if(ctx_it != m_imsi_to_ue_ctx.end())
{
m_s1ap_log->error("UE Context already exists. IMSI %015lu",ue_ctx->emm_ctx.imsi);
return false;
}
if(ue_ctx->ecm_ctx.mme_ue_s1ap_id != 0)
{
std::map<uint32_t,ue_ctx_t*>::iterator ctx_it2 = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id);
if(ctx_it2 != m_mme_ue_s1ap_id_to_imsi.end() && ctx_it2->second != ue_ctx)
{
m_s1ap_log->error("Context identified with IMSI does not match context identified by MME UE S1AP Id.\n");
return false;
}
}
return true;
}
bool
s1ap::add_ue_ctx_to_mme_ue_s1ap_id_map(const ue_ctx_t *ue_ctx)
{
if(ue_ctx->ecm_ctx.mme_ue_s1ap_id == 0)
{
m_s1ap_log->error("Could not add UE context to MME UE S1AP map. MME UE S1AP ID 0 is not valid.")
return false;
}
std::map<uint32_t, ue_ctx_t*>::iterator ctx_it = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx->ecm_ctx.mme_ue_s1ap_id);
if(ctx_it != m_mme_ue_s1ap_id_to_ue_ctx.end())
{
m_s1ap_log->error("UE Context already exists. MME UE S1AP Id %015lu",ue_ctx->emm_ctx.imsi);
return false;
}
if(ue_ctx->ecm_ctx.imsi != 0)
{
std::map<uint32_t,ue_ctx_t*>::iterator ctx_it2 = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id);
if(ctx_it2 != m_mme_ue_s1ap_id_to_imsi.end() && ctx_it2->second != ue_ctx)
{
m_s1ap_log->error("Context identified with MME UE S1AP Id does not match context identified by IMSI.\n");
return false;
}
}
return true;
}
void
@ -389,32 +457,11 @@ s1ap::get_tmp_ue_emm_ctx(uint32_t mme_ue_s1ap_id, ue_emm_ctx_t* ue_emm_ptr)
return true;
}
void
s1ap::add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx)
ue_ctx_t*
s1ap::find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id)
{
ue_ecm_ctx_t *ue_ptr = new ue_ecm_ctx_t;
memcpy(ue_ptr,&ue_ecm_ctx,sizeof(ue_ecm_ctx));
//This map will store UE's ECM context.
m_mme_ue_s1ap_id_to_ue_ecm_ctx.insert(std::pair<uint32_t,ue_ecm_ctx_t*>(ue_ptr->mme_ue_s1ap_id,ue_ptr));
//Store which enb currently holds the UE
std::map<int32_t,uint16_t>::iterator it_enb = m_sctp_to_enb_id.find(ue_ptr->enb_sri.sinfo_assoc_id);
uint16_t enb_id = it_enb->second;
std::map<uint16_t,std::set<uint32_t> >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id);
if(it_ue_id==m_enb_id_to_ue_ids.end())
{
m_s1ap_log->error("Could not find eNB's UEs\n");
return;
}
it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id);
}
ue_emm_ctx_t*
s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator it = m_imsi_to_ue_emm_ctx.find(imsi);
if(it == m_imsi_to_ue_emm_ctx.end())
std::map<uint32_t, ue_ctx_t*>::iterator it = m_mme_ue_s1ap_id_to_ue_ctx.find(mme_ue_s1ap_id);
if(it == m_mme_ue_s1ap_id_to_imsi.end())
{
return NULL;
}
@ -424,11 +471,11 @@ s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi)
}
}
ue_ecm_ctx_t*
s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id)
ue_ctx_t*
s1ap::find_ue_ctx_from_imsi(uint64_t imsi)
{
std::map<uint32_t, ue_ecm_ctx_t*>::iterator it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id);
if(it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end())
std::map<uint64_t, ue_ctx_t*>::iterator it = m_imsi_to_ue_ctx.find(imsi);
if(it == m_imsi_to_ue_ctx.end())
{
return NULL;
}
@ -437,39 +484,39 @@ s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id)
return it->second;
}
}
bool
s1ap::delete_ue_emm_ctx(uint64_t imsi)
void
s1ap::release_ues_ecm_ctx_in_enb(uint16_t enb_id)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator ue_emm_ctx_it = m_imsi_to_ue_emm_ctx.find(imsi);
if(ue_emm_ctx_it == m_imsi_to_ue_emm_ctx.end())
//delete UEs ctx
std::map<uint16_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id);
std::set<uint32_t>::iterator ue_id = ues_in_enb->second.begin();
while(ue_id != ues_in_enb->second.end() )
{
m_s1ap_log->info("Cannot delete UE EMM context, UE not found. IMSI: %d\n", imsi);
return false;
}
std::map<uint32_t, ue_ctx_t*>::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ctx.find(*ue_id);
m_s1ap_log->info("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id);
m_s1ap_log->console("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id);
//Delete UE context
m_imsi_to_ue_emm_ctx.erase(ue_emm_ctx_it);
delete ue_emm_ctx_it->second;
m_s1ap_log->info("Deleted UE EMM Context.\n");
return true;
ue_set->second.erase(mme_ue_s1ap_id);
}
}
bool
s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id)
s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id)
{
std::map<uint32_t, ue_ecm_ctx_t*>::iterator ue_ecm_ctx_it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id);
if(ue_ecm_ctx_it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end())
ue_ctx_t *ue_ctx = find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id)
if(ue_ctx == NULL)
{
m_s1ap_log->info("Cannot delete UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->error("Cannot release UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false;
}
ue_ecm_ctx_t* ue_ecm_ctx = ue_ecm_ctx_it->second;
ue_ecm_ctx_t* ecm_ctx = &ue_ctx->ecm_ctx;
//Delete UE within eNB UE set
std::map<int32_t,uint16_t>::iterator it = m_sctp_to_enb_id.find(ue_ecm_ctx->enb_sri.sinfo_assoc_id);
std::map<int32_t,uint16_t>::iterator it = m_sctp_to_enb_id.find(ecm_ctx->enb_sri.sinfo_assoc_id);
if(it == m_sctp_to_enb_id.end() )
{
m_s1ap_log->error("Could not find eNB for this request.\n");
m_s1ap_log->error("Could not find eNB for UE release request.\n");
return false;
}
uint16_t enb_id = it->second;
@ -481,31 +528,42 @@ s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id)
}
ue_set->second.erase(mme_ue_s1ap_id);
//Delete UE context
m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ecm_ctx_it);
delete ue_ecm_ctx;
m_s1ap_log->info("Deleted UE ECM Context.\n");
//Release UE ECM context
m_mme_ue_s1ap_id_to_imsi.erase(mme_ue_s1ap_id);
ecm_ctx->state = ECM_STATE_IDLE;
ecm_ctx->mme_ue_s1ap_id = 0;
ecm_ctx->enb_ue_s1ap_id = 0;
m_s1ap_log->info("Released UE ECM Context.\n");
return true;
}
void
s1ap::delete_ues_ecm_ctx_in_enb(uint16_t enb_id)
bool
s1ap::delete_ue_ctx(uint64_t imsi)
{
//delete UEs ctx
std::map<uint16_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id);
std::set<uint32_t>::iterator ue_id = ues_in_enb->second.begin();
while(ue_id != ues_in_enb->second.end() )
ue_ctx_t *ue_ctx = find_ue_ctx_from_imsi(imsi);
if(ue_ctx == NULL)
{
std::map<uint32_t, ue_ecm_ctx_t*>::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(*ue_id);
m_s1ap_log->info("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id);
m_s1ap_log->console("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id);
m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ctx); //remove from general MME map
delete ue_ctx->second; //delete UE context
ues_in_enb->second.erase(ue_id++); //erase from the eNB's UE set
m_s1ap_log->info("Cannot delete UE context, UE not found. IMSI: %d\n", imsi);
return false;
}
//Make sure to release ECM ctx
if(ue_ctx->ecm_ctx.state == ECM_STATE_CONNECTED)
{
release_ue_ecm_ctx(ue_ctx->ecm_state.mme_ue_s1ap_id);
}
//Delete UE context
m_imsi_to_ue_ctx.erase(imsi);
delete ue_ctx;
m_s1ap_log->info("Deleted UE Context.\n");
return true;
}
//UE Bearer Managment
void
s1ap::activate_eps_bearer(uint64_t imsi, uint8_t ebi)
@ -580,3 +638,126 @@ s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx)
}
} //namespace srsepc
/*
void
s1ap::add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator emm_ctx_it = m_imsi_to_ue_emm_ctx.find(ue_emm_ctx.imsi);
if(emm_ctx_it != m_imsi_to_ue_emm_ctx.end())
{
m_s1ap_log->warning("EMM Context already exists. Replacing EMM Context\n");
delete emm_ctx_it->second;
m_imsi_to_ue_emm_ctx.erase(emm_ctx_it);
}
ue_emm_ctx_t *ue_ptr = new ue_emm_ctx_t;
memcpy(ue_ptr,&ue_emm_ctx,sizeof(ue_emm_ctx));
//This map will store UEs EMM context
m_imsi_to_ue_emm_ctx.insert(std::pair<uint64_t,ue_emm_ctx_t*>(ue_ptr->imsi,ue_ptr));
}
*/
/*
void
s1ap::add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx)
{
ue_ecm_ctx_t *ue_ptr = new ue_ecm_ctx_t;
memcpy(ue_ptr,&ue_ecm_ctx,sizeof(ue_ecm_ctx));
//This map will store UE's ECM context.
m_mme_ue_s1ap_id_to_ue_ecm_ctx.insert(std::pair<uint32_t,ue_ecm_ctx_t*>(ue_ptr->mme_ue_s1ap_id,ue_ptr));
//Store which enb currently holds the UE
std::map<int32_t,uint16_t>::iterator it_enb = m_sctp_to_enb_id.find(ue_ptr->enb_sri.sinfo_assoc_id);
uint16_t enb_id = it_enb->second;
std::map<uint16_t,std::set<uint32_t> >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id);
if(it_ue_id==m_enb_id_to_ue_ids.end())
{
m_s1ap_log->error("Could not find eNB's UEs\n");
return;
}
it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id);
}
*/
/*
ue_emm_ctx_t*
s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator it = m_imsi_to_ue_emm_ctx.find(imsi);
if(it == m_imsi_to_ue_emm_ctx.end())
{
return NULL;
}
else
{
return it->second;
}
}
ue_ecm_ctx_t*
s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id)
{
std::map<uint32_t, ue_ecm_ctx_t*>::iterator it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id);
if(it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end())
{
return NULL;
}
else
{
return it->second;
}
}*/
/*
bool
s1ap::delete_ue_emm_ctx(uint64_t imsi)
{
std::map<uint64_t, ue_emm_ctx_t*>::iterator ue_emm_ctx_it = m_imsi_to_ue_emm_ctx.find(imsi);
if(ue_emm_ctx_it == m_imsi_to_ue_emm_ctx.end())
{
m_s1ap_log->info("Cannot delete UE EMM context, UE not found. IMSI: %d\n", imsi);
return false;
}
//Delete UE context
m_imsi_to_ue_emm_ctx.erase(ue_emm_ctx_it);
delete ue_emm_ctx_it->second;
m_s1ap_log->info("Deleted UE EMM Context.\n");
return true;
}
*/
/*
bool
s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id)
{
std::map<uint32_t, ue_ecm_ctx_t*>::iterator ue_ecm_ctx_it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id);
if(ue_ecm_ctx_it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end())
{
m_s1ap_log->info("Cannot delete UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false;
}
ue_ecm_ctx_t* ue_ecm_ctx = ue_ecm_ctx_it->second;
//Delete UE within eNB UE set
std::map<int32_t,uint16_t>::iterator it = m_sctp_to_enb_id.find(ue_ecm_ctx->enb_sri.sinfo_assoc_id);
if(it == m_sctp_to_enb_id.end() )
{
m_s1ap_log->error("Could not find eNB for this request.\n");
return false;
}
uint16_t enb_id = it->second;
std::map<uint16_t,std::set<uint32_t> >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id);
if(ue_set == m_enb_id_to_ue_ids.end())
{
m_s1ap_log->error("Could not find the eNB's UEs.\n");
return false;
}
ue_set->second.erase(mme_ue_s1ap_id);
//Delete UE context
m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ecm_ctx_it);
delete ue_ecm_ctx;
m_s1ap_log->info("Deleted UE ECM Context.\n");
return true;
}
*/

@ -205,27 +205,24 @@ bool
s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp)
{
uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID;
ue_ecm_ctx_t *ue_ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (ue_ecm_ctx == NULL)
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (ue_ctx == NULL)
{
m_s1ap_log->error("Could not find UE's ECM context in active UE's map\n");
return false;
}
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if (emm_ctx == NULL)
{
m_s1ap_log->error("Could not find UE's EMM context in active UE's map\n");
m_s1ap_log->error("Could not find UE's context in active UE's map\n");
return false;
}
ue_emm_ctx_t * emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t * ecm_ctx = &ue_ctx->ecm_ctx;
m_s1ap_log->console("Received Initial Context Setup Response\n");
//Setup E-RABs
for(uint32_t i=0; i<in_ctxt_resp->E_RABSetupListCtxtSURes.len;i++)
{
uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID;
erab_ctx_t *erab_ctx = &ue_ecm_ctx->erabs_ctx[erab_id];
erab_ctx_t *erab_ctx = &ecm_ctx->erabs_ctx[erab_id];
if (erab_ctx->state != ERAB_CTX_REQUESTED)
{
m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id);
m_s1ap_log->error("E-RAB requested was not previously requested %d\n",erab_id);
return false;
}
//Mark E-RAB with context setup
@ -254,7 +251,7 @@ s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_I
{
m_s1ap_log->console("Initial Context Setup Response triggered from Service Request.\n");
m_s1ap_log->console("Sending Modify Bearer Request.\n");
m_mme_gtpc->send_modify_bearer_request(ue_ecm_ctx->imsi, &ue_ecm_ctx->erabs_ctx[5]);
m_mme_gtpc->send_modify_bearer_request(emm_ctx->imsi, &ecm_ctx->erabs_ctx[5]);
}
return true;
}
@ -269,13 +266,14 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON
m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id);
ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ecm_ctx == NULL)
ue_ctx_t * ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ue_ctx == NULL)
{
m_s1ap_log->info("No UE ECM context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("No UE ECM context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false;
}
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Delete user plane context at the SPGW (but keep GTP-C connection).
if (ecm_ctx->state == ECM_STATE_CONNECTED)
@ -284,23 +282,27 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON
m_s1ap_log->console("There are active E-RABs, send release access mearers request");
m_s1ap_log->info("There are active E-RABs, send release access mearers request");
m_mme_gtpc->send_release_access_bearers_request(ecm_ctx->imsi);
//The handle_releease_access_bearers_response function will make sure to mark E-RABS DEACTIVATED
//It will release the UEs downstream S1-u and keep the upstream S1-U connection active.
}
else
{
//No ECM Context to release
m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id);
m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id);
//Make sure E-RABS are merked as DEACTIVATED.
for(int i=0;i<MAX_ERABS_PER_UE;i++)
{
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
}
}
//m_s1ap->delete_ue_ctx(ue_ctx);
for(int i=0;i<MAX_ERABS_PER_UE;i++)
{
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
}
//Delete UE context
ecm_ctx->state = ECM_STATE_DISCONNECTED;
ecm_ctx->state = ECM_STATE_IDLE;
ecm_ctx->enb_ue_s1ap_id = 0;
ecm_ctx->mme_ue_s1ap_id = 0;
m_s1ap_log->info("UE ECM Disconnected.\n");
m_s1ap_log->console("Deleted UE ECM Context.\n");
m_s1ap_log->info("UE is ECM IDLE.\n");
m_s1ap_log->console("UE is ECM IDLE.\n");
return true;
}

@ -140,14 +140,16 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
bool mac_valid = false;
//Get UE ECM context
ue_ecm_ctx_t *ue_ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ue_ecm_ctx == NULL)
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ue_ctx == NULL)
{
m_s1ap_log->warning("Received uplink NAS, but could not find UE ECM context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id);
return false;
}
m_s1ap_log->debug("Received uplink NAS and found UE ECM context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id);
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Parse NAS message header
srslte::byte_buffer_t *nas_msg = m_pool->allocate();
@ -161,15 +163,13 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
//Find UE EMM context if message is security protected.
if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS)
{
//Get EMM context to do integrity check/de-chiphering
ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(ue_emm_ctx == NULL)
//Make sure EMM context is set-up, to do integrity check/de-chiphering
if(emm_ctx->imsi == 0)
{
//No EMM context found.
//Perhaps a temporary context is being created?
//This can happen with integrity protected identity reponse and authentication response messages
if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) &&
!(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY))
//This can happen with integrity protected identity reponse messages
if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY))
{
m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id);
m_pool->deallocate(nas_msg);
@ -191,12 +191,12 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received Identity Response\n");
m_s1ap_log->console("Uplink NAS: Received Identity Response\n");
handle_identity_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received Authentication Response\n");
m_s1ap_log->console("Uplink NAS: Received Authentication Response\n");
handle_nas_authentication_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
default:
m_s1ap_log->warning("Unhandled Plain NAS message 0x%x\n", msg_type );
@ -205,14 +205,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
return false;
}
//Increment UL NAS count.
ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(ue_emm_ctx == NULL)
{
m_s1ap_log->warning("Could not find UE EMM context in ", msg_type );
m_pool->deallocate(nas_msg);
return false;
}
ue_emm_ctx->security_ctxt.ul_nas_count++;
emm_ctx->security_ctxt.ul_nas_count++;
}
else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT)
{
@ -220,11 +213,11 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE:
m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n");
m_s1ap_log->console("Uplink NAS: Received Security Mode Complete\n");
ue_emm_ctx->security_ctxt.ul_nas_count = 0;
ue_emm_ctx->security_ctxt.dl_nas_count = 0;
mac_valid = integrity_check(ue_emm_ctx,nas_msg);
emm_ctx->security_ctxt.ul_nas_count = 0;
emm_ctx->security_ctxt.dl_nas_count = 0;
mac_valid = integrity_check(emm_ctx,nas_msg);
if(mac_valid){
handle_nas_security_mode_complete(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag);
} else {
m_s1ap_log->warning("Invalid MAC in Security Mode Command Complete message.\n" );
}
@ -237,7 +230,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED)
{
//Integrity protected NAS message, possibly chiphered.
ue_emm_ctx->security_ctxt.ul_nas_count++;
emm_ctx->security_ctxt.ul_nas_count++;
mac_valid = integrity_check(ue_emm_ctx,nas_msg);
if(!mac_valid){
m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type);
@ -248,20 +241,20 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE:
m_s1ap_log->info("Uplink NAS: Received Attach Complete\n");
m_s1ap_log->console("Uplink NAS: Received Attach Complete\n");
handle_nas_attach_complete(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received ESM Information Response\n");
m_s1ap_log->console("Uplink NAS: Received ESM Information Response\n");
handle_esm_information_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST:
m_s1ap_log->info("UL NAS: Tracking Area Update Request\n");
handle_tracking_area_update_request(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE:
m_s1ap_log->info("Uplink NAS: Authentication Failure\n");
handle_authentication_failure(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag);
handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag);
break;
default:
m_s1ap_log->warning("Unhandled NAS integrity protected message 0x%x\n", msg_type );
@ -281,8 +274,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
if(*reply_flag == true)
{
if(ue_emm_ctx != NULL){
m_s1ap_log->console("DL NAS: Sent Downlink NAs Message. DL NAS Count=%d, UL NAS count=%d\n",ue_emm_ctx->security_ctxt.dl_nas_count,ue_emm_ctx->security_ctxt.ul_nas_count );
m_s1ap_log->info("DL NAS: Sent Downlink NAS message. DL NAS Count=%d, UL NAS count=%d\n",ue_emm_ctx->security_ctxt.dl_nas_count, ue_emm_ctx->security_ctxt.ul_nas_count);
m_s1ap_log->console("DL NAS: Sent Downlink NAs Message. DL NAS Count=%d, UL NAS count=%d\n",emm_ctx->security_ctxt.dl_nas_count,emm_ctx->security_ctxt.ul_nas_count );
m_s1ap_log->info("DL NAS: Sent Downlink NAS message. DL NAS Count=%d, UL NAS count=%d\n",emm_ctx->security_ctxt.dl_nas_count, emm_ctx->security_ctxt.ul_nas_count);
}
else{
m_s1ap_log->console("DL NAS: Sent Downlink NAS Message\n");
@ -290,7 +283,6 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
}
}
m_pool->deallocate(nas_msg);
return true;
}
@ -353,54 +345,54 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id,
uint8_t rand[16];
uint8_t xres[8];
ue_emm_ctx_t ue_emm_ctx;
ue_ecm_ctx_t ue_ecm_ctx;
ue_ctx_t ue_ctx;
ue_emm_ctx_t *emm_ctx = &ue_ctx.emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx.ecm_ctx;
//Set UE's EMM context
ue_emm_ctx.imsi = 0;
emm_ctx->imsi = 0;
for(int i=0;i<=14;i++){
ue_emm_ctx.imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i);
emm_ctx->imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i);
}
ue_emm_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
ue_emm_ctx.state = EMM_STATE_DEREGISTERED;
emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
emm_ctx->state = EMM_STATE_DEREGISTERED;
//Save UE network capabilities
memcpy(&ue_emm_ctx.security_ctxt.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT));
ue_emm_ctx.security_ctxt.ms_network_cap_present = attach_req.ms_network_cap_present;
memcpy(&emm_ctx->security_ctxt.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT));
emm_ctx->security_ctxt.ms_network_cap_present = attach_req.ms_network_cap_present;
if(attach_req.ms_network_cap_present)
{
memcpy(&ue_emm_ctx.security_ctxt.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT));
memcpy(&emm_ctx->security_ctxt.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT));
}
uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused
ue_emm_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id;
emm_ctx->procedure_transaction_id = pdn_con_req.proc_transaction_id;
//Initialize NAS count
ue_emm_ctx.security_ctxt.ul_nas_count = 0;
ue_emm_ctx.security_ctxt.dl_nas_count = 0;
emm_ctx->security_ctxt.ul_nas_count = 0;
emm_ctx->security_ctxt.dl_nas_count = 0;
//Set UE ECM context
ue_ecm_ctx.imsi = ue_emm_ctx.imsi;
ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx.mme_ue_s1ap_id;
ecm_ctx->imsi = emm_ctx->imsi;
ecm_ctx->mme_ue_s1ap_id = emm_ctx->mme_ue_s1ap_id;
//Set eNB information
ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary
ue_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present;
ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present;
//Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i;
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ecm_ctx->erabs_ctx[i].erab_id = i;
}
//Log Attach Request information
m_s1ap_log->console("Attach request -- IMSI: %015lu\n", ue_emm_ctx.imsi);
m_s1ap_log->info("Attach request -- IMSI: %015lu\n", ue_emm_ctx.imsi);
m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id);
m_s1ap_log->info("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id);
m_s1ap_log->console("Attach request -- IMSI: %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("Attach request -- IMSI: %015lu\n", emm_ctx->imsi);
m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id);
m_s1ap_log->info("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id);
m_s1ap_log->console("Attach request -- Attach type: %d\n", attach_req.eps_attach_type);
m_s1ap_log->info("Attach request -- Attach type: %d\n", attach_req.eps_attach_type);
@ -428,21 +420,20 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id,
m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false");
//Save attach request type
ue_emm_ctx.attach_type = attach_req.eps_attach_type;
emm_ctx->attach_type = attach_req.eps_attach_type;
//Get Authentication Vectors from HSS
if(!m_hss->gen_auth_info_answer(ue_emm_ctx.imsi, ue_emm_ctx.security_ctxt.k_asme, autn, rand, ue_emm_ctx.security_ctxt.xres))
if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres))
{
m_s1ap_log->console("User not found. IMSI %015lu\n",ue_emm_ctx.imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n",ue_emm_ctx.imsi);
m_s1ap_log->console("User not found. IMSI %015lu\n",emm_ctx->imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi);
return false;
}
m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx);
m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
m_s1ap->add_new_ue_ctx(ue_ctx);
//Pack NAS Authentication Request in Downlink NAS Transport msg
pack_authentication_request(reply_buffer, ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id, autn, rand);
pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
//Send reply to eNB
*reply_flag = true;
@ -542,7 +533,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi);
m_s1ap_log->info("Could not find M-TMSI=0x%x. Sending Id Request\n", m_tmsi);
m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
//m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
//We do not know the IMSI of the UE yet
//This will be removed when the identity response is received
@ -558,45 +549,48 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id,
m_s1ap_log->console("Attach Request -- Found M-TMSI: %d\n",m_tmsi);
m_s1ap_log->console("Attach Request -- IMSI: %d\n",it->second);
//Get UE EMM context
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second);
if(ue_emm_ctx!=NULL)
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second);
if(ue_ctx!=NULL)
{
m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_emm_ctx->imsi);
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
m_s1ap_log->console("Found UE context. IMSI: %015lu\n",emm_ctx->imsi);
//Check NAS integrity
bool msg_valid = false;
ue_emm_ctx->security_ctxt.ul_nas_count++;
msg_valid = integrity_check(ue_emm_ctx,nas_msg);
emm_ctx->security_ctxt.ul_nas_count++;
msg_valid = integrity_check(emm_ctx,nas_msg);
if(msg_valid == true)
{
//Create new MME UE S1AP Identity
ue_emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
//Set EMM as de-registered
ue_emm_ctx->state = EMM_STATE_DEREGISTERED;
emm_ctx->state = EMM_STATE_DEREGISTERED;
//Save Attach type
ue_emm_ctx->attach_type = attach_req.eps_attach_type;
//Create UE ECM context
ue_ecm_ctx_t ue_ecm_ctx;
emm_ctx->attach_type = attach_req.eps_attach_type;
//Set UE ECM context
ue_ecm_ctx.imsi = ue_emm_ctx->imsi;
ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx->mme_ue_s1ap_id;
ecm_ctx->imsi = ecm_ctx->imsi;
ecm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id;
//Set eNB information
ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary
ue_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present;
ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present;
//Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i;
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ecm_ctx->erabs_ctx[i].erab_id = i;
}
m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
//m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
//Create session request
m_s1ap_log->console("GUTI Attach -- NAS Integrity OK.");
m_mme_gtpc->send_create_session_request(ue_emm_ctx->imsi);
m_mme_gtpc->send_create_session_request(emm_ctx->imsi);
*reply_flag = false; //No reply needed
return true;
}
@ -649,8 +643,8 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
return true;
}
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second);
if(emm_ctx == NULL || emm_ctx->state != EMM_STATE_REGISTERED)
ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second);
if(ue_ctx == NULL || ue_ctx->emm_ctx.state != EMM_STATE_REGISTERED)
{
m_s1ap_log->console("UE is not EMM-Registered.\n");
m_s1ap_log->error("UE is not EMM-Registered.\n");
@ -658,80 +652,68 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
*reply_flag = true;
return true;
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
emm_ctx->security_ctxt.ul_nas_count++;
mac_valid = short_integrity_check(emm_ctx,nas_msg);
if(mac_valid)
{
m_s1ap_log->console("Service Request -- Short MAC valid\n");
m_s1ap_log->info("Service Request -- Short MAC valid\n");
ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id);
if(ecm_ctx == NULL)
if(ecm_ctx->state == ECM_STATE_CONNECTED)
{
m_s1ap_log->console("UE ECM context is not initialized.\n");
m_s1ap_log->error("UE ECM context is not initialized.\n");
pack_service_reject(reply_buffer, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED, enb_ue_s1ap_id);
*reply_flag = true;
return true;
m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n");
//Service request to Connected UE.
//Set eNB UE S1ap identity
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
m_s1ap_log->console("Service Request -- eNB UE S1AP Id %d \n", enb_ue_s1ap_id);
m_s1ap_log->info("Service Request -- eNB UE S1AP Id %d\n ", enb_ue_s1ap_id);
//Delete eNB context and connect.
m_s1ap_log->console("Service Request -- User has ECM context already\n");
m_s1ap_log->info("Service Request -- User has ECM context already\n");
m_s1ap->m_s1ap_ctx_mngmt_proc->send_ue_context_release_command(ecm_ctx,reply_buffer);
//int default_bearer_id = 5;
//m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx, &ecm_ctx->erabs_ctx[default_bearer_id]);
//FIXME Send Modify context request OR send ctx release command and wait for the reply.
}
else
else if(ecm_ctx->state == ECM_STATE_IDLE)
{
if(ecm_ctx->state == ECM_STATE_CONNECTED)
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
//UE not connect. Connect normally.
m_s1ap_log->console("Service Request -- User is ECM DISCONNECTED\n");
m_s1ap_log->info("Service Request -- User is ECM DISCONNECTED\n");
//Create ECM context
ecm_ctx->imsi = emm_ctx->imsi;
ecm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
emm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id;
//Set eNB information
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary
ecm_ctx->eit = false;
//Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{
m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n");
//Service request to Connected UE.
//Set eNB UE S1ap identity
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
m_s1ap_log->console("Service Request -- eNB UE S1AP Id %d \n", enb_ue_s1ap_id);
m_s1ap_log->info("Service Request -- eNB UE S1AP Id %d\n ", enb_ue_s1ap_id);
//Delete eNB context and connect.
m_s1ap_log->console("Service Request -- User has ECM context already\n");
m_s1ap_log->info("Service Request -- User has ECM context already\n");
m_s1ap->m_s1ap_ctx_mngmt_proc->send_ue_context_release_command(ecm_ctx,reply_buffer);
//int default_bearer_id = 5;
//m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx, &ecm_ctx->erabs_ctx[default_bearer_id]);
//FIXME Send Modify context request OR send ctx release command and wait for the reply.
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ecm_ctx->erabs_ctx[i].erab_id = i;
}
else if(ecm_ctx->state == ECM_STATE_DISCONNECTED)
{
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
//UE not connect. Connect normally.
m_s1ap_log->console("Service Request -- User is ECM DISCONNECTED\n");
m_s1ap_log->info("Service Request -- User is ECM DISCONNECTED\n");
//Create ECM context
ecm_ctx->imsi = emm_ctx->imsi;
ecm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
emm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id;
//Set eNB information
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary
ecm_ctx->eit = false;
//Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i;
}
ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id);
//Re-generate K_eNB
liblte_security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb);
m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",emm_ctx->security_ctxt.ul_nas_count);
m_s1ap_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid);
m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]);
}
else
{
m_s1ap_log->console("ECM context is un-initialized.\n");
m_s1ap_log->error("ECM context is un-initialized.\n");
}
//Re-generate K_eNB
liblte_security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb);
m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",emm_ctx->security_ctxt.ul_nas_count);
m_s1ap_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid);
m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]);
}
else
{
m_s1ap_log->console("ECM context is un-initialized.\n");
m_s1ap_log->error("ECM context is un-initialized.\n");
}
}
else
@ -743,19 +725,15 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
return true;
}
bool
s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag)
s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag)
{
LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp;
bool ue_valid=true;
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(ue_emm_ctx == NULL)
{
m_s1ap_log->error("Authentication Response -- Could not find UE EMM context.\n");
return false;
}
m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", ue_emm_ctx->imsi);
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", emm_ctx->imsi);
//Get NAS authentication response
LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp);
@ -772,26 +750,19 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na
for(int i=0; i<8;i++)
{
if(auth_resp.res[i] != ue_emm_ctx->security_ctxt.xres[i])
if(auth_resp.res[i] != emm_ctx->security_ctxt.xres[i])
{
ue_valid = false;
}
}
if(!ue_valid)
{
std::cout<<std::endl;
std::cout<<"XRES: ";
for(int i=0;i<8;i++)
{
std::cout << std::hex <<(uint16_t)ue_emm_ctx->security_ctxt.xres[i];
}
std::cout<<std::endl;
m_s1ap_log->info_hex(emm_ctx->security_ctxt.xres,8, "XRES");
m_s1ap_log->console("UE Authentication Rejected.\n");
m_s1ap_log->warning("UE Authentication Rejected.\n");
//Send back Athentication Reject
pack_authentication_reject(reply_buffer, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id);
pack_authentication_reject(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id);
*reply_flag = true;
m_s1ap_log->console("Downlink NAS: Sending Authentication Reject.\n");
return false;
@ -801,7 +772,7 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na
m_s1ap_log->console("UE Authentication Accepted.\n");
m_s1ap_log->info("UE Authentication Accepted.\n");
//Send Security Mode Command
pack_security_mode_command(reply_buffer, ue_emm_ctx, ue_ecm_ctx);
pack_security_mode_command(reply_buffer, emm_ctx, ecm_ctx);
*reply_flag = true;
m_s1ap_log->console("Downlink NAS: Sending NAS Security Mode Command.\n");
}
@ -809,15 +780,11 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na
}
bool
s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag)
s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag)
{
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(ue_emm_ctx == NULL)
{
m_s1ap_log->error("Could not find UE's EMM context\n");
return false;
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp;
@ -834,11 +801,11 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas
m_s1ap_log->warning("IMEI-SV present but not handled");
}
m_s1ap_log->info("Security Mode Command Complete -- IMSI: %lu\n", ue_ecm_ctx->imsi);
m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", ue_ecm_ctx->imsi);
if(ue_ecm_ctx->eit == true)
m_s1ap_log->info("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi);
m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi);
if(ecm_ctx->eit == true)
{
pack_esm_information_request(reply_buffer, ue_emm_ctx, ue_ecm_ctx);
pack_esm_information_request(reply_buffer, emm_ctx, ecm_ctx);
m_s1ap_log->console("Sending ESM information request\n");
m_s1ap_log->info("Sending ESM information request\n");
*reply_flag = true;
@ -847,14 +814,14 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas
{
//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_ecm_ctx->imsi);
m_mme_gtpc->send_create_session_request(emm_ctx->imsi);
*reply_flag = false; //No reply needed
}
return true;
}
bool
s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
{
LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp;
@ -877,11 +844,8 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u
return false;
}
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ecm_ctx->imsi);
if(emm_ctx == NULL)
{
m_s1ap_log->error("Received Attach complete, but could not find UE's EMM Context.\n");
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
m_s1ap_log->console("Unpacked Attached Complete Message. IMSI %d\n", emm_ctx->imsi);
m_s1ap_log->console("Unpacked Activate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id);
@ -894,10 +858,10 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u
if(emm_ctx->state == EMM_STATE_DEREGISTERED)
{
//Attach requested from attach request
m_mme_gtpc->send_modify_bearer_request(ecm_ctx->imsi, &ecm_ctx->erabs_ctx[act_bearer.eps_bearer_id]);
m_mme_gtpc->send_modify_bearer_request(emm_ctx->imsi, &ecm_ctx->erabs_ctx[act_bearer.eps_bearer_id]);
//Send reply to eNB
m_s1ap_log->console("Packing EMM infromationi\n");
*reply_flag = pack_emm_information(ecm_ctx, reply_msg);
*reply_flag = pack_emm_information(ue_ctx, reply_msg);
m_s1ap_log->console("Sending EMM infromation, bytes %d\n",reply_msg->N_bytes);
m_s1ap_log->info("Sending EMM infromation\n");
}
@ -906,7 +870,7 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u
}
bool
s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
{
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp;
@ -930,12 +894,12 @@ s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_m
//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_ecm_ctx->imsi);
m_mme_gtpc->send_create_session_request(ue_ctx->emm_ctx.imsi);
return true;
}
bool
s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
{
uint8_t autn[16];
uint8_t rand[16];
@ -953,40 +917,42 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_
imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i);
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Check if EMM context already exists
ue_emm_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_emm_ctx_from_imsi(imsi);
if(ue_tmp_ptr != NULL)
{
m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n");
m_s1ap->delete_ue_emm_ctx(imsi);
}
//ue_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_ctx_from_imsi(imsi);
//if(ue_tmp_ptr != NULL)
//{
// m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n");
// m_s1ap->delete_ue_emm_ctx(imsi);
//}
m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi);
m_s1ap_log->console("Id Response -- IMSI: %015lu\n", imsi);
ue_ecm_ctx->imsi = imsi;
ecm_ctx->imsi = imsi;
//Get UE EMM context
ue_emm_ctx_t ue_emm_ctx;
if(m_s1ap->get_tmp_ue_emm_ctx(ue_ecm_ctx->mme_ue_s1ap_id, &ue_emm_ctx) == false)
{
m_s1ap_log->error("Could not find UE's temporary EMM context. MME UE S1AP Id: %d\n",ue_ecm_ctx->mme_ue_s1ap_id);
return false;
}
ue_emm_ctx.imsi=imsi;
//if(m_s1ap->get_tmp_ue_emm_ctx(ue_ecm_ctx->mme_ue_s1ap_id, &ue_emm_ctx) == false)
//{
// m_s1ap_log->error("Could not find UE's temporary EMM context. MME UE S1AP Id: %d\n",ue_ecm_ctx->mme_ue_s1ap_id);
// return false;
//}
emm_ctx->imsi=imsi;
//Get Authentication Vectors from HSS
if(!m_hss->gen_auth_info_answer(imsi, ue_emm_ctx.security_ctxt.k_asme, autn, rand, ue_emm_ctx.security_ctxt.xres))
if(!m_hss->gen_auth_info_answer(imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres))
{
m_s1ap_log->console("User not found. IMSI %015lu\n",imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n",imsi);
return false;
}
//Store UE EMM context
m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx);
//m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx);
//Pack NAS Authentication Request in Downlink NAS Transport msg
pack_authentication_request(reply_msg, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id, autn, rand);
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
//Send reply to eNB
*reply_flag = true;
@ -999,7 +965,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_
bool
s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
{
m_s1ap_log->console("Warning: Tracking Area Update Request messages not handled yet.\n");
@ -1018,8 +984,8 @@ s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *n
//Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport;
dw_nas->ext=false;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ecm_ctx->mme_ue_s1ap_id;
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ecm_ctx->enb_ue_s1ap_id;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->ecm_ctx.mme_ue_s1ap_id;
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->ecm_ctx.enb_ue_s1ap_id;
dw_nas->HandoverRestrictionList_present=false;
dw_nas->SubscriberProfileIDforRFP_present=false;
//m_s1ap_log->console("Tracking area accept to MME-UE S1AP Id %d\n", ue_ctx->mme_ue_s1ap_id);
@ -1197,7 +1163,7 @@ s1ap_nas_transport::integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t
bool
s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag)
{
uint8_t autn[16];
uint8_t rand[16];
@ -1210,12 +1176,8 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
return false;
}
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(emm_ctx == NULL)
{
m_s1ap_log->error("Could not find UE EMM context\n");
return false;
}
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
switch(auth_fail.emm_cause){
case 20:
@ -1233,22 +1195,22 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
m_s1ap_log->error("Missing fail parameter\n");
return false;
}
if(!m_hss->resync_sqn(ue_ecm_ctx->imsi, auth_fail.auth_fail_param))
if(!m_hss->resync_sqn(emm_ctx->imsi, auth_fail.auth_fail_param))
{
m_s1ap_log->console("Resynchronization failed. IMSI %015lu\n", ue_ecm_ctx->imsi);
m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", ue_ecm_ctx->imsi);
m_s1ap_log->console("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi);
return false;
}
//Get Authentication Vectors from HSS
if(!m_hss->gen_auth_info_answer(ue_ecm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres))
if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres))
{
m_s1ap_log->console("User not found. IMSI %015lu\n", ue_ecm_ctx->imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n", ue_ecm_ctx->imsi);
m_s1ap_log->console("User not found. IMSI %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n", emm_ctx->imsi);
return false;
}
//Pack NAS Authentication Request in Downlink NAS Transport msg
pack_authentication_request(reply_msg, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id, autn, rand);
pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand);
//Send reply to eNB
*reply_flag = true;
@ -1764,10 +1726,12 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint
}
bool
s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_msg)
s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_msg)
{
srslte::byte_buffer_t *nas_buffer = m_pool->allocate();
ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Setup initiating message
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT));
@ -1782,8 +1746,8 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte
//Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport;
dw_nas->ext=false;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ecm_ctx->mme_ue_s1ap_id;//FIXME Change name
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ecm_ctx->enb_ue_s1ap_id;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ecm_ctx->mme_ue_s1ap_id;//FIXME Change name
dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ecm_ctx->enb_ue_s1ap_id;
dw_nas->HandoverRestrictionList_present=false;
dw_nas->SubscriberProfileIDforRFP_present=false;
@ -1799,13 +1763,9 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte
emm_info.utc_and_local_time_zone_present = false;
emm_info.net_dst_present = false;
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi);
if(ue_emm_ctx ==NULL)
return false;
uint8_t sec_hdr_type =2;
ue_emm_ctx->security_ctxt.dl_nas_count++;
LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);
emm_ctx->security_ctxt.dl_nas_count++;
LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer);
if(err != LIBLTE_SUCCESS)
{
m_s1ap_log->error("Error packing EMM Information\n");
@ -1814,8 +1774,8 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte
}
uint8_t mac[4];
srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16],
ue_emm_ctx->security_ctxt.dl_nas_count,
srslte::security_128_eia1 (&emm_ctx->security_ctxt.k_nas_int[16],
emm_ctx->security_ctxt.dl_nas_count,
0,
SECURITY_DIRECTION_DOWNLINK,
&nas_buffer->msg[5],

Loading…
Cancel
Save