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(); int get_s1_mme();
void delete_enb_ctx(int32_t assoc_id); 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_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); 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); 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); 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); 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); //ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id);
void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx); //void add_new_ue_ctx(const ue_ctx_t &ue_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); //void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx);
bool delete_ue_emm_ctx(uint64_t imsi); //void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx);
bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id); //ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi);
void delete_ues_ecm_ctx_in_enb(uint16_t enb_id); //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); 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); 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<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<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<uint64_t, ue_ctx_t*> m_imsi_to_ue_ctx;
std::map<int32_t,ue_emm_ctx_t*> m_mme_ue_s1ap_id_to_tmp_ue_emm_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_mme_ue_s1ap_id;
uint32_t m_next_m_tmsi; uint32_t m_next_m_tmsi;

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

@ -72,14 +72,14 @@ public:
srslte::byte_buffer_t *reply_buffer, srslte::byte_buffer_t *reply_buffer,
bool* reply_flag, bool* reply_flag,
struct sctp_sndrcvinfo *enb_sri); 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_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_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_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_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_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_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, 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_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_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_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_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 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); 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_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_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); 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); 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 //Save create session response info to E-RAB context
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(imsi); ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(imsi);
if(emm_ctx == NULL){ if(ue_ctx == NULL){
m_mme_gtpc_log->error("Could not find UE EMM context\n"); m_mme_gtpc_log->error("Could not find UE 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");
return; 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 //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); 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->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); 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; delete enb_it->second;
m_active_enbs.erase(enb_it++); m_active_enbs.erase(enb_it++);
} }
std::map<uint64_t,ue_emm_ctx_t*>::iterator ue_it = m_imsi_to_ue_emm_ctx.begin(); std::map<uint64_t,ue_ctx_t*>::iterator ue_it = m_imsi_to_ue_ctx.begin();
while(ue_it!=m_imsi_to_ue_emm_ctx.end()) 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->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); m_s1ap_log->console("Deleting UE EMM context. IMSI: %015lu\n", ue_it->first);
delete ue_it->second; delete ue_it->second;
m_imsi_to_ue_emm_ctx.erase(ue_it++); m_imsi_to_ue_ctx.erase(ue_it++);
} }
//Cleanup message handlers //Cleanup message handlers
s1ap_mngmt_proc::cleanup(); 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); m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id);
//Delete connected UEs ctx //Delete connected UEs ctx
delete_ues_ecm_ctx_in_enb(enb_id); release_ues_ecm_ctx_in_enb(enb_id);
//Delete eNB //Delete eNB
delete it_ctx->second; delete it_ctx->second;
@ -348,20 +347,89 @@ s1ap::delete_enb_ctx(int32_t assoc_id)
//UE Context Management //UE Context Management
void 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); std::map<uint64_t, ue_ctx_t*>::iterator ctx_it = m_imsi_to_ue_ctx.find(ue_ctx.emm_ctx.imsi);
if(emm_ctx_it != m_imsi_to_ue_emm_ctx.end()) if(ctx_it != m_imsi_to_ue_ctx.end())
{ {
m_s1ap_log->warning("EMM Context already exists. Replacing EMM Context\n"); m_s1ap_log->warning("UE Context already exists. Replacing UE Context\n");
delete emm_ctx_it->second; delete ctx_it->second;
m_imsi_to_ue_emm_ctx.erase(emm_ctx_it); 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; ue_ctx_t *new_ctx = new ue_ctx_t;
memcpy(ue_ptr,&ue_emm_ctx,sizeof(ue_emm_ctx)); memcpy(new_ctx, &ue_ctx,sizeof(ue_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)); //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 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; return true;
} }
void ue_ctx_t*
s1ap::add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx) 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); 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_imsi_to_ue_emm_ctx.end()) if(it == m_mme_ue_s1ap_id_to_imsi.end())
{ {
return NULL; return NULL;
} }
@ -424,11 +471,11 @@ s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi)
} }
} }
ue_ecm_ctx_t* ue_ctx_t*
s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) 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); std::map<uint64_t, ue_ctx_t*>::iterator it = m_imsi_to_ue_ctx.find(imsi);
if(it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) if(it == m_imsi_to_ue_ctx.end())
{ {
return NULL; 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; 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); //delete UEs ctx
if(ue_emm_ctx_it == m_imsi_to_ue_emm_ctx.end()) 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); std::map<uint32_t, ue_ctx_t*>::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ctx.find(*ue_id);
return false; 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 ue_set->second.erase(mme_ue_s1ap_id);
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 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); ue_ctx_t *ue_ctx = find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id)
if(ue_ecm_ctx_it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) 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; 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 //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() ) 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; return false;
} }
uint16_t enb_id = it->second; 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); ue_set->second.erase(mme_ue_s1ap_id);
//Delete UE context //Release UE ECM context
m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ecm_ctx_it); m_mme_ue_s1ap_id_to_imsi.erase(mme_ue_s1ap_id);
delete ue_ecm_ctx; ecm_ctx->state = ECM_STATE_IDLE;
m_s1ap_log->info("Deleted UE ECM Context.\n"); 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; return true;
} }
void bool
s1ap::delete_ues_ecm_ctx_in_enb(uint16_t enb_id) s1ap::delete_ue_ctx(uint64_t imsi)
{ {
//delete UEs ctx ue_ctx_t *ue_ctx = find_ue_ctx_from_imsi(imsi);
std::map<uint16_t,std::set<uint32_t> >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id); if(ue_ctx == NULL)
std::set<uint32_t>::iterator ue_id = ues_in_enb->second.begin();
while(ue_id != ues_in_enb->second.end() )
{ {
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("Cannot delete UE context, UE not found. IMSI: %d\n", imsi);
m_s1ap_log->info("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id); return false;
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
} }
//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 //UE Bearer Managment
void void
s1ap::activate_eps_bearer(uint64_t imsi, uint8_t ebi) 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 } //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) 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; 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); ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if (ue_ecm_ctx == NULL) if (ue_ctx == NULL)
{ {
m_s1ap_log->error("Could not find UE's ECM 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 = 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");
return false; 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"); m_s1ap_log->console("Received Initial Context Setup Response\n");
//Setup E-RABs //Setup E-RABs
for(uint32_t i=0; i<in_ctxt_resp->E_RABSetupListCtxtSURes.len;i++) 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; 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) 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; return false;
} }
//Mark E-RAB with context setup //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("Initial Context Setup Response triggered from Service Request.\n");
m_s1ap_log->console("Sending Modify Bearer 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; 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->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); 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); ue_ctx_t * ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ecm_ctx == NULL) 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->info("No UE 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->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id);
return false; return false;
} }
ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
//Delete user plane context at the SPGW (but keep GTP-C connection). //Delete user plane context at the SPGW (but keep GTP-C connection).
if (ecm_ctx->state == ECM_STATE_CONNECTED) 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->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_s1ap_log->info("There are active E-RABs, send release access mearers request");
m_mme_gtpc->send_release_access_bearers_request(ecm_ctx->imsi); 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 else
{ {
//No ECM Context to release //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->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); 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.
//m_s1ap->delete_ue_ctx(ue_ctx);
for(int i=0;i<MAX_ERABS_PER_UE;i++) for(int i=0;i<MAX_ERABS_PER_UE;i++)
{ {
ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
} }
}
//Delete UE context //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; ecm_ctx->mme_ue_s1ap_id = 0;
m_s1ap_log->info("UE ECM Disconnected.\n"); m_s1ap_log->info("UE is ECM IDLE.\n");
m_s1ap_log->console("Deleted UE ECM Context.\n"); m_s1ap_log->console("UE is ECM IDLE.\n");
return true; return true;
} }

@ -140,14 +140,16 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
bool mac_valid = false; bool mac_valid = false;
//Get UE ECM context //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); ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id);
if(ue_ecm_ctx == NULL) 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); 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; return false;
} }
m_s1ap_log->debug("Received uplink NAS and found UE ECM context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); 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 //Parse NAS message header
srslte::byte_buffer_t *nas_msg = m_pool->allocate(); 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. //Find UE EMM context if message is security protected.
if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS)
{ {
//Get EMM context to do integrity check/de-chiphering //Make sure EMM context is set-up, to do integrity check/de-chiphering
ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); if(emm_ctx->imsi == 0)
if(ue_emm_ctx == NULL)
{ {
//No EMM context found. //No EMM context found.
//Perhaps a temporary context is being created? //Perhaps a temporary context is being created?
//This can happen with integrity protected identity reponse and authentication response messages //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) && 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))
{ {
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_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); 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: case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); m_s1ap_log->info("Uplink NAS: Received Identity Response\n");
m_s1ap_log->console("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; break;
case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received Authentication Response\n"); m_s1ap_log->info("Uplink NAS: Received Authentication Response\n");
m_s1ap_log->console("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; break;
default: default:
m_s1ap_log->warning("Unhandled Plain NAS message 0x%x\n", msg_type ); 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; return false;
} }
//Increment UL NAS count. //Increment UL NAS count.
ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); emm_ctx->security_ctxt.ul_nas_count++;
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++;
} }
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) 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: case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE:
m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n"); m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n");
m_s1ap_log->console("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; emm_ctx->security_ctxt.ul_nas_count = 0;
ue_emm_ctx->security_ctxt.dl_nas_count = 0; emm_ctx->security_ctxt.dl_nas_count = 0;
mac_valid = integrity_check(ue_emm_ctx,nas_msg); mac_valid = integrity_check(emm_ctx,nas_msg);
if(mac_valid){ 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 { } else {
m_s1ap_log->warning("Invalid MAC in Security Mode Command Complete message.\n" ); 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) 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. //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); mac_valid = integrity_check(ue_emm_ctx,nas_msg);
if(!mac_valid){ if(!mac_valid){
m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); 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: case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE:
m_s1ap_log->info("Uplink NAS: Received Attach Complete\n"); m_s1ap_log->info("Uplink NAS: Received Attach Complete\n");
m_s1ap_log->console("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; break;
case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE:
m_s1ap_log->info("Uplink NAS: Received ESM Information Response\n"); m_s1ap_log->info("Uplink NAS: Received ESM Information Response\n");
m_s1ap_log->console("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; break;
case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST:
m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); 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; break;
case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE:
m_s1ap_log->info("Uplink NAS: Authentication Failure\n"); 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; break;
default: default:
m_s1ap_log->warning("Unhandled NAS integrity protected message 0x%x\n", msg_type ); 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(*reply_flag == true)
{ {
if(ue_emm_ctx != NULL){ 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->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",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",emm_ctx->security_ctxt.dl_nas_count, emm_ctx->security_ctxt.ul_nas_count);
} }
else{ else{
m_s1ap_log->console("DL NAS: Sent Downlink NAS Message\n"); 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); m_pool->deallocate(nas_msg);
return true; 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 rand[16];
uint8_t xres[8]; uint8_t xres[8];
ue_ctx_t ue_ctx;
ue_emm_ctx_t ue_emm_ctx; ue_emm_ctx_t *emm_ctx = &ue_ctx.emm_ctx;
ue_ecm_ctx_t ue_ecm_ctx; ue_ecm_ctx_t *ecm_ctx = &ue_ctx.ecm_ctx;
//Set UE's EMM context //Set UE's EMM context
ue_emm_ctx.imsi = 0; emm_ctx->imsi = 0;
for(int i=0;i<=14;i++){ 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(); emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id();
ue_emm_ctx.state = EMM_STATE_DEREGISTERED; emm_ctx->state = EMM_STATE_DEREGISTERED;
//Save UE network capabilities //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)); memcpy(&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; emm_ctx->security_ctxt.ms_network_cap_present = attach_req.ms_network_cap_present;
if(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 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 //Initialize NAS count
ue_emm_ctx.security_ctxt.ul_nas_count = 0; emm_ctx->security_ctxt.ul_nas_count = 0;
ue_emm_ctx.security_ctxt.dl_nas_count = 0; emm_ctx->security_ctxt.dl_nas_count = 0;
//Set UE ECM context //Set UE ECM context
ue_ecm_ctx.imsi = ue_emm_ctx.imsi; ecm_ctx->imsi = emm_ctx->imsi;
ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx.mme_ue_s1ap_id; ecm_ctx->mme_ue_s1ap_id = emm_ctx->mme_ue_s1ap_id;
//Set eNB information //Set eNB information
ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary //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 //Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{ {
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i; ecm_ctx->erabs_ctx[i].erab_id = i;
} }
//Log Attach Request information //Log Attach Request information
m_s1ap_log->console("Attach request -- IMSI: %015lu\n", ue_emm_ctx.imsi); m_s1ap_log->console("Attach request -- IMSI: %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("Attach request -- IMSI: %015lu\n", ue_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", ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id); 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", 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", 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->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); 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"); 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 //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 //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->console("User not found. IMSI %015lu\n",emm_ctx->imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n",ue_emm_ctx.imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi);
return false; return false;
} }
m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx); m_s1ap->add_new_ue_ctx(ue_ctx);
m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx);
//Pack NAS Authentication Request in Downlink NAS Transport msg //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 //Send reply to eNB
*reply_flag = true; *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->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_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 //We do not know the IMSI of the UE yet
//This will be removed when the identity response is received //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 -- Found M-TMSI: %d\n",m_tmsi);
m_s1ap_log->console("Attach Request -- IMSI: %d\n",it->second); m_s1ap_log->console("Attach Request -- IMSI: %d\n",it->second);
//Get UE EMM context //Get UE EMM context
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second); ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second);
if(ue_emm_ctx!=NULL) 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 //Check NAS integrity
bool msg_valid = false; bool msg_valid = false;
ue_emm_ctx->security_ctxt.ul_nas_count++; emm_ctx->security_ctxt.ul_nas_count++;
msg_valid = integrity_check(ue_emm_ctx,nas_msg); msg_valid = integrity_check(emm_ctx,nas_msg);
if(msg_valid == true) if(msg_valid == true)
{ {
//Create new MME UE S1AP Identity //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 //Set EMM as de-registered
ue_emm_ctx->state = EMM_STATE_DEREGISTERED; emm_ctx->state = EMM_STATE_DEREGISTERED;
//Save Attach type //Save Attach type
ue_emm_ctx->attach_type = attach_req.eps_attach_type; emm_ctx->attach_type = attach_req.eps_attach_type;
//Create UE ECM context
ue_ecm_ctx_t ue_ecm_ctx;
//Set UE ECM context //Set UE ECM context
ue_ecm_ctx.imsi = ue_emm_ctx->imsi; ecm_ctx->imsi = ecm_ctx->imsi;
ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx->mme_ue_s1ap_id; ecm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id;
//Set eNB information //Set eNB information
ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo));
//Save whether secure ESM information transfer is necessary //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 //Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{ {
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i; 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 //Create session request
m_s1ap_log->console("GUTI Attach -- NAS Integrity OK."); 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 *reply_flag = false; //No reply needed
return true; return true;
} }
@ -649,8 +643,8 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
return true; return true;
} }
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second); ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second);
if(emm_ctx == NULL || emm_ctx->state != EMM_STATE_REGISTERED) 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->console("UE is not EMM-Registered.\n");
m_s1ap_log->error("UE is not EMM-Registered.\n"); m_s1ap_log->error("UE is not EMM-Registered.\n");
@ -658,23 +652,15 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
*reply_flag = true; *reply_flag = true;
return 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++; emm_ctx->security_ctxt.ul_nas_count++;
mac_valid = short_integrity_check(emm_ctx,nas_msg); mac_valid = short_integrity_check(emm_ctx,nas_msg);
if(mac_valid) if(mac_valid)
{ {
m_s1ap_log->console("Service Request -- Short MAC valid\n"); m_s1ap_log->console("Service Request -- Short MAC valid\n");
m_s1ap_log->info("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)
{
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;
}
else
{
if(ecm_ctx->state == ECM_STATE_CONNECTED) if(ecm_ctx->state == ECM_STATE_CONNECTED)
{ {
m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n"); m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n");
@ -692,9 +678,8 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
//int default_bearer_id = 5; //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]); //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. //FIXME Send Modify context request OR send ctx release command and wait for the reply.
} }
else if(ecm_ctx->state == ECM_STATE_DISCONNECTED) else if(ecm_ctx->state == ECM_STATE_IDLE)
{ {
ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id;
@ -715,17 +700,15 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
//Initialize E-RABs //Initialize E-RABs
for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++)
{ {
ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED;
ue_ecm_ctx.erabs_ctx[i].erab_id = i; 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 //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); 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->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_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]); m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]);
} }
else else
{ {
@ -733,7 +716,6 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
m_s1ap_log->error("ECM context is un-initialized.\n"); m_s1ap_log->error("ECM context is un-initialized.\n");
} }
} }
}
else else
{ {
m_s1ap_log->console("Service Request -- Short MAC invalid. Re-starting authentication procedure \n"); m_s1ap_log->console("Service Request -- Short MAC invalid. Re-starting authentication procedure \n");
@ -743,19 +725,15 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi,
return true; return true;
} }
bool 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; LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp;
bool ue_valid=true; bool ue_valid=true;
ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
if(ue_emm_ctx == NULL) ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
{ m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", emm_ctx->imsi);
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);
//Get NAS authentication response //Get NAS authentication response
LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); 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++) 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; ue_valid = false;
} }
} }
if(!ue_valid) if(!ue_valid)
{ {
std::cout<<std::endl; m_s1ap_log->info_hex(emm_ctx->security_ctxt.xres,8, "XRES");
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->console("UE Authentication Rejected.\n"); m_s1ap_log->console("UE Authentication Rejected.\n");
m_s1ap_log->warning("UE Authentication Rejected.\n"); m_s1ap_log->warning("UE Authentication Rejected.\n");
//Send back Athentication Reject //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; *reply_flag = true;
m_s1ap_log->console("Downlink NAS: Sending Authentication Reject.\n"); m_s1ap_log->console("Downlink NAS: Sending Authentication Reject.\n");
return false; 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->console("UE Authentication Accepted.\n");
m_s1ap_log->info("UE Authentication Accepted.\n"); m_s1ap_log->info("UE Authentication Accepted.\n");
//Send Security Mode Command //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; *reply_flag = true;
m_s1ap_log->console("Downlink NAS: Sending NAS Security Mode Command.\n"); 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 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); ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
if(ue_emm_ctx == NULL) ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
{
m_s1ap_log->error("Could not find UE's EMM context\n");
return false;
}
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; 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->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->info("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi);
m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", ue_ecm_ctx->imsi); m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi);
if(ue_ecm_ctx->eit == true) 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->console("Sending ESM information request\n");
m_s1ap_log->info("Sending ESM information request\n"); m_s1ap_log->info("Sending ESM information request\n");
*reply_flag = true; *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. //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. //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 *reply_flag = false; //No reply needed
} }
return true; return true;
} }
bool 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; 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; return false;
} }
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ecm_ctx->imsi); ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
if(emm_ctx == NULL) ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
{
m_s1ap_log->error("Received Attach complete, but could not find UE's EMM Context.\n");
}
m_s1ap_log->console("Unpacked Attached Complete Message. IMSI %d\n", emm_ctx->imsi); 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); 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) if(emm_ctx->state == EMM_STATE_DEREGISTERED)
{ {
//Attach requested from attach request //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 //Send reply to eNB
m_s1ap_log->console("Packing EMM infromationi\n"); 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->console("Sending EMM infromation, bytes %d\n",reply_msg->N_bytes);
m_s1ap_log->info("Sending EMM infromation\n"); 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 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; 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. //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. //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; return true;
} }
bool 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 autn[16];
uint8_t rand[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); 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 //Check if EMM context already exists
ue_emm_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_emm_ctx_from_imsi(imsi); //ue_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_ctx_from_imsi(imsi);
if(ue_tmp_ptr != NULL) //if(ue_tmp_ptr != NULL)
{ //{
m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n"); // m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n");
m_s1ap->delete_ue_emm_ctx(imsi); // m_s1ap->delete_ue_emm_ctx(imsi);
} //}
m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi);
m_s1ap_log->console("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 //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)
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);
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;
return false; //}
} emm_ctx->imsi=imsi;
ue_emm_ctx.imsi=imsi;
//Get Authentication Vectors from HSS //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->console("User not found. IMSI %015lu\n",imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi);
return false; return false;
} }
//Store UE EMM context //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 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 //Send reply to eNB
*reply_flag = true; *reply_flag = true;
@ -999,7 +965,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_
bool 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"); 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 //Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport;
dw_nas->ext=false; dw_nas->ext=false;
dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ecm_ctx->mme_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_ecm_ctx->enb_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->HandoverRestrictionList_present=false;
dw_nas->SubscriberProfileIDforRFP_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); //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 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 autn[16];
uint8_t rand[16]; uint8_t rand[16];
@ -1210,12 +1176,8 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg
return false; return false;
} }
ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx;
if(emm_ctx == NULL) ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx;
{
m_s1ap_log->error("Could not find UE EMM context\n");
return false;
}
switch(auth_fail.emm_cause){ switch(auth_fail.emm_cause){
case 20: 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"); m_s1ap_log->error("Missing fail parameter\n");
return false; 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->console("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", ue_ecm_ctx->imsi); m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi);
return false; return false;
} }
//Get Authentication Vectors from HSS //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->console("User not found. IMSI %015lu\n", emm_ctx->imsi);
m_s1ap_log->info("User not found. IMSI %015lu\n", ue_ecm_ctx->imsi); m_s1ap_log->info("User not found. IMSI %015lu\n", emm_ctx->imsi);
return false; return false;
} }
//Pack NAS Authentication Request in Downlink NAS Transport msg //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 //Send reply to eNB
*reply_flag = true; *reply_flag = true;
@ -1764,10 +1726,12 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint
} }
bool 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(); 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 //Setup initiating message
LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu;
bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); 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 //Setup Dw NAS structure
LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport;
dw_nas->ext=false; 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->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 = ue_ecm_ctx->enb_ue_s1ap_id; dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ecm_ctx->enb_ue_s1ap_id;
dw_nas->HandoverRestrictionList_present=false; dw_nas->HandoverRestrictionList_present=false;
dw_nas->SubscriberProfileIDforRFP_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.utc_and_local_time_zone_present = false;
emm_info.net_dst_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; uint8_t sec_hdr_type =2;
ue_emm_ctx->security_ctxt.dl_nas_count++; 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); 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) if(err != LIBLTE_SUCCESS)
{ {
m_s1ap_log->error("Error packing EMM Information\n"); 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]; uint8_t mac[4];
srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], srslte::security_128_eia1 (&emm_ctx->security_ctxt.k_nas_int[16],
ue_emm_ctx->security_ctxt.dl_nas_count, emm_ctx->security_ctxt.dl_nas_count,
0, 0,
SECURITY_DIRECTION_DOWNLINK, SECURITY_DIRECTION_DOWNLINK,
&nas_buffer->msg[5], &nas_buffer->msg[5],

Loading…
Cancel
Save