@ -45,634 +45,7 @@ nas::~nas() {}
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool
//FIXME Move UE Initiating mesages from s1ap_nas_transport
nas : : handle_nas_attach_request ( uint32_t enb_ue_s1ap_id ,
srslte : : byte_buffer_t * nas_msg ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req ;
LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req ;
//Get NAS Attach Request and PDN connectivity request messages
LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg ( ( LIBLTE_BYTE_MSG_STRUCT * ) nas_msg , & attach_req ) ;
if ( err ! = LIBLTE_SUCCESS ) {
m_s1ap_log - > error ( " Error unpacking NAS attach request. Error: %s \n " , liblte_error_text [ err ] ) ;
m_pool - > deallocate ( nas_msg ) ;
return false ;
}
/*Get PDN Connectivity Request*/
err = liblte_mme_unpack_pdn_connectivity_request_msg ( & attach_req . esm_msg , & pdn_con_req ) ;
if ( err ! = LIBLTE_SUCCESS ) {
m_s1ap_log - > error ( " Error unpacking NAS PDN Connectivity Request. Error: %s \n " , liblte_error_text [ err ] ) ;
m_pool - > deallocate ( nas_msg ) ;
return false ;
}
//Get attach type from attach request
if ( attach_req . eps_mobile_id . type_of_id = = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI )
{
m_s1ap_log - > console ( " Attach Request -- IMSI-style attach request \n " ) ;
m_s1ap_log - > info ( " Attach Request -- IMSI-style attach request \n " ) ;
handle_nas_imsi_attach_request ( enb_ue_s1ap_id , attach_req , pdn_con_req , reply_buffer , reply_flag , enb_sri ) ;
}
else if ( attach_req . eps_mobile_id . type_of_id = = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI )
{
m_s1ap_log - > console ( " Attach Request -- GUTI-style attach request \n " ) ;
m_s1ap_log - > info ( " Attach Request -- GUTI-style attach request \n " ) ;
handle_nas_guti_attach_request ( enb_ue_s1ap_id , attach_req , pdn_con_req , nas_msg , reply_buffer , reply_flag , enb_sri ) ;
}
else
{
m_s1ap_log - > error ( " Unhandle Mobile Id type in attach request \n " ) ;
return false ;
}
return true ;
}
bool
nas : : handle_nas_imsi_attach_request ( uint32_t enb_ue_s1ap_id ,
const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT & attach_req ,
const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT & pdn_con_req ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
uint8_t k_asme [ 32 ] ;
uint8_t autn [ 16 ] ;
uint8_t rand [ 16 ] ;
uint8_t xres [ 8 ] ;
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
uint64_t imsi = 0 ;
for ( int i = 0 ; i < = 14 ; i + + ) {
imsi + = attach_req . eps_mobile_id . imsi [ i ] * std : : pow ( 10 , 14 - i ) ;
}
//Check if UE is already atached
ue_ctx_t * old_ctx = m_s1ap - > find_ue_ctx_from_imsi ( imsi ) ;
if ( old_ctx ! = NULL )
{
m_s1ap_log - > console ( " Attach Request -- UE is already attached. " ) ;
m_s1ap_log - > info ( " Attach Request -- UE is already attached. " ) ;
//Detaching previoulsy attached UE.
m_mme_gtpc - > send_delete_session_request ( imsi ) ;
if ( old_ctx - > ecm_ctx . mme_ue_s1ap_id ! = 0 )
{
m_s1ap - > m_s1ap_ctx_mngmt_proc - > send_ue_context_release_command ( & old_ctx - > ecm_ctx , reply_buffer ) ;
}
m_s1ap - > delete_ue_ctx ( imsi ) ;
}
emm_ctx - > imsi = imsi ;
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 ( & 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 ( & 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
emm_ctx - > procedure_transaction_id = pdn_con_req . proc_transaction_id ;
//Initialize NAS count
emm_ctx - > security_ctxt . ul_nas_count = 0 ;
emm_ctx - > security_ctxt . dl_nas_count = 0 ;
//Set UE ECM context
ecm_ctx - > imsi = emm_ctx - > imsi ;
ecm_ctx - > mme_ue_s1ap_id = emm_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 = pdn_con_req . esm_info_transfer_flag_present ;
//Initialize E-RABs
for ( uint i = 0 ; i < MAX_ERABS_PER_UE ; 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 " , 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 ) ;
m_s1ap_log - > console ( " Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eea [ 0 ] ,
attach_req . ue_network_cap . eea [ 1 ] ,
attach_req . ue_network_cap . eea [ 2 ] ,
attach_req . ue_network_cap . eea [ 3 ] ,
attach_req . ue_network_cap . eea [ 4 ] ,
attach_req . ue_network_cap . eea [ 5 ] ,
attach_req . ue_network_cap . eea [ 6 ] ,
attach_req . ue_network_cap . eea [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eia [ 0 ] ,
attach_req . ue_network_cap . eia [ 1 ] ,
attach_req . ue_network_cap . eia [ 2 ] ,
attach_req . ue_network_cap . eia [ 3 ] ,
attach_req . ue_network_cap . eia [ 4 ] ,
attach_req . ue_network_cap . eia [ 5 ] ,
attach_req . ue_network_cap . eia [ 6 ] ,
attach_req . ue_network_cap . eia [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- MS Network Capabilities Present: %s \n " , attach_req . ms_network_cap_present ? " true " : " false " ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- EPS Bearer Identity requested: %d \n " , pdn_con_req . eps_bearer_id ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- Procedure Transaction Id: %d \n " , pdn_con_req . proc_transaction_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
emm_ctx - > attach_type = attach_req . eps_attach_type ;
//Get Authentication Vectors from HSS
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 " , emm_ctx - > imsi ) ;
m_s1ap_log - > info ( " User not found. IMSI %015lu \n " , emm_ctx - > imsi ) ;
return false ;
}
//Allocate eKSI for this authentication vector
//Here we assume a new security context thus a new eKSI
emm_ctx - > security_ctxt . eksi = 0 ;
//Save the UE context
ue_ctx_t * new_ctx = new ue_ctx_t ;
memcpy ( new_ctx , & ue_ctx , sizeof ( ue_ctx_t ) ) ;
m_s1ap - > add_ue_ctx_to_imsi_map ( new_ctx ) ;
m_s1ap - > add_ue_ctx_to_mme_ue_s1ap_id_map ( new_ctx ) ;
m_s1ap - > add_ue_to_enb_set ( enb_sri - > sinfo_assoc_id , ecm_ctx - > mme_ue_s1ap_id ) ;
//Pack NAS Authentication Request in Downlink NAS Transport msg
pack_authentication_request ( reply_buffer , ecm_ctx - > enb_ue_s1ap_id , ecm_ctx - > mme_ue_s1ap_id , emm_ctx - > security_ctxt . eksi , autn , rand ) ;
//Send reply to eNB
* reply_flag = true ;
m_s1ap_log - > info ( " Downlink NAS: Sending Authentication Request \n " ) ;
m_s1ap_log - > console ( " Downlink NAS: Sending Authentication Request \n " ) ;
return true ;
}
bool
nas : : handle_nas_guti_attach_request ( uint32_t enb_ue_s1ap_id ,
const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT & attach_req ,
const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT & pdn_con_req ,
srslte : : byte_buffer_t * nas_msg ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
//Parse the message security header
uint8 pd = 0 ;
uint8 sec_hdr_type = 0 ;
liblte_mme_parse_msg_sec_header ( ( LIBLTE_BYTE_MSG_STRUCT * ) nas_msg , & pd , & sec_hdr_type ) ;
bool integrity_valid = false ;
if ( sec_hdr_type ! = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY )
{
m_s1ap_log - > info ( " Attach request -- GUTI-stlye attach request is not integrity protected \n " ) ;
m_s1ap_log - > console ( " Attach request -- GUTI-stlye attach request is not integrity protected \n " ) ;
}
else {
m_s1ap_log - > info ( " Attach request -- GUTI-stlye attach request is integrity protected \n " ) ;
m_s1ap_log - > console ( " Attach request -- GUTI-stlye attach request is integrity protected \n " ) ;
}
//GUTI style attach
uint32_t m_tmsi = attach_req . eps_mobile_id . guti . m_tmsi ;
std : : map < uint32_t , uint64_t > : : iterator it = m_s1ap - > m_tmsi_to_imsi . find ( m_tmsi ) ;
if ( it = = m_s1ap - > m_tmsi_to_imsi . end ( ) )
{
m_s1ap_log - > console ( " Attach Request -- Could not find M-TMSI 0x%x \n " , m_tmsi ) ;
m_s1ap_log - > info ( " Attach Request -- Could not find M-TMSI 0x%x \n " , m_tmsi ) ;
//Could not find IMSI from M-TMSI, send Id request
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 ;
//We do not know the IMSI of the UE yet
//The IMSI will be set when the identity response is received
//Set EMM ctx
emm_ctx - > imsi = 0 ;
emm_ctx - > state = EMM_STATE_DEREGISTERED ;
emm_ctx - > mme_ue_s1ap_id = m_s1ap - > get_next_mme_ue_s1ap_id ( ) ;
//Save UE network capabilities
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 ( & emm_ctx - > security_ctxt . ms_network_cap , & attach_req . ms_network_cap , sizeof ( LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ) ) ;
}
//Initialize NAS count
emm_ctx - > security_ctxt . ul_nas_count = 0 ;
emm_ctx - > security_ctxt . dl_nas_count = 0 ;
emm_ctx - > procedure_transaction_id = pdn_con_req . proc_transaction_id ;
//Set ECM context
ecm_ctx - > imsi = 0 ;
ecm_ctx - > enb_ue_s1ap_id = enb_ue_s1ap_id ;
ecm_ctx - > mme_ue_s1ap_id = emm_ctx - > mme_ue_s1ap_id ;
uint8_t eps_bearer_id = pdn_con_req . eps_bearer_id ; //TODO: Unused
//Save attach request type
emm_ctx - > attach_type = attach_req . eps_attach_type ;
//Save whether ESM information transfer is necessary
ecm_ctx - > eit = pdn_con_req . esm_info_transfer_flag_present ;
//Add eNB info to UE ctxt
memcpy ( & ecm_ctx - > enb_sri , enb_sri , sizeof ( struct sctp_sndrcvinfo ) ) ;
//Initialize E-RABs
for ( uint i = 0 ; i < MAX_ERABS_PER_UE ; i + + )
{
ecm_ctx - > erabs_ctx [ i ] . state = ERAB_DEACTIVATED ;
ecm_ctx - > erabs_ctx [ i ] . erab_id = i ;
}
m_s1ap_log - > console ( " Attach request -- IMSI: %015lu \n " , ecm_ctx - > imsi ) ;
m_s1ap_log - > info ( " Attach request -- IMSI: %015lu \n " , ecm_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 - > console ( " Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eea [ 0 ] , attach_req . ue_network_cap . eea [ 1 ] , attach_req . ue_network_cap . eea [ 2 ] , attach_req . ue_network_cap . eea [ 3 ] ,
attach_req . ue_network_cap . eea [ 4 ] , attach_req . ue_network_cap . eea [ 5 ] , attach_req . ue_network_cap . eea [ 6 ] , attach_req . ue_network_cap . eea [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eia [ 0 ] , attach_req . ue_network_cap . eia [ 1 ] , attach_req . ue_network_cap . eia [ 2 ] , attach_req . ue_network_cap . eia [ 3 ] ,
attach_req . ue_network_cap . eia [ 4 ] , attach_req . ue_network_cap . eia [ 5 ] , attach_req . ue_network_cap . eia [ 6 ] , attach_req . ue_network_cap . eia [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- MS Network Capabilities Present: %s \n " , attach_req . ms_network_cap_present ? " true " : " false " ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- EPS Bearer Identity requested: %d \n " , pdn_con_req . eps_bearer_id ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- Procedure Transaction Id: %d \n " , pdn_con_req . proc_transaction_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 ( " 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 ) ;
//Store temporary ue context
ue_ctx_t * new_ctx = new ue_ctx_t ;
memcpy ( new_ctx , & ue_ctx , sizeof ( ue_ctx_t ) ) ;
m_s1ap - > add_ue_ctx_to_mme_ue_s1ap_id_map ( new_ctx ) ;
m_s1ap - > add_ue_to_enb_set ( enb_sri - > sinfo_assoc_id , ecm_ctx - > mme_ue_s1ap_id ) ;
pack_identity_request ( reply_buffer , ecm_ctx - > enb_ue_s1ap_id , ecm_ctx - > mme_ue_s1ap_id ) ;
* reply_flag = true ;
return true ;
}
else {
m_s1ap_log - > console ( " Attach Request -- Found M-TMSI: %d \n " , m_tmsi ) ;
m_s1ap_log - > console ( " Attach Request -- IMSI: %015lu \n " , it - > second ) ;
//Get UE EMM context
ue_ctx_t * ue_ctx = m_s1ap - > find_ue_ctx_from_imsi ( it - > second ) ;
if ( ue_ctx ! = NULL )
{
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, old eNB UE S1ap Id %d, old MME UE S1AP Id %d \n " , emm_ctx - > imsi , ecm_ctx - > enb_ue_s1ap_id , ecm_ctx - > mme_ue_s1ap_id ) ;
//Check NAS integrity
bool msg_valid = false ;
emm_ctx - > security_ctxt . ul_nas_count + + ;
msg_valid = integrity_check ( emm_ctx , nas_msg ) ;
if ( msg_valid = = true & & emm_ctx - > state = = EMM_STATE_DEREGISTERED )
{
m_s1ap_log - > console ( " GUTI Attach Integrity valid. UL count %d, DL count %d \n " , emm_ctx - > security_ctxt . ul_nas_count , emm_ctx - > security_ctxt . dl_nas_count ) ;
//Create new MME UE S1AP Identity
emm_ctx - > mme_ue_s1ap_id = m_s1ap - > get_next_mme_ue_s1ap_id ( ) ;
ecm_ctx - > mme_ue_s1ap_id = emm_ctx - > mme_ue_s1ap_id ;
ecm_ctx - > enb_ue_s1ap_id = enb_ue_s1ap_id ;
ecm_ctx - > imsi = ecm_ctx - > imsi ;
emm_ctx - > procedure_transaction_id = pdn_con_req . proc_transaction_id ;
//Save Attach type
emm_ctx - > attach_type = attach_req . eps_attach_type ;
//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 = pdn_con_req . esm_info_transfer_flag_present ;
//Initialize E-RABs
for ( uint i = 0 ; i < MAX_ERABS_PER_UE ; i + + )
{
ecm_ctx - > erabs_ctx [ i ] . state = ERAB_DEACTIVATED ;
ecm_ctx - > erabs_ctx [ i ] . erab_id = i ;
}
//Store context based on MME UE S1AP id
m_s1ap - > add_ue_ctx_to_mme_ue_s1ap_id_map ( ue_ctx ) ;
m_s1ap - > add_ue_to_enb_set ( enb_sri - > sinfo_assoc_id , ecm_ctx - > mme_ue_s1ap_id ) ;
//Re-generate K_eNB
srslte : : 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 ( " Generating KeNB with UL NAS COUNT: %d \n " , emm_ctx - > security_ctxt . ul_nas_count ) ;
m_s1ap_log - > info_hex ( emm_ctx - > security_ctxt . k_enb , 32 , " Key eNodeB (k_enb) \n " ) ;
m_s1ap_log - > console ( " Attach request -- IMSI: %015lu \n " , ecm_ctx - > imsi ) ;
m_s1ap_log - > info ( " Attach request -- IMSI: %015lu \n " , ecm_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 - > console ( " Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eea [ 0 ] , attach_req . ue_network_cap . eea [ 1 ] , attach_req . ue_network_cap . eea [ 2 ] , attach_req . ue_network_cap . eea [ 3 ] ,
attach_req . ue_network_cap . eea [ 4 ] , attach_req . ue_network_cap . eea [ 5 ] , attach_req . ue_network_cap . eea [ 6 ] , attach_req . ue_network_cap . eea [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d \n " ,
attach_req . ue_network_cap . eia [ 0 ] , attach_req . ue_network_cap . eia [ 1 ] , attach_req . ue_network_cap . eia [ 2 ] , attach_req . ue_network_cap . eia [ 3 ] ,
attach_req . ue_network_cap . eia [ 4 ] , attach_req . ue_network_cap . eia [ 5 ] , attach_req . ue_network_cap . eia [ 6 ] , attach_req . ue_network_cap . eia [ 7 ] ) ;
m_s1ap_log - > console ( " Attach Request -- MS Network Capabilities Present: %s \n " , attach_req . ms_network_cap_present ? " true " : " false " ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- EPS Bearer Identity requested: %d \n " , pdn_con_req . eps_bearer_id ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- Procedure Transaction Id: %d \n " , pdn_con_req . proc_transaction_id ) ;
m_s1ap_log - > console ( " PDN Connectivity Request -- ESM Information Transfer requested: %s \n " , pdn_con_req . esm_info_transfer_flag_present ? " true " : " false " ) ;
//Create session request
m_s1ap_log - > console ( " GUTI Attach -- NAS Integrity OK. \n " ) ;
if ( ecm_ctx - > eit )
{
m_s1ap_log - > console ( " Secure ESM information transfer requested. \n " ) ;
m_s1ap_log - > info ( " Secure ESM information transfer requested. \n " ) ;
pack_esm_information_request ( reply_buffer , emm_ctx , ecm_ctx ) ;
* reply_flag = true ;
}
else
{
//Get subscriber info from HSS
uint8_t default_bearer = 5 ;
m_hss - > gen_update_loc_answer ( emm_ctx - > imsi , & ue_ctx - > ecm_ctx . erabs_ctx [ default_bearer ] . qci ) ;
m_s1ap_log - > debug ( " Getting subscription information -- QCI %d \n " , ue_ctx - > ecm_ctx . erabs_ctx [ default_bearer ] . qci ) ;
m_s1ap_log - > console ( " Getting subscription information -- QCI %d \n " , ue_ctx - > ecm_ctx . erabs_ctx [ default_bearer ] . qci ) ;
m_mme_gtpc - > send_create_session_request ( emm_ctx - > imsi ) ;
* reply_flag = false ; //No reply needed
}
return true ;
}
else
{
if ( emm_ctx - > state ! = EMM_STATE_DEREGISTERED )
{
m_s1ap_log - > error ( " Received GUTI-Attach Request from attached user. \n " ) ;
m_s1ap_log - > console ( " Received GUTI-Attach Request from attached user. \n " ) ;
//Delete previous Ctx, restart authentication
//Detaching previoulsy attached UE.
m_mme_gtpc - > send_delete_session_request ( emm_ctx - > imsi ) ;
if ( ecm_ctx - > mme_ue_s1ap_id ! = 0 )
{
m_s1ap - > m_s1ap_ctx_mngmt_proc - > send_ue_context_release_command ( ecm_ctx , reply_buffer ) ;
}
}
emm_ctx - > security_ctxt . ul_nas_count = 0 ;
emm_ctx - > security_ctxt . dl_nas_count = 0 ;
//Create new MME UE S1AP Identity
uint32_t new_mme_ue_s1ap_id = m_s1ap - > get_next_mme_ue_s1ap_id ( ) ;
//Make sure context from previous NAS connections is not present
if ( ecm_ctx - > mme_ue_s1ap_id ! = 0 )
{
m_s1ap - > release_ue_ecm_ctx ( ecm_ctx - > mme_ue_s1ap_id ) ;
}
emm_ctx - > mme_ue_s1ap_id = m_s1ap - > get_next_mme_ue_s1ap_id ( ) ;
ecm_ctx - > mme_ue_s1ap_id = emm_ctx - > mme_ue_s1ap_id ;
//Set EMM as de-registered
emm_ctx - > state = EMM_STATE_DEREGISTERED ;
//Save Attach type
emm_ctx - > attach_type = attach_req . eps_attach_type ;
//Set UE ECM context
ecm_ctx - > imsi = ecm_ctx - > imsi ;
ecm_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 = pdn_con_req . esm_info_transfer_flag_present ;
//Initialize E-RABs
for ( uint i = 0 ; i < MAX_ERABS_PER_UE ; i + + )
{
ecm_ctx - > erabs_ctx [ i ] . state = ERAB_DEACTIVATED ;
ecm_ctx - > erabs_ctx [ i ] . erab_id = i ;
}
//Store context based on MME UE S1AP id
m_s1ap - > add_ue_ctx_to_mme_ue_s1ap_id_map ( ue_ctx ) ;
m_s1ap - > add_ue_to_enb_set ( enb_sri - > sinfo_assoc_id , ecm_ctx - > mme_ue_s1ap_id ) ;
//NAS integrity failed. Re-start authentication process.
m_s1ap_log - > console ( " GUTI Attach request NAS integrity failed. \n " ) ;
m_s1ap_log - > console ( " RE-starting authentication procedure. \n " ) ;
uint8_t autn [ 16 ] ;
uint8_t rand [ 16 ] ;
//Get Authentication Vectors from HSS
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 " , emm_ctx - > imsi ) ;
m_s1ap_log - > info ( " User not found. IMSI %015lu \n " , emm_ctx - > imsi ) ;
return false ;
}
//Restarting security context. Reseting eKSI to 0.
emm_ctx - > security_ctxt . eksi = 0 ;
pack_authentication_request ( reply_buffer , ecm_ctx - > enb_ue_s1ap_id , ecm_ctx - > mme_ue_s1ap_id , emm_ctx - > security_ctxt . eksi , autn , rand ) ;
//Send reply to eNB
* reply_flag = true ;
m_s1ap_log - > info ( " Downlink NAS: Sent Authentication Request \n " ) ;
m_s1ap_log - > console ( " Downlink NAS: Sent Authentication Request \n " ) ;
return true ;
}
}
else
{
m_s1ap_log - > error ( " Found M-TMSI but could not find UE context \n " ) ;
m_s1ap_log - > console ( " Error: Found M-TMSI but could not find UE context \n " ) ;
return false ;
}
}
return true ;
}
bool
nas : : handle_nas_service_request ( uint32_t m_tmsi ,
uint32_t enb_ue_s1ap_id ,
srslte : : byte_buffer_t * nas_msg ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
bool mac_valid = false ;
LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT service_req ;
LIBLTE_ERROR_ENUM err = liblte_mme_unpack_service_request_msg ( ( LIBLTE_BYTE_MSG_STRUCT * ) nas_msg , & service_req ) ;
if ( err ! = LIBLTE_SUCCESS )
{
m_s1ap_log - > error ( " Could not unpack service request \n " ) ;
return false ;
}
std : : map < uint32_t , uint64_t > : : iterator it = m_s1ap - > m_tmsi_to_imsi . find ( m_tmsi ) ;
if ( it = = m_s1ap - > m_tmsi_to_imsi . end ( ) )
{
m_s1ap_log - > console ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
m_s1ap_log - > error ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
pack_service_reject ( reply_buffer , LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED , enb_ue_s1ap_id ) ;
* reply_flag = true ;
return true ;
}
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 " ) ;
pack_service_reject ( reply_buffer , LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED , enb_ue_s1ap_id ) ;
* 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 " ) ;
if ( ecm_ctx - > state = = ECM_STATE_CONNECTED )
{
m_s1ap_log - > error ( " Service Request -- User is ECM CONNECTED \n " ) ;
//Release previous context
m_s1ap_log - > info ( " Service Request -- Releasing previouse ECM context. eNB S1AP Id %d, MME UE S1AP Id %d \n " , ecm_ctx - > enb_ue_s1ap_id , ecm_ctx - > mme_ue_s1ap_id ) ;
m_s1ap - > m_s1ap_ctx_mngmt_proc - > send_ue_context_release_command ( ecm_ctx , reply_buffer ) ;
m_s1ap - > release_ue_ecm_ctx ( ecm_ctx - > mme_ue_s1ap_id ) ;
}
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 ;
//Get UE IP, and uplink F-TEID
if ( emm_ctx - > ue_ip . s_addr = = 0 ) {
m_s1ap_log - > error ( " UE has no valid IP assigned upon reception of service request " ) ;
}
m_s1ap_log - > console ( " UE previously assigned IP: %s " , inet_ntoa ( emm_ctx - > ue_ip ) ) ;
//Re-generate K_eNB
srslte : : 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 ( " Generating KeNB with UL NAS COUNT: %d \n " , emm_ctx - > security_ctxt . ul_nas_count ) ;
m_s1ap_log - > info_hex ( emm_ctx - > security_ctxt . k_enb , 32 , " Key eNodeB (k_enb) \n " ) ;
m_s1ap_log - > console ( " UE Ctr TEID %d \n " , emm_ctx - > sgw_ctrl_fteid . teid ) ;
//Save UE ctx to MME UE S1AP id
m_s1ap - > add_ue_ctx_to_mme_ue_s1ap_id_map ( ue_ctx ) ;
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 ( " Service Request -- Short MAC invalid. Ignoring service request \n " ) ;
m_s1ap_log - > console ( " Service Request -- Short MAC invalid. Ignoring service request \n " ) ;
}
return true ;
}
bool
nas : : handle_nas_detach_request ( uint32_t m_tmsi ,
uint32_t enb_ue_s1ap_id ,
srslte : : byte_buffer_t * nas_msg ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
bool mac_valid = false ;
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_req ;
LIBLTE_ERROR_ENUM err = liblte_mme_unpack_detach_request_msg ( ( LIBLTE_BYTE_MSG_STRUCT * ) nas_msg , & detach_req ) ;
if ( err ! = LIBLTE_SUCCESS )
{
m_s1ap_log - > error ( " Could not unpack detach request \n " ) ;
return false ;
}
std : : map < uint32_t , uint64_t > : : iterator it = m_s1ap - > m_tmsi_to_imsi . find ( m_tmsi ) ;
if ( it = = m_s1ap - > m_tmsi_to_imsi . end ( ) )
{
m_s1ap_log - > console ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
m_s1ap_log - > error ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
return true ;
}
ue_ctx_t * ue_ctx = m_s1ap - > find_ue_ctx_from_imsi ( it - > second ) ;
ue_emm_ctx_t * emm_ctx = & ue_ctx - > emm_ctx ;
ue_ecm_ctx_t * ecm_ctx = & ue_ctx - > ecm_ctx ;
m_mme_gtpc - > send_delete_session_request ( emm_ctx - > imsi ) ;
emm_ctx - > state = EMM_STATE_DEREGISTERED ;
emm_ctx - > security_ctxt . ul_nas_count + + ;
m_s1ap_log - > console ( " Received. M-TMSI 0x%x \n " , m_tmsi ) ;
//Received detach request as an initial UE message
//eNB created new ECM context to send the detach request; this needs to be cleared.
ecm_ctx - > mme_ue_s1ap_id = m_s1ap - > get_next_mme_ue_s1ap_id ( ) ;
ecm_ctx - > enb_ue_s1ap_id = enb_ue_s1ap_id ;
m_s1ap - > m_s1ap_ctx_mngmt_proc - > send_ue_context_release_command ( ecm_ctx , reply_buffer ) ;
return true ;
}
bool
nas : : handle_nas_tracking_area_update_request ( uint32_t m_tmsi ,
uint32_t enb_ue_s1ap_id ,
srslte : : byte_buffer_t * nas_msg ,
srslte : : byte_buffer_t * reply_buffer ,
bool * reply_flag ,
struct sctp_sndrcvinfo * enb_sri )
{
m_s1ap_log - > console ( " Warning: Tracking area update requests are not handled yet. \n " ) ;
m_s1ap_log - > warning ( " Tracking area update requests are not handled yet. \n " ) ;
std : : map < uint32_t , uint64_t > : : iterator it = m_s1ap - > m_tmsi_to_imsi . find ( m_tmsi ) ;
if ( it = = m_s1ap - > m_tmsi_to_imsi . end ( ) )
{
m_s1ap_log - > console ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
m_s1ap_log - > error ( " Could not find IMSI from M-TMSI. M-TMSI 0x%x \n " , m_tmsi ) ;
return true ;
}
ue_ctx_t * ue_ctx = m_s1ap - > find_ue_ctx_from_imsi ( it - > second ) ;
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 + + ; //Increment the NAS count, not to break the security ctx
return true ;
}
/*
/*
*
*
@ -680,7 +53,7 @@ nas::handle_nas_tracking_area_update_request(uint32_t m_tmsi,
*
*
*/
*/
//FIXME re-factor to reduce code duplication
//FIXME re-factor to reduce code duplication for messages that can be both initiating messages and uplink NAS messages
bool
bool
nas : : handle_nas_detach_request ( srslte : : byte_buffer_t * nas_msg , ue_ctx_t * ue_ctx , srslte : : byte_buffer_t * reply_msg , bool * reply_flag )
nas : : handle_nas_detach_request ( srslte : : byte_buffer_t * nas_msg , ue_ctx_t * ue_ctx , srslte : : byte_buffer_t * reply_msg , bool * reply_flag )
{
{