diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index d2c0d0acbe8f7375370fdc3699af8f6d6be1ca86..a2c570c00980cb8dd09b62779672db25a41f4155 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -59,6 +59,10 @@ #include "gtpv1u_eNB_task.h" #include "RRC/LITE/rrc_eNB_GTPV1U.h" +#include "TLVDecoder.h" +#include "S1ap-NAS-PDU.h" +#include "flexran_agent_common_internal.h" + extern RAN_CONTEXT_t RC; /* Value to indicate an invalid UE initial id */ @@ -542,6 +546,74 @@ rrc_eNB_send_S1AP_UPLINK_NAS( S1AP_UPLINK_NAS (msg_p).nas_pdu.length = pdu_length; S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer = pdu_buffer; + /* Process NAS message locally to get the IMSI */ + nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(nas_message_t)); + int size = 0; + uint32_t pdu_len = S1AP_UPLINK_NAS (msg_p).nas_pdu.length; + uint8_t *pdu_buff = malloc(pdu_len * sizeof(uint8_t)); + memcpy(pdu_buff, S1AP_UPLINK_NAS (msg_p).nas_pdu.buffer, pdu_len * sizeof(uint8_t)); + + nas_message_security_header_t *header = &nas_msg.header; + /* Decode the first octet of the header (security header type or EPS + * bearer identity, and protocol discriminator) */ + DECODE_U8((char *) pdu_buff, *(uint8_t*) (header), size); + + /* Decode NAS message */ + if (header->security_header_type <= SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED + && header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE + && pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE) { + + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { + /* Decode the message authentication code */ + DECODE_U32((char *) pdu_buff+size, header->message_authentication_code, size); + /* Decode the sequence number */ + DECODE_U8((char *) pdu_buff+size, header->sequence_number, size); + } + + if (size > 1) { + pdu_buff += size; + pdu_len -= size; + } + + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + + /* First decode the EMM message header */ + int e_head_size = 0; + + /* Check the buffer length */ + if (pdu_len > sizeof(emm_msg_header_t)) { + + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buff + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* Decode the message type */ + DECODE_U8(pdu_buff + e_head_size, emm_header->message_type, e_head_size); + + /* Check the protocol discriminator */ + if (emm_header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) { + + pdu_buff += e_head_size; + pdu_len -= e_head_size; + + if (emm_header->message_type == IDENTITY_RESPONSE) { + decode_identity_response(&e_msg->identity_response, pdu_buff, pdu_len); + + if (e_msg->identity_response.mobileidentity.imsi.typeofidentity == MOBILE_IDENTITY_IMSI) { + ue_context_pP->ue_context.imsi = compute_imsi(&(e_msg->identity_response.mobileidentity.imsi)); + } + } + + pdu_buff -= e_head_size; + if (size > 1) { + pdu_buff -= size; + } + } + } + } + free(pdu_buff); + itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p); } } @@ -563,16 +635,82 @@ rrc_eNB_send_S1AP_UPLINK_NAS( &ulInformationTransfer->criticalExtensions.choice. c1.choice.ulInformationTransfer_r8; - if (ulInformationTransferR8->dedicatedInfoType. - present == - ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS) + if (ulInformationTransferR8->dedicatedInfoType.present == + ULInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS) { + + /* Process NAS message locally to get the IMSI */ + nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(nas_message_t)); + + int size = 0; + uint32_t pdu_len = ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.size; + uint8_t *pdu_buff = malloc(pdu_len * sizeof(uint8_t)); + memcpy(pdu_buff, ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.buf, pdu_len * sizeof(uint8_t)); + + nas_message_security_header_t *header = &nas_msg.header; + /* Decode the first octet of the header (security header type or EPS + * bearer identity, and protocol discriminator) */ + DECODE_U8((char *) pdu_buff, *(uint8_t*) (header), size); + + /* Decode NAS message */ + if (header->security_header_type <= SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED && + header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE && + pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE) { + + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { + /* Decode the message authentication code */ + DECODE_U32((char *) pdu_buff+size, header->message_authentication_code, size); + /* Decode the sequence number */ + DECODE_U8((char *) pdu_buff+size, header->sequence_number, size); + } + + if (size > 1) { + pdu_buff += size; + pdu_len -= size; + } + + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + + /* First decode the EMM message header */ + int e_head_size = 0; + + /* Check the buffer length */ + if (pdu_len > sizeof(emm_msg_header_t)) { + + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buff + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* Decode the message type */ + DECODE_U8(pdu_buff + e_head_size, emm_header->message_type, e_head_size); + + /* Check the protocol discriminator */ + if (emm_header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) { + + pdu_buff += e_head_size; + pdu_len -= e_head_size; + + if (emm_header->message_type == IDENTITY_RESPONSE) { + decode_identity_response(&e_msg->identity_response, pdu_buff, pdu_len); + + if (e_msg->identity_response.mobileidentity.imsi.typeofidentity == MOBILE_IDENTITY_IMSI) { + ue_context_pP->ue_context.imsi = compute_imsi(&(e_msg->identity_response.mobileidentity.imsi)); + } + } + + pdu_buff -= e_head_size; + if (size > 1) { + pdu_buff -= size; + } + } + } + } + free(pdu_buff); + s1ap_eNB_new_data_request (mod_id, ue_index, - ulInformationTransferR8-> - dedicatedInfoType.choice. - dedicatedInfoNAS.buf, - ulInformationTransferR8-> - dedicatedInfoType.choice. - dedicatedInfoNAS.size); + ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.buf, + ulInformationTransferR8->dedicatedInfoType.choice.dedicatedInfoNAS.size); + } } } } @@ -674,6 +812,78 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( rrcConnectionSetupComplete->dedicatedInfoNAS.buf; S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length = rrcConnectionSetupComplete->dedicatedInfoNAS.size; + // Process NAS message locally to get the IMSI + nas_message_t nas_msg; + memset(&nas_msg, 0, sizeof(nas_message_t)); + + int size = 0; + uint32_t pdu_len = S1AP_NAS_FIRST_REQ (message_p).nas_pdu.length; + uint8_t *pdu_buff = malloc(pdu_len * sizeof(uint8_t)); + memcpy(pdu_buff, S1AP_NAS_FIRST_REQ (message_p).nas_pdu.buffer, pdu_len * sizeof(uint8_t)); + + nas_message_security_header_t *header = &nas_msg.header; + /* Decode the first octet of the header (security header type or EPS + * bearer identity, and protocol discriminator) */ + DECODE_U8((char *) pdu_buff, *(uint8_t*) (header), size); + + /* Decode NAS message */ + if (header->security_header_type <= SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED && + header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE && + pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE) { + + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { + /* Decode the message authentication code */ + DECODE_U32((char *) pdu_buff+size, header->message_authentication_code, size); + /* Decode the sequence number */ + DECODE_U8((char *) pdu_buff+size, header->sequence_number, size); + } + + if (size > 1) { + pdu_buff += size; + pdu_len -= size; + } + + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + + /* First decode the EMM message header */ + int e_head_size = 0; + + /* Check the buffer length */ + if (pdu_len > sizeof(emm_msg_header_t)) { + + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buff + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* Decode the message type */ + DECODE_U8(pdu_buff + e_head_size, emm_header->message_type, e_head_size); + + /* Check the protocol discriminator */ + if (emm_header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) { + + pdu_buff += e_head_size; + pdu_len -= e_head_size; + + if (emm_header->message_type == ATTACH_REQUEST) { + decode_attach_request(&e_msg->attach_request, pdu_buff, pdu_len); + + if (e_msg->attach_request.oldgutiorimsi.imsi.typeofidentity == MOBILE_IDENTITY_IMSI) { + /* the following is very dirty, we cast from + * ImsiEpsMobileIdentity_t to ImsiMobileIdentity_t*/ + ue_context_pP->ue_context.imsi = compute_imsi((ImsiMobileIdentity_t *)&(e_msg->attach_request.oldgutiorimsi.imsi)); + } else { + ue_context_pP->ue_context.imsi = e_msg->attach_request.oldgutiorimsi.guti.mtmsi; + } + } + pdu_buff -= e_head_size; + if (size > 1) { + pdu_buff -= size; + } + } + } + } + free(pdu_buff); + /* Fill UE identities with available information */ { S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask = UE_IDENTITIES_NONE;