|
|
|
@ -172,9 +172,25 @@ bool nas::attach_request() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nas::deattach_request() {
|
|
|
|
|
state = EMM_STATE_DEREGISTERED_INITIATED;
|
|
|
|
|
nas_log->info("Dettach request not supported\n");
|
|
|
|
|
bool nas::detach_request() {
|
|
|
|
|
// attempt detach for 5s
|
|
|
|
|
nas_log->info("Detach Request\n");
|
|
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
|
case EMM_STATE_DEREGISTERED:
|
|
|
|
|
// do nothing ..
|
|
|
|
|
break;
|
|
|
|
|
case EMM_STATE_REGISTERED:
|
|
|
|
|
// send detach request
|
|
|
|
|
send_detach_request(true);
|
|
|
|
|
state = EMM_STATE_DEREGISTERED_INITIATED;
|
|
|
|
|
break;
|
|
|
|
|
case EMM_STATE_DEREGISTERED_INITIATED:
|
|
|
|
|
// do nothing ..
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -355,6 +371,9 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
case LIBLTE_MME_MSG_TYPE_EMM_INFORMATION:
|
|
|
|
|
parse_emm_information(lcid, pdu);
|
|
|
|
|
break;
|
|
|
|
|
case LIBLTE_MME_MSG_TYPE_DETACH_REQUEST:
|
|
|
|
|
parse_detach_request(lcid, pdu);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
nas_log->error("Not handling NAS message with MSG_TYPE=%02X\n", msg_type);
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
@ -959,6 +978,23 @@ void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::parse_detach_request(uint32_t lcid, byte_buffer_t *pdu)
|
|
|
|
|
{
|
|
|
|
|
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request;
|
|
|
|
|
liblte_mme_unpack_detach_request_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &detach_request);
|
|
|
|
|
ctxt.rx_count++;
|
|
|
|
|
pool->deallocate(pdu);
|
|
|
|
|
|
|
|
|
|
if (state == EMM_STATE_REGISTERED) {
|
|
|
|
|
nas_log->info("Received Detach request (type=%d)\n", detach_request.detach_type.type_of_detach);
|
|
|
|
|
state = EMM_STATE_DEREGISTERED;
|
|
|
|
|
// send accept
|
|
|
|
|
send_detach_accept();
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->warning("Received detach request in invalid state (state=%d)\n", state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
* Senders
|
|
|
|
|
******************************************************************************/
|
|
|
|
@ -1132,6 +1168,104 @@ void nas::send_security_mode_reject(uint8_t cause) {
|
|
|
|
|
rrc->write_sdu(cfg.lcid, msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::send_detach_request(bool switch_off)
|
|
|
|
|
{
|
|
|
|
|
byte_buffer_t *pdu = pool_allocate_blocking;
|
|
|
|
|
if (!pdu) {
|
|
|
|
|
nas_log->error("Fatal Error: Couldn't allocate PDU in %s().\n", __FUNCTION__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT detach_request = {};
|
|
|
|
|
if (switch_off) {
|
|
|
|
|
detach_request.detach_type.switch_off = 1;
|
|
|
|
|
detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_SWITCH_OFF;
|
|
|
|
|
} else {
|
|
|
|
|
detach_request.detach_type.switch_off = 0;
|
|
|
|
|
detach_request.detach_type.type_of_detach = LIBLTE_MME_SO_FLAG_NORMAL_DETACH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GUTI or IMSI detach
|
|
|
|
|
if (have_guti && have_ctxt) {
|
|
|
|
|
detach_request.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI;
|
|
|
|
|
memcpy(&detach_request.eps_mobile_id.guti, &ctxt.guti, sizeof(LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT));
|
|
|
|
|
detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
|
|
|
|
|
detach_request.nas_ksi.nas_ksi = ctxt.ksi;
|
|
|
|
|
nas_log->info("Requesting Detach with GUTI\n");
|
|
|
|
|
liblte_mme_pack_detach_request_msg(&detach_request,
|
|
|
|
|
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
|
|
|
|
|
ctxt.tx_count,
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
|
|
|
|
|
if(pcap != NULL) {
|
|
|
|
|
pcap->write_nas(pdu->msg, pdu->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add MAC
|
|
|
|
|
if (pdu->N_bytes > 5) {
|
|
|
|
|
cipher_encrypt(pdu);
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
ctxt.tx_count,
|
|
|
|
|
SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
&pdu->msg[5],
|
|
|
|
|
pdu->N_bytes - 5,
|
|
|
|
|
&pdu->msg[1]);
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
detach_request.eps_mobile_id.type_of_id = LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI;
|
|
|
|
|
detach_request.nas_ksi.tsc_flag = LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_NATIVE;
|
|
|
|
|
detach_request.nas_ksi.nas_ksi = 0;
|
|
|
|
|
usim->get_imsi_vec(detach_request.eps_mobile_id.imsi, 15);
|
|
|
|
|
nas_log->info("Requesting IMSI detach (IMSI=%s)\n", usim->get_imsi_str().c_str());
|
|
|
|
|
liblte_mme_pack_detach_request_msg(&detach_request, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, ctxt.tx_count, (LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
|
|
|
|
|
if(pcap != NULL) {
|
|
|
|
|
pcap->write_nas(pdu->msg, pdu->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nas_log->info("Sending detach request\n");
|
|
|
|
|
rrc->write_sdu(cfg.lcid, pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nas::send_detach_accept()
|
|
|
|
|
{
|
|
|
|
|
byte_buffer_t *pdu = pool_allocate_blocking;
|
|
|
|
|
if (!pdu) {
|
|
|
|
|
nas_log->error("Fatal Error: Couldn't allocate PDU in %s().\n", __FUNCTION__);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT detach_accept;
|
|
|
|
|
bzero(&detach_accept, sizeof(detach_accept));
|
|
|
|
|
liblte_mme_pack_detach_accept_msg(&detach_accept,
|
|
|
|
|
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
|
|
|
|
|
ctxt.tx_count,
|
|
|
|
|
(LIBLTE_BYTE_MSG_STRUCT *) pdu);
|
|
|
|
|
|
|
|
|
|
if(pcap != NULL) {
|
|
|
|
|
pcap->write_nas(pdu->msg, pdu->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Encrypt and add MAC
|
|
|
|
|
if (pdu->N_bytes > 5) {
|
|
|
|
|
cipher_encrypt(pdu);
|
|
|
|
|
integrity_generate(&k_nas_int[16],
|
|
|
|
|
ctxt.tx_count,
|
|
|
|
|
SECURITY_DIRECTION_UPLINK,
|
|
|
|
|
&pdu->msg[5],
|
|
|
|
|
pdu->N_bytes - 5,
|
|
|
|
|
&pdu->msg[1]);
|
|
|
|
|
} else {
|
|
|
|
|
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nas_log->info("Sending detach accept\n");
|
|
|
|
|
rrc->write_sdu(cfg.lcid, pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void nas::send_authentication_response(const uint8_t* res, const size_t res_len, const uint8_t sec_hdr_type) {
|
|
|
|
|
byte_buffer_t *pdu = pool_allocate_blocking;
|
|
|
|
|