diff --git a/lib/include/srslte/asn1/gtpc.h b/lib/include/srslte/asn1/gtpc.h index 3c2a3247f..5fc958e63 100644 --- a/lib/include/srslte/asn1/gtpc.h +++ b/lib/include/srslte/asn1/gtpc.h @@ -52,15 +52,14 @@ const uint8_t GTPC_V2 = 2; * n+2 | Sequence | * n+3 | Spare | ***************************************************************************/ -typedef struct gtpc_header -{ - uint8_t version; - bool piggyback; - bool teid_present; - uint8_t type; +typedef struct gtpc_header { + uint8_t version; + bool piggyback; + bool teid_present; + uint8_t type; uint64_t teid; uint64_t sequence; -}gtpc_header_t; +} gtpc_header_t; /**************************************************************************** * GTP-C v2 Payload @@ -68,17 +67,16 @@ typedef struct gtpc_header * * Union that hold the different structures for the possible message types. ***************************************************************************/ -typedef union gtpc_msg_choice -{ - struct gtpc_create_session_request create_session_request; - struct gtpc_create_session_response create_session_response; - struct gtpc_modify_bearer_request modify_bearer_request; - struct gtpc_modify_bearer_response modify_bearer_response; - struct gtpc_release_access_bearers_request release_access_bearers_request; +typedef union gtpc_msg_choice { + struct gtpc_create_session_request create_session_request; + struct gtpc_create_session_response create_session_response; + struct gtpc_modify_bearer_request modify_bearer_request; + struct gtpc_modify_bearer_response modify_bearer_response; + struct gtpc_release_access_bearers_request release_access_bearers_request; struct gtpc_release_access_bearers_response release_access_bearers_response; - struct gtpc_delete_session_request delete_session_request; - struct gtpc_delete_session_response delete_session_response; -}gtpc_msg_choice_t; + struct gtpc_delete_session_request delete_session_request; + struct gtpc_delete_session_response delete_session_response; +} gtpc_msg_choice_t; /**************************************************************************** * GTP-C v2 Message @@ -88,10 +86,9 @@ typedef union gtpc_msg_choice * of one GTP-C header and one union of structures, which can hold * all the possible GTP-C messages ***************************************************************************/ -typedef struct gtpc_pdu -{ - struct gtpc_header header; +typedef struct gtpc_pdu { + struct gtpc_header header; union gtpc_msg_choice choice; -}gtpc_pdu_t; -}//namespace +} gtpc_pdu_t; +} // namespace srslte #endif // SRSLTE_GTPC_H diff --git a/lib/include/srslte/asn1/gtpc_msg.h b/lib/include/srslte/asn1/gtpc_msg.h index 42b6ad3cf..9eebb5afa 100644 --- a/lib/include/srslte/asn1/gtpc_msg.h +++ b/lib/include/srslte/asn1/gtpc_msg.h @@ -26,121 +26,121 @@ #include "srslte/asn1/gtpc_ies.h" -namespace srslte{ +namespace srslte { /**************************************************************** * * GTP-C Message Types - * Ref: TS 29.274 v10.14.0 Table 6.1-1 + * Ref: TS 29.274 v10.14.0 Table 6.1-1 * ****************************************************************/ -const uint8_t GTPC_MSG_TYPE_RESERVED = 0; -const uint8_t GTPC_MSG_TYPE_ECHO_REQUEST = 1; -const uint8_t GTPC_MSG_TYPE_ECHO_RESPONSE = 2; +const uint8_t GTPC_MSG_TYPE_RESERVED = 0; +const uint8_t GTPC_MSG_TYPE_ECHO_REQUEST = 1; +const uint8_t GTPC_MSG_TYPE_ECHO_RESPONSE = 2; const uint8_t GTPC_MSG_TYPE_VERSION_SUPPORT = 3; -//4-24 Reserved for S101 -//25-31 Reserved for Sv interface -//SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_REQUEST = 32; +// 4-24 Reserved for S101 +// 25-31 Reserved for Sv interface +// SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_REQUEST = 32; const uint8_t GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE = 33; -const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_REQUEST = 36; +const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_REQUEST = 36; const uint8_t GTPC_MSG_TYPE_DELETE_SESSION_RESPONSE = 37; -//SGSN/MME to PGW (S4/S11, S5/S8) -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST = 34; -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE = 35; -const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_REQUEST = 38; +// SGSN/MME to PGW (S4/S11, S5/S8) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST = 34; +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE = 35; +const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_REQUEST = 38; const uint8_t GTPC_MSG_TYPE_CHANGE_NOTIFICATION_RESPONSE = 39; -//40 - 63 for future use +// 40 - 63 for future use const uint8_t GTPC_MSG_TYPE_RESUME_NOTIFICATION = 164; -const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; -//Messages without explicit response -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) -const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) -const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) -//74-94 For future use -//P-GW to SGSN/MME/ePDG -const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; +const uint8_t GTPC_MSG_TYPE_RESUME_ACKNOWLEDGE = 165; +// Messages without explicit response +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_COMMAND = 64; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_MODIFY_BEARER_FAILURE_INDICATION = 65; //(PGW to MME/SGSN/ePDG – S5/S8, S11/S4, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_COMMAND = 66; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_FAILURE_INDICATION = 67; //(PGW to MME/SGSN – S5/S8, S11/S4)) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_COMMAND = 68; //(MME/SGSN to PGW – S11/S4, S5/S8) +const uint8_t GTPC_MSG_TYPE_BEARER_RESOURCE_FAILURE_INDICATION = 69; //(PGW to MME/SGSN – S5/S8, S11/S4) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION = 70; //(SGSN/MME to SGW – S4/S11) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_ACTIVATION = 71; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_TRACE_SESSION_DEACTIVATION = 72; //(MME/SGSN/ePDG to PGW – S11/S4, S5/S8, S2b) +const uint8_t GTPC_MSG_TYPE_STOP_PAGING_INDICATION = 73; //(SGW to MME/SGSN – S11/S4) +// 74-94 For future use +// P-GW to SGSN/MME/ePDG +const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_REQUEST = 95; const uint8_t GTPC_MSG_TYPE_CREATE_BEARER_RESPONSE = 96; -const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_REQUEST = 97; +const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_REQUEST = 97; const uint8_t GTPC_MSG_TYPE_UPDATE_BEARER_RESPONSE = 98; -const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_REQUEST = 99; +const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_REQUEST = 99; const uint8_t GTPC_MSG_TYPE_DELETE_BEARER_RESPONSE = 100; -//PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to ePDG, ePDG to PGW (S5/S8, S11, S2b) -const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_REQUEST = 101; +// PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to ePDG, ePDG to PGW (S5/S8, S11, S2b) +const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_REQUEST = 101; const uint8_t GTPC_MSG_TYPE_DELETE_PDN_CONNECTION_SET_RESPONSE = 102; -//103-127 For future use -//MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN (S3/S10/S16) -const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_REQUEST = 128; -const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_RESPONSE = 129; -const uint8_t GTPC_MSG_TYPE_CONTEXT_REQUEST = 130; -const uint8_t GTPC_MSG_TYPE_CONTEXT_RESPONSE = 131; -const uint8_t GTPC_MSG_TYPE_CONTEXT_ACKNOWLEDGE = 132; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_REQUEST = 133; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_RESPONSE = 134; +// 103-127 For future use +// MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN (S3/S10/S16) +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_REQUEST = 128; +const uint8_t GTPC_MSG_TYPE_IDENTIFICATION_RESPONSE = 129; +const uint8_t GTPC_MSG_TYPE_CONTEXT_REQUEST = 130; +const uint8_t GTPC_MSG_TYPE_CONTEXT_RESPONSE = 131; +const uint8_t GTPC_MSG_TYPE_CONTEXT_ACKNOWLEDGE = 132; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_REQUEST = 133; +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_RESPONSE = 134; const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_NOTIFICATION = 135; -const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_ACKNOWLEDGE = 136; -const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_NOTIFICATION = 137; -const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_ACKNOWLEDGE = 138; -const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_REQUEST = 139; -const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_RESPONSE = 140; -const uint8_t GTPC_MSG_TYPE_CONFIGURATION_TRANSFER_TUNNEL = 141; -//142 - 148 For future use +const uint8_t GTPC_MSG_TYPE_FORWARD_RELOCATION_COMPLETE_ACKNOWLEDGE = 136; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_NOTIFICATION = 137; +const uint8_t GTPC_MSG_TYPE_FORWARD_ACCESS_CONTEXT_ACKNOWLEDGE = 138; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_REQUEST = 139; +const uint8_t GTPC_MSG_TYPE_RELOCATION_CANCEL_RESPONSE = 140; +const uint8_t GTPC_MSG_TYPE_CONFIGURATION_TRANSFER_TUNNEL = 141; +// 142 - 148 For future use const uint8_t GTPC_MSG_TYPE_RAN_INFORMATION_RELAY = 152; -//SGSN to MME, MME to SGSN (S3) -const uint8_t GTPC_MSG_TYPE_DETACH_NOTIFICATION = 149; -const uint8_t GTPC_MSG_TYPE_DETACH_ACKNOWLEDGE = 150; -const uint8_t GTPC_MSG_TYPE_CS_PAGING_INDICATION = 151; -const uint8_t GTPC_MSG_TYPE_ALERT_MME_NOTIFICATION = 153; -const uint8_t GTPC_MSG_TYPE_ALERT_MME_ACKNOWLEDGE = 154; +// SGSN to MME, MME to SGSN (S3) +const uint8_t GTPC_MSG_TYPE_DETACH_NOTIFICATION = 149; +const uint8_t GTPC_MSG_TYPE_DETACH_ACKNOWLEDGE = 150; +const uint8_t GTPC_MSG_TYPE_CS_PAGING_INDICATION = 151; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_NOTIFICATION = 153; +const uint8_t GTPC_MSG_TYPE_ALERT_MME_ACKNOWLEDGE = 154; const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_NOTIFICATION = 155; -const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; -//157 - 159 For future use -//GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_UE_ACTIVITY_ACKNOWLEDGE = 156; +// 157 - 159 For future use +// GSN/MME to SGW, SGSN to MME (S4/S11/S3) SGSN to SGSN (S16), SGW to PGW (S5/S8) const uint8_t GTPC_MSG_TYPE_SUSPEND_NOTIFICATION = 162; -const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; -//SGSN/MME to SGW (S4/S11) const uint8_t GTPC_IE_TYPE_ -const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; -const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; -const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; +const uint8_t GTPC_MSG_TYPE_SUSPEND_ACKNOWLEDGE = 163; +// SGSN/MME to SGW (S4/S11) const uint8_t GTPC_IE_TYPE_ +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_REQUEST = 160; +const uint8_t GTPC_MSG_TYPE_CREATE_FORWARDING_TUNNEL_RESPONSE = 161; +const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 166; const uint8_t GTPC_MSG_TYPE_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 167; -const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 168; +const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST = 168; const uint8_t GTPC_MSG_TYPE_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE = 169; -const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST = 170; -const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_RESPONSE = 171; -//172 - 175 For future use -//SGW to SGSN/MME (S4/S11) -const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION = 176; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST = 170; +const uint8_t GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_RESPONSE = 171; +// 172 - 175 For future use +// SGW to SGSN/MME (S4/S11) +const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION = 176; const uint8_t GTPC_MSG_TYPE_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE = 177; -const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION = 179; -const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE = 180; -//SGW to SGSN (S4) -//178 Reserved. Allocated in earlier version of the specification. -//181 -189 For future use -//SGW to PGW, PGW to SGW (S5/S8) -const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_REQUEST = 200; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION = 179; +const uint8_t GTPC_MSG_TYPE_PGW_RESTART_NOTIFICATION_ACKNOWLEDGE = 180; +// SGW to SGSN (S4) +// 178 Reserved. Allocated in earlier version of the specification. +// 181 -189 For future use +// SGW to PGW, PGW to SGW (S5/S8) +const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_REQUEST = 200; const uint8_t GTPC_MSG_TYPE_UPDATE_PDN_CONNECTION_SET_RESPONSE = 201; -//For future use -//MME to SGW (S11) -const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_REQUEST = 211; +// For future use +// MME to SGW (S11) +const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_REQUEST = 211; const uint8_t GTPC_MSG_TYPE_MODIFY_ACCESS_BEARERS_RESPONSE = 212; -//For future use -//MBMS GW to MME/SGSN (Sm/Sn) -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_REQUEST = 231; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_RESPONSE = 232; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_REQUEST = 233; +// For future use +// MBMS GW to MME/SGSN (Sm/Sn) +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_REQUEST = 231; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_START_RESPONSE = 232; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_REQUEST = 233; const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_UPDATE_RESPONSE = 234; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_REQUEST = 235; -const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; -//For future use -//Other -//240 - 255 For future use +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_REQUEST = 235; +const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; +// For future use +// Other +// 240 - 255 For future use /**************************************************************************** * @@ -148,91 +148,89 @@ const uint8_t GTPC_MSG_TYPE_MBMS_SESSION_STOP_RESPONSE = 236; * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.1-1 * ***************************************************************************/ +struct gtpc_create_session_request { + bool imsi_present; + uint64_t imsi; // C + // bool msidn_present; + // uint64_t msisdn; // C + // bool mei_present; + // uint64_t mei; // C/CO + // bool user_location_info_present; + // struct gtpc_user_location_info_ie uli; // C/CO + // bool serving_network_present; + // struct gtpc_serving_network_ie serving_network; // C/CO -struct gtpc_create_session_request -{ - bool imsi_present; - uint64_t imsi; // C - //bool msidn_present; - //uint64_t msisdn; // C - //bool mei_present; - //uint64_t mei; // C/CO - //bool user_location_info_present; - //struct gtpc_user_location_info_ie uli; // C/CO - //bool serving_network_present; - //struct gtpc_serving_network_ie serving_network; // C/CO + enum gtpc_rat_type rat_type; // M + // bool indication_flags_present; + // struct indication_flags_ indication_flags; // C - enum gtpc_rat_type rat_type; // M - //bool indication_flags_present; - //struct indication_flags_ indication_flags; // C + struct gtpc_f_teid_ie sender_f_teid; // M + bool pgw_addr_present; + struct gtpc_f_teid_ie pgw_addr; // C - struct gtpc_f_teid_ie sender_f_teid; // M - bool pgw_addr_present; - struct gtpc_f_teid_ie pgw_addr; // C + char apn[MAX_APN_LENGTH]; // M + // bool selection_mode_present; + // enum selection_mode_ selection_mode; // C/CO + // bool pdn_type_present; + // enum gtpc_pdn_type pdn_type; // C + // bool pdn_addr_alloc_present; + // struct pdn_addr_alloc_ pdn_addr_alloc; // C/CO + // bool max_apn_restriction_present; + // enum apn_restriction_ max_apn_restriction; // C + // bool apn_ambr_present; + // struct ambr_ apn_ambr; // C + // bool linked_eps_bearer_id_present; + // uint8_t linked_eps_bearer_id; // C + // bool pco_present; + // uint8_t pco; // C - char apn[MAX_APN_LENGTH]; // M - //bool selection_mode_present; - //enum selection_mode_ selection_mode; // C/CO - //bool pdn_type_present; - //enum gtpc_pdn_type pdn_type; // C - //bool pdn_addr_alloc_present; - //struct pdn_addr_alloc_ pdn_addr_alloc; // C/CO - //bool max_apn_restriction_present; - //enum apn_restriction_ max_apn_restriction; // C - //bool apn_ambr_present; - //struct ambr_ apn_ambr; // C - //bool linked_eps_bearer_id_present; - //uint8_t linked_eps_bearer_id; // C - //bool pco_present; - //uint8_t pco; // C - - struct gtpc_bearer_context_created_ie //see TS 29.274 v10.14.0 Table 7.2.1-2 + struct gtpc_bearer_context_created_ie // see TS 29.274 v10.14.0 Table 7.2.1-2 { - uint8_t ebi; - bool tft_present; - bool s1_u_enodeb_f_teid_present; - struct gtpc_f_teid_ie s1_u_enodeb_f_teid; - bool s4_u_sgsn_f_teid_present; - struct gtpc_f_teid_ie s4_u_sgsn_f_teid; - bool s5_s8_u_sgw_f_teid_present; - struct gtpc_f_teid_ie s5_s8_u_sgw_f_teid; - bool s5_s8_u_pgw_f_teid_present; - struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; - bool s12_rnc_f_teid_present; - struct gtpc_f_teid_ie s12_rnc_f_teid; - bool s2b_u_epdg_f_teid_present; - struct gtpc_f_teid_ie s2b_u_epdg_f_teid; - struct gtpc_bearer_qos_ie bearer_qos; // M - } eps_bearer_context_created; // M - //bool bearer_context_deleted_present; - //struct bearer_context_ bearer_context_deleted; // C - //bool trace_information_present; - //struct trace_infromation_ trace_information; // C - //bool recovery_present - //uint8_t recovery; // C - //bool mme_fq_csid_present; - //struct fq_csid_ mme_fq_csid; // C - //bool sgw_fq_csid_present; - //struct fq_csid_ sgw_fq_csid; // C - //bool epdg_fq_csid_present; - //struct fq_csid_ epdg_fq_csid; // C - //bool ue_time_zone_present; - //struct ue_time_zone_ ue_time_zone; // CO - //bool uci_present; - //struct uci_ uci; // CO - //bool charging_caracteristics_present; - //enum charging_characteristics_ charging_caracteristics; // O - //bool mme_ldn_present; - //uint8_t mme_ldn[LDN_MAX_SIZE]; // O - //bool sgw_ldn_present; - //uint8_t sgw_ldn[LDN_MAX_SIZE]; // O - //bool epgd_ldn_present; - //uint8_t epdg_ldn[LDN_MAX_SIZE]; // O - //bool signaling_priority_indication; - //enum signalling_priority_indication_ spi; // CO - //bool acpo_present; - //uint8_t apco; // CO - //bool ext; // O + uint8_t ebi; + bool tft_present; + bool s1_u_enodeb_f_teid_present; + struct gtpc_f_teid_ie s1_u_enodeb_f_teid; + bool s4_u_sgsn_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgsn_f_teid; + bool s5_s8_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_sgw_f_teid; + bool s5_s8_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; + bool s12_rnc_f_teid_present; + struct gtpc_f_teid_ie s12_rnc_f_teid; + bool s2b_u_epdg_f_teid_present; + struct gtpc_f_teid_ie s2b_u_epdg_f_teid; + struct gtpc_bearer_qos_ie bearer_qos; + } eps_bearer_context_created; + // bool bearer_context_deleted_present; + // struct bearer_context_ bearer_context_deleted; // C + // bool trace_information_present; + // struct trace_infromation_ trace_information; // C + // bool recovery_present + // uint8_t recovery; // C + // bool mme_fq_csid_present; + // struct fq_csid_ mme_fq_csid; // C + // bool sgw_fq_csid_present; + // struct fq_csid_ sgw_fq_csid; // C + // bool epdg_fq_csid_present; + // struct fq_csid_ epdg_fq_csid; // C + // bool ue_time_zone_present; + // struct ue_time_zone_ ue_time_zone; // CO + // bool uci_present; + // struct uci_ uci; // CO + // bool charging_caracteristics_present; + // enum charging_characteristics_ charging_caracteristics; // O + // bool mme_ldn_present; + // uint8_t mme_ldn[LDN_MAX_SIZE]; // O + // bool sgw_ldn_present; + // uint8_t sgw_ldn[LDN_MAX_SIZE]; // O + // bool epgd_ldn_present; + // uint8_t epdg_ldn[LDN_MAX_SIZE]; // O + // bool signaling_priority_indication; + // enum signalling_priority_indication_ spi; // CO + // bool acpo_present; + // uint8_t apco; // CO + // bool ext; // O }; /**************************************************************************** @@ -241,58 +239,55 @@ struct gtpc_create_session_request * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.2-1 * ***************************************************************************/ -struct gtpc_create_session_response -{ - struct gtpc_cause_ie cause; //M - //Change Reporting Action //C - //CSG Information Reporting Action //CO - bool sender_f_teid_present; - struct gtpc_f_teid_ie sender_f_teid; //C - //PGW S5/S8/S2b F-TEID //C - bool paa_present; - struct gtpc_pdn_address_allocation_ie paa; //C - //apn_restriction - //apn_ambr - //linked_eps_bearer_id - //pco - struct gtpc_bearer_context_created_ie - { - uint8_t ebi; - gtpc_cause_ie cause; - bool s1_u_sgw_f_teid_present; - struct gtpc_f_teid_ie s1_u_sgw_f_teid; - bool s4_u_sgw_f_teid_present; - struct gtpc_f_teid_ie s4_u_sgw_f_teid; - bool s5_s8_u_pgw_f_teid_present; - struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; - bool s12_sgw_f_teid_present; - struct gtpc_f_teid_ie s12_sgw_f_teid; - bool s2b_u_pgw_f_teid_present; - struct gtpc_f_teid_ie s2b_u_pgw_f_teid; - bool bearer_level_qos_present; +struct gtpc_create_session_response { + struct gtpc_cause_ie cause; // M + // Change Reporting Action //C + // CSG Information Reporting Action //CO + bool sender_f_teid_present; + struct gtpc_f_teid_ie sender_f_teid; // C + // PGW S5/S8/S2b F-TEID //C + bool paa_present; + struct gtpc_pdn_address_allocation_ie paa; // C + // apn_restriction + // apn_ambr + // linked_eps_bearer_id + // pco + struct gtpc_bearer_context_created_ie { + uint8_t ebi; + gtpc_cause_ie cause; + bool s1_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s1_u_sgw_f_teid; + bool s4_u_sgw_f_teid_present; + struct gtpc_f_teid_ie s4_u_sgw_f_teid; + bool s5_s8_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s5_s8_u_pgw_f_teid; + bool s12_sgw_f_teid_present; + struct gtpc_f_teid_ie s12_sgw_f_teid; + bool s2b_u_pgw_f_teid_present; + struct gtpc_f_teid_ie s2b_u_pgw_f_teid; + bool bearer_level_qos_present; struct gtpc_bearer_qos_ie bearer_level_qos; - //charging_id_present - //charging_id - //bearer_flags_present - //bearer_flags - } eps_bearer_context_created; //M + // charging_id_present + // charging_id + // bearer_flags_present + // bearer_flags + } eps_bearer_context_created; // M /* struct gtpc_bearer_context_removed_ie { uint8_t ebi; - // } bearer_context_removed; //C */ - //recovery; //C - //charging_gateway_name; //C - //charging_gateway_address; //C - //PGW-FQ-CSID //C - //SGW-FQ-CSID //C - //SGW LDN //O - //PGW LDN //O - //PGW Back-Off Time //O - //acpo //CO + // recovery; //C + // charging_gateway_name; //C + // charging_gateway_address; //C + // PGW-FQ-CSID //C + // SGW-FQ-CSID //C + // SGW LDN //O + // PGW LDN //O + // PGW Back-Off Time //O + // acpo //CO }; /**************************************************************************** @@ -301,38 +296,35 @@ struct gtpc_create_session_response * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.7-1, 7.2.7-2 and 7.2.7-3 * ***************************************************************************/ - -struct gtpc_modify_bearer_request -{ - //ME Identity (MEI)//C - //User Location Information (ULI)//C - //Serving Network //CO - //RAT Type //C/CO - //Indication Flags - //Sender F-TEID for Control Plane - //APN-AMBR - //Delay Downlink Packet Notification Request - struct gtpc_bearer_context_modified_ie - { - uint8_t ebi; - gtpc_cause_ie cause; - bool s1_u_enb_f_teid_present; +struct gtpc_modify_bearer_request { + // ME Identity (MEI)//C + // User Location Information (ULI)//C + // Serving Network //CO + // RAT Type //C/CO + // Indication Flags + // Sender F-TEID for Control Plane + // APN-AMBR + // Delay Downlink Packet Notification Request + struct gtpc_bearer_context_modified_ie { + uint8_t ebi; + gtpc_cause_ie cause; + bool s1_u_enb_f_teid_present; struct gtpc_f_teid_ie s1_u_enb_f_teid; - bool s5_s8_u_sgw_f_teid_present; + bool s5_s8_u_sgw_f_teid_present; struct gtpc_f_teid_ie s5_s8_u_sgw_f_teid; - bool s12_rnc_f_teid_present; + bool s12_rnc_f_teid_present; struct gtpc_f_teid_ie s12_rnc_f_teid; - bool s4_u_sgsn_f_teid_present; + bool s4_u_sgsn_f_teid_present; struct gtpc_f_teid_ie s4_u_sgsn_f_teid; } eps_bearer_context_to_modify; - //Bearer Contexts to be removed - //Recovery - //UE Time Zone - //MME-FQ-CSID - //SGW-FQ-CSID - //User CSG Information (UCI) - //MME/S4-SGSN LDN - //SGW LDN + // Bearer Contexts to be removed + // Recovery + // UE Time Zone + // MME-FQ-CSID + // SGW-FQ-CSID + // User CSG Information (UCI) + // MME/S4-SGSN LDN + // SGW LDN }; /**************************************************************************** @@ -341,41 +333,38 @@ struct gtpc_modify_bearer_request * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.8-1 * ***************************************************************************/ - -struct gtpc_modify_bearer_response -{ +struct gtpc_modify_bearer_response { struct gtpc_cause_ie cause; - //MSISDN - //Linked EPS Bearer ID - //APN-AMBR - //APN Restriction - //Protocol Configuration Options + // MSISDN + // Linked EPS Bearer ID + // APN-AMBR + // APN Restriction + // Protocol Configuration Options - struct gtpc_bearer_context_modified_ie - { - uint8_t ebi; - struct gtpc_cause_ie cause; - bool s1_u_sgw_f_teid_present; + struct gtpc_bearer_context_modified_ie { + uint8_t ebi; + struct gtpc_cause_ie cause; + bool s1_u_sgw_f_teid_present; struct gtpc_f_teid_ie s1_u_sgw_f_teid; - bool s12_sgw_f_teid_present; + bool s12_sgw_f_teid_present; struct gtpc_f_teid_ie s12_sgw_f_teid; - bool s4_u_sgw_f_teid_present; + bool s4_u_sgw_f_teid_present; struct gtpc_f_teid_ie s4_u_sgw_f_teid; - //charging id - //bearer flags + // charging id + // bearer flags } eps_bearer_context_modified; - //Bearer Contexts marked for removal - //Change Reporting action - //CSG information reporting action - //Charging gateway name - //charging gateway address - //P-GW FQ-CSID - //S-GW FQ-CSID - //Recovery - //S-GW LDN - //P-GW LDN - //indication Flags - //ext + // Bearer Contexts marked for removal + // Change Reporting action + // CSG information reporting action + // Charging gateway name + // charging gateway address + // P-GW FQ-CSID + // S-GW FQ-CSID + // Recovery + // S-GW LDN + // P-GW LDN + // indication Flags + // ext }; /**************************************************************************** @@ -384,16 +373,14 @@ struct gtpc_modify_bearer_response * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.9.1-1 * ***************************************************************************/ - -struct gtpc_delete_session_request -{ +struct gtpc_delete_session_request { struct gtpc_cause_ie cause; - //Linked EPS Bearer ID - //User Location Information - //Indication Flags - //Protocol Configuration Options - //Originating Node - //Private extension + // Linked EPS Bearer ID + // User Location Information + // Indication Flags + // Protocol Configuration Options + // Originating Node + // Private extension }; /**************************************************************************** @@ -402,13 +389,11 @@ struct gtpc_delete_session_request * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.10.1-1 * ***************************************************************************/ - -struct gtpc_delete_session_response -{ +struct gtpc_delete_session_response { struct gtpc_cause_ie cause; - //Recovery - //Protocol Configuration Options - //Private extension + // Recovery + // Protocol Configuration Options + // Private extension }; /**************************************************************************** @@ -417,30 +402,25 @@ struct gtpc_delete_session_response * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.21.1-1 * ***************************************************************************/ -struct gtpc_release_access_bearers_request -{ +struct gtpc_release_access_bearers_request { bool list_of_rabs_present; - //Linked EPS Bearer ID + // Linked EPS Bearer ID bool originating_node_present; - //Indication Flags - //Private Extension + // Indication Flags + // Private Extension }; - /**************************************************************************** - * - * GTP-C v2 Delete Session Response - * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.22.1-1 - * - ***************************************************************************/ - - struct gtpc_release_access_bearers_response - { - struct gtpc_cause_ie cause; - //Recovery - //Private extension - }; - - +/**************************************************************************** + * + * GTP-C v2 Delete Session Response + * Ref: 3GPP TS 29.274 v10.14.0 Table 7.2.22.1-1 + * + ***************************************************************************/ +struct gtpc_release_access_bearers_response { + struct gtpc_cause_ie cause; + // Recovery + // Private extension +}; -} //namespace +} // namespace srslte #endif // SRSLTE_GTPC_MSG_H diff --git a/lib/include/srslte/interfaces/epc_interfaces.h b/lib/include/srslte/interfaces/epc_interfaces.h index 6655c02a1..157d676fd 100644 --- a/lib/include/srslte/interfaces/epc_interfaces.h +++ b/lib/include/srslte/interfaces/epc_interfaces.h @@ -27,48 +27,50 @@ namespace srsepc { class nas; -//NAS -> GTP-C -class gtpc_interface_nas +/****************** + * MME Interfaces * + ******************/ +class gtpc_interface_nas // NAS -> GTP-C { public: - virtual bool send_create_session_request(uint64_t imsi) = 0; - virtual bool send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, struct srslte::gtpc_f_teid_ie *enb_fteid) = 0; - virtual bool send_delete_session_request(uint64_t imsi) = 0; + virtual bool send_create_session_request(uint64_t imsi) = 0; + virtual bool send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, srslte::gtp_fteid_t* enb_fteid) = 0; + virtual bool send_delete_session_request(uint64_t imsi) = 0; }; -//GTP-C -> S1AP -class s1ap_interface_gtpc +class s1ap_interface_gtpc // GTP-C -> S1AP { public: virtual bool send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) = 0; }; -//NAS -> S1AP -class s1ap_interface_nas +class s1ap_interface_nas // NAS -> S1AP { public: - virtual uint32_t allocate_m_tmsi(uint64_t imsi) = 0; - virtual uint32_t get_next_mme_ue_s1ap_id() = 0; - virtual bool add_nas_ctx_to_imsi_map(nas *nas_ctx) = 0; - virtual bool add_nas_ctx_to_mme_ue_s1ap_id_map(nas *nas_ctx) = 0; - virtual bool add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id) = 0; - virtual bool release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) = 0; - virtual bool delete_ue_ctx(uint64_t imsi) = 0; - virtual uint64_t find_imsi_from_m_tmsi(uint32_t m_tmsi) = 0; - virtual nas* find_nas_ctx_from_imsi(uint64_t imsi) = 0; + virtual uint32_t allocate_m_tmsi(uint64_t imsi) = 0; + virtual uint32_t get_next_mme_ue_s1ap_id() = 0; + virtual bool add_nas_ctx_to_imsi_map(nas* nas_ctx) = 0; + virtual bool add_nas_ctx_to_mme_ue_s1ap_id_map(nas* nas_ctx) = 0; + virtual bool add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id) = 0; + virtual bool release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) = 0; + virtual bool delete_ue_ctx(uint64_t imsi) = 0; + virtual uint64_t find_imsi_from_m_tmsi(uint32_t m_tmsi) = 0; + virtual nas* find_nas_ctx_from_imsi(uint64_t imsi) = 0; virtual bool send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) = 0; - virtual bool send_ue_context_release_command(uint32_t mme_ue_s1ap_id) = 0; - virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t *nas_msg, struct sctp_sndrcvinfo enb_sri) = 0; + virtual bool send_ue_context_release_command(uint32_t mme_ue_s1ap_id) = 0; + virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + srslte::byte_buffer_t* nas_msg, + struct sctp_sndrcvinfo enb_sri) = 0; }; -//NAS -> HSS -class hss_interface_nas +class hss_interface_nas // NAS -> HSS { public: - virtual bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) = 0; - virtual bool gen_update_loc_answer(uint64_t imsi, uint8_t *qci) = 0; - virtual bool resync_sqn(uint64_t imsi, uint8_t *auts) = 0; + virtual bool gen_auth_info_answer(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres) = 0; + virtual bool gen_update_loc_answer(uint64_t imsi, uint8_t* qci) = 0; + virtual bool resync_sqn(uint64_t imsi, uint8_t* auts) = 0; }; -} +} // namespace srsepc #endif // SRSLTE_EPC_INTERFACES_H diff --git a/lib/src/asn1/gtpc.cc b/lib/src/asn1/gtpc.cc index ac0116840..ccfdafb90 100644 --- a/lib/src/asn1/gtpc.cc +++ b/lib/src/asn1/gtpc.cc @@ -1,5 +1,4 @@ -/** - * +/* * \section COPYRIGHT * * Copyright 2013-2017 Software Radio Systems Limited @@ -27,14 +26,11 @@ #include "srslte/asn1/gtpc.h" #include "srslte/common/common.h" -namespace srslte{ - +namespace srslte { -int -gtpc_pack_create_session_request(struct gtpc_create_session_request *cs_req, srslte::byte_buffer_t) +int gtpc_pack_create_session_request(struct gtpc_create_session_request* cs_req, srslte::byte_buffer_t) { - //FIXME + // TODO return 0; } - -}; +} // namespace srslte diff --git a/srsepc/hdr/hss/hss.h b/srsepc/hdr/hss/hss.h index 7d7e2e83b..d7ec9cedd 100644 --- a/srsepc/hdr/hss/hss.h +++ b/srsepc/hdr/hss/hss.h @@ -47,93 +47,86 @@ #define LTE_FDD_ENB_IND_HE_MAX_VALUE 31 #define LTE_FDD_ENB_SEQ_HE_MAX_VALUE 0x07FFFFFFFFFFUL -namespace srsepc{ +namespace srsepc { -typedef struct{ +typedef struct { std::string auth_algo; std::string db_file; - uint16_t mcc; - uint16_t mnc; -}hss_args_t; - -typedef struct{ - std::string name; - uint64_t imsi; - uint8_t key[16]; - bool op_configured; - uint8_t op[16]; - uint8_t opc[16]; - uint8_t amf[2]; - uint8_t sqn[6]; - uint16_t qci; - uint8_t last_rand[16]; -}hss_ue_ctx_t; - -enum hss_auth_algo { - HSS_ALGO_XOR, - HSS_ALGO_MILENAGE -}; + uint16_t mcc; + uint16_t mnc; +} hss_args_t; + +typedef struct { + std::string name; + uint64_t imsi; + uint8_t key[16]; + bool op_configured; + uint8_t op[16]; + uint8_t opc[16]; + uint8_t amf[2]; + uint8_t sqn[6]; + uint16_t qci; + uint8_t last_rand[16]; +} hss_ue_ctx_t; + +enum hss_auth_algo { HSS_ALGO_XOR, HSS_ALGO_MILENAGE }; class hss : public hss_interface_nas { public: static hss* get_instance(void); static void cleanup(void); - int init(hss_args_t *hss_args, srslte::log_filter* hss_log); - void stop(void); + int init(hss_args_t* hss_args, srslte::log_filter* hss_log); + void stop(void); - virtual bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); + virtual bool gen_auth_info_answer(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres); virtual bool gen_update_loc_answer(uint64_t imsi, uint8_t* qci); - virtual bool resync_sqn(uint64_t imsi, uint8_t *auts); + virtual bool resync_sqn(uint64_t imsi, uint8_t* auts); private: - hss(); virtual ~hss(); - static hss *m_instance; - - srslte::byte_buffer_pool *m_pool; - - std::map m_imsi_to_ue_ctx; + static hss* m_instance; + std::map m_imsi_to_ue_ctx; void gen_rand(uint8_t rand_[16]); - bool get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn); + bool get_k_amf_opc_sqn(uint64_t imsi, uint8_t* k, uint8_t* amf, uint8_t* opc, uint8_t* sqn); - bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); - bool gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); + bool gen_auth_info_answer_milenage(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres); + bool gen_auth_info_answer_xor(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres); - bool resync_sqn_milenage(uint64_t imsi, uint8_t *auts); - bool resync_sqn_xor(uint64_t imsi, uint8_t *auts); + bool resync_sqn_milenage(uint64_t imsi, uint8_t* auts); + bool resync_sqn_xor(uint64_t imsi, uint8_t* auts); - std::vector split_string(const std::string &str, char delimiter); - void get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len); + std::vector split_string(const std::string& str, char delimiter); + void get_uint_vec_from_hex_str(const std::string& key_str, uint8_t* key, uint len); void increment_ue_sqn(uint64_t imsi); void increment_seq_after_resync(uint64_t imsi); - void increment_sqn(uint8_t *sqn, uint8_t *next_sqn); - void set_sqn(uint64_t imsi, uint8_t *sqn); + void increment_sqn(uint8_t* sqn, uint8_t* next_sqn); + void set_sqn(uint64_t imsi, uint8_t* sqn); - void set_last_rand(uint64_t imsi, uint8_t *rand); - void get_last_rand(uint64_t imsi, uint8_t *rand); + void set_last_rand(uint64_t imsi, uint8_t* rand); + void get_last_rand(uint64_t imsi, uint8_t* rand); bool set_auth_algo(std::string auth_algo); bool read_db_file(std::string db_file); bool write_db_file(std::string db_file); - bool get_ue_ctx(uint64_t imsi, hss_ue_ctx_t **ue_ctx); - - std::string hex_string(uint8_t *hex, int size); + bool get_ue_ctx(uint64_t imsi, hss_ue_ctx_t** ue_ctx); + + std::string hex_string(uint8_t* hex, int size); enum hss_auth_algo m_auth_algo; - std::string db_file; + std::string db_file; + /*Logs*/ - srslte::log_filter *m_hss_log; - + srslte::log_filter* m_hss_log; + uint16_t mcc; uint16_t mnc; }; } // namespace srsepc - #endif // SRSEPC_HSS_H diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 058009487..053887d54 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -41,44 +41,43 @@ #include "srslte/common/threads.h" #include "s1ap.h" +namespace srsepc { -namespace srsepc{ - -typedef struct{ +typedef struct { s1ap_args_t s1ap_args; - //diameter_args_t diameter_args; - //gtpc_args_t gtpc_args; + // diameter_args_t diameter_args; + // gtpc_args_t gtpc_args; } mme_args_t; - -class mme: - public thread +class mme : public thread { public: static mme* get_instance(void); static void cleanup(void); - int init(mme_args_t* args, srslte::log_filter *nas_log, srslte::log_filter *s1ap_log, srslte::log_filter *mme_gtpc_log, hss_interface_nas * hss); + + int init(mme_args_t* args, + srslte::log_filter* nas_log, + srslte::log_filter* s1ap_log, + srslte::log_filter* mme_gtpc_log); void stop(); - int get_s1_mme(); + int get_s1_mme(); void run_thread(); private: - mme(); virtual ~mme(); - static mme *m_instance; - s1ap *m_s1ap; - mme_gtpc *m_mme_gtpc; + static mme* m_instance; + s1ap* m_s1ap; + mme_gtpc* m_mme_gtpc; - bool m_running; - srslte::byte_buffer_pool *m_pool; + bool m_running; + srslte::byte_buffer_pool* m_pool; /*Logs*/ - srslte::log_filter *m_nas_log; - srslte::log_filter *m_s1ap_log; - srslte::log_filter *m_mme_gtpc_log; + srslte::log_filter* m_nas_log; + srslte::log_filter* m_s1ap_log; + srslte::log_filter* m_mme_gtpc_log; }; } // namespace srsepc - #endif // SRSEPC_MME_H diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index 08cd30e42..a854124f8 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -26,58 +26,53 @@ #ifndef SRSEPC_MME_GTPC_H #define SRSEPC_MME_GTPC_H +#include "nas.h" +#include "srslte/asn1/gtpc.h" +#include "srslte/common/buffer_pool.h" #include "srslte/common/log.h" #include "srslte/common/log_filter.h" -#include "srslte/common/buffer_pool.h" -#include "srslte/asn1/gtpc.h" -#include "nas.h" -namespace srsepc -{ +namespace srsepc { class spgw; class s1ap; -class mme_gtpc - : public gtpc_interface_nas +class mme_gtpc : public gtpc_interface_nas { public: - - typedef struct gtpc_ctx{ + typedef struct gtpc_ctx { srslte::gtp_fteid_t mme_ctr_fteid; srslte::gtp_fteid_t sgw_ctr_fteid; - }gtpc_ctx_t; + } gtpc_ctx_t; static mme_gtpc* get_instance(void); - static void cleanup(void); + static void cleanup(void); - bool init(srslte::log_filter *mme_gtpc_log); + bool init(srslte::log_filter* mme_gtpc_log); - uint32_t get_new_ctrl_teid(); + uint32_t get_new_ctrl_teid(); virtual bool send_create_session_request(uint64_t imsi); - bool handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu); - virtual bool send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, srslte::gtp_fteid_t *enb_fteid); - void handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu); - void send_release_access_bearers_request(uint64_t imsi); + bool handle_create_session_response(srslte::gtpc_pdu* cs_resp_pdu); + virtual bool send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, srslte::gtp_fteid_t* enb_fteid); + void handle_modify_bearer_response(srslte::gtpc_pdu* mb_resp_pdu); + void send_release_access_bearers_request(uint64_t imsi); virtual bool send_delete_session_request(uint64_t imsi); private: - mme_gtpc(); virtual ~mme_gtpc(); - static mme_gtpc *m_instance; + static mme_gtpc* m_instance; - srslte::log_filter *m_mme_gtpc_log; - srslte::byte_buffer_pool *m_pool; + srslte::log_filter* m_mme_gtpc_log; + srslte::byte_buffer_pool* m_pool; - s1ap* m_s1ap; - spgw* m_spgw; + s1ap* m_s1ap; + spgw* m_spgw; in_addr_t m_mme_gtpc_ip; - uint32_t m_next_ctrl_teid; - std::map m_mme_ctr_teid_to_imsi; - std::map m_imsi_to_gtpc_ctx; - + uint32_t m_next_ctrl_teid; + std::map m_mme_ctr_teid_to_imsi; + std::map m_imsi_to_gtpc_ctx; }; -} +} // namespace srsepc #endif // SRSEPC_MME_GTPC_H diff --git a/srsepc/hdr/mme/nas.h b/srsepc/hdr/mme/nas.h index f0c2f7a6a..a4c3b3d20 100644 --- a/srsepc/hdr/mme/nas.h +++ b/srsepc/hdr/mme/nas.h @@ -21,16 +21,15 @@ #ifndef SRSEPC_NAS_H #define SRSEPC_NAS_H -#include - -#include "srslte/common/security.h" #include "srslte/asn1/gtpc_ies.h" -#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/liblte_mme.h" +#include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/buffer_pool.h" +#include "srslte/common/security.h" #include "srslte/interfaces/epc_interfaces.h" +#include -namespace srsepc{ +namespace srsepc { static const uint8_t MAX_ERABS_PER_UE = 16; @@ -42,9 +41,7 @@ typedef enum { EMM_STATE_DEREGISTERED_INITIATED, EMM_STATE_N_ITEMS, } emm_state_t; -static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"DEREGISTERED", - "COMMON PROCEDURE INITIATED", - "REGISTERED", +static const char emm_state_text[EMM_STATE_N_ITEMS][100] = {"DEREGISTERED", "COMMON PROCEDURE INITIATED", "REGISTERED", "DEREGISTERED INITIATED"}; // MME ECM states (3GPP 23.401 v10.0.0, section 4.6.3) @@ -53,8 +50,8 @@ typedef enum { ECM_STATE_CONNECTED, ECM_STATE_N_ITEMS, } ecm_state_t; -static const char ecm_state_text[ECM_STATE_N_ITEMS][100] = {"IDLE", - "CONNECTED"}; +static const char ecm_state_text[ECM_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"}; + /* // MME ESM states (3GPP 23.401 v10.0.0, section 4.6.3) typedef enum { @@ -75,73 +72,67 @@ static const char esm_state_text[ESM_STATE_N_ITEMS][100] = {"CONTEXT INACTIVE", "PROCEDURE_TRANSACTION_INACTIVE" "PROCEDURE_TRANSACTION_PENDING"}; */ -typedef enum -{ - ERAB_DEACTIVATED, - ERAB_CTX_REQUESTED, - ERAB_CTX_SETUP, - ERAB_ACTIVE -} esm_state_t; +typedef enum { ERAB_DEACTIVATED, ERAB_CTX_REQUESTED, ERAB_CTX_SETUP, ERAB_ACTIVE } esm_state_t; /* * EMM, ECM, ESM and EPS Security context definitions */ -typedef struct{ - uint64_t imsi; - emm_state_t state; - uint8_t procedure_transaction_id; - uint8_t attach_type; - struct in_addr ue_ip; - srslte::gtpc_f_teid_ie sgw_ctrl_fteid; +typedef struct { + uint64_t imsi; + emm_state_t state; + uint8_t procedure_transaction_id; + uint8_t attach_type; + struct in_addr ue_ip; + srslte::gtpc_f_teid_ie sgw_ctrl_fteid; } emm_ctx_t; -typedef struct{ - ecm_state_t state; - uint32_t enb_ue_s1ap_id; - uint32_t mme_ue_s1ap_id; - struct sctp_sndrcvinfo enb_sri; - bool eit; +typedef struct { + ecm_state_t state; + uint32_t enb_ue_s1ap_id; + uint32_t mme_ue_s1ap_id; + struct sctp_sndrcvinfo enb_sri; + bool eit; } ecm_ctx_t; -typedef struct{ - uint8_t erab_id; - esm_state_t state; - uint8_t qci; - srslte::gtpc_f_teid_ie enb_fteid; - srslte::gtpc_f_teid_ie sgw_s1u_fteid; +typedef struct { + uint8_t erab_id; + esm_state_t state; + uint8_t qci; + srslte::gtpc_f_teid_ie enb_fteid; + srslte::gtpc_f_teid_ie sgw_s1u_fteid; srslte::gtpc_pdn_address_allocation_ie pdn_addr_alloc; } esm_ctx_t; -typedef struct{ - uint8_t eksi; - uint8_t k_asme[32]; - uint8_t autn[16]; - uint8_t rand[16]; - uint8_t xres[16]; //minimum 6, maximum 16 - uint32_t dl_nas_count; - uint32_t ul_nas_count; - srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; - srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; - uint8_t k_nas_enc[32]; - uint8_t k_nas_int[32]; - uint8_t k_enb[32]; +typedef struct { + uint8_t eksi; + uint8_t k_asme[32]; + uint8_t autn[16]; + uint8_t rand[16]; + uint8_t xres[16]; // minimum 6, maximum 16 + uint32_t dl_nas_count; + uint32_t ul_nas_count; + srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; + srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; + uint8_t k_nas_enc[32]; + uint8_t k_nas_int[32]; + uint8_t k_enb[32]; 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_EPS_MOBILE_ID_GUTI_STRUCT guti; + LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; } sec_ctx_t; /* * NAS Initialization Arguments */ typedef struct { - uint16_t mcc; - uint16_t mnc; - uint8_t mme_code; - uint16_t mme_group; - uint16_t tac; - std::string apn; - std::string dns; + uint16_t mcc; + uint16_t mnc; + uint8_t mme_code; + uint16_t mme_group; + uint16_t tac; + std::string apn; + std::string dns; srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo; srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo; } nas_init_t; @@ -150,101 +141,101 @@ class nas { public: nas(); - void init(nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + void init(nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); /*********************** * Initial UE messages * ***********************/ - //Attach request messages - static bool handle_attach_request( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + // Attach request messages + static bool handle_attach_request(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - static bool handle_imsi_attach_request_unknown_ue( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, - const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + static bool handle_imsi_attach_request_unknown_ue(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT& attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT& pdn_con_req, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - static bool handle_imsi_attach_request_known_ue( nas *nas_ctx, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - 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_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + static bool handle_imsi_attach_request_known_ue(nas* nas_ctx, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + 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_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); + static bool handle_guti_attach_request_unknown_ue(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT& attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT& pdn_con_req, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - static bool handle_guti_attach_request_unknown_ue( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, - const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + static bool handle_guti_attach_request_known_ue(nas* nas_ctx, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + 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_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - static bool handle_guti_attach_request_known_ue( nas *nas_ctx, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - 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_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); - //Service request messages - static bool handle_service_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + // Service request messages + static bool handle_service_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - //Dettach request messages - static bool handle_detach_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + // Dettach request messages + static bool handle_detach_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); - //Tracking area update request messages - static bool handle_tracking_area_update_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log); + // Tracking area update request messages + static bool handle_tracking_area_update_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log); /* Uplink NAS messages handling */ bool handle_authentication_response(srslte::byte_buffer_t* nas_rx); @@ -269,7 +260,7 @@ public: /* Security functions */ bool integrity_check(srslte::byte_buffer_t* pdu); bool short_integrity_check(srslte::byte_buffer_t* pdu); - void integrity_generate(srslte::byte_buffer_t* pdu, uint8_t *mac); + void integrity_generate(srslte::byte_buffer_t* pdu, uint8_t* mac); void cipher_decrypt(srslte::byte_buffer_t* pdu); void cipher_encrypt(srslte::byte_buffer_t* pdu); @@ -280,20 +271,20 @@ public: sec_ctx_t m_sec_ctx; private: - srslte::byte_buffer_pool *m_pool; - srslte::log *m_nas_log; - gtpc_interface_nas *m_gtpc; - s1ap_interface_nas *m_s1ap; - hss_interface_nas *m_hss; + srslte::byte_buffer_pool* m_pool; + srslte::log* m_nas_log; + gtpc_interface_nas* m_gtpc; + s1ap_interface_nas* m_s1ap; + hss_interface_nas* m_hss; - uint16_t m_mcc; - uint16_t m_mnc; - uint16_t m_mme_group; - uint16_t m_mme_code; - uint16_t m_tac; - std::string m_apn; - std::string m_dns; + uint16_t m_mcc; + uint16_t m_mnc; + uint16_t m_mme_group; + uint16_t m_mme_code; + uint16_t m_tac; + std::string m_apn; + std::string m_dns; }; -}//namespace +} // namespace srsepc #endif // SRSEPC_NAS_H diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 3e7ba7b79..d3a89125b 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -26,129 +26,126 @@ #ifndef SRSEPC_S1AP_H #define SRSEPC_S1AP_H +#include "mme_gtpc.h" +#include "nas.h" +#include "s1ap_ctx_mngmt_proc.h" +#include "s1ap_mngmt_proc.h" +#include "s1ap_nas_transport.h" +#include "srsepc/hdr/hss/hss.h" #include "srslte/asn1/gtpc.h" -#include "srslte/asn1/liblte_s1ap.h" #include "srslte/asn1/liblte_mme.h" +#include "srslte/asn1/liblte_s1ap.h" #include "srslte/common/common.h" #include "srslte/common/log.h" #include "srslte/common/s1ap_pcap.h" #include "srslte/interfaces/epc_interfaces.h" - -#include #include -#include -#include -#include -#include #include +#include #include -#include "nas.h" -#include "s1ap_mngmt_proc.h" -#include "s1ap_nas_transport.h" -#include "s1ap_ctx_mngmt_proc.h" -#include "mme_gtpc.h" -#include "srsepc/hdr/hss/hss.h" +#include +#include +#include +#include -namespace srsepc{ +namespace srsepc { const uint16_t S1MME_PORT = 36412; -class s1ap: - public s1ap_interface_nas, - public s1ap_interface_gtpc +class s1ap : public s1ap_interface_nas, public s1ap_interface_gtpc { public: - static s1ap* get_instance(); - static void cleanup(); + static void cleanup(); - int enb_listen(); - int init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log, srslte::log_filter *nas_log, hss_interface_nas * hss_); + int enb_listen(); + int init(s1ap_args_t s1ap_args, srslte::log_filter* s1ap_log, srslte::log_filter* nas_log); void stop(); int get_s1_mme(); void delete_enb_ctx(int32_t assoc_id); - bool s1ap_tx_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_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); + bool s1ap_tx_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_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg); void activate_eps_bearer(uint64_t imsi, uint8_t ebi); - void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); + void print_enb_ctx_info(const std::string& prefix, const enb_ctx_t& enb_ctx); - uint32_t get_plmn(); - uint32_t get_next_mme_ue_s1ap_id(); + uint32_t get_plmn(); + uint32_t get_next_mme_ue_s1ap_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 get_enb_ctx(uint16_t sctp_stream); + void add_new_enb_ctx(const enb_ctx_t& enb_ctx, const struct sctp_sndrcvinfo* enb_sri); + void get_enb_ctx(uint16_t sctp_stream); - bool add_nas_ctx_to_imsi_map(nas *nas_ctx); - bool add_nas_ctx_to_mme_ue_s1ap_id_map(nas *nas_ctx); + bool add_nas_ctx_to_imsi_map(nas* nas_ctx); + bool add_nas_ctx_to_mme_ue_s1ap_id_map(nas* nas_ctx); bool add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id); virtual nas* find_nas_ctx_from_imsi(uint64_t imsi); - nas* find_nas_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); + nas* find_nas_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); - bool release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id); - void release_ues_ecm_ctx_in_enb(int32_t enb_assoc); + bool release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id); + void release_ues_ecm_ctx_in_enb(int32_t enb_assoc); virtual bool delete_ue_ctx(uint64_t imsi); - uint32_t allocate_m_tmsi(uint64_t imsi); + uint32_t allocate_m_tmsi(uint64_t imsi); virtual uint64_t find_imsi_from_m_tmsi(uint32_t m_tmsi); - s1ap_args_t m_s1ap_args; - srslte::log_filter *m_s1ap_log; - srslte::log_filter *m_nas_log; + s1ap_args_t m_s1ap_args; + srslte::log_filter* m_s1ap_log; + srslte::log_filter* m_nas_log; - s1ap_mngmt_proc* m_s1ap_mngmt_proc; - s1ap_nas_transport* m_s1ap_nas_transport; - s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; + s1ap_mngmt_proc* m_s1ap_mngmt_proc; + s1ap_nas_transport* m_s1ap_nas_transport; + s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; - std::map m_tmsi_to_imsi; + std::map m_tmsi_to_imsi; - //Interfaces + // Interfaces virtual bool send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup); virtual bool send_ue_context_release_command(uint32_t mme_ue_s1ap_id); - virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t *nas_msg, struct sctp_sndrcvinfo enb_sri); + virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + srslte::byte_buffer_t* nas_msg, + struct sctp_sndrcvinfo enb_sri); + private: s1ap(); virtual ~s1ap(); - static s1ap *m_instance; + static s1ap* m_instance; - uint32_t m_plmn; - srslte::byte_buffer_pool *m_pool; + uint32_t m_plmn; + srslte::byte_buffer_pool* m_pool; - hss_interface_nas *m_hss; - int m_s1mme; - std::map m_active_enbs; - std::map m_sctp_to_enb_id; - std::map > m_enb_assoc_to_ue_ids; + hss_interface_nas* m_hss; + int m_s1mme; + std::map m_active_enbs; + std::map m_sctp_to_enb_id; + std::map > m_enb_assoc_to_ue_ids; - std::map m_imsi_to_nas_ctx; - std::map m_mme_ue_s1ap_id_to_nas_ctx; + std::map m_imsi_to_nas_ctx; + std::map m_mme_ue_s1ap_id_to_nas_ctx; - uint32_t m_next_mme_ue_s1ap_id; - uint32_t m_next_m_tmsi; + uint32_t m_next_mme_ue_s1ap_id; + uint32_t m_next_m_tmsi; - //FIXME the GTP-C should be moved to the MME class, when the packaging of GTP-C messages is done. - mme_gtpc *m_mme_gtpc; + // FIXME the GTP-C should be moved to the MME class, when the packaging of GTP-C messages is done. + mme_gtpc* m_mme_gtpc; - //PCAP + // PCAP bool m_pcap_enable; srslte::s1ap_pcap m_pcap; }; -inline uint32_t -s1ap::get_plmn() +inline uint32_t s1ap::get_plmn() { return m_plmn; } - -} //namespace srsepc - +} // namespace srsepc #endif // SRSEPC_S1AP_H diff --git a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h index b35cd95d2..380003fc5 100644 --- a/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h +++ b/srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h @@ -26,47 +26,47 @@ #ifndef SRSEPC_S1AP_CTX_MNGMT_PROC_H #define SRSEPC_S1AP_CTX_MNGMT_PROC_H +#include "mme_gtpc.h" +#include "s1ap_common.h" #include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/buffer_pool.h" #include "srslte/common/common.h" -#include "s1ap_common.h" #include "srslte/common/log_filter.h" -#include "mme_gtpc.h" -#include "srslte/common/buffer_pool.h" -namespace srsepc{ +namespace srsepc { class s1ap; class s1ap_ctx_mngmt_proc { public: - - static s1ap_ctx_mngmt_proc *m_instance; + static s1ap_ctx_mngmt_proc* m_instance; static s1ap_ctx_mngmt_proc* get_instance(void); - static void cleanup(void); + static void cleanup(void); void init(void); - bool send_initial_context_setup_request(nas *nas_ctx, uint16_t erab_to_setup); - bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); - bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); - bool send_ue_context_release_command(nas *nas_ctx); - bool handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT *rel_comp); + bool send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup); + bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT* in_ctxt_resp); + bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag); + bool send_ue_context_release_command(nas* nas_ctx); + bool handle_ue_context_release_complete(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASECOMPLETE_STRUCT* rel_comp); private: s1ap_ctx_mngmt_proc(); virtual ~s1ap_ctx_mngmt_proc(); - s1ap* m_s1ap; - s1ap_nas_transport* m_s1ap_nas_transport; - srslte::log_filter *m_s1ap_log; + s1ap* m_s1ap; + srslte::log_filter* m_s1ap_log; s1ap_args_t m_s1ap_args; - mme_gtpc* m_mme_gtpc; - srslte::byte_buffer_pool *m_pool; + mme_gtpc* m_mme_gtpc; + srslte::byte_buffer_pool* m_pool; }; -} //namespace srsepc - +} // namespace srsepc #endif // SRSEPC_S1AP_CTX_MNGMT_PROC_H diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index 17322f68b..f6055ba38 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -26,29 +26,34 @@ #ifndef SRSEPC_S1AP_NAS_TRANSPORT_H #define SRSEPC_S1AP_NAS_TRANSPORT_H -#include "srslte/asn1/liblte_s1ap.h" -#include "srslte/common/buffer_pool.h" +#include "mme_gtpc.h" #include "s1ap_common.h" -#include "srslte/asn1/gtpc.h" #include "srsepc/hdr/hss/hss.h" -#include "mme_gtpc.h" +#include "srslte/asn1/gtpc.h" +#include "srslte/asn1/liblte_s1ap.h" +#include "srslte/common/buffer_pool.h" -namespace srsepc{ +namespace srsepc { class s1ap_nas_transport { public: static s1ap_nas_transport* m_instance; - static s1ap_nas_transport* get_instance(void); - static void cleanup(void); - void init(hss_interface_nas * hss_); + static s1ap_nas_transport* get_instance(); + static void cleanup(); + void init(); - bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue, struct sctp_sndrcvinfo* enb_sri, - srslte::byte_buffer_t* reply_buffer, bool* reply_flag); + bool handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag); bool handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT* ul_xport, - struct sctp_sndrcvinfo* enb_sri, srslte::byte_buffer_t* reply_buffer, - bool* reply_flag); - bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t* nas_msg, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag); + bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + srslte::byte_buffer_t* nas_msg, struct sctp_sndrcvinfo enb_sri); private: @@ -62,5 +67,6 @@ private: hss_interface_nas* m_hss; mme_gtpc* m_mme_gtpc; }; -} //namespace srsepc + +} // namespace srsepc #endif // SRSEPC_S1AP_NAS_TRANSPORT_H diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 3222f5120..7cf2782cd 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -41,7 +41,7 @@ #include "srslte/common/threads.h" #include "srslte/asn1/gtpc.h" -namespace srsepc{ +namespace srsepc { class mme_gtpc; @@ -53,64 +53,61 @@ typedef struct { std::string sgi_if_name; } spgw_args_t; - typedef struct spgw_tunnel_ctx { - uint64_t imsi; - in_addr_t ue_ipv4; - uint8_t ebi; - struct srslte::gtpc_f_teid_ie up_ctrl_fteid; - struct srslte::gtpc_f_teid_ie up_user_fteid; - struct srslte::gtpc_f_teid_ie dw_ctrl_fteid; - struct srslte::gtpc_f_teid_ie dw_user_fteid; + uint64_t imsi; + in_addr_t ue_ipv4; + uint8_t ebi; + srslte::gtp_fteid_t up_ctrl_fteid; + srslte::gtp_fteid_t up_user_fteid; + srslte::gtp_fteid_t dw_ctrl_fteid; + srslte::gtp_fteid_t dw_user_fteid; } spgw_tunnel_ctx_t; -class spgw: - public thread +class spgw : public thread { public: static spgw* get_instance(void); - static void cleanup(void); - int init(spgw_args_t* args, srslte::log_filter *spgw_log); - void stop(); - void run_thread(); + static void cleanup(void); + int init(spgw_args_t* args, srslte::log_filter* spgw_log); + void stop(); + void run_thread(); - void handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu); - void handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu); - void handle_delete_session_request(struct srslte::gtpc_pdu *del_req_pdu, struct srslte::gtpc_pdu *del_resp_pdu); - void handle_release_access_bearers_request(struct srslte::gtpc_pdu *rel_req_pdu, struct srslte::gtpc_pdu *rel_resp_pdu); + void handle_create_session_request(struct srslte::gtpc_create_session_request* cs_req, + struct srslte::gtpc_pdu* cs_resp_pdu); + void handle_modify_bearer_request(struct srslte::gtpc_pdu* mb_req_pdu, struct srslte::gtpc_pdu* mb_resp_pdu); + void handle_delete_session_request(struct srslte::gtpc_pdu* del_req_pdu, struct srslte::gtpc_pdu* del_resp_pdu); + void handle_release_access_bearers_request(struct srslte::gtpc_pdu* rel_req_pdu, + struct srslte::gtpc_pdu* rel_resp_pdu); - void handle_sgi_pdu(srslte::byte_buffer_t *msg); - void handle_s1u_pdu(srslte::byte_buffer_t *msg); + void handle_sgi_pdu(srslte::byte_buffer_t* msg); + void handle_s1u_pdu(srslte::byte_buffer_t* msg); private: - spgw(); virtual ~spgw(); - static spgw *m_instance; + static spgw* m_instance; - srslte::error_t init_sgi_if(spgw_args_t *args); - srslte::error_t init_s1u(spgw_args_t *args); - srslte::error_t init_ue_ip(spgw_args_t *args); + srslte::error_t init_sgi_if(spgw_args_t* args); + srslte::error_t init_s1u(spgw_args_t* args); + srslte::error_t init_ue_ip(spgw_args_t* args); - uint64_t get_new_ctrl_teid(); - uint64_t get_new_user_teid(); + uint64_t get_new_ctrl_teid(); + uint64_t get_new_user_teid(); in_addr_t get_new_ue_ipv4(); - spgw_tunnel_ctx_t* create_gtp_ctx(struct srslte::gtpc_create_session_request *cs_req); - bool delete_gtp_ctx(uint32_t ctrl_teid); - - - bool m_running; - srslte::byte_buffer_pool *m_pool; - mme_gtpc *m_mme_gtpc; + spgw_tunnel_ctx_t* create_gtp_ctx(struct srslte::gtpc_create_session_request* cs_req); + bool delete_gtp_ctx(uint32_t ctrl_teid); + bool m_running; + srslte::byte_buffer_pool* m_pool; + mme_gtpc* m_mme_gtpc; bool m_sgi_up; - int m_sgi_if; - int m_sgi_sock; + int m_sgi_if; + int m_sgi_sock; bool m_s1u_up; - int m_s1u; + int m_s1u; uint64_t m_next_ctrl_teid; uint64_t m_next_user_teid; @@ -119,21 +116,19 @@ private: pthread_mutex_t m_mutex; - std::map m_imsi_to_ctr_teid; //IMSI to control TEID map. Important to check if UE is previously connected - std::map m_teid_to_tunnel_ctx; //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. - std::map m_ip_to_teid; //Map IP to User-plane TEID for downlink traffic + std::map m_imsi_to_ctr_teid; // IMSI to control TEID map. + // Important to check if UE is previously connected - uint32_t m_h_next_ue_ip; + std::map m_teid_to_tunnel_ctx; // Map control TEID to tunnel ctx. + // Usefull to get reply ctrl TEID, UE IP, etc. - /*Time*/ - struct timeval m_t_last_dl; - struct timeval m_t_last_ul; + std::map m_ip_to_teid; // Map IP to User-plane TEID for downlink traffic - /*Logs*/ - srslte::log_filter *m_spgw_log; + uint32_t m_h_next_ue_ip; + /*Logs*/ + srslte::log_filter* m_spgw_log; }; } // namespace srsepc - #endif // SRSEPC_SPGW_H diff --git a/srsepc/src/hss/hss.cc b/srsepc/src/hss/hss.cc index 959c04206..571c49d11 100644 --- a/srsepc/src/hss/hss.cc +++ b/srsepc/src/hss/hss.cc @@ -23,25 +23,22 @@ * and at http://www.gnu.org/licenses/. * */ -#include /* srand, rand */ -#include /* time */ -#include -#include -#include -#include // for printing uint64_t #include "srsepc/hdr/hss/hss.h" #include "srslte/common/security.h" +#include // for printing uint64_t +#include +#include +#include /* srand, rand */ +#include +#include -using namespace srslte; - -namespace srsepc{ +namespace srsepc { -hss* hss::m_instance = NULL; +hss* hss::m_instance = NULL; pthread_mutex_t hss_instance_mutex = PTHREAD_MUTEX_INITIALIZER; hss::hss() { - m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -50,43 +47,38 @@ hss::~hss() return; } -hss* -hss::get_instance(void) +hss* hss::get_instance() { pthread_mutex_lock(&hss_instance_mutex); - if(NULL == m_instance) { + if (NULL == m_instance) { m_instance = new hss(); } pthread_mutex_unlock(&hss_instance_mutex); - return(m_instance); + return (m_instance); } -void -hss::cleanup(void) +void hss::cleanup() { pthread_mutex_lock(&hss_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&hss_instance_mutex); } -int -hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) +int hss::init(hss_args_t* hss_args, srslte::log_filter* hss_log) { srand(time(NULL)); /*Init loggers*/ m_hss_log = hss_log; /*Set authentication algorithm*/ - if(set_auth_algo(hss_args->auth_algo) == false) - { + if (set_auth_algo(hss_args->auth_algo) == false) { return -1; } /*Read user information from DB*/ - if(read_db_file(hss_args->db_file) == false) - { + if (read_db_file(hss_args->db_file) == false) { m_hss_log->console("Error reading user database file %s\n", hss_args->db_file.c_str()); return -1; } @@ -96,110 +88,92 @@ hss::init(hss_args_t *hss_args, srslte::log_filter *hss_log) db_file = hss_args->db_file; - m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s, MCC: %d, MNC: %d\n", hss_args->db_file.c_str(),hss_args->auth_algo.c_str(), mcc, mnc); + m_hss_log->info("HSS Initialized. DB file %s, authentication algorithm %s, MCC: %d, MNC: %d\n", + hss_args->db_file.c_str(), hss_args->auth_algo.c_str(), mcc, mnc); m_hss_log->console("HSS Initialized.\n"); return 0; } -void -hss::stop(void) +void hss::stop() { write_db_file(db_file); - std::map::iterator it = m_imsi_to_ue_ctx.begin(); - while(it!=m_imsi_to_ue_ctx.end()) - { - m_hss_log->info("Deleting UE context in HSS. IMSI: %015" PRIu64 "\n", it->second->imsi); - m_hss_log->console("Deleting UE context in HSS. IMSI: %015" PRIu64 "\n", it->second->imsi); - delete it->second; - m_imsi_to_ue_ctx.erase(it++); - } + std::map::iterator it = m_imsi_to_ue_ctx.begin(); + while (it != m_imsi_to_ue_ctx.end()) { + m_hss_log->info("Deleting UE context in HSS. IMSI: %015" PRIu64 "\n", it->second->imsi); + m_hss_log->console("Deleting UE context in HSS. IMSI: %015" PRIu64 "\n", it->second->imsi); + delete it->second; + m_imsi_to_ue_ctx.erase(it++); + } return; } - -bool -hss::set_auth_algo(std::string auth_algo) +bool hss::set_auth_algo(std::string auth_algo) { - if(auth_algo != "xor" && auth_algo != "milenage" ) - { + if (auth_algo != "xor" && auth_algo != "milenage") { m_hss_log->error("Unrecognized authentication algorithm. auth_algo = %s\n", auth_algo.c_str()); return false; } - if(auth_algo == "xor") - { + if (auth_algo == "xor") { m_auth_algo = HSS_ALGO_XOR; - } - else - { + } else { m_auth_algo = HSS_ALGO_MILENAGE; } return true; } -bool -hss::read_db_file(std::string db_filename) +bool hss::read_db_file(std::string db_filename) { std::ifstream m_db_file; m_db_file.open(db_filename.c_str(), std::ifstream::in); - if(!m_db_file.is_open()) - { + if (!m_db_file.is_open()) { return false; } - m_hss_log->info("Opened DB file: %s\n", db_filename.c_str() ); + m_hss_log->info("Opened DB file: %s\n", db_filename.c_str()); std::string line; - while (std::getline(m_db_file, line)) - { - if(line[0] != '#') - { - uint column_size = 8; - std::vector split = split_string(line,','); - if(split.size() != column_size) - { + while (std::getline(m_db_file, line)) { + if (line[0] != '#') { + uint column_size = 8; + std::vector split = split_string(line, ','); + if (split.size() != column_size) { m_hss_log->error("Error parsing UE database. Wrong number of columns in .csv\n"); m_hss_log->error("Columns: %zd, Expected %d.\n", split.size(), column_size); return false; } - hss_ue_ctx_t *ue_ctx = new hss_ue_ctx_t; - ue_ctx->name = split[0]; - ue_ctx->imsi = atoll(split[1].c_str()); - get_uint_vec_from_hex_str(split[2],ue_ctx->key,16); - if(split[3] == std::string("op")) - { + hss_ue_ctx_t* ue_ctx = new hss_ue_ctx_t; + ue_ctx->name = split[0]; + ue_ctx->imsi = atoll(split[1].c_str()); + get_uint_vec_from_hex_str(split[2], ue_ctx->key, 16); + if (split[3] == std::string("op")) { ue_ctx->op_configured = true; - get_uint_vec_from_hex_str(split[4],ue_ctx->op,16); - compute_opc(ue_ctx->key,ue_ctx->op,ue_ctx->opc); - } - else if (split[3] == std::string("opc")) - { - ue_ctx->op_configured =false; - get_uint_vec_from_hex_str(split[4],ue_ctx->opc,16); - } - else - { + get_uint_vec_from_hex_str(split[4], ue_ctx->op, 16); + srslte::compute_opc(ue_ctx->key, ue_ctx->op, ue_ctx->opc); + } else if (split[3] == std::string("opc")) { + ue_ctx->op_configured = false; + get_uint_vec_from_hex_str(split[4], ue_ctx->opc, 16); + } else { m_hss_log->error("Neither OP nor OPc configured.\n"); return false; } - get_uint_vec_from_hex_str(split[5],ue_ctx->amf,2); - get_uint_vec_from_hex_str(split[6],ue_ctx->sqn,6); + get_uint_vec_from_hex_str(split[5], ue_ctx->amf, 2); + get_uint_vec_from_hex_str(split[6], ue_ctx->sqn, 6); m_hss_log->debug("Added user from DB, IMSI: %015" PRIu64 "\n", ue_ctx->imsi); m_hss_log->debug_hex(ue_ctx->key, 16, "User Key : "); - if(ue_ctx->op_configured){ + if (ue_ctx->op_configured) { m_hss_log->debug_hex(ue_ctx->op, 16, "User OP : "); } m_hss_log->debug_hex(ue_ctx->opc, 16, "User OPc : "); m_hss_log->debug_hex(ue_ctx->amf, 2, "AMF : "); m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN : "); ue_ctx->qci = atoi(split[7].c_str()); - m_hss_log->debug("Default Bearer QCI: %d\n",ue_ctx->qci); - m_imsi_to_ue_ctx.insert(std::pair(ue_ctx->imsi,ue_ctx)); + m_hss_log->debug("Default Bearer QCI: %d\n", ue_ctx->qci); + m_imsi_to_ue_ctx.insert(std::pair(ue_ctx->imsi, ue_ctx)); } } - if(m_db_file.is_open()) - { + if (m_db_file.is_open()) { m_db_file.close(); } @@ -209,19 +183,18 @@ hss::read_db_file(std::string db_filename) bool hss::write_db_file(std::string db_filename) { std::string line; - uint8_t k[16]; - uint8_t amf[2]; - uint8_t op[16]; - uint8_t sqn[6]; + uint8_t k[16]; + uint8_t amf[2]; + uint8_t op[16]; + uint8_t sqn[6]; std::ofstream m_db_file; m_db_file.open(db_filename.c_str(), std::ofstream::out); - if(!m_db_file.is_open()) - { + if (!m_db_file.is_open()) { return false; } - m_hss_log->info("Opened DB file: %s\n", db_filename.c_str() ); + m_hss_log->info("Opened DB file: %s\n", db_filename.c_str()); //Write comment info m_db_file << "# " << std::endl @@ -239,86 +212,69 @@ bool hss::write_db_file(std::string db_filename) << "# " << std::endl << "# Note: Lines starting by '#' are ignored and will be overwritten " << std::endl; - std::map::iterator it = m_imsi_to_ue_ctx.begin(); - while(it!=m_imsi_to_ue_ctx.end()) - { - m_db_file << it->second->name; - m_db_file << ","; - m_db_file << std::setfill('0') << std::setw(15) << it->second->imsi; - m_db_file << ","; - m_db_file << hex_string(it->second->key, 16); - m_db_file << ","; - if(it->second->op_configured){ - m_db_file << "op,"; - m_db_file << hex_string(it->second->op, 16); - } - else{ - m_db_file << "opc,"; - m_db_file << hex_string(it->second->opc, 16); - } - m_db_file << ","; - m_db_file << hex_string(it->second->amf, 2); - m_db_file << ","; - m_db_file << hex_string(it->second->sqn, 6); - m_db_file << ","; - m_db_file << it->second->qci; - m_db_file << std::endl; - it++; - } - if(m_db_file.is_open()) - { + std::map::iterator it = m_imsi_to_ue_ctx.begin(); + while (it != m_imsi_to_ue_ctx.end()) { + m_db_file << it->second->name; + m_db_file << ","; + m_db_file << std::setfill('0') << std::setw(15) << it->second->imsi; + m_db_file << ","; + m_db_file << hex_string(it->second->key, 16); + m_db_file << ","; + if (it->second->op_configured) { + m_db_file << "op,"; + m_db_file << hex_string(it->second->op, 16); + } else { + m_db_file << "opc,"; + m_db_file << hex_string(it->second->opc, 16); + } + m_db_file << ","; + m_db_file << hex_string(it->second->amf, 2); + m_db_file << ","; + m_db_file << hex_string(it->second->sqn, 6); + m_db_file << ","; + m_db_file << it->second->qci; + m_db_file << std::endl; + it++; + } + if (m_db_file.is_open()) { m_db_file.close(); } return true; } -bool -hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +bool hss::gen_auth_info_answer(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres) { bool ret = false; - switch (m_auth_algo) - { - case HSS_ALGO_XOR: - ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); - break; - case HSS_ALGO_MILENAGE: - ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres); - break; + switch (m_auth_algo) { + case HSS_ALGO_XOR: + ret = gen_auth_info_answer_xor(imsi, k_asme, autn, rand, xres); + break; + case HSS_ALGO_MILENAGE: + ret = gen_auth_info_answer_milenage(imsi, k_asme, autn, rand, xres); + break; } increment_ue_sqn(imsi); return ret; - } - - -bool -hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +bool hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres) { uint8_t k[16]; uint8_t amf[2]; uint8_t opc[16]; uint8_t sqn[6]; - uint8_t ck[16]; - uint8_t ik[16]; - uint8_t ak[6]; - uint8_t mac[8]; - + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t ak[6]; + uint8_t mac[8]; - if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) - { + if (!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } gen_rand(rand); - - security_milenage_f2345( k, - opc, - rand, - xres, - ck, - ik, - ak); + + srslte::security_milenage_f2345(k, opc, rand, xres, ck, ik, ak); m_hss_log->debug_hex(k, 16, "User Key : "); m_hss_log->debug_hex(opc, 16, "User OPc : "); @@ -328,85 +284,67 @@ hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn m_hss_log->debug_hex(ik, 16, "User IK: "); m_hss_log->debug_hex(ak, 6, "User AK: "); - security_milenage_f1( k, - opc, - rand, - sqn, - amf, - mac); + srslte::security_milenage_f1(k, opc, rand, sqn, amf, mac); m_hss_log->debug_hex(sqn, 6, "User SQN : "); m_hss_log->debug_hex(mac, 8, "User MAC : "); // Generate K_asme - security_generate_k_asme( ck, - ik, - ak, - sqn, - mcc, - mnc, - k_asme); + srslte::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); m_hss_log->debug("User MCC : %x MNC : %x \n", mcc, mnc); m_hss_log->debug_hex(k_asme, 32, "User k_asme : "); - //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) - for(int i=0;i<6;i++ ) - { - autn[i] = sqn[i]^ak[i]; + // Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for (int i = 0; i < 6; i++) { + autn[i] = sqn[i] ^ ak[i]; } - for(int i=0;i<2;i++) - { - autn[6+i]=amf[i]; + for (int i = 0; i < 2; i++) { + autn[6 + i] = amf[i]; } - for(int i=0;i<8;i++) - { - autn[8+i]=mac[i]; + for (int i = 0; i < 8; i++) { + autn[8 + i] = mac[i]; } - m_hss_log->debug_hex(autn, 16, "User AUTN: "); set_last_rand(imsi, rand); - return true; } -bool -hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) +bool hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t* k_asme, uint8_t* autn, uint8_t* rand, uint8_t* xres) { uint8_t k[16]; uint8_t amf[2]; uint8_t opc[16]; uint8_t sqn[6]; - uint8_t xdout[16]; - uint8_t cdout[8]; + uint8_t xdout[16]; + uint8_t cdout[8]; - uint8_t ck[16]; - uint8_t ik[16]; - uint8_t ak[6]; - uint8_t mac[8]; + uint8_t ck[16]; + uint8_t ik[16]; + uint8_t ak[6]; + uint8_t mac[8]; int i = 0; - if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) - { + if (!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } gen_rand(rand); // Use RAND and K to compute RES, CK, IK and AK - for(i=0; i<16; i++) { - xdout[i] = k[i]^rand[i]; + for (i = 0; i < 16; i++) { + xdout[i] = k[i] ^ rand[i]; } - for(i=0; i<16; i++) { - xres[i] = xdout[i]; - ck[i] = xdout[(i+1)%16]; - ik[i] = xdout[(i+2)%16]; + for (i = 0; i < 16; i++) { + xres[i] = xdout[i]; + ck[i] = xdout[(i + 1) % 16]; + ik[i] = xdout[(i + 2) % 16]; } - for(i=0; i<6; i++) { - ak[i] = xdout[i+3]; + for (i = 0; i < 6; i++) { + ak[i] = xdout[i + 3]; } m_hss_log->debug_hex(k, 16, "User Key : "); @@ -418,59 +356,47 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin m_hss_log->debug_hex(ak, 6, "User AK: "); // Generate cdout - for(i=0; i<6; i++) { + for (i = 0; i < 6; i++) { cdout[i] = sqn[i]; } - for(i=0; i<2; i++) { - cdout[6+i] = amf[i]; + for (i = 0; i < 2; i++) { + cdout[6 + i] = amf[i]; } // Generate MAC - for(i=0;i<8;i++) { + for (i = 0; i < 8; i++) { mac[i] = xdout[i] ^ cdout[i]; } m_hss_log->debug_hex(sqn, 6, "User SQN : "); m_hss_log->debug_hex(mac, 8, "User MAC : "); - //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) - for(int i=0;i<6;i++ ) - { - autn[i] = sqn[i]^ak[i]; + // Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for (int i = 0; i < 6; i++) { + autn[i] = sqn[i] ^ ak[i]; } - for(int i=0;i<2;i++) - { - autn[6+i]=amf[i]; + for (int i = 0; i < 2; i++) { + autn[6 + i] = amf[i]; } - for(int i=0;i<8;i++) - { - autn[8+i]=mac[i]; + for (int i = 0; i < 8; i++) { + autn[8 + i] = mac[i]; } // Generate K_asme - security_generate_k_asme( ck, - ik, - ak, - sqn, - mcc, - mnc, - k_asme); + srslte::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme); m_hss_log->debug("User MCC : %x MNC : %x \n", mcc, mnc); m_hss_log->debug_hex(k_asme, 32, "User k_asme : "); - //Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) - for(int i=0;i<6;i++ ) - { - autn[i] = sqn[i]^ak[i]; + // Generate AUTN (autn = sqn ^ ak |+| amf |+| mac) + for (int i = 0; i < 6; i++) { + autn[i] = sqn[i] ^ ak[i]; } - for(int i=0;i<2;i++) - { - autn[6+i]=amf[i]; + for (int i = 0; i < 2; i++) { + autn[6 + i] = amf[i]; } - for(int i=0;i<8;i++) - { - autn[8+i]=mac[i]; + for (int i = 0; i < 8; i++) { + autn[8 + i] = mac[i]; } m_hss_log->debug_hex(autn, 8, "User AUTN: "); @@ -480,73 +406,60 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin return true; } -bool -hss::gen_update_loc_answer(uint64_t imsi, uint8_t* qci) +bool hss::gen_update_loc_answer(uint64_t imsi, uint8_t* qci) { - std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); - if(ue_ctx_it == m_imsi_to_ue_ctx.end()) - { - m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n",imsi); - m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n",imsi); + std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); + if (ue_ctx_it == m_imsi_to_ue_ctx.end()) { + m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n", imsi); + m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); return false; } - hss_ue_ctx_t *ue_ctx = ue_ctx_it->second; - m_hss_log->info("Found User %015" PRIu64 "\n",imsi); + hss_ue_ctx_t* ue_ctx = ue_ctx_it->second; + m_hss_log->info("Found User %015" PRIu64 "\n", imsi); *qci = ue_ctx->qci; return true; } - - -bool -hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn) +bool hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t* k, uint8_t* amf, uint8_t* opc, uint8_t* sqn) { - - std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); - if(ue_ctx_it == m_imsi_to_ue_ctx.end()) - { - m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n",imsi); - m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n",imsi); + std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); + if (ue_ctx_it == m_imsi_to_ue_ctx.end()) { + m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n", imsi); + m_hss_log->console("User not found at HSS. IMSI: %015" PRIu64 "\n", imsi); return false; } - hss_ue_ctx_t *ue_ctx = ue_ctx_it->second; - m_hss_log->info("Found User %015" PRIu64 "\n",imsi); + hss_ue_ctx_t* ue_ctx = ue_ctx_it->second; + m_hss_log->info("Found User %015" PRIu64 "\n", imsi); memcpy(k, ue_ctx->key, 16); memcpy(amf, ue_ctx->amf, 2); memcpy(opc, ue_ctx->opc, 16); memcpy(sqn, ue_ctx->sqn, 6); - return true; } -bool -hss::resync_sqn(uint64_t imsi, uint8_t *auts) +bool hss::resync_sqn(uint64_t imsi, uint8_t* auts) { bool ret = false; - switch (m_auth_algo) - { - case HSS_ALGO_XOR: - ret = resync_sqn_xor(imsi, auts); - break; - case HSS_ALGO_MILENAGE: - ret = resync_sqn_milenage(imsi, auts); - break; + switch (m_auth_algo) { + case HSS_ALGO_XOR: + ret = resync_sqn_xor(imsi, auts); + break; + case HSS_ALGO_MILENAGE: + ret = resync_sqn_milenage(imsi, auts); + break; } increment_seq_after_resync(imsi); return ret; } -bool -hss::resync_sqn_xor(uint64_t imsi, uint8_t *auts) +bool hss::resync_sqn_xor(uint64_t imsi, uint8_t* auts) { m_hss_log->error("XOR SQN synchronization not supported yet\n"); m_hss_log->console("XOR SQNs synchronization not supported yet\n"); return false; } - -bool -hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) +bool hss::resync_sqn_milenage(uint64_t imsi, uint8_t* auts) { uint8_t last_rand[16]; uint8_t ak[6]; @@ -558,19 +471,18 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) uint8_t opc[16]; uint8_t sqn[6]; - if(!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) - { + if (!get_k_amf_opc_sqn(imsi, k, amf, opc, sqn)) { return false; } get_last_rand(imsi, last_rand); - for(int i=0; i<6; i++){ + for (int i = 0; i < 6; i++) { sqn_ms_xor_ak[i] = auts[i]; } - for(int i=0; i<8; i++){ - mac_s[i] = auts[i+6]; + for (int i = 0; i < 8; i++) { + mac_s[i] = auts[i + 6]; } m_hss_log->debug_hex(k, 16, "User Key : "); @@ -580,62 +492,55 @@ hss::resync_sqn_milenage(uint64_t imsi, uint8_t *auts) m_hss_log->debug_hex(sqn_ms_xor_ak, 6, "SQN xor AK : "); m_hss_log->debug_hex(mac_s, 8, "MAC : "); - security_milenage_f5_star(k, opc, last_rand, ak); + srslte::security_milenage_f5_star(k, opc, last_rand, ak); m_hss_log->debug_hex(ak, 6, "Resynch AK : "); uint8_t sqn_ms[6]; - for(int i=0; i<6; i++){ + for (int i = 0; i < 6; i++) { sqn_ms[i] = sqn_ms_xor_ak[i] ^ ak[i]; } m_hss_log->debug_hex(sqn_ms, 6, "SQN MS : "); - m_hss_log->debug_hex(sqn , 6, "SQN HE : "); + m_hss_log->debug_hex(sqn, 6, "SQN HE : "); m_hss_log->debug_hex(amf, 2, "AMF : "); uint8_t mac_s_tmp[8]; - for(int i=0; i<2; i++){ + for (int i = 0; i < 2; i++) { amf[i] = 0; } - security_milenage_f1_star(k, opc, last_rand, sqn_ms, amf, mac_s_tmp); - + srslte::security_milenage_f1_star(k, opc, last_rand, sqn_ms, amf, mac_s_tmp); m_hss_log->debug_hex(mac_s_tmp, 8, "MAC calc : "); set_sqn(imsi, sqn_ms); - return true; } -void -hss::increment_ue_sqn(uint64_t imsi) +void hss::increment_ue_sqn(uint64_t imsi) { - hss_ue_ctx_t *ue_ctx = NULL; - bool ret = get_ue_ctx(imsi, &ue_ctx); - if(ret == false) - { + hss_ue_ctx_t* ue_ctx = NULL; + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { return; } - increment_sqn(ue_ctx->sqn,ue_ctx->sqn); + increment_sqn(ue_ctx->sqn, ue_ctx->sqn); m_hss_log->debug("Incremented SQN -- IMSI: %015" PRIu64 "\n", imsi); m_hss_log->debug_hex(ue_ctx->sqn, 6, "SQN: "); } -void -hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn) +void hss::increment_sqn(uint8_t* sqn, uint8_t* next_sqn) { // The following SQN incrementation function is implemented according to 3GPP TS 33.102 version 11.5.1 Annex C - uint64_t seq; uint64_t ind; uint64_t sqn64; - sqn64 =0; + sqn64 = 0; - for(int i=0; i<6; i++) - { - sqn64 |= (uint64_t)sqn[i] << (5-i)*8; + for (int i = 0; i < 6; i++) { + sqn64 |= (uint64_t)sqn[i] << (5 - i) * 8; } seq = sqn64 >> LTE_FDD_ENB_IND_HE_N_BITS; @@ -649,40 +554,31 @@ hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn) nextind = (ind + 1) % LTE_FDD_ENB_IND_HE_MAX_VALUE; nextsqn = (nextseq << LTE_FDD_ENB_IND_HE_N_BITS) | nextind; - for(int i=0; i<6; i++) - { - next_sqn[i] = (nextsqn >> (5-i)*8) & 0xFF; + for (int i = 0; i < 6; i++) { + next_sqn[i] = (nextsqn >> (5 - i) * 8) & 0xFF; } - return; - } - -void -hss::increment_seq_after_resync(uint64_t imsi) +void hss::increment_seq_after_resync(uint64_t imsi) { - -// This function only increment the SEQ part of the SQN for resynchronization purpose - - hss_ue_ctx_t *ue_ctx = NULL; - bool ret = get_ue_ctx(imsi, &ue_ctx); - if(ret == false) - { + // This function only increment the SEQ part of the SQN for resynchronization purpose + hss_ue_ctx_t* ue_ctx = NULL; + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { return; } - uint8_t *sqn = ue_ctx->sqn; + uint8_t* sqn = ue_ctx->sqn; uint64_t seq; uint64_t ind; uint64_t sqn64; - sqn64 =0; + sqn64 = 0; - for(int i=0; i<6; i++) - { - sqn64 |= (uint64_t)sqn[i] << (5-i)*8; + for (int i = 0; i < 6; i++) { + sqn64 |= (uint64_t)sqn[i] << (5 - i) * 8; } seq = sqn64 >> LTE_FDD_ENB_IND_HE_N_BITS; @@ -694,70 +590,55 @@ hss::increment_seq_after_resync(uint64_t imsi) nextseq = (seq + 1) % LTE_FDD_ENB_SEQ_HE_MAX_VALUE; nextsqn = (nextseq << LTE_FDD_ENB_IND_HE_N_BITS) | ind; - for(int i=0; i<6; i++) - { - sqn[i] = (nextsqn >> (5-i)*8) & 0xFF; + for (int i = 0; i < 6; i++) { + sqn[i] = (nextsqn >> (5 - i) * 8) & 0xFF; } - return; - } - - -void -hss::set_sqn(uint64_t imsi, uint8_t *sqn) +void hss::set_sqn(uint64_t imsi, uint8_t* sqn) { - hss_ue_ctx_t *ue_ctx = NULL; - bool ret = get_ue_ctx(imsi, &ue_ctx); - if(ret == false) - { + hss_ue_ctx_t* ue_ctx = NULL; + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { return; } memcpy(ue_ctx->sqn, sqn, 6); } -void -hss::set_last_rand(uint64_t imsi, uint8_t *rand) +void hss::set_last_rand(uint64_t imsi, uint8_t* rand) { - hss_ue_ctx_t *ue_ctx = NULL; - bool ret = get_ue_ctx(imsi, &ue_ctx); - if(ret == false) - { + hss_ue_ctx_t* ue_ctx = NULL; + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { return; } memcpy(ue_ctx->last_rand, rand, 16); - } -void -hss::get_last_rand(uint64_t imsi, uint8_t *rand) +void hss::get_last_rand(uint64_t imsi, uint8_t* rand) { - hss_ue_ctx_t *ue_ctx = NULL; - bool ret = get_ue_ctx(imsi, &ue_ctx); - if(ret == false) - { + hss_ue_ctx_t* ue_ctx = NULL; + bool ret = get_ue_ctx(imsi, &ue_ctx); + if (ret == false) { return; } memcpy(rand, ue_ctx->last_rand, 16); } -void -hss::gen_rand(uint8_t rand_[16]) +void hss::gen_rand(uint8_t rand_[16]) { - for(int i=0;i<16;i++) - { - rand_[i]=rand()%256; //Pulls on byte at a time. It's slow, but does not depend on RAND_MAX. + for (int i = 0; i < 16; i++) { + rand_[i] = rand() % 256; // Pulls on byte at a time. It's slow, but does not depend on RAND_MAX. } return; } -bool hss::get_ue_ctx(uint64_t imsi, hss_ue_ctx_t **ue_ctx) +bool hss::get_ue_ctx(uint64_t imsi, hss_ue_ctx_t** ue_ctx) { - std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); - if(ue_ctx_it == m_imsi_to_ue_ctx.end()) - { - m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n",imsi); + std::map::iterator ue_ctx_it = m_imsi_to_ue_ctx.find(imsi); + if (ue_ctx_it == m_imsi_to_ue_ctx.end()) { + m_hss_log->info("User not found. IMSI: %015" PRIu64 "\n", imsi); return false; } @@ -766,43 +647,37 @@ bool hss::get_ue_ctx(uint64_t imsi, hss_ue_ctx_t **ue_ctx) } /* Helper functions*/ -std::vector -hss::split_string(const std::string &str, char delimiter) +std::vector hss::split_string(const std::string& str, char delimiter) { std::vector tokens; - std::string token; - std::istringstream tokenStream(str); + std::string token; + std::istringstream tokenStream(str); - while (std::getline(tokenStream, token, delimiter)) - { - tokens.push_back(token); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); } return tokens; } -void -hss::get_uint_vec_from_hex_str(const std::string &key_str, uint8_t *key, uint len) +void hss::get_uint_vec_from_hex_str(const std::string& key_str, uint8_t* key, uint len) { - const char *pos = key_str.c_str(); + const char* pos = key_str.c_str(); for (uint count = 0; count < len; count++) { sscanf(pos, "%2hhx", &key[count]); pos += 2; } - return; } - -std::string -hss::hex_string(uint8_t *hex, int size) +std::string hss::hex_string(uint8_t* hex, int size) { std::stringstream ss; ss << std::hex << std::setfill('0'); - for(int i=0;i(hex[i]); } return ss.str(); } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index 1dcf1cf69..2cdafac09 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -21,20 +21,20 @@ * and at http://www.gnu.org/licenses/. * */ -#include -#include -#include -#include -#include -#include -#include -#include "srslte/common/crash_handler.h" -#include "srslte/common/bcd_helpers.h" -#include "srslte/common/config_file.h" -#include "srslte/build_info.h" -#include "srsepc/hdr/mme/mme.h" #include "srsepc/hdr/hss/hss.h" +#include "srsepc/hdr/mme/mme.h" #include "srsepc/hdr/spgw/spgw.h" +#include "srslte/build_info.h" +#include "srslte/common/bcd_helpers.h" +#include "srslte/common/config_file.h" +#include "srslte/common/crash_handler.h" +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace srsepc; @@ -42,43 +42,41 @@ namespace bpo = boost::program_options; bool running = true; -void -sig_int_handler(int signo){ +void sig_int_handler(int signo) +{ running = false; } typedef struct { - std::string nas_level; - int nas_hex_limit; - std::string s1ap_level; - int s1ap_hex_limit; - std::string gtpc_level; - int gtpc_hex_limit; - std::string spgw_level; - int spgw_hex_limit; - std::string hss_level; - int hss_hex_limit; - std::string all_level; - int all_hex_limit; - std::string filename; -}log_args_t; - - -typedef struct{ - mme_args_t mme_args; - hss_args_t hss_args; - spgw_args_t spgw_args; - log_args_t log_args; -}all_args_t; + std::string nas_level; + int nas_hex_limit; + std::string s1ap_level; + int s1ap_hex_limit; + std::string gtpc_level; + int gtpc_hex_limit; + std::string spgw_level; + int spgw_hex_limit; + std::string hss_level; + int hss_hex_limit; + std::string all_level; + int all_hex_limit; + std::string filename; +} log_args_t; + +typedef struct { + mme_args_t mme_args; + hss_args_t hss_args; + spgw_args_t spgw_args; + log_args_t log_args; +} all_args_t; /********************************************************************** * Program arguments processing ***********************************************************************/ string config_file; -void -parse_args(all_args_t *args, int argc, char* argv[]) { - +void parse_args(all_args_t* args, int argc, char* argv[]) +{ string mme_name; string mme_code; string mme_group; @@ -107,7 +105,6 @@ parse_args(all_args_t *args, int argc, char* argv[]) { // Command line or config file options bpo::options_description common("Configuration options"); common.add_options() - ("mme.mme_code", bpo::value(&mme_code)->default_value("0x01"), "MME Code") ("mme.name", bpo::value(&mme_name)->default_value("srsmme01"), "MME Name") ("mme.mme_group", bpo::value(&mme_group)->default_value("0x01"), "Cell ID") @@ -136,10 +133,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("log.gtpc_hex_limit", bpo::value(&args->log_args.gtpc_hex_limit), "MME GTPC log hex dump limit") ("log.spgw_level", bpo::value(&args->log_args.spgw_level), "SPGW log level") ("log.spgw_hex_limit", bpo::value(&args->log_args.spgw_hex_limit), "SPGW log hex dump limit") - //("log.gtpu_level", bpo::value(&args->log.gtpu_level), "GTPU log level") ("log.hss_level", bpo::value(&args->log_args.hss_level), "HSS log level") ("log.hss_hex_limit", bpo::value(&args->log_args.hss_hex_limit), "HSS log hex dump limit") - //("log.gtpu_hex_limit",bpo::value(&args->log.gtpu_hex_limit), "GTPU log hex dump limit") ("log.all_level", bpo::value(&args->log_args.all_level)->default_value("info"), "ALL log level") ("log.all_hex_limit", bpo::value(&args->log_args.all_hex_limit)->default_value(32), "ALL log hex dump limit") @@ -150,7 +145,7 @@ parse_args(all_args_t *args, int argc, char* argv[]) { // Positional options - config file location bpo::options_description position("Positional options"); position.add_options() - ("config_file", bpo::value< string >(&config_file), "MME configuration file") + ("config_file", bpo::value< string >(&config_file), "MME configuration file") ; bpo::positional_options_description p; p.add("config_file", -1); @@ -164,16 +159,16 @@ parse_args(all_args_t *args, int argc, char* argv[]) { try { bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm); bpo::notify(vm); - } catch(bpo::error &e) { - cerr<< e.what() << endl; + } catch (bpo::error& e) { + cerr << e.what() << endl; exit(1); } // help option was given - print usage and exit if (vm.count("help")) { - cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; - cout << common << endl << general << endl; - exit(0); + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + cout << common << endl << general << endl; + exit(0); } // if no config file given, check users home path @@ -184,10 +179,10 @@ parse_args(all_args_t *args, int argc, char* argv[]) { } } - //Parsing Config File + // Parsing Config File cout << "Reading configuration file " << config_file << "..." << endl; ifstream conf(config_file.c_str(), ios::in); - if(conf.fail()) { + if (conf.fail()) { cout << "Failed to read configuration file " << config_file << " - exiting" << endl; exit(1); } @@ -212,37 +207,39 @@ parse_args(all_args_t *args, int argc, char* argv[]) { sstr << std::hex << vm["mme.tac"].as(); sstr >> args->mme_args.s1ap_args.tac; } + // Convert MCC/MNC strings - if(!srslte::string_to_mcc(mcc, &args->mme_args.s1ap_args.mcc)) { + if (!srslte::string_to_mcc(mcc, &args->mme_args.s1ap_args.mcc)) { cout << "Error parsing mme.mcc:" << mcc << " - must be a 3-digit string." << endl; } - if(!srslte::string_to_mnc(mnc, &args->mme_args.s1ap_args.mnc)) { + if (!srslte::string_to_mnc(mnc, &args->mme_args.s1ap_args.mnc)) { cout << "Error parsing mme.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } // Convert MCC/MNC strings - if(!srslte::string_to_mcc(mcc, &args->hss_args.mcc)) { + if (!srslte::string_to_mcc(mcc, &args->hss_args.mcc)) { cout << "Error parsing mme.mcc:" << mcc << " - must be a 3-digit string." << endl; } - if(!srslte::string_to_mnc(mnc, &args->hss_args.mnc)) { + if (!srslte::string_to_mnc(mnc, &args->hss_args.mnc)) { cout << "Error parsing mme.mnc:" << mnc << " - must be a 2 or 3-digit string." << endl; } - if(boost::iequals(encryption_algo, "eea0")){ + if (boost::iequals(encryption_algo, "eea0")) { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; - } else if (boost::iequals(encryption_algo, "eea1")){ + } else if (boost::iequals(encryption_algo, "eea1")) { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; - } else if (boost::iequals(encryption_algo, "eea2")){ + } else if (boost::iequals(encryption_algo, "eea2")) { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; - } else{ + } else { args->mme_args.s1ap_args.encryption_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; cout << "Error parsing mme.encryption_algo:" << encryption_algo << " - must be EEA0, EEA1, or EEA2." << endl; cout << "Using default mme.encryption_algo: EEA0" << endl; } - if (boost::iequals(integrity_algo, "eia0")){ + if (boost::iequals(integrity_algo, "eia0")) { args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0; - cout << "Warning parsing mme.integrity_algo:" << encryption_algo << " - EIA0 will not supported by UEs use EIA1 or EIA2" << endl; + cout << "Warning parsing mme.integrity_algo:" << encryption_algo + << " - EIA0 will not supported by UEs use EIA1 or EIA2" << endl; } else if (boost::iequals(integrity_algo, "eia1")) { args->mme_args.s1ap_args.integrity_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; } else if (boost::iequals(integrity_algo, "eia2")) { @@ -254,49 +251,49 @@ parse_args(all_args_t *args, int argc, char* argv[]) { } args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; - args->mme_args.s1ap_args.mme_name = mme_name; - args->mme_args.s1ap_args.dns_addr = dns_addr; - args->mme_args.s1ap_args.mme_apn = mme_apn; - args->spgw_args.gtpu_bind_addr = spgw_bind_addr; - args->spgw_args.sgi_if_addr = sgi_if_addr; - args->spgw_args.sgi_if_name = sgi_if_name; - args->hss_args.db_file = hss_db_file; - args->hss_args.auth_algo = hss_auth_algo; + args->mme_args.s1ap_args.mme_name = mme_name; + args->mme_args.s1ap_args.dns_addr = dns_addr; + args->mme_args.s1ap_args.mme_apn = mme_apn; + args->spgw_args.gtpu_bind_addr = spgw_bind_addr; + args->spgw_args.sgi_if_addr = sgi_if_addr; + args->spgw_args.sgi_if_name = sgi_if_name; + args->hss_args.db_file = hss_db_file; + args->hss_args.auth_algo = hss_auth_algo; // Apply all_level to any unset layers if (vm.count("log.all_level")) { - if(!vm.count("log.nas_level")) { + if (!vm.count("log.nas_level")) { args->log_args.nas_level = args->log_args.all_level; } - if(!vm.count("log.s1ap_level")) { + if (!vm.count("log.s1ap_level")) { args->log_args.s1ap_level = args->log_args.all_level; } - if(!vm.count("log.gtpc_level")) { + if (!vm.count("log.gtpc_level")) { args->log_args.gtpc_level = args->log_args.all_level; } - if(!vm.count("log.spgw_level")) { + if (!vm.count("log.spgw_level")) { args->log_args.spgw_level = args->log_args.all_level; } - if(!vm.count("log.hss_level")) { + if (!vm.count("log.hss_level")) { args->log_args.hss_level = args->log_args.all_level; } } // Apply all_hex_limit to any unset layers if (vm.count("log.all_hex_limit")) { - if(!vm.count("log.s1ap_hex_limit")) { + if (!vm.count("log.s1ap_hex_limit")) { args->log_args.s1ap_hex_limit = args->log_args.all_hex_limit; } - if(!vm.count("log.gtpc_hex_limit")) { + if (!vm.count("log.gtpc_hex_limit")) { args->log_args.gtpc_hex_limit = args->log_args.all_hex_limit; } - if(!vm.count("log.spgw_hex_limit")) { + if (!vm.count("log.spgw_hex_limit")) { args->log_args.spgw_hex_limit = args->log_args.all_hex_limit; } - if(!vm.count("log.hss_hex_limit")) { + if (!vm.count("log.hss_hex_limit")) { args->log_args.hss_hex_limit = args->log_args.all_hex_limit; } - if(!vm.count("log.nas_hex_limit")) { + if (!vm.count("log.nas_hex_limit")) { args->log_args.nas_hex_limit = args->log_args.all_hex_limit; } } @@ -310,21 +307,20 @@ parse_args(all_args_t *args, int argc, char* argv[]) { return; } -srslte::LOG_LEVEL_ENUM -level(std::string l) +srslte::LOG_LEVEL_ENUM level(std::string l) { boost::to_upper(l); - if("NONE" == l){ + if ("NONE" == l) { return srslte::LOG_LEVEL_NONE; - }else if("ERROR" == l){ + } else if ("ERROR" == l) { return srslte::LOG_LEVEL_ERROR; - }else if("WARNING" == l){ + } else if ("WARNING" == l) { return srslte::LOG_LEVEL_WARNING; - }else if("INFO" == l){ + } else if ("INFO" == l) { return srslte::LOG_LEVEL_INFO; - }else if("DEBUG" == l){ + } else if ("DEBUG" == l) { return srslte::LOG_LEVEL_DEBUG; - }else{ + } else { return srslte::LOG_LEVEL_NONE; } } @@ -349,8 +345,7 @@ std::string get_build_string() return ss.str(); } -int -main (int argc,char * argv[] ) +int main(int argc, char* argv[]) { signal(SIGINT, sig_int_handler); signal(SIGTERM, sig_int_handler); @@ -359,15 +354,15 @@ main (int argc,char * argv[] ) // print build info cout << endl << get_build_string() << endl; - cout << endl <<"--- Software Radio Systems EPC ---" << endl << endl; + cout << endl << "--- Software Radio Systems EPC ---" << endl << endl; srslte_debug_handle_crash(argc, argv); all_args_t args; - parse_args(&args, argc, argv); + parse_args(&args, argc, argv); srslte::logger_stdout logger_stdout; srslte::logger_file logger_file; - srslte::logger *logger; + srslte::logger* logger; /*Init logger*/ if (!args.log_args.filename.compare("stdout")) { @@ -381,52 +376,51 @@ main (int argc,char * argv[] ) } srslte::log_filter nas_log; - nas_log.init("NAS ",logger); + nas_log.init("NAS ", logger); nas_log.set_level(level(args.log_args.nas_level)); nas_log.set_hex_limit(args.log_args.nas_hex_limit); srslte::log_filter s1ap_log; - s1ap_log.init("S1AP",logger); + s1ap_log.init("S1AP", logger); s1ap_log.set_level(level(args.log_args.s1ap_level)); s1ap_log.set_hex_limit(args.log_args.s1ap_hex_limit); srslte::log_filter mme_gtpc_log; - mme_gtpc_log.init("GTPC",logger); + mme_gtpc_log.init("GTPC", logger); mme_gtpc_log.set_level(level(args.log_args.gtpc_level)); mme_gtpc_log.set_hex_limit(args.log_args.gtpc_hex_limit); srslte::log_filter hss_log; - hss_log.init("HSS ",logger); + hss_log.init("HSS ", logger); hss_log.set_level(level(args.log_args.hss_level)); hss_log.set_hex_limit(args.log_args.hss_hex_limit); srslte::log_filter spgw_log; - spgw_log.init("SPGW",logger); + spgw_log.init("SPGW", logger); spgw_log.set_level(level(args.log_args.spgw_level)); spgw_log.set_hex_limit(args.log_args.spgw_hex_limit); - - hss *hss = hss::get_instance(); - if (hss->init(&args.hss_args,&hss_log)) { + hss* hss = hss::get_instance(); + if (hss->init(&args.hss_args, &hss_log)) { cout << "Error initializing HSS" << endl; exit(1); } - mme *mme = mme::get_instance(); - if (mme->init(&args.mme_args, &nas_log, &s1ap_log, &mme_gtpc_log, hss)) { + mme* mme = mme::get_instance(); + if (mme->init(&args.mme_args, &nas_log, &s1ap_log, &mme_gtpc_log)) { cout << "Error initializing MME" << endl; exit(1); } - spgw *spgw = spgw::get_instance(); - if (spgw->init(&args.spgw_args,&spgw_log)) { + spgw* spgw = spgw::get_instance(); + if (spgw->init(&args.spgw_args, &spgw_log)) { cout << "Error initializing SP-GW" << endl; exit(1); } mme->start(); spgw->start(); - while(running) { + while (running) { sleep(1); } @@ -437,6 +431,6 @@ main (int argc,char * argv[] ) hss->stop(); hss->cleanup(); - cout << std::endl <<"--- exiting ---" << endl; + cout << std::endl << "--- exiting ---" << endl; return 0; } diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index f9de83830..5d64a2e27 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -24,22 +24,21 @@ * */ -#include //TODO Remove +#include "srsepc/hdr/mme/mme.h" #include -#include -#include +#include // for printing uint64_t #include -#include "srsepc/hdr/mme/mme.h" +#include +#include -namespace srsepc{ +namespace srsepc { -mme* mme::m_instance = NULL; +mme* mme::m_instance = NULL; pthread_mutex_t mme_instance_mutex = PTHREAD_MUTEX_INITIALIZER; -mme::mme(): - m_running(false) +mme::mme() : m_running(false) { - m_pool = srslte::byte_buffer_pool::get_instance(); + m_pool = srslte::byte_buffer_pool::get_instance(); return; } @@ -48,40 +47,39 @@ mme::~mme() return; } -mme* -mme::get_instance(void) +mme* mme::get_instance(void) { pthread_mutex_lock(&mme_instance_mutex); - if(NULL == m_instance) { + if (NULL == m_instance) { m_instance = new mme(); } pthread_mutex_unlock(&mme_instance_mutex); - return(m_instance); + return (m_instance); } -void -mme::cleanup(void) +void mme::cleanup(void) { pthread_mutex_lock(&mme_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&mme_instance_mutex); } -int -mme::init(mme_args_t* args, srslte::log_filter *nas_log, srslte::log_filter *s1ap_log, srslte::log_filter *mme_gtpc_log, hss_interface_nas * hss) +int mme::init(mme_args_t* args, + srslte::log_filter* nas_log, + srslte::log_filter* s1ap_log, + srslte::log_filter* mme_gtpc_log) { - /*Init logger*/ - m_nas_log = nas_log; - m_s1ap_log = s1ap_log; + m_nas_log = nas_log; + m_s1ap_log = s1ap_log; m_mme_gtpc_log = mme_gtpc_log; /*Init S1AP*/ m_s1ap = s1ap::get_instance(); - if (m_s1ap->init(args->s1ap_args, nas_log, s1ap_log, hss)) { + if (m_s1ap->init(args->s1ap_args, nas_log, s1ap_log)) { m_s1ap_log->error("Error initializing MME S1APP\n"); exit(-1); } @@ -99,8 +97,7 @@ mme::init(mme_args_t* args, srslte::log_filter *nas_log, srslte::log_filter *s1a return 0; } -void -mme::stop() +void mme::stop() { if (m_running) { m_s1ap->stop(); @@ -112,52 +109,49 @@ mme::stop() return; } -void -mme::run_thread() +void mme::run_thread() { - srslte::byte_buffer_t *pdu = m_pool->allocate("mme::run_thread"); - uint32_t sz = SRSLTE_MAX_BUFFER_SIZE_BYTES - SRSLTE_BUFFER_HEADER_OFFSET; + srslte::byte_buffer_t* pdu = m_pool->allocate("mme::run_thread"); + uint32_t sz = SRSLTE_MAX_BUFFER_SIZE_BYTES - SRSLTE_BUFFER_HEADER_OFFSET; - struct sockaddr_in enb_addr; + struct sockaddr_in enb_addr; struct sctp_sndrcvinfo sri; - socklen_t fromlen = sizeof(enb_addr); + socklen_t fromlen = sizeof(enb_addr); bzero(&enb_addr, sizeof(enb_addr)); int rd_sz; - int msg_flags=0; + int msg_flags = 0; - //Mark the thread as running - m_running=true; + // Mark the thread as running + m_running = true; - //Get S1-MME socket + // Get S1-MME socket int s1mme = m_s1ap->get_s1_mme(); - while(m_running) - { + while (m_running) { m_s1ap_log->debug("Waiting for SCTP Msg\n"); pdu->reset(); - rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz,(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); - if (rd_sz == -1 && errno != EAGAIN){ + rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz, (struct sockaddr*)&enb_addr, &fromlen, &sri, &msg_flags); + if (rd_sz == -1 && errno != EAGAIN) { m_s1ap_log->error("Error reading from SCTP socket: %s", strerror(errno)); - } - else if (rd_sz == -1 && errno == EAGAIN){ + } else if (rd_sz == -1 && errno == EAGAIN) { m_s1ap_log->debug("Socket timeout reached"); } else { if (msg_flags & MSG_NOTIFICATION) { - //Received notification - union sctp_notification *notification = (union sctp_notification*)pdu->msg; + // Received notification + union sctp_notification* notification = (union sctp_notification*)pdu->msg; m_s1ap_log->debug("SCTP Notification %d\n", notification->sn_header.sn_type); if (notification->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { - m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); - m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n",sri.sinfo_assoc_id); + m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); + m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); m_s1ap->delete_enb_ctx(sri.sinfo_assoc_id); } } else { - //Received data + // Received data pdu->N_bytes = rd_sz; m_s1ap_log->info("Received S1AP msg. Size: %d\n", pdu->N_bytes); - m_s1ap->handle_s1ap_rx_pdu(pdu,&sri); + m_s1ap->handle_s1ap_rx_pdu(pdu, &sri); } } } return; } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 570dbf2f8..8d38925cb 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -24,52 +24,48 @@ * */ -#include -#include // for printing uint64_t -#include "srslte/asn1/gtpc.h" #include "srsepc/hdr/mme/mme_gtpc.h" #include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/spgw/spgw.h" +#include "srslte/asn1/gtpc.h" +#include // for printing uint64_t -namespace srsepc{ +namespace srsepc { -mme_gtpc* mme_gtpc::m_instance = NULL; +mme_gtpc* mme_gtpc::m_instance = NULL; pthread_mutex_t mme_gtpc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; - mme_gtpc::mme_gtpc() { + return; } mme_gtpc::~mme_gtpc() { + return; } -mme_gtpc* -mme_gtpc::get_instance(void) +mme_gtpc* mme_gtpc::get_instance(void) { pthread_mutex_lock(&mme_gtpc_instance_mutex); - if(NULL == m_instance) { + if (NULL == m_instance) { m_instance = new mme_gtpc(); } pthread_mutex_unlock(&mme_gtpc_instance_mutex); - return(m_instance); + return (m_instance); } -void -mme_gtpc::cleanup(void) +void mme_gtpc::cleanup(void) { pthread_mutex_lock(&mme_gtpc_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&mme_gtpc_instance_mutex); } - -bool -mme_gtpc::init(srslte::log_filter *mme_gtpc_log) +bool mme_gtpc::init(srslte::log_filter* mme_gtpc_log) { /*Init log*/ @@ -77,8 +73,7 @@ mme_gtpc::init(srslte::log_filter *mme_gtpc_log) m_next_ctrl_teid = 1; - m_s1ap = s1ap::get_instance(); - m_mme_gtpc_ip = inet_addr("127.0.0.1");//FIXME At the moment, the GTP-C messages are not sent over the wire. So this parameter is not used. + m_s1ap = s1ap::get_instance(); m_spgw = spgw::get_instance(); m_mme_gtpc_log->info("MME GTP-C Initialized\n"); @@ -86,32 +81,30 @@ mme_gtpc::init(srslte::log_filter *mme_gtpc_log) return true; } -uint32_t -mme_gtpc::get_new_ctrl_teid() +uint32_t mme_gtpc::get_new_ctrl_teid() { - return m_next_ctrl_teid++; //FIXME Use a Id pool? + return m_next_ctrl_teid++; // FIXME Use a Id pool? } -bool -mme_gtpc::send_create_session_request(uint64_t imsi) +bool mme_gtpc::send_create_session_request(uint64_t imsi) { m_mme_gtpc_log->info("Sending Create Session Request.\n"); m_mme_gtpc_log->console("Sending Create Session Request.\n"); - struct srslte::gtpc_pdu cs_req_pdu; - struct srslte::gtpc_create_session_request *cs_req = &cs_req_pdu.choice.create_session_request; + struct srslte::gtpc_pdu cs_req_pdu; + struct srslte::gtpc_create_session_request* cs_req = &cs_req_pdu.choice.create_session_request; struct srslte::gtpc_pdu cs_resp_pdu; - //Initialize GTP-C message to zero + // Initialize GTP-C message to zero bzero(&cs_req_pdu, sizeof(struct srslte::gtpc_pdu)); - //Setup GTP-C Header. FIXME: Length, sequence and other fields need to be added. - cs_req_pdu.header.piggyback = false; + // Setup GTP-C Header. FIXME: Length, sequence and other fields need to be added. + cs_req_pdu.header.piggyback = false; cs_req_pdu.header.teid_present = true; - cs_req_pdu.header.teid = 0; //Send create session request to the butler TEID + cs_req_pdu.header.teid = 0; // Send create session request to the butler TEID cs_req_pdu.header.type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_REQUEST; - //Setup GTP-C Create Session Request IEs + // Setup GTP-C Create Session Request IEs cs_req->imsi = imsi; // Control TEID allocated cs_req->sender_f_teid.teid = get_new_ctrl_teid(); @@ -123,63 +116,63 @@ mme_gtpc::send_create_session_request(uint64_t imsi) m_mme_gtpc_log->console("Creating Session Response -- MME control TEID: %d\n", cs_req->sender_f_teid.teid); // APN - strncpy(cs_req->apn, m_s1ap->m_s1ap_args.mme_apn.c_str(), sizeof(cs_req->apn)-1); - cs_req->apn[sizeof(cs_req->apn)-1] = 0; + strncpy(cs_req->apn, m_s1ap->m_s1ap_args.mme_apn.c_str(), sizeof(cs_req->apn) - 1); + cs_req->apn[sizeof(cs_req->apn) - 1] = 0; // RAT Type - //cs_req->rat_type = srslte::GTPC_RAT_TYPE::EUTRAN; + // cs_req->rat_type = srslte::GTPC_RAT_TYPE::EUTRAN; - //Bearer QoS + // Bearer QoS cs_req->eps_bearer_context_created.ebi = 5; - //Check whether this UE is already registed + // Check whether this UE is already registed std::map::iterator it = m_imsi_to_gtpc_ctx.find(imsi); if (it != m_imsi_to_gtpc_ctx.end()) { m_mme_gtpc_log->warning("Create Session Request being called for an UE with an active GTP-C connection.\n"); m_mme_gtpc_log->warning("Deleting previous GTP-C connection.\n"); std::map::iterator jt = m_mme_ctr_teid_to_imsi.find(it->second.mme_ctr_fteid.teid); if (jt == m_mme_ctr_teid_to_imsi.end()) { - m_mme_gtpc_log->error("Could not find IMSI from MME Ctrl TEID. MME Ctr TEID: %d\n", it->second.mme_ctr_fteid.teid); + m_mme_gtpc_log->error("Could not find IMSI from MME Ctrl TEID. MME Ctr TEID: %d\n", + it->second.mme_ctr_fteid.teid); } else { m_mme_ctr_teid_to_imsi.erase(jt); } m_imsi_to_gtpc_ctx.erase(it); - //No need to send delete session request to the SPGW. - //The create session request will be interpreted as a new request and SPGW will delete locally in existing context. + // No need to send delete session request to the SPGW. + // The create session request will be interpreted as a new request and SPGW will delete locally in existing context. } - //Save RX Control TEID - m_mme_ctr_teid_to_imsi.insert(std::pair(cs_req->sender_f_teid.teid, imsi)); + // Save RX Control TEID + m_mme_ctr_teid_to_imsi.insert(std::pair(cs_req->sender_f_teid.teid, imsi)); - //Save GTP-C context + // Save GTP-C context gtpc_ctx_t gtpc_ctx; - bzero(>pc_ctx,sizeof(gtpc_ctx_t)); + bzero(>pc_ctx, sizeof(gtpc_ctx_t)); gtpc_ctx.mme_ctr_fteid = cs_req->sender_f_teid; - m_imsi_to_gtpc_ctx.insert(std::pair(imsi,gtpc_ctx)); + m_imsi_to_gtpc_ctx.insert(std::pair(imsi, gtpc_ctx)); m_spgw->handle_create_session_request(cs_req, &cs_resp_pdu); return true; } -bool -mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) +bool mme_gtpc::handle_create_session_response(srslte::gtpc_pdu* cs_resp_pdu) { - struct srslte::gtpc_create_session_response *cs_resp = & cs_resp_pdu->choice.create_session_response; + struct srslte::gtpc_create_session_response* cs_resp = &cs_resp_pdu->choice.create_session_response; m_mme_gtpc_log->info("Received Create Session Response\n"); m_mme_gtpc_log->console("Received Create Session Response\n"); if (cs_resp_pdu->header.type != srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE) { - m_mme_gtpc_log->warning("Could not create GTPC session. Not a create session response\n"); - //TODO Handle error - return false; + m_mme_gtpc_log->warning("Could not create GTPC session. Not a create session response\n"); + // TODO Handle error + return false; } if (cs_resp->cause.cause_value != srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED) { m_mme_gtpc_log->warning("Could not create GTPC session. Create Session Request not accepted\n"); - //TODO Handle error + // TODO Handle error return false; } - //Get IMSI from the control TEID - std::map::iterator id_it = m_mme_ctr_teid_to_imsi.find(cs_resp_pdu->header.teid); - if(id_it == m_mme_ctr_teid_to_imsi.end()) { + // Get IMSI from the control TEID + std::map::iterator id_it = m_mme_ctr_teid_to_imsi.find(cs_resp_pdu->header.teid); + if (id_it == m_mme_ctr_teid_to_imsi.end()) { m_mme_gtpc_log->warning("Could not find IMSI from Ctrl TEID.\n"); return false; } @@ -187,13 +180,13 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) m_mme_gtpc_log->info("MME GTPC Ctrl TEID %" PRIu64 ", IMSI %" PRIu64 "\n", cs_resp_pdu->header.teid, imsi); - //Get S-GW Control F-TEID + // Get S-GW Control F-TEID srslte::gtp_fteid_t sgw_ctr_fteid; sgw_ctr_fteid.teid = cs_resp_pdu->header.teid; - sgw_ctr_fteid.ipv4 = 0; //FIXME This is not used for now. In the future it will be obtained from the socket addr_info + sgw_ctr_fteid.ipv4 = 0; // FIXME This is not used for now. In the future it will be obtained from the socket addr_info - //Get S-GW S1-u F-TEID - if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ + // Get S-GW S1-u F-TEID + if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false) { m_mme_gtpc_log->error("Did not receive SGW S1-U F-TEID in create session response\n"); return false; } @@ -204,7 +197,7 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) m_mme_gtpc_log->console("Create Session Response -- SPGW S1-U Address: %s\n", inet_ntoa(s1u_addr)); m_mme_gtpc_log->info("Create Session Response -- SPGW S1-U Address: %s\n", inet_ntoa(s1u_addr)); - //Check UE Ipv4 address was allocated + // Check UE Ipv4 address was allocated if (cs_resp->paa_present != true) { m_mme_gtpc_log->error("PDN Adress Allocation not present\n"); return false; @@ -214,79 +207,76 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) return false; } - //Save create session response info to E-RAB context - nas *nas_ctx = m_s1ap->find_nas_ctx_from_imsi(imsi); - if(nas_ctx == NULL){ + // Save create session response info to E-RAB context + nas* nas_ctx = m_s1ap->find_nas_ctx_from_imsi(imsi); + if (nas_ctx == NULL) { m_mme_gtpc_log->error("Could not find UE context. IMSI %015lu\n", imsi); return false; } - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; - //Save UE IP to nas ctxt + // Save UE IP to nas ctxt emm_ctx->ue_ip.s_addr = cs_resp->paa.ipv4; - m_mme_gtpc_log->console("SPGW Allocated IP %s to ISMI %015lu\n",inet_ntoa(emm_ctx->ue_ip),emm_ctx->imsi); - //Save SGW ctrl F-TEID in GTP-C context - std::map::iterator it_g = m_imsi_to_gtpc_ctx.find(imsi); - if(it_g == m_imsi_to_gtpc_ctx.end()) { - //Could not find GTP-C Context + m_mme_gtpc_log->console("SPGW Allocated IP %s to ISMI %015lu\n", inet_ntoa(emm_ctx->ue_ip), emm_ctx->imsi); + + // Save SGW ctrl F-TEID in GTP-C context + std::map::iterator it_g = m_imsi_to_gtpc_ctx.find(imsi); + if (it_g == m_imsi_to_gtpc_ctx.end()) { + // Could not find GTP-C Context m_mme_gtpc_log->error("Could not find GTP-C context\n"); return false; } - gtpc_ctx_t *gtpc_ctx = &it_g->second; + gtpc_ctx_t* gtpc_ctx = &it_g->second; gtpc_ctx->sgw_ctr_fteid = sgw_ctr_fteid; - //Set EPS bearer context - //FIXME default EPS bearer is hard-coded - int default_bearer=5; - esm_ctx_t *esm_ctx = &nas_ctx->m_esm_ctx[default_bearer]; - esm_ctx->pdn_addr_alloc= cs_resp->paa; - esm_ctx->sgw_s1u_fteid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid; + // Set EPS bearer context + // FIXME default EPS bearer is hard-coded + int default_bearer = 5; + esm_ctx_t* esm_ctx = &nas_ctx->m_esm_ctx[default_bearer]; + esm_ctx->pdn_addr_alloc = cs_resp->paa; + esm_ctx->sgw_s1u_fteid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid; m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(nas_ctx, default_bearer); return true; } - -bool -mme_gtpc::send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, srslte::gtp_fteid_t *enb_fteid) +bool mme_gtpc::send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify, srslte::gtp_fteid_t* enb_fteid) { m_mme_gtpc_log->info("Sending GTP-C Modify bearer request\n"); srslte::gtpc_pdu mb_req_pdu; - std::map::iterator it = m_imsi_to_gtpc_ctx.find(imsi); + std::map::iterator it = m_imsi_to_gtpc_ctx.find(imsi); if (it == m_imsi_to_gtpc_ctx.end()) { m_mme_gtpc_log->error("Modify bearer request for UE without GTP-C connection\n"); return false; } - srslte::gtp_fteid_t sgw_ctr_fteid = it->second.sgw_ctr_fteid; + srslte::gtp_fteid_t sgw_ctr_fteid = it->second.sgw_ctr_fteid; - srslte::gtpc_header *header = &mb_req_pdu.header; - header->teid_present = true; - header->teid = sgw_ctr_fteid.teid; - header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; + srslte::gtpc_header* header = &mb_req_pdu.header; + header->teid_present = true; + header->teid = sgw_ctr_fteid.teid; + header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST; - srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu.choice.modify_bearer_request; - mb_req->eps_bearer_context_to_modify.ebi = erab_to_modify; + srslte::gtpc_modify_bearer_request* mb_req = &mb_req_pdu.choice.modify_bearer_request; + mb_req->eps_bearer_context_to_modify.ebi = erab_to_modify; mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4 = enb_fteid->ipv4; mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid = enb_fteid->teid; - m_mme_gtpc_log->info("GTP-C Modify bearer request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid ); + m_mme_gtpc_log->info("GTP-C Modify bearer request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid); struct in_addr addr; addr.s_addr = enb_fteid->ipv4; - m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x, IP %s\n", enb_fteid->teid, inet_ntoa(addr) ); + m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x, IP %s\n", enb_fteid->teid, inet_ntoa(addr)); - // srslte::gtpc_pdu mb_resp_pdu; - m_spgw->handle_modify_bearer_request(&mb_req_pdu,&mb_resp_pdu); + m_spgw->handle_modify_bearer_request(&mb_req_pdu, &mb_resp_pdu); handle_modify_bearer_response(&mb_resp_pdu); return true; } -void -mme_gtpc::handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu) +void mme_gtpc::handle_modify_bearer_response(srslte::gtpc_pdu* mb_resp_pdu) { - uint32_t mme_ctrl_teid = mb_resp_pdu->header.teid; - std::map::iterator imsi_it = m_mme_ctr_teid_to_imsi.find(mme_ctrl_teid); + uint32_t mme_ctrl_teid = mb_resp_pdu->header.teid; + std::map::iterator imsi_it = m_mme_ctr_teid_to_imsi.find(mme_ctrl_teid); if (imsi_it == m_mme_ctr_teid_to_imsi.end()) { m_mme_gtpc_log->error("Could not find IMSI from control TEID\n"); return; @@ -294,44 +284,43 @@ mme_gtpc::handle_modify_bearer_response(srslte::gtpc_pdu *mb_resp_pdu) uint8_t ebi = mb_resp_pdu->choice.modify_bearer_response.eps_bearer_context_modified.ebi; m_mme_gtpc_log->debug("Activating EPS bearer with id %d\n", ebi); - m_s1ap->activate_eps_bearer(imsi_it->second,ebi); + m_s1ap->activate_eps_bearer(imsi_it->second, ebi); return; } -bool -mme_gtpc::send_delete_session_request(uint64_t imsi) +bool mme_gtpc::send_delete_session_request(uint64_t imsi) { - m_mme_gtpc_log->info("Sending GTP-C Delete Session Request request. IMSI %" PRIu64 "\n",imsi); - srslte::gtpc_pdu del_req_pdu; + m_mme_gtpc_log->info("Sending GTP-C Delete Session Request request. IMSI %" PRIu64 "\n", imsi); + srslte::gtpc_pdu del_req_pdu; srslte::gtp_fteid_t sgw_ctr_fteid; srslte::gtp_fteid_t mme_ctr_fteid; - //Get S-GW Ctr TEID - std::map::iterator it_ctx = m_imsi_to_gtpc_ctx.find(imsi); + // Get S-GW Ctr TEID + std::map::iterator it_ctx = m_imsi_to_gtpc_ctx.find(imsi); if (it_ctx == m_imsi_to_gtpc_ctx.end()) { - m_mme_gtpc_log->error("Could not find GTP-C context to remove\n"); - return false; + m_mme_gtpc_log->error("Could not find GTP-C context to remove\n"); + return false; } - sgw_ctr_fteid = it_ctx->second.sgw_ctr_fteid; - mme_ctr_fteid = it_ctx->second.mme_ctr_fteid; - srslte::gtpc_header *header = &del_req_pdu.header; - header->teid_present = true; - header->teid = sgw_ctr_fteid.teid; - header->type = srslte::GTPC_MSG_TYPE_DELETE_SESSION_REQUEST; + sgw_ctr_fteid = it_ctx->second.sgw_ctr_fteid; + mme_ctr_fteid = it_ctx->second.mme_ctr_fteid; + srslte::gtpc_header* header = &del_req_pdu.header; + header->teid_present = true; + header->teid = sgw_ctr_fteid.teid; + header->type = srslte::GTPC_MSG_TYPE_DELETE_SESSION_REQUEST; - srslte::gtpc_delete_session_request *del_req = &del_req_pdu.choice.delete_session_request; - del_req->cause.cause_value = srslte::GTPC_CAUSE_VALUE_ISR_DEACTIVATION; - m_mme_gtpc_log->info("GTP-C Delete Session Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid ); + srslte::gtpc_delete_session_request* del_req = &del_req_pdu.choice.delete_session_request; + del_req->cause.cause_value = srslte::GTPC_CAUSE_VALUE_ISR_DEACTIVATION; + m_mme_gtpc_log->info("GTP-C Delete Session Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid); srslte::gtpc_pdu del_resp_pdu; m_spgw->handle_delete_session_request(&del_req_pdu, &del_resp_pdu); - //TODO Handle delete session response + // TODO Handle delete session response - //Delete GTP-C context - std::map::iterator it_imsi = m_mme_ctr_teid_to_imsi.find(mme_ctr_fteid.teid); + // Delete GTP-C context + std::map::iterator it_imsi = m_mme_ctr_teid_to_imsi.find(mme_ctr_fteid.teid); if (it_imsi == m_mme_ctr_teid_to_imsi.end()) { m_mme_gtpc_log->error("Could not find IMSI from MME ctr TEID"); } else { @@ -341,35 +330,33 @@ mme_gtpc::send_delete_session_request(uint64_t imsi) return true; } -void -mme_gtpc::send_release_access_bearers_request(uint64_t imsi) +void mme_gtpc::send_release_access_bearers_request(uint64_t imsi) { m_mme_gtpc_log->info("Sending GTP-C Delete Access Bearers Request\n"); - srslte::gtpc_pdu rel_req_pdu; + srslte::gtpc_pdu rel_req_pdu; srslte::gtp_fteid_t sgw_ctr_fteid; - //Get S-GW Ctr TEID - std::map::iterator it_ctx = m_imsi_to_gtpc_ctx.find(imsi); - if(it_ctx == m_imsi_to_gtpc_ctx.end()) - { + // Get S-GW Ctr TEID + std::map::iterator it_ctx = m_imsi_to_gtpc_ctx.find(imsi); + if (it_ctx == m_imsi_to_gtpc_ctx.end()) { m_mme_gtpc_log->error("Could not find GTP-C context to remove\n"); return; } sgw_ctr_fteid = it_ctx->second.sgw_ctr_fteid; - //Set GTP-C header - srslte::gtpc_header *header = &rel_req_pdu.header; - header->teid_present = true; - header->teid = sgw_ctr_fteid.teid; - header->type = srslte::GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST; + // Set GTP-C header + srslte::gtpc_header* header = &rel_req_pdu.header; + header->teid_present = true; + header->teid = sgw_ctr_fteid.teid; + header->type = srslte::GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST; - srslte::gtpc_release_access_bearers_request *rel_req = &rel_req_pdu.choice.release_access_bearers_request; - m_mme_gtpc_log->info("GTP-C Release Access Berarers Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid ); + srslte::gtpc_release_access_bearers_request* rel_req = &rel_req_pdu.choice.release_access_bearers_request; + m_mme_gtpc_log->info("GTP-C Release Access Berarers Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid); srslte::gtpc_pdu rel_resp_pdu; m_spgw->handle_release_access_bearers_request(&rel_req_pdu, &rel_resp_pdu); - //The GTP-C connection will not be torn down, just the user plane bearers. + // The GTP-C connection will not be torn down, just the user plane bearers. return; } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index 9fb7450ec..8f6a8168a 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -24,26 +24,22 @@ * */ -#include -#include -#include // for printing uint64_t #include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/mme/s1ap_nas_transport.h" -#include "srslte/common/security.h" #include "srslte/common/liblte_security.h" +#include "srslte/common/security.h" +#include +#include // for printing uint64_t -namespace srsepc{ +namespace srsepc { -nas::nas() { +nas::nas() +{ m_pool = srslte::byte_buffer_pool::get_instance(); } -void -nas::init(nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +void nas::init( + nas_init_t args, s1ap_interface_nas* s1ap, gtpc_interface_nas* gtpc, hss_interface_nas* hss, srslte::log* nas_log) { m_mcc = args.mcc; m_mnc = args.mnc; @@ -52,10 +48,10 @@ nas::init(nas_init_t args, m_tac = args.tac; m_apn = args.apn; m_dns = args.dns; - - m_sec_ctx.integ_algo = args.integ_algo; - m_sec_ctx.cipher_algo = args.cipher_algo; - + + m_sec_ctx.integ_algo = args.integ_algo; + m_sec_ctx.cipher_algo = args.cipher_algo; + m_s1ap = s1ap; m_gtpc = gtpc; m_hss = hss; @@ -68,38 +64,37 @@ nas::init(nas_init_t args, * Handle UE Initiating Messages * ********************************/ -bool -nas::handle_attach_request( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_attach_request(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { - uint32_t m_tmsi = 0; - uint64_t imsi = 0; - LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; + uint32_t m_tmsi = 0; + uint64_t imsi = 0; + 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_rx, &attach_req); - if(err != LIBLTE_SUCCESS){ + // Get NAS Attach Request and PDN connectivity request messages + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &attach_req); + if (err != LIBLTE_SUCCESS) { nas_log->error("Error unpacking NAS attach request. Error: %s\n", liblte_error_text[err]); return false; } - //Get PDN Connectivity Request*/ + // Get PDN Connectivity Request*/ err = liblte_mme_unpack_pdn_connectivity_request_msg(&attach_req.esm_msg, &pdn_con_req); - if(err != LIBLTE_SUCCESS){ + if (err != LIBLTE_SUCCESS) { nas_log->error("Error unpacking NAS PDN Connectivity Request. Error: %s\n", liblte_error_text[err]); return false; } - //Get UE IMSI + // Get UE IMSI if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + for (int i = 0; i <= 14; i++) { + imsi += attach_req.eps_mobile_id.imsi[i] * std::pow(10, 14 - i); } nas_log->console("Attach request -- IMSI Style Attach request\n"); nas_log->info("Attach request -- IMSI Style Attach request\n"); @@ -107,7 +102,7 @@ nas::handle_attach_request( uint32_t enb_ue_s1ap_id, nas_log->info("Attach request -- IMSI: %015" PRIu64 "\n", imsi); } else if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) { m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; - imsi = s1ap->find_imsi_from_m_tmsi(m_tmsi); + imsi = s1ap->find_imsi_from_m_tmsi(m_tmsi); nas_log->console("Attach request -- GUTI Style Attach request\n"); nas_log->info("Attach request -- GUTI Style Attach request\n"); nas_log->console("Attach request -- M-TMSI: 0x%x\n", m_tmsi); @@ -117,41 +112,50 @@ nas::handle_attach_request( uint32_t enb_ue_s1ap_id, return false; } - //Log Attach Request Information + // Log Attach Request Information nas_log->console("Attach request -- eNB-UE S1AP Id: %d\n", enb_ue_s1ap_id); nas_log->info("Attach request -- eNB-UE S1AP Id: %d\n", enb_ue_s1ap_id); nas_log->console("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); nas_log->info("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); nas_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]); - nas_log->info("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]); + 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]); + nas_log->info("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]); nas_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]); - nas_log->info("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]); - nas_log->console("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); - nas_log->info("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); + 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]); + nas_log->info("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]); + nas_log->console("Attach Request -- MS Network Capabilities Present: %s\n", + attach_req.ms_network_cap_present ? "true" : "false"); + nas_log->info("Attach Request -- MS Network Capabilities Present: %s\n", + attach_req.ms_network_cap_present ? "true" : "false"); nas_log->console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); nas_log->info("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); nas_log->console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); nas_log->info("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); - nas_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); - nas_log->info("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); - - //Get NAS Context if UE is known - nas * nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); - if (nas_ctx == NULL) - { - //Get attach type from attach request + nas_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", + pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); + nas_log->info("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", + pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); + + // Get NAS Context if UE is known + nas* nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); + if (nas_ctx == NULL) { + // Get attach type from attach request if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { - nas::handle_imsi_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, hss, nas_log); + nas::handle_imsi_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, + hss, nas_log); } else if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) { - nas::handle_guti_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, hss, nas_log); + nas::handle_guti_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, + hss, nas_log); } else { return false; } @@ -159,9 +163,11 @@ nas::handle_attach_request( uint32_t enb_ue_s1ap_id, nas_log->info("Attach Request -- Found previously attached UE.\n"); nas_log->console("Attach Request -- Found previously attach UE.\n"); if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) { - nas::handle_imsi_attach_request_known_ue(nas_ctx, enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, nas_rx, args, s1ap, gtpc, hss, nas_log); + nas::handle_imsi_attach_request_known_ue(nas_ctx, enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, nas_rx, args, + s1ap, gtpc, hss, nas_log); } else if (attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) { - nas::handle_guti_attach_request_known_ue(nas_ctx, enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, nas_rx, args, s1ap, gtpc, hss, nas_log); + nas::handle_guti_attach_request_known_ue(nas_ctx, enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, nas_rx, args, + s1ap, gtpc, hss, nas_log); } else { return false; } @@ -169,90 +175,92 @@ nas::handle_attach_request( uint32_t enb_ue_s1ap_id, return true; } -bool -nas::handle_imsi_attach_request_unknown_ue( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, - const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) - +bool nas::handle_imsi_attach_request_unknown_ue(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT& attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT& pdn_con_req, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { - nas *nas_ctx; - srslte::byte_buffer_t *nas_tx; - srslte::byte_buffer_pool *pool = srslte::byte_buffer_pool::get_instance(); + nas* nas_ctx; + srslte::byte_buffer_t* nas_tx; + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); - //Get IMSI + // Get IMSI uint64_t imsi = 0; - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + for (int i = 0; i <= 14; i++) { + imsi += attach_req.eps_mobile_id.imsi[i] * std::pow(10, 14 - i); } - //Create UE context + // Create UE context nas_ctx = new nas; - nas_ctx->init(args,s1ap,gtpc,hss,nas_log); + nas_ctx->init(args, s1ap, gtpc, hss, nas_log); - //Save IMSI, eNB UE S1AP Id, MME UE S1AP Id and make sure UE is EMM_DEREGISTERED - nas_ctx->m_emm_ctx.imsi = imsi; - nas_ctx->m_emm_ctx.state = EMM_STATE_DEREGISTERED; + // Save IMSI, eNB UE S1AP Id, MME UE S1AP Id and make sure UE is EMM_DEREGISTERED + nas_ctx->m_emm_ctx.imsi = imsi; + nas_ctx->m_emm_ctx.state = EMM_STATE_DEREGISTERED; nas_ctx->m_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; nas_ctx->m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - //Save UE network capabilities - memcpy(&nas_ctx->m_sec_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + // Save UE network capabilities + memcpy(&nas_ctx->m_sec_ctx.ue_network_cap, &attach_req.ue_network_cap, + sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); nas_ctx->m_sec_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; if (attach_req.ms_network_cap_present) { - memcpy(&nas_ctx->m_sec_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + memcpy(&nas_ctx->m_sec_ctx.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 nas_ctx->m_emm_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; - //Initialize NAS count + // Initialize NAS count nas_ctx->m_sec_ctx.ul_nas_count = 0; nas_ctx->m_sec_ctx.dl_nas_count = 0; - //Set eNB information + // Set eNB information memcpy(&nas_ctx->m_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 nas_ctx->m_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - //Initialize E-RABs - for (uint i = 0 ; i< MAX_ERABS_PER_UE; i++) { - nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; + // Initialize E-RABs + for (uint i = 0; i < MAX_ERABS_PER_UE; i++) { + nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; nas_ctx->m_esm_ctx[i].erab_id = i; } - //Save attach request type + // Save attach request type nas_ctx->m_emm_ctx.attach_type = attach_req.eps_attach_type; - //Get Authentication Vectors from HSS - if (!hss->gen_auth_info_answer(nas_ctx->m_emm_ctx.imsi, nas_ctx->m_sec_ctx.k_asme, nas_ctx->m_sec_ctx.autn, nas_ctx->m_sec_ctx.rand, nas_ctx->m_sec_ctx.xres)) { - nas_log->console("User not found. IMSI %015" PRIu64 "\n",nas_ctx->m_emm_ctx.imsi); - nas_log->info("User not found. IMSI %015" PRIu64 "\n",nas_ctx->m_emm_ctx.imsi); + // Get Authentication Vectors from HSS + if (!hss->gen_auth_info_answer(nas_ctx->m_emm_ctx.imsi, nas_ctx->m_sec_ctx.k_asme, nas_ctx->m_sec_ctx.autn, + nas_ctx->m_sec_ctx.rand, nas_ctx->m_sec_ctx.xres)) { + nas_log->console("User not found. IMSI %015" PRIu64 "\n", nas_ctx->m_emm_ctx.imsi); + nas_log->info("User not found. IMSI %015" PRIu64 "\n", nas_ctx->m_emm_ctx.imsi); delete nas_ctx; return false; } - //Allocate eKSI for this authentication vector - //Here we assume a new security context thus a new eKSI - nas_ctx->m_sec_ctx.eksi=0; + // Allocate eKSI for this authentication vector + // Here we assume a new security context thus a new eKSI + nas_ctx->m_sec_ctx.eksi = 0; - //Save the UE context + // Save the UE context s1ap->add_nas_ctx_to_imsi_map(nas_ctx); s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); - //Pack NAS Authentication Request in Downlink NAS Transport msg + // Pack NAS Authentication Request in Downlink NAS Transport msg nas_tx = pool->allocate(); nas_ctx->pack_authentication_request(nas_tx); - //Send reply to eNB - s1ap->send_downlink_nas_transport(nas_ctx->m_ecm_ctx.enb_ue_s1ap_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_tx, nas_ctx->m_ecm_ctx.enb_sri); + // Send reply to eNB + s1ap->send_downlink_nas_transport(nas_ctx->m_ecm_ctx.enb_ue_s1ap_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_tx, + nas_ctx->m_ecm_ctx.enb_sri); pool->deallocate(nas_tx); nas_log->info("Downlink NAS: Sending Authentication Request\n"); @@ -260,168 +268,172 @@ nas::handle_imsi_attach_request_unknown_ue( uint32_t enb_ue_s1ap_id, return true; } -bool -nas::handle_imsi_attach_request_known_ue( nas *nas_ctx, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - 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_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_imsi_attach_request_known_ue(nas* nas_ctx, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + 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_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { bool err; - //Delete previous GTP-U session + // Delete previous GTP-U session gtpc->send_delete_session_request(nas_ctx->m_emm_ctx.imsi); - //Release previous context in the eNB, if present - if(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id != 0){ + // Release previous context in the eNB, if present + if (nas_ctx->m_ecm_ctx.mme_ue_s1ap_id != 0) { s1ap->send_ue_context_release_command(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); } - //Delete previous NAS context + // Delete previous NAS context s1ap->delete_ue_ctx(nas_ctx->m_emm_ctx.imsi); - //Handle new attach - err = nas::handle_imsi_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, hss, nas_log); + // Handle new attach + err = nas::handle_imsi_attach_request_unknown_ue(enb_ue_s1ap_id, enb_sri, attach_req, pdn_con_req, args, s1ap, gtpc, + hss, nas_log); return err; } -bool -nas::handle_guti_attach_request_unknown_ue( uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT &attach_req, - const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT &pdn_con_req, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_guti_attach_request_unknown_ue(uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT& attach_req, + const LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT& pdn_con_req, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { - nas *nas_ctx; - srslte::byte_buffer_pool *pool = srslte::byte_buffer_pool::get_instance(); - srslte::byte_buffer_t *nas_tx; + nas* nas_ctx; + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); + srslte::byte_buffer_t* nas_tx; - //Create new NAS context. + // Create new NAS context. nas_ctx = new nas; nas_ctx->init(args, s1ap, gtpc, hss, nas_log); - //Could not find IMSI from M-TMSI, send Id request - //The IMSI will be set when the identity response is received - //Set EMM ctx - nas_ctx->m_emm_ctx.imsi = 0; + // Could not find IMSI from M-TMSI, send Id request + // The IMSI will be set when the identity response is received + // Set EMM ctx + nas_ctx->m_emm_ctx.imsi = 0; nas_ctx->m_emm_ctx.state = EMM_STATE_DEREGISTERED; - //Save UE network capabilities - memcpy(&nas_ctx->m_sec_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - nas_ctx->m_sec_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; + // Save UE network capabilities + memcpy(&nas_ctx->m_sec_ctx.ue_network_cap, &attach_req.ue_network_cap, + sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + nas_ctx->m_sec_ctx.ms_network_cap_present = attach_req.ms_network_cap_present; if (attach_req.ms_network_cap_present) { - memcpy(&nas_ctx->m_sec_ctx.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + memcpy(&nas_ctx->m_sec_ctx.ms_network_cap, &attach_req.ms_network_cap, + sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); } - //Initialize NAS count - nas_ctx->m_sec_ctx.ul_nas_count = 0; - nas_ctx->m_sec_ctx.dl_nas_count = 0; + // Initialize NAS count + nas_ctx->m_sec_ctx.ul_nas_count = 0; + nas_ctx->m_sec_ctx.dl_nas_count = 0; nas_ctx->m_emm_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; - //Set ECM context + // Set ECM context nas_ctx->m_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; nas_ctx->m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; - //Save attach request type + // Save attach request type nas_ctx->m_emm_ctx.attach_type = attach_req.eps_attach_type; - //Save whether ESM information transfer is necessary + // Save whether ESM information transfer is necessary nas_ctx->m_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; - //Add eNB info to UE ctxt + // Add eNB info to UE ctxt memcpy(&nas_ctx->m_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); - //Initialize E-RABs - for (uint i = 0 ; i< MAX_ERABS_PER_UE; i++) { - nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; + // Initialize E-RABs + for (uint i = 0; i < MAX_ERABS_PER_UE; i++) { + nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; nas_ctx->m_esm_ctx[i].erab_id = i; } - //Store temporary ue context + // Store temporary ue context s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); - s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); + s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); - //Send Identity Request + // Send Identity Request nas_tx = pool->allocate(); nas_ctx->pack_identity_request(nas_tx); - s1ap->send_downlink_nas_transport(nas_ctx->m_ecm_ctx.enb_ue_s1ap_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_tx, nas_ctx->m_ecm_ctx.enb_sri); + s1ap->send_downlink_nas_transport(nas_ctx->m_ecm_ctx.enb_ue_s1ap_id, nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_tx, + nas_ctx->m_ecm_ctx.enb_sri); pool->deallocate(nas_tx); return true; } -bool -nas::handle_guti_attach_request_known_ue( nas *nas_ctx, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - 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_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_guti_attach_request_known_ue(nas* nas_ctx, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + 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_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { - bool msg_valid = false; - srslte::byte_buffer_t *nas_tx; - srslte::byte_buffer_pool *pool = srslte::byte_buffer_pool::get_instance(); + bool msg_valid = false; + srslte::byte_buffer_t* nas_tx; + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; - sec_ctx_t *sec_ctx = &nas_ctx->m_sec_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; + sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; - nas_log->console("Found UE context. IMSI: %015" PRIu64 ", 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); + nas_log->console("Found UE context. IMSI: %015" PRIu64 ", 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 + // Check NAS integrity msg_valid = nas_ctx->integrity_check(nas_rx); if (msg_valid == true && emm_ctx->state == EMM_STATE_DEREGISTERED) { - nas_log->console("GUTI Attach -- NAS Integrity OK. UL count %d, DL count %d\n",sec_ctx->ul_nas_count, sec_ctx->dl_nas_count); - nas_log->info ("GUTI Attach -- NAS Integrity OK. UL count %d, DL count %d\n",sec_ctx->ul_nas_count, sec_ctx->dl_nas_count); + nas_log->console("GUTI Attach -- NAS Integrity OK. UL count %d, DL count %d\n", sec_ctx->ul_nas_count, + sec_ctx->dl_nas_count); + nas_log->info("GUTI Attach -- NAS Integrity OK. UL count %d, DL count %d\n", sec_ctx->ul_nas_count, + sec_ctx->dl_nas_count); - //Create new MME UE S1AP Identity + // Create new MME UE S1AP Identity ecm_ctx->mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; emm_ctx->procedure_transaction_id = pdn_con_req.proc_transaction_id; - //Save Attach type + // Save Attach type emm_ctx->attach_type = attach_req.eps_attach_type; - //Set eNB information + // 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 + // 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++) { - nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; + // Initialize E-RABs + for (uint i = 0; i < MAX_ERABS_PER_UE; i++) { + nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; nas_ctx->m_esm_ctx[i].erab_id = i; } - //Store context based on MME UE S1AP id + // Store context based on MME UE S1AP id s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id, ecm_ctx->mme_ue_s1ap_id); - //Re-generate K_eNB + // Re-generate K_eNB srslte::security_generate_k_enb(sec_ctx->k_asme, sec_ctx->ul_nas_count, sec_ctx->k_enb); nas_log->info("Generating KeNB with UL NAS COUNT: %d\n", sec_ctx->ul_nas_count); nas_log->console("Generating KeNB with UL NAS COUNT: %d\n", sec_ctx->ul_nas_count); nas_log->info_hex(sec_ctx->k_enb, 32, "Key eNodeB (k_enb)\n"); - //Send reply + // Send reply nas_tx = pool->allocate(); if (ecm_ctx->eit) { nas_log->console("Secure ESM information transfer requested.\n"); @@ -429,9 +441,9 @@ nas::handle_guti_attach_request_known_ue( nas *nas_ctx, nas_ctx->pack_esm_information_request(nas_tx); s1ap->send_downlink_nas_transport(ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, nas_tx, *enb_sri); } else { - //Get subscriber info from HSS - uint8_t default_bearer=5; - hss->gen_update_loc_answer(emm_ctx->imsi,&nas_ctx->m_esm_ctx[default_bearer].qci); + // Get subscriber info from HSS + uint8_t default_bearer = 5; + hss->gen_update_loc_answer(emm_ctx->imsi, &nas_ctx->m_esm_ctx[default_bearer].qci); nas_log->debug("Getting subscription information -- QCI %d\n", nas_ctx->m_esm_ctx[default_bearer].qci); nas_log->console("Getting subscription information -- QCI %d\n", nas_ctx->m_esm_ctx[default_bearer].qci); gtpc->send_create_session_request(emm_ctx->imsi); @@ -444,8 +456,8 @@ nas::handle_guti_attach_request_known_ue( nas *nas_ctx, nas_log->error("Received GUTI-Attach Request from attached user.\n"); nas_log->console("Received GUTI-Attach Request from attached user.\n"); - //Delete previous Ctx, restart authentication - //Detaching previoulsy attached UE. + // Delete previous Ctx, restart authentication + // Detaching previoulsy attached UE. gtpc->send_delete_session_request(emm_ctx->imsi); if (ecm_ctx->mme_ue_s1ap_id != 0) { s1ap->send_ue_context_release_command(ecm_ctx->mme_ue_s1ap_id); @@ -454,53 +466,53 @@ nas::handle_guti_attach_request_known_ue( nas *nas_ctx, sec_ctx->ul_nas_count = 0; sec_ctx->dl_nas_count = 0; - //Create new MME UE S1AP Identity - uint32_t new_mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); + // Create new MME UE S1AP Identity + uint32_t new_mme_ue_s1ap_id = 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) { + // Make sure context from previous NAS connections is not present + if (ecm_ctx->mme_ue_s1ap_id != 0) { s1ap->release_ue_ecm_ctx(ecm_ctx->mme_ue_s1ap_id); } ecm_ctx->mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - //Set EMM as de-registered + // Set EMM as de-registered emm_ctx->state = EMM_STATE_DEREGISTERED; - //Save Attach type + // Save Attach type emm_ctx->attach_type = attach_req.eps_attach_type; - //Set eNB information + // 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 + // 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++) { - nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; + // Initialize E-RABs + for (uint i = 0; i < MAX_ERABS_PER_UE; i++) { + nas_ctx->m_esm_ctx[i].state = ERAB_DEACTIVATED; nas_ctx->m_esm_ctx[i].erab_id = i; } - //Store context based on MME UE S1AP id + // Store context based on MME UE S1AP id s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); - s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id,ecm_ctx->mme_ue_s1ap_id); + s1ap->add_ue_to_enb_set(enb_sri->sinfo_assoc_id, ecm_ctx->mme_ue_s1ap_id); - //NAS integrity failed. Re-start authentication process. + // NAS integrity failed. Re-start authentication process. nas_log->console("GUTI Attach request NAS integrity failed.\n"); nas_log->console("RE-starting authentication procedure.\n"); - //Get Authentication Vectors from HSS + // Get Authentication Vectors from HSS if (!hss->gen_auth_info_answer(emm_ctx->imsi, sec_ctx->k_asme, sec_ctx->autn, sec_ctx->rand, sec_ctx->xres)) { nas_log->console("User not found. IMSI %015" PRIu64 "\n", emm_ctx->imsi); nas_log->info("User not found. IMSI %015" PRIu64 "\n", emm_ctx->imsi); return false; } - //Restarting security context. Reseting eKSI to 0. - sec_ctx->eksi=0; - nas_tx = pool->allocate(); + // Restarting security context. Reseting eKSI to 0. + sec_ctx->eksi = 0; + nas_tx = pool->allocate(); nas_ctx->pack_authentication_request(nas_tx); - //Send reply to eNB - s1ap->send_downlink_nas_transport(ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id,nas_tx, *enb_sri); + // Send reply to eNB + s1ap->send_downlink_nas_transport(ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, nas_tx, *enb_sri); pool->deallocate(nas_tx); nas_log->info("Downlink NAS: Sent Authentication Request\n"); nas_log->console("Downlink NAS: Sent Authentication Request\n"); @@ -508,29 +520,28 @@ nas::handle_guti_attach_request_known_ue( nas *nas_ctx, } } -//Service Requests -bool -nas::handle_service_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +// Service Requests +bool nas::handle_service_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { nas_log->info("Service request -- S-TMSI 0x%x\n", m_tmsi); nas_log->console("Service request -- S-TMSI 0x%x\n", m_tmsi); nas_log->info("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); nas_log->console("Service request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - bool mac_valid = false; + bool mac_valid = false; LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT service_req; - srslte::byte_buffer_pool *pool = srslte::byte_buffer_pool::get_instance(); + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_service_request_msg((LIBLTE_BYTE_MSG_STRUCT*) nas_rx, &service_req); - if (err !=LIBLTE_SUCCESS) { + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_service_request_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &service_req); + if (err != LIBLTE_SUCCESS) { nas_log->error("Could not unpack service request\n"); return false; } @@ -542,76 +553,77 @@ nas::handle_service_request( uint32_t m_tmsi, nas nas_tmp; nas_tmp.m_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - srslte::byte_buffer_t *nas_tx = pool->allocate(); + srslte::byte_buffer_t* nas_tx = pool->allocate(); nas_tmp.pack_service_reject(nas_tx); s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx, *enb_sri); pool->deallocate(nas_tx); return true; } - nas *nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); + nas* nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); if (nas_ctx == NULL || nas_ctx->m_emm_ctx.state != EMM_STATE_REGISTERED) { nas_log->console("UE is not EMM-Registered.\n"); nas_log->error("UE is not EMM-Registered.\n"); nas nas_tmp; nas_tmp.m_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; nas_tmp.m_ecm_ctx.mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - srslte::byte_buffer_t *nas_tx = pool->allocate(); + srslte::byte_buffer_t* nas_tx = pool->allocate(); nas_tmp.pack_service_reject(nas_tx); s1ap->send_downlink_nas_transport(enb_ue_s1ap_id, nas_tmp.m_ecm_ctx.mme_ue_s1ap_id, nas_tx, *enb_sri); pool->deallocate(nas_tx); return true; } - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; - sec_ctx_t *sec_ctx = &nas_ctx->m_sec_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; + sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; mac_valid = nas_ctx->short_integrity_check(nas_rx); if (mac_valid) { nas_log->console("Service Request -- Short MAC valid\n"); nas_log->info("Service Request -- Short MAC valid\n"); - if(ecm_ctx->state == ECM_STATE_CONNECTED) { + if (ecm_ctx->state == ECM_STATE_CONNECTED) { nas_log->error("Service Request -- User is ECM CONNECTED\n"); - //Release previous context - nas_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); + // Release previous context + nas_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); s1ap->send_ue_context_release_command(ecm_ctx->mme_ue_s1ap_id); 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. + // UE not connect. Connect normally. nas_log->console("Service Request -- User is ECM DISCONNECTED\n"); nas_log->info("Service Request -- User is ECM DISCONNECTED\n"); - //Create ECM context + // Create ECM context ecm_ctx->mme_ue_s1ap_id = s1ap->get_next_mme_ue_s1ap_id(); - //Set eNB information + // 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 + // 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 ){ + // Get UE IP, and uplink F-TEID + if (emm_ctx->ue_ip.s_addr == 0) { nas_log->error("UE has no valid IP assigned upon reception of service request"); } - nas_log->console("UE previously assigned IP: %s",inet_ntoa(emm_ctx->ue_ip)); + nas_log->console("UE previously assigned IP: %s", inet_ntoa(emm_ctx->ue_ip)); - //Re-generate K_eNB + // Re-generate K_eNB srslte::security_generate_k_enb(sec_ctx->k_asme, sec_ctx->ul_nas_count, sec_ctx->k_enb); nas_log->info("Generating KeNB with UL NAS COUNT: %d\n", sec_ctx->ul_nas_count); nas_log->console("Generating KeNB with UL NAS COUNT: %d\n", sec_ctx->ul_nas_count); nas_log->info_hex(sec_ctx->k_enb, 32, "Key eNodeB (k_enb)\n"); nas_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid); - //Save UE ctx to MME UE S1AP id + // Save UE ctx to MME UE S1AP id s1ap->add_nas_ctx_to_mme_ue_s1ap_id_map(nas_ctx); - s1ap->send_initial_context_setup_request(imsi,5); + s1ap->send_initial_context_setup_request(imsi, 5); sec_ctx->ul_nas_count++; } else { nas_log->console("Service Request -- Short MAC invalid. Ignoring service request\n"); @@ -620,27 +632,26 @@ nas::handle_service_request( uint32_t m_tmsi, return true; } -bool -nas::handle_detach_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_detach_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { nas_log->info("Detach Request -- S-TMSI 0x%x\n", m_tmsi); nas_log->console("Detach Request -- S-TMSI 0x%x\n", m_tmsi); nas_log->info("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); nas_log->console("Detach Request -- eNB UE S1AP Id %d\n", enb_ue_s1ap_id); - bool mac_valid = false; + 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_rx, &detach_req); - if (err !=LIBLTE_SUCCESS) { + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &detach_req); + if (err != LIBLTE_SUCCESS) { nas_log->error("Could not unpack detach request\n"); return false; } @@ -652,40 +663,39 @@ nas::handle_detach_request( uint32_t m_tmsi, return true; } - nas *nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); + nas* nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); if (nas_ctx == NULL) { nas_log->console("Could not find UE context from IMSI\n"); nas_log->error("Could not find UE context from IMSI\n"); return true; } - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; - sec_ctx_t *sec_ctx = &nas_ctx->m_sec_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; + sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; gtpc->send_delete_session_request(emm_ctx->imsi); emm_ctx->state = EMM_STATE_DEREGISTERED; sec_ctx->ul_nas_count++; nas_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. + // 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 = s1ap->get_next_mme_ue_s1ap_id(); ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; s1ap->send_ue_context_release_command(ecm_ctx->mme_ue_s1ap_id); return true; } -bool -nas::handle_tracking_area_update_request( uint32_t m_tmsi, - uint32_t enb_ue_s1ap_id, - struct sctp_sndrcvinfo *enb_sri, - srslte::byte_buffer_t *nas_rx, - nas_init_t args, - s1ap_interface_nas *s1ap, - gtpc_interface_nas *gtpc, - hss_interface_nas *hss, - srslte::log *nas_log) +bool nas::handle_tracking_area_update_request(uint32_t m_tmsi, + uint32_t enb_ue_s1ap_id, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* nas_rx, + nas_init_t args, + s1ap_interface_nas* s1ap, + gtpc_interface_nas* gtpc, + hss_interface_nas* hss, + srslte::log* nas_log) { nas_log->info("Tracking Area Update Request -- S-TMSI 0x%x\n", m_tmsi); nas_log->console("Tracking Area Update Request -- S-TMSI 0x%x\n", m_tmsi); @@ -702,13 +712,13 @@ nas::handle_tracking_area_update_request( uint32_t m_tmsi, return true; } - nas *nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; + nas* nas_ctx = s1ap->find_nas_ctx_from_imsi(imsi); + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; - sec_ctx_t *sec_ctx = &nas_ctx->m_sec_ctx; + sec_ctx_t* sec_ctx = &nas_ctx->m_sec_ctx; - sec_ctx->ul_nas_count++; //Increment the NAS count, not to break the security ctx + sec_ctx->ul_nas_count++; // Increment the NAS count, not to break the security ctx return true; } @@ -717,90 +727,88 @@ nas::handle_tracking_area_update_request( uint32_t m_tmsi, * Handle Uplink NAS Transport messages * ***************************************/ -bool -nas::handle_authentication_response(srslte::byte_buffer_t *nas_rx) +bool nas::handle_authentication_response(srslte::byte_buffer_t* nas_rx) { - srslte::byte_buffer_t *nas_tx; + srslte::byte_buffer_t* nas_tx; LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; - bool ue_valid=true; + bool ue_valid = true; - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &auth_resp); - if(err != LIBLTE_SUCCESS){ + // Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &auth_resp); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); return false; } - //Log received authentication response + // Log received authentication response m_nas_log->console("Authentication Response -- IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); m_nas_log->info("Authentication Response -- IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); - m_nas_log->info_hex(auth_resp.res,8, "Authentication response -- RES"); - m_nas_log->info_hex(m_sec_ctx.xres,8, "Authentication response -- XRES"); + m_nas_log->info_hex(auth_resp.res, 8, "Authentication response -- RES"); + m_nas_log->info_hex(m_sec_ctx.xres, 8, "Authentication response -- XRES"); - //Check UE authentication - for(int i=0; i<8;i++){ - if( auth_resp.res[i] != m_sec_ctx.xres[i] ) { + // Check UE authentication + for (int i = 0; i < 8; i++) { + if (auth_resp.res[i] != m_sec_ctx.xres[i]) { ue_valid = false; } } nas_tx = m_pool->allocate(); - if(!ue_valid) { - //Authentication rejected + if (!ue_valid) { + // Authentication rejected m_nas_log->console("UE Authentication Rejected.\n"); m_nas_log->warning("UE Authentication Rejected.\n"); - //Send back Athentication Reject + // Send back Athentication Reject pack_authentication_reject(nas_tx); m_nas_log->info("Downlink NAS: Sending Authentication Reject.\n"); } else { - //Authentication accepted + // Authentication accepted m_nas_log->console("UE Authentication Accepted.\n"); m_nas_log->info("UE Authentication Accepted.\n"); - //Send Security Mode Command + // Send Security Mode Command m_sec_ctx.ul_nas_count = 0; // Reset the NAS uplink counter for the right key k_enb derivation pack_security_mode_command(nas_tx); m_nas_log->console("Downlink NAS: Sending NAS Security Mode Command.\n"); } - //Send reply + // Send reply m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, m_ecm_ctx.enb_sri); m_pool->deallocate(nas_tx); return true; } -bool -nas::handle_security_mode_complete(srslte::byte_buffer_t *nas_rx) +bool nas::handle_security_mode_complete(srslte::byte_buffer_t* nas_rx) { - srslte::byte_buffer_t *nas_tx; + srslte::byte_buffer_t* nas_tx; LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; - //Get NAS security mode complete - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &sm_comp); - if(err != LIBLTE_SUCCESS){ + // Get NAS security mode complete + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_security_mode_complete_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &sm_comp); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); return false; } - //Log security mode complete + // Log security mode complete m_nas_log->info("Security Mode Command Complete -- IMSI: %015" PRIu64 "\n", m_emm_ctx.imsi); m_nas_log->console("Security Mode Command Complete -- IMSI: %015" PRIu64 "\n", m_emm_ctx.imsi); - //Check wether secure ESM information transfer is required + // Check wether secure ESM information transfer is required nas_tx = m_pool->allocate(); if (m_ecm_ctx.eit == true) { - //Secure ESM information transfer is required + // Secure ESM information transfer is required m_nas_log->console("Sending ESM information request\n"); m_nas_log->info("Sending ESM information request\n"); - //Packing ESM information request + // Packing ESM information request pack_esm_information_request(nas_tx); m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, m_ecm_ctx.enb_sri); } else { - //Secure ESM information transfer not necessary - //Sending create session request to SP-GW. - uint8_t default_bearer=5; + // Secure ESM information transfer not necessary + // Sending create session request to SP-GW. + uint8_t default_bearer = 5; m_hss->gen_update_loc_answer(m_emm_ctx.imsi, &m_esm_ctx[default_bearer].qci); m_nas_log->debug("Getting subscription information -- QCI %d\n", m_esm_ctx[default_bearer].qci); m_nas_log->console("Getting subscription information -- QCI %d\n", m_esm_ctx[default_bearer].qci); @@ -810,40 +818,40 @@ nas::handle_security_mode_complete(srslte::byte_buffer_t *nas_rx) return true; } - -bool -nas::handle_attach_complete(srslte::byte_buffer_t *nas_rx) +bool nas::handle_attach_complete(srslte::byte_buffer_t* nas_rx) { - LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; - uint8_t pd, msg_type; + LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; + uint8_t pd, msg_type; LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_bearer; - srslte::byte_buffer_t *nas_tx; + srslte::byte_buffer_t* nas_tx; - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &attach_comp); - if(err != LIBLTE_SUCCESS){ + // Get NAS authentication response + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_attach_complete_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &attach_comp); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); return false; } - err = liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg( (LIBLTE_BYTE_MSG_STRUCT *) &attach_comp.esm_msg, &act_bearer); - if(err != LIBLTE_SUCCESS){ + err = liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg((LIBLTE_BYTE_MSG_STRUCT*)&attach_comp.esm_msg, + &act_bearer); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking Activate EPS Bearer Context Accept Msg. Error: %s\n", liblte_error_text[err]); return false; } m_nas_log->console("Unpacked Attached Complete Message. IMSI %" PRIu64 "\n", m_emm_ctx.imsi); - m_nas_log->console("Unpacked Activate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id); + m_nas_log->console("Unpacked Activate Default EPS Bearer message. EPS Bearer id %d\n", act_bearer.eps_bearer_id); if (act_bearer.eps_bearer_id < 5 || act_bearer.eps_bearer_id > 15) { m_nas_log->error("EPS Bearer ID out of range\n"); return false; } if (m_emm_ctx.state == EMM_STATE_DEREGISTERED) { - //Attach requested from attach request - m_gtpc->send_modify_bearer_request(m_emm_ctx.imsi, act_bearer.eps_bearer_id, &m_esm_ctx[act_bearer.eps_bearer_id].enb_fteid); + // Attach requested from attach request + m_gtpc->send_modify_bearer_request(m_emm_ctx.imsi, act_bearer.eps_bearer_id, + &m_esm_ctx[act_bearer.eps_bearer_id].enb_fteid); - //Send reply to EMM Info to UE + // Send reply to EMM Info to UE nas_tx = m_pool->allocate(); pack_emm_information(nas_tx); @@ -857,80 +865,79 @@ nas::handle_attach_complete(srslte::byte_buffer_t *nas_rx) return true; } -bool -nas::handle_esm_information_response(srslte::byte_buffer_t *nas_rx) +bool nas::handle_esm_information_response(srslte::byte_buffer_t* nas_rx) { LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; - //Get NAS authentication response - LIBLTE_ERROR_ENUM err = srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &esm_info_resp); - if(err != LIBLTE_SUCCESS){ + // Get NAS authentication response + LIBLTE_ERROR_ENUM err = + srslte_mme_unpack_esm_information_response_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &esm_info_resp); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS authentication response. Error: %s\n", liblte_error_text[err]); return false; } - m_nas_log->info("ESM Info: EPS bearer id %d\n",esm_info_resp.eps_bearer_id); - if(esm_info_resp.apn_present){ - m_nas_log->info("ESM Info: APN %s\n",esm_info_resp.apn.apn); - m_nas_log->console("ESM Info: APN %s\n",esm_info_resp.apn.apn); + m_nas_log->info("ESM Info: EPS bearer id %d\n", esm_info_resp.eps_bearer_id); + if (esm_info_resp.apn_present) { + m_nas_log->info("ESM Info: APN %s\n", esm_info_resp.apn.apn); + m_nas_log->console("ESM Info: APN %s\n", esm_info_resp.apn.apn); } - if(esm_info_resp.protocol_cnfg_opts_present){ - m_nas_log->info("ESM Info: %d Protocol Configuration Options\n",esm_info_resp.protocol_cnfg_opts.N_opts); - m_nas_log->console("ESM Info: %d Protocol Configuration Options\n",esm_info_resp.protocol_cnfg_opts.N_opts); + if (esm_info_resp.protocol_cnfg_opts_present) { + m_nas_log->info("ESM Info: %d Protocol Configuration Options\n", esm_info_resp.protocol_cnfg_opts.N_opts); + m_nas_log->console("ESM Info: %d Protocol Configuration Options\n", esm_info_resp.protocol_cnfg_opts.N_opts); } - //Get subscriber info from HSS - uint8_t default_bearer=5; + // Get subscriber info from HSS + uint8_t default_bearer = 5; m_hss->gen_update_loc_answer(m_emm_ctx.imsi, &m_esm_ctx[default_bearer].qci); m_nas_log->debug("Getting subscription information -- QCI %d\n", m_esm_ctx[default_bearer].qci); m_nas_log->console("Getting subscription information -- QCI %d\n", m_esm_ctx[default_bearer].qci); - //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. + // FIXME The packging of GTP-C messages is not ready. + // This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. m_gtpc->send_create_session_request(m_emm_ctx.imsi); return true; } -bool -nas::handle_identity_response(srslte::byte_buffer_t *nas_rx) +bool nas::handle_identity_response(srslte::byte_buffer_t* nas_rx) { - srslte::byte_buffer_t *nas_tx; + srslte::byte_buffer_t* nas_tx; LIBLTE_MME_ID_RESPONSE_MSG_STRUCT id_resp; - LIBLTE_ERROR_ENUM err = liblte_mme_unpack_identity_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &id_resp); - if(err != LIBLTE_SUCCESS){ + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_identity_response_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &id_resp); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS identity response. Error: %s\n", liblte_error_text[err]); return false; } uint64_t imsi = 0; - for(int i=0;i<=14;i++){ - imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i); + for (int i = 0; i <= 14; i++) { + imsi += id_resp.mobile_id.imsi[i] * std::pow(10, 14 - i); } m_nas_log->info("ID response -- IMSI: %015" PRIu64 "\n", imsi); m_nas_log->console("ID Response -- IMSI: %015" PRIu64 "\n", imsi); - //Set UE's IMSI - m_emm_ctx.imsi=imsi; + // Set UE's IMSI + m_emm_ctx.imsi = imsi; - //Get Authentication Vectors from HSS + // Get Authentication Vectors from HSS if (!m_hss->gen_auth_info_answer(imsi, m_sec_ctx.k_asme, m_sec_ctx.autn, m_sec_ctx.rand, m_sec_ctx.xres)) { - m_nas_log->console("User not found. IMSI %015" PRIu64 "\n",imsi); - m_nas_log->info("User not found. IMSI %015" PRIu64 "\n",imsi); + m_nas_log->console("User not found. IMSI %015" PRIu64 "\n", imsi); + m_nas_log->info("User not found. IMSI %015" PRIu64 "\n", imsi); return false; } - //Identity reponse from unknown GUTI atach. Assigning new eKSI. - m_sec_ctx.eksi=0; + // Identity reponse from unknown GUTI atach. Assigning new eKSI. + m_sec_ctx.eksi = 0; - //Store UE context im IMSI map + // Store UE context im IMSI map m_s1ap->add_nas_ctx_to_imsi_map(this); - //Pack NAS Authentication Request in Downlink NAS Transport msg + // Pack NAS Authentication Request in Downlink NAS Transport msg nas_tx = m_pool->allocate(); pack_authentication_request(nas_tx); - //Send reply to eNB + // Send reply to eNB m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, m_ecm_ctx.enb_sri); m_pool->deallocate(nas_tx); @@ -939,9 +946,7 @@ nas::handle_identity_response(srslte::byte_buffer_t *nas_rx) return true; } - -bool -nas::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_rx) +bool nas::handle_tracking_area_update_request(srslte::byte_buffer_t* nas_rx) { m_nas_log->console("Warning: Tracking Area Update Request messages not handled yet.\n"); m_nas_log->warning("Warning: Tracking Area Update Request messages not handled yet.\n"); @@ -949,105 +954,103 @@ nas::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_rx) return true; } - -bool -nas::handle_authentication_failure(srslte::byte_buffer_t *nas_rx) +bool nas::handle_authentication_failure(srslte::byte_buffer_t* nas_rx) { m_nas_log->info("Received Authentication Failure\n"); - srslte::byte_buffer_t *nas_tx; + srslte::byte_buffer_t* nas_tx; LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT auth_fail; - LIBLTE_ERROR_ENUM err; + LIBLTE_ERROR_ENUM err; - err = liblte_mme_unpack_authentication_failure_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_rx, &auth_fail); - if(err != LIBLTE_SUCCESS){ + err = liblte_mme_unpack_authentication_failure_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_rx, &auth_fail); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error unpacking NAS authentication failure. Error: %s\n", liblte_error_text[err]); return false; } switch (auth_fail.emm_cause) { case 20: - m_nas_log->console("MAC code failure\n"); - m_nas_log->info("MAC code failure\n"); - break; + m_nas_log->console("MAC code failure\n"); + m_nas_log->info("MAC code failure\n"); + break; case 26: - m_nas_log->console("Non-EPS authentication unacceptable\n"); - m_nas_log->info("Non-EPS authentication unacceptable\n"); - break; + m_nas_log->console("Non-EPS authentication unacceptable\n"); + m_nas_log->info("Non-EPS authentication unacceptable\n"); + break; case 21: - m_nas_log->console("Authentication Failure -- Synchronization Failure\n"); - m_nas_log->info("Authentication Failure -- Synchronization Failure\n"); - if(auth_fail.auth_fail_param_present == false){ - m_nas_log->error("Missing fail parameter\n"); - return false; - } - if (!m_hss->resync_sqn(m_emm_ctx.imsi, auth_fail.auth_fail_param)) { - m_nas_log->console("Resynchronization failed. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); - m_nas_log->info("Resynchronization failed. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); - return false; - } - //Get Authentication Vectors from HSS - if (!m_hss->gen_auth_info_answer(m_emm_ctx.imsi, m_sec_ctx.k_asme, m_sec_ctx.autn, m_sec_ctx.rand, m_sec_ctx.xres)) { - m_nas_log->console("User not found. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); - m_nas_log->info("User not found. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); - return false; - } + m_nas_log->console("Authentication Failure -- Synchronization Failure\n"); + m_nas_log->info("Authentication Failure -- Synchronization Failure\n"); + if (auth_fail.auth_fail_param_present == false) { + m_nas_log->error("Missing fail parameter\n"); + return false; + } + if (!m_hss->resync_sqn(m_emm_ctx.imsi, auth_fail.auth_fail_param)) { + m_nas_log->console("Resynchronization failed. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); + m_nas_log->info("Resynchronization failed. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); + return false; + } + // Get Authentication Vectors from HSS + if (!m_hss->gen_auth_info_answer(m_emm_ctx.imsi, m_sec_ctx.k_asme, m_sec_ctx.autn, m_sec_ctx.rand, + m_sec_ctx.xres)) { + m_nas_log->console("User not found. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); + m_nas_log->info("User not found. IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); + return false; + } - //Making sure eKSI is different from previous eKSI. - m_sec_ctx.eksi = (m_sec_ctx.eksi+1)%6; + // Making sure eKSI is different from previous eKSI. + m_sec_ctx.eksi = (m_sec_ctx.eksi + 1) % 6; - //Pack NAS Authentication Request in Downlink NAS Transport msg - nas_tx = m_pool->allocate(); - pack_authentication_request(nas_tx); + // Pack NAS Authentication Request in Downlink NAS Transport msg + nas_tx = m_pool->allocate(); + pack_authentication_request(nas_tx); - //Send reply to eNB - m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, m_ecm_ctx.enb_sri); - m_pool->deallocate(nas_tx); + // Send reply to eNB + m_s1ap->send_downlink_nas_transport(m_ecm_ctx.enb_ue_s1ap_id, m_ecm_ctx.mme_ue_s1ap_id, nas_tx, + m_ecm_ctx.enb_sri); + m_pool->deallocate(nas_tx); - m_nas_log->info("Downlink NAS: Sent Authentication Request\n"); - m_nas_log->console("Downlink NAS: Sent Authentication Request\n"); - //TODO Start T3460 Timer! - break; + m_nas_log->info("Downlink NAS: Sent Authentication Request\n"); + m_nas_log->console("Downlink NAS: Sent Authentication Request\n"); + // TODO Start T3460 Timer! + break; } return true; } -bool -nas::handle_detach_request(srslte::byte_buffer_t *nas_msg) +bool nas::handle_detach_request(srslte::byte_buffer_t* nas_msg) { m_nas_log->console("Detach request -- IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); m_nas_log->info("Detach request -- IMSI %015" PRIu64 "\n", m_emm_ctx.imsi); 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) { + LIBLTE_ERROR_ENUM err = liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &detach_req); + if (err != LIBLTE_SUCCESS) { m_nas_log->error("Could not unpack detach request\n"); return false; } m_gtpc->send_delete_session_request(m_emm_ctx.imsi); m_emm_ctx.state = EMM_STATE_DEREGISTERED; - if (m_ecm_ctx.mme_ue_s1ap_id!=0) { + if (m_ecm_ctx.mme_ue_s1ap_id != 0) { m_s1ap->send_ue_context_release_command(m_ecm_ctx.mme_ue_s1ap_id); } return true; } /*Packing/Unpacking helper functions*/ -bool -nas::pack_authentication_request(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_authentication_request(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing Authentication Request\n"); - //Pack NAS msg + // Pack NAS msg LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req; - memcpy(auth_req.autn , m_sec_ctx.autn, 16); + memcpy(auth_req.autn, m_sec_ctx.autn, 16); memcpy(auth_req.rand, m_sec_ctx.rand, 16); - auth_req.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - auth_req.nas_ksi.nas_ksi = m_sec_ctx.eksi; + auth_req.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + auth_req.nas_ksi.nas_ksi = m_sec_ctx.eksi; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_request_msg(&auth_req, (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing Authentication Request\n"); m_nas_log->console("Error packing Authentication Request\n"); @@ -1056,13 +1059,12 @@ nas::pack_authentication_request(srslte::byte_buffer_t *nas_buffer) return true; } -bool -nas::pack_authentication_reject(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_authentication_reject(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing Authentication Reject\n"); LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT auth_rej; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_reject_msg(&auth_rej, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_mme_pack_authentication_reject_msg(&auth_rej, (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing Authentication Reject\n"); m_nas_log->console("Error packing Authentication Reject\n"); @@ -1071,51 +1073,47 @@ nas::pack_authentication_reject(srslte::byte_buffer_t *nas_buffer) return true; } -bool -nas::pack_security_mode_command(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_security_mode_command(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing Security Mode Command\n"); - //Pack NAS PDU + // Pack NAS PDU LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sm_cmd; - sm_cmd.selected_nas_sec_algs.type_of_eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM) m_sec_ctx.cipher_algo; - sm_cmd.selected_nas_sec_algs.type_of_eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM) m_sec_ctx.integ_algo; + sm_cmd.selected_nas_sec_algs.type_of_eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM)m_sec_ctx.cipher_algo; + sm_cmd.selected_nas_sec_algs.type_of_eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM)m_sec_ctx.integ_algo; - sm_cmd.nas_ksi.tsc_flag=LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; - sm_cmd.nas_ksi.nas_ksi=m_sec_ctx.eksi; + sm_cmd.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE; + sm_cmd.nas_ksi.nas_ksi = m_sec_ctx.eksi; - //Replay UE security cap - memcpy(sm_cmd.ue_security_cap.eea,m_sec_ctx.ue_network_cap.eea,8*sizeof(bool)); - memcpy(sm_cmd.ue_security_cap.eia,m_sec_ctx.ue_network_cap.eia,8*sizeof(bool)); + // Replay UE security cap + memcpy(sm_cmd.ue_security_cap.eea, m_sec_ctx.ue_network_cap.eea, 8 * sizeof(bool)); + memcpy(sm_cmd.ue_security_cap.eia, m_sec_ctx.ue_network_cap.eia, 8 * sizeof(bool)); sm_cmd.ue_security_cap.uea_present = m_sec_ctx.ue_network_cap.uea_present; - memcpy(sm_cmd.ue_security_cap.uea,m_sec_ctx.ue_network_cap.uea,8*sizeof(bool)); + memcpy(sm_cmd.ue_security_cap.uea, m_sec_ctx.ue_network_cap.uea, 8 * sizeof(bool)); sm_cmd.ue_security_cap.uia_present = m_sec_ctx.ue_network_cap.uia_present; - memcpy(sm_cmd.ue_security_cap.uia,m_sec_ctx.ue_network_cap.uia,8*sizeof(bool)); + memcpy(sm_cmd.ue_security_cap.uia, m_sec_ctx.ue_network_cap.uia, 8 * sizeof(bool)); sm_cmd.ue_security_cap.gea_present = m_sec_ctx.ms_network_cap_present; - memcpy(sm_cmd.ue_security_cap.gea,m_sec_ctx.ms_network_cap.gea,8*sizeof(bool)); + memcpy(sm_cmd.ue_security_cap.gea, m_sec_ctx.ms_network_cap.gea, 8 * sizeof(bool)); - sm_cmd.imeisv_req_present=false; - sm_cmd.nonce_ue_present=false; - sm_cmd.nonce_mme_present=false; + sm_cmd.imeisv_req_present = false; + sm_cmd.nonce_ue_present = false; + sm_cmd.nonce_mme_present = false; - uint8_t sec_hdr_type=3; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd,sec_hdr_type, m_sec_ctx.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + uint8_t sec_hdr_type = 3; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_security_mode_command_msg(&sm_cmd, sec_hdr_type, m_sec_ctx.dl_nas_count, + (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->console("Error packing Authentication Request\n"); return false; } - //Generate EPS security context - srslte::security_generate_k_nas( m_sec_ctx.k_asme, - m_sec_ctx.cipher_algo, - m_sec_ctx.integ_algo, - m_sec_ctx.k_nas_enc, - m_sec_ctx.k_nas_int - ); + // Generate EPS security context + srslte::security_generate_k_nas(m_sec_ctx.k_asme, m_sec_ctx.cipher_algo, m_sec_ctx.integ_algo, m_sec_ctx.k_nas_enc, + m_sec_ctx.k_nas_int); m_nas_log->info_hex(m_sec_ctx.k_nas_enc, 32, "Key NAS Encryption (k_nas_enc)\n"); m_nas_log->info_hex(m_sec_ctx.k_nas_int, 32, "Key NAS Integrity (k_nas_int)\n"); @@ -1125,27 +1123,27 @@ nas::pack_security_mode_command(srslte::byte_buffer_t *nas_buffer) m_nas_log->info("Generating KeNB with UL NAS COUNT: %d\n", m_sec_ctx.ul_nas_count); m_nas_log->console("Generating KeNB with UL NAS COUNT: %d\n", m_sec_ctx.ul_nas_count); m_nas_log->info_hex(m_sec_ctx.k_enb, 32, "Key eNodeB (k_enb)\n"); - - //Generate MAC for integrity protection + + // Generate MAC for integrity protection uint8_t mac[4]; integrity_generate(nas_buffer, mac); - memcpy(&nas_buffer->msg[1],mac,4); + memcpy(&nas_buffer->msg[1], mac, 4); return true; } -bool -nas::pack_esm_information_request(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_esm_information_request(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing ESM Information request\n"); LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req; - esm_info_req.eps_bearer_id = 0; + esm_info_req.eps_bearer_id = 0; esm_info_req.proc_transaction_id = m_emm_ctx.procedure_transaction_id; uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; m_sec_ctx.dl_nas_count++; - LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg(&esm_info_req, sec_hdr_type, m_sec_ctx.dl_nas_count,(LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = srslte_mme_pack_esm_information_request_msg( + &esm_info_req, sec_hdr_type, m_sec_ctx.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing ESM information request\n"); m_nas_log->console("Error packing ESM information request\n"); @@ -1160,120 +1158,118 @@ nas::pack_esm_information_request(srslte::byte_buffer_t *nas_buffer) return true; } -bool -nas::pack_attach_accept(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_attach_accept(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing Attach Accept\n"); - LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; + LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept; LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req; - //Get decimal MCC and MNC + // Get decimal MCC and MNC uint32_t mcc = 0; mcc += 0x000F & m_mcc; - mcc += 10*( (0x00F0 & m_mcc) >> 4); - mcc += 100*( (0x0F00 & m_mcc) >> 8); + mcc += 10 * ((0x00F0 & m_mcc) >> 4); + mcc += 100 * ((0x0F00 & m_mcc) >> 8); uint32_t mnc = 0; - if ( 0xFF00 == (m_mnc & 0xFF00)) { - //Two digit MNC - mnc += 0x000F & m_mnc; - mnc += 10*((0x00F0 & m_mnc) >> 4); + if (0xFF00 == (m_mnc & 0xFF00)) { + // Two digit MNC + mnc += 0x000F & m_mnc; + mnc += 10 * ((0x00F0 & m_mnc) >> 4); } else { - //Three digit MNC - mnc += 0x000F & m_mnc; - mnc += 10*((0x00F0 & m_mnc) >> 4); - mnc += 100*((0x0F00 & m_mnc) >> 8); + // Three digit MNC + mnc += 0x000F & m_mnc; + mnc += 10 * ((0x00F0 & m_mnc) >> 4); + mnc += 100 * ((0x0F00 & m_mnc) >> 8); } - //Attach accept + // Attach accept attach_accept.eps_attach_result = m_emm_ctx.attach_type; - //FIXME: Set t3412 from config - attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit - attach_accept.t3412.value = 30; // 30 minute periodic timer + // FIXME: Set t3412 from config + attach_accept.t3412.unit = LIBLTE_MME_GPRS_TIMER_UNIT_1_MINUTE; // GPRS 1 minute unit + attach_accept.t3412.value = 30; // 30 minute periodic timer - attach_accept.tai_list.N_tais = 1; + attach_accept.tai_list.N_tais = 1; attach_accept.tai_list.tai[0].mcc = mcc; attach_accept.tai_list.tai[0].mnc = mnc; attach_accept.tai_list.tai[0].tac = m_tac; m_nas_log->info("Attach Accept -- MCC 0x%x, MNC 0x%x\n", m_mcc, m_mnc); - //Allocate a GUTI ot the UE - attach_accept.guti_present=true; - attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = mcc; - attach_accept.guti.guti.mnc = mnc; + // Allocate a GUTI ot the UE + attach_accept.guti_present = true; + attach_accept.guti.type_of_id = 6; // 110 -> GUTI + attach_accept.guti.guti.mcc = mcc; + attach_accept.guti.guti.mnc = mnc; attach_accept.guti.guti.mme_group_id = m_mme_group; - attach_accept.guti.guti.mme_code = m_mme_code; - attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(m_emm_ctx.imsi); + attach_accept.guti.guti.mme_code = m_mme_code; + attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(m_emm_ctx.imsi); m_nas_log->debug("Allocated GUTI: MCC %d, MNC %d, MME Group Id %d, MME Code 0x%x, M-TMSI 0x%x\n", - attach_accept.guti.guti.mcc, - attach_accept.guti.guti.mnc, - attach_accept.guti.guti.mme_group_id, - attach_accept.guti.guti.mme_code, - attach_accept.guti.guti.m_tmsi); - - //Set up LAI for combined EPS/IMSI attach - attach_accept.lai_present=true; - attach_accept.lai.mcc = mcc; - attach_accept.lai.mnc = mnc; - attach_accept.lai.lac = 001; - - attach_accept.ms_id_present=true; + attach_accept.guti.guti.mcc, attach_accept.guti.guti.mnc, attach_accept.guti.guti.mme_group_id, + attach_accept.guti.guti.mme_code, attach_accept.guti.guti.m_tmsi); + + // Set up LAI for combined EPS/IMSI attach + attach_accept.lai_present = true; + attach_accept.lai.mcc = mcc; + attach_accept.lai.mnc = mnc; + attach_accept.lai.lac = 001; + + attach_accept.ms_id_present = true; attach_accept.ms_id.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_TMSI; - attach_accept.ms_id.tmsi = attach_accept.guti.guti.m_tmsi; - - //Make sure all unused options are set to false - attach_accept.emm_cause_present=false; - attach_accept.t3402_present=false; - attach_accept.t3423_present=false; - attach_accept.equivalent_plmns_present=false; - attach_accept.emerg_num_list_present=false; - attach_accept.eps_network_feature_support_present=false; - attach_accept.additional_update_result_present=false; - attach_accept.t3412_ext_present=false; - - //Set activate default eps bearer (esm_ms) - //Set pdn_addr + attach_accept.ms_id.tmsi = attach_accept.guti.guti.m_tmsi; + + // Make sure all unused options are set to false + attach_accept.emm_cause_present = false; + attach_accept.t3402_present = false; + attach_accept.t3423_present = false; + attach_accept.equivalent_plmns_present = false; + attach_accept.emerg_num_list_present = false; + attach_accept.eps_network_feature_support_present = false; + attach_accept.additional_update_result_present = false; + attach_accept.t3412_ext_present = false; + + // Set activate default eps bearer (esm_ms) + // Set pdn_addr act_def_eps_bearer_context_req.pdn_addr.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4; memcpy(act_def_eps_bearer_context_req.pdn_addr.addr, &m_emm_ctx.ue_ip.s_addr, 4); - //Set eps bearer id - act_def_eps_bearer_context_req.eps_bearer_id = 5; + // Set eps bearer id + act_def_eps_bearer_context_req.eps_bearer_id = 5; act_def_eps_bearer_context_req.transaction_id_present = false; - //set eps_qos - act_def_eps_bearer_context_req.eps_qos.qci = m_esm_ctx[5].qci; - act_def_eps_bearer_context_req.eps_qos.br_present = false; + // set eps_qos + act_def_eps_bearer_context_req.eps_qos.qci = m_esm_ctx[5].qci; + act_def_eps_bearer_context_req.eps_qos.br_present = false; act_def_eps_bearer_context_req.eps_qos.br_ext_present = false; - //set apn - strncpy(act_def_eps_bearer_context_req.apn.apn, m_apn.c_str(), LIBLTE_STRING_LEN-1); - act_def_eps_bearer_context_req.proc_transaction_id = m_emm_ctx.procedure_transaction_id; //FIXME + // set apn + strncpy(act_def_eps_bearer_context_req.apn.apn, m_apn.c_str(), LIBLTE_STRING_LEN - 1); + act_def_eps_bearer_context_req.proc_transaction_id = m_emm_ctx.procedure_transaction_id; // FIXME - //Set DNS server - act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; - act_def_eps_bearer_context_req.protocol_cnfg_opts.N_opts = 1; - act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].id = 0x0d; + // Set DNS server + act_def_eps_bearer_context_req.protocol_cnfg_opts_present = true; + act_def_eps_bearer_context_req.protocol_cnfg_opts.N_opts = 1; + act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].id = 0x0d; act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; struct sockaddr_in dns_addr; inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)); - memcpy(act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents,&dns_addr.sin_addr.s_addr, 4); - - //Make sure all unused options are set to false - act_def_eps_bearer_context_req.negotiated_qos_present = false; - act_def_eps_bearer_context_req.llc_sapi_present = false; - act_def_eps_bearer_context_req.radio_prio_present = false; - act_def_eps_bearer_context_req.packet_flow_id_present = false; - act_def_eps_bearer_context_req.apn_ambr_present = false; - act_def_eps_bearer_context_req.esm_cause_present = false; + memcpy(act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents, &dns_addr.sin_addr.s_addr, 4); + + // Make sure all unused options are set to false + act_def_eps_bearer_context_req.negotiated_qos_present = false; + act_def_eps_bearer_context_req.llc_sapi_present = false; + act_def_eps_bearer_context_req.radio_prio_present = false; + act_def_eps_bearer_context_req.packet_flow_id_present = false; + act_def_eps_bearer_context_req.apn_ambr_present = false; + act_def_eps_bearer_context_req.esm_cause_present = false; act_def_eps_bearer_context_req.connectivity_type_present = false; uint8_t sec_hdr_type = 2; m_sec_ctx.dl_nas_count++; - liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, &attach_accept.esm_msg); - liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, m_sec_ctx.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + liblte_mme_pack_activate_default_eps_bearer_context_request_msg(&act_def_eps_bearer_context_req, + &attach_accept.esm_msg); + liblte_mme_pack_attach_accept_msg(&attach_accept, sec_hdr_type, m_sec_ctx.dl_nas_count, + (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); // Encrypt NAS message cipher_encrypt(nas_buffer); @@ -1281,21 +1277,20 @@ nas::pack_attach_accept(srslte::byte_buffer_t *nas_buffer) // Integrity protect NAS message uint8_t mac[4]; integrity_generate(nas_buffer, mac); - memcpy(&nas_buffer->msg[1],mac,4); + memcpy(&nas_buffer->msg[1], mac, 4); - //Log attach accept info + // Log attach accept info m_nas_log->info("Packed Attach Accept\n"); return true; } -bool -nas::pack_identity_request(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_identity_request(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing Identity Request\n"); LIBLTE_MME_ID_REQUEST_MSG_STRUCT id_req; - id_req.id_type = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_identity_request_msg(&id_req, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + id_req.id_type = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_identity_request_msg(&id_req, (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing Identity Request\n"); m_nas_log->console("Error packing Identity REquest\n"); @@ -1304,26 +1299,26 @@ nas::pack_identity_request(srslte::byte_buffer_t *nas_buffer) return true; } -bool -nas::pack_emm_information(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_emm_information(srslte::byte_buffer_t* nas_buffer) { m_nas_log->info("Packing EMM Information\n"); LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT emm_info; emm_info.full_net_name_present = true; strncpy(emm_info.full_net_name.name, "Software Radio Systems LTE", LIBLTE_STRING_LEN); - emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; + emm_info.full_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; emm_info.short_net_name_present = true; strncpy(emm_info.short_net_name.name, "srsLTE", LIBLTE_STRING_LEN); emm_info.short_net_name.add_ci = LIBLTE_MME_ADD_CI_DONT_ADD; - emm_info.local_time_zone_present = false; + emm_info.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; - uint8_t sec_hdr_type =LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; + uint8_t sec_hdr_type = LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED; m_sec_ctx.dl_nas_count++; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, m_sec_ctx.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, m_sec_ctx.dl_nas_count, + (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing EMM Information\n"); m_nas_log->console("Error packing EMM Information\n"); @@ -1335,27 +1330,27 @@ nas::pack_emm_information(srslte::byte_buffer_t *nas_buffer) // Integrity protect NAS message uint8_t mac[4]; - integrity_generate(nas_buffer,mac); - memcpy(&nas_buffer->msg[1],mac,4); + integrity_generate(nas_buffer, mac); + memcpy(&nas_buffer->msg[1], mac, 4); m_nas_log->info("Packed UE EMM information\n"); return true; } -bool -nas::pack_service_reject(srslte::byte_buffer_t *nas_buffer) +bool nas::pack_service_reject(srslte::byte_buffer_t* nas_buffer) { uint8_t emm_cause = LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED; LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT service_rej; service_rej.t3442_present = true; - service_rej.t3442.unit = LIBLTE_MME_GPRS_TIMER_DEACTIVATED; - service_rej.t3442.value = 0; + service_rej.t3442.unit = LIBLTE_MME_GPRS_TIMER_DEACTIVATED; + service_rej.t3442.value = 0; service_rej.t3446_present = true; - service_rej.t3446 = 0; - service_rej.emm_cause = emm_cause; + service_rej.t3446 = 0; + service_rej.emm_cause = emm_cause; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_service_reject_msg(&service_rej, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + LIBLTE_ERROR_ENUM err = liblte_mme_pack_service_reject_msg(&service_rej, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, + (LIBLTE_BYTE_MSG_STRUCT*)nas_buffer); if (err != LIBLTE_SUCCESS) { m_nas_log->error("Error packing Service Reject\n"); m_nas_log->console("Error packing Service Reject\n"); @@ -1380,30 +1375,19 @@ bool nas::short_integrity_check(srslte::byte_buffer_t* pdu) return false; } - switch (m_sec_ctx.integ_algo) - { - case srslte::INTEGRITY_ALGORITHM_ID_EIA0: - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: - srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[0], - 2, - &exp_mac[0]); - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: - srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[0], - 2, - &exp_mac[0]); - break; - default: - break; + switch (m_sec_ctx.integ_algo) { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], 2, &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], m_sec_ctx.ul_nas_count, 0, SECURITY_DIRECTION_UPLINK, + &pdu->msg[0], 2, &exp_mac[0]); + break; + default: + break; } // Check if expected mac equals the sent mac for (i = 0; i < 2; i++) { @@ -1420,36 +1404,35 @@ bool nas::short_integrity_check(srslte::byte_buffer_t* pdu) return true; } -bool nas::integrity_check(srslte::byte_buffer_t *pdu) +bool nas::integrity_check(srslte::byte_buffer_t* pdu) { - uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t *mac = &pdu->msg[1]; - int i; - - switch (m_sec_ctx.integ_algo) - { - case srslte::INTEGRITY_ALGORITHM_ID_EIA0: - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: - srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - &exp_mac[0]); - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: - srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.ul_nas_count, - 0, - SECURITY_DIRECTION_UPLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - &exp_mac[0]); - break; - default: - break; + uint8_t exp_mac[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t* mac = &pdu->msg[1]; + int i; + + switch (m_sec_ctx.integ_algo) { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], + m_sec_ctx.ul_nas_count, + 0, + SECURITY_DIRECTION_UPLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + &exp_mac[0]); + break; + default: + break; } // Check if expected mac equals the sent mac for (i = 0; i < 4; i++) { @@ -1462,8 +1445,7 @@ bool nas::integrity_check(srslte::byte_buffer_t *pdu) return false; } } - m_nas_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", - m_sec_ctx.ul_nas_count, pdu->msg[5]); + m_nas_log->info("Integrity check ok. Local: count=%d, Received: count=%d\n", m_sec_ctx.ul_nas_count, pdu->msg[5]); return true; } @@ -1474,55 +1456,54 @@ void nas::integrity_generate(srslte::byte_buffer_t* pdu, uint8_t* mac) break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: srslte::security_128_eia1(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.dl_nas_count, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - mac); + m_sec_ctx.dl_nas_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); break; case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: srslte::security_128_eia2(&m_sec_ctx.k_nas_int[16], - m_sec_ctx.dl_nas_count, - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[5], - pdu->N_bytes - 5, - mac); + m_sec_ctx.dl_nas_count, + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[5], + pdu->N_bytes - 5, + mac); break; default: break; } } -void nas::cipher_decrypt(srslte::byte_buffer_t *pdu) +void nas::cipher_decrypt(srslte::byte_buffer_t* pdu) { srslte::byte_buffer_t tmp_pdu; - switch(m_sec_ctx.cipher_algo) - { - case srslte::CIPHERING_ALGORITHM_ID_EEA0: + switch (m_sec_ctx.cipher_algo) { + case srslte::CIPHERING_ALGORITHM_ID_EEA0: break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: + case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: srslte::security_128_eea1(&m_sec_ctx.k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &tmp_pdu.msg[6]); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); m_nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: + case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: srslte::security_128_eea2(&m_sec_ctx.k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_UPLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &tmp_pdu.msg[6]); + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_UPLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &tmp_pdu.msg[6]); m_nas_log->debug_hex(tmp_pdu.msg, pdu->N_bytes, "Decrypted"); - memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6); + memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes - 6); break; default: m_nas_log->error("Ciphering algorithms not known\n"); @@ -1530,39 +1511,37 @@ void nas::cipher_decrypt(srslte::byte_buffer_t *pdu) } } -void nas::cipher_encrypt(srslte::byte_buffer_t *pdu) +void nas::cipher_encrypt(srslte::byte_buffer_t* pdu) { srslte::byte_buffer_t pdu_tmp; - switch(m_sec_ctx.cipher_algo) - { - case srslte::CIPHERING_ALGORITHM_ID_EEA0: + switch (m_sec_ctx.cipher_algo) { + case srslte::CIPHERING_ALGORITHM_ID_EEA0: break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: + case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: srslte::security_128_eea1(&m_sec_ctx.k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); m_nas_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: + case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: srslte::security_128_eea2(&m_sec_ctx.k_nas_enc[16], - pdu->msg[5], - 0, // Bearer always 0 for NAS - SECURITY_DIRECTION_DOWNLINK, - &pdu->msg[6], - pdu->N_bytes-6, - &pdu_tmp.msg[6]); - memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6); + pdu->msg[5], + 0, // Bearer always 0 for NAS + SECURITY_DIRECTION_DOWNLINK, + &pdu->msg[6], + pdu->N_bytes - 6, + &pdu_tmp.msg[6]); + memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes - 6); m_nas_log->debug_hex(pdu_tmp.msg, pdu->N_bytes, "Encrypted"); break; - default: + default: m_nas_log->error("Ciphering algorithm not known\n"); break; } } - -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 95d464ac8..9347b5233 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -24,98 +24,92 @@ * */ -#include -#include -#include // for printing uint64_t -#include "srslte/common/bcd_helpers.h" #include "srsepc/hdr/mme/s1ap.h" #include "srslte/asn1/gtpc.h" +#include "srslte/common/bcd_helpers.h" #include "srslte/common/liblte_security.h" +#include +#include // for printing uint64_t -namespace srsepc{ +namespace srsepc { -s1ap* s1ap::m_instance = NULL; +s1ap* s1ap::m_instance = NULL; pthread_mutex_t s1ap_instance_mutex = PTHREAD_MUTEX_INITIALIZER; -s1ap::s1ap(): - m_s1mme(-1), - m_next_mme_ue_s1ap_id(1), - m_mme_gtpc(NULL), - m_pool(NULL) +s1ap::s1ap() : m_s1mme(-1), m_next_mme_ue_s1ap_id(1), m_mme_gtpc(NULL), m_pool(NULL) { + return; } s1ap::~s1ap() { + return; } -s1ap* -s1ap::get_instance(void) +s1ap* s1ap::get_instance(void) { pthread_mutex_lock(&s1ap_instance_mutex); - if(m_instance == NULL) { + if (m_instance == NULL) { m_instance = new s1ap(); } pthread_mutex_unlock(&s1ap_instance_mutex); - return(m_instance); + return (m_instance); } -void -s1ap::cleanup(void) +void s1ap::cleanup(void) { pthread_mutex_lock(&s1ap_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&s1ap_instance_mutex); } -int -s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *nas_log, srslte::log_filter *s1ap_log, hss_interface_nas * hss) +int s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter* nas_log, srslte::log_filter* s1ap_log) { m_pool = srslte::byte_buffer_pool::get_instance(); m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); m_next_m_tmsi = rand(); - //Init log - m_nas_log = nas_log; + + // Init log + m_nas_log = nas_log; m_s1ap_log = s1ap_log; - //Get pointer to the HSS - m_hss = hss; + // Get pointer to the HSS + m_hss = hss::get_instance(); - //Init message handlers - m_s1ap_mngmt_proc = s1ap_mngmt_proc::get_instance(); //Managment procedures + // Init message handlers + m_s1ap_mngmt_proc = s1ap_mngmt_proc::get_instance(); // Managment procedures m_s1ap_mngmt_proc->init(); - m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); //NAS Transport procedures - m_s1ap_nas_transport->init(m_hss); - m_s1ap_ctx_mngmt_proc = s1ap_ctx_mngmt_proc::get_instance(); //Context Management Procedures + m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); // NAS Transport procedures + m_s1ap_nas_transport->init(); + m_s1ap_ctx_mngmt_proc = s1ap_ctx_mngmt_proc::get_instance(); // Context Management Procedures m_s1ap_ctx_mngmt_proc->init(); - //Get pointer to GTP-C class + // Get pointer to GTP-C class m_mme_gtpc = mme_gtpc::get_instance(); - //Initialize S1-MME + // Initialize S1-MME m_s1mme = enb_listen(); - //Init PCAP + // Init PCAP m_pcap_enable = s1ap_args.pcap_enable; - if(m_pcap_enable){ + if (m_pcap_enable) { m_pcap.open(s1ap_args.pcap_filename.c_str()); } m_s1ap_log->info("S1AP Initialized\n"); return 0; } -void -s1ap::stop() +void s1ap::stop() { - if (m_s1mme != -1){ + if (m_s1mme != -1) { close(m_s1mme); } - std::map::iterator enb_it = m_active_enbs.begin(); - while (enb_it!=m_active_enbs.end()) { + std::map::iterator enb_it = m_active_enbs.begin(); + while (enb_it != m_active_enbs.end()) { m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id); m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id); delete enb_it->second; @@ -123,81 +117,76 @@ s1ap::stop() } std::map::iterator ue_it = m_imsi_to_nas_ctx.begin(); - while (ue_it!=m_imsi_to_nas_ctx.end()) { + while (ue_it != m_imsi_to_nas_ctx.end()) { m_s1ap_log->info("Deleting UE EMM context. IMSI: %015" PRIu64 "\n", ue_it->first); m_s1ap_log->console("Deleting UE EMM context. IMSI: %015" PRIu64 "\n", ue_it->first); delete ue_it->second; m_imsi_to_nas_ctx.erase(ue_it++); } - //Cleanup message handlers + // Cleanup message handlers s1ap_mngmt_proc::cleanup(); s1ap_nas_transport::cleanup(); s1ap_ctx_mngmt_proc::cleanup(); - //PCAP - if(m_pcap_enable){ + // PCAP + if (m_pcap_enable) { m_pcap.close(); } - return; } -int -s1ap::get_s1_mme() +int s1ap::get_s1_mme() { return m_s1mme; } -uint32_t -s1ap::get_next_mme_ue_s1ap_id() +uint32_t s1ap::get_next_mme_ue_s1ap_id() { - return m_next_mme_ue_s1ap_id++; + return m_next_mme_ue_s1ap_id++; } - -int -s1ap::enb_listen() +int s1ap::enb_listen() { /*This function sets up the SCTP socket for eNBs to connect to*/ - int sock_fd, err; - struct sockaddr_in s1mme_addr; + int sock_fd, err; + struct sockaddr_in s1mme_addr; struct sctp_event_subscribe evnts; m_s1ap_log->info("S1-MME Initializing\n"); - sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); - if (sock_fd == -1){ - m_s1ap_log->console("Could not create SCTP socket\n"); + sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); + if (sock_fd == -1) { + m_s1ap_log->console("Could not create SCTP socket\n"); return -1; } - //Sets the data_io_event to be able to use sendrecv_info - //Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown - bzero (&evnts, sizeof (evnts)) ; - evnts.sctp_data_io_event = 1; - evnts.sctp_shutdown_event=1; - if(setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof (evnts))){ + // Sets the data_io_event to be able to use sendrecv_info + // Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown + bzero(&evnts, sizeof(evnts)); + evnts.sctp_data_io_event = 1; + evnts.sctp_shutdown_event = 1; + if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) { close(sock_fd); m_s1ap_log->console("Subscribing to sctp_data_io_events failed\n"); return -1; } - //S1-MME bind + // S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; - inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr) ); + inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr)); s1mme_addr.sin_port = htons(S1MME_PORT); - err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); - if (err != 0){ + err = bind(sock_fd, (struct sockaddr*)&s1mme_addr, sizeof(s1mme_addr)); + if (err != 0) { close(sock_fd); m_s1ap_log->error("Error binding SCTP socket\n"); m_s1ap_log->console("Error binding SCTP socket\n"); return -1; } - //Listen for connections - err = listen(sock_fd,SOMAXCONN); - if (err != 0){ + // Listen for connections + err = listen(sock_fd, SOMAXCONN); + if (err != 0) { close(sock_fd); m_s1ap_log->error("Error in SCTP socket listen\n"); m_s1ap_log->console("Error in SCTP socket listen\n"); @@ -207,88 +196,89 @@ s1ap::enb_listen() return sock_fd; } -bool -s1ap::s1ap_tx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) +bool s1ap::s1ap_tx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri) { ssize_t n_sent = sctp_send(m_s1mme, pdu->msg, pdu->N_bytes, enb_sri, 0); - if(n_sent == -1){ + if (n_sent == -1) { m_s1ap_log->console("Failed to send S1AP PDU.\n"); m_s1ap_log->error("Failed to send S1AP PDU. \n"); return false; } - if(m_pcap_enable){ - m_pcap.write_s1ap(pdu->msg,pdu->N_bytes); + if (m_pcap_enable) { + m_pcap.write_s1ap(pdu->msg, pdu->N_bytes); } return true; } -bool -s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri) +bool s1ap::handle_s1ap_rx_pdu(srslte::byte_buffer_t* pdu, struct sctp_sndrcvinfo* enb_sri) { LIBLTE_S1AP_S1AP_PDU_STRUCT rx_pdu; - if(liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { + if (liblte_s1ap_unpack_s1ap_pdu((LIBLTE_BYTE_MSG_STRUCT*)pdu, &rx_pdu) != LIBLTE_SUCCESS) { m_s1ap_log->error("Failed to unpack received PDU\n"); return false; } - if(m_pcap_enable){ - m_pcap.write_s1ap(pdu->msg,pdu->N_bytes); - } - - switch(rx_pdu.choice_type) { - case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: - m_s1ap_log->info("Received initiating PDU\n"); - return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri); - break; - case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: - m_s1ap_log->info("Received Succeseful Outcome PDU\n"); - return handle_successful_outcome(&rx_pdu.choice.successfulOutcome); - break; - case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: - m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); - return true;//TODO handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); - break; - default: - m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); - return false; + if (m_pcap_enable) { + m_pcap.write_s1ap(pdu->msg, pdu->N_bytes); + } + + switch (rx_pdu.choice_type) { + case LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE: + m_s1ap_log->info("Received initiating PDU\n"); + return handle_initiating_message(&rx_pdu.choice.initiatingMessage, enb_sri); + break; + case LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME: + m_s1ap_log->info("Received Succeseful Outcome PDU\n"); + return handle_successful_outcome(&rx_pdu.choice.successfulOutcome); + break; + case LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME: + m_s1ap_log->info("Received Unsucceseful Outcome PDU\n"); + return true; // TODO handle_unsuccessfuloutcome(&rx_pdu.choice.unsuccessfulOutcome); + break; + default: + m_s1ap_log->error("Unhandled PDU type %d\n", rx_pdu.choice_type); + return false; } return true; - } -bool -s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri) +bool s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* msg, struct sctp_sndrcvinfo* enb_sri) { - bool reply_flag = false; - srslte::byte_buffer_t * reply_buffer = m_pool->allocate(); - bool ret = false; - - switch(msg->choice_type) { - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: - m_s1ap_log->info("Received S1 Setup Request.\n"); - m_s1ap_mngmt_proc->handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri, reply_buffer, &reply_flag); - break; - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: - m_s1ap_log->info("Received Initial UE Message.\n"); - m_s1ap_nas_transport->handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri, reply_buffer, &reply_flag); - break; - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: - m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); - m_s1ap_nas_transport->handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri, reply_buffer, &reply_flag); - break; - case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: - m_s1ap_log->info("Received UE Context Release Request Message.\n"); - m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri, reply_buffer, &reply_flag); - break; - default: - m_s1ap_log->error("Unhandled S1AP intiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); - m_s1ap_log->console("Unhandled S1APintiating message: %s\n", liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); - } - - //Send Reply to eNB - if(reply_flag == true){ + bool reply_flag = false; + srslte::byte_buffer_t* reply_buffer = m_pool->allocate(); + bool ret = false; + + switch (msg->choice_type) { + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_S1SETUPREQUEST: + m_s1ap_log->info("Received S1 Setup Request.\n"); + m_s1ap_mngmt_proc->handle_s1_setup_request(&msg->choice.S1SetupRequest, enb_sri, reply_buffer, &reply_flag); + break; + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALUEMESSAGE: + m_s1ap_log->info("Received Initial UE Message.\n"); + m_s1ap_nas_transport->handle_initial_ue_message(&msg->choice.InitialUEMessage, enb_sri, reply_buffer, + &reply_flag); + break; + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UPLINKNASTRANSPORT: + m_s1ap_log->info("Received Uplink NAS Transport Message.\n"); + m_s1ap_nas_transport->handle_uplink_nas_transport(&msg->choice.UplinkNASTransport, enb_sri, reply_buffer, + &reply_flag); + break; + case LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_UECONTEXTRELEASEREQUEST: + m_s1ap_log->info("Received UE Context Release Request Message.\n"); + m_s1ap_ctx_mngmt_proc->handle_ue_context_release_request(&msg->choice.UEContextReleaseRequest, enb_sri, + reply_buffer, &reply_flag); + break; + default: + m_s1ap_log->error("Unhandled S1AP intiating message: %s\n", + liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); + m_s1ap_log->console("Unhandled S1APintiating message: %s\n", + liblte_s1ap_initiatingmessage_choice_text[msg->choice_type]); + } + + // Send Reply to eNB + if (reply_flag == true) { ret = s1ap_tx_pdu(reply_buffer, enb_sri); } @@ -296,101 +286,91 @@ s1ap::handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, stru return ret; } -bool -s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) +bool s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* msg) { - switch(msg->choice_type) { - case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE: - m_s1ap_log->info("Received Initial Context Setup Response.\n"); - return m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); - case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE: - m_s1ap_log->info("Received UE Context Release Complete\n"); - return m_s1ap_ctx_mngmt_proc->handle_ue_context_release_complete(&msg->choice.UEContextReleaseComplete); - default: - m_s1ap_log->error("Unhandled successful outcome message: %s\n", liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]); + switch (msg->choice_type) { + case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_INITIALCONTEXTSETUPRESPONSE: + m_s1ap_log->info("Received Initial Context Setup Response.\n"); + return m_s1ap_ctx_mngmt_proc->handle_initial_context_setup_response(&msg->choice.InitialContextSetupResponse); + case LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_UECONTEXTRELEASECOMPLETE: + m_s1ap_log->info("Received UE Context Release Complete\n"); + return m_s1ap_ctx_mngmt_proc->handle_ue_context_release_complete(&msg->choice.UEContextReleaseComplete); + default: + m_s1ap_log->error("Unhandled successful outcome message: %s\n", + liblte_s1ap_successfuloutcome_choice_text[msg->choice_type]); } return true; } -//eNB Context Managment -void -s1ap::add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo *enb_sri) +// eNB Context Managment +void s1ap::add_new_enb_ctx(const enb_ctx_t& enb_ctx, const struct sctp_sndrcvinfo* enb_sri) { m_s1ap_log->info("Adding new eNB context. eNB ID %d\n", enb_ctx.enb_id); std::set ue_set; - enb_ctx_t *enb_ptr = new enb_ctx_t; - memcpy(enb_ptr,&enb_ctx,sizeof(enb_ctx_t)); - m_active_enbs.insert(std::pair(enb_ptr->enb_id,enb_ptr)); - m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); - m_enb_assoc_to_ue_ids.insert(std::pair >(enb_sri->sinfo_assoc_id,ue_set)); + enb_ctx_t* enb_ptr = new enb_ctx_t; + memcpy(enb_ptr, &enb_ctx, sizeof(enb_ctx_t)); + m_active_enbs.insert(std::pair(enb_ptr->enb_id, enb_ptr)); + m_sctp_to_enb_id.insert(std::pair(enb_sri->sinfo_assoc_id, enb_ptr->enb_id)); + m_enb_assoc_to_ue_ids.insert(std::pair >(enb_sri->sinfo_assoc_id, ue_set)); return; } -enb_ctx_t* -s1ap::find_enb_ctx(uint16_t enb_id) +enb_ctx_t* s1ap::find_enb_ctx(uint16_t enb_id) { - std::map::iterator it = m_active_enbs.find(enb_id); - if(it == m_active_enbs.end()) - { + std::map::iterator it = m_active_enbs.find(enb_id); + if (it == m_active_enbs.end()) { return NULL; - } - else - { + } else { return it->second; } } -void -s1ap::delete_enb_ctx(int32_t assoc_id) +void s1ap::delete_enb_ctx(int32_t assoc_id) { - std::map::iterator it_assoc = m_sctp_to_enb_id.find(assoc_id); - uint16_t enb_id = it_assoc->second; + std::map::iterator it_assoc = m_sctp_to_enb_id.find(assoc_id); + uint16_t enb_id = it_assoc->second; - std::map::iterator it_ctx = m_active_enbs.find(enb_id); - if(it_ctx == m_active_enbs.end() || it_assoc == m_sctp_to_enb_id.end()) - { - m_s1ap_log->error("Could not find eNB to delete. Association: %d\n",assoc_id); + std::map::iterator it_ctx = m_active_enbs.find(enb_id); + if (it_ctx == m_active_enbs.end() || it_assoc == m_sctp_to_enb_id.end()) { + m_s1ap_log->error("Could not find eNB to delete. Association: %d\n", assoc_id); return; } m_s1ap_log->info("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 release_ues_ecm_ctx_in_enb(assoc_id); - //Delete eNB + // Delete eNB delete it_ctx->second; m_active_enbs.erase(it_ctx); m_sctp_to_enb_id.erase(it_assoc); return; } - //UE Context Management -bool -s1ap::add_nas_ctx_to_imsi_map(nas *nas_ctx) +bool s1ap::add_nas_ctx_to_imsi_map(nas* nas_ctx) { std::map::iterator ctx_it = m_imsi_to_nas_ctx.find(nas_ctx->m_emm_ctx.imsi); if (ctx_it != m_imsi_to_nas_ctx.end()) { - m_s1ap_log->error("UE Context already exists. IMSI %015" PRIu64 "",nas_ctx->m_emm_ctx.imsi); + m_s1ap_log->error("UE Context already exists. IMSI %015" PRIu64 "", nas_ctx->m_emm_ctx.imsi); return false; } if (nas_ctx->m_ecm_ctx.mme_ue_s1ap_id != 0) { - std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_nas_ctx.find(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); - if(ctx_it2 != m_mme_ue_s1ap_id_to_nas_ctx.end() && ctx_it2->second != nas_ctx) { + std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_nas_ctx.find(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); + if (ctx_it2 != m_mme_ue_s1ap_id_to_nas_ctx.end() && ctx_it2->second != nas_ctx) { m_s1ap_log->error("Context identified with IMSI does not match context identified by MME UE S1AP Id.\n"); return false; } } - m_imsi_to_nas_ctx.insert(std::pair(nas_ctx->m_emm_ctx.imsi, nas_ctx)); - m_s1ap_log->debug("Saved UE context corresponding to IMSI %015" PRIu64 "\n",nas_ctx->m_emm_ctx.imsi); + m_imsi_to_nas_ctx.insert(std::pair(nas_ctx->m_emm_ctx.imsi, nas_ctx)); + m_s1ap_log->debug("Saved UE context corresponding to IMSI %015" PRIu64 "\n", nas_ctx->m_emm_ctx.imsi); return true; } -bool -s1ap::add_nas_ctx_to_mme_ue_s1ap_id_map(nas *nas_ctx) +bool s1ap::add_nas_ctx_to_mme_ue_s1ap_id_map(nas* nas_ctx) { if (nas_ctx->m_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."); @@ -398,33 +378,31 @@ s1ap::add_nas_ctx_to_mme_ue_s1ap_id_map(nas *nas_ctx) } std::map::iterator ctx_it = m_mme_ue_s1ap_id_to_nas_ctx.find(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); if (ctx_it != m_mme_ue_s1ap_id_to_nas_ctx.end()) { - m_s1ap_log->error("UE Context already exists. MME UE S1AP Id %015" PRIu64 "",nas_ctx->m_emm_ctx.imsi); + m_s1ap_log->error("UE Context already exists. MME UE S1AP Id %015" PRIu64 "", nas_ctx->m_emm_ctx.imsi); return false; } if (nas_ctx->m_emm_ctx.imsi != 0) { - std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_nas_ctx.find(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); + std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_nas_ctx.find(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); if (ctx_it2 != m_mme_ue_s1ap_id_to_nas_ctx.end() && ctx_it2->second != nas_ctx) { m_s1ap_log->error("Context identified with MME UE S1AP Id does not match context identified by IMSI.\n"); return false; } } m_mme_ue_s1ap_id_to_nas_ctx.insert(std::pair(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id, nas_ctx)); - m_s1ap_log->debug("Saved UE context corresponding to MME UE S1AP Id %d\n",nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); + m_s1ap_log->debug("Saved UE context corresponding to MME UE S1AP Id %d\n", nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); return true; } -bool -s1ap::add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id) +bool s1ap::add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id) { - std::map >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc); + std::map >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc); if (ues_in_enb == m_enb_assoc_to_ue_ids.end()) { - m_s1ap_log->error("Could not find eNB from eNB SCTP association %d",enb_assoc); + m_s1ap_log->error("Could not find eNB from eNB SCTP association %d", enb_assoc); return false; } std::set::iterator ue_id = ues_in_enb->second.find(mme_ue_s1ap_id); - if(ue_id != ues_in_enb->second.end()) - { - m_s1ap_log->error("UE with MME UE S1AP Id already exists %d",mme_ue_s1ap_id); + if (ue_id != ues_in_enb->second.end()) { + m_s1ap_log->error("UE with MME UE S1AP Id already exists %d", mme_ue_s1ap_id); return false; } ues_in_enb->second.insert(mme_ue_s1ap_id); @@ -432,8 +410,7 @@ s1ap::add_ue_to_enb_set(int32_t enb_assoc, uint32_t mme_ue_s1ap_id) return true; } -nas* -s1ap::find_nas_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) +nas* s1ap::find_nas_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) { std::map::iterator it = m_mme_ue_s1ap_id_to_nas_ctx.find(mme_ue_s1ap_id); if (it == m_mme_ue_s1ap_id_to_nas_ctx.end()) { @@ -443,8 +420,7 @@ s1ap::find_nas_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) } } -nas* -s1ap::find_nas_ctx_from_imsi(uint64_t imsi) +nas* s1ap::find_nas_ctx_from_imsi(uint64_t imsi) { std::map::iterator it = m_imsi_to_nas_ctx.find(imsi); if (it == m_imsi_to_nas_ctx.end()) { @@ -454,27 +430,27 @@ s1ap::find_nas_ctx_from_imsi(uint64_t imsi) } } -void -s1ap::release_ues_ecm_ctx_in_enb(int32_t enb_assoc) +void s1ap::release_ues_ecm_ctx_in_enb(int32_t enb_assoc) { m_s1ap_log->console("Releasing UEs context\n"); - std::map >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc); - std::set::iterator ue_id = ues_in_enb->second.begin(); + std::map >::iterator ues_in_enb = m_enb_assoc_to_ue_ids.find(enb_assoc); + std::set::iterator ue_id = ues_in_enb->second.begin(); if (ue_id == ues_in_enb->second.end()) { m_s1ap_log->console("No UEs to be released\n"); } else { - while (ue_id != ues_in_enb->second.end() ) { + while (ue_id != ues_in_enb->second.end()) { std::map::iterator nas_ctx = m_mme_ue_s1ap_id_to_nas_ctx.find(*ue_id); - emm_ctx_t *emm_ctx = &nas_ctx->second->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->second->m_ecm_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->second->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->second->m_ecm_ctx; - m_s1ap_log->info("Releasing UE context. IMSI: %015" PRIu64 ", UE-MME S1AP Id: %d\n", emm_ctx->imsi, ecm_ctx->mme_ue_s1ap_id); - if(emm_ctx->state == EMM_STATE_REGISTERED) { + m_s1ap_log->info("Releasing UE context. IMSI: %015" PRIu64 ", UE-MME S1AP Id: %d\n", emm_ctx->imsi, + ecm_ctx->mme_ue_s1ap_id); + if (emm_ctx->state == EMM_STATE_REGISTERED) { m_mme_gtpc->send_delete_session_request(emm_ctx->imsi); emm_ctx->state = EMM_STATE_DEREGISTERED; } m_s1ap_log->console("Releasing UE ECM context. UE-MME S1AP Id: %d\n", ecm_ctx->mme_ue_s1ap_id); - ecm_ctx->state = ECM_STATE_IDLE; + ecm_ctx->state = ECM_STATE_IDLE; ecm_ctx->mme_ue_s1ap_id = 0; ecm_ctx->enb_ue_s1ap_id = 0; ues_in_enb->second.erase(ue_id++); @@ -482,33 +458,32 @@ s1ap::release_ues_ecm_ctx_in_enb(int32_t enb_assoc) } } -bool -s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) +bool s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) { - nas *nas_ctx = find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + nas* nas_ctx = find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); if (nas_ctx == NULL) { m_s1ap_log->error("Cannot release UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); return false; } ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; - //Delete UE within eNB UE set - std::map::iterator it = m_sctp_to_enb_id.find(ecm_ctx->enb_sri.sinfo_assoc_id); - if (it == m_sctp_to_enb_id.end() ) { + // Delete UE within eNB UE set + std::map::iterator it = m_sctp_to_enb_id.find(ecm_ctx->enb_sri.sinfo_assoc_id); + if (it == m_sctp_to_enb_id.end()) { m_s1ap_log->error("Could not find eNB for UE release request.\n"); return false; } - uint16_t enb_id = it->second; - std::map >::iterator ue_set = m_enb_assoc_to_ue_ids.find(ecm_ctx->enb_sri.sinfo_assoc_id); + uint16_t enb_id = it->second; + std::map >::iterator ue_set = m_enb_assoc_to_ue_ids.find(ecm_ctx->enb_sri.sinfo_assoc_id); if (ue_set == m_enb_assoc_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); - //Release UE ECM context + // Release UE ECM context m_mme_ue_s1ap_id_to_nas_ctx.erase(mme_ue_s1ap_id); - ecm_ctx->state = ECM_STATE_IDLE; + ecm_ctx->state = ECM_STATE_IDLE; ecm_ctx->mme_ue_s1ap_id = 0; ecm_ctx->enb_ue_s1ap_id = 0; @@ -516,76 +491,73 @@ s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) return true; } -bool -s1ap::delete_ue_ctx(uint64_t imsi) +bool s1ap::delete_ue_ctx(uint64_t imsi) { - nas *nas_ctx = find_nas_ctx_from_imsi(imsi); + nas* nas_ctx = find_nas_ctx_from_imsi(imsi); if (nas_ctx == NULL) { m_s1ap_log->info("Cannot delete UE context, UE not found. IMSI: %" PRIu64 "\n", imsi); return false; } - //Make sure to release ECM ctx + // Make sure to release ECM ctx if (nas_ctx->m_ecm_ctx.mme_ue_s1ap_id != 0) { release_ue_ecm_ctx(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); } - //Delete UE context + // Delete UE context m_imsi_to_nas_ctx.erase(imsi); delete nas_ctx; m_s1ap_log->info("Deleted UE Context.\n"); return true; } - - - //UE Bearer Managment -void -s1ap::activate_eps_bearer(uint64_t imsi, uint8_t ebi) +void s1ap::activate_eps_bearer(uint64_t imsi, uint8_t ebi) { - std::map::iterator ue_ctx_it = m_imsi_to_nas_ctx.find(imsi); + std::map::iterator ue_ctx_it = m_imsi_to_nas_ctx.find(imsi); if (ue_ctx_it == m_imsi_to_nas_ctx.end()) { m_s1ap_log->error("Could not activate EPS bearer: Could not find UE context\n"); - return; + return; } - //Make sure NAS is active - uint32_t mme_ue_s1ap_id = ue_ctx_it->second->m_ecm_ctx.mme_ue_s1ap_id; - std::map::iterator it = m_mme_ue_s1ap_id_to_nas_ctx.find(mme_ue_s1ap_id); + // Make sure NAS is active + uint32_t mme_ue_s1ap_id = ue_ctx_it->second->m_ecm_ctx.mme_ue_s1ap_id; + std::map::iterator it = m_mme_ue_s1ap_id_to_nas_ctx.find(mme_ue_s1ap_id); if (it == m_mme_ue_s1ap_id_to_nas_ctx.end()) { m_s1ap_log->error("Could not activate EPS bearer: ECM context seems to be missing\n"); return; } - ecm_ctx_t * ecm_ctx = &ue_ctx_it->second->m_ecm_ctx; - esm_ctx_t * esm_ctx = &ue_ctx_it->second->m_esm_ctx[ebi]; + ecm_ctx_t* ecm_ctx = &ue_ctx_it->second->m_ecm_ctx; + esm_ctx_t* esm_ctx = &ue_ctx_it->second->m_esm_ctx[ebi]; if (esm_ctx->state != ERAB_CTX_SETUP) { - m_s1ap_log->error("Could not be activate EPS Bearer, bearer in wrong state: MME S1AP Id %d, EPS Bearer id %d, state %d\n", mme_ue_s1ap_id, ebi, esm_ctx->state); - m_s1ap_log->console("Could not be activate EPS Bearer, bearer in wrong state: MME S1AP Id %d, EPS Bearer id %d, state %d\n", mme_ue_s1ap_id, ebi, esm_ctx->state); + m_s1ap_log->error( + "Could not be activate EPS Bearer, bearer in wrong state: MME S1AP Id %d, EPS Bearer id %d, state %d\n", + mme_ue_s1ap_id, ebi, esm_ctx->state); + m_s1ap_log->console( + "Could not be activate EPS Bearer, bearer in wrong state: MME S1AP Id %d, EPS Bearer id %d, state %d\n", + mme_ue_s1ap_id, ebi, esm_ctx->state); return; } esm_ctx->state = ERAB_ACTIVE; ecm_ctx->state = ECM_STATE_CONNECTED; - m_s1ap_log->info("Activated EPS Bearer: Bearer id %d\n",ebi); + m_s1ap_log->info("Activated EPS Bearer: Bearer id %d\n", ebi); return; } -uint32_t -s1ap::allocate_m_tmsi(uint64_t imsi) +uint32_t s1ap::allocate_m_tmsi(uint64_t imsi) { uint32_t m_tmsi = m_next_m_tmsi; - m_next_m_tmsi = (m_next_m_tmsi + 1) % UINT32_MAX; + m_next_m_tmsi = (m_next_m_tmsi + 1) % UINT32_MAX; - m_tmsi_to_imsi.insert(std::pair(m_tmsi,imsi)); - m_s1ap_log->debug("Allocated M-TMSI 0x%x to IMSI %015" PRIu64 ",\n",m_tmsi,imsi); + m_tmsi_to_imsi.insert(std::pair(m_tmsi, imsi)); + m_s1ap_log->debug("Allocated M-TMSI 0x%x to IMSI %015" PRIu64 ",\n", m_tmsi, imsi); return m_tmsi; } -uint64_t -s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi) +uint64_t s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi) { - std::map::iterator it = m_tmsi_to_imsi.find(m_tmsi); + std::map::iterator it = m_tmsi_to_imsi.find(m_tmsi); if (it != m_tmsi_to_imsi.end()) { m_s1ap_log->debug("Found IMSI %015" PRIu64 " from M-TMSI 0x%x\n", it->second, m_tmsi); return it->second; @@ -595,38 +567,37 @@ s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi) } } -void -s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx) +void s1ap::print_enb_ctx_info(const std::string& prefix, const enb_ctx_t& enb_ctx) { std::string mnc_str, mcc_str; if (enb_ctx.enb_name_present) { - m_s1ap_log->console("%s - eNB Name: %s, eNB id: 0x%x\n",prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); + m_s1ap_log->console("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); m_s1ap_log->info("%s - eNB Name: %s, eNB id: 0x%x\n", prefix.c_str(), enb_ctx.enb_name, enb_ctx.enb_id); } else { - m_s1ap_log->console("%s - eNB Id 0x%x\n",prefix.c_str(), enb_ctx.enb_id); + m_s1ap_log->console("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id); m_s1ap_log->info("%s - eNB Id 0x%x\n", prefix.c_str(), enb_ctx.enb_id); } srslte::mcc_to_string(enb_ctx.mcc, &mcc_str); srslte::mnc_to_string(enb_ctx.mnc, &mnc_str); m_s1ap_log->info("%s - MCC:%s, MNC:%s, PLMN: %d\n", prefix.c_str(), mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); - m_s1ap_log->console("%s - MCC:%s, MNC:%s, PLMN: %d\n", prefix.c_str(), mcc_str.c_str(), mnc_str.c_str(), enb_ctx.plmn); - for (int i=0;iinfo("%s - TAC %d, B-PLMN %d\n",prefix.c_str(), enb_ctx.tac[i],enb_ctx.bplmns[i][j]); - m_s1ap_log->console("%s - TAC %d, B-PLMN %d\n",prefix.c_str(), enb_ctx.tac[i],enb_ctx.bplmns[i][j]); + m_s1ap_log->console("%s - MCC:%s, MNC:%s, PLMN: %d\n", prefix.c_str(), mcc_str.c_str(), mnc_str.c_str(), + enb_ctx.plmn); + for (int i = 0; i < enb_ctx.nof_supported_ta; i++) { + for (int j = 0; i < enb_ctx.nof_supported_ta; i++) { + m_s1ap_log->info("%s - TAC %d, B-PLMN %d\n", prefix.c_str(), enb_ctx.tac[i], enb_ctx.bplmns[i][j]); + m_s1ap_log->console("%s - TAC %d, B-PLMN %d\n", prefix.c_str(), enb_ctx.tac[i], enb_ctx.bplmns[i][j]); } } - m_s1ap_log->console("%s - Paging DRX %d\n",prefix.c_str(),enb_ctx.drx); + m_s1ap_log->console("%s - Paging DRX %d\n", prefix.c_str(), enb_ctx.drx); return; } /* * Interfaces */ -/*GTP-C||NAS -> S1AP interface*/ -bool -s1ap::send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) +/* GTP-C || NAS -> S1AP interface */ +bool s1ap::send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) { nas* nas_ctx = find_nas_ctx_from_imsi(imsi); if (nas_ctx == NULL) { @@ -637,9 +608,8 @@ s1ap::send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) return true; } -/*NAS -> S1AP interface*/ -bool -s1ap::send_ue_context_release_command(uint32_t mme_ue_s1ap_id) +/* NAS -> S1AP interface */ +bool s1ap::send_ue_context_release_command(uint32_t mme_ue_s1ap_id) { nas* nas_ctx = find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); if (nas_ctx == NULL) { @@ -650,9 +620,11 @@ s1ap::send_ue_context_release_command(uint32_t mme_ue_s1ap_id) return true; } -bool -s1ap::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t *nas_msg, struct sctp_sndrcvinfo enb_sri) +bool s1ap::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + srslte::byte_buffer_t* nas_msg, + struct sctp_sndrcvinfo enb_sri) { return m_s1ap_nas_transport->send_downlink_nas_transport(enb_ue_s1ap_id, mme_ue_s1ap_id, nas_msg, enb_sri); } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index fc2e92ac7..702ce01a3 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -24,22 +24,28 @@ * */ -#include "srslte/common/bcd_helpers.h" -#include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/mme/s1ap_ctx_mngmt_proc.h" -#include "srslte/common/liblte_security.h" +#include "srsepc/hdr/mme/s1ap.h" +#include "srslte/common/bcd_helpers.h" #include "srslte/common/int_helpers.h" +#include "srslte/common/liblte_security.h" - -namespace srsepc{ +namespace srsepc { s1ap_ctx_mngmt_proc* s1ap_ctx_mngmt_proc::m_instance = NULL; pthread_mutex_t s1ap_ctx_mngmt_proc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; -s1ap_ctx_mngmt_proc::s1ap_ctx_mngmt_proc() {} -s1ap_ctx_mngmt_proc::~s1ap_ctx_mngmt_proc() {} +s1ap_ctx_mngmt_proc::s1ap_ctx_mngmt_proc() +{ + return; +} + +s1ap_ctx_mngmt_proc::~s1ap_ctx_mngmt_proc() +{ + return; +} -s1ap_ctx_mngmt_proc* s1ap_ctx_mngmt_proc::get_instance(void) +s1ap_ctx_mngmt_proc* s1ap_ctx_mngmt_proc::get_instance() { pthread_mutex_lock(&s1ap_ctx_mngmt_proc_instance_mutex); if (NULL == m_instance) { @@ -49,7 +55,7 @@ s1ap_ctx_mngmt_proc* s1ap_ctx_mngmt_proc::get_instance(void) return (m_instance); } -void s1ap_ctx_mngmt_proc::cleanup(void) +void s1ap_ctx_mngmt_proc::cleanup() { pthread_mutex_lock(&s1ap_ctx_mngmt_proc_instance_mutex); if (NULL != m_instance) { @@ -59,14 +65,13 @@ void s1ap_ctx_mngmt_proc::cleanup(void) pthread_mutex_unlock(&s1ap_ctx_mngmt_proc_instance_mutex); } -void s1ap_ctx_mngmt_proc::init(void) +void s1ap_ctx_mngmt_proc::init() { - m_s1ap = s1ap::get_instance(); - m_mme_gtpc = mme_gtpc::get_instance(); - m_s1ap_log = m_s1ap->m_s1ap_log; - m_s1ap_args = m_s1ap->m_s1ap_args; - m_pool = srslte::byte_buffer_pool::get_instance(); - m_s1ap_nas_transport = s1ap_nas_transport::get_instance(); + m_s1ap = s1ap::get_instance(); + m_mme_gtpc = mme_gtpc::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; + m_s1ap_args = m_s1ap->m_s1ap_args; + m_pool = srslte::byte_buffer_pool::get_instance(); } bool s1ap_ctx_mngmt_proc::send_initial_context_setup_request(nas* nas_ctx, uint16_t erab_to_setup) @@ -238,7 +243,8 @@ bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response( bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT* ue_rel, struct sctp_sndrcvinfo* enb_sri, - srslte::byte_buffer_t* reply_buffer, bool* reply_flag) + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag) { LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT ue_rel_req; @@ -246,40 +252,40 @@ bool s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_ 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); - nas * nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); if (nas_ctx == NULL) { m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); return false; } - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_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) { - //There are active E-RABs, send release access mearers request + // There are active E-RABs, send release access mearers request m_s1ap_log->console("There are active E-RABs, send release access bearers request\n"); m_s1ap_log->info("There are active E-RABs, send release access bearers request\n"); - //The handle_release_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. + // The handle_release_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. m_mme_gtpc->send_release_access_bearers_request(emm_ctx->imsi); - //Send release context command to enb, so that it can release it's bearers + // Send release context command to enb, so that it can release it's bearers send_ue_context_release_command(nas_ctx); } 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->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); - //Make sure E-RABS are merked as DEACTIVATED. - for (int i=0;im_esm_ctx[i].state = ERAB_DEACTIVATED; } } - //Set UE context to ECM Idle - ecm_ctx->state = ECM_STATE_IDLE; + // Set UE context to ECM Idle + ecm_ctx->state = ECM_STATE_IDLE; ecm_ctx->enb_ue_s1ap_id = 0; ecm_ctx->mme_ue_s1ap_id = 0; m_s1ap_log->info("UE is ECM IDLE.\n"); @@ -334,14 +340,14 @@ bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete( m_s1ap_log->info("Received UE Context Release Complete. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Complete. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); - nas * nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + nas* nas_ctx = m_s1ap->find_nas_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); if (nas_ctx == NULL) { m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); return false; } - emm_ctx_t *emm_ctx = &nas_ctx->m_emm_ctx; - ecm_ctx_t *ecm_ctx = &nas_ctx->m_ecm_ctx; + emm_ctx_t* emm_ctx = &nas_ctx->m_emm_ctx; + ecm_ctx_t* ecm_ctx = &nas_ctx->m_ecm_ctx; // Delete user plane context at the SPGW (but keep GTP-C connection). if (ecm_ctx->state == ECM_STATE_CONNECTED) { @@ -349,22 +355,22 @@ bool s1ap_ctx_mngmt_proc::handle_ue_context_release_complete( m_s1ap_log->console("There are active E-RABs, send release access bearers request"); m_s1ap_log->info("There are active E-RABs, send release access bearers request"); m_mme_gtpc->send_release_access_bearers_request(emm_ctx->imsi); - //The handle_release_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. + // The handle_release_access_bearers_response function will make sure to mark E-RABS DEACTIVATED + // It will release the UEs downstream S1-U and keep the upstream S1-U connection active. } else { - //No ECM Context to release + // No ECM Context to release m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); - //Make sure E-RABS are marked as DEACTIVATED. - for (int i=0;im_esm_ctx[i].state = ERAB_DEACTIVATED; } } - //Delete UE context + // Delete UE context m_s1ap->release_ue_ecm_ctx(nas_ctx->m_ecm_ctx.mme_ue_s1ap_id); m_s1ap_log->info("UE Context Release Completed.\n"); m_s1ap_log->console("UE Context Release Completed.\n"); return true; } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/s1ap_mngmt_proc.cc b/srsepc/src/mme/s1ap_mngmt_proc.cc index dbd45cdd9..f9667aa2e 100644 --- a/srsepc/src/mme/s1ap_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_mngmt_proc.cc @@ -24,92 +24,84 @@ * */ -//#include "srslte/upper/s1ap_common.h" -#include "srslte/common/bcd_helpers.h" -#include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/mme/s1ap_mngmt_proc.h" +#include "srsepc/hdr/mme/s1ap.h" +#include "srslte/common/bcd_helpers.h" -namespace srsepc{ - -s1ap_mngmt_proc* s1ap_mngmt_proc::m_instance = NULL; -pthread_mutex_t s1ap_mngmt_proc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; +namespace srsepc { +s1ap_mngmt_proc* s1ap_mngmt_proc::m_instance = NULL; +pthread_mutex_t s1ap_mngmt_proc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; s1ap_mngmt_proc::s1ap_mngmt_proc() { + return; } s1ap_mngmt_proc::~s1ap_mngmt_proc() { + return; } -s1ap_mngmt_proc* -s1ap_mngmt_proc::get_instance(void) +s1ap_mngmt_proc* s1ap_mngmt_proc::get_instance(void) { pthread_mutex_lock(&s1ap_mngmt_proc_instance_mutex); - if(NULL == m_instance) { + if (NULL == m_instance) { m_instance = new s1ap_mngmt_proc(); } pthread_mutex_unlock(&s1ap_mngmt_proc_instance_mutex); - return(m_instance); + return (m_instance); } -void -s1ap_mngmt_proc::cleanup(void) +void s1ap_mngmt_proc::cleanup(void) { pthread_mutex_lock(&s1ap_mngmt_proc_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&s1ap_mngmt_proc_instance_mutex); } -void -s1ap_mngmt_proc::init(void) +void s1ap_mngmt_proc::init(void) { - m_s1ap = s1ap::get_instance(); - m_s1ap_log = m_s1ap->m_s1ap_log; - m_s1mme = m_s1ap->get_s1_mme(); + m_s1ap = s1ap::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; + m_s1mme = m_s1ap->get_s1_mme(); m_s1ap_args = m_s1ap->m_s1ap_args; } -bool -s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +bool s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag) { - - enb_ctx_t enb_ctx; + enb_ctx_t enb_ctx; LIBLTE_S1AP_S1AP_PDU_STRUCT reply_pdu; - if(!unpack_s1_setup_request(msg, &enb_ctx)) - { + if (!unpack_s1_setup_request(msg, &enb_ctx)) { m_s1ap_log->error("Malformed S1 Setup Request\n"); return false; } - //Log S1 Setup Request Info + // Log S1 Setup Request Info m_s1ap_log->console("Received S1 Setup Request.\n"); - m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"),enb_ctx); - - //Check matching PLMNs - if(enb_ctx.plmn!=m_s1ap->get_plmn()){ + m_s1ap->print_enb_ctx_info(std::string("S1 Setup Request"), enb_ctx); + // Check matching PLMNs + if (enb_ctx.plmn != m_s1ap->get_plmn()) { m_s1ap_log->console("Sending S1 Setup Failure - Unknown PLMN\n"); m_s1ap_log->warning("Sending S1 Setup Failure - Unknown PLMN\n"); - pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN,reply_buffer); - } - else{ - enb_ctx_t *enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id); - if(enb_ptr != NULL) - { - //eNB already registered - //TODO replace enb_ctx + pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_UNKNOWN_PLMN, reply_buffer); + } else { + enb_ctx_t* enb_ptr = m_s1ap->find_enb_ctx(enb_ctx.enb_id); + if (enb_ptr != NULL) { + // eNB already registered + // TODO replace enb_ctx m_s1ap_log->warning("eNB Already registered\n"); - } - else - { - //new eNB - m_s1ap->add_new_enb_ctx(enb_ctx,enb_sri); + } else { + // new eNB + m_s1ap->add_new_enb_ctx(enb_ctx, enb_sri); } pack_s1_setup_response(m_s1ap_args, reply_buffer); @@ -121,33 +113,31 @@ s1ap_mngmt_proc::handle_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU return true; } - /* * Packing/Unpacking helper functions. */ -bool -s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT *msg, enb_ctx_t* enb_ctx) +bool s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRUCT* msg, enb_ctx_t* enb_ctx) { - - uint8_t enb_id_bits[32]; - uint32_t plmn = 0; + + uint8_t enb_id_bits[32]; + uint32_t plmn = 0; uint16_t tac, bplmn; - uint32_t tmp32=0; - //eNB Name - enb_ctx->enb_name_present=msg->eNBname_present; - if(msg->eNBname_present) - { - bzero(enb_ctx->enb_name,sizeof(enb_ctx->enb_name)); - memcpy(enb_ctx->enb_name,&msg->eNBname.buffer,msg->eNBname.n_octets); + uint32_t tmp32 = 0; + // eNB Name + enb_ctx->enb_name_present = msg->eNBname_present; + if (msg->eNBname_present) { + bzero(enb_ctx->enb_name, sizeof(enb_ctx->enb_name)); + memcpy(enb_ctx->enb_name, &msg->eNBname.buffer, msg->eNBname.n_octets); } - //eNB Id - bzero(enb_id_bits,sizeof(enb_id_bits)); - memcpy(&enb_id_bits[32-LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN], msg->Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer, LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN); - liblte_pack(enb_id_bits, 32, (uint8_t*) &tmp32); - enb_ctx->enb_id=ntohl(tmp32); - - //PLMN Id + // eNB Id + bzero(enb_id_bits, sizeof(enb_id_bits)); + memcpy(&enb_id_bits[32 - LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN], msg->Global_ENB_ID.eNB_ID.choice.macroENB_ID.buffer, + LIBLTE_S1AP_MACROENB_ID_BIT_STRING_LEN); + liblte_pack(enb_id_bits, 32, (uint8_t*)&tmp32); + enb_ctx->enb_id = ntohl(tmp32); + + // PLMN Id ((uint8_t*)&plmn)[1] = msg->Global_ENB_ID.pLMNidentity.buffer[0]; ((uint8_t*)&plmn)[2] = msg->Global_ENB_ID.pLMNidentity.buffer[1]; ((uint8_t*)&plmn)[3] = msg->Global_ENB_ID.pLMNidentity.buffer[2]; @@ -155,18 +145,16 @@ s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU enb_ctx->plmn = ntohl(plmn); srslte::s1ap_plmn_to_mccmnc(enb_ctx->plmn, &enb_ctx->mcc, &enb_ctx->mnc); - //SupportedTAs - enb_ctx->nof_supported_ta=msg->SupportedTAs.len; - for(uint16_t i=0; iSupportedTAs.len; i++) - { - //TAC - ((uint8_t*)&enb_ctx->tac[i])[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; - ((uint8_t*)&enb_ctx->tac[i])[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; - enb_ctx->tac[i]=ntohs(enb_ctx->tac[i]); - enb_ctx->nof_supported_bplmns[i]=msg->SupportedTAs.buffer[i].broadcastPLMNs.len; - for (uint16_t j=0; jSupportedTAs.buffer[i].broadcastPLMNs.len; j++) - { - //BPLMNs + // SupportedTAs + enb_ctx->nof_supported_ta = msg->SupportedTAs.len; + for (uint16_t i = 0; i < msg->SupportedTAs.len; i++) { + // TAC + ((uint8_t*)&enb_ctx->tac[i])[0] = msg->SupportedTAs.buffer[i].tAC.buffer[0]; + ((uint8_t*)&enb_ctx->tac[i])[1] = msg->SupportedTAs.buffer[i].tAC.buffer[1]; + enb_ctx->tac[i] = ntohs(enb_ctx->tac[i]); + enb_ctx->nof_supported_bplmns[i] = msg->SupportedTAs.buffer[i].broadcastPLMNs.len; + for (uint16_t j = 0; j < msg->SupportedTAs.buffer[i].broadcastPLMNs.len; j++) { + // BPLMNs ((uint8_t*)&enb_ctx->bplmns[i][j])[1] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[0]; ((uint8_t*)&enb_ctx->bplmns[i][j])[2] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[1]; ((uint8_t*)&enb_ctx->bplmns[i][j])[3] = msg->SupportedTAs.buffer[i].broadcastPLMNs.buffer[j].buffer[2]; @@ -175,41 +163,38 @@ s1ap_mngmt_proc::unpack_s1_setup_request(LIBLTE_S1AP_MESSAGE_S1SETUPREQUEST_STRU } } - //Default Paging DRX + // Default Paging DRX enb_ctx->drx = msg->DefaultPagingDRX.e; return true; } -bool -s1ap_mngmt_proc::pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t *msg) +bool s1ap_mngmt_proc::pack_s1_setup_failure(LIBLTE_S1AP_CAUSEMISC_ENUM cause, srslte::byte_buffer_t* msg) { LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_UNSUCCESSFULOUTCOME; - LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT *unsucc = &pdu.choice.unsuccessfulOutcome; - unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; - unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; - unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE; - - LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail=(LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; - - s1_fail->TimeToWait_present=false; - s1_fail->CriticalityDiagnostics_present=false; - s1_fail->Cause.ext=false; - s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; - s1_fail->Cause.choice.misc.ext=false; - s1_fail->Cause.choice.misc.e=cause; - + LIBLTE_S1AP_UNSUCCESSFULOUTCOME_STRUCT* unsucc = &pdu.choice.unsuccessfulOutcome; + unsucc->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + unsucc->criticality = LIBLTE_S1AP_CRITICALITY_REJECT; + unsucc->choice_type = LIBLTE_S1AP_UNSUCCESSFULOUTCOME_CHOICE_S1SETUPFAILURE; + + LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT* s1_fail = (LIBLTE_S1AP_MESSAGE_S1SETUPFAILURE_STRUCT*)&unsucc->choice; + + s1_fail->TimeToWait_present = false; + s1_fail->CriticalityDiagnostics_present = false; + s1_fail->Cause.ext = false; + s1_fail->Cause.choice_type = LIBLTE_S1AP_CAUSE_CHOICE_MISC; + s1_fail->Cause.choice.misc.ext = false; + s1_fail->Cause.choice.misc.e = cause; + liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); return true; - } - +} -bool -s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t *msg) +bool s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buffer_t* msg) { LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; @@ -217,55 +202,50 @@ s1ap_mngmt_proc::pack_s1_setup_response(s1ap_args_t s1ap_args, srslte::byte_buff pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_SUCCESSFULOUTCOME; - LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *succ = &pdu.choice.successfulOutcome; - succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; - succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; - succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; + LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT* succ = &pdu.choice.successfulOutcome; + succ->procedureCode = LIBLTE_S1AP_PROC_ID_S1SETUP; + succ->criticality = LIBLTE_S1AP_CRITICALITY_IGNORE; + succ->choice_type = LIBLTE_S1AP_SUCCESSFULOUTCOME_CHOICE_S1SETUPRESPONSE; - LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp=(LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; + LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT* s1_resp = (LIBLTE_S1AP_MESSAGE_S1SETUPRESPONSE_STRUCT*)&succ->choice; - s1_resp->ext=false; + s1_resp->ext = false; - //MME Name - s1_resp->MMEname_present=true; - s1_resp->MMEname.ext=false; - s1_resp->MMEname.n_octets=s1ap_args.mme_name.length(); - memcpy(s1_resp->MMEname.buffer,s1ap_args.mme_name.c_str(),s1ap_args.mme_name.length()); + // MME Name + s1_resp->MMEname_present = true; + s1_resp->MMEname.ext = false; + s1_resp->MMEname.n_octets = s1ap_args.mme_name.length(); + memcpy(s1_resp->MMEname.buffer, s1ap_args.mme_name.c_str(), s1ap_args.mme_name.length()); - //Served GUMEIs - s1_resp->ServedGUMMEIs.len=1;//TODO Only one served GUMMEI supported - LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT *serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; + // Served GUMEIs + s1_resp->ServedGUMMEIs.len = 1; // TODO Only one served GUMMEI supported + LIBLTE_S1AP_SERVEDGUMMEISITEM_STRUCT* serv_gummei = &s1_resp->ServedGUMMEIs.buffer[0]; - serv_gummei->ext=false; + serv_gummei->ext = false; serv_gummei->iE_Extensions_present = false; - uint32_t plmn=0; + uint32_t plmn = 0; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &plmn); - plmn=htonl(plmn); - serv_gummei->servedPLMNs.len = 1; //Only one PLMN supported - serv_gummei->servedPLMNs.buffer[0].buffer[0]=((uint8_t*)&plmn)[1]; - serv_gummei->servedPLMNs.buffer[0].buffer[1]=((uint8_t*)&plmn)[2]; - serv_gummei->servedPLMNs.buffer[0].buffer[2]=((uint8_t*)&plmn)[3]; - - serv_gummei->servedGroupIDs.len=1; //LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT - uint16_t tmp=htons(s1ap_args.mme_group); - serv_gummei->servedGroupIDs.buffer[0].buffer[0]=((uint8_t*)&tmp)[0]; - serv_gummei->servedGroupIDs.buffer[0].buffer[1]=((uint8_t*)&tmp)[1]; - - serv_gummei->servedMMECs.len=1; //Only one MMEC served - serv_gummei->servedMMECs.buffer[0].buffer[0]=s1ap_args.mme_code; - - //Relative MME Capacity - s1_resp->RelativeMMECapacity.RelativeMMECapacity=255; - - //Relay Unsupported - s1_resp->MMERelaySupportIndicator_present=false; - + plmn = htonl(plmn); + serv_gummei->servedPLMNs.len = 1; // Only one PLMN supported + serv_gummei->servedPLMNs.buffer[0].buffer[0] = ((uint8_t*)&plmn)[1]; + serv_gummei->servedPLMNs.buffer[0].buffer[1] = ((uint8_t*)&plmn)[2]; + serv_gummei->servedPLMNs.buffer[0].buffer[2] = ((uint8_t*)&plmn)[3]; + + serv_gummei->servedGroupIDs.len = 1; // LIBLTE_S1AP_SERVEDGROUPIDS_STRUCT + uint16_t tmp = htons(s1ap_args.mme_group); + serv_gummei->servedGroupIDs.buffer[0].buffer[0] = ((uint8_t*)&tmp)[0]; + serv_gummei->servedGroupIDs.buffer[0].buffer[1] = ((uint8_t*)&tmp)[1]; + + serv_gummei->servedMMECs.len = 1; // Only one MMEC served + serv_gummei->servedMMECs.buffer[0].buffer[0] = s1ap_args.mme_code; + + s1_resp->RelativeMMECapacity.RelativeMMECapacity = 255; + s1_resp->MMERelaySupportIndicator_present = false; s1_resp->CriticalityDiagnostics_present = false; liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)msg); - - return true; + return true; } -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index d2e59354b..d0eb53034 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -24,22 +24,28 @@ * */ -#include -#include -#include // for printing uint64_t -#include "srsepc/hdr/mme/s1ap.h" #include "srsepc/hdr/mme/s1ap_nas_transport.h" -#include "srslte/common/security.h" -#include "srslte/common/liblte_security.h" +#include "srsepc/hdr/mme/s1ap.h" #include "srslte/common/int_helpers.h" +#include "srslte/common/liblte_security.h" +#include "srslte/common/security.h" +#include +#include // for printing uint64_t -namespace srsepc{ +namespace srsepc { s1ap_nas_transport* s1ap_nas_transport::m_instance = NULL; pthread_mutex_t s1ap_nas_transport_instance_mutex = PTHREAD_MUTEX_INITIALIZER; -s1ap_nas_transport::s1ap_nas_transport() {} -s1ap_nas_transport::~s1ap_nas_transport() {} +s1ap_nas_transport::s1ap_nas_transport() +{ + return; +} + +s1ap_nas_transport::~s1ap_nas_transport() +{ + return; +} s1ap_nas_transport* s1ap_nas_transport::get_instance(void) { @@ -61,46 +67,47 @@ void s1ap_nas_transport::cleanup(void) pthread_mutex_unlock(&s1ap_nas_transport_instance_mutex); } -void s1ap_nas_transport::init(hss_interface_nas* hss_) +void s1ap_nas_transport::init() { m_s1ap = s1ap::get_instance(); m_s1ap_log = m_s1ap->m_s1ap_log; m_pool = srslte::byte_buffer_pool::get_instance(); - m_hss = hss_; + m_hss = hss::get_instance(); m_mme_gtpc = mme_gtpc::get_instance(); } bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSAGE_STRUCT* init_ue, - struct sctp_sndrcvinfo* enb_sri, srslte::byte_buffer_t* reply_buffer, - bool* reply_flag) + struct sctp_sndrcvinfo* enb_sri, + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag) { - bool err, mac_valid; - uint8_t pd, msg_type, sec_hdr_type; - srslte::byte_buffer_t *nas_msg = m_pool->allocate(); + bool err, mac_valid; + uint8_t pd, msg_type, sec_hdr_type; + srslte::byte_buffer_t* nas_msg = m_pool->allocate(); memcpy(nas_msg->msg, &init_ue->NAS_PDU.buffer, init_ue->NAS_PDU.n_octets); nas_msg->N_bytes = init_ue->NAS_PDU.n_octets; - uint64_t imsi = 0; - uint32_t m_tmsi = 0; + uint64_t imsi = 0; + uint32_t m_tmsi = 0; uint32_t enb_ue_s1ap_id = init_ue->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &msg_type); m_s1ap_log->console("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type)); - m_s1ap_log->info ("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type)); + m_s1ap_log->info("Initial UE message: %s\n", liblte_nas_msg_type_to_string(msg_type)); nas_init_t nas_init; - nas_init.mcc = m_s1ap->m_s1ap_args.mcc; - nas_init.mnc = m_s1ap->m_s1ap_args.mnc; - nas_init.mme_code = m_s1ap->m_s1ap_args.mme_code; - nas_init.mme_group = m_s1ap->m_s1ap_args.mme_group; - nas_init.tac = m_s1ap->m_s1ap_args.tac; - nas_init.apn = m_s1ap->m_s1ap_args.mme_apn; - nas_init.dns = m_s1ap->m_s1ap_args.dns_addr; + nas_init.mcc = m_s1ap->m_s1ap_args.mcc; + nas_init.mnc = m_s1ap->m_s1ap_args.mnc; + nas_init.mme_code = m_s1ap->m_s1ap_args.mme_code; + nas_init.mme_group = m_s1ap->m_s1ap_args.mme_group; + nas_init.tac = m_s1ap->m_s1ap_args.tac; + nas_init.apn = m_s1ap->m_s1ap_args.mme_apn; + nas_init.dns = m_s1ap->m_s1ap_args.dns_addr; nas_init.integ_algo = m_s1ap->m_s1ap_args.integrity_algo; nas_init.cipher_algo = m_s1ap->m_s1ap_args.encryption_algo; - if(init_ue->S_TMSI_present){ + if (init_ue->S_TMSI_present) { srslte::uint8_to_uint32(init_ue->S_TMSI.m_TMSI.buffer, &m_tmsi); } @@ -140,7 +147,8 @@ bool s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUE bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRANSPORT_STRUCT* ul_xport, struct sctp_sndrcvinfo* enb_sri, - srslte::byte_buffer_t* reply_buffer, bool* reply_flag) + srslte::byte_buffer_t* reply_buffer, + bool* reply_flag) { uint8_t pd, msg_type, sec_hdr_type; uint32_t enb_ue_s1ap_id = ul_xport->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID; @@ -168,36 +176,34 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN // Parse the message security header liblte_mme_parse_msg_sec_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &sec_hdr_type); - + // Invalid Security Header Type simply return function if (!(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS || - sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || - sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || 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)) - { + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT)) { m_s1ap_log->error("Unhandled security header type in Uplink NAS Transport: %d\n", sec_hdr_type); m_pool->deallocate(nas_msg); return false; } // Todo: Check on count mismatch of uplink count and do resync nas counter... - + // Check MAC if message is integrity protected if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || 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) - { + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { mac_valid = nas_ctx->integrity_check(nas_msg); - if (mac_valid == false){ - m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection (Maybe: Identity Response or Authenticatio Response)\n" ); + if (mac_valid == false) { + m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection (Maybe: " + "Identity Response or Authenticatio Response)\n"); } } // Decrypt message if indicated if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED || - sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) - { + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { m_s1ap_log->debug_hex(nas_msg->msg, nas_msg->N_bytes, "Encrypted"); nas_ctx->cipher_decrypt(nas_msg); msg_encrypted = true; @@ -205,17 +211,19 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN } // Now parse message header and handle message - liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &pd, &msg_type); + liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)nas_msg, &pd, &msg_type); - - //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) { - //Make sure EMM context is set-up, to do integrity check/de-chiphering + // Make sure EMM context is set-up, to do integrity check/de-chiphering if (emm_ctx->imsi == 0) { - //No EMM context found. Perhaps a temporary context is being created? - //This can happen with integrity protected identity reponse messages - if ( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) ) { - m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n",mme_ue_s1ap_id); + // No EMM context found. Perhaps a temporary context is being created? + // This can happen with integrity protected identity reponse messages + if (!(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && + sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) { + m_s1ap_log->warning( + "Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %d\n", + mme_ue_s1ap_id); m_pool->deallocate(nas_msg); return false; } @@ -237,85 +245,90 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN liblte_nas_sec_hdr_type_to_string(sec_hdr_type), mac_valid == true ? "yes" : "no", msg_encrypted == true ? "yes" : "no"); - switch (msg_type) - { - case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: - m_s1ap_log->info("UL NAS: Received Identity Response\n"); - m_s1ap_log->console("UL NAS: Received Identity Response\n"); - nas_ctx->handle_identity_response(nas_msg); - break; - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received Authentication Response\n"); - m_s1ap_log->console("UL NAS: Received Authentication Response\n"); - nas_ctx->handle_authentication_response(nas_msg); - // In case of a successful authentication response, security mode command follows. - // Reset counter for incoming security mode complete - sec_ctx->ul_nas_count = 0; - sec_ctx->dl_nas_count = 0; - increase_ul_nas_cnt = false; - break; - // Authentication failure with the option sync failure can be sent not integrity protected - case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: - m_s1ap_log->info("UL NAS: Authentication Failure\n"); - m_s1ap_log->console("UL NAS: Authentication Failure\n"); - nas_ctx->handle_authentication_failure(nas_msg); - break; - // Detach request can be sent not integrity protected when "power off" option is used - case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: - m_s1ap_log->info("UL NAS: Detach Request\n"); - m_s1ap_log->console("UL NAS: Detach Request\n"); - // FIXME: check integrity protection in detach request - nas_ctx->handle_detach_request(nas_msg); - break; - case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: - m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); - m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); - if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT && mac_valid == true){ - nas_ctx->handle_security_mode_complete(nas_msg); - } else { - // Security Mode Complete was not integrity protected - m_s1ap_log->console("Security Mode Complete %s. Discard message.\n", (mac_valid ? "not integrity protected": "invalid integrity")); - m_s1ap_log->warning("Security Mode Complete %s. Discard message.\n", (mac_valid ? "not integrity protected": "invalid integrity")); - increase_ul_nas_cnt = false; - } - break; - case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: - m_s1ap_log->info("UL NAS: Received Attach Complete\n"); - m_s1ap_log->console("UL NAS: Received Attach Complete\n"); - if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true){ - nas_ctx->handle_attach_complete(nas_msg); - } else { - // Attach Complete was not integrity protected - m_s1ap_log->console("Attach Complete not integrity protected. Discard message.\n"); - m_s1ap_log->warning("Attach Complete not integrity protected. Discard message.\n"); - increase_ul_nas_cnt = false; - } - break; - case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: - m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); - m_s1ap_log->console("UL NAS: Received ESM Information Response\n"); - if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true){ - nas_ctx->handle_esm_information_response(nas_msg); - } else { - // Attach Complete was not integrity protected - m_s1ap_log->console("ESM Information Response %s. Discard message.\n", (mac_valid ? "not integrity protected": "invalid integrity")); - m_s1ap_log->warning("ESM Information Response %s. Discard message.\n", (mac_valid ? "not integrity protected": "invalid integrity")); - increase_ul_nas_cnt = false; - } - break; - case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: - m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); - m_s1ap_log->console("UL NAS: Tracking Area Update Request\n"); - nas_ctx->handle_tracking_area_update_request(nas_msg); - break; - default: - m_s1ap_log->warning("Unhandled NAS integrity protected message %s\n", liblte_nas_msg_type_to_string(msg_type)); - m_s1ap_log->console("Unhandled NAS integrity protected message %s\n", liblte_nas_msg_type_to_string(msg_type)); - m_pool->deallocate(nas_msg); - return false; + switch (msg_type) { + case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: + m_s1ap_log->info("UL NAS: Received Identity Response\n"); + m_s1ap_log->console("UL NAS: Received Identity Response\n"); + nas_ctx->handle_identity_response(nas_msg); + break; + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received Authentication Response\n"); + m_s1ap_log->console("UL NAS: Received Authentication Response\n"); + nas_ctx->handle_authentication_response(nas_msg); + // In case of a successful authentication response, security mode command follows. + // Reset counter for incoming security mode complete + sec_ctx->ul_nas_count = 0; + sec_ctx->dl_nas_count = 0; + increase_ul_nas_cnt = false; + break; + // Authentication failure with the option sync failure can be sent not integrity protected + case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: + m_s1ap_log->info("UL NAS: Authentication Failure\n"); + m_s1ap_log->console("UL NAS: Authentication Failure\n"); + nas_ctx->handle_authentication_failure(nas_msg); + break; + // Detach request can be sent not integrity protected when "power off" option is used + case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST: + m_s1ap_log->info("UL NAS: Detach Request\n"); + m_s1ap_log->console("UL NAS: Detach Request\n"); + // FIXME: check integrity protection in detach request + nas_ctx->handle_detach_request(nas_msg); + break; + case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: + m_s1ap_log->info("UL NAS: Received Security Mode Complete\n"); + m_s1ap_log->console("UL NAS: Received Security Mode Complete\n"); + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT && + mac_valid == true) { + nas_ctx->handle_security_mode_complete(nas_msg); + } else { + // Security Mode Complete was not integrity protected + m_s1ap_log->console("Security Mode Complete %s. Discard message.\n", + (mac_valid ? "not integrity protected" : "invalid integrity")); + m_s1ap_log->warning("Security Mode Complete %s. Discard message.\n", + (mac_valid ? "not integrity protected" : "invalid integrity")); + increase_ul_nas_cnt = false; + } + break; + case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: + m_s1ap_log->info("UL NAS: Received Attach Complete\n"); + m_s1ap_log->console("UL NAS: Received Attach Complete\n"); + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true) { + nas_ctx->handle_attach_complete(nas_msg); + } else { + // Attach Complete was not integrity protected + m_s1ap_log->console("Attach Complete not integrity protected. Discard message.\n"); + m_s1ap_log->warning("Attach Complete not integrity protected. Discard message.\n"); + increase_ul_nas_cnt = false; + } + break; + case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: + m_s1ap_log->info("UL NAS: Received ESM Information Response\n"); + m_s1ap_log->console("UL NAS: Received ESM Information Response\n"); + if (sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED && mac_valid == true) { + nas_ctx->handle_esm_information_response(nas_msg); + } else { + // Attach Complete was not integrity protected + m_s1ap_log->console("ESM Information Response %s. Discard message.\n", + (mac_valid ? "not integrity protected" : "invalid integrity")); + m_s1ap_log->warning("ESM Information Response %s. Discard message.\n", + (mac_valid ? "not integrity protected" : "invalid integrity")); + increase_ul_nas_cnt = false; + } + break; + case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: + m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); + m_s1ap_log->console("UL NAS: Tracking Area Update Request\n"); + nas_ctx->handle_tracking_area_update_request(nas_msg); + break; + default: + m_s1ap_log->warning("Unhandled NAS integrity protected message %s\n", liblte_nas_msg_type_to_string(msg_type)); + m_s1ap_log->console("Unhandled NAS integrity protected message %s\n", liblte_nas_msg_type_to_string(msg_type)); + m_pool->deallocate(nas_msg); + return false; } - //Increment UL NAS count. if counter not resetted in function, e.g., DL Security mode command after Authentication response + // Increment UL NAS count. if counter not resetted in function, e.g., DL Security mode command after Authentication + // response if (increase_ul_nas_cnt == true) { sec_ctx->ul_nas_count++; } @@ -323,37 +336,39 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN return true; } -bool s1ap_nas_transport::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, - srslte::byte_buffer_t* nas_msg, struct sctp_sndrcvinfo enb_sri) +bool s1ap_nas_transport::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + srslte::byte_buffer_t* nas_msg, + struct sctp_sndrcvinfo enb_sri) { - //Allocate Reply buffer - srslte::byte_buffer_t *reply_msg = m_pool->allocate(); + // Allocate Reply buffer + srslte::byte_buffer_t* reply_msg = m_pool->allocate(); - //Setup initiating message + // Setup initiating message LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - tx_pdu.ext = false; - tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; + tx_pdu.ext = false; + tx_pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; - LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &tx_pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; + LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT* init = &tx_pdu.choice.initiatingMessage; + init->procedureCode = LIBLTE_S1AP_PROC_ID_DOWNLINKNASTRANSPORT; + init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_DOWNLINKNASTRANSPORT; - //Setup Dw NAS structure - LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; - dw_nas->ext=false; - dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id; - dw_nas->HandoverRestrictionList_present=false; - dw_nas->SubscriberProfileIDforRFP_present=false; + // Setup Dw NAS structure + LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT* dw_nas = &init->choice.DownlinkNASTransport; + dw_nas->ext = false; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = enb_ue_s1ap_id; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = mme_ue_s1ap_id; + dw_nas->HandoverRestrictionList_present = false; + dw_nas->SubscriberProfileIDforRFP_present = false; - //Copy NAS PDU to Downlink NAS Trasport message buffer + // Copy NAS PDU to Downlink NAS Trasport message buffer memcpy(dw_nas->NAS_PDU.buffer, nas_msg->msg, nas_msg->N_bytes); dw_nas->NAS_PDU.n_octets = nas_msg->N_bytes; - //Pack Downlink NAS Transport Message - LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT *) reply_msg); + // Pack Downlink NAS Transport Message + LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&tx_pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_msg); if (err != LIBLTE_SUCCESS) { m_s1ap_log->error("Error packing Downlink NAS Transport.\n"); m_s1ap_log->console("Error packing Downlink NAS Transport.\n"); @@ -365,5 +380,4 @@ bool s1ap_nas_transport::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, ui return true; } - -} //namespace srsepc +} // namespace srsepc diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 85eb38c54..3e5fd15a1 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -24,33 +24,27 @@ * */ -#include +#include "srsepc/hdr/spgw/spgw.h" +#include "srsepc/hdr/mme/mme_gtpc.h" +#include "srslte/upper/gtpu.h" #include #include -#include -#include -#include +#include // for printing uint64_t #include #include #include -#include // for printing uint64_t -#include "srsepc/hdr/spgw/spgw.h" -#include "srsepc/hdr/mme/mme_gtpc.h" -#include "srslte/upper/gtpu.h" +#include +#include +#include -namespace srsepc{ +namespace srsepc { -spgw* spgw::m_instance = NULL; +spgw* spgw::m_instance = NULL; pthread_mutex_t spgw_instance_mutex = PTHREAD_MUTEX_INITIALIZER; const uint16_t SPGW_BUFFER_SIZE = 2500; -spgw::spgw(): - m_running(false), - m_sgi_up(false), - m_s1u_up(false), - m_next_ctrl_teid(1), - m_next_user_teid(1) +spgw::spgw() : m_running(false), m_sgi_up(false), m_s1u_up(false), m_next_ctrl_teid(1), m_next_user_teid(1) { return; } @@ -60,92 +54,83 @@ spgw::~spgw() return; } -spgw* -spgw::get_instance(void) +spgw* spgw::get_instance() { pthread_mutex_lock(&spgw_instance_mutex); - if(NULL == m_instance) { + if (NULL == m_instance) { m_instance = new spgw(); } pthread_mutex_unlock(&spgw_instance_mutex); - return(m_instance); + return (m_instance); } -void -spgw::cleanup(void) +void spgw::cleanup() { pthread_mutex_lock(&spgw_instance_mutex); - if(NULL != m_instance) { + if (NULL != m_instance) { delete m_instance; m_instance = NULL; } pthread_mutex_unlock(&spgw_instance_mutex); } -int -spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) +int spgw::init(spgw_args_t* args, srslte::log_filter* spgw_log) { srslte::error_t err; m_pool = srslte::byte_buffer_pool::get_instance(); - //Init log + // Init log m_spgw_log = spgw_log; m_mme_gtpc = mme_gtpc::get_instance(); - //Init SGi interface + // Init SGi interface err = init_sgi_if(args); - if (err != srslte::ERROR_NONE) - { + if (err != srslte::ERROR_NONE) { m_spgw_log->console("Could not initialize the SGi interface.\n"); return -1; } - //Init S1-U + // Init S1-U err = init_s1u(args); - if (err != srslte::ERROR_NONE) - { + if (err != srslte::ERROR_NONE) { m_spgw_log->console("Could not initialize the S1-U interface.\n"); return -1; } - //Initialize UE ip pool + // Initialize UE ip pool err = init_ue_ip(args); - if (err != srslte::ERROR_NONE) - { + if (err != srslte::ERROR_NONE) { m_spgw_log->console("Could not initialize the S1-U interface.\n"); return -1; } - //Init mutex - pthread_mutex_init(&m_mutex,NULL); + // Init mutex + pthread_mutex_init(&m_mutex, NULL); m_spgw_log->info("SP-GW Initialized.\n"); m_spgw_log->console("SP-GW Initialized.\n"); return 0; } -void -spgw::stop() +void spgw::stop() { - if(m_running) - { + if (m_running) { m_running = false; thread_cancel(); wait_thread_finish(); - //Clean up SGi interface - if(m_sgi_up) - { + // Clean up SGi interface + if (m_sgi_up) { close(m_sgi_if); close(m_sgi_sock); } - //Clean up S1-U socket - if(m_s1u_up) - { + // Clean up S1-U socket + if (m_s1u_up) { close(m_s1u); } } - std::map::iterator it = m_teid_to_tunnel_ctx.begin(); //Map control TEID to tunnel ctx. Usefull to get reply ctrl TEID, UE IP, etc. - while(it!=m_teid_to_tunnel_ctx.end()) - { + + //Delete GTP-C tunnel + std::map::iterator it = m_teid_to_tunnel_ctx.begin(); + while (it != m_teid_to_tunnel_ctx.end()) { m_spgw_log->info("Deleting SP-GW GTP-C Tunnel. IMSI: %lu\n", it->second->imsi); m_spgw_log->console("Deleting SP-GW GTP-C Tunnel. IMSI: %lu\n", it->second->imsi); delete it->second; @@ -154,33 +139,31 @@ spgw::stop() return; } -srslte::error_t -spgw::init_sgi_if(spgw_args_t *args) +srslte::error_t spgw::init_sgi_if(spgw_args_t* args) { - struct ifreq ifr; - if (m_sgi_up) { - return(srslte::ERROR_ALREADY_STARTED); + return (srslte::ERROR_ALREADY_STARTED); } - // Construct the TUN device m_sgi_if = open("/dev/net/tun", O_RDWR); m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); if (m_sgi_if < 0) { m_spgw_log->error("Failed to open TUN device: %s\n", strerror(errno)); - return(srslte::ERROR_CANT_START); + return (srslte::ERROR_CANT_START); } + struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - strncpy(ifr.ifr_ifrn.ifrn_name, args->sgi_if_name.c_str(), std::min(args->sgi_if_name.length(), (size_t)(IFNAMSIZ-1))); - ifr.ifr_ifrn.ifrn_name[IFNAMSIZ-1]='\0'; + strncpy(ifr.ifr_ifrn.ifrn_name, args->sgi_if_name.c_str(), + std::min(args->sgi_if_name.length(), (size_t)(IFNAMSIZ - 1))); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = '\0'; if (ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) { m_spgw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); close(m_sgi_if); - return(srslte::ERROR_CANT_START); + return (srslte::ERROR_CANT_START); } // Bring up the interface @@ -189,31 +172,32 @@ spgw::init_sgi_if(spgw_args_t *args) if (ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) { m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); close(m_sgi_if); - return(srslte::ERROR_CANT_START); + return (srslte::ERROR_CANT_START); } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) { m_spgw_log->error("Failed to set socket flags: %s\n", strerror(errno)); close(m_sgi_if); - return(srslte::ERROR_CANT_START); + return (srslte::ERROR_CANT_START); } - //Set IP of the interface - struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); - addr->sin_port = 0; + // Set IP of the interface + struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); + addr->sin_port = 0; if (ioctl(m_sgi_sock, SIOCSIFADDR, &ifr) < 0) { - m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), strerror(errno)); + m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), + strerror(errno)); close(m_sgi_if); close(m_sgi_sock); return srslte::ERROR_CANT_START; } - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); if (ioctl(m_sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { m_spgw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); close(m_sgi_if); @@ -221,75 +205,69 @@ spgw::init_sgi_if(spgw_args_t *args) return srslte::ERROR_CANT_START; } - //Set initial time of setup - gettimeofday(&m_t_last_dl, NULL); - m_sgi_up = true; - return(srslte::ERROR_NONE); + return (srslte::ERROR_NONE); } -srslte::error_t -spgw::init_s1u(spgw_args_t *args) +srslte::error_t spgw::init_s1u(spgw_args_t* args) { - //Open S1-U socket - m_s1u = socket(AF_INET,SOCK_DGRAM,0); + // Open S1-U socket + m_s1u = socket(AF_INET, SOCK_DGRAM, 0); if (m_s1u == -1) { m_spgw_log->error("Failed to open socket: %s\n", strerror(errno)); return srslte::ERROR_CANT_START; } m_s1u_up = true; - //Bind the socket - m_s1u_addr.sin_family = AF_INET; - m_s1u_addr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); - m_s1u_addr.sin_port=htons(GTPU_RX_PORT); + // Bind the socket + m_s1u_addr.sin_family = AF_INET; + m_s1u_addr.sin_addr.s_addr = inet_addr(args->gtpu_bind_addr.c_str()); + m_s1u_addr.sin_port = htons(GTPU_RX_PORT); - if (bind(m_s1u,(struct sockaddr *)&m_s1u_addr,sizeof(struct sockaddr_in))) { + if (bind(m_s1u, (struct sockaddr*)&m_s1u_addr, sizeof(struct sockaddr_in))) { m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); return srslte::ERROR_CANT_START; } m_spgw_log->info("S1-U socket = %d\n", m_s1u); - m_spgw_log->info("S1-U IP = %s, Port = %d \n", inet_ntoa(m_s1u_addr.sin_addr),ntohs(m_s1u_addr.sin_port)); + m_spgw_log->info("S1-U IP = %s, Port = %d \n", inet_ntoa(m_s1u_addr.sin_addr), ntohs(m_s1u_addr.sin_port)); return srslte::ERROR_NONE; } -srslte::error_t -spgw::init_ue_ip(spgw_args_t *args) +srslte::error_t spgw::init_ue_ip(spgw_args_t* args) { m_h_next_ue_ip = ntohl(inet_addr(args->sgi_if_addr.c_str())); return srslte::ERROR_NONE; } -void -spgw::run_thread() +void spgw::run_thread() { - //Mark the thread as running - m_running=true; - srslte::byte_buffer_t *msg; + // Mark the thread as running + m_running = true; + srslte::byte_buffer_t* msg; msg = m_pool->allocate(); struct sockaddr src_addr; - socklen_t addrlen; - struct iphdr *ip_pkt; - int sgi = m_sgi_if; + socklen_t addrlen; + struct iphdr* ip_pkt; + int sgi = m_sgi_if; fd_set set; - //struct timeval to; - int max_fd = std::max(m_s1u,sgi); + // struct timeval to; + int max_fd = std::max(m_s1u, sgi); while (m_running) { msg->reset(); FD_ZERO(&set); FD_SET(m_s1u, &set); FD_SET(sgi, &set); - //m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); - int n = select(max_fd+1, &set, NULL, NULL, NULL); + // m_spgw_log->info("Waiting for S1-U or SGi packets.\n"); + int n = select(max_fd + 1, &set, NULL, NULL, NULL); if (n == -1) { m_spgw_log->error("Error from select\n"); } else if (n) { if (FD_ISSET(m_s1u, &set)) { - msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen ); + msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen); handle_s1u_pdu(msg); } if (FD_ISSET(m_sgi_if, &set)) { @@ -304,17 +282,16 @@ spgw::run_thread() return; } -void -spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) +void spgw::handle_sgi_pdu(srslte::byte_buffer_t* msg) { - uint8_t version=0; - uint32_t dest_ip; - struct in_addr dest_addr; - std::map::iterator gtp_fteid_it; - bool ip_found = false; - srslte::gtpc_f_teid_ie enb_fteid; - - struct iphdr *iph = (struct iphdr *) msg->msg; + uint8_t version = 0; + uint32_t dest_ip; + struct in_addr dest_addr; + std::map::iterator gtp_fteid_it; + bool ip_found = false; + srslte::gtpc_f_teid_ie enb_fteid; + + struct iphdr* iph = (struct iphdr*)msg->msg; if (iph->version != 4) { m_spgw_log->warning("IPv6 not supported yet.\n"); return; @@ -327,7 +304,7 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) pthread_mutex_lock(&m_mutex); gtp_fteid_it = m_ip_to_teid.find(iph->daddr); if (gtp_fteid_it != m_ip_to_teid.end()) { - ip_found = true; + ip_found = true; enb_fteid = gtp_fteid_it->second; } pthread_mutex_unlock(&m_mutex); @@ -337,145 +314,61 @@ spgw::handle_sgi_pdu(srslte::byte_buffer_t *msg) } struct sockaddr_in enb_addr; - enb_addr.sin_family = AF_INET; - enb_addr.sin_port = htons(GTPU_RX_PORT); + enb_addr.sin_family = AF_INET; + enb_addr.sin_port = htons(GTPU_RX_PORT); enb_addr.sin_addr.s_addr = enb_fteid.ipv4; - //Setup GTP-U header + // Setup GTP-U header srslte::gtpu_header_t header; header.flags = GTPU_FLAGS_VERSION_V1 | GTPU_FLAGS_GTP_PROTOCOL; header.message_type = GTPU_MSG_DATA_PDU; header.length = msg->N_bytes; header.teid = enb_fteid.teid; - //Write header into packet + // Write header into packet if (!srslte::gtpu_write_header(&header, msg, m_spgw_log)) { m_spgw_log->console("Error writing GTP-U header on PDU\n"); } - - //Send packet to destination - int n = sendto(m_s1u,msg->msg,msg->N_bytes,0,(struct sockaddr*) &enb_addr,sizeof(enb_addr)); - if (n<0) { + // Send packet to destination + int n = sendto(m_s1u, msg->msg, msg->N_bytes, 0, (struct sockaddr*)&enb_addr, sizeof(enb_addr)); + if (n < 0) { m_spgw_log->error("Error sending packet to eNB\n"); return; - } else if((unsigned int) n!=msg->N_bytes) { - m_spgw_log->error("Mis-match between packet bytes and sent bytes: Sent: %d, Packet: %d \n",n,msg->N_bytes); + } else if ((unsigned int)n != msg->N_bytes) { + m_spgw_log->error("Mis-match between packet bytes and sent bytes: Sent: %d, Packet: %d \n", n, msg->N_bytes); } return; } - -void -spgw::handle_s1u_pdu(srslte::byte_buffer_t *msg) +void spgw::handle_s1u_pdu(srslte::byte_buffer_t* msg) { - //m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); + // m_spgw_log->console("Received PDU from S1-U. Bytes=%d\n",msg->N_bytes); srslte::gtpu_header_t header; srslte::gtpu_read_header(msg, &header, m_spgw_log); - //m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); + // m_spgw_log->console("TEID 0x%x. Bytes=%d\n", header.teid, msg->N_bytes); int n = write(m_sgi_if, msg->msg, msg->N_bytes); - if (n<0) { + if (n < 0) { m_spgw_log->error("Could not write to TUN interface.\n"); } else { - //m_spgw_log->console("Forwarded packet to TUN interface. Bytes= %d/%d\n", n, msg->N_bytes); + // m_spgw_log->console("Forwarded packet to TUN interface. Bytes= %d/%d\n", n, msg->N_bytes); } return; } + /* - * Helper Functions + * GTP-C Handler Functions */ -uint64_t -spgw::get_new_ctrl_teid() -{ - return m_next_ctrl_teid++; -} - -uint64_t -spgw::get_new_user_teid() -{ - return m_next_user_teid++; -} - -in_addr_t -spgw::get_new_ue_ipv4() -{ - m_h_next_ue_ip++; - return ntohl(m_h_next_ue_ip);//FIXME Tmp hack -} - -spgw_tunnel_ctx_t* -spgw::create_gtp_ctx(struct srslte::gtpc_create_session_request *cs_req) -{ - //Setup uplink control TEID - uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); - //Setup uplink user TEID - uint64_t spgw_uplink_user_teid = get_new_user_teid(); - //Allocate UE IP - in_addr_t ue_ip = get_new_ue_ipv4(); - //in_addr_t ue_ip = inet_addr("172.16.0.2"); - uint8_t default_bearer_id = 5; - - m_spgw_log->console("SPGW: Allocated Ctrl TEID %" PRIu64 "\n", spgw_uplink_ctrl_teid); - m_spgw_log->console("SPGW: Allocated User TEID %" PRIu64 "\n", spgw_uplink_user_teid); - struct in_addr ue_ip_; - ue_ip_.s_addr=ue_ip; - m_spgw_log->console("SPGW: Allocate UE IP %s\n", inet_ntoa(ue_ip_)); - - - //Save the UE IP to User TEID map - spgw_tunnel_ctx_t *tunnel_ctx = new spgw_tunnel_ctx_t; - bzero(tunnel_ctx,sizeof(spgw_tunnel_ctx_t)); - - tunnel_ctx->imsi = cs_req->imsi; - tunnel_ctx->ebi = default_bearer_id; - tunnel_ctx->up_user_fteid.teid = spgw_uplink_user_teid; - tunnel_ctx->up_user_fteid.ipv4 = m_s1u_addr.sin_addr.s_addr; - tunnel_ctx->dw_ctrl_fteid.teid = cs_req->sender_f_teid.teid; - tunnel_ctx->dw_ctrl_fteid.ipv4 = cs_req->sender_f_teid.ipv4; - - tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; - tunnel_ctx->ue_ipv4 = ue_ip; - m_teid_to_tunnel_ctx.insert(std::pair(spgw_uplink_ctrl_teid,tunnel_ctx)); - m_imsi_to_ctr_teid.insert(std::pair(cs_req->imsi,spgw_uplink_ctrl_teid)); - return tunnel_ctx; -} - -bool -spgw::delete_gtp_ctx(uint32_t ctrl_teid) -{ - spgw_tunnel_ctx_t *tunnel_ctx; - if (!m_teid_to_tunnel_ctx.count(ctrl_teid)) { - m_spgw_log->error("Could not find GTP context to delete.\n"); - return false; - } - tunnel_ctx = m_teid_to_tunnel_ctx[ctrl_teid]; - - //Remove GTP-U connections, if any. - if (m_ip_to_teid.count(tunnel_ctx->ue_ipv4)) { - pthread_mutex_lock(&m_mutex); - m_ip_to_teid.erase(tunnel_ctx->ue_ipv4); - pthread_mutex_unlock(&m_mutex); - } - - //Remove Ctrl TEID from IMSI to control TEID map - m_imsi_to_ctr_teid.erase(tunnel_ctx->imsi); - - //Remove GTP context from control TEID mapping - m_teid_to_tunnel_ctx.erase(ctrl_teid); - delete tunnel_ctx; - return true; -} - -void -spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_pdu *cs_resp_pdu) +void spgw::handle_create_session_request(struct srslte::gtpc_create_session_request* cs_req, + struct srslte::gtpc_pdu* cs_resp_pdu) { m_spgw_log->info("Received Create Session Request\n"); - spgw_tunnel_ctx_t *tunnel_ctx; - int default_bearer_id = 5; - //Check if IMSI has active GTP-C and/or GTP-U + spgw_tunnel_ctx_t* tunnel_ctx; + int default_bearer_id = 5; + // Check if IMSI has active GTP-C and/or GTP-U bool gtpc_present = m_imsi_to_ctr_teid.count(cs_req->imsi); if (gtpc_present) { m_spgw_log->console("SPGW: GTP-C context for IMSI %015" PRIu64 " already exists.\n", cs_req->imsi); @@ -486,64 +379,64 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request * m_spgw_log->info("Creating new GTP-C context\n"); tunnel_ctx = create_gtp_ctx(cs_req); - //Create session response message - srslte::gtpc_header *header = &cs_resp_pdu->header; - srslte::gtpc_create_session_response *cs_resp = &cs_resp_pdu->choice.create_session_response; + // Create session response message + srslte::gtpc_header* header = &cs_resp_pdu->header; + srslte::gtpc_create_session_response* cs_resp = &cs_resp_pdu->choice.create_session_response; - //Setup GTP-C header - header->piggyback = false; + // Setup GTP-C header + header->piggyback = false; header->teid_present = true; - header->teid = tunnel_ctx->dw_ctrl_fteid.teid; //Send create session requesponse to the UE's MME Ctrl TEID - header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; + header->teid = tunnel_ctx->dw_ctrl_fteid.teid; // Send create session requesponse to the UE's MME Ctrl TEID + header->type = srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE; - //Initialize to zero - bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response)); - //Setup Cause + // Initialize to zero + bzero(cs_resp, sizeof(struct srslte::gtpc_create_session_response)); + // Setup Cause cs_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; - //Setup sender F-TEID (ctrl) + // Setup sender F-TEID (ctrl) cs_resp->sender_f_teid.ipv4_present = true; - cs_resp->sender_f_teid = tunnel_ctx->up_ctrl_fteid; + cs_resp->sender_f_teid = tunnel_ctx->up_ctrl_fteid; - //Bearer context created - cs_resp->eps_bearer_context_created.ebi = default_bearer_id; - cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; - cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true; - cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid = tunnel_ctx->up_user_fteid; + // Bearer context created + cs_resp->eps_bearer_context_created.ebi = default_bearer_id; + cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; + cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present = true; + cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid = tunnel_ctx->up_user_fteid; - //Fill in the PAA - cs_resp->paa_present = true; - cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; + // Fill in the PAA + cs_resp->paa_present = true; + cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; cs_resp->paa.ipv4_present = true; - cs_resp->paa.ipv4 = tunnel_ctx->ue_ipv4; + cs_resp->paa.ipv4 = tunnel_ctx->ue_ipv4; m_spgw_log->info("Sending Create Session Response\n"); m_mme_gtpc->handle_create_session_response(cs_resp_pdu); return; } -void -spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct srslte::gtpc_pdu *mb_resp_pdu) +void spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu* mb_req_pdu, struct srslte::gtpc_pdu* mb_resp_pdu) { m_spgw_log->info("Received Modified Bearer Request\n"); - //Get control tunnel info from mb_req PDU - uint32_t ctrl_teid = mb_req_pdu->header.teid; - std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); + // Get control tunnel info from mb_req PDU + uint32_t ctrl_teid = mb_req_pdu->header.teid; + std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); if (tunnel_it == m_teid_to_tunnel_ctx.end()) { - m_spgw_log->warning("Could not find TEID %d to modify\n",ctrl_teid); + m_spgw_log->warning("Could not find TEID %d to modify\n", ctrl_teid); return; } - spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; + spgw_tunnel_ctx_t* tunnel_ctx = tunnel_it->second; - //Store user DW link TEID - srslte::gtpc_modify_bearer_request *mb_req = &mb_req_pdu->choice.modify_bearer_request; - tunnel_ctx->dw_user_fteid.teid = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid; - tunnel_ctx->dw_user_fteid.ipv4 = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4; - //Set up actual tunnel + // Store user DW link TEID + srslte::gtpc_modify_bearer_request* mb_req = &mb_req_pdu->choice.modify_bearer_request; + tunnel_ctx->dw_user_fteid.teid = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.teid; + tunnel_ctx->dw_user_fteid.ipv4 = mb_req->eps_bearer_context_to_modify.s1_u_enb_f_teid.ipv4; + // Set up actual tunnel m_spgw_log->info("Setting Up GTP-U tunnel. Tunnel info: \n"); struct in_addr addr; addr.s_addr = tunnel_ctx->ue_ipv4; - m_spgw_log->info("IMSI: %lu, UE IP, %s \n",tunnel_ctx->imsi, inet_ntoa(addr)); - m_spgw_log->info("S-GW Rx Ctrl TEID 0x%x, MME Rx Ctrl TEID 0x%x\n", tunnel_ctx->up_ctrl_fteid.teid, tunnel_ctx->dw_ctrl_fteid.teid); + m_spgw_log->info("IMSI: %lu, UE IP, %s \n", tunnel_ctx->imsi, inet_ntoa(addr)); + m_spgw_log->info("S-GW Rx Ctrl TEID 0x%x, MME Rx Ctrl TEID 0x%x\n", tunnel_ctx->up_ctrl_fteid.teid, + tunnel_ctx->dw_ctrl_fteid.teid); m_spgw_log->info("S-GW Rx Ctrl IP (NA), MME Rx Ctrl IP (NA)\n"); struct in_addr addr2; @@ -554,79 +447,158 @@ spgw::handle_modify_bearer_request(struct srslte::gtpc_pdu *mb_req_pdu, struct s addr3.s_addr = tunnel_ctx->dw_user_fteid.ipv4; m_spgw_log->info("eNB Rx User TEID 0x%x, eNB Rx User IP %s\n", tunnel_ctx->dw_user_fteid.teid, inet_ntoa(addr3)); - //Setup IP to F-TEID map - //bool ret = false; + // Setup IP to F-TEID map + // bool ret = false; pthread_mutex_lock(&m_mutex); - m_ip_to_teid[tunnel_ctx->ue_ipv4]=tunnel_ctx->dw_user_fteid; - //ret = m_ip_to_teid.insert(std::pair(tunnel_ctx->ue_ipv4, tunnel_ctx->dw_user_fteid)); + m_ip_to_teid[tunnel_ctx->ue_ipv4] = tunnel_ctx->dw_user_fteid; + // ret = m_ip_to_teid.insert(std::pair(tunnel_ctx->ue_ipv4, + // tunnel_ctx->dw_user_fteid)); pthread_mutex_unlock(&m_mutex); - //Setting up Modify bearer response PDU - //Header - srslte::gtpc_header *header = &mb_resp_pdu->header; - header->piggyback = false; - header->teid_present = true; - header->teid = tunnel_ctx->dw_ctrl_fteid.teid; // - header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; - - //PDU - srslte::gtpc_modify_bearer_response *mb_resp = &mb_resp_pdu->choice.modify_bearer_response; - mb_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; - mb_resp->eps_bearer_context_modified.ebi = tunnel_ctx->ebi; + // Setting up Modify bearer response PDU + // Header + srslte::gtpc_header* header = &mb_resp_pdu->header; + header->piggyback = false; + header->teid_present = true; + header->teid = tunnel_ctx->dw_ctrl_fteid.teid; // + header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; + + // PDU + srslte::gtpc_modify_bearer_response* mb_resp = &mb_resp_pdu->choice.modify_bearer_response; + mb_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; + mb_resp->eps_bearer_context_modified.ebi = tunnel_ctx->ebi; mb_resp->eps_bearer_context_modified.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; return; } -void -spgw::handle_delete_session_request(struct srslte::gtpc_pdu *del_req_pdu, struct srslte::gtpc_pdu *del_resp_pdu) +void spgw::handle_delete_session_request(struct srslte::gtpc_pdu* del_req_pdu, struct srslte::gtpc_pdu* del_resp_pdu) { - //Find tunel ctxt - uint32_t ctrl_teid = del_req_pdu->header.teid; - std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); + // Find tunel ctxt + uint32_t ctrl_teid = del_req_pdu->header.teid; + std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); if (tunnel_it == m_teid_to_tunnel_ctx.end()) { - m_spgw_log->warning("Could not find TEID %d to delete\n",ctrl_teid); + m_spgw_log->warning("Could not find TEID %d to delete\n", ctrl_teid); return; } - spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; - in_addr_t ue_ipv4 = tunnel_ctx->ue_ipv4; + spgw_tunnel_ctx_t* tunnel_ctx = tunnel_it->second; + in_addr_t ue_ipv4 = tunnel_ctx->ue_ipv4; - //Delete data tunnel + // Delete data tunnel pthread_mutex_lock(&m_mutex); - std::map::iterator data_it = m_ip_to_teid.find(tunnel_ctx->ue_ipv4); + std::map::iterator data_it = m_ip_to_teid.find(tunnel_ctx->ue_ipv4); if (data_it != m_ip_to_teid.end()) { m_ip_to_teid.erase(data_it); } pthread_mutex_unlock(&m_mutex); m_teid_to_tunnel_ctx.erase(tunnel_it); - delete tunnel_ctx; + delete tunnel_ctx; return; } -void -spgw::handle_release_access_bearers_request(struct srslte::gtpc_pdu *rel_req_pdu, struct srslte::gtpc_pdu *rel_resp_pdu) +void spgw::handle_release_access_bearers_request(struct srslte::gtpc_pdu* rel_req_pdu, + struct srslte::gtpc_pdu* rel_resp_pdu) { - //Find tunel ctxt - uint32_t ctrl_teid = rel_req_pdu->header.teid; - std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); + // Find tunel ctxt + uint32_t ctrl_teid = rel_req_pdu->header.teid; + std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); if (tunnel_it == m_teid_to_tunnel_ctx.end()) { - m_spgw_log->warning("Could not find TEID %d to release bearers from\n",ctrl_teid); + m_spgw_log->warning("Could not find TEID %d to release bearers from\n", ctrl_teid); return; } - spgw_tunnel_ctx_t *tunnel_ctx = tunnel_it->second; - in_addr_t ue_ipv4 = tunnel_ctx->ue_ipv4; + spgw_tunnel_ctx_t* tunnel_ctx = tunnel_it->second; + in_addr_t ue_ipv4 = tunnel_ctx->ue_ipv4; - //Delete data tunnel + // Delete data tunnel pthread_mutex_lock(&m_mutex); - std::map::iterator data_it = m_ip_to_teid.find(tunnel_ctx->ue_ipv4); + std::map::iterator data_it = m_ip_to_teid.find(tunnel_ctx->ue_ipv4); if (data_it != m_ip_to_teid.end()) { m_ip_to_teid.erase(data_it); } pthread_mutex_unlock(&m_mutex); - //Do NOT delete control tunnel + // Do NOT delete control tunnel return; } -} //namespace srsepc +/* + * Helper Functions + */ +uint64_t spgw::get_new_ctrl_teid() +{ + return m_next_ctrl_teid++; +} + +uint64_t spgw::get_new_user_teid() +{ + return m_next_user_teid++; +} + +in_addr_t spgw::get_new_ue_ipv4() +{ + m_h_next_ue_ip++; + return ntohl(m_h_next_ue_ip); // FIXME Tmp hack +} + +spgw_tunnel_ctx_t* spgw::create_gtp_ctx(struct srslte::gtpc_create_session_request* cs_req) +{ + // Setup uplink control TEID + uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid(); + // Setup uplink user TEID + uint64_t spgw_uplink_user_teid = get_new_user_teid(); + // Allocate UE IP + in_addr_t ue_ip = get_new_ue_ipv4(); + // in_addr_t ue_ip = inet_addr("172.16.0.2"); + uint8_t default_bearer_id = 5; + + m_spgw_log->console("SPGW: Allocated Ctrl TEID %" PRIu64 "\n", spgw_uplink_ctrl_teid); + m_spgw_log->console("SPGW: Allocated User TEID %" PRIu64 "\n", spgw_uplink_user_teid); + struct in_addr ue_ip_; + ue_ip_.s_addr = ue_ip; + m_spgw_log->console("SPGW: Allocate UE IP %s\n", inet_ntoa(ue_ip_)); + + // Save the UE IP to User TEID map + spgw_tunnel_ctx_t* tunnel_ctx = new spgw_tunnel_ctx_t; + bzero(tunnel_ctx, sizeof(spgw_tunnel_ctx_t)); + + tunnel_ctx->imsi = cs_req->imsi; + tunnel_ctx->ebi = default_bearer_id; + tunnel_ctx->up_user_fteid.teid = spgw_uplink_user_teid; + tunnel_ctx->up_user_fteid.ipv4 = m_s1u_addr.sin_addr.s_addr; + tunnel_ctx->dw_ctrl_fteid.teid = cs_req->sender_f_teid.teid; + tunnel_ctx->dw_ctrl_fteid.ipv4 = cs_req->sender_f_teid.ipv4; + + tunnel_ctx->up_ctrl_fteid.teid = spgw_uplink_ctrl_teid; + tunnel_ctx->ue_ipv4 = ue_ip; + m_teid_to_tunnel_ctx.insert(std::pair(spgw_uplink_ctrl_teid, tunnel_ctx)); + m_imsi_to_ctr_teid.insert(std::pair(cs_req->imsi, spgw_uplink_ctrl_teid)); + return tunnel_ctx; +} + +bool spgw::delete_gtp_ctx(uint32_t ctrl_teid) +{ + spgw_tunnel_ctx_t* tunnel_ctx; + if (!m_teid_to_tunnel_ctx.count(ctrl_teid)) { + m_spgw_log->error("Could not find GTP context to delete.\n"); + return false; + } + tunnel_ctx = m_teid_to_tunnel_ctx[ctrl_teid]; + + // Remove GTP-U connections, if any. + if (m_ip_to_teid.count(tunnel_ctx->ue_ipv4)) { + pthread_mutex_lock(&m_mutex); + m_ip_to_teid.erase(tunnel_ctx->ue_ipv4); + pthread_mutex_unlock(&m_mutex); + } + + // Remove Ctrl TEID from IMSI to control TEID map + m_imsi_to_ctr_teid.erase(tunnel_ctx->imsi); + + // Remove GTP context from control TEID mapping + m_teid_to_tunnel_ctx.erase(ctrl_teid); + delete tunnel_ctx; + return true; +} + +} // namespace srsepc