Files
open5gs/lib/message/nas/nas_decoder.c
Sukchan Lee a9a9ea92dc update it
2017-02-17 11:41:46 +09:00

324 lines
14 KiB
C

#define TRACE_MODULE _nasdec
#include "core_debug.h"
#include "nas_message.h"
c_int32_t nas_decode_attach_request(nas_message_t *message, pkbuf_t *pkbuf)
{
nas_attach_request_t *attach_request = &message->emm.attach_request;
c_uint16_t decoded = 0;
c_int32_t size = 0;
size = nas_decode_attach_type(&attach_request->attach_type, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
decoded += size;
size = nas_decode_eps_mobile_identity(
&attach_request->eps_mobile_identity, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
decoded += size;
size = nas_decode_ue_network_capability(
&attach_request->ue_network_capability, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
decoded += size;
size = nas_decode_esm_message_container(
&attach_request->esm_message_container, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
decoded += size;
while(pkbuf->len > 0)
{
c_uint8_t *buffer = pkbuf->payload;
c_uint8_t type = (*buffer) >= 0x80 ? ((*buffer) & 0xf0) : (*buffer);
size = sizeof(c_uint8_t);
d_assert(pkbuf_header(pkbuf, -size) == CORE_OK, return -1,
"pkbuf_header error");
decoded += size;
switch(type)
{
case NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_TYPE:
size = nas_decode_p_tmsi_signature(
&attach_request->old_p_tmsi_signature, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_OLD_P_TMSI_SIGNATURE_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_TYPE:
size = nas_decode_eps_mobile_identity(
&attach_request->additional_guti, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_ADDITIONAL_GUTI_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE:
size = nas_decode_tracking_area_identity(
&attach_request->last_visited_registered_tai, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_TYPE;
decoded += size;
break;
case NAS_ATTACH_REQUEST_DRX_PARAMETER_TYPE:
size = nas_decode_drx_parameter(
&attach_request->drx_parameter, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_DRX_PARAMETER_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_MS_NETWORK_CAPABILITY_TYPE:
size = nas_decode_ms_network_capability(
&attach_request->ms_network_capability, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_TYPE:
size = nas_decode_location_area_identification(
&attach_request->old_location_area_identification, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_OLD_LOCATION_AREA_IDENTIFICATION_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_TMSI_STATUS_TYPE:
size = nas_decode_tmsi_status(
&attach_request->tmsi_status, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_TMSI_STATUS_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_TYPE:
size = nas_decode_mobile_station_classmark_2(
&attach_request->mobile_station_classmark_2, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_2_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_TYPE:
size = nas_decode_mobile_station_classmark_3(
&attach_request->mobile_station_classmark_3, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_MOBILE_STATION_CLASSMARK_3_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_SUPPORTED_CODECS_TYPE:
size = nas_decode_supported_codec_list(
&attach_request->supported_codecs, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_SUPPORTED_CODECS_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_TYPE:
size = nas_decode_additional_update_type(
&attach_request->additional_update_type, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_ADDITIONAL_UPDATE_TYPE_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_TYPE:
size = nas_decode_voice_domain_preference_and_ue_usage_setting(
&attach_request->voice_domain_preference_and_ue_usage_setting, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_VOICE_DOMAIN_PREFERENCE_AND_UE_USAGE_SETTING_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_TYPE:
size = nas_decode_device_properties(
&attach_request->device_properties, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_DEVICE_PROPERTIES_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_TYPE:
size = nas_decode_guti_type(
&attach_request->old_guti_type, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_OLD_GUTI_TYPE_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_TYPE:
size = nas_decode_ms_network_feature_support(
&attach_request->ms_network_feature_support, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_MS_NETWORK_FEATURE_SUPPORT_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_TYPE:
size = nas_decode_network_resource_identifier_container(
&attach_request->tmsi_based_nri_container, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_TMSI_BASED_NRI_CONTAINER_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_T3324_VALUE_TYPE:
size = nas_decode_gprs_timer_2(
&attach_request->t3324_value, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_T3324_VALUE_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_TYPE:
size = nas_decode_gprs_timer_3(
&attach_request->t3412_extended_value, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_T3412_EXTENDED_VALUE_PRESENT;
decoded += size;
break;
case NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_TYPE:
size = nas_decode_extended_drx_parameters(
&attach_request->extended_drx_parameters, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
attach_request->presencemask |=
NAS_ATTACH_REQUEST_EXTENDED_DRX_PARAMETERS_PRESENT;
decoded += size;
break;
default:
d_error("Unknown type(0x%x) or not implemented\n", type);
return -1;
}
}
return decoded;
}
c_int32_t nas_decode_attach_complete(nas_message_t *message, pkbuf_t *pkbuf)
{
nas_attach_complete_t *attach_complete = &message->emm.attach_complete;
c_uint16_t decoded = 0;
c_int32_t size = 0;
size = nas_decode_esm_message_container(
&attach_complete->esm_message_container, pkbuf);
d_assert(size >= 0, return -1, "decode failed");
decoded += size;
return decoded;
}
status_t nas_decode_pdu(nas_message_t *message, pkbuf_t *pkbuf)
{
status_t rv = CORE_ERROR;
nas_security_header_t *security_header = NULL;
c_uint16_t size = 0;
c_uint16_t decoded = 0;
d_assert(pkbuf, return CORE_ERROR, "Null param");
d_assert(pkbuf->payload, return CORE_ERROR, "Null param");
security_header = pkbuf->payload;
if (security_header->security_header_type !=
NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE)
{
size = sizeof(nas_security_header_t);
d_assert(pkbuf_header(pkbuf, -size) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
decoded += size;
}
memset(message, 0, sizeof(nas_message_t));
size = sizeof(nas_header_t);
d_assert(pkbuf_header(pkbuf, -size) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
memcpy(&message->h, pkbuf->payload - size, size);
decoded += size;
switch(message->h.message_type)
{
case NAS_ATTACH_REQUEST:
size = nas_decode_attach_request(message, pkbuf);
d_assert(size >= CORE_OK, return CORE_ERROR, "decode error");
decoded += size;
break;
case NAS_ATTACH_ACCEPT:
d_error("Not implemented");
return CORE_ERROR;
case NAS_ATTACH_COMPLETE:
size = nas_decode_attach_complete(message, pkbuf);
d_assert(size >= CORE_OK, return CORE_ERROR, "decode error");
decoded += size;
break;
case NAS_ATTACH_REJECT:
case NAS_DETACH_REQUEST:
case NAS_DETACH_ACCEPT:
case NAS_TRACKING_AREA_UPDATE_REQUEST:
case NAS_TRACKING_AREA_UPDATE_ACCEPT:
case NAS_TRACKING_AREA_UPDATE_COMPLETE:
case NAS_TRACKING_AREA_UPDATE_REJECT:
case NAS_EXTENDED_SERVICE_REQUEST:
case NAS_SERVICE_REJECT:
case NAS_GUTI_REALLOCATION_COMMAND:
case NAS_GUTI_REALLOCATION_COMPLETE:
case NAS_AUTHENTICATION_REQUEST:
case NAS_AUTHENTICATION_RESPONSE:
case NAS_AUTHENTICATION_REJECT:
case NAS_AUTHENTICATION_FAILURE:
case NAS_IDENTITY_REQUEST:
case NAS_IDENTITY_RESPONSE:
case NAS_SECURITY_MODE_COMMAND:
case NAS_SECURITY_MODE_COMPLETE:
case NAS_SECURITY_MODE_REJECT:
case NAS_EMM_STATUS:
case NAS_EMM_INFORMATION:
case NAS_DOWNLINK_NAS_TRANSPORT:
case NAS_UPLINK_NAS_TRANSPORT:
case NAS_CS_SERVICE_NOTIFICATION:
case NAS_DOWNLINK_GENERIC_NAS_TRANSPORT:
case NAS_UPLINK_GENERIC_NAS_TRANSPORT:
case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST:
case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
case NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT:
case NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST:
case NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT:
case NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT:
case NAS_MODIFY_EPS_BEARER_CONTEXT_REQUEST:
case NAS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT:
case NAS_MODIFY_EPS_BEARER_CONTEXT_REJECT:
case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST:
case NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT:
case NAS_PDN_CONNECTIVITY_REQUEST:
case NAS_PDN_CONNECTIVITY_REJECT:
case NAS_PDN_DISCONNECT_REQUEST:
case NAS_PDN_DISCONNECT_REJECT:
case NAS_BEARER_RESOURCE_ALLOCATION_REQUEST:
case NAS_BEARER_RESOURCE_ALLOCATION_REJECT:
case NAS_BEARER_RESOURCE_MODIFICATION_REQUEST:
case NAS_BEARER_RESOURCE_MODIFICATION_REJECT:
case NAS_ESM_INFORMATION_REQUEST:
case NAS_ESM_INFORMATION_RESPONSE:
case NAS_ESM_STATUS:
default:
d_error("Unknown message type (%d) or not implemented",
message->h.message_type);
break;
}
rv = pkbuf_header(pkbuf, decoded);
d_assert(rv == CORE_OK, return CORE_ERROR, "pkbuf_header error");
return CORE_OK;
}