|
|
|
@ -25,7 +25,9 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "srslte/asn1/liblte_rrc.h"
|
|
|
|
|
#include "upper/nas.h"
|
|
|
|
|
#include "srslte/common/bcd_helpers.h"
|
|
|
|
|
|
|
|
|
|
using namespace srslte;
|
|
|
|
|
|
|
|
|
@ -45,11 +47,9 @@ namespace srsue {
|
|
|
|
|
gw = gw_;
|
|
|
|
|
nas_log = nas_log_;
|
|
|
|
|
state = EMM_STATE_DEREGISTERED;
|
|
|
|
|
|
|
|
|
|
// Manual PLMN selection procedure
|
|
|
|
|
current_plmn.mcc = 1;
|
|
|
|
|
current_plmn.mnc = 1;
|
|
|
|
|
plmn_selection = PLMN_SELECTED;
|
|
|
|
|
plmn_selection = PLMN_NOT_SELECTED;
|
|
|
|
|
home_plmn.mcc = 61441; // This is 001
|
|
|
|
|
home_plmn.mnc = 65281; // This is 01
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::stop() {}
|
|
|
|
@ -62,11 +62,14 @@ namespace srsue {
|
|
|
|
|
UE interface
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
void nas::attach_request() {
|
|
|
|
|
nas_log->info("Attach Request\n");
|
|
|
|
|
if (state == EMM_STATE_DEREGISTERED) {
|
|
|
|
|
state = EMM_STATE_REGISTERED_INITIATED;
|
|
|
|
|
if (plmn_selection == PLMN_NOT_SELECTED) {
|
|
|
|
|
nas_log->info("Starting PLMN Search...\n");
|
|
|
|
|
rrc->plmn_search();
|
|
|
|
|
} else if (plmn_selection == PLMN_SELECTED) {
|
|
|
|
|
nas_log->info("Selecting PLMN %s\n", plmn_id_to_c_str(current_plmn).c_str());
|
|
|
|
|
rrc->plmn_select(current_plmn);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -83,44 +86,57 @@ namespace srsue {
|
|
|
|
|
RRC interface
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
|
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
|
|
|
|
|
// if it's the plmn we want rrc->plmn_select() and plmn_selection = PLMN_SELECTED
|
|
|
|
|
}
|
|
|
|
|
void nas::plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) {
|
|
|
|
|
|
|
|
|
|
void nas::cell_selected() {
|
|
|
|
|
// Store PLMN if not registered
|
|
|
|
|
for (uint32_t i=0;i<known_plmns.size();i++) {
|
|
|
|
|
if (plmn_id.mcc == known_plmns[i].mcc && plmn_id.mnc == known_plmns[i].mnc) {
|
|
|
|
|
nas_log->info("Detected known PLMN %s\n", plmn_id_to_c_str(plmn_id).c_str());
|
|
|
|
|
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
|
|
|
|
|
rrc->plmn_select(plmn_id);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nas_log->info("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
|
|
|
|
|
tracking_area_code);
|
|
|
|
|
nas_log->console("Found PLMN: Id=%s, TAC=%d\n", plmn_id_to_c_str(plmn_id).c_str(),
|
|
|
|
|
tracking_area_code);
|
|
|
|
|
if (plmn_id.mcc == home_plmn.mcc && plmn_id.mnc == home_plmn.mnc) {
|
|
|
|
|
rrc->plmn_select(plmn_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::cell_selected() {
|
|
|
|
|
if (state == EMM_STATE_REGISTERED_INITIATED) {
|
|
|
|
|
rrc->connect();
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->info("Cell selcted in invalid state = %s\n", emm_state_text[state]);
|
|
|
|
|
nas_log->info("Cell selected in invalid state = %s\n", emm_state_text[state]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nas::is_attached()
|
|
|
|
|
{
|
|
|
|
|
bool nas::is_attached() {
|
|
|
|
|
return state == EMM_STATE_REGISTERED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::notify_connection_setup()
|
|
|
|
|
{
|
|
|
|
|
void nas::notify_connection_setup() {
|
|
|
|
|
nas_log->debug("State = %s\n", emm_state_text[state]);
|
|
|
|
|
if(EMM_STATE_REGISTERED_INITIATED == state) {
|
|
|
|
|
if (EMM_STATE_REGISTERED_INITIATED == state) {
|
|
|
|
|
send_attach_request();
|
|
|
|
|
} else {
|
|
|
|
|
send_service_request();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
uint8 pd;
|
|
|
|
|
uint8 msg_type;
|
|
|
|
|
|
|
|
|
|
nas_log->info_hex(pdu->msg, pdu->N_bytes, "DL %s PDU", rb_id_text[lcid]);
|
|
|
|
|
|
|
|
|
|
// Parse the message
|
|
|
|
|
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT*)pdu, &pd, &msg_type);
|
|
|
|
|
switch(msg_type)
|
|
|
|
|
{
|
|
|
|
|
liblte_mme_parse_msg_header((LIBLTE_BYTE_MSG_STRUCT *) pdu, &pd, &msg_type);
|
|
|
|
|
switch (msg_type) {
|
|
|
|
|
case LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT:
|
|
|
|
|
parse_attach_accept(lcid, pdu);
|
|
|
|
|
break;
|
|
|
|
@ -149,42 +165,38 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
parse_emm_information(lcid, pdu);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
nas_log->error("Not handling NAS message with MSG_TYPE=%02X\n",msg_type);
|
|
|
|
|
nas_log->error("Not handling NAS message with MSG_TYPE=%02X\n", msg_type);
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t nas::get_ul_count()
|
|
|
|
|
{
|
|
|
|
|
uint32_t nas::get_ul_count() {
|
|
|
|
|
return count_ul;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi)
|
|
|
|
|
{
|
|
|
|
|
if(is_guti_set) {
|
|
|
|
|
bool nas::get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) {
|
|
|
|
|
if (is_guti_set) {
|
|
|
|
|
s_tmsi->mmec = guti.mme_code;
|
|
|
|
|
s_tmsi->m_tmsi = guti.m_tmsi;
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Security
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
|
void nas::integrity_generate(uint8_t *key_128,
|
|
|
|
|
void nas::integrity_generate(uint8_t *key_128,
|
|
|
|
|
uint32_t count,
|
|
|
|
|
uint8_t rb_id,
|
|
|
|
|
uint8_t direction,
|
|
|
|
|
uint8_t *msg,
|
|
|
|
|
uint32_t msg_len,
|
|
|
|
|
uint8_t *mac)
|
|
|
|
|
{
|
|
|
|
|
switch(integ_algo)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *mac) {
|
|
|
|
|
switch (integ_algo) {
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_EIA0:
|
|
|
|
|
break;
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_128_EIA1:
|
|
|
|
@ -208,31 +220,26 @@ void nas::integrity_generate(uint8_t *key_128,
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::integrity_check()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
void nas::integrity_check() {
|
|
|
|
|
|
|
|
|
|
void nas::cipher_encrypt()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
void nas::cipher_encrypt() {
|
|
|
|
|
|
|
|
|
|
void nas::cipher_decrypt()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
void nas::cipher_decrypt() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Parsers
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
|
void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept;
|
|
|
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT act_def_eps_bearer_context_req;
|
|
|
|
|
LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_complete;
|
|
|
|
@ -241,44 +248,32 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
nas_log->info("Received Attach Accept\n");
|
|
|
|
|
count_dl++;
|
|
|
|
|
|
|
|
|
|
liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu, &attach_accept);
|
|
|
|
|
liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_accept);
|
|
|
|
|
|
|
|
|
|
if(attach_accept.eps_attach_result == LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY)
|
|
|
|
|
{
|
|
|
|
|
if (attach_accept.eps_attach_result == LIBLTE_MME_EPS_ATTACH_RESULT_EPS_ONLY) {
|
|
|
|
|
//FIXME: Handle t3412.unit
|
|
|
|
|
//FIXME: Handle tai_list
|
|
|
|
|
if(attach_accept.guti_present)
|
|
|
|
|
{
|
|
|
|
|
if (attach_accept.guti_present) {
|
|
|
|
|
memcpy(&guti, &attach_accept.guti.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
|
|
|
|
|
is_guti_set = true;
|
|
|
|
|
// TODO: log message to console
|
|
|
|
|
}
|
|
|
|
|
if(attach_accept.lai_present)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
if(attach_accept.ms_id_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.emm_cause_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.t3402_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.t3423_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.equivalent_plmns_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.emerg_num_list_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.eps_network_feature_support_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.additional_update_result_present)
|
|
|
|
|
{}
|
|
|
|
|
if(attach_accept.t3412_ext_present)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg, &act_def_eps_bearer_context_req);
|
|
|
|
|
|
|
|
|
|
if(LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type)
|
|
|
|
|
{
|
|
|
|
|
if (attach_accept.lai_present) {
|
|
|
|
|
}
|
|
|
|
|
if (attach_accept.ms_id_present) {}
|
|
|
|
|
if (attach_accept.emm_cause_present) {}
|
|
|
|
|
if (attach_accept.t3402_present) {}
|
|
|
|
|
if (attach_accept.t3423_present) {}
|
|
|
|
|
if (attach_accept.equivalent_plmns_present) {}
|
|
|
|
|
if (attach_accept.emerg_num_list_present) {}
|
|
|
|
|
if (attach_accept.eps_network_feature_support_present) {}
|
|
|
|
|
if (attach_accept.additional_update_result_present) {}
|
|
|
|
|
if (attach_accept.t3412_ext_present) {}
|
|
|
|
|
|
|
|
|
|
liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(&attach_accept.esm_msg,
|
|
|
|
|
&act_def_eps_bearer_context_req);
|
|
|
|
|
|
|
|
|
|
if (LIBLTE_MME_PDN_TYPE_IPV4 == act_def_eps_bearer_context_req.pdn_addr.pdn_type) {
|
|
|
|
|
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[0] << 24;
|
|
|
|
|
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[1] << 16;
|
|
|
|
|
ip_addr |= act_def_eps_bearer_context_req.pdn_addr.addr[2] << 8;
|
|
|
|
@ -298,20 +293,16 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
|
|
|
|
|
// Setup GW
|
|
|
|
|
char *err_str = NULL;
|
|
|
|
|
if(gw->setup_if_addr(ip_addr, err_str))
|
|
|
|
|
{
|
|
|
|
|
if (gw->setup_if_addr(ip_addr, err_str)) {
|
|
|
|
|
nas_log->error("Failed to set gateway address - %s\n", err_str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->error("Not handling IPV6 or IPV4V6\n");
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
eps_bearer_id = act_def_eps_bearer_context_req.eps_bearer_id;
|
|
|
|
|
if(act_def_eps_bearer_context_req.transaction_id_present)
|
|
|
|
|
{
|
|
|
|
|
if (act_def_eps_bearer_context_req.transaction_id_present) {
|
|
|
|
|
transaction_id = act_def_eps_bearer_context_req.proc_transaction_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -337,17 +328,18 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id;
|
|
|
|
|
act_def_eps_bearer_context_accept.proc_transaction_id = transaction_id;
|
|
|
|
|
act_def_eps_bearer_context_accept.protocol_cnfg_opts_present = false;
|
|
|
|
|
liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_def_eps_bearer_context_accept, &attach_complete.esm_msg);
|
|
|
|
|
liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(&act_def_eps_bearer_context_accept,
|
|
|
|
|
&attach_complete.esm_msg);
|
|
|
|
|
liblte_mme_pack_attach_complete_msg(&attach_complete,
|
|
|
|
|
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
|
|
|
|
|
count_ul,
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT*)pdu);
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
count_ul,
|
|
|
|
|
lcid-1,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
&pdu->msg[5],
|
|
|
|
|
pdu->N_bytes-5,
|
|
|
|
|
pdu->N_bytes - 5,
|
|
|
|
|
&pdu->msg[1]);
|
|
|
|
|
|
|
|
|
|
// Instruct RRC to enable capabilities
|
|
|
|
@ -356,34 +348,30 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
nas_log->info("Sending Attach Complete\n");
|
|
|
|
|
rrc->write_sdu(lcid, pdu);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->info("Not handling attach type %u\n", attach_accept.eps_attach_result);
|
|
|
|
|
state = EMM_STATE_DEREGISTERED;
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_attach_reject(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT attach_rej;
|
|
|
|
|
|
|
|
|
|
liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu, &attach_rej);
|
|
|
|
|
liblte_mme_unpack_attach_reject_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_rej);
|
|
|
|
|
nas_log->warning("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause);
|
|
|
|
|
nas_log->console("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause);
|
|
|
|
|
state = EMM_STATE_DEREGISTERED;
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
// FIXME: Command RRC to release?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT auth_req;
|
|
|
|
|
LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_res;
|
|
|
|
|
|
|
|
|
|
nas_log->info("Received Authentication Request\n");;
|
|
|
|
|
liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu, &auth_req);
|
|
|
|
|
liblte_mme_unpack_authentication_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &auth_req);
|
|
|
|
|
|
|
|
|
|
// Reuse the pdu for the response message
|
|
|
|
|
pdu->reset();
|
|
|
|
@ -399,52 +387,45 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
uint8_t res[16];
|
|
|
|
|
usim->generate_authentication_response(auth_req.rand, auth_req.autn, mcc, mnc, &net_valid, res);
|
|
|
|
|
|
|
|
|
|
if(net_valid)
|
|
|
|
|
{
|
|
|
|
|
if (net_valid) {
|
|
|
|
|
nas_log->info("Network authentication successful\n");
|
|
|
|
|
for(int i=0; i<8; i++)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
|
auth_res.res[i] = res[i];
|
|
|
|
|
}
|
|
|
|
|
liblte_mme_pack_authentication_response_msg(&auth_res, (LIBLTE_BYTE_MSG_STRUCT*)pdu);
|
|
|
|
|
liblte_mme_pack_authentication_response_msg(&auth_res, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
|
|
|
|
|
nas_log->info("Sending Authentication Response\n");
|
|
|
|
|
rrc->write_sdu(lcid, pdu);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->warning("Network authentication failure\n");
|
|
|
|
|
nas_log->console("Warning: Network authentication failure\n");
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
nas_log->warning("Received Authentication Reject\n");
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
state = EMM_STATE_DEREGISTERED;
|
|
|
|
|
// FIXME: Command RRC to release?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_identity_request(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
nas_log->error("TODO:parse_identity_request\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
bool success;
|
|
|
|
|
LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT sec_mode_cmd;
|
|
|
|
|
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sec_mode_comp;
|
|
|
|
|
LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT sec_mode_rej;
|
|
|
|
|
|
|
|
|
|
nas_log->info("Received Security Mode Command\n");
|
|
|
|
|
liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT*)pdu, &sec_mode_cmd);
|
|
|
|
|
liblte_mme_unpack_security_mode_command_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &sec_mode_cmd);
|
|
|
|
|
|
|
|
|
|
ksi = sec_mode_cmd.nas_ksi.nas_ksi;
|
|
|
|
|
cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eea;
|
|
|
|
|
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)sec_mode_cmd.selected_nas_sec_algs.type_of_eia;
|
|
|
|
|
cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eea;
|
|
|
|
|
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM) sec_mode_cmd.selected_nas_sec_algs.type_of_eia;
|
|
|
|
|
// FIXME: Handle nonce_ue, nonce_mme
|
|
|
|
|
// FIXME: Currently only handling ciphering EEA0 (null) and integrity EIA1,EIA2
|
|
|
|
|
// FIXME: Use selected_nas_sec_algs to choose correct algos
|
|
|
|
@ -453,17 +434,14 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
ksi, ciphering_algorithm_id_text[cipher_algo], integrity_algorithm_id_text[integ_algo]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(CIPHERING_ALGORITHM_ID_EEA0 != cipher_algo ||
|
|
|
|
|
if (CIPHERING_ALGORITHM_ID_EEA0 != cipher_algo ||
|
|
|
|
|
(INTEGRITY_ALGORITHM_ID_128_EIA2 != integ_algo &&
|
|
|
|
|
INTEGRITY_ALGORITHM_ID_128_EIA1 != integ_algo) ||
|
|
|
|
|
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE)
|
|
|
|
|
{
|
|
|
|
|
sec_mode_cmd.nas_ksi.tsc_flag != LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE) {
|
|
|
|
|
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH;
|
|
|
|
|
nas_log->warning("Sending Security Mode Reject due to security capabilities mismatch\n");
|
|
|
|
|
success = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
// Generate NAS encryption key and integrity protection key
|
|
|
|
|
usim->generate_nas_keys(k_nas_enc, k_nas_int, cipher_algo, integ_algo);
|
|
|
|
|
nas_log->debug_hex(k_nas_enc, 32, "NAS encryption key - k_nas_enc");
|
|
|
|
@ -474,37 +452,34 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
uint8_t genMAC[4];
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
count_dl,
|
|
|
|
|
lcid-1,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
SECURITY_DIRECTION_DOWNLINK,
|
|
|
|
|
&pdu->msg[5],
|
|
|
|
|
pdu->N_bytes-5,
|
|
|
|
|
pdu->N_bytes - 5,
|
|
|
|
|
genMAC);
|
|
|
|
|
|
|
|
|
|
nas_log->info_hex(inMAC, 4, "Incoming PDU MAC:");
|
|
|
|
|
nas_log->info_hex(genMAC, 4, "Generated PDU MAC:");
|
|
|
|
|
|
|
|
|
|
bool match=true;
|
|
|
|
|
for(int i=0;i<4;i++) {
|
|
|
|
|
if(inMAC[i] != genMAC[i]) {
|
|
|
|
|
bool match = true;
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
if (inMAC[i] != genMAC[i]) {
|
|
|
|
|
match = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!match) {
|
|
|
|
|
if (!match) {
|
|
|
|
|
sec_mode_rej.emm_cause = LIBLTE_MME_EMM_CAUSE_SECURITY_MODE_REJECTED_UNSPECIFIED;
|
|
|
|
|
nas_log->warning("Sending Security Mode Reject due to integrity check failure\n");
|
|
|
|
|
success = false;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
if(sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req)
|
|
|
|
|
{
|
|
|
|
|
if (sec_mode_cmd.imeisv_req_present && LIBLTE_MME_IMEISV_REQUESTED == sec_mode_cmd.imeisv_req) {
|
|
|
|
|
sec_mode_comp.imeisv_present = true;
|
|
|
|
|
sec_mode_comp.imeisv.type_of_id = LIBLTE_MME_MOBILE_ID_TYPE_IMEISV;
|
|
|
|
|
usim->get_imei_vec(sec_mode_comp.imeisv.imeisv, 15);
|
|
|
|
|
sec_mode_comp.imeisv.imeisv[14] = 5;
|
|
|
|
|
sec_mode_comp.imeisv.imeisv[15] = 3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
sec_mode_comp.imeisv_present = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -513,13 +488,13 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
liblte_mme_pack_security_mode_complete_msg(&sec_mode_comp,
|
|
|
|
|
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
|
|
|
|
|
count_ul,
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT*)pdu);
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
count_ul,
|
|
|
|
|
lcid-1,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
&pdu->msg[5],
|
|
|
|
|
pdu->N_bytes-5,
|
|
|
|
|
pdu->N_bytes - 5,
|
|
|
|
|
&pdu->msg[1]);
|
|
|
|
|
nas_log->info("Sending Security Mode Complete nas_count_ul=%d, RB=%s\n",
|
|
|
|
|
count_ul,
|
|
|
|
@ -528,42 +503,39 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!success) {
|
|
|
|
|
if (!success) {
|
|
|
|
|
// Reuse pdu for response
|
|
|
|
|
pdu->reset();
|
|
|
|
|
liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT*)pdu);
|
|
|
|
|
liblte_mme_pack_security_mode_reject_msg(&sec_mode_rej, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rrc->write_sdu(lcid, pdu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
nas_log->error("TODO:parse_service_reject\n");
|
|
|
|
|
}
|
|
|
|
|
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
nas_log->error("TODO:parse_esm_information_request\n");
|
|
|
|
|
}
|
|
|
|
|
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
nas_log->error("TODO:parse_emm_information\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
Senders
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
|
void nas::send_attach_request()
|
|
|
|
|
{
|
|
|
|
|
void nas::send_attach_request() {
|
|
|
|
|
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req;
|
|
|
|
|
byte_buffer_t *msg = pool_allocate;
|
|
|
|
|
u_int32_t i;
|
|
|
|
|
|
|
|
|
|
attach_req.eps_attach_type = LIBLTE_MME_EPS_ATTACH_TYPE_EPS_ATTACH;
|
|
|
|
|
|
|
|
|
|
for(i=0; i<8; i++)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
|
attach_req.ue_network_cap.eea[i] = false;
|
|
|
|
|
attach_req.ue_network_cap.eia[i] = false;
|
|
|
|
|
}
|
|
|
|
@ -599,14 +571,13 @@ void nas::send_attach_request()
|
|
|
|
|
attach_req.old_guti_type_present = false;
|
|
|
|
|
|
|
|
|
|
// Pack the message
|
|
|
|
|
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT*)msg);
|
|
|
|
|
liblte_mme_pack_attach_request_msg(&attach_req, (LIBLTE_BYTE_MSG_STRUCT *) msg);
|
|
|
|
|
|
|
|
|
|
nas_log->info("Sending attach request\n");
|
|
|
|
|
rrc->write_sdu(RB_ID_SRB1, msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg)
|
|
|
|
|
{
|
|
|
|
|
void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
|
|
|
|
|
LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req;
|
|
|
|
|
|
|
|
|
|
nas_log->info("Generating PDN Connectivity Request\n");
|
|
|
|
@ -625,12 +596,11 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg)
|
|
|
|
|
|
|
|
|
|
// Pack the message
|
|
|
|
|
liblte_mme_pack_pdn_connectivity_request_msg(&pdn_con_req, msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::send_identity_response(){}
|
|
|
|
|
void nas::send_identity_response() {}
|
|
|
|
|
|
|
|
|
|
void nas::send_service_request()
|
|
|
|
|
{
|
|
|
|
|
void nas::send_service_request() {
|
|
|
|
|
byte_buffer_t *msg = pool_allocate;
|
|
|
|
|
count_ul++;
|
|
|
|
|
|
|
|
|
@ -644,7 +614,7 @@ void nas::send_service_request()
|
|
|
|
|
uint8_t mac[4];
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
count_ul,
|
|
|
|
|
RB_ID_SRB1-1,
|
|
|
|
|
RB_ID_SRB1 - 1,
|
|
|
|
|
SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
&msg->msg[0],
|
|
|
|
|
2,
|
|
|
|
@ -656,8 +626,8 @@ void nas::send_service_request()
|
|
|
|
|
msg->N_bytes++;
|
|
|
|
|
nas_log->info("Sending service request\n");
|
|
|
|
|
rrc->write_sdu(RB_ID_SRB1, msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::send_esm_information_response(){}
|
|
|
|
|
void nas::send_esm_information_response() {}
|
|
|
|
|
|
|
|
|
|
} // namespace srsue
|
|
|
|
|