Starting to add Bearer QoS parameter to create session request.

master
Pedro Alvarez 7 years ago
parent 1b43c40422
commit 66db3deeb4

@ -11,6 +11,7 @@ class hss_interface_s1ap
{ {
public: 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_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 resync_sqn(uint64_t imsi, uint8_t *auts) = 0;
}; };

@ -78,6 +78,8 @@ public:
void stop(void); void stop(void);
bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres); bool gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres);
bool gen_update_loc_answer(uint64_t imsi, uint8_t* qci);
bool resync_sqn(uint64_t imsi, uint8_t *auts); bool resync_sqn(uint64_t imsi, uint8_t *auts);
private: private:

@ -111,7 +111,7 @@ typedef struct{
typedef struct{ typedef struct{
uint8_t eksi; uint8_t eksi;
uint8_t k_asme[32]; uint8_t k_asme[32];
uint8_t xres[16]; //minimum 6, maximum 16 uint8_t xres[16]; //minimum 6, maximum 16
uint32_t dl_nas_count; uint32_t dl_nas_count;
uint32_t ul_nas_count; uint32_t ul_nas_count;
@ -128,6 +128,7 @@ typedef struct{
typedef struct{ typedef struct{
enum erab_state state; enum erab_state state;
uint8_t erab_id; uint8_t erab_id;
uint8_t qci;
srslte::gtpc_f_teid_ie enb_fteid; srslte::gtpc_f_teid_ie enb_fteid;
srslte::gtpc_f_teid_ie sgw_s1u_fteid; srslte::gtpc_f_teid_ie sgw_s1u_fteid;
srslte::gtpc_pdn_address_allocation_ie pdn_addr_alloc; srslte::gtpc_pdn_address_allocation_ie pdn_addr_alloc;

@ -289,90 +289,8 @@ hss::gen_auth_info_answer(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t
} }
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;
}
increment_ue_sqn(imsi);
return ret;
}
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)
{
uint8_t last_rand[16];
uint8_t ak[6];
uint8_t mac_s[8];
uint8_t sqn_ms_xor_ak[6];
uint8_t k[16];
uint8_t amf[2];
uint8_t opc[16];
uint8_t sqn[6];
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++){
sqn_ms_xor_ak[i] = auts[i];
}
for(int i=0; i<8; i++){
mac_s[i] = auts[i+6];
}
m_hss_log->debug_hex(k, 16, "User Key : ");
m_hss_log->debug_hex(opc, 16, "User OPc : ");
m_hss_log->debug_hex(last_rand, 16, "User Last Rand : ");
m_hss_log->debug_hex(auts, 16, "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);
m_hss_log->debug_hex(ak, 6, "Resynch AK : ");
uint8_t sqn_ms[6];
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(amf, 2, "AMF : ");
uint8_t mac_s_tmp[8];
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;
}
bool bool
hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres) hss::gen_auth_info_answer_milenage(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uint8_t *rand, uint8_t *xres)
{ {
@ -536,7 +454,7 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
mcc, mcc,
mnc, mnc,
k_asme); k_asme);
m_hss_log->debug("User MCC : %x MNC : %x \n", mcc, mnc); m_hss_log->debug("User MCC : %x MNC : %x \n", mcc, mnc);
m_hss_log->debug_hex(k_asme, 32, "User k_asme : "); m_hss_log->debug_hex(k_asme, 32, "User k_asme : ");
@ -561,6 +479,23 @@ hss::gen_auth_info_answer_xor(uint64_t imsi, uint8_t *k_asme, uint8_t *autn, uin
return true; return true;
} }
bool
hss::gen_update_loc_answer(uint64_t imsi, uint8_t* qci)
{
std::map<uint64_t,hss_ue_ctx_t*>::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: %015lu\n",imsi);
m_hss_log->console("User not found. IMSI: %015lu\n",imsi);
return false;
}
hss_ue_ctx_t *ue_ctx = ue_ctx_it->second;
m_hss_log->info("Found User %015lu\n",imsi);
*qci = ue_ctx->qci;
return true;
}
bool bool
hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn) hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, uint8_t *sqn)
@ -583,6 +518,90 @@ hss::get_k_amf_opc_sqn(uint64_t imsi, uint8_t *k, uint8_t *amf, uint8_t *opc, ui
return true; return true;
} }
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;
}
increment_ue_sqn(imsi);
return ret;
}
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)
{
uint8_t last_rand[16];
uint8_t ak[6];
uint8_t mac_s[8];
uint8_t sqn_ms_xor_ak[6];
uint8_t k[16];
uint8_t amf[2];
uint8_t opc[16];
uint8_t sqn[6];
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++){
sqn_ms_xor_ak[i] = auts[i];
}
for(int i=0; i<8; i++){
mac_s[i] = auts[i+6];
}
m_hss_log->debug_hex(k, 16, "User Key : ");
m_hss_log->debug_hex(opc, 16, "User OPc : ");
m_hss_log->debug_hex(last_rand, 16, "User Last Rand : ");
m_hss_log->debug_hex(auts, 16, "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);
m_hss_log->debug_hex(ak, 6, "Resynch AK : ");
uint8_t sqn_ms[6];
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(amf, 2, "AMF : ");
uint8_t mac_s_tmp[8];
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 void
hss::increment_ue_sqn(uint64_t imsi) hss::increment_ue_sqn(uint64_t imsi)
{ {
@ -615,6 +634,7 @@ hss::increment_sqn(uint8_t *sqn, uint8_t *next_sqn)
} }
return; return;
} }
void void
hss::set_sqn(uint64_t imsi, uint8_t *sqn) hss::set_sqn(uint64_t imsi, uint8_t *sqn)
{ {
@ -670,7 +690,7 @@ bool hss::get_ue_ctx(uint64_t imsi, hss_ue_ctx_t **ue_ctx)
m_hss_log->info("User not found. IMSI: %015lu\n",imsi); m_hss_log->info("User not found. IMSI: %015lu\n",imsi);
return false; return false;
} }
*ue_ctx = ue_ctx_it->second; *ue_ctx = ue_ctx_it->second;
return true; return true;
} }
@ -715,15 +735,4 @@ hss::hex_string(uint8_t *hex, int size)
} }
return ss.str(); return ss.str();
} }
/*
uint64_t
string_to_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);
}
return imsi;
}
*/
} //namespace srsepc } //namespace srsepc

@ -92,7 +92,7 @@ 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?
} }
void void
mme_gtpc::send_create_session_request(uint64_t imsi) mme_gtpc::send_create_session_request(uint64_t imsi, uint8_t qci)
{ {
m_mme_gtpc_log->info("Sending Create Session Request.\n"); m_mme_gtpc_log->info("Sending Create Session Request.\n");
m_mme_gtpc_log->console("Sending Create Session Request.\n"); m_mme_gtpc_log->console("Sending Create Session Request.\n");
@ -124,9 +124,14 @@ mme_gtpc::send_create_session_request(uint64_t imsi)
// APN // APN
strncpy(cs_req->apn, m_s1ap->m_s1ap_args.mme_apn.c_str(), sizeof(cs_req->apn)-1); 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; cs_req->apn[sizeof(cs_req->apn)-1] = 0;
// RAT Type // RAT Type
//cs_req->rat_type = srslte::GTPC_RAT_TYPE::EUTRAN; //cs_req->rat_type = srslte::GTPC_RAT_TYPE::EUTRAN;
//Bearer QoS
cs_req->eps_bearer_context_created.ebi = 5;
cs_req->eps_bearer_context_created.bearer_qos.qci=qci;
//Check whether this UE is already registed //Check whether this UE is already registed
std::map<uint64_t, struct gtpc_ctx>::iterator it = m_imsi_to_gtpc_ctx.find(imsi); std::map<uint64_t, struct gtpc_ctx>::iterator it = m_imsi_to_gtpc_ctx.find(imsi);
if(it != m_imsi_to_gtpc_ctx.end()) if(it != m_imsi_to_gtpc_ctx.end())

@ -227,9 +227,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA
(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) (msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY))
{ {
//Only identity response and authentication response are valid as plain NAS. //Only identity response and authentication response are valid as plain NAS.
//Sometimes authentication response and identity are sent as integrity protected, //Sometimes authentication response/failure and identity response are sent as integrity protected,
//but these messages are sent when the securty context is not setup yet, so we cannot integrity check it. //but these messages are sent when the securty context is not setup yet, so we cannot integrity check it.
//FIXME Double-check
switch(msg_type) switch(msg_type)
{ {
case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE:
@ -1082,9 +1081,13 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas
} }
else else
{ {
//Get subscriber info from HSS
uint8_t qci;
m_hss->gen_update_loc_answer(emm_ctx->imsi,&qci);
m_s1ap_log->console("QCI %d\n", qci);
//FIXME The packging of GTP-C messages is not ready. //FIXME The packging of GTP-C messages is not ready.
//This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C.
m_mme_gtpc->send_create_session_request(emm_ctx->imsi); m_mme_gtpc->send_create_session_request(emm_ctx->imsi,qci);
*reply_flag = false; //No reply needed *reply_flag = false; //No reply needed
} }
return true; return true;

@ -537,6 +537,10 @@ spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *
cs_resp->eps_bearer_context_created.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; 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_present=true;
cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid = tunnel_ctx->up_user_fteid; cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid = tunnel_ctx->up_user_fteid;
//Bearer QoS
cs_resp->eps_bearer_context_created.bearer_qos.qci = cs_req->eps_bearer_context_created.bearer_qos.qci;
//Fill in the PAA //Fill in the PAA
cs_resp->paa_present = true; cs_resp->paa_present = true;
cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4; cs_resp->paa.pdn_type = srslte::GTPC_PDN_TYPE_IPV4;

Loading…
Cancel
Save