mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10467 lines
348 KiB
C++
10467 lines
348 KiB
C++
/**
|
|
*
|
|
* \section COPYRIGHT
|
|
*
|
|
* Copyright 2014-2015 Ben Wojtowicz
|
|
* 2016-2020 Software Radio Systems Limited
|
|
*
|
|
* By using this file, you agree to the terms and conditions set
|
|
* forth in the LICENSE file which can be found at the top level of
|
|
* the distribution.
|
|
*
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
INCLUDES
|
|
*******************************************************************************/
|
|
|
|
#include "srsran/asn1/liblte_mme.h"
|
|
#include "srsran/common/liblte_security.h"
|
|
|
|
/*******************************************************************************
|
|
DEFINES
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
TYPEDEFS
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
GLOBAL VARIABLES
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
INFORMATION ELEMENT FUNCTIONS
|
|
*******************************************************************************/
|
|
|
|
/*********************************************************************
|
|
IE Name: Additional Information
|
|
|
|
Description: Provides additional information to upper layers in
|
|
relation to the generic NAS message transport
|
|
mechanism.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.0
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_additional_information_ie(LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT* add_info,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (add_info != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = add_info->N_octets;
|
|
for (i = 0; i < add_info->N_octets; i++) {
|
|
(*ie_ptr)[1 + i] = add_info->info[i];
|
|
}
|
|
*ie_ptr += add_info->N_octets + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_information_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_ADDITIONAL_INFORMATION_STRUCT* add_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && add_info != NULL) {
|
|
add_info->N_octets = (*ie_ptr)[0];
|
|
for (i = 0; i < add_info->N_octets; i++) {
|
|
add_info->info[i] = (*ie_ptr)[1 + i];
|
|
}
|
|
*ie_ptr += add_info->N_octets + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Device Properties
|
|
|
|
Description: Indicates if the UE is configured for NAS signalling
|
|
low priority.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.0A
|
|
24.008 v10.2.0 Section 10.5.7.8
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_device_properties_ie(LIBLTE_MME_DEVICE_PROPERTIES_ENUM device_props, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= device_props << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_device_properties_ie(uint8** ie_ptr,
|
|
uint8 bit_offset,
|
|
LIBLTE_MME_DEVICE_PROPERTIES_ENUM* device_props)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && device_props != NULL) {
|
|
*device_props = (LIBLTE_MME_DEVICE_PROPERTIES_ENUM)((**ie_ptr >> bit_offset) & 0x01);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Bearer Context Status
|
|
|
|
Description: Indicates the state of each EPS bearer context that
|
|
can be identified by an EPS bearer identity.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_bearer_context_status_ie(LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT* ebcs,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ebcs != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 2;
|
|
(*ie_ptr)[1] = (ebcs->ebi[7] << 7);
|
|
(*ie_ptr)[1] |= (ebcs->ebi[6] << 6);
|
|
(*ie_ptr)[1] |= (ebcs->ebi[5] << 5);
|
|
(*ie_ptr)[2] = (ebcs->ebi[15] << 7);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[14] << 6);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[13] << 5);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[12] << 4);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[11] << 3);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[10] << 2);
|
|
(*ie_ptr)[2] |= (ebcs->ebi[9] << 1);
|
|
(*ie_ptr)[2] |= ebcs->ebi[8];
|
|
*ie_ptr += 3;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_bearer_context_status_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_STRUCT* ebcs)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ebcs != NULL) {
|
|
ebcs->ebi[5] = ((*ie_ptr)[1] >> 5) & 0x01;
|
|
ebcs->ebi[6] = ((*ie_ptr)[1] >> 6) & 0x01;
|
|
ebcs->ebi[7] = ((*ie_ptr)[1] >> 7) & 0x01;
|
|
ebcs->ebi[8] = (*ie_ptr)[2] & 0x01;
|
|
ebcs->ebi[9] = ((*ie_ptr)[2] >> 1) & 0x01;
|
|
ebcs->ebi[10] = ((*ie_ptr)[2] >> 2) & 0x01;
|
|
ebcs->ebi[11] = ((*ie_ptr)[2] >> 3) & 0x01;
|
|
ebcs->ebi[12] = ((*ie_ptr)[2] >> 4) & 0x01;
|
|
ebcs->ebi[13] = ((*ie_ptr)[2] >> 5) & 0x01;
|
|
ebcs->ebi[14] = ((*ie_ptr)[2] >> 6) & 0x01;
|
|
ebcs->ebi[15] = ((*ie_ptr)[2] >> 7) & 0x01;
|
|
*ie_ptr += 3;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Location Area Identification
|
|
|
|
Description: Provides an unambiguous identification of location
|
|
areas within the area covered by the 3GPP system.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.2
|
|
24.008 v10.2.0 Section 10.5.1.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_location_area_id_ie(LIBLTE_MME_LOCATION_AREA_ID_STRUCT* lai, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (lai != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (((lai->mcc / 10) % 10) << 4) | ((lai->mcc / 100) % 10);
|
|
if (lai->mnc < 100) {
|
|
(*ie_ptr)[1] = 0xF0 | (lai->mcc % 10);
|
|
(*ie_ptr)[2] = ((lai->mnc % 10) << 4) | ((lai->mnc / 10) % 10);
|
|
} else {
|
|
(*ie_ptr)[1] = ((lai->mnc % 10) << 4) | (lai->mcc % 10);
|
|
(*ie_ptr)[2] = (((lai->mnc / 10) % 10) << 4) | ((lai->mnc / 100) % 10);
|
|
}
|
|
(*ie_ptr)[3] = (lai->lac >> 8) & 0xFF;
|
|
(*ie_ptr)[4] = lai->lac & 0xFF;
|
|
*ie_ptr += 5;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_location_area_id_ie(uint8** ie_ptr, LIBLTE_MME_LOCATION_AREA_ID_STRUCT* lai)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && lai != NULL) {
|
|
lai->mcc = ((*ie_ptr)[0] & 0x0F) * 100;
|
|
lai->mcc += (((*ie_ptr)[0] >> 4) & 0x0F) * 10;
|
|
lai->mcc += (*ie_ptr)[1] & 0x0F;
|
|
if ((((*ie_ptr)[1] >> 4) & 0x0F) == 0x0F) {
|
|
lai->mnc = ((*ie_ptr)[2] & 0x0F) * 10;
|
|
lai->mnc += ((*ie_ptr)[2] >> 4) & 0x0F;
|
|
} else {
|
|
lai->mnc = ((*ie_ptr)[1] >> 4) & 0x0F;
|
|
lai->mnc += ((*ie_ptr)[2] & 0x0F) * 100;
|
|
lai->mnc += (((*ie_ptr)[2] >> 4) & 0x0F) * 10;
|
|
}
|
|
lai->lac = (*ie_ptr)[3] << 8;
|
|
lai->lac |= (*ie_ptr)[4];
|
|
*ie_ptr += 5;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobile Identity
|
|
|
|
Description: Provides either the IMSI, TMSI/P-TMSI/M-TMSI, IMEI,
|
|
IMEISV, or TMGI, associated with the optional MBMS
|
|
session identity.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.3
|
|
24.008 v10.2.0 Section 10.5.1.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_id_ie(LIBLTE_MME_MOBILE_ID_STRUCT* mobile_id, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* id = NULL;
|
|
uint32 id32 = 0;
|
|
uint32 i;
|
|
uint8 length = 0;
|
|
bool odd = false;
|
|
|
|
if (mobile_id != NULL && ie_ptr != NULL) {
|
|
if (LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id) {
|
|
id = mobile_id->imsi;
|
|
length = 8;
|
|
odd = true;
|
|
} else if (LIBLTE_MME_MOBILE_ID_TYPE_IMEI == mobile_id->type_of_id) {
|
|
id = mobile_id->imei;
|
|
length = 8;
|
|
odd = true;
|
|
} else if (LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == mobile_id->type_of_id) {
|
|
id = mobile_id->imeisv;
|
|
length = 9;
|
|
odd = false;
|
|
} else if (LIBLTE_MME_MOBILE_ID_TYPE_TMSI == mobile_id->type_of_id) {
|
|
id32 = mobile_id->tmsi;
|
|
length = 5;
|
|
odd = false;
|
|
}
|
|
} else {
|
|
// TODO: Not handling these IDs
|
|
return (err);
|
|
}
|
|
|
|
// Length
|
|
**ie_ptr = length;
|
|
*ie_ptr += 1;
|
|
if (LIBLTE_MME_MOBILE_ID_TYPE_TMSI != mobile_id->type_of_id) {
|
|
// | Identity digit 1 | odd/even | Id type |
|
|
if (odd) {
|
|
**ie_ptr = (id[0] << 4) | (1 << 3) | mobile_id->type_of_id;
|
|
} else {
|
|
**ie_ptr = (id[0] << 4) | (0 << 3) | mobile_id->type_of_id;
|
|
}
|
|
*ie_ptr += 1;
|
|
|
|
// | Identity digit p+1 | Identity digit p |
|
|
for (i = 0; i < 7; i++) {
|
|
(*ie_ptr)[i] = (id[i * 2 + 2] << 4) | id[i * 2 + 1];
|
|
}
|
|
*ie_ptr += 7;
|
|
if (!odd) {
|
|
**ie_ptr = 0xF0 | id[15];
|
|
*ie_ptr += 1;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
} else {
|
|
**ie_ptr = (0xFF << 4) | (0 << 3) | mobile_id->type_of_id;
|
|
*ie_ptr += 1;
|
|
// 4-Byte based ids
|
|
**ie_ptr = (id32 >> 24) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (id32 >> 16) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (id32 >> 8) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = id32 & 0xFF;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_id_ie(uint8** ie_ptr, LIBLTE_MME_MOBILE_ID_STRUCT* mobile_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* id;
|
|
uint32 length;
|
|
uint32 i;
|
|
bool odd = false;
|
|
|
|
if (ie_ptr != NULL && mobile_id != NULL) {
|
|
length = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
|
|
mobile_id->type_of_id = **ie_ptr & 0x07;
|
|
|
|
if (LIBLTE_MME_MOBILE_ID_TYPE_IMSI == mobile_id->type_of_id) {
|
|
id = mobile_id->imsi;
|
|
odd = true;
|
|
} else if (LIBLTE_MME_MOBILE_ID_TYPE_IMEI == mobile_id->type_of_id) {
|
|
id = mobile_id->imei;
|
|
odd = true;
|
|
} else if (LIBLTE_MME_MOBILE_ID_TYPE_IMEISV == mobile_id->type_of_id) {
|
|
id = mobile_id->imeisv;
|
|
odd = false;
|
|
} else {
|
|
// TODO: Not handling these IDs
|
|
return (err);
|
|
}
|
|
|
|
id[0] = **ie_ptr >> 4;
|
|
*ie_ptr += 1;
|
|
for (i = 0; i < 7; i++) {
|
|
id[i * 2 + 1] = (*ie_ptr)[i] & 0x0F;
|
|
id[i * 2 + 2] = (*ie_ptr)[i] >> 4;
|
|
}
|
|
if (odd) {
|
|
*ie_ptr += 7;
|
|
} else {
|
|
id[i * 2 + 1] = (*ie_ptr)[i] & 0xF;
|
|
*ie_ptr += 8;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobile Station Classmark 2
|
|
|
|
Description: Provides the network with information concerning
|
|
aspects of both high and low priority of the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.4
|
|
24.008 v10.2.0 Section 10.5.1.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_2_ie(LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT* ms_cm2,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ms_cm2 != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 3;
|
|
(*ie_ptr)[1] = (ms_cm2->rev_lev & 0x03) << 5;
|
|
(*ie_ptr)[1] |= ms_cm2->es_ind << 4;
|
|
(*ie_ptr)[1] |= ms_cm2->a5_1 << 3;
|
|
(*ie_ptr)[1] |= ms_cm2->rf_power_cap & 0x07;
|
|
(*ie_ptr)[2] = ms_cm2->ps_cap << 6;
|
|
(*ie_ptr)[2] |= (ms_cm2->ss_screen_ind & 0x03) << 4;
|
|
(*ie_ptr)[2] |= ms_cm2->sm_cap << 3;
|
|
(*ie_ptr)[2] |= ms_cm2->vbs << 2;
|
|
(*ie_ptr)[2] |= ms_cm2->vgcs << 1;
|
|
(*ie_ptr)[2] |= ms_cm2->fc;
|
|
(*ie_ptr)[3] = ms_cm2->cm3 << 7;
|
|
(*ie_ptr)[3] |= ms_cm2->lcsva_cap << 5;
|
|
(*ie_ptr)[3] |= ms_cm2->ucs2 << 4;
|
|
(*ie_ptr)[3] |= ms_cm2->solsa << 3;
|
|
(*ie_ptr)[3] |= ms_cm2->cmsp << 2;
|
|
(*ie_ptr)[3] |= ms_cm2->a5_3 << 1;
|
|
(*ie_ptr)[3] |= ms_cm2->a5_2;
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_2_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_MOBILE_STATION_CLASSMARK_2_STRUCT* ms_cm2)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ms_cm2 != NULL) {
|
|
ms_cm2->rev_lev = (LIBLTE_MME_REVISION_LEVEL_ENUM)(((*ie_ptr)[1] >> 5) & 0x03);
|
|
ms_cm2->es_ind = ((*ie_ptr)[1] >> 4) & 0x01;
|
|
ms_cm2->a5_1 = ((*ie_ptr)[1] >> 3) & 0x01;
|
|
ms_cm2->rf_power_cap = (LIBLTE_MME_RF_POWER_CAPABILITY_ENUM)((*ie_ptr)[1] & 0x07);
|
|
ms_cm2->ps_cap = ((*ie_ptr)[2] >> 6) & 0x01;
|
|
ms_cm2->ss_screen_ind = (LIBLTE_MME_SS_SCREEN_INDICATOR_ENUM)(((*ie_ptr)[2] >> 4) & 0x03);
|
|
ms_cm2->sm_cap = ((*ie_ptr)[2] >> 3) & 0x01;
|
|
ms_cm2->vbs = ((*ie_ptr)[2] >> 2) & 0x01;
|
|
ms_cm2->vgcs = ((*ie_ptr)[2] >> 1) & 0x01;
|
|
ms_cm2->fc = (*ie_ptr)[2] & 0x01;
|
|
ms_cm2->cm3 = ((*ie_ptr)[3] >> 7) & 0x01;
|
|
ms_cm2->lcsva_cap = ((*ie_ptr)[3] >> 5) & 0x01;
|
|
ms_cm2->ucs2 = ((*ie_ptr)[3] >> 4) & 0x01;
|
|
ms_cm2->solsa = ((*ie_ptr)[3] >> 3) & 0x01;
|
|
ms_cm2->cmsp = ((*ie_ptr)[3] >> 2) & 0x01;
|
|
ms_cm2->a5_3 = ((*ie_ptr)[3] >> 1) & 0x01;
|
|
ms_cm2->a5_2 = (*ie_ptr)[3] & 0x01;
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobile Station Classmark 3
|
|
|
|
Description: Provides the network with information concerning
|
|
aspects of the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.5
|
|
24.008 v10.2.0 Section 10.5.1.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_mobile_station_classmark_3_ie(LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT* ms_cm3,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ms_cm3 != NULL && ie_ptr != NULL) {
|
|
// TODO
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_mobile_station_classmark_3_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_MOBILE_STATION_CLASSMARK_3_STRUCT* ms_cm3)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ms_cm3 != NULL) {
|
|
// TODO
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: NAS Security Parameters From E-UTRA
|
|
|
|
Description: Provides the UE with information that enables the UE
|
|
to create a mapped UMTS security context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_parameters_from_eutra_ie(uint8 dl_nas_count, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = dl_nas_count & 0x0F;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_parameters_from_eutra_ie(uint8** ie_ptr, uint8* dl_nas_count)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && dl_nas_count != NULL) {
|
|
*dl_nas_count = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: NAS Security Parameters To E-UTRA
|
|
|
|
Description: Provides the UE with parameters that enables the UE
|
|
to create a mapped EPS security context and take
|
|
this context into use after inter-system handover to
|
|
S1 mode.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_nas_security_parameters_to_eutra_ie(LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT* sec_params,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (sec_params != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (sec_params->nonce_mme >> 24) & 0xFF;
|
|
(*ie_ptr)[1] = (sec_params->nonce_mme >> 16) & 0xFF;
|
|
(*ie_ptr)[2] = (sec_params->nonce_mme >> 8) & 0xFF;
|
|
(*ie_ptr)[3] = sec_params->nonce_mme & 0xFF;
|
|
(*ie_ptr)[4] = (sec_params->eea & 0x07) << 4;
|
|
(*ie_ptr)[4] |= sec_params->eia & 0x07;
|
|
(*ie_ptr)[5] = (sec_params->tsc_flag & 0x01) << 3;
|
|
(*ie_ptr)[5] |= sec_params->nas_ksi & 0x07;
|
|
*ie_ptr += 6;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_nas_security_parameters_to_eutra_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_NAS_SECURITY_PARAMETERS_TO_EUTRA_STRUCT* sec_params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && sec_params != NULL) {
|
|
sec_params->nonce_mme = (*ie_ptr)[0] << 24;
|
|
sec_params->nonce_mme |= (*ie_ptr)[1] << 16;
|
|
sec_params->nonce_mme |= (*ie_ptr)[2] << 8;
|
|
sec_params->nonce_mme |= (*ie_ptr)[3];
|
|
sec_params->eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM)(((*ie_ptr)[4] >> 4) & 0x07);
|
|
sec_params->eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM)((*ie_ptr)[4] & 0x07);
|
|
sec_params->tsc_flag = (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM)(((*ie_ptr)[5] >> 3) & 0x01);
|
|
sec_params->nas_ksi = (*ie_ptr)[5] & 0x07;
|
|
*ie_ptr += 6;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PLMN List
|
|
|
|
Description: Provides a list of PLMN codes to the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.8
|
|
24.008 v10.2.0 Section 10.5.1.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_plmn_list_ie(LIBLTE_MME_PLMN_LIST_STRUCT* plmn_list, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (plmn_list != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = plmn_list->N_plmns * 3;
|
|
for (i = 0; i < plmn_list->N_plmns; i++) {
|
|
(*ie_ptr)[i * 3 + 0] = (((plmn_list->mcc[i] / 10) % 10) << 4) | ((plmn_list->mcc[i] / 100) % 10);
|
|
if (plmn_list->mnc[i] < 100) {
|
|
(*ie_ptr)[i * 3 + 1] = 0xF0 | (plmn_list->mcc[i] % 10);
|
|
(*ie_ptr)[i * 3 + 2] = ((plmn_list->mnc[i] % 10) << 4) | ((plmn_list->mnc[i] / 10) % 10);
|
|
} else {
|
|
(*ie_ptr)[i * 3 + 1] = ((plmn_list->mnc[i] % 10) << 4) | (plmn_list->mcc[i] % 10);
|
|
(*ie_ptr)[i * 3 + 2] = (((plmn_list->mnc[i] / 10) % 10) << 4) | ((plmn_list->mnc[i] / 100) % 10);
|
|
}
|
|
}
|
|
*ie_ptr += (plmn_list->N_plmns * 3) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_plmn_list_ie(uint8** ie_ptr, LIBLTE_MME_PLMN_LIST_STRUCT* plmn_list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && plmn_list != NULL) {
|
|
plmn_list->N_plmns = (*ie_ptr)[0] / 3;
|
|
for (i = 0; i < plmn_list->N_plmns; i++) {
|
|
plmn_list->mcc[i] = ((*ie_ptr)[i * 3 + 0] & 0x0F) * 100;
|
|
plmn_list->mcc[i] += (((*ie_ptr)[i * 3 + 0] >> 4) & 0x0F) * 10;
|
|
plmn_list->mcc[i] += (*ie_ptr)[i * 3 + 1] & 0x0F;
|
|
if ((((*ie_ptr)[i * 3 + 1] >> 4) & 0x0F) == 0x0F) {
|
|
plmn_list->mnc[i] = ((*ie_ptr)[i * 3 + 2] & 0x0F) * 10;
|
|
plmn_list->mnc[i] += ((*ie_ptr)[i * 3 + 2] >> 4) & 0x0F;
|
|
} else {
|
|
plmn_list->mnc[i] = ((*ie_ptr)[i * 3 + 1] >> 4) & 0x0F;
|
|
plmn_list->mnc[i] += ((*ie_ptr)[i * 3 + 2] & 0x0F) * 100;
|
|
plmn_list->mnc[i] += (((*ie_ptr)[i * 3 + 2] >> 4) & 0x0F) * 10;
|
|
}
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Spare Half Octet
|
|
|
|
Description: Used in the description of EMM and ESM messages when
|
|
an odd number of half octet type 1 information
|
|
elements are used.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.9
|
|
*********************************************************************/
|
|
|
|
/*********************************************************************
|
|
IE Name: Supported Codec List
|
|
|
|
Description: Provides the network with information about the
|
|
speech codecs supported by the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.2.10
|
|
24.008 v10.2.0 Section 10.5.4.32
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_supported_codec_list_ie(LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT* supported_codec_list,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (supported_codec_list != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = supported_codec_list->N_supported_codecs * 4;
|
|
for (i = 0; i < supported_codec_list->N_supported_codecs; i++) {
|
|
(*ie_ptr)[1 + i * 4 + 0] = supported_codec_list->supported_codec[i].sys_id;
|
|
(*ie_ptr)[1 + i * 4 + 1] = 2;
|
|
(*ie_ptr)[1 + i * 4 + 2] = (supported_codec_list->supported_codec[i].codec_bitmap >> 8) & 0xFF;
|
|
(*ie_ptr)[1 + i * 4 + 3] = supported_codec_list->supported_codec[i].codec_bitmap & 0xFF;
|
|
}
|
|
*ie_ptr += (supported_codec_list->N_supported_codecs * 4) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_supported_codec_list_ie(uint8** ie_ptr, LIBLTE_MME_SUPPORTED_CODEC_LIST_STRUCT* supported_codec_list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && supported_codec_list != NULL) {
|
|
supported_codec_list->N_supported_codecs = ((*ie_ptr)[0] / 4);
|
|
for (i = 0; i < supported_codec_list->N_supported_codecs; i++) {
|
|
supported_codec_list->supported_codec[i].sys_id = (*ie_ptr)[1 + i * 4 + 0];
|
|
supported_codec_list->supported_codec[i].codec_bitmap = (*ie_ptr)[1 + i * 4 + 2] << 8;
|
|
supported_codec_list->supported_codec[i].codec_bitmap |= (*ie_ptr)[1 + i * 4 + 3];
|
|
}
|
|
*ie_ptr += (supported_codec_list->N_supported_codecs * 4) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Additional Update Result
|
|
|
|
Description: Provides additional information about the result of
|
|
a combined attached procedure or a combined tracking
|
|
area updating procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.0A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_additional_update_result_ie(LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM result,
|
|
uint8 bit_offset,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= result << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_result_ie(uint8** ie_ptr,
|
|
uint8 bit_offset,
|
|
LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM* result)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (result != NULL && ie_ptr != NULL) {
|
|
*result = (LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_ENUM)((**ie_ptr >> bit_offset) & 0x03);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Additional Update Type
|
|
|
|
Description: Provides additional information about the type of
|
|
request for a combined attach or a combined tracking
|
|
area updating procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.0B
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_additional_update_type_ie(LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM aut, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= aut << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_additional_update_type_ie(uint8** ie_ptr,
|
|
uint8 bit_offset,
|
|
LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM* aut)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && aut != NULL) {
|
|
*aut = (LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_ENUM)((**ie_ptr >> bit_offset) & 0x01);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Authentication Failure Parameter
|
|
|
|
Description: Provides the network with the necessary information
|
|
to begin a re-authentication procedure in the case
|
|
of a 'Synch failure', following a UMTS or EPS
|
|
authentication challenge.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.1
|
|
24.008 v10.2.0 Section 10.5.3.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_parameter_ie(uint8* auth_fail_param, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (auth_fail_param != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 14;
|
|
for (i = 0; i < 14; i++) {
|
|
(*ie_ptr)[i + 1] = auth_fail_param[i];
|
|
}
|
|
*ie_ptr += 15;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_parameter_ie(uint8** ie_ptr, uint8* auth_fail_param)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && auth_fail_param != NULL) {
|
|
for (i = 0; i < 14; i++) {
|
|
auth_fail_param[i] = (*ie_ptr)[i + 1];
|
|
}
|
|
*ie_ptr += 15;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Authentication Parameter AUTN
|
|
|
|
Description: Provides the UE with a means of authenticating the
|
|
network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.2
|
|
24.008 v10.2.0 Section 10.5.3.1.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_autn_ie(uint8* autn, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (autn != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 16;
|
|
for (i = 0; i < 16; i++) {
|
|
(*ie_ptr)[i + 1] = autn[i];
|
|
}
|
|
*ie_ptr += 17;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_autn_ie(uint8** ie_ptr, uint8* autn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && autn != NULL) {
|
|
for (i = 0; i < 16; i++) {
|
|
autn[i] = (*ie_ptr)[i + 1];
|
|
}
|
|
*ie_ptr += 17;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Authentication Parameter RAND
|
|
|
|
Description: Provides the UE with a non-predictable number to be
|
|
used to calculate the authentication signature SRES
|
|
and the ciphering key Kc (for a GSM authentication
|
|
challenge), or the response RES and both the
|
|
ciphering key CK and the integrity key IK (for a
|
|
UMTS authentication challenge).
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.3
|
|
24.008 v10.2.0 Section 10.5.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_parameter_rand_ie(uint8* rand_val, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (rand_val != NULL && ie_ptr != NULL) {
|
|
for (i = 0; i < 16; i++) {
|
|
(*ie_ptr)[i] = rand_val[i];
|
|
}
|
|
*ie_ptr += 16;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_parameter_rand_ie(uint8** ie_ptr, uint8* rand_val)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && rand_val != NULL) {
|
|
for (i = 0; i < 16; i++) {
|
|
rand_val[i] = (*ie_ptr)[i];
|
|
}
|
|
*ie_ptr += 16;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Authentication Response Parameter
|
|
|
|
Description: Provides the network with the authentication
|
|
response calculated in the USIM.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_parameter_ie(uint8* res, int res_len, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (res != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = res_len;
|
|
*ie_ptr += 1;
|
|
for (i = 0; i < res_len; i++) {
|
|
(*ie_ptr)[i] = res[i];
|
|
}
|
|
*ie_ptr += res_len;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_response_parameter_ie(uint8** ie_ptr, uint8* res)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && res != NULL) {
|
|
for (i = 0; i < (*ie_ptr)[0]; i++) {
|
|
res[i] = (*ie_ptr)[i + 1];
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Ciphering Key Sequence Number
|
|
|
|
Description: Makes it possible for the network to identify the
|
|
ciphering key Kc which is stored in the UE without
|
|
invoking the authentication procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.4A
|
|
24.008 v10.2.0 Section 10.5.1.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ciphering_key_sequence_number_ie(uint8 key_seq, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (key_seq & 0x07) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_ciphering_key_sequence_number_ie(uint8** ie_ptr, uint8 bit_offset, uint8* key_seq)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && key_seq != NULL) {
|
|
*key_seq = ((*ie_ptr)[0] >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CSFB Response
|
|
|
|
Description: Indicates whether the UE accepts or rejects a paging
|
|
for CS fallback.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_csfb_response_ie(uint8 csfb_resp, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (csfb_resp & 0x07) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_csfb_response_ie(uint8** ie_ptr, uint8 bit_offset, uint8* csfb_resp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && csfb_resp != NULL) {
|
|
*csfb_resp = ((*ie_ptr)[0] & 0x07) >> bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Daylight Saving Time
|
|
|
|
Description: Encodes the daylight saving time in steps of 1 hour.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.6
|
|
24.008 v10.2.0 Section 10.5.3.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_daylight_saving_time_ie(LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM dst, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 1;
|
|
(*ie_ptr)[1] = dst & 0x03;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_daylight_saving_time_ie(uint8** ie_ptr, LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM* dst)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && dst != NULL) {
|
|
*dst = (LIBLTE_MME_DAYLIGHT_SAVING_TIME_ENUM)((*ie_ptr)[1] & 0x03);
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Detach Type
|
|
|
|
Description: Indicates the type of detach.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_detach_type_ie(LIBLTE_MME_DETACH_TYPE_STRUCT* detach_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (detach_type != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (detach_type->switch_off & 0x01) << (3 + bit_offset);
|
|
(*ie_ptr)[0] |= (detach_type->type_of_detach & 0x07) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_detach_type_ie(uint8** ie_ptr, uint8 bit_offset, LIBLTE_MME_DETACH_TYPE_STRUCT* detach_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && detach_type != NULL) {
|
|
detach_type->switch_off = ((*ie_ptr)[0] >> (3 + bit_offset)) & 0x01;
|
|
detach_type->type_of_detach = ((*ie_ptr)[0] >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: DRX Parameter
|
|
|
|
Description: Indicates whether the UE uses DRX mode or not.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.8
|
|
24.008 v10.2.0 Section 10.5.5.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_drx_parameter_ie(LIBLTE_MME_DRX_PARAMETER_STRUCT* drx_param, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (drx_param != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = drx_param->split_pg_cycle_code;
|
|
(*ie_ptr)[1] = (drx_param->drx_cycle_len_coeff_and_value & 0x0F) << 4;
|
|
(*ie_ptr)[1] |= (drx_param->split_on_ccch & 0x01) << 3;
|
|
(*ie_ptr)[1] |= drx_param->non_drx_timer & 0x07;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_drx_parameter_ie(uint8** ie_ptr, LIBLTE_MME_DRX_PARAMETER_STRUCT* drx_param)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && drx_param != NULL) {
|
|
drx_param->split_pg_cycle_code = (*ie_ptr)[0];
|
|
drx_param->drx_cycle_len_coeff_and_value = ((*ie_ptr)[1] >> 4) & 0x0F;
|
|
drx_param->split_on_ccch = ((*ie_ptr)[1] >> 3) & 0x01;
|
|
drx_param->non_drx_timer = (LIBLTE_MME_NON_DRX_TIMER_ENUM)((*ie_ptr)[1] & 0x07);
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EMM Cause
|
|
|
|
Description: Indicates the reason why an EMM request from the UE
|
|
is rejected by the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_emm_cause_ie(uint8 emm_cause, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr = emm_cause;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_cause_ie(uint8** ie_ptr, uint8* emm_cause)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && emm_cause != NULL) {
|
|
*emm_cause = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Attach Result
|
|
|
|
Description: Specifies the result of an attach procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.10
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_result_ie(uint8 result, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= result << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_result_ie(uint8** ie_ptr, uint8 bit_offset, uint8* result)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && result != NULL) {
|
|
*result = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Attach Type
|
|
|
|
Description: Indicates the type of the requested attach.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.11
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_attach_type_ie(uint8 attach_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= attach_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_attach_type_ie(uint8** ie_ptr, uint8 bit_offset, uint8* attach_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && attach_type != NULL) {
|
|
*attach_type = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Mobile Identity
|
|
|
|
Description: Provides either the IMSI, the GUTI, or the IMEI.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_mobile_id_ie(LIBLTE_MME_EPS_MOBILE_ID_STRUCT* eps_mobile_id, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* id;
|
|
uint32 i;
|
|
|
|
if (eps_mobile_id != NULL && ie_ptr != NULL) {
|
|
if (LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) {
|
|
**ie_ptr = 11;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = 0xF0 | eps_mobile_id->type_of_id;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (((eps_mobile_id->guti.mcc / 10) % 10) << 4) | ((eps_mobile_id->guti.mcc / 100) % 10);
|
|
*ie_ptr += 1;
|
|
if (eps_mobile_id->guti.mnc < 100) {
|
|
**ie_ptr = 0xF0 | (eps_mobile_id->guti.mcc % 10);
|
|
*ie_ptr += 1;
|
|
**ie_ptr = ((eps_mobile_id->guti.mnc % 10) << 4) | ((eps_mobile_id->guti.mnc / 10) % 10);
|
|
*ie_ptr += 1;
|
|
} else {
|
|
**ie_ptr = ((eps_mobile_id->guti.mnc % 10) << 4) | (eps_mobile_id->guti.mcc % 10);
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (((eps_mobile_id->guti.mnc / 10) % 10) << 4) | ((eps_mobile_id->guti.mnc / 100) % 10);
|
|
*ie_ptr += 1;
|
|
}
|
|
**ie_ptr = (eps_mobile_id->guti.mme_group_id >> 8) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = eps_mobile_id->guti.mme_group_id & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = eps_mobile_id->guti.mme_code;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (eps_mobile_id->guti.m_tmsi >> 24) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (eps_mobile_id->guti.m_tmsi >> 16) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (eps_mobile_id->guti.m_tmsi >> 8) & 0xFF;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = eps_mobile_id->guti.m_tmsi & 0xFF;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
if (LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) {
|
|
id = eps_mobile_id->imsi;
|
|
} else {
|
|
id = eps_mobile_id->imei;
|
|
}
|
|
|
|
**ie_ptr = 8;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = (id[0] << 4) | (1 << 3) | eps_mobile_id->type_of_id;
|
|
*ie_ptr += 1;
|
|
for (i = 0; i < 7; i++) {
|
|
**ie_ptr = (id[i * 2 + 2] << 4) | id[i * 2 + 1];
|
|
*ie_ptr += 1;
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_mobile_id_ie(uint8** ie_ptr, LIBLTE_MME_EPS_MOBILE_ID_STRUCT* eps_mobile_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* id;
|
|
uint32 length;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && eps_mobile_id != NULL) {
|
|
length = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
|
|
eps_mobile_id->type_of_id = **ie_ptr & 0x07;
|
|
|
|
if (LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI == eps_mobile_id->type_of_id) {
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mcc = (**ie_ptr & 0x0F) * 100;
|
|
eps_mobile_id->guti.mcc += ((**ie_ptr >> 4) & 0x0F) * 10;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mcc += **ie_ptr & 0x0F;
|
|
if (((**ie_ptr >> 4) & 0x0F) == 0x0F) {
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mnc = (**ie_ptr & 0x0F) * 10;
|
|
eps_mobile_id->guti.mnc += (**ie_ptr >> 4) & 0x0F;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
eps_mobile_id->guti.mnc = (**ie_ptr >> 4) & 0x0F;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mnc += (**ie_ptr & 0x0F) * 100;
|
|
eps_mobile_id->guti.mnc += ((**ie_ptr >> 4) & 0x0F) * 10;
|
|
*ie_ptr += 1;
|
|
}
|
|
eps_mobile_id->guti.mme_group_id = **ie_ptr << 8;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mme_group_id |= **ie_ptr;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.mme_code = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.m_tmsi = **ie_ptr << 24;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.m_tmsi |= **ie_ptr << 16;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.m_tmsi |= **ie_ptr << 8;
|
|
*ie_ptr += 1;
|
|
eps_mobile_id->guti.m_tmsi |= **ie_ptr;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
if (LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI == eps_mobile_id->type_of_id) {
|
|
id = eps_mobile_id->imsi;
|
|
} else {
|
|
id = eps_mobile_id->imei;
|
|
}
|
|
|
|
id[0] = **ie_ptr >> 4;
|
|
*ie_ptr += 1;
|
|
for (i = 0; i < 7; i++) {
|
|
id[i * 2 + 1] = **ie_ptr & 0x0F;
|
|
id[i * 2 + 2] = **ie_ptr >> 4;
|
|
*ie_ptr += 1;
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Network Feature Support
|
|
|
|
Description: Indicates whether certain features are supported by
|
|
the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.12A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_network_feature_support_ie(LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT* eps_nfs,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (eps_nfs != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 1;
|
|
(*ie_ptr)[1] = eps_nfs->esrps << 5;
|
|
(*ie_ptr)[1] |= (eps_nfs->cs_lcs & 0x03) << 3;
|
|
(*ie_ptr)[1] |= eps_nfs->epc_lcs << 2;
|
|
(*ie_ptr)[1] |= eps_nfs->emc_bs << 1;
|
|
(*ie_ptr)[1] |= eps_nfs->ims_vops;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_eps_network_feature_support_ie(uint8** ie_ptr, LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_STRUCT* eps_nfs)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && eps_nfs != NULL) {
|
|
eps_nfs->esrps = ((*ie_ptr)[1] >> 5) & 0x01;
|
|
eps_nfs->cs_lcs = (LIBLTE_MME_CS_LCS_ENUM)(((*ie_ptr)[1] >> 3) & 0x03);
|
|
eps_nfs->epc_lcs = ((*ie_ptr)[1] >> 2) & 0x01;
|
|
eps_nfs->emc_bs = ((*ie_ptr)[1] >> 1) & 0x01;
|
|
eps_nfs->ims_vops = (*ie_ptr)[1] & 0x01;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Update Result
|
|
|
|
Description: Specifies the result of the associated updating
|
|
procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_update_result_ie(uint8 eps_update_res, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (eps_update_res & 0x07) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_result_ie(uint8** ie_ptr, uint8 bit_offset, uint8* eps_update_res)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && eps_update_res != NULL) {
|
|
*eps_update_res = ((*ie_ptr)[0] >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Update Type
|
|
|
|
Description: Specifies the area the updating procedure is
|
|
associated with.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.14
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_eps_update_type_ie(LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT* eps_update_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (eps_update_type != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (eps_update_type->active_flag & 0x01) << (bit_offset + 3);
|
|
(*ie_ptr)[0] |= (eps_update_type->type & 0x07) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_update_type_ie(uint8** ie_ptr,
|
|
uint8 bit_offset,
|
|
LIBLTE_MME_EPS_UPDATE_TYPE_STRUCT* eps_update_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && eps_update_type != NULL) {
|
|
eps_update_type->active_flag = ((*ie_ptr)[0] >> (bit_offset + 3)) & 0x01;
|
|
eps_update_type->type = (LIBLTE_MME_EPS_UPDATE_TYPE_ENUM)(((*ie_ptr)[0] >> bit_offset) & 0x07);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ESM Message Container
|
|
|
|
Description: Enables piggybacked transfer of a single ESM message
|
|
within an EMM message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.15
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_esm_message_container_ie(LIBLTE_BYTE_MSG_STRUCT* esm_msg, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (esm_msg != NULL && ie_ptr != NULL && esm_msg->N_bytes <= LIBLTE_MAX_MSG_SIZE_BYTES) {
|
|
(*ie_ptr)[0] = esm_msg->N_bytes >> 8;
|
|
(*ie_ptr)[1] = esm_msg->N_bytes & 0xFF;
|
|
for (i = 0; i < esm_msg->N_bytes; i++) {
|
|
(*ie_ptr)[2 + i] = esm_msg->msg[i];
|
|
}
|
|
*ie_ptr += esm_msg->N_bytes + 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_message_container_ie(uint8** ie_ptr, LIBLTE_BYTE_MSG_STRUCT* esm_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && esm_msg != NULL) {
|
|
esm_msg->N_bytes = (*ie_ptr)[0] << 8;
|
|
esm_msg->N_bytes |= (*ie_ptr)[1];
|
|
|
|
if (esm_msg->N_bytes > LIBLTE_MAX_MSG_SIZE_BYTES) {
|
|
return err;
|
|
}
|
|
|
|
for (i = 0; i < esm_msg->N_bytes; i++) {
|
|
esm_msg->msg[i] = (*ie_ptr)[2 + i];
|
|
}
|
|
*ie_ptr += esm_msg->N_bytes + 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: GPRS Timer
|
|
|
|
Description: Specifies GPRS specific timer values.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.16
|
|
24.008 v10.2.0 Section 10.5.7.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_ie(LIBLTE_MME_GPRS_TIMER_STRUCT* timer, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (timer != NULL && ie_ptr != NULL) {
|
|
**ie_ptr = ((timer->unit & 0x07) << 5) | (timer->value & 0x1F);
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_ie(uint8** ie_ptr, LIBLTE_MME_GPRS_TIMER_STRUCT* timer)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && timer != NULL) {
|
|
timer->unit = **ie_ptr >> 5;
|
|
timer->value = **ie_ptr & 0x1F;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: GPRS Timer 2
|
|
|
|
Description: Specifies GPRS specific timer values.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.16A
|
|
24.008 v10.2.0 Section 10.5.7.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_2_ie(uint8 value, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr = 1;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = value;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_2_ie(uint8** ie_ptr, uint8* value)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && value != NULL) {
|
|
*ie_ptr += 1;
|
|
*value = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: GPRS Timer 3
|
|
|
|
Description: Specifies GPRS specific timer values.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.16B
|
|
24.008 v10.2.0 Section 10.5.7.4A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_gprs_timer_3_ie(LIBLTE_MME_GPRS_TIMER_3_STRUCT* timer, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (timer != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 1;
|
|
(*ie_ptr)[1] = ((timer->unit & 0x07) << 5) | (timer->value & 0x1F);
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_gprs_timer_3_ie(uint8** ie_ptr, LIBLTE_MME_GPRS_TIMER_3_STRUCT* timer)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && timer != NULL) {
|
|
timer->unit = (*ie_ptr)[1] >> 5;
|
|
timer->value = (*ie_ptr)[1] & 0x1F;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Identity Type 2
|
|
|
|
Description: Specifies which identity is requested.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.17
|
|
24.008 v10.2.0 Section 10.5.5.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_identity_type_2_ie(uint8 id_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= id_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_type_2_ie(uint8** ie_ptr, uint8 bit_offset, uint8* id_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && id_type != NULL) {
|
|
*id_type = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: IMEISV Request
|
|
|
|
Description: Indicates that the IMEISV shall be included by the
|
|
UE in the authentication and ciphering response
|
|
message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.18
|
|
24.008 v10.2.0 Section 10.5.5.10
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_imeisv_request_ie(LIBLTE_MME_IMEISV_REQUEST_ENUM imeisv_req, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= imeisv_req << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_imeisv_request_ie(uint8** ie_ptr, uint8 bit_offset, LIBLTE_MME_IMEISV_REQUEST_ENUM* imeisv_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && imeisv_req != NULL) {
|
|
*imeisv_req = (LIBLTE_MME_IMEISV_REQUEST_ENUM)((**ie_ptr >> bit_offset) & 0x07);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: KSI And Sequence Number
|
|
|
|
Description: Provides the network with the key set identifier
|
|
(KSI) value of the current EPS security context and
|
|
the 5 least significant bits of the NAS COUNT value
|
|
applicable for the message including this information
|
|
element.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.19
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ksi_and_sequence_number_ie(LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT* ksi_and_seq_num,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ksi_and_seq_num != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (ksi_and_seq_num->ksi & 0x07) << 5;
|
|
(*ie_ptr)[0] |= ksi_and_seq_num->seq_num & 0x1F;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_ksi_and_sequence_number_ie(uint8** ie_ptr, LIBLTE_MME_KSI_AND_SEQUENCE_NUMBER_STRUCT* ksi_and_seq_num)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ksi_and_seq_num != NULL) {
|
|
ksi_and_seq_num->ksi = ((*ie_ptr)[0] >> 5) & 0x07;
|
|
ksi_and_seq_num->seq_num = (*ie_ptr)[0] & 0x1F;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: MS Network Capability
|
|
|
|
Description: Provides the network with information concerning
|
|
aspects of the UE related to GPRS.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.20
|
|
24.008 v10.2.0 Section 10.5.5.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ms_network_capability_ie(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT* ms_network_cap,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ms_network_cap != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 3;
|
|
(*ie_ptr)[1] = ms_network_cap->gea[1] << 7;
|
|
(*ie_ptr)[1] |= ms_network_cap->sm_cap_ded << 6;
|
|
(*ie_ptr)[1] |= ms_network_cap->sm_cap_gprs << 5;
|
|
(*ie_ptr)[1] |= ms_network_cap->ucs2 << 4;
|
|
(*ie_ptr)[1] |= (ms_network_cap->ss_screening & 0x03) << 2;
|
|
(*ie_ptr)[1] |= ms_network_cap->solsa << 1;
|
|
(*ie_ptr)[1] |= ms_network_cap->revision;
|
|
(*ie_ptr)[2] = ms_network_cap->pfc << 7;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[2] << 6;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[3] << 5;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[4] << 4;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[5] << 3;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[6] << 2;
|
|
(*ie_ptr)[2] |= ms_network_cap->gea[7] << 1;
|
|
(*ie_ptr)[2] |= ms_network_cap->lcsva;
|
|
(*ie_ptr)[3] = ms_network_cap->ho_g2u_via_iu << 7;
|
|
(*ie_ptr)[3] |= ms_network_cap->ho_g2e_via_s1 << 6;
|
|
(*ie_ptr)[3] |= ms_network_cap->emm_comb << 5;
|
|
(*ie_ptr)[3] |= ms_network_cap->isr << 4;
|
|
(*ie_ptr)[3] |= ms_network_cap->srvcc << 3;
|
|
(*ie_ptr)[3] |= ms_network_cap->epc << 2;
|
|
(*ie_ptr)[3] |= ms_network_cap->nf << 1;
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_ms_network_capability_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT* ms_network_cap)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ms_network_cap != NULL) {
|
|
ms_network_cap->gea[1] = ((*ie_ptr)[1] >> 7) & 0x01;
|
|
ms_network_cap->sm_cap_ded = ((*ie_ptr)[1] >> 6) & 0x01;
|
|
ms_network_cap->sm_cap_gprs = ((*ie_ptr)[1] >> 5) & 0x01;
|
|
ms_network_cap->ucs2 = ((*ie_ptr)[1] >> 4) & 0x01;
|
|
ms_network_cap->ss_screening = (LIBLTE_MME_SS_SCREENING_INDICATOR_ENUM)(((*ie_ptr)[1] >> 2) & 0x03);
|
|
ms_network_cap->solsa = ((*ie_ptr)[1] >> 1) & 0x01;
|
|
ms_network_cap->revision = (*ie_ptr)[1] & 0x01;
|
|
ms_network_cap->pfc = ((*ie_ptr)[2] >> 7) & 0x01;
|
|
ms_network_cap->gea[2] = ((*ie_ptr)[2] >> 6) & 0x01;
|
|
ms_network_cap->gea[3] = ((*ie_ptr)[2] >> 5) & 0x01;
|
|
ms_network_cap->gea[4] = ((*ie_ptr)[2] >> 4) & 0x01;
|
|
ms_network_cap->gea[5] = ((*ie_ptr)[2] >> 3) & 0x01;
|
|
ms_network_cap->gea[6] = ((*ie_ptr)[2] >> 2) & 0x01;
|
|
ms_network_cap->gea[7] = ((*ie_ptr)[2] >> 1) & 0x01;
|
|
ms_network_cap->lcsva = (*ie_ptr)[2] & 0x01;
|
|
ms_network_cap->ho_g2u_via_iu = ((*ie_ptr)[3] >> 7) & 0x01;
|
|
ms_network_cap->ho_g2e_via_s1 = ((*ie_ptr)[3] >> 6) & 0x01;
|
|
ms_network_cap->emm_comb = ((*ie_ptr)[3] >> 5) & 0x01;
|
|
ms_network_cap->isr = ((*ie_ptr)[3] >> 4) & 0x01;
|
|
ms_network_cap->srvcc = ((*ie_ptr)[3] >> 3) & 0x01;
|
|
ms_network_cap->epc = ((*ie_ptr)[3] >> 2) & 0x01;
|
|
ms_network_cap->nf = ((*ie_ptr)[3] >> 1) & 0x01;
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: NAS Key Set Identifier
|
|
|
|
Description: Provides the NAS key set identifier that is allocated
|
|
by the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.21
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_nas_key_set_id_ie(LIBLTE_MME_NAS_KEY_SET_ID_STRUCT* nas_ksi, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (nas_ksi != NULL && ie_ptr != NULL) {
|
|
**ie_ptr |= nas_ksi->tsc_flag << (bit_offset + 3);
|
|
**ie_ptr |= nas_ksi->nas_ksi << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_nas_key_set_id_ie(uint8** ie_ptr, uint8 bit_offset, LIBLTE_MME_NAS_KEY_SET_ID_STRUCT* nas_ksi)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && nas_ksi != NULL) {
|
|
nas_ksi->tsc_flag = (LIBLTE_MME_TYPE_OF_SECURITY_CONTEXT_FLAG_ENUM)((**ie_ptr >> (bit_offset + 3)) & 0x01);
|
|
nas_ksi->nas_ksi = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: NAS Message Container
|
|
|
|
Description: Encapsulates the SMS messages transferred between
|
|
the UE and the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.22
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_nas_message_container_ie(LIBLTE_BYTE_MSG_STRUCT* nas_msg, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (nas_msg != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = nas_msg->N_bytes & 0xFF;
|
|
for (i = 0; i < nas_msg->N_bytes; i++) {
|
|
(*ie_ptr)[1 + i] = nas_msg->msg[i];
|
|
}
|
|
*ie_ptr += nas_msg->N_bytes + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_message_container_ie(uint8** ie_ptr, LIBLTE_BYTE_MSG_STRUCT* nas_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && nas_msg != NULL) {
|
|
nas_msg->N_bytes = (*ie_ptr)[0];
|
|
for (i = 0; i < nas_msg->N_bytes; i++) {
|
|
nas_msg->msg[i] = (*ie_ptr)[1 + i];
|
|
}
|
|
*ie_ptr += nas_msg->N_bytes + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: NAS Security Algorithms
|
|
|
|
Description: Indicates the algorithms to be used for ciphering
|
|
and integrity protection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.23
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_nas_security_algorithms_ie(LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT* nas_sec_algs,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (nas_sec_algs != NULL && ie_ptr != NULL) {
|
|
**ie_ptr = (nas_sec_algs->type_of_eea << 4) | (nas_sec_algs->type_of_eia);
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_nas_security_algorithms_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_NAS_SECURITY_ALGORITHMS_STRUCT* nas_sec_algs)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && nas_sec_algs != NULL) {
|
|
nas_sec_algs->type_of_eea = (LIBLTE_MME_TYPE_OF_CIPHERING_ALGORITHM_ENUM)((**ie_ptr >> 4) & 0x07);
|
|
nas_sec_algs->type_of_eia = (LIBLTE_MME_TYPE_OF_INTEGRITY_ALGORITHM_ENUM)(**ie_ptr & 0x07);
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Network Name
|
|
|
|
Description: Passes a text string to the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.24
|
|
24.008 v10.2.0 Section 10.5.3.5A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_network_name_ie(LIBLTE_MME_NETWORK_NAME_STRUCT* net_name, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 bit_offset;
|
|
uint32 byte_offset;
|
|
const char* char_str = net_name->name;
|
|
|
|
if (net_name != NULL && ie_ptr != NULL) {
|
|
bit_offset = 0;
|
|
byte_offset = 2;
|
|
for (i = 0; i < strnlen(char_str, LIBLTE_STRING_LEN); i++) {
|
|
if (char_str[i] == 0x0A || char_str[i] == 0x0D || (char_str[i] >= 0x20 && char_str[i] <= 0x3F) ||
|
|
(char_str[i] >= 0x41 && char_str[i] <= 0x5A) || (char_str[i] >= 0x61 && char_str[i] <= 0x7A)) {
|
|
switch (bit_offset) {
|
|
case 0:
|
|
(*ie_ptr)[byte_offset] = char_str[i];
|
|
bit_offset = 7;
|
|
break;
|
|
case 1:
|
|
(*ie_ptr)[byte_offset] |= (char_str[i] << 1);
|
|
bit_offset = 0;
|
|
byte_offset++;
|
|
break;
|
|
case 2:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 2) & 0xFC);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 6) & 0x01);
|
|
bit_offset = 1;
|
|
break;
|
|
case 3:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 3) & 0xF8);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 5) & 0x03);
|
|
bit_offset = 2;
|
|
break;
|
|
case 4:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 4) & 0xF0);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 4) & 0x07);
|
|
bit_offset = 3;
|
|
break;
|
|
case 5:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 5) & 0xE0);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 3) & 0x0F);
|
|
bit_offset = 4;
|
|
break;
|
|
case 6:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 6) & 0xC0);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 2) & 0x1F);
|
|
bit_offset = 5;
|
|
break;
|
|
case 7:
|
|
(*ie_ptr)[byte_offset] |= ((char_str[i] << 7) & 0x80);
|
|
byte_offset++;
|
|
(*ie_ptr)[byte_offset] = ((char_str[i] >> 1) & 0x3F);
|
|
bit_offset = 6;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (0 == bit_offset) {
|
|
(*ie_ptr)[0] = byte_offset - 1;
|
|
(*ie_ptr)[1] = 0x80 | ((net_name->add_ci & 0x01) << 3);
|
|
*ie_ptr += byte_offset;
|
|
} else {
|
|
(*ie_ptr)[0] = byte_offset;
|
|
(*ie_ptr)[1] = 0x80 | ((net_name->add_ci & 0x01) << 3) | ((8 - bit_offset) & 0x07);
|
|
*ie_ptr += byte_offset + 1;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_network_name_ie(uint8** ie_ptr, LIBLTE_MME_NETWORK_NAME_STRUCT* net_name)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 bit_offset;
|
|
uint32 byte_offset;
|
|
uint32 N_bytes;
|
|
uint8 spare_field;
|
|
char tmp_char;
|
|
uint32 str_cnt;
|
|
|
|
if (ie_ptr != NULL && net_name != NULL) {
|
|
net_name->add_ci = (LIBLTE_MME_ADD_CI_ENUM)(((*ie_ptr)[1] >> 3) & 0x01);
|
|
spare_field = (*ie_ptr)[1] & 0x07;
|
|
N_bytes = (*ie_ptr)[0];
|
|
bit_offset = 0;
|
|
byte_offset = 2;
|
|
str_cnt = 0;
|
|
|
|
while (byte_offset < N_bytes && str_cnt < LIBLTE_STRING_LEN) {
|
|
switch (bit_offset) {
|
|
case 0:
|
|
tmp_char = (*ie_ptr)[byte_offset] & 0x7F;
|
|
bit_offset = 7;
|
|
break;
|
|
case 1:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 1) & 0x7F;
|
|
bit_offset = 0;
|
|
byte_offset++;
|
|
break;
|
|
case 2:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 2) & 0x3F;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 6) & 0x40;
|
|
bit_offset = 1;
|
|
break;
|
|
case 3:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 3) & 0x1F;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 5) & 0x60;
|
|
bit_offset = 2;
|
|
break;
|
|
case 4:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 4) & 0x0F;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 4) & 0x70;
|
|
bit_offset = 3;
|
|
break;
|
|
case 5:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 5) & 0x07;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 3) & 0x78;
|
|
bit_offset = 4;
|
|
break;
|
|
case 6:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 6) & 0x03;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 2) & 0x7C;
|
|
bit_offset = 5;
|
|
break;
|
|
case 7:
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 7) & 0x01;
|
|
byte_offset++;
|
|
tmp_char |= ((*ie_ptr)[byte_offset] << 1) & 0x7E;
|
|
bit_offset = 6;
|
|
break;
|
|
}
|
|
|
|
if (tmp_char == 0x0A || tmp_char == 0x0D || (tmp_char >= 0x20 && tmp_char <= 0x3F) ||
|
|
(tmp_char >= 0x41 && tmp_char <= 0x5A) || (tmp_char >= 0x61 && tmp_char <= 0x7A)) {
|
|
if (str_cnt < LIBLTE_STRING_LEN) {
|
|
net_name->name[str_cnt] = tmp_char;
|
|
str_cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 == bit_offset || (1 == bit_offset && 0 == spare_field)) {
|
|
if (0 == bit_offset) {
|
|
tmp_char = (*ie_ptr)[byte_offset] & 0x7F;
|
|
} else {
|
|
tmp_char = ((*ie_ptr)[byte_offset] >> 1) & 0x7F;
|
|
}
|
|
if (tmp_char == 0x0A || tmp_char == 0x0D || (tmp_char >= 0x20 && tmp_char <= 0x3F) ||
|
|
(tmp_char >= 0x41 && tmp_char <= 0x5A) || (tmp_char >= 0x61 && tmp_char <= 0x7A)) {
|
|
if (str_cnt < LIBLTE_STRING_LEN) {
|
|
net_name->name[str_cnt] = tmp_char;
|
|
str_cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (str_cnt < LIBLTE_STRING_LEN) {
|
|
net_name->name[str_cnt] = '\0';
|
|
str_cnt++;
|
|
}
|
|
|
|
*ie_ptr += byte_offset + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Nonce
|
|
|
|
Description: Transfers a 32-bit nonce value to support deriving
|
|
a new mapped EPS security context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.25
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_nonce_ie(uint32 nonce, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (nonce >> 24) & 0xFF;
|
|
(*ie_ptr)[1] = (nonce >> 16) & 0xFF;
|
|
(*ie_ptr)[2] = (nonce >> 8) & 0xFF;
|
|
(*ie_ptr)[3] = nonce & 0xFF;
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_nonce_ie(uint8** ie_ptr, uint32* nonce)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && nonce != NULL) {
|
|
*nonce = (*ie_ptr)[0] << 24;
|
|
*nonce |= (*ie_ptr)[1] << 16;
|
|
*nonce |= (*ie_ptr)[2] << 8;
|
|
*nonce |= (*ie_ptr)[3];
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Paging Identity
|
|
|
|
Description: Indicates the identity used for paging for non-EPS
|
|
services.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.25A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_paging_identity_ie(uint8 paging_id, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = paging_id & 0x01;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_paging_identity_ie(uint8** ie_ptr, uint8* paging_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && paging_id != NULL) {
|
|
*paging_id = (*ie_ptr)[0] & 0x01;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: P-TMSI Signature
|
|
|
|
Description: Identifies a GMM context of a UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.26
|
|
24.008 v10.2.0 Section 10.5.5.8
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_p_tmsi_signature_ie(uint32 p_tmsi_signature, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (p_tmsi_signature >> 24) & 0xFF;
|
|
(*ie_ptr)[1] = (p_tmsi_signature >> 16) & 0xFF;
|
|
(*ie_ptr)[2] = (p_tmsi_signature >> 8) & 0xFF;
|
|
(*ie_ptr)[3] = p_tmsi_signature & 0xFF;
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_p_tmsi_signature_ie(uint8** ie_ptr, uint32* p_tmsi_signature)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && p_tmsi_signature != NULL) {
|
|
*p_tmsi_signature = (*ie_ptr)[0] << 24;
|
|
*p_tmsi_signature |= (*ie_ptr)[1] << 16;
|
|
*p_tmsi_signature |= (*ie_ptr)[2] << 8;
|
|
*p_tmsi_signature |= (*ie_ptr)[3];
|
|
*ie_ptr += 4;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Service Type
|
|
|
|
Description: Specifies the purpose of the service request
|
|
procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.27
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_service_type_ie(uint8 value, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (value & 0x0F) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_service_type_ie(uint8** ie_ptr, uint8 bit_offset, uint8* value)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && value != NULL) {
|
|
*value = ((*ie_ptr)[0] >> bit_offset) & 0x0F;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Short MAC
|
|
|
|
Description: Protects the integrity of a SERVICE REQUEST message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.28
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_short_mac_ie(uint16 short_mac, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (short_mac >> 8) & 0xFF;
|
|
(*ie_ptr)[1] = short_mac & 0xFF;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_short_mac_ie(uint8** ie_ptr, uint16* short_mac)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && short_mac != NULL) {
|
|
*short_mac = (*ie_ptr)[0] << 8;
|
|
*short_mac |= (*ie_ptr)[1];
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Time Zone
|
|
|
|
Description: Encodes the offset between universal time and local
|
|
time in steps of 15 minutes.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.29
|
|
24.008 v10.2.0 Section 10.5.3.8
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_ie(uint8 tz, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = tz;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_ie(uint8** ie_ptr, uint8* tz)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && tz != NULL) {
|
|
*tz = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Time Zone And Time
|
|
|
|
Description: Encodes the offset between universal time and local
|
|
time in steps of 15 minutes and encodes the universal
|
|
time at which the IE may have been sent by the
|
|
network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.30
|
|
24.008 v10.2.0 Section 10.5.3.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_time_zone_and_time_ie(LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT* ttz, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ttz != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = ((ttz->year % 10) << 4) | ((ttz->year % 100) / 10);
|
|
(*ie_ptr)[1] = ((ttz->month % 10) << 4) | (ttz->month / 10);
|
|
(*ie_ptr)[2] = ((ttz->day % 10) << 4) | (ttz->day / 10);
|
|
(*ie_ptr)[3] = ((ttz->hour % 10) << 4) | (ttz->hour / 10);
|
|
(*ie_ptr)[4] = ((ttz->minute % 10) << 4) | (ttz->minute / 10);
|
|
(*ie_ptr)[5] = ((ttz->second % 10) << 4) | (ttz->second / 10);
|
|
(*ie_ptr)[6] = ttz->tz;
|
|
*ie_ptr += 7;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_time_zone_and_time_ie(uint8** ie_ptr, LIBLTE_MME_TIME_ZONE_AND_TIME_STRUCT* ttz)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && ttz != NULL) {
|
|
ttz->year = 2000 + (((*ie_ptr)[0] & 0x0F) * 10) + (((*ie_ptr)[0] >> 4) & 0x0F);
|
|
ttz->month = (((*ie_ptr)[1] & 0x0F) * 10) + (((*ie_ptr)[1] >> 4) & 0x0F);
|
|
ttz->day = (((*ie_ptr)[2] & 0x0F) * 10) + (((*ie_ptr)[2] >> 4) & 0x0F);
|
|
ttz->hour = (((*ie_ptr)[3] & 0x0F) * 10) + (((*ie_ptr)[3] >> 4) & 0x0F);
|
|
ttz->minute = (((*ie_ptr)[4] & 0x0F) * 10) + (((*ie_ptr)[4] >> 4) & 0x0F);
|
|
ttz->second = (((*ie_ptr)[5] & 0x0F) * 10) + (((*ie_ptr)[5] >> 4) & 0x0F);
|
|
ttz->tz = (*ie_ptr)[6];
|
|
*ie_ptr += 7;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: TMSI Status
|
|
|
|
Description: Indicates whether a valid TMSI is available in the
|
|
UE or not.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.31
|
|
24.008 v10.2.0 Section 10.5.5.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_tmsi_status_ie(LIBLTE_MME_TMSI_STATUS_ENUM tmsi_status, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= tmsi_status << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_tmsi_status_ie(uint8** ie_ptr, uint8 bit_offset, LIBLTE_MME_TMSI_STATUS_ENUM* tmsi_status)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && tmsi_status != NULL) {
|
|
*tmsi_status = (LIBLTE_MME_TMSI_STATUS_ENUM)((**ie_ptr >> bit_offset) & 0x01);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Tracking Area Identity
|
|
|
|
Description: Provides an unambiguous identification of tracking
|
|
areas within the area covered by the 3GPP system.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.32
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_id_ie(LIBLTE_MME_TRACKING_AREA_ID_STRUCT* tai, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (tai != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (((tai->mcc / 10) % 10) << 4) | ((tai->mcc / 100) % 10);
|
|
if (tai->mnc < 100) {
|
|
(*ie_ptr)[1] = 0xF0 | (tai->mcc % 10);
|
|
(*ie_ptr)[2] = ((tai->mnc % 10) << 4) | ((tai->mnc / 10) % 10);
|
|
} else {
|
|
(*ie_ptr)[1] = ((tai->mnc % 10) << 4) | (tai->mcc % 10);
|
|
(*ie_ptr)[2] = (((tai->mnc / 10) % 10) << 4) | ((tai->mnc / 100) % 10);
|
|
}
|
|
(*ie_ptr)[3] = (tai->tac >> 8) & 0xFF;
|
|
(*ie_ptr)[4] = tai->tac & 0xFF;
|
|
*ie_ptr += 5;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_id_ie(uint8** ie_ptr, LIBLTE_MME_TRACKING_AREA_ID_STRUCT* tai)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && tai != NULL) {
|
|
tai->mcc = ((*ie_ptr)[0] & 0x0F) * 100;
|
|
tai->mcc += (((*ie_ptr)[0] >> 4) & 0x0F) * 10;
|
|
tai->mcc += (*ie_ptr)[1] & 0x0F;
|
|
if ((((*ie_ptr)[1] >> 4) & 0x0F) == 0x0F) {
|
|
tai->mnc = ((*ie_ptr)[2] & 0x0F) * 10;
|
|
tai->mnc += ((*ie_ptr)[2] >> 4) & 0x0F;
|
|
} else {
|
|
tai->mnc = ((*ie_ptr)[1] >> 4) & 0x0F;
|
|
tai->mnc += ((*ie_ptr)[2] & 0x0F) * 100;
|
|
tai->mnc += (((*ie_ptr)[2] >> 4) & 0x0F) * 10;
|
|
}
|
|
tai->tac = (*ie_ptr)[3] << 8;
|
|
tai->tac |= (*ie_ptr)[4];
|
|
*ie_ptr += 5;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Tracking Area Identity List
|
|
|
|
Description: Transfers a list of tracking areas from the network
|
|
to the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.33
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_tracking_area_identity_list_ie(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT* tai_list, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (tai_list != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = (tai_list->N_tais * 5) + 1;
|
|
// TODO: Support all types
|
|
if (1 == tai_list->N_tais) {
|
|
(*ie_ptr)[1] = (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_NON_CONSECUTIVE_TACS << 5) |
|
|
((tai_list->N_tais - 1) & 0x1F);
|
|
} else {
|
|
(*ie_ptr)[1] =
|
|
(LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_DIFFERENT_PLMNS << 5) | ((tai_list->N_tais - 1) & 0x1F);
|
|
}
|
|
*ie_ptr += 2;
|
|
for (i = 0; i < tai_list->N_tais; i++) {
|
|
liblte_mme_pack_tracking_area_id_ie(&tai_list->tai[i], ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_tracking_area_identity_list_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_STRUCT* tai_list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ENUM type;
|
|
uint32 sent_length;
|
|
uint32 length;
|
|
uint32 i;
|
|
uint32 N_elems;
|
|
uint16 mcc;
|
|
uint16 mnc;
|
|
uint16 tac;
|
|
|
|
if (ie_ptr != NULL && tai_list != NULL) {
|
|
sent_length = (*ie_ptr)[0] + 1;
|
|
length = 1;
|
|
tai_list->N_tais = 0;
|
|
while (length < sent_length) {
|
|
type = (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ENUM)(((*ie_ptr)[length] >> 5) & 0x03);
|
|
N_elems = (*ie_ptr)[length++] & 0x1F;
|
|
if (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_NON_CONSECUTIVE_TACS == type) {
|
|
mcc = ((*ie_ptr)[length] & 0x0F) * 100;
|
|
mcc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
mcc += (*ie_ptr)[length] & 0x0F;
|
|
if ((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) {
|
|
length++;
|
|
mnc = ((*ie_ptr)[length] & 0x0F) * 10;
|
|
mnc += ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
} else {
|
|
mnc = ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
mnc += ((*ie_ptr)[length] & 0x0F) * 100;
|
|
mnc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
}
|
|
for (i = 0; i < N_elems; i++) {
|
|
tai_list->tai[tai_list->N_tais].mcc = mcc;
|
|
tai_list->tai[tai_list->N_tais].mnc = mnc;
|
|
tai_list->tai[tai_list->N_tais].tac = (*ie_ptr)[length++] << 8;
|
|
tai_list->tai[tai_list->N_tais].tac |= (*ie_ptr)[length++];
|
|
tai_list->N_tais++;
|
|
}
|
|
} else if (LIBLTE_MME_TRACKING_AREA_IDENTITY_LIST_TYPE_ONE_PLMN_CONSECUTIVE_TACS == type) {
|
|
mcc = ((*ie_ptr)[length] & 0x0F) * 100;
|
|
mcc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
mcc += (*ie_ptr)[length] & 0x0F;
|
|
if ((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) {
|
|
length++;
|
|
mnc = ((*ie_ptr)[length] & 0x0F) * 10;
|
|
mnc += ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
} else {
|
|
mnc = ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
mnc += ((*ie_ptr)[length] & 0x0F) * 100;
|
|
mnc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
}
|
|
tac = (*ie_ptr)[length++] << 8;
|
|
tac |= (*ie_ptr)[length++];
|
|
for (i = 0; i < N_elems; i++) {
|
|
tai_list->tai[tai_list->N_tais].mcc = mcc;
|
|
tai_list->tai[tai_list->N_tais].mnc = mnc;
|
|
tai_list->tai[tai_list->N_tais].tac = tac + i;
|
|
tai_list->N_tais++;
|
|
}
|
|
} else {
|
|
for (i = 0; i < N_elems; i++) {
|
|
tai_list->tai[tai_list->N_tais].mcc = ((*ie_ptr)[length] & 0x0F) * 100;
|
|
tai_list->tai[tai_list->N_tais].mcc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
tai_list->tai[tai_list->N_tais].mcc += (*ie_ptr)[length] & 0x0F;
|
|
if ((((*ie_ptr)[length] >> 4) & 0x0F) == 0x0F) {
|
|
length++;
|
|
tai_list->tai[tai_list->N_tais].mnc = ((*ie_ptr)[length] & 0x0F) * 10;
|
|
tai_list->tai[tai_list->N_tais].mnc += ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
} else {
|
|
tai_list->tai[tai_list->N_tais].mnc = ((*ie_ptr)[length++] >> 4) & 0x0F;
|
|
tai_list->tai[tai_list->N_tais].mnc += ((*ie_ptr)[length] & 0x0F) * 100;
|
|
tai_list->tai[tai_list->N_tais].mnc += (((*ie_ptr)[length++] >> 4) & 0x0F) * 10;
|
|
}
|
|
tai_list->tai[tai_list->N_tais].tac = (*ie_ptr)[length++] << 8;
|
|
tai_list->tai[tai_list->N_tais].tac |= (*ie_ptr)[length++];
|
|
tai_list->N_tais++;
|
|
}
|
|
}
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: UE Network Capability
|
|
|
|
Description: Provides the network with information concerning
|
|
aspects of the UE related to EPS or interworking with
|
|
GPRS.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.34
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ue_network_capability_ie(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT* ue_network_cap,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ue_network_cap != NULL && ie_ptr != NULL) {
|
|
if (ue_network_cap->dc_nr_present) {
|
|
**ie_ptr = 7;
|
|
} else {
|
|
**ie_ptr = 2;
|
|
}
|
|
*ie_ptr += 1;
|
|
**ie_ptr = ue_network_cap->eea[0] << 7;
|
|
**ie_ptr |= ue_network_cap->eea[1] << 6;
|
|
**ie_ptr |= ue_network_cap->eea[2] << 5;
|
|
**ie_ptr |= ue_network_cap->eea[3] << 4;
|
|
**ie_ptr |= ue_network_cap->eea[4] << 3;
|
|
**ie_ptr |= ue_network_cap->eea[5] << 2;
|
|
**ie_ptr |= ue_network_cap->eea[6] << 1;
|
|
**ie_ptr |= ue_network_cap->eea[7];
|
|
*ie_ptr += 1;
|
|
**ie_ptr = ue_network_cap->eia[0] << 7;
|
|
**ie_ptr |= ue_network_cap->eia[1] << 6;
|
|
**ie_ptr |= ue_network_cap->eia[2] << 5;
|
|
**ie_ptr |= ue_network_cap->eia[3] << 4;
|
|
**ie_ptr |= ue_network_cap->eia[4] << 3;
|
|
**ie_ptr |= ue_network_cap->eia[5] << 2;
|
|
**ie_ptr |= ue_network_cap->eia[6] << 1;
|
|
**ie_ptr |= ue_network_cap->eia[7];
|
|
*ie_ptr += 1;
|
|
|
|
if (ue_network_cap->dc_nr_present) {
|
|
// skip empty caps
|
|
for (int i = 0; i < 4; i++) {
|
|
**ie_ptr = 0;
|
|
*ie_ptr += 1;
|
|
}
|
|
|
|
// set dcnr bit
|
|
**ie_ptr = ue_network_cap->dc_nr << 4;
|
|
*ie_ptr += 1;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_network_capability_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT* ue_network_cap)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 length;
|
|
|
|
if (ie_ptr != NULL && ue_network_cap != NULL) {
|
|
length = **ie_ptr;
|
|
*ie_ptr += 1;
|
|
ue_network_cap->eea[0] = (**ie_ptr >> 7) & 0x01;
|
|
ue_network_cap->eea[1] = (**ie_ptr >> 6) & 0x01;
|
|
ue_network_cap->eea[2] = (**ie_ptr >> 5) & 0x01;
|
|
ue_network_cap->eea[3] = (**ie_ptr >> 4) & 0x01;
|
|
ue_network_cap->eea[4] = (**ie_ptr >> 3) & 0x01;
|
|
ue_network_cap->eea[5] = (**ie_ptr >> 2) & 0x01;
|
|
ue_network_cap->eea[6] = (**ie_ptr >> 1) & 0x01;
|
|
ue_network_cap->eea[7] = **ie_ptr & 0x01;
|
|
*ie_ptr += 1;
|
|
ue_network_cap->eia[0] = (**ie_ptr >> 7) & 0x01;
|
|
ue_network_cap->eia[1] = (**ie_ptr >> 6) & 0x01;
|
|
ue_network_cap->eia[2] = (**ie_ptr >> 5) & 0x01;
|
|
ue_network_cap->eia[3] = (**ie_ptr >> 4) & 0x01;
|
|
ue_network_cap->eia[4] = (**ie_ptr >> 3) & 0x01;
|
|
ue_network_cap->eia[5] = (**ie_ptr >> 2) & 0x01;
|
|
ue_network_cap->eia[6] = (**ie_ptr >> 1) & 0x01;
|
|
ue_network_cap->eia[7] = **ie_ptr & 0x01;
|
|
*ie_ptr += 1;
|
|
if (length > 2) {
|
|
ue_network_cap->uea[0] = (**ie_ptr >> 7) & 0x01;
|
|
ue_network_cap->uea[1] = (**ie_ptr >> 6) & 0x01;
|
|
ue_network_cap->uea[2] = (**ie_ptr >> 5) & 0x01;
|
|
ue_network_cap->uea[3] = (**ie_ptr >> 4) & 0x01;
|
|
ue_network_cap->uea[4] = (**ie_ptr >> 3) & 0x01;
|
|
ue_network_cap->uea[5] = (**ie_ptr >> 2) & 0x01;
|
|
ue_network_cap->uea[6] = (**ie_ptr >> 1) & 0x01;
|
|
ue_network_cap->uea[7] = **ie_ptr & 0x01;
|
|
ue_network_cap->uea_present = true;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
ue_network_cap->uea_present = false;
|
|
}
|
|
if (length > 3) {
|
|
ue_network_cap->ucs2 = (**ie_ptr >> 7) & 0x01;
|
|
ue_network_cap->ucs2_present = true;
|
|
ue_network_cap->uia[1] = (**ie_ptr >> 6) & 0x01;
|
|
ue_network_cap->uia[2] = (**ie_ptr >> 5) & 0x01;
|
|
ue_network_cap->uia[3] = (**ie_ptr >> 4) & 0x01;
|
|
ue_network_cap->uia[4] = (**ie_ptr >> 3) & 0x01;
|
|
ue_network_cap->uia[5] = (**ie_ptr >> 2) & 0x01;
|
|
ue_network_cap->uia[6] = (**ie_ptr >> 1) & 0x01;
|
|
ue_network_cap->uia[7] = **ie_ptr & 0x01;
|
|
ue_network_cap->uia_present = true;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
ue_network_cap->ucs2_present = false;
|
|
ue_network_cap->uia_present = false;
|
|
}
|
|
if (length > 4) {
|
|
ue_network_cap->lpp = (**ie_ptr >> 3) & 0x01;
|
|
ue_network_cap->lpp_present = true;
|
|
ue_network_cap->lcs = (**ie_ptr >> 2) & 0x01;
|
|
ue_network_cap->lcs_present = true;
|
|
ue_network_cap->onexsrvcc = (**ie_ptr >> 1) & 0x01;
|
|
ue_network_cap->onexsrvcc_present = true;
|
|
ue_network_cap->nf = **ie_ptr >> 1;
|
|
ue_network_cap->nf_present = true;
|
|
*ie_ptr += 1;
|
|
} else {
|
|
ue_network_cap->lpp_present = false;
|
|
ue_network_cap->lcs_present = false;
|
|
ue_network_cap->onexsrvcc_present = false;
|
|
ue_network_cap->nf_present = false;
|
|
}
|
|
if (length > 5) {
|
|
*ie_ptr += length - 5;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: UE Radio Capability Update Needed
|
|
|
|
Description: Indicates whether the MME shall delete the stored
|
|
UE radio capability information, if any.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.35
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_ue_radio_capability_update_needed_ie(uint8 urc_update, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (urc_update & 0x01) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_ue_radio_capability_update_needed_ie(uint8** ie_ptr, uint8 bit_offset, uint8* urc_update)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && urc_update != NULL) {
|
|
*urc_update = ((*ie_ptr)[0] >> bit_offset) & 0x01;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: UE Security Capability
|
|
|
|
Description: Indicates which security algorithms are supported by
|
|
the UE in S1 mode.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.36
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ue_security_capabilities_ie(LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT* ue_sec_cap,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 idx;
|
|
|
|
if (ue_sec_cap != NULL && ie_ptr != NULL) {
|
|
if (ue_sec_cap->uea_present && ue_sec_cap->uia_present && ue_sec_cap->gea_present) {
|
|
(*ie_ptr)[0] = 5;
|
|
} else if (ue_sec_cap->uea_present && ue_sec_cap->uia_present) {
|
|
(*ie_ptr)[0] = 4;
|
|
} else if (ue_sec_cap->uea_present) {
|
|
(*ie_ptr)[0] = 3;
|
|
} else {
|
|
(*ie_ptr)[0] = 2;
|
|
}
|
|
idx = 1;
|
|
(*ie_ptr)[idx] = ue_sec_cap->eea[0] << 7;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[1] << 6;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[2] << 5;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[3] << 4;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[4] << 3;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[5] << 2;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[6] << 1;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eea[7];
|
|
idx++;
|
|
(*ie_ptr)[idx] = ue_sec_cap->eia[0] << 7;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[1] << 6;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[2] << 5;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[3] << 4;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[4] << 3;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[5] << 2;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[6] << 1;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->eia[7];
|
|
idx++;
|
|
if (ue_sec_cap->uea_present) {
|
|
(*ie_ptr)[idx] = ue_sec_cap->uea[0] << 7;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[1] << 6;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[2] << 5;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[3] << 4;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[4] << 3;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[5] << 2;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[6] << 1;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uea[7];
|
|
idx++;
|
|
}
|
|
if (ue_sec_cap->uia_present) {
|
|
(*ie_ptr)[idx] = ue_sec_cap->uia[1] << 6;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[2] << 5;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[3] << 4;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[4] << 3;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[5] << 2;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[6] << 1;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->uia[7];
|
|
idx++;
|
|
}
|
|
if (ue_sec_cap->gea_present) {
|
|
(*ie_ptr)[idx] = ue_sec_cap->gea[1] << 6;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[2] << 5;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[3] << 4;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[4] << 3;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[5] << 2;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[6] << 1;
|
|
(*ie_ptr)[idx] |= ue_sec_cap->gea[7];
|
|
idx++;
|
|
}
|
|
*ie_ptr += idx;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_ue_security_capabilities_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_UE_SECURITY_CAPABILITIES_STRUCT* ue_sec_cap)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 length;
|
|
|
|
if (ie_ptr != NULL && ue_sec_cap != NULL) {
|
|
length = (*ie_ptr)[0];
|
|
ue_sec_cap->eea[0] = ((*ie_ptr)[1] >> 7) & 0x01;
|
|
ue_sec_cap->eea[1] = ((*ie_ptr)[1] >> 6) & 0x01;
|
|
ue_sec_cap->eea[2] = ((*ie_ptr)[1] >> 5) & 0x01;
|
|
ue_sec_cap->eea[3] = ((*ie_ptr)[1] >> 4) & 0x01;
|
|
ue_sec_cap->eea[4] = ((*ie_ptr)[1] >> 3) & 0x01;
|
|
ue_sec_cap->eea[5] = ((*ie_ptr)[1] >> 2) & 0x01;
|
|
ue_sec_cap->eea[6] = ((*ie_ptr)[1] >> 1) & 0x01;
|
|
ue_sec_cap->eea[7] = (*ie_ptr)[1] & 0x01;
|
|
ue_sec_cap->eia[0] = ((*ie_ptr)[2] >> 7) & 0x01;
|
|
ue_sec_cap->eia[1] = ((*ie_ptr)[2] >> 6) & 0x01;
|
|
ue_sec_cap->eia[2] = ((*ie_ptr)[2] >> 5) & 0x01;
|
|
ue_sec_cap->eia[3] = ((*ie_ptr)[2] >> 4) & 0x01;
|
|
ue_sec_cap->eia[4] = ((*ie_ptr)[2] >> 3) & 0x01;
|
|
ue_sec_cap->eia[5] = ((*ie_ptr)[2] >> 2) & 0x01;
|
|
ue_sec_cap->eia[6] = ((*ie_ptr)[2] >> 1) & 0x01;
|
|
ue_sec_cap->eia[7] = (*ie_ptr)[2] & 0x01;
|
|
if (length > 2) {
|
|
ue_sec_cap->uea[0] = ((*ie_ptr)[3] >> 7) & 0x01;
|
|
ue_sec_cap->uea[1] = ((*ie_ptr)[3] >> 6) & 0x01;
|
|
ue_sec_cap->uea[2] = ((*ie_ptr)[3] >> 5) & 0x01;
|
|
ue_sec_cap->uea[3] = ((*ie_ptr)[3] >> 4) & 0x01;
|
|
ue_sec_cap->uea[4] = ((*ie_ptr)[3] >> 3) & 0x01;
|
|
ue_sec_cap->uea[5] = ((*ie_ptr)[3] >> 2) & 0x01;
|
|
ue_sec_cap->uea[6] = ((*ie_ptr)[3] >> 1) & 0x01;
|
|
ue_sec_cap->uea[7] = (*ie_ptr)[3] & 0x01;
|
|
ue_sec_cap->uea_present = true;
|
|
} else {
|
|
ue_sec_cap->uea_present = false;
|
|
}
|
|
if (length > 3) {
|
|
ue_sec_cap->uia[1] = ((*ie_ptr)[4] >> 6) & 0x01;
|
|
ue_sec_cap->uia[2] = ((*ie_ptr)[4] >> 5) & 0x01;
|
|
ue_sec_cap->uia[3] = ((*ie_ptr)[4] >> 4) & 0x01;
|
|
ue_sec_cap->uia[4] = ((*ie_ptr)[4] >> 3) & 0x01;
|
|
ue_sec_cap->uia[5] = ((*ie_ptr)[4] >> 2) & 0x01;
|
|
ue_sec_cap->uia[6] = ((*ie_ptr)[4] >> 1) & 0x01;
|
|
ue_sec_cap->uia[7] = (*ie_ptr)[4] & 0x01;
|
|
ue_sec_cap->uia_present = true;
|
|
} else {
|
|
ue_sec_cap->uia_present = false;
|
|
}
|
|
if (length > 4) {
|
|
ue_sec_cap->gea[1] = ((*ie_ptr)[5] >> 6) & 0x01;
|
|
ue_sec_cap->gea[2] = ((*ie_ptr)[5] >> 5) & 0x01;
|
|
ue_sec_cap->gea[3] = ((*ie_ptr)[5] >> 4) & 0x01;
|
|
ue_sec_cap->gea[4] = ((*ie_ptr)[5] >> 3) & 0x01;
|
|
ue_sec_cap->gea[5] = ((*ie_ptr)[5] >> 2) & 0x01;
|
|
ue_sec_cap->gea[6] = ((*ie_ptr)[5] >> 1) & 0x01;
|
|
ue_sec_cap->gea[7] = (*ie_ptr)[5] & 0x01;
|
|
ue_sec_cap->gea_present = true;
|
|
} else {
|
|
ue_sec_cap->gea_present = false;
|
|
}
|
|
*ie_ptr += length + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Emergency Number List
|
|
|
|
Description: Encodes emergency number(s) for use within the
|
|
country (as indicated by MCC) where the IE is
|
|
received.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.37
|
|
24.008 v10.2.0 Section 10.5.3.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_emergency_number_list_ie(LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT* emerg_num_list,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 j;
|
|
uint32 length;
|
|
|
|
if (emerg_num_list != NULL && ie_ptr != NULL) {
|
|
length = 1;
|
|
for (i = 0; i < emerg_num_list->N_emerg_nums; i++) {
|
|
if ((emerg_num_list->emerg_num[i].N_emerg_num_digits % 2) == 0) {
|
|
(*ie_ptr)[length++] = (emerg_num_list->emerg_num[i].N_emerg_num_digits / 2) + 1;
|
|
(*ie_ptr)[length++] = emerg_num_list->emerg_num[i].emerg_service_cat;
|
|
|
|
if (emerg_num_list->emerg_num[i].N_emerg_num_digits / 2 > LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS) {
|
|
return err;
|
|
}
|
|
|
|
for (j = 0; j < emerg_num_list->emerg_num[i].N_emerg_num_digits / 2; j++) {
|
|
(*ie_ptr)[length] = emerg_num_list->emerg_num[i].emerg_num[j * 2 + 0];
|
|
(*ie_ptr)[length++] |= emerg_num_list->emerg_num[i].emerg_num[j * 2 + 1] << 4;
|
|
}
|
|
} else {
|
|
(*ie_ptr)[length++] = (emerg_num_list->emerg_num[i].N_emerg_num_digits / 2) + 2;
|
|
(*ie_ptr)[length++] = emerg_num_list->emerg_num[i].emerg_service_cat;
|
|
for (j = 0; j < emerg_num_list->emerg_num[i].N_emerg_num_digits / 2; j++) {
|
|
(*ie_ptr)[length] = emerg_num_list->emerg_num[i].emerg_num[j * 2 + 0];
|
|
(*ie_ptr)[length++] |= emerg_num_list->emerg_num[i].emerg_num[j * 2 + 1] << 4;
|
|
}
|
|
(*ie_ptr)[length++] = 0xF0 | emerg_num_list->emerg_num[i].emerg_num[j * 2];
|
|
}
|
|
}
|
|
(*ie_ptr)[0] = length - 2;
|
|
*ie_ptr += length - 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_emergency_number_list_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_EMERGENCY_NUMBER_LIST_STRUCT* emerg_num_list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 sent_length;
|
|
uint32 length;
|
|
uint32 idx;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && emerg_num_list != NULL) {
|
|
sent_length = (*ie_ptr)[0] + 1;
|
|
length = 1;
|
|
emerg_num_list->N_emerg_nums = 0;
|
|
while (length < sent_length) {
|
|
idx = emerg_num_list->N_emerg_nums;
|
|
emerg_num_list->emerg_num[idx].N_emerg_num_digits = ((*ie_ptr)[length++] - 1) * 2;
|
|
if (emerg_num_list->emerg_num[idx].N_emerg_num_digits > LIBLTE_MME_EMERGENCY_NUMBER_MAX_NUM_DIGITS) {
|
|
return err;
|
|
}
|
|
|
|
emerg_num_list->emerg_num[idx].emerg_service_cat =
|
|
(LIBLTE_MME_EMERGENCY_SERVICE_CATEGORY_ENUM)((*ie_ptr)[length++] & 0x1F);
|
|
for (i = 0; i < emerg_num_list->emerg_num[idx].N_emerg_num_digits / 2; i++) {
|
|
emerg_num_list->emerg_num[idx].emerg_num[i * 2 + 0] = (*ie_ptr)[length] & 0x0F;
|
|
emerg_num_list->emerg_num[idx].emerg_num[i * 2 + 1] = (*ie_ptr)[length++] >> 4;
|
|
}
|
|
// Added by Ismael: if i==0 this is negative
|
|
if (i > 0) {
|
|
if (emerg_num_list->emerg_num[idx].emerg_num[i * 2 - 1] == 0x0F) {
|
|
emerg_num_list->emerg_num[idx].N_emerg_num_digits--;
|
|
}
|
|
}
|
|
emerg_num_list->N_emerg_nums++;
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CLI
|
|
|
|
Description: Conveys information about the calling line for a
|
|
terminated call to a CS fallback capable UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.38
|
|
*********************************************************************/
|
|
// TODO
|
|
|
|
/*********************************************************************
|
|
IE Name: SS Code
|
|
|
|
Description: Conveys information related to a network initiated
|
|
supplementary service request to a CS fallback
|
|
capable UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.39
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_ss_code_ie(uint8 code, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = code;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_ss_code_ie(uint8** ie_ptr, uint8* code)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && code != NULL) {
|
|
*code = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: LCS Indicator
|
|
|
|
Description: Indicates that the origin of the message is due to a
|
|
LCS request and the type of this request to a CS
|
|
fallback capable UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.40
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_lcs_indicator_ie(uint8 lcs_ind, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = lcs_ind;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_lcs_indicator_ie(uint8** ie_ptr, uint8* lcs_ind)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && lcs_ind != NULL) {
|
|
*lcs_ind = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: LCS Client Identity
|
|
|
|
Description: Conveys information related to the client of a LCS
|
|
request for a CS fallback capable UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.41
|
|
*********************************************************************/
|
|
// TODO
|
|
|
|
/*********************************************************************
|
|
IE Name: Generic Message Container Type
|
|
|
|
Description: Specifies the type of message contained in the
|
|
generic message container IE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.42
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_type_ie(uint8 msg_cont_type, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = msg_cont_type;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_type_ie(uint8** ie_ptr, uint8* msg_cont_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && msg_cont_type != NULL) {
|
|
*msg_cont_type = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Generic Message Container
|
|
|
|
Description: Encapsulates the application message transferred
|
|
between the UE and the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.43
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_generic_message_container_ie(LIBLTE_BYTE_MSG_STRUCT* msg, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (msg != NULL && ie_ptr != NULL && msg->N_bytes <= LIBLTE_MAX_MSG_SIZE_BYTES) {
|
|
(*ie_ptr)[0] = msg->N_bytes >> 8;
|
|
(*ie_ptr)[1] = msg->N_bytes & 0xFF;
|
|
for (i = 0; i < msg->N_bytes; i++) {
|
|
(*ie_ptr)[2 + i] = msg->msg[i];
|
|
}
|
|
*ie_ptr += msg->N_bytes + 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_generic_message_container_ie(uint8** ie_ptr, LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && msg != NULL) {
|
|
msg->N_bytes = (*ie_ptr)[0] << 8;
|
|
msg->N_bytes |= (*ie_ptr)[1];
|
|
|
|
if (msg->N_bytes > LIBLTE_MAX_MSG_SIZE_BYTES) {
|
|
return err;
|
|
}
|
|
|
|
for (i = 0; i < msg->N_bytes; i++) {
|
|
msg->msg[i] = (*ie_ptr)[2 + i];
|
|
}
|
|
*ie_ptr += msg->N_bytes + 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Voice Domain Preference and UE's Usage Setting
|
|
|
|
Description: Provides the network with the UE's usage setting and
|
|
the voice domain preference for the E-UTRAN.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.44
|
|
24.008 v10.2.0 Section 10.5.5.28
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(
|
|
LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT* voice_domain_pref_and_ue_usage_setting,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (voice_domain_pref_and_ue_usage_setting != NULL && ie_ptr != NULL) {
|
|
**ie_ptr = 1;
|
|
*ie_ptr += 1;
|
|
**ie_ptr = voice_domain_pref_and_ue_usage_setting->ue_usage_setting << 2;
|
|
**ie_ptr |= voice_domain_pref_and_ue_usage_setting->voice_domain_pref;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(
|
|
uint8** ie_ptr,
|
|
LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_STRUCT* voice_domain_pref_and_ue_usage_setting)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && voice_domain_pref_and_ue_usage_setting != NULL) {
|
|
*ie_ptr += 1;
|
|
voice_domain_pref_and_ue_usage_setting->ue_usage_setting =
|
|
(LIBLTE_MME_UE_USAGE_SETTING_ENUM)((**ie_ptr >> 2) & 0x01);
|
|
voice_domain_pref_and_ue_usage_setting->voice_domain_pref = (LIBLTE_MME_VOICE_DOMAIN_PREF_ENUM)(**ie_ptr & 0x03);
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: GUTI Type
|
|
|
|
Description: Indicates whether the GUTI included in the same
|
|
message in an information element of type EPS
|
|
mobility identity represents a native GUTI or a
|
|
mapped GUTI.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.3.45
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_guti_type_ie(LIBLTE_MME_GUTI_TYPE_ENUM guti_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= guti_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_type_ie(uint8** ie_ptr, uint8 bit_offset, LIBLTE_MME_GUTI_TYPE_ENUM* guti_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && guti_type != NULL) {
|
|
*guti_type = (LIBLTE_MME_GUTI_TYPE_ENUM)((**ie_ptr >> bit_offset) & 0x01);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Access Point Name
|
|
|
|
Description: Identifies the packet data network to which the GPRS
|
|
user wishes to connect and notifies the access point
|
|
of the packet data network that wishes to connect to
|
|
the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.1
|
|
24.008 v10.2.0 Section 10.5.6.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_access_point_name_ie(LIBLTE_MME_ACCESS_POINT_NAME_STRUCT* apn, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
const char* apn_str;
|
|
uint32 i;
|
|
uint32 len_idx;
|
|
uint32 apn_idx;
|
|
uint32 label_len;
|
|
|
|
if (apn != NULL && ie_ptr != NULL) {
|
|
apn_str = apn->apn;
|
|
(*ie_ptr)[0] = strnlen(apn->apn, LIBLTE_STRING_LEN) + 1;
|
|
len_idx = 0;
|
|
apn_idx = 0;
|
|
label_len = 0;
|
|
while (strnlen(apn->apn, LIBLTE_STRING_LEN) > apn_idx) {
|
|
(*ie_ptr)[1 + apn_idx + 1] = (uint8)apn_str[apn_idx];
|
|
apn_idx++;
|
|
label_len++;
|
|
|
|
if (apn_str[apn_idx] == '.') {
|
|
(*ie_ptr)[1 + len_idx] = label_len;
|
|
label_len = 0;
|
|
len_idx = apn_idx + 1;
|
|
apn_idx++;
|
|
}
|
|
}
|
|
(*ie_ptr)[1 + len_idx] = label_len;
|
|
*ie_ptr += strnlen(apn->apn, LIBLTE_STRING_LEN) + 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_access_point_name_ie(uint8** ie_ptr, LIBLTE_MME_ACCESS_POINT_NAME_STRUCT* apn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 ie_idx;
|
|
uint32 label_len;
|
|
uint32 str_cnt;
|
|
|
|
if (ie_ptr != NULL && apn != NULL) {
|
|
ie_idx = 0;
|
|
str_cnt = 0;
|
|
while (ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) {
|
|
label_len = (*ie_ptr)[1 + ie_idx];
|
|
for (i = 0; i < label_len && str_cnt < LIBLTE_STRING_LEN; i++) {
|
|
apn->apn[str_cnt] = (char)((*ie_ptr)[1 + ie_idx + i + 1]);
|
|
str_cnt++;
|
|
}
|
|
ie_idx += label_len + 1;
|
|
if (ie_idx < (*ie_ptr)[0] && str_cnt < LIBLTE_STRING_LEN) {
|
|
apn->apn[str_cnt] = '.';
|
|
str_cnt++;
|
|
}
|
|
}
|
|
if (str_cnt < LIBLTE_STRING_LEN) {
|
|
apn->apn[str_cnt] = '\0';
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: APN Aggregate Maximum Bit Rate
|
|
|
|
Description: Indicates the initial subscribed APN-AMBR when the
|
|
UE establishes a PDN connection or indicates the new
|
|
APN-AMBR if it is changed by the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT* apn_ambr,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (apn_ambr != NULL && ie_ptr != NULL) {
|
|
if (apn_ambr->ext_present && apn_ambr->ext2_present) {
|
|
(*ie_ptr)[0] = 6;
|
|
} else if (apn_ambr->ext_present) {
|
|
(*ie_ptr)[0] = 4;
|
|
} else {
|
|
(*ie_ptr)[0] = 2;
|
|
}
|
|
(*ie_ptr)[1] = apn_ambr->apn_ambr_dl;
|
|
(*ie_ptr)[2] = apn_ambr->apn_ambr_ul;
|
|
if (apn_ambr->ext_present) {
|
|
(*ie_ptr)[3] = apn_ambr->apn_ambr_dl_ext;
|
|
(*ie_ptr)[4] = apn_ambr->apn_ambr_ul_ext;
|
|
}
|
|
if (apn_ambr->ext2_present) {
|
|
(*ie_ptr)[5] = apn_ambr->apn_ambr_dl_ext2;
|
|
(*ie_ptr)[6] = apn_ambr->apn_ambr_ul_ext2;
|
|
}
|
|
if (apn_ambr->ext_present && apn_ambr->ext2_present) {
|
|
*ie_ptr += 7;
|
|
} else if (apn_ambr->ext_present) {
|
|
*ie_ptr += 5;
|
|
} else {
|
|
*ie_ptr += 3;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_APN_AGGREGATE_MAXIMUM_BIT_RATE_STRUCT* apn_ambr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && apn_ambr != NULL) {
|
|
if (6 == (*ie_ptr)[0]) {
|
|
apn_ambr->ext_present = true;
|
|
apn_ambr->ext2_present = true;
|
|
} else if (4 == (*ie_ptr)[0]) {
|
|
apn_ambr->ext_present = true;
|
|
apn_ambr->ext2_present = false;
|
|
} else {
|
|
apn_ambr->ext_present = false;
|
|
apn_ambr->ext2_present = false;
|
|
}
|
|
apn_ambr->apn_ambr_dl = (*ie_ptr)[1];
|
|
apn_ambr->apn_ambr_ul = (*ie_ptr)[2];
|
|
if (apn_ambr->ext_present) {
|
|
apn_ambr->apn_ambr_dl_ext = (*ie_ptr)[3];
|
|
apn_ambr->apn_ambr_ul_ext = (*ie_ptr)[4];
|
|
}
|
|
if (apn_ambr->ext2_present) {
|
|
apn_ambr->apn_ambr_dl_ext2 = (*ie_ptr)[5];
|
|
apn_ambr->apn_ambr_ul_ext2 = (*ie_ptr)[6];
|
|
}
|
|
if (apn_ambr->ext_present && apn_ambr->ext2_present) {
|
|
*ie_ptr += 7;
|
|
} else if (apn_ambr->ext_present) {
|
|
*ie_ptr += 5;
|
|
} else {
|
|
*ie_ptr += 3;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Connectivity Type
|
|
|
|
Description: Specifies the type of connectivity selected by the
|
|
network for the PDN connection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.2A
|
|
24.008 v10.2.0 Section 10.5.6.19
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_connectivity_type_ie(uint8 con_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= con_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_connectivity_type_ie(uint8** ie_ptr, uint8 bit_offset, uint8* con_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && con_type != NULL) {
|
|
*con_type = ((*ie_ptr)[0] >> bit_offset) & 0x0F;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: EPS Quality Of Service
|
|
|
|
Description: Specifies the QoS parameters for an EPS bearer
|
|
context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_eps_quality_of_service_ie(LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT* qos,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (qos != NULL && ie_ptr != NULL) {
|
|
if (qos->br_present && qos->br_ext_present) {
|
|
(*ie_ptr)[0] = 9;
|
|
} else if (qos->br_present) {
|
|
(*ie_ptr)[0] = 5;
|
|
} else {
|
|
(*ie_ptr)[0] = 1;
|
|
}
|
|
(*ie_ptr)[1] = qos->qci;
|
|
if (qos->br_present) {
|
|
(*ie_ptr)[2] = qos->mbr_ul;
|
|
(*ie_ptr)[3] = qos->mbr_dl;
|
|
(*ie_ptr)[4] = qos->gbr_ul;
|
|
(*ie_ptr)[5] = qos->gbr_dl;
|
|
}
|
|
if (qos->br_ext_present) {
|
|
(*ie_ptr)[6] = qos->mbr_ul_ext;
|
|
(*ie_ptr)[7] = qos->mbr_dl_ext;
|
|
(*ie_ptr)[8] = qos->gbr_ul_ext;
|
|
(*ie_ptr)[9] = qos->gbr_dl_ext;
|
|
}
|
|
if (qos->br_present && qos->br_ext_present) {
|
|
*ie_ptr += 10;
|
|
} else if (qos->br_present) {
|
|
*ie_ptr += 6;
|
|
} else {
|
|
*ie_ptr += 2;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_eps_quality_of_service_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_EPS_QUALITY_OF_SERVICE_STRUCT* qos)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && qos != NULL) {
|
|
if ((*ie_ptr)[0] == 1) {
|
|
qos->br_present = false;
|
|
qos->br_ext_present = false;
|
|
} else if ((*ie_ptr)[0] == 5) {
|
|
qos->br_present = true;
|
|
qos->br_ext_present = false;
|
|
} else {
|
|
qos->br_present = true;
|
|
qos->br_ext_present = true;
|
|
}
|
|
qos->qci = (*ie_ptr)[1];
|
|
if (qos->br_present) {
|
|
qos->mbr_ul = (*ie_ptr)[2];
|
|
qos->mbr_dl = (*ie_ptr)[3];
|
|
qos->gbr_ul = (*ie_ptr)[4];
|
|
qos->gbr_dl = (*ie_ptr)[5];
|
|
}
|
|
if (qos->br_ext_present) {
|
|
qos->mbr_ul_ext = (*ie_ptr)[6];
|
|
qos->mbr_dl_ext = (*ie_ptr)[7];
|
|
qos->gbr_ul_ext = (*ie_ptr)[8];
|
|
qos->gbr_dl_ext = (*ie_ptr)[9];
|
|
}
|
|
if (qos->br_present && qos->br_ext_present) {
|
|
*ie_ptr += 10;
|
|
} else if (qos->br_present) {
|
|
*ie_ptr += 6;
|
|
} else {
|
|
*ie_ptr += 2;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ESM Cause
|
|
|
|
Description: Indicates the reason why a session management request
|
|
is rejected.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_esm_cause_ie(uint8 cause, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = cause;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_cause_ie(uint8** ie_ptr, uint8* cause)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && cause != NULL) {
|
|
*cause = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ESM Information Transfer Flag
|
|
|
|
Description: Indicates whether ESM information, i.e. protocol
|
|
configuration options or APN or both, is to be
|
|
transferred security protected.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_esm_info_transfer_flag_ie(LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM esm_info_transfer_flag,
|
|
uint8 bit_offset,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= esm_info_transfer_flag << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_esm_info_transfer_flag_ie(uint8** ie_ptr,
|
|
uint8 bit_offset,
|
|
LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM* esm_info_transfer_flag)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && esm_info_transfer_flag != NULL) {
|
|
*esm_info_transfer_flag = (LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_ENUM)((**ie_ptr >> bit_offset) & 0x01);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Linked EPS Bearer Identity
|
|
|
|
Description: Identifies the default bearer that is associated
|
|
with a dedicated EPS bearer or identifies the EPS
|
|
bearer (default or dedicated) with which one or more
|
|
packet filters specified in a traffic flow aggregate
|
|
are associated.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_linked_eps_bearer_identity_ie(uint8 bearer_id, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] |= (bearer_id & 0x0F) << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_linked_eps_bearer_identity_ie(uint8** ie_ptr, uint8 bit_offset, uint8* bearer_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && bearer_id != NULL) {
|
|
*bearer_id = ((*ie_ptr)[0] >> bit_offset) & 0x0F;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: LLC Service Access Point Identifier
|
|
|
|
Description: Identifies the service access point that is used for
|
|
the GPRS data transfer at LLC layer.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.7
|
|
24.008 v10.2.0 Section 10.5.6.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_llc_service_access_point_identifier_ie(uint8 llc_sapi, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = llc_sapi;
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_llc_service_access_point_identifier_ie(uint8** ie_ptr, uint8* llc_sapi)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && llc_sapi != NULL) {
|
|
*llc_sapi = (*ie_ptr)[0];
|
|
*ie_ptr += 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Notification Indicator
|
|
|
|
Description: Informs the UE about an event which is relevant for
|
|
the upper layer using an EPS bearer context or
|
|
having requested a procedure transaction.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.7A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_notification_indicator_ie(uint8 notification_ind, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 1;
|
|
(*ie_ptr)[1] = notification_ind;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_indicator_ie(uint8** ie_ptr, uint8* notification_ind)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && notification_ind != NULL) {
|
|
*notification_ind = (*ie_ptr)[1];
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Packet Flow Identifier
|
|
|
|
Description: Indicates the packet flow identifier for a packet
|
|
flow context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.8
|
|
24.008 v10.2.0 Section 10.5.6.11
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_packet_flow_identifier_ie(uint8 packet_flow_id, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = 1;
|
|
(*ie_ptr)[1] = packet_flow_id;
|
|
*ie_ptr += 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_packet_flow_identifier_ie(uint8** ie_ptr, uint8* packet_flow_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && packet_flow_id != NULL) {
|
|
*packet_flow_id = (*ie_ptr)[1];
|
|
*ie_ptr += (*ie_ptr)[0];
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PDN Address
|
|
|
|
Description: Assigns an IPv4 address to the UE associated with a
|
|
packet data network and provides the UE with an
|
|
interface identifier to be used to build the IPv6
|
|
link local address.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_address_ie(LIBLTE_MME_PDN_ADDRESS_STRUCT* pdn_addr, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (pdn_addr != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[1] = 0x00 | (pdn_addr->pdn_type & 0x07);
|
|
if (LIBLTE_MME_PDN_TYPE_IPV4 == pdn_addr->pdn_type) {
|
|
for (i = 0; i < 4; i++) {
|
|
(*ie_ptr)[2 + i] = pdn_addr->addr[i];
|
|
}
|
|
(*ie_ptr)[0] = 5;
|
|
*ie_ptr += 6;
|
|
} else if (LIBLTE_MME_PDN_TYPE_IPV6 == pdn_addr->pdn_type) {
|
|
for (i = 0; i < 8; i++) {
|
|
(*ie_ptr)[2 + i] = pdn_addr->addr[i];
|
|
}
|
|
(*ie_ptr)[0] = 9;
|
|
*ie_ptr += 10;
|
|
} else {
|
|
for (i = 0; i < 12; i++) {
|
|
(*ie_ptr)[2 + i] = pdn_addr->addr[i];
|
|
}
|
|
(*ie_ptr)[0] = 13;
|
|
*ie_ptr += 14;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_address_ie(uint8** ie_ptr, LIBLTE_MME_PDN_ADDRESS_STRUCT* pdn_addr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && pdn_addr != NULL) {
|
|
pdn_addr->pdn_type = (*ie_ptr)[1] & 0x07;
|
|
if (LIBLTE_MME_PDN_TYPE_IPV4 == pdn_addr->pdn_type) {
|
|
for (i = 0; i < 4; i++) {
|
|
pdn_addr->addr[i] = (*ie_ptr)[2 + i];
|
|
}
|
|
} else if (LIBLTE_MME_PDN_TYPE_IPV6 == pdn_addr->pdn_type) {
|
|
for (i = 0; i < 8; i++) {
|
|
pdn_addr->addr[i] = (*ie_ptr)[2 + i];
|
|
}
|
|
} else {
|
|
for (i = 0; i < 12; i++) {
|
|
pdn_addr->addr[i] = (*ie_ptr)[2 + i];
|
|
}
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PDN Type
|
|
|
|
Description: Indicates the IP version capability of the IP stack
|
|
associated with the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.10
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_type_ie(uint8 pdn_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= pdn_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_pdn_type_ie(uint8** ie_ptr, uint8 bit_offset, uint8* pdn_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && pdn_type != NULL) {
|
|
*pdn_type = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Protocol Configuration Options
|
|
|
|
Description: Transfers external network protocol options
|
|
associated with a PDP context activation and
|
|
transfers additional (protocol) data (e.g.
|
|
configuration parameters, error codes or messages/
|
|
events) associated with an external protocol or an
|
|
application.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.11
|
|
24.008 v10.2.0 Section 10.5.6.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_protocol_config_options_ie(LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT* protocol_cnfg_opts,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 idx;
|
|
uint32 i;
|
|
uint32 j;
|
|
|
|
if (protocol_cnfg_opts != NULL && ie_ptr != NULL) {
|
|
(*ie_ptr)[1] = 0x80;
|
|
idx = 2;
|
|
for (i = 0; i < protocol_cnfg_opts->N_opts; i++) {
|
|
(*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].id >> 8;
|
|
(*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].id & 0x00FF;
|
|
(*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].len;
|
|
for (j = 0; j < protocol_cnfg_opts->opt[i].len; j++) {
|
|
(*ie_ptr)[idx++] = protocol_cnfg_opts->opt[i].contents[j];
|
|
}
|
|
}
|
|
(*ie_ptr)[0] = idx - 1;
|
|
*ie_ptr += idx;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_protocol_config_options_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_PROTOCOL_CONFIG_OPTIONS_STRUCT* protocol_cnfg_opts)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 idx;
|
|
uint32 i;
|
|
|
|
if (ie_ptr != NULL && protocol_cnfg_opts != NULL) {
|
|
idx = 2;
|
|
protocol_cnfg_opts->N_opts = 0;
|
|
while (idx < (*ie_ptr)[0]) {
|
|
protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].id = (*ie_ptr)[idx++] << 8;
|
|
protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].id |= (*ie_ptr)[idx++];
|
|
protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].len = (*ie_ptr)[idx++];
|
|
for (i = 0; i < protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].len; i++) {
|
|
protocol_cnfg_opts->opt[protocol_cnfg_opts->N_opts].contents[i] = (*ie_ptr)[idx++];
|
|
}
|
|
protocol_cnfg_opts->N_opts++;
|
|
}
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Quality Of Service
|
|
|
|
Description: Specifies the QoS parameters for a PDP context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.12
|
|
24.008 v10.2.0 Section 10.5.6.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_quality_of_service_ie(LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT* qos, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (qos != NULL && ie_ptr != NULL) {
|
|
if (qos->dl_ext_present && qos->ul_ext_present) {
|
|
(*ie_ptr)[0] = 16;
|
|
} else if (qos->dl_ext_present) {
|
|
(*ie_ptr)[0] = 14;
|
|
} else {
|
|
(*ie_ptr)[0] = 12;
|
|
}
|
|
(*ie_ptr)[1] = ((qos->delay_class & 0x07) << 3) | (qos->reliability_class & 0x07);
|
|
(*ie_ptr)[2] = ((qos->peak_throughput & 0x0F) << 4) | (qos->precedence_class & 0x07);
|
|
(*ie_ptr)[3] = qos->mean_throughput & 0x1F;
|
|
(*ie_ptr)[4] = ((qos->traffic_class & 0x07) << 5) | ((qos->delivery_order & 0x03) << 3) |
|
|
(qos->delivery_of_erroneous_sdu & 0x03);
|
|
(*ie_ptr)[5] = qos->max_sdu_size;
|
|
(*ie_ptr)[6] = qos->mbr_ul;
|
|
(*ie_ptr)[7] = qos->mbr_dl;
|
|
(*ie_ptr)[8] = ((qos->residual_ber & 0x0F) << 4) | (qos->sdu_error_ratio & 0x0F);
|
|
(*ie_ptr)[9] = ((qos->transfer_delay & 0x3F) << 2) | (qos->traffic_handling_prio & 0x03);
|
|
(*ie_ptr)[10] = qos->gbr_ul;
|
|
(*ie_ptr)[11] = qos->gbr_dl;
|
|
(*ie_ptr)[12] = ((qos->signalling_ind & 0x01) << 4) | (qos->source_stats_descriptor & 0x0F);
|
|
if (qos->dl_ext_present) {
|
|
(*ie_ptr)[13] = qos->mbr_dl_ext;
|
|
(*ie_ptr)[14] = qos->gbr_dl_ext;
|
|
}
|
|
if (qos->ul_ext_present) {
|
|
(*ie_ptr)[15] = qos->mbr_ul_ext;
|
|
(*ie_ptr)[16] = qos->gbr_ul_ext;
|
|
}
|
|
if (qos->dl_ext_present && qos->ul_ext_present) {
|
|
*ie_ptr += 17;
|
|
} else if (qos->dl_ext_present) {
|
|
*ie_ptr += 15;
|
|
} else {
|
|
*ie_ptr += 13;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_quality_of_service_ie(uint8** ie_ptr, LIBLTE_MME_QUALITY_OF_SERVICE_STRUCT* qos)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && qos != NULL) {
|
|
if (16 == (*ie_ptr)[0]) {
|
|
qos->dl_ext_present = true;
|
|
qos->ul_ext_present = true;
|
|
} else if (14 == (*ie_ptr)[0]) {
|
|
qos->dl_ext_present = true;
|
|
qos->ul_ext_present = false;
|
|
} else {
|
|
qos->dl_ext_present = false;
|
|
qos->ul_ext_present = false;
|
|
}
|
|
qos->delay_class = ((*ie_ptr)[1] >> 3) & 0x07;
|
|
qos->reliability_class = (*ie_ptr)[1] & 0x07;
|
|
qos->peak_throughput = (*ie_ptr)[2] >> 4;
|
|
qos->precedence_class = (*ie_ptr)[2] & 0x07;
|
|
qos->mean_throughput = (*ie_ptr)[3] & 0x1F;
|
|
qos->traffic_class = ((*ie_ptr)[4] >> 5) & 0x07;
|
|
qos->delivery_order = ((*ie_ptr)[4] >> 3) & 0x03;
|
|
qos->delivery_of_erroneous_sdu = (*ie_ptr)[4] & 0x07;
|
|
qos->max_sdu_size = (*ie_ptr)[5];
|
|
qos->mbr_ul = (*ie_ptr)[6];
|
|
qos->mbr_dl = (*ie_ptr)[7];
|
|
qos->residual_ber = ((*ie_ptr)[8] >> 4) & 0x0F;
|
|
qos->sdu_error_ratio = (*ie_ptr)[8] & 0x0F;
|
|
qos->transfer_delay = ((*ie_ptr)[9] >> 2) & 0x3F;
|
|
qos->traffic_handling_prio = (*ie_ptr)[9] & 0x03;
|
|
qos->gbr_ul = (*ie_ptr)[10];
|
|
qos->gbr_dl = (*ie_ptr)[11];
|
|
qos->signalling_ind = ((*ie_ptr)[12] >> 4) & 0x01;
|
|
qos->source_stats_descriptor = (*ie_ptr)[12] & 0x0F;
|
|
if (qos->dl_ext_present) {
|
|
qos->mbr_dl_ext = (*ie_ptr)[13];
|
|
qos->gbr_dl_ext = (*ie_ptr)[14];
|
|
}
|
|
if (qos->ul_ext_present) {
|
|
qos->mbr_ul_ext = (*ie_ptr)[15];
|
|
qos->gbr_ul_ext = (*ie_ptr)[16];
|
|
}
|
|
if (qos->dl_ext_present && qos->ul_ext_present) {
|
|
*ie_ptr += 17;
|
|
} else if (qos->dl_ext_present) {
|
|
*ie_ptr += 15;
|
|
} else {
|
|
*ie_ptr += 13;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Radio Priority
|
|
|
|
Description: Specifies the priority level the UE shall use at the
|
|
lower layers for transmission of data related to a
|
|
PDP context or for mobile originated SMS
|
|
transmission.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.13
|
|
24.008 v10.2.0 Section 10.5.7.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_radio_priority_ie(uint8 radio_prio, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
(*ie_ptr)[0] = radio_prio << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_radio_priority_ie(uint8** ie_ptr, uint8 bit_offset, uint8* radio_prio)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && radio_prio != NULL) {
|
|
*radio_prio = ((*ie_ptr)[0] >> bit_offset) & 0x07;
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Request Type
|
|
|
|
Description: Indicates whether the UE requests to establish a new
|
|
connectivity to a PDN or keep the connection(s) to
|
|
which it has connected via non-3GPP access.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.14
|
|
24.008 v10.2.0 Section 10.5.6.17
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_request_type_ie(uint8 req_type, uint8 bit_offset, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL) {
|
|
**ie_ptr |= req_type << bit_offset;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_request_type_ie(uint8** ie_ptr, uint8 bit_offset, uint8* req_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && req_type != NULL) {
|
|
*req_type = (**ie_ptr >> bit_offset) & 0x07;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Traffic Flow Aggregate Description
|
|
|
|
Description: Specifies the aggregate of one or more packet filters
|
|
and their related parameters and operations.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.15
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_traffic_flow_aggregate_description_ie(LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT* tfad,
|
|
uint8** ie_ptr)
|
|
{
|
|
return (liblte_mme_pack_traffic_flow_template_ie((LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT*)tfad, ie_ptr));
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_traffic_flow_aggregate_description_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_TRAFFIC_FLOW_AGGREGATE_DESCRIPTION_STRUCT* tfad)
|
|
{
|
|
return (liblte_mme_unpack_traffic_flow_template_ie(ie_ptr, (LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT*)tfad));
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Traffic Flow Template
|
|
|
|
Description: Specifies the TFT parameters and operations for a
|
|
PDP context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.16
|
|
24.008 v10.2.0 Section 10.5.6.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_traffic_flow_template_ie(LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft, uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 idx;
|
|
uint32 i;
|
|
uint32 j;
|
|
|
|
if (tft != NULL && ie_ptr != NULL) {
|
|
idx = 1;
|
|
(*ie_ptr)[idx] = (tft->tft_op_code & 0x07) << 5;
|
|
if (0 != tft->parameter_list_size) {
|
|
(*ie_ptr)[idx] |= 0x10;
|
|
}
|
|
(*ie_ptr)[idx] |= tft->packet_filter_list_size & 0x0F;
|
|
idx++;
|
|
|
|
for (i = 0; i < tft->packet_filter_list_size; i++) {
|
|
(*ie_ptr)[idx] = (tft->packet_filter_list[i].dir & 0x0F) << 4;
|
|
(*ie_ptr)[idx] |= tft->packet_filter_list[i].id & 0x0F;
|
|
idx++;
|
|
if (LIBLTE_MME_TFT_OPERATION_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING_TFT != tft->tft_op_code) {
|
|
(*ie_ptr)[idx] = tft->packet_filter_list[i].eval_precedence;
|
|
idx++;
|
|
(*ie_ptr)[idx] = tft->packet_filter_list[i].filter_size;
|
|
idx++;
|
|
for (j = 0; j < tft->packet_filter_list[i].filter_size; j++) {
|
|
(*ie_ptr)[idx] = tft->packet_filter_list[i].filter[j];
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < tft->parameter_list_size; i++) {
|
|
(*ie_ptr)[idx] = tft->parameter_list[i].id;
|
|
idx++;
|
|
(*ie_ptr)[idx] = tft->parameter_list[i].parameter_size;
|
|
idx++;
|
|
for (j = 0; j < tft->parameter_list[i].parameter_size; j++) {
|
|
(*ie_ptr)[idx] = tft->parameter_list[i].parameter[j];
|
|
idx++;
|
|
}
|
|
}
|
|
(*ie_ptr)[0] = idx - 1;
|
|
*ie_ptr += idx;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_traffic_flow_template_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 idx;
|
|
uint32 i;
|
|
uint32 j;
|
|
bool param_list_present;
|
|
|
|
if (ie_ptr != NULL && tft != NULL) {
|
|
idx = 1;
|
|
tft->tft_op_code = (LIBLTE_MME_TFT_OPERATION_CODE_ENUM)(((*ie_ptr)[idx] >> 5) & 0x07);
|
|
param_list_present = ((*ie_ptr)[idx] >> 4) & 0x01;
|
|
tft->packet_filter_list_size = (*ie_ptr)[idx] & 0x0F;
|
|
idx++;
|
|
|
|
for (i = 0; i < tft->packet_filter_list_size; i++) {
|
|
tft->packet_filter_list[i].dir = (LIBLTE_MME_TFT_PACKET_FILTER_DIRECTION_ENUM)(((*ie_ptr)[idx] >> 4) & 0x0F);
|
|
tft->packet_filter_list[i].id = (*ie_ptr)[idx] & 0x0F;
|
|
idx++;
|
|
if (LIBLTE_MME_TFT_OPERATION_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING_TFT != tft->tft_op_code) {
|
|
tft->packet_filter_list[i].eval_precedence = (*ie_ptr)[idx];
|
|
idx++;
|
|
tft->packet_filter_list[i].filter_size = (*ie_ptr)[idx];
|
|
idx++;
|
|
for (j = 0; j < tft->packet_filter_list[i].filter_size; j++) {
|
|
tft->packet_filter_list[i].filter[j] = (*ie_ptr)[idx];
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
tft->parameter_list_size = 0;
|
|
if (param_list_present) {
|
|
while (idx < (*ie_ptr)[0]) {
|
|
tft->parameter_list[tft->parameter_list_size].id = (*ie_ptr)[idx];
|
|
idx++;
|
|
tft->parameter_list[tft->parameter_list_size].parameter_size = (*ie_ptr)[idx];
|
|
idx++;
|
|
for (i = 0; i < tft->parameter_list[tft->parameter_list_size].parameter_size; i++) {
|
|
tft->parameter_list[tft->parameter_list_size].parameter[i] = (*ie_ptr)[idx];
|
|
idx++;
|
|
}
|
|
tft->parameter_list_size++;
|
|
}
|
|
}
|
|
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Transaction Identifier
|
|
|
|
Description: Represents the corresponding PDP context in A/Gb
|
|
mode or Iu mode which is mapped from the EPS bearer
|
|
context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.9.4.17
|
|
24.008 v10.2.0 Section 10.5.6.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_transaction_identifier_ie(LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT* trans_id,
|
|
uint8** ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (trans_id != NULL && ie_ptr != NULL) {
|
|
if (LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE == trans_id->tio) {
|
|
(*ie_ptr)[0] = 2;
|
|
} else {
|
|
(*ie_ptr)[0] = 1;
|
|
}
|
|
(*ie_ptr)[1] = ((trans_id->ti_flag & 0x01) << 7) | ((trans_id->tio & 0x07) << 4);
|
|
if (LIBLTE_MME_TI_VALUE_IS_GIVEN_BY_TIE == trans_id->tio) {
|
|
(*ie_ptr)[2] = 0x80 | (trans_id->tie & 0x7F);
|
|
*ie_ptr += 3;
|
|
} else {
|
|
*ie_ptr += 2;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_transaction_identifier_ie(uint8** ie_ptr,
|
|
LIBLTE_MME_TRANSACTION_IDENTIFIER_STRUCT* trans_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (ie_ptr != NULL && trans_id != NULL) {
|
|
uint8_t len = (*ie_ptr)[0];
|
|
trans_id->ti_flag = (*ie_ptr)[1] >> 7;
|
|
trans_id->tio = ((*ie_ptr)[1] >> 4) & 0x07;
|
|
if (len > 2 || len == 0) {
|
|
return err;
|
|
}
|
|
|
|
if (2 == len) {
|
|
trans_id->tie = (*ie_ptr)[2] & 0x7F;
|
|
}
|
|
|
|
*ie_ptr += (*ie_ptr)[0] + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
MESSAGE FUNCTIONS
|
|
*******************************************************************************/
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Message Header (Plain NAS Message)
|
|
|
|
Description: Security header for NAS messages.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.1
|
|
*********************************************************************/
|
|
|
|
LIBLTE_ERROR_ENUM liblte_mme_parse_msg_sec_header(LIBLTE_BYTE_MSG_STRUCT* msg, uint8* pd, uint8* sec_hdr_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if (msg != NULL && pd != NULL && sec_hdr_type != NULL) {
|
|
*sec_hdr_type = (uint8)((msg->msg[0] & 0xF0) >> 4);
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Message Header (Plain NAS Message)
|
|
|
|
Description: Message header for plain NAS messages.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 9.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_parse_msg_header(LIBLTE_BYTE_MSG_STRUCT* msg, uint8* pd, uint8* msg_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && pd != NULL && msg_type != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
|
|
// Protocol Discriminator
|
|
*pd = msg->msg[0] & 0x0F;
|
|
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST == sec_hdr_type) {
|
|
*msg_type = LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST;
|
|
} else {
|
|
if (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT == *pd) {
|
|
// Message Type
|
|
*msg_type = msg->msg[2];
|
|
} else {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
// Message Type
|
|
*msg_type = msg->msg[1];
|
|
} else {
|
|
// Protocol Discriminator
|
|
*pd = msg->msg[6] & 0x0F;
|
|
|
|
if (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT == *pd) {
|
|
*msg_type = msg->msg[8];
|
|
} else {
|
|
*msg_type = msg->msg[7];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_security_protected_nas_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* sec_msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = sec_msg->msg;
|
|
uint32 i;
|
|
|
|
if (msg != NULL && sec_msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// NAS Message
|
|
for (i = 0; i < msg->N_bytes; i++) {
|
|
*msg_ptr = msg->msg[i];
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
sec_msg->N_bytes = msg_ptr - sec_msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Attach Accept
|
|
|
|
Description: Sent by the network to the UE to indicate that the
|
|
corresponding attach request has been accepted.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_accept_msg(LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT* attach_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (attach_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// EPS Attach Result & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_eps_attach_result_ie(attach_accept->eps_attach_result, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// T3412 Value
|
|
liblte_mme_pack_gprs_timer_ie(&attach_accept->t3412, &msg_ptr);
|
|
|
|
// TAI List
|
|
liblte_mme_pack_tracking_area_identity_list_ie(&attach_accept->tai_list, &msg_ptr);
|
|
|
|
// ESM Message Container
|
|
liblte_mme_pack_esm_message_container_ie(&attach_accept->esm_msg, &msg_ptr);
|
|
|
|
// GUTI
|
|
if (attach_accept->guti_present) {
|
|
*msg_ptr = LIBLTE_MME_GUTI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_mobile_id_ie(&attach_accept->guti, &msg_ptr);
|
|
}
|
|
|
|
// Location Area Identification
|
|
if (attach_accept->lai_present) {
|
|
*msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_location_area_id_ie(&attach_accept->lai, &msg_ptr);
|
|
}
|
|
|
|
// MS Identity
|
|
if (attach_accept->ms_id_present) {
|
|
*msg_ptr = LIBLTE_MME_MS_IDENTITY_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_mobile_id_ie(&attach_accept->ms_id, &msg_ptr);
|
|
}
|
|
|
|
// EMM Cause
|
|
if (attach_accept->emm_cause_present) {
|
|
*msg_ptr = LIBLTE_MME_EMM_CAUSE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_emm_cause_ie(attach_accept->emm_cause, &msg_ptr);
|
|
}
|
|
|
|
// T3402 Value
|
|
if (attach_accept->t3402_present) {
|
|
*msg_ptr = LIBLTE_MME_T3402_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&attach_accept->t3402, &msg_ptr);
|
|
}
|
|
|
|
// T3423 Value
|
|
if (attach_accept->t3423_present) {
|
|
*msg_ptr = LIBLTE_MME_T3423_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&attach_accept->t3423, &msg_ptr);
|
|
}
|
|
|
|
// Equivalent PLMNs
|
|
if (attach_accept->equivalent_plmns_present) {
|
|
*msg_ptr = LIBLTE_MME_EQUIVALENT_PLMNS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_plmn_list_ie(&attach_accept->equivalent_plmns, &msg_ptr);
|
|
}
|
|
|
|
// Emergency Number List
|
|
if (attach_accept->emerg_num_list_present) {
|
|
*msg_ptr = LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_emergency_number_list_ie(&attach_accept->emerg_num_list, &msg_ptr);
|
|
}
|
|
|
|
// EPS Network Feature Support
|
|
if (attach_accept->eps_network_feature_support_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_network_feature_support_ie(&attach_accept->eps_network_feature_support, &msg_ptr);
|
|
}
|
|
|
|
// Additional Update Result
|
|
if (attach_accept->additional_update_result_present) {
|
|
*msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4;
|
|
liblte_mme_pack_additional_update_result_ie(attach_accept->additional_update_result, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// T3412 Extended Value
|
|
if (attach_accept->t3412_ext_present) {
|
|
*msg_ptr = LIBLTE_MME_T3412_EXTENDED_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_3_ie(&attach_accept->t3412_ext, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_accept_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT* attach_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && attach_accept != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EPS Attach Result & Spare Half Octet
|
|
liblte_mme_unpack_eps_attach_result_ie(&msg_ptr, 0, &attach_accept->eps_attach_result);
|
|
msg_ptr++;
|
|
|
|
// T3412 Value
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3412);
|
|
|
|
// TAI List
|
|
liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &attach_accept->tai_list);
|
|
|
|
// ESM Message Container
|
|
liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_accept->esm_msg);
|
|
|
|
// GUTI
|
|
if (LIBLTE_MME_GUTI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_accept->guti);
|
|
attach_accept->guti_present = true;
|
|
} else {
|
|
attach_accept->guti_present = false;
|
|
}
|
|
|
|
// Location Area Identification
|
|
if (LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_location_area_id_ie(&msg_ptr, &attach_accept->lai);
|
|
attach_accept->lai_present = true;
|
|
} else {
|
|
attach_accept->lai_present = false;
|
|
}
|
|
|
|
// MS Identity
|
|
if (LIBLTE_MME_MS_IDENTITY_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_mobile_id_ie(&msg_ptr, &attach_accept->ms_id);
|
|
attach_accept->ms_id_present = true;
|
|
} else {
|
|
attach_accept->ms_id_present = false;
|
|
}
|
|
|
|
// EMM Cause
|
|
if (LIBLTE_MME_EMM_CAUSE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &attach_accept->emm_cause);
|
|
attach_accept->emm_cause_present = true;
|
|
} else {
|
|
attach_accept->emm_cause_present = false;
|
|
}
|
|
|
|
// T3402 Value
|
|
if (LIBLTE_MME_T3402_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3402);
|
|
attach_accept->t3402_present = true;
|
|
} else {
|
|
attach_accept->t3402_present = false;
|
|
}
|
|
|
|
// T3423 Value
|
|
if (LIBLTE_MME_T3423_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &attach_accept->t3423);
|
|
attach_accept->t3423_present = true;
|
|
} else {
|
|
attach_accept->t3423_present = false;
|
|
}
|
|
|
|
// Equivalent PLMNs
|
|
if (LIBLTE_MME_EQUIVALENT_PLMNS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_plmn_list_ie(&msg_ptr, &attach_accept->equivalent_plmns);
|
|
attach_accept->equivalent_plmns_present = true;
|
|
} else {
|
|
attach_accept->equivalent_plmns_present = false;
|
|
}
|
|
|
|
// Emergency Number List
|
|
if (LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_emergency_number_list_ie(&msg_ptr, &attach_accept->emerg_num_list);
|
|
attach_accept->emerg_num_list_present = true;
|
|
} else {
|
|
attach_accept->emerg_num_list_present = false;
|
|
}
|
|
|
|
// EPS Network Feature Support
|
|
if (LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_network_feature_support_ie(&msg_ptr, &attach_accept->eps_network_feature_support);
|
|
attach_accept->eps_network_feature_support_present = true;
|
|
} else {
|
|
attach_accept->eps_network_feature_support_present = false;
|
|
}
|
|
|
|
// Additional Update Result
|
|
if ((LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_additional_update_result_ie(&msg_ptr, 0, &attach_accept->additional_update_result);
|
|
msg_ptr++;
|
|
attach_accept->additional_update_result_present = true;
|
|
} else {
|
|
attach_accept->additional_update_result_present = false;
|
|
}
|
|
|
|
// T3412 Extended Value
|
|
if (LIBLTE_MME_T3412_EXTENDED_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &attach_accept->t3412_ext);
|
|
attach_accept->t3412_ext_present = true;
|
|
} else {
|
|
attach_accept->t3412_ext_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Attach Complete
|
|
|
|
Description: Sent by the UE to the network in response to an
|
|
ATTACH ACCEPT message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_complete_msg(LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT* attach_comp,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (attach_comp != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// ESM Message Container
|
|
liblte_mme_pack_esm_message_container_ie(&attach_comp->esm_msg, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_complete_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT* attach_comp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && attach_comp != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Message Container
|
|
liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_comp->esm_msg);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Attach Reject
|
|
|
|
Description: Sent by the network to the UE to indicate that the
|
|
corresponding attach request has been rejected.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_reject_msg(LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT* attach_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (attach_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_REJECT;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(attach_rej->emm_cause, &msg_ptr);
|
|
|
|
// ESM Message Container
|
|
if (attach_rej->esm_msg_present) {
|
|
*msg_ptr = LIBLTE_MME_ESM_MSG_CONTAINER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_esm_message_container_ie(&attach_rej->esm_msg, &msg_ptr);
|
|
}
|
|
|
|
// T3446 Value
|
|
if (attach_rej->t3446_value_present) {
|
|
*msg_ptr = LIBLTE_MME_T3446_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_2_ie(attach_rej->t3446_value, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ATTACH_REJECT_MSG_STRUCT* attach_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && attach_rej != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &attach_rej->emm_cause);
|
|
|
|
// ESM Message Container
|
|
if (LIBLTE_MME_ESM_MSG_CONTAINER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_rej->esm_msg);
|
|
attach_rej->esm_msg_present = true;
|
|
} else {
|
|
attach_rej->esm_msg_present = false;
|
|
}
|
|
|
|
// T3446 Value
|
|
if (LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &attach_rej->t3446_value);
|
|
attach_rej->t3446_value_present = true;
|
|
} else {
|
|
attach_rej->t3446_value_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Attach Request
|
|
|
|
Description: Sent by the UE to the network to perform an attach
|
|
procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT* attach_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
return liblte_mme_pack_attach_request_msg(attach_req, LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS, 0, msg);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_attach_request_msg(LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT* attach_req,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (attach_req != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// EPS Attach Type & NAS Key Set Identifier
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_eps_attach_type_ie(attach_req->eps_attach_type, 0, &msg_ptr);
|
|
liblte_mme_pack_nas_key_set_id_ie(&attach_req->nas_ksi, 4, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// EPS Mobile ID
|
|
liblte_mme_pack_eps_mobile_id_ie(&attach_req->eps_mobile_id, &msg_ptr);
|
|
|
|
// UE Network Capability
|
|
liblte_mme_pack_ue_network_capability_ie(&attach_req->ue_network_cap, &msg_ptr);
|
|
|
|
// ESM Message Container
|
|
liblte_mme_pack_esm_message_container_ie(&attach_req->esm_msg, &msg_ptr);
|
|
|
|
// Old P-TMSI Signature
|
|
if (attach_req->old_p_tmsi_signature_present) {
|
|
*msg_ptr = LIBLTE_MME_P_TMSI_SIGNATURE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_p_tmsi_signature_ie(attach_req->old_p_tmsi_signature, &msg_ptr);
|
|
}
|
|
|
|
// Additional GUTI
|
|
if (attach_req->additional_guti_present) {
|
|
*msg_ptr = LIBLTE_MME_ADDITIONAL_GUTI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_mobile_id_ie(&attach_req->additional_guti, &msg_ptr);
|
|
}
|
|
|
|
// Last Visited Registered TAI
|
|
if (attach_req->last_visited_registered_tai_present) {
|
|
*msg_ptr = LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_tracking_area_id_ie(&attach_req->last_visited_registered_tai, &msg_ptr);
|
|
}
|
|
|
|
// DRX Parameter
|
|
if (attach_req->drx_param_present) {
|
|
*msg_ptr = LIBLTE_MME_DRX_PARAMETER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_drx_parameter_ie(&attach_req->drx_param, &msg_ptr);
|
|
}
|
|
|
|
// MS Network Capability
|
|
if (attach_req->ms_network_cap_present) {
|
|
*msg_ptr = LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_ms_network_capability_ie(&attach_req->ms_network_cap, &msg_ptr);
|
|
}
|
|
|
|
// Old Location Area ID
|
|
if (attach_req->old_lai_present) {
|
|
*msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_location_area_id_ie(&attach_req->old_lai, &msg_ptr);
|
|
}
|
|
|
|
// TMSI Status
|
|
if (attach_req->tmsi_status_present) {
|
|
*msg_ptr = LIBLTE_MME_TMSI_STATUS_IEI << 4;
|
|
liblte_mme_pack_tmsi_status_ie(attach_req->tmsi_status, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Mobile Station Classmark 2
|
|
if (attach_req->ms_cm2_present) {
|
|
*msg_ptr = LIBLTE_MME_MS_CLASSMARK_2_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_mobile_station_classmark_2_ie(&attach_req->ms_cm2, &msg_ptr);
|
|
}
|
|
|
|
// Mobile Station Classmark 3
|
|
if (attach_req->ms_cm3_present) {
|
|
*msg_ptr = LIBLTE_MME_MS_CLASSMARK_3_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_mobile_station_classmark_3_ie(&attach_req->ms_cm3, &msg_ptr);
|
|
}
|
|
|
|
// Supported Codecs
|
|
if (attach_req->supported_codecs_present) {
|
|
*msg_ptr = LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_supported_codec_list_ie(&attach_req->supported_codecs, &msg_ptr);
|
|
}
|
|
|
|
// Additional Update Type
|
|
if (attach_req->additional_update_type_present) {
|
|
*msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4;
|
|
liblte_mme_pack_additional_update_type_ie(attach_req->additional_update_type, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Voice Domain Preference and UE's Usage Setting
|
|
if (attach_req->voice_domain_pref_and_ue_usage_setting_present) {
|
|
*msg_ptr = LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_voice_domain_pref_and_ue_usage_setting_ie(&attach_req->voice_domain_pref_and_ue_usage_setting,
|
|
&msg_ptr);
|
|
}
|
|
|
|
// Device Properties
|
|
if (attach_req->device_properties_present) {
|
|
*msg_ptr = LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4;
|
|
liblte_mme_pack_device_properties_ie(attach_req->device_properties, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Old GUTI Type
|
|
if (attach_req->old_guti_type_present) {
|
|
*msg_ptr = LIBLTE_MME_GUTI_TYPE_IEI << 4;
|
|
liblte_mme_pack_guti_type_ie(attach_req->old_guti_type, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
if (attach_req->additional_security_cap_present) {
|
|
*msg_ptr = LIBLTE_MME_ADDITIONAL_SECURITY_CAP_IEI;
|
|
msg_ptr++;
|
|
*msg_ptr = 0x4; // Length
|
|
msg_ptr++;
|
|
|
|
// Pack same capabilities that are used for EUTRA
|
|
*msg_ptr = attach_req->ue_network_cap.eea[0] << 7;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[1] << 6;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[2] << 5;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[3] << 4;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[4] << 3;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[5] << 2;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[6] << 1;
|
|
*msg_ptr |= attach_req->ue_network_cap.eea[7];
|
|
msg_ptr++;
|
|
|
|
// 0x00 (5G-EA8=0, 5G-EA9=0, 5G-EA10=0, 5G-EA11=0, 5G-EA12=0, 5G-EA13=0, 5G-EA14=0, 5G-EA15=0)
|
|
*msg_ptr = 0x00;
|
|
msg_ptr++;
|
|
|
|
// Pack same integrity caps
|
|
*msg_ptr = attach_req->ue_network_cap.eia[0] << 7;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[1] << 6;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[2] << 5;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[3] << 4;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[4] << 3;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[5] << 2;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[6] << 1;
|
|
*msg_ptr |= attach_req->ue_network_cap.eia[7];
|
|
msg_ptr++;
|
|
|
|
// 0x00 (5G-IA8=0, 5G-IA9=0, 5G-IA10=0, 5G-IA11=0, 5G-IA12=0, 5G-IA13=0, 5G-IA14=0, 5G-IA15=0)
|
|
*msg_ptr = 0x00;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_attach_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT* attach_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && attach_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EPS Attach Type & NAS Key Set Identifier
|
|
liblte_mme_unpack_eps_attach_type_ie(&msg_ptr, 0, &attach_req->eps_attach_type);
|
|
liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &attach_req->nas_ksi);
|
|
msg_ptr++;
|
|
|
|
// EPS Mobile ID
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->eps_mobile_id);
|
|
|
|
// UE Network Capability
|
|
liblte_mme_unpack_ue_network_capability_ie(&msg_ptr, &attach_req->ue_network_cap);
|
|
|
|
// ESM Message Container
|
|
liblte_mme_unpack_esm_message_container_ie(&msg_ptr, &attach_req->esm_msg);
|
|
|
|
// Old P-TMSI Signature
|
|
if (LIBLTE_MME_P_TMSI_SIGNATURE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_p_tmsi_signature_ie(&msg_ptr, &attach_req->old_p_tmsi_signature);
|
|
attach_req->old_p_tmsi_signature_present = true;
|
|
} else {
|
|
attach_req->old_p_tmsi_signature_present = false;
|
|
}
|
|
|
|
// Additional GUTI
|
|
if (LIBLTE_MME_ADDITIONAL_GUTI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &attach_req->additional_guti);
|
|
attach_req->additional_guti_present = true;
|
|
} else {
|
|
attach_req->additional_guti_present = false;
|
|
}
|
|
|
|
// Last Visited Registered TAI
|
|
if (LIBLTE_MME_LAST_VISITED_REGISTERED_TAI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_tracking_area_id_ie(&msg_ptr, &attach_req->last_visited_registered_tai);
|
|
attach_req->last_visited_registered_tai_present = true;
|
|
} else {
|
|
attach_req->last_visited_registered_tai_present = false;
|
|
}
|
|
|
|
// DRX Parameter
|
|
if (LIBLTE_MME_DRX_PARAMETER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_drx_parameter_ie(&msg_ptr, &attach_req->drx_param);
|
|
attach_req->drx_param_present = true;
|
|
} else {
|
|
attach_req->drx_param_present = false;
|
|
}
|
|
|
|
// MS Network Capability
|
|
if (LIBLTE_MME_MS_NETWORK_CAPABILITY_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_ms_network_capability_ie(&msg_ptr, &attach_req->ms_network_cap);
|
|
attach_req->ms_network_cap_present = true;
|
|
} else {
|
|
attach_req->ms_network_cap_present = false;
|
|
}
|
|
|
|
// Old Location Area ID
|
|
if (LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_location_area_id_ie(&msg_ptr, &attach_req->old_lai);
|
|
attach_req->old_lai_present = true;
|
|
} else {
|
|
attach_req->old_lai_present = false;
|
|
}
|
|
|
|
// TMSI Status
|
|
if ((LIBLTE_MME_TMSI_STATUS_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_tmsi_status_ie(&msg_ptr, 0, &attach_req->tmsi_status);
|
|
msg_ptr++;
|
|
attach_req->tmsi_status_present = true;
|
|
} else {
|
|
attach_req->tmsi_status_present = false;
|
|
}
|
|
|
|
// Mobile Station Classmark 2
|
|
if (LIBLTE_MME_MS_CLASSMARK_2_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_mobile_station_classmark_2_ie(&msg_ptr, &attach_req->ms_cm2);
|
|
attach_req->ms_cm2_present = true;
|
|
} else {
|
|
attach_req->ms_cm2_present = false;
|
|
}
|
|
|
|
// Mobile Station Classmark 3
|
|
if (LIBLTE_MME_MS_CLASSMARK_3_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_mobile_station_classmark_3_ie(&msg_ptr, &attach_req->ms_cm3);
|
|
attach_req->ms_cm3_present = true;
|
|
} else {
|
|
attach_req->ms_cm3_present = false;
|
|
}
|
|
|
|
// Supported Codecs
|
|
if (LIBLTE_MME_SUPPORTED_CODEC_LIST_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_supported_codec_list_ie(&msg_ptr, &attach_req->supported_codecs);
|
|
attach_req->supported_codecs_present = true;
|
|
} else {
|
|
attach_req->supported_codecs_present = false;
|
|
}
|
|
|
|
// Additional Update Type
|
|
if ((LIBLTE_MME_ADDITIONAL_UPDATE_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_additional_update_type_ie(&msg_ptr, 0, &attach_req->additional_update_type);
|
|
msg_ptr++;
|
|
attach_req->additional_update_type_present = true;
|
|
} else {
|
|
attach_req->additional_update_type_present = false;
|
|
}
|
|
|
|
// Voice Domain Preference and UE's Usage Setting
|
|
if (LIBLTE_MME_VOICE_DOMAIN_PREF_AND_UE_USAGE_SETTING_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_voice_domain_pref_and_ue_usage_setting_ie(&msg_ptr,
|
|
&attach_req->voice_domain_pref_and_ue_usage_setting);
|
|
attach_req->voice_domain_pref_and_ue_usage_setting_present = true;
|
|
} else {
|
|
attach_req->voice_domain_pref_and_ue_usage_setting_present = false;
|
|
}
|
|
|
|
// Device Properties
|
|
if ((LIBLTE_MME_ATTACH_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &attach_req->device_properties);
|
|
msg_ptr++;
|
|
attach_req->device_properties_present = true;
|
|
} else {
|
|
attach_req->device_properties_present = false;
|
|
}
|
|
|
|
// Old GUTI Type
|
|
if ((LIBLTE_MME_GUTI_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_guti_type_ie(&msg_ptr, 0, &attach_req->old_guti_type);
|
|
msg_ptr++;
|
|
attach_req->old_guti_type_present = true;
|
|
} else {
|
|
attach_req->old_guti_type_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Authentication Failure
|
|
|
|
Description: Sent by the UE to the network to indicate that
|
|
authentication of the network has failed.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_failure_msg(LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT* auth_fail,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (auth_fail != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(auth_fail->emm_cause, &msg_ptr);
|
|
|
|
// Authentication Failure Parameter
|
|
if (auth_fail->auth_fail_param_present) {
|
|
*msg_ptr = LIBLTE_MME_AUTHENTICATION_FAILURE_PARAMETER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_authentication_failure_parameter_ie(auth_fail->auth_fail_param, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_failure_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_AUTHENTICATION_FAILURE_MSG_STRUCT* auth_fail)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && auth_fail != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &auth_fail->emm_cause);
|
|
|
|
// Authentication Failure Parameter
|
|
if (LIBLTE_MME_AUTHENTICATION_FAILURE_PARAMETER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_authentication_failure_parameter_ie(&msg_ptr, auth_fail->auth_fail_param);
|
|
auth_fail->auth_fail_param_present = true;
|
|
} else {
|
|
auth_fail->auth_fail_param_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Authentication Reject
|
|
|
|
Description: Sent by the network to the UE to indicate that the
|
|
authentication procedure has failed and that the UE
|
|
shall abort all activities.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_reject_msg(LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT* auth_reject,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (auth_reject != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REJECT;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_AUTHENTICATION_REJECT_MSG_STRUCT* auth_reject)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && auth_reject != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Authentication Request
|
|
|
|
Description: Sent by the network to the UE to initiate
|
|
authentication of the UE identity.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_request_msg(LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT* auth_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (auth_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// NAS Key Set Identifier & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_nas_key_set_id_ie(&auth_req->nas_ksi, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// Authentication Parameter RAND
|
|
liblte_mme_pack_authentication_parameter_rand_ie(auth_req->rand, &msg_ptr);
|
|
|
|
// Authentication Parameter AUTN
|
|
liblte_mme_pack_authentication_parameter_autn_ie(auth_req->autn, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_authentication_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_AUTHENTICATION_REQUEST_MSG_STRUCT* auth_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && auth_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// NAS Key Set Identifier & Spare Half Octet
|
|
liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 0, &auth_req->nas_ksi);
|
|
msg_ptr++;
|
|
|
|
// Authentication Parameter RAND
|
|
liblte_mme_unpack_authentication_parameter_rand_ie(&msg_ptr, auth_req->rand);
|
|
|
|
// Authentication Parameter AUTN
|
|
liblte_mme_unpack_authentication_parameter_autn_ie(&msg_ptr, auth_req->autn);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Authentication Response
|
|
|
|
Description: Sent by the UE to the network to deliver a calculated
|
|
authentication response to the network.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.8
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_authentication_response_msg(LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT* auth_resp,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (auth_resp != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE;
|
|
msg_ptr++;
|
|
|
|
// Authentication Response Parameter (RES)
|
|
liblte_mme_pack_authentication_response_parameter_ie(auth_resp->res, auth_resp->res_len, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_authentication_response_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT* auth_resp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && auth_resp != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Authentication Response Parameter (RES)
|
|
liblte_mme_unpack_authentication_response_parameter_ie(&msg_ptr, auth_resp->res);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: CS Service Notification
|
|
|
|
Description: Sent by the network when a paging request with CS
|
|
call indicator was received via SGs for a UE, and a
|
|
NAS signalling connection is already established for
|
|
the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.9
|
|
*********************************************************************/
|
|
// TODO
|
|
|
|
/*********************************************************************
|
|
Message Name: Detach Accept
|
|
|
|
Description: Sent by the network to indicate that the detach
|
|
procedure has been completed.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.10
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_detach_accept_msg(LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT* detach_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (detach_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DETACH_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_accept_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DETACH_ACCEPT_MSG_STRUCT* detach_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && detach_accept != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Detach Request
|
|
|
|
Description: Sent by the UE to request the release of an EMM
|
|
context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.11
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_detach_request_msg(LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT* detach_req,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (detach_req != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DETACH_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Detach Type & NAS Key Set Identifier
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_detach_type_ie(&detach_req->detach_type, 0, &msg_ptr);
|
|
liblte_mme_pack_nas_key_set_id_ie(&detach_req->nas_ksi, 4, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// EPS Mobile ID
|
|
liblte_mme_pack_eps_mobile_id_ie(&detach_req->eps_mobile_id, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_detach_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DETACH_REQUEST_MSG_STRUCT* detach_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && detach_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Detach Type & NAS Key Set Identifier
|
|
liblte_mme_unpack_detach_type_ie(&msg_ptr, 0, &detach_req->detach_type);
|
|
liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &detach_req->nas_ksi);
|
|
msg_ptr++;
|
|
|
|
// EPS Mobile ID
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &detach_req->eps_mobile_id);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Downlink NAS Transport
|
|
|
|
Description: Sent by the network to the UE in order to carry an
|
|
SMS message in encapsulated format.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_downlink_nas_transport_msg(LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT* dl_nas_transport,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (dl_nas_transport != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DOWNLINK_NAS_TRANSPORT;
|
|
msg_ptr++;
|
|
|
|
// NAS Message Container
|
|
liblte_mme_pack_nas_message_container_ie(&dl_nas_transport->nas_msg, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_downlink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DOWNLINK_NAS_TRANSPORT_MSG_STRUCT* dl_nas_transport)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && dl_nas_transport != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// NAS Message Container
|
|
liblte_mme_unpack_nas_message_container_ie(&msg_ptr, &dl_nas_transport->nas_msg);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: EMM Information
|
|
|
|
Description: Sent by the network at any time during EMM context is
|
|
established to send certain information to the UE.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_emm_information_msg(LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT* emm_info,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (emm_info != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_EMM_INFORMATION;
|
|
msg_ptr++;
|
|
|
|
// Full Name For Network
|
|
if (emm_info->full_net_name_present) {
|
|
*msg_ptr = LIBLTE_MME_FULL_NAME_FOR_NETWORK_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_network_name_ie(&emm_info->full_net_name, &msg_ptr);
|
|
}
|
|
|
|
// Short Name For Network
|
|
if (emm_info->short_net_name_present) {
|
|
*msg_ptr = LIBLTE_MME_SHORT_NAME_FOR_NETWORK_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_network_name_ie(&emm_info->short_net_name, &msg_ptr);
|
|
}
|
|
|
|
// Local Time Zone
|
|
if (emm_info->local_time_zone_present) {
|
|
*msg_ptr = LIBLTE_MME_LOCAL_TIME_ZONE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_time_zone_ie(emm_info->local_time_zone, &msg_ptr);
|
|
}
|
|
|
|
// Universal Time And Local Time Zone
|
|
if (emm_info->utc_and_local_time_zone_present) {
|
|
*msg_ptr = LIBLTE_MME_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_time_zone_and_time_ie(&emm_info->utc_and_local_time_zone, &msg_ptr);
|
|
}
|
|
|
|
// Network Daylight Saving Time
|
|
if (emm_info->net_dst_present) {
|
|
*msg_ptr = LIBLTE_MME_NETWORK_DAYLIGHT_SAVING_TIME_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_daylight_saving_time_ie(emm_info->net_dst, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_information_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_EMM_INFORMATION_MSG_STRUCT* emm_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8* msg_end = msg->msg + msg->N_bytes;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && emm_info != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Full Name For Network
|
|
if (LIBLTE_MME_FULL_NAME_FOR_NETWORK_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_network_name_ie(&msg_ptr, &emm_info->full_net_name);
|
|
emm_info->full_net_name_present = true;
|
|
} else {
|
|
emm_info->full_net_name_present = false;
|
|
}
|
|
|
|
// Short Name For Network
|
|
if (msg_ptr < msg_end && LIBLTE_MME_SHORT_NAME_FOR_NETWORK_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_network_name_ie(&msg_ptr, &emm_info->short_net_name);
|
|
emm_info->short_net_name_present = true;
|
|
} else {
|
|
emm_info->short_net_name_present = false;
|
|
}
|
|
|
|
// Local Time Zone
|
|
if (msg_ptr < msg_end && LIBLTE_MME_LOCAL_TIME_ZONE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_time_zone_ie(&msg_ptr, &emm_info->local_time_zone);
|
|
emm_info->local_time_zone_present = true;
|
|
} else {
|
|
emm_info->local_time_zone_present = false;
|
|
}
|
|
|
|
// Universal Time And Local Time Zone
|
|
if (msg_ptr < msg_end && LIBLTE_MME_UNIVERSAL_TIME_AND_LOCAL_TIME_ZONE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_time_zone_and_time_ie(&msg_ptr, &emm_info->utc_and_local_time_zone);
|
|
emm_info->utc_and_local_time_zone_present = true;
|
|
} else {
|
|
emm_info->utc_and_local_time_zone_present = false;
|
|
}
|
|
|
|
// Network Daylight Saving Time
|
|
if (msg_ptr < msg_end && LIBLTE_MME_NETWORK_DAYLIGHT_SAVING_TIME_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_daylight_saving_time_ie(&msg_ptr, &emm_info->net_dst);
|
|
emm_info->net_dst_present = true;
|
|
} else {
|
|
emm_info->net_dst_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: EMM Status
|
|
|
|
Description: Sent by the UE or by the network at any time to
|
|
report certain error conditions.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.14
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_emm_status_msg(LIBLTE_MME_EMM_STATUS_MSG_STRUCT* emm_status,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (emm_status != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_EMM_STATUS;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(emm_status->emm_cause, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_emm_status_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_EMM_STATUS_MSG_STRUCT* emm_status)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && emm_status != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &emm_status->emm_cause);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Extended Service Request
|
|
|
|
Description: Sent by the UE to the network to initiate a CS
|
|
fallback or 1xCS fallback call or respond to a mobile
|
|
terminated CS fallback or 1xCS fallback request from
|
|
the network or to request the establishment of a NAS
|
|
signalling connection and of the radio and S1 bearers
|
|
for packet services, if the UE needs to provide
|
|
additional information that cannot be provided via a
|
|
SERVICE REQUEST message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.15
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_extended_service_request_msg(LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT* ext_service_req,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ext_service_req != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_EXTENDED_SERVICE_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Service Type & NAS Key Set Identifier
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_service_type_ie(ext_service_req->service_type, 0, &msg_ptr);
|
|
liblte_mme_pack_nas_key_set_id_ie(&ext_service_req->nas_ksi, 4, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// M-TMSI
|
|
liblte_mme_pack_mobile_id_ie(&ext_service_req->m_tmsi, &msg_ptr);
|
|
|
|
// CSFB Response
|
|
if (ext_service_req->csfb_resp_present) {
|
|
*msg_ptr = LIBLTE_MME_CSFB_RESPONSE_IEI << 4;
|
|
liblte_mme_pack_csfb_response_ie(ext_service_req->csfb_resp, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// EPS Bearer Context Status
|
|
if (ext_service_req->eps_bearer_context_status_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_bearer_context_status_ie(&ext_service_req->eps_bearer_context_status, &msg_ptr);
|
|
}
|
|
|
|
// Device Properties
|
|
if (ext_service_req->device_props_present) {
|
|
*msg_ptr = LIBLTE_MME_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_IEI << 4;
|
|
liblte_mme_pack_device_properties_ie(ext_service_req->device_props, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_extended_service_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_EXTENDED_SERVICE_REQUEST_MSG_STRUCT* ext_service_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ext_service_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Service Type & NAS Key Set Identifier
|
|
liblte_mme_unpack_service_type_ie(&msg_ptr, 0, &ext_service_req->service_type);
|
|
liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 4, &ext_service_req->nas_ksi);
|
|
msg_ptr++;
|
|
|
|
// M-TMSI
|
|
liblte_mme_unpack_mobile_id_ie(&msg_ptr, &ext_service_req->m_tmsi);
|
|
|
|
// CSFB Response
|
|
if ((LIBLTE_MME_CSFB_RESPONSE_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_csfb_response_ie(&msg_ptr, 0, &ext_service_req->csfb_resp);
|
|
msg_ptr++;
|
|
ext_service_req->csfb_resp_present = true;
|
|
} else {
|
|
ext_service_req->csfb_resp_present = false;
|
|
}
|
|
|
|
// EPS Bearer Context Status
|
|
if (LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_bearer_context_status_ie(&msg_ptr, &ext_service_req->eps_bearer_context_status);
|
|
ext_service_req->eps_bearer_context_status_present = true;
|
|
} else {
|
|
ext_service_req->eps_bearer_context_status_present = false;
|
|
}
|
|
|
|
// Device Properties
|
|
if ((LIBLTE_MME_EXTENDED_SERVICE_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &ext_service_req->device_props);
|
|
msg_ptr++;
|
|
ext_service_req->device_props_present = true;
|
|
} else {
|
|
ext_service_req->device_props_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: GUTI Reallocation Command
|
|
|
|
Description: Sent by the network to the UE to reallocate a GUTI
|
|
and optionally provide a new TAI list.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.16
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_guti_reallocation_command_msg(LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT* guti_realloc_cmd,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (guti_realloc_cmd != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMMAND;
|
|
msg_ptr++;
|
|
|
|
// GUTI
|
|
liblte_mme_pack_eps_mobile_id_ie(&guti_realloc_cmd->guti, &msg_ptr);
|
|
|
|
// TAI List
|
|
if (guti_realloc_cmd->tai_list_present) {
|
|
*msg_ptr = LIBLTE_MME_TAI_LIST_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_tracking_area_identity_list_ie(&guti_realloc_cmd->tai_list, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_guti_reallocation_command_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_GUTI_REALLOCATION_COMMAND_MSG_STRUCT* guti_realloc_cmd)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && guti_realloc_cmd != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// GUTI
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &guti_realloc_cmd->guti);
|
|
|
|
// TAI List
|
|
if (LIBLTE_MME_TAI_LIST_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &guti_realloc_cmd->tai_list);
|
|
guti_realloc_cmd->tai_list_present = true;
|
|
} else {
|
|
guti_realloc_cmd->tai_list_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: GUTI Reallocation Complete
|
|
|
|
Description: Sent by the UE to the network to indicate that
|
|
reallocation of a GUTI has taken place.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.17
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_guti_reallocation_complete_msg(LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT* guti_realloc_complete,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (guti_realloc_complete != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_guti_reallocation_complete_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_GUTI_REALLOCATION_COMPLETE_MSG_STRUCT* guti_realloc_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && guti_realloc_complete != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Identity Request
|
|
|
|
Description: Sent by the network to the UE to request the UE to
|
|
provide the specified identity.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.18
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_identity_request_msg(LIBLTE_MME_ID_REQUEST_MSG_STRUCT* id_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (id_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_IDENTITY_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// ID Type & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_identity_type_2_ie(id_req->id_type, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ID_REQUEST_MSG_STRUCT* id_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && id_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ID Type & Spare Half Offset
|
|
liblte_mme_unpack_identity_type_2_ie(&msg_ptr, 0, &id_req->id_type);
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
/*********************************************************************
|
|
Message Name: Identity Response
|
|
|
|
Description: Sent by the UE to the network in response to an
|
|
IDENTITY REQUEST message and provides the requested
|
|
identity.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.19
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_identity_response_msg(LIBLTE_MME_ID_RESPONSE_MSG_STRUCT* id_resp,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (id_resp != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE;
|
|
msg_ptr++;
|
|
|
|
// Mobile Identity
|
|
liblte_mme_pack_mobile_id_ie(&id_resp->mobile_id, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_identity_response_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ID_RESPONSE_MSG_STRUCT* id_resp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && id_resp != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Mobile Identity
|
|
liblte_mme_unpack_mobile_id_ie(&msg_ptr, &id_resp->mobile_id);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Command
|
|
|
|
Description: Sent by the network to the UE to establish NAS
|
|
signalling security.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.20
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_command_msg(LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT* sec_mode_cmd,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (sec_mode_cmd != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMMAND;
|
|
msg_ptr++;
|
|
|
|
// Selected NAS Security Algorithms
|
|
liblte_mme_pack_nas_security_algorithms_ie(&sec_mode_cmd->selected_nas_sec_algs, &msg_ptr);
|
|
|
|
// NAS Key Set Identifier & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_nas_key_set_id_ie(&sec_mode_cmd->nas_ksi, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// Replayed UE Security Capabilities
|
|
liblte_mme_pack_ue_security_capabilities_ie(&sec_mode_cmd->ue_security_cap, &msg_ptr);
|
|
|
|
// IMEISV Request
|
|
if (sec_mode_cmd->imeisv_req_present) {
|
|
*msg_ptr = LIBLTE_MME_IMEISV_REQUEST_IEI << 4;
|
|
liblte_mme_pack_imeisv_request_ie(sec_mode_cmd->imeisv_req, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Replayed NONCE_ue
|
|
if (sec_mode_cmd->nonce_ue_present) {
|
|
*msg_ptr = LIBLTE_MME_REPLAYED_NONCE_UE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_nonce_ie(sec_mode_cmd->nonce_ue, &msg_ptr);
|
|
}
|
|
|
|
// NONCE_mme
|
|
if (sec_mode_cmd->nonce_mme_present) {
|
|
*msg_ptr = LIBLTE_MME_NONCE_MME_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_nonce_ie(sec_mode_cmd->nonce_mme, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_command_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_SECURITY_MODE_COMMAND_MSG_STRUCT* sec_mode_cmd)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && sec_mode_cmd != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Selected NAS Security Algorithms
|
|
liblte_mme_unpack_nas_security_algorithms_ie(&msg_ptr, &sec_mode_cmd->selected_nas_sec_algs);
|
|
|
|
// NAS Key Set Identifier & Spare Half Octet
|
|
liblte_mme_unpack_nas_key_set_id_ie(&msg_ptr, 0, &sec_mode_cmd->nas_ksi);
|
|
msg_ptr++;
|
|
|
|
// Replayed UE Security Capabilities
|
|
liblte_mme_unpack_ue_security_capabilities_ie(&msg_ptr, &sec_mode_cmd->ue_security_cap);
|
|
|
|
// IMEISV Request
|
|
if ((LIBLTE_MME_IMEISV_REQUEST_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_imeisv_request_ie(&msg_ptr, 0, &sec_mode_cmd->imeisv_req);
|
|
msg_ptr++;
|
|
sec_mode_cmd->imeisv_req_present = true;
|
|
} else {
|
|
sec_mode_cmd->imeisv_req_present = false;
|
|
}
|
|
|
|
// Replayed NONCE_ue
|
|
if (LIBLTE_MME_REPLAYED_NONCE_UE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_nonce_ie(&msg_ptr, &sec_mode_cmd->nonce_ue);
|
|
sec_mode_cmd->nonce_ue_present = true;
|
|
} else {
|
|
sec_mode_cmd->nonce_ue_present = false;
|
|
}
|
|
|
|
// NONCE_mme
|
|
if (LIBLTE_MME_NONCE_MME_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_nonce_ie(&msg_ptr, &sec_mode_cmd->nonce_mme);
|
|
sec_mode_cmd->nonce_mme_present = true;
|
|
} else {
|
|
sec_mode_cmd->nonce_mme_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Complete
|
|
|
|
Description: Sent by the UE to the network in response to a
|
|
SECURITY MODE COMMAND message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.21
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_security_mode_complete_msg(LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT* sec_mode_comp,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (sec_mode_comp != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// IMEISV
|
|
if (sec_mode_comp->imeisv_present) {
|
|
*msg_ptr = LIBLTE_MME_IMEISV_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_mobile_id_ie(&sec_mode_comp->imeisv, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_security_mode_complete_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT* sec_mode_comp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && sec_mode_comp != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// IMEISV
|
|
if (LIBLTE_MME_IMEISV_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_mobile_id_ie(&msg_ptr, &sec_mode_comp->imeisv);
|
|
sec_mode_comp->imeisv_present = true;
|
|
} else {
|
|
sec_mode_comp->imeisv_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Reject
|
|
|
|
Description: Sent by the UE to the network to indicate that the
|
|
corresponding security mode command has been
|
|
rejected.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.22
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_security_mode_reject_msg(LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT* sec_mode_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (sec_mode_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_SECURITY_MODE_REJECT;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(sec_mode_rej->emm_cause, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_security_mode_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_SECURITY_MODE_REJECT_MSG_STRUCT* sec_mode_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && sec_mode_rej != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &sec_mode_rej->emm_cause);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Service Reject
|
|
|
|
Description: Sent by the network to the UE in order to reject the
|
|
service request procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.24
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_service_reject_msg(LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT* service_rej,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (service_rej != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_SERVICE_REJECT;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(service_rej->emm_cause, &msg_ptr);
|
|
|
|
// T3442 Value
|
|
if (service_rej->t3442_present) {
|
|
*msg_ptr = LIBLTE_MME_T3442_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&service_rej->t3442, &msg_ptr);
|
|
}
|
|
|
|
// T3446 Value
|
|
if (service_rej->t3446_present) {
|
|
*msg_ptr = LIBLTE_MME_T3446_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_2_ie(service_rej->t3446, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_service_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_SERVICE_REJECT_MSG_STRUCT* service_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && service_rej != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &service_rej->emm_cause);
|
|
|
|
// T3442 Value
|
|
if (LIBLTE_MME_T3442_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &service_rej->t3442);
|
|
service_rej->t3442_present = true;
|
|
} else {
|
|
service_rej->t3442_present = false;
|
|
}
|
|
|
|
// T3446 Value
|
|
if (LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &service_rej->t3446);
|
|
service_rej->t3446_present = true;
|
|
} else {
|
|
service_rej->t3446_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Service Request
|
|
|
|
Description: Sent by the UE to the network to request the
|
|
establishment of a NAS signalling connection and of
|
|
the radio and S1 bearers.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.25
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_service_request_msg(LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT* service_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (service_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// KSI and Sequence Number
|
|
liblte_mme_pack_ksi_and_sequence_number_ie(&service_req->ksi_and_seq_num, &msg_ptr);
|
|
|
|
// Short MAC
|
|
liblte_mme_pack_short_mac_ie(service_req->short_mac, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_service_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_SERVICE_REQUEST_MSG_STRUCT* service_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && service_req != NULL) {
|
|
// Protocol Discriminator and Security Header Type
|
|
msg_ptr++;
|
|
|
|
// KSI and Sequence Number
|
|
liblte_mme_unpack_ksi_and_sequence_number_ie(&msg_ptr, &service_req->ksi_and_seq_num);
|
|
|
|
// Short MAC
|
|
liblte_mme_unpack_short_mac_ie(&msg_ptr, &service_req->short_mac);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Tracking Area Update Accept
|
|
|
|
Description: Sent by the network to the UE to provide the UE with
|
|
EPS mobility management related data in response to
|
|
a tracking area update request message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.26
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_tracking_area_update_accept_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT* ta_update_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ta_update_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// EPS Update Result & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_eps_update_result_ie(ta_update_accept->eps_update_result, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// T3412 Value
|
|
if (ta_update_accept->t3412_present) {
|
|
*msg_ptr = LIBLTE_MME_T3412_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3412, &msg_ptr);
|
|
}
|
|
|
|
// GUTI
|
|
if (ta_update_accept->guti_present) {
|
|
*msg_ptr = LIBLTE_MME_GUTI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_mobile_id_ie(&ta_update_accept->guti, &msg_ptr);
|
|
}
|
|
|
|
// TAI List
|
|
if (ta_update_accept->tai_list_present) {
|
|
*msg_ptr = LIBLTE_MME_TAI_LIST_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_tracking_area_identity_list_ie(&ta_update_accept->tai_list, &msg_ptr);
|
|
}
|
|
|
|
// EPS Bearer Context Status
|
|
if (ta_update_accept->eps_bearer_context_status_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_bearer_context_status_ie(&ta_update_accept->eps_bearer_context_status, &msg_ptr);
|
|
}
|
|
|
|
// Location Area Identification
|
|
if (ta_update_accept->lai_present) {
|
|
*msg_ptr = LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_location_area_id_ie(&ta_update_accept->lai, &msg_ptr);
|
|
}
|
|
|
|
// MS Identity
|
|
if (ta_update_accept->ms_id_present) {
|
|
*msg_ptr = LIBLTE_MME_MS_IDENTITY_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_mobile_id_ie(&ta_update_accept->ms_id, &msg_ptr);
|
|
}
|
|
|
|
// EMM Cause
|
|
if (ta_update_accept->emm_cause_present) {
|
|
*msg_ptr = LIBLTE_MME_EMM_CAUSE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_emm_cause_ie(ta_update_accept->emm_cause, &msg_ptr);
|
|
}
|
|
|
|
// T3402 Value
|
|
if (ta_update_accept->t3402_present) {
|
|
*msg_ptr = LIBLTE_MME_T3402_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3402, &msg_ptr);
|
|
}
|
|
|
|
// T3423 Value
|
|
if (ta_update_accept->t3423_present) {
|
|
*msg_ptr = LIBLTE_MME_T3423_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_ie(&ta_update_accept->t3423, &msg_ptr);
|
|
}
|
|
|
|
// Equivalent PLMNs
|
|
if (ta_update_accept->equivalent_plmns_present) {
|
|
*msg_ptr = LIBLTE_MME_EQUIVALENT_PLMNS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_plmn_list_ie(&ta_update_accept->equivalent_plmns, &msg_ptr);
|
|
}
|
|
|
|
// Emergency Number List
|
|
if (ta_update_accept->emerg_num_list_present) {
|
|
*msg_ptr = LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_emergency_number_list_ie(&ta_update_accept->emerg_num_list, &msg_ptr);
|
|
}
|
|
|
|
// EPS Network Feature Support
|
|
if (ta_update_accept->eps_network_feature_support_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_network_feature_support_ie(&ta_update_accept->eps_network_feature_support, &msg_ptr);
|
|
}
|
|
|
|
// Additional Update Result
|
|
if (ta_update_accept->additional_update_result_present) {
|
|
*msg_ptr = LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4;
|
|
liblte_mme_pack_additional_update_result_ie(ta_update_accept->additional_update_result, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// T3412 Extended Value
|
|
if (ta_update_accept->t3412_ext_present) {
|
|
*msg_ptr = LIBLTE_MME_T3412_EXTENDED_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_3_ie(&ta_update_accept->t3412_ext, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_tracking_area_update_accept_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_TRACKING_AREA_UPDATE_ACCEPT_MSG_STRUCT* ta_update_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ta_update_accept != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EPS Update Result & Spare Half Octet
|
|
liblte_mme_unpack_eps_update_result_ie(&msg_ptr, 0, &ta_update_accept->eps_update_result);
|
|
msg_ptr++;
|
|
|
|
// T3412 Value
|
|
if (LIBLTE_MME_T3412_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3412);
|
|
ta_update_accept->t3412_present = true;
|
|
} else {
|
|
ta_update_accept->t3412_present = false;
|
|
}
|
|
|
|
// GUTI
|
|
if (LIBLTE_MME_GUTI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_mobile_id_ie(&msg_ptr, &ta_update_accept->guti);
|
|
ta_update_accept->guti_present = true;
|
|
} else {
|
|
ta_update_accept->guti_present = false;
|
|
}
|
|
|
|
// TAI List
|
|
if (LIBLTE_MME_TAI_LIST_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_tracking_area_identity_list_ie(&msg_ptr, &ta_update_accept->tai_list);
|
|
ta_update_accept->tai_list_present = true;
|
|
} else {
|
|
ta_update_accept->tai_list_present = false;
|
|
}
|
|
|
|
// EPS Bearer Context Status
|
|
if (LIBLTE_MME_EPS_BEARER_CONTEXT_STATUS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_bearer_context_status_ie(&msg_ptr, &ta_update_accept->eps_bearer_context_status);
|
|
ta_update_accept->eps_bearer_context_status_present = true;
|
|
} else {
|
|
ta_update_accept->eps_bearer_context_status_present = false;
|
|
}
|
|
|
|
// Location Area Identification
|
|
if (LIBLTE_MME_LOCATION_AREA_IDENTIFICATION_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_location_area_id_ie(&msg_ptr, &ta_update_accept->lai);
|
|
ta_update_accept->lai_present = true;
|
|
} else {
|
|
ta_update_accept->lai_present = false;
|
|
}
|
|
|
|
// MS Identity
|
|
if (LIBLTE_MME_MS_IDENTITY_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_mobile_id_ie(&msg_ptr, &ta_update_accept->ms_id);
|
|
ta_update_accept->ms_id_present = true;
|
|
} else {
|
|
ta_update_accept->ms_id_present = false;
|
|
}
|
|
|
|
// EMM Cause
|
|
if (LIBLTE_MME_EMM_CAUSE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &ta_update_accept->emm_cause);
|
|
ta_update_accept->emm_cause_present = true;
|
|
} else {
|
|
ta_update_accept->emm_cause_present = false;
|
|
}
|
|
|
|
// T3402 Value
|
|
if (LIBLTE_MME_T3402_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3402);
|
|
ta_update_accept->t3402_present = true;
|
|
} else {
|
|
ta_update_accept->t3402_present = false;
|
|
}
|
|
|
|
// T3423 Value
|
|
if (LIBLTE_MME_T3423_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_ie(&msg_ptr, &ta_update_accept->t3423);
|
|
ta_update_accept->t3423_present = true;
|
|
} else {
|
|
ta_update_accept->t3423_present = false;
|
|
}
|
|
|
|
// Equivalent PLMNs
|
|
if (LIBLTE_MME_EQUIVALENT_PLMNS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_plmn_list_ie(&msg_ptr, &ta_update_accept->equivalent_plmns);
|
|
ta_update_accept->equivalent_plmns_present = true;
|
|
} else {
|
|
ta_update_accept->equivalent_plmns_present = false;
|
|
}
|
|
|
|
// Emergency Number List
|
|
if (LIBLTE_MME_EMERGENCY_NUMBER_LIST_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_emergency_number_list_ie(&msg_ptr, &ta_update_accept->emerg_num_list);
|
|
ta_update_accept->emerg_num_list_present = true;
|
|
} else {
|
|
ta_update_accept->emerg_num_list_present = false;
|
|
}
|
|
|
|
// EPS Network Feature Support
|
|
if (LIBLTE_MME_EPS_NETWORK_FEATURE_SUPPORT_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_network_feature_support_ie(&msg_ptr, &ta_update_accept->eps_network_feature_support);
|
|
ta_update_accept->eps_network_feature_support_present = true;
|
|
} else {
|
|
ta_update_accept->eps_network_feature_support_present = false;
|
|
}
|
|
|
|
// Additional Update Result
|
|
if ((LIBLTE_MME_ADDITIONAL_UPDATE_RESULT_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_additional_update_result_ie(&msg_ptr, 0, &ta_update_accept->additional_update_result);
|
|
msg_ptr++;
|
|
ta_update_accept->additional_update_result_present = true;
|
|
} else {
|
|
ta_update_accept->additional_update_result_present = false;
|
|
}
|
|
|
|
// T3412 Extended Value
|
|
if (LIBLTE_MME_T3412_EXTENDED_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &ta_update_accept->t3412_ext);
|
|
ta_update_accept->t3412_ext_present = true;
|
|
} else {
|
|
ta_update_accept->t3412_ext_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Tracking Area Update Complete
|
|
|
|
Description: Sent by the UE to the network in response to a
|
|
tracking area update accept message if a GUTI has
|
|
been changed or a new TMSI has been assigned.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.27
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_tracking_area_update_complete_msg(
|
|
LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT* ta_update_complete,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ta_update_complete != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_tracking_area_update_complete_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_TRACKING_AREA_UPDATE_COMPLETE_MSG_STRUCT* ta_update_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ta_update_complete != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Tracking Area Update Reject
|
|
|
|
Description: Sent by the network to the UE in order to reject the
|
|
tracking area updating procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.28
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_tracking_area_update_reject_msg(LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT* ta_update_rej,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ta_update_rej != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REJECT;
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_pack_emm_cause_ie(ta_update_rej->emm_cause, &msg_ptr);
|
|
|
|
// T3446 Value
|
|
if (ta_update_rej->t3446_present) {
|
|
*msg_ptr = LIBLTE_MME_T3446_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_2_ie(ta_update_rej->t3446, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_tracking_area_update_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_TRACKING_AREA_UPDATE_REJECT_MSG_STRUCT* ta_update_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ta_update_rej != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EMM Cause
|
|
liblte_mme_unpack_emm_cause_ie(&msg_ptr, &ta_update_rej->emm_cause);
|
|
|
|
// T3446 Value
|
|
if (LIBLTE_MME_T3446_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_2_ie(&msg_ptr, &ta_update_rej->t3446);
|
|
ta_update_rej->t3446_present = true;
|
|
} else {
|
|
ta_update_rej->t3446_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Tracking Area Update Request
|
|
|
|
Description: Sent by the UE to the network to initiate a tracking
|
|
area updating procedure.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.29
|
|
*********************************************************************/
|
|
// TODO
|
|
|
|
/*********************************************************************
|
|
Message Name: Uplink NAS Transport
|
|
|
|
Description: Sent by the UE to the network in order to carry an
|
|
SMS message in encapsulated format.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.30
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_nas_transport_msg(LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT* ul_nas_transport,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ul_nas_transport != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_UPLINK_NAS_TRANSPORT;
|
|
msg_ptr++;
|
|
|
|
// NAS Message Container
|
|
liblte_mme_pack_nas_message_container_ie(&ul_nas_transport->nas_msg, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_uplink_nas_transport_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_UPLINK_NAS_TRANSPORT_MSG_STRUCT* ul_nas_transport)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ul_nas_transport != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// NAS Message Container
|
|
liblte_mme_unpack_nas_message_container_ie(&msg_ptr, &ul_nas_transport->nas_msg);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Downlink Generic NAS Transport
|
|
|
|
Description: Sent by the network to the UE in order to carry an
|
|
application message in encapsulated format.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.31
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_downlink_generic_nas_transport_msg(
|
|
LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT* dl_generic_nas_transport,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (dl_generic_nas_transport != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DOWNLINK_GENERIC_NAS_TRANSPORT;
|
|
msg_ptr++;
|
|
|
|
// Generic Message Container Type
|
|
liblte_mme_pack_generic_message_container_type_ie(dl_generic_nas_transport->generic_msg_cont_type, &msg_ptr);
|
|
|
|
// Generic Message Container
|
|
liblte_mme_pack_generic_message_container_ie(&dl_generic_nas_transport->generic_msg_cont, &msg_ptr);
|
|
|
|
// Additional Information
|
|
liblte_mme_pack_additional_information_ie(&dl_generic_nas_transport->add_info, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_downlink_generic_nas_transport_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DOWNLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT* dl_generic_nas_transport)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && dl_generic_nas_transport != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Generic Message Container Type
|
|
liblte_mme_unpack_generic_message_container_type_ie(&msg_ptr, &dl_generic_nas_transport->generic_msg_cont_type);
|
|
|
|
// Generic Message Container
|
|
liblte_mme_unpack_generic_message_container_ie(&msg_ptr, &dl_generic_nas_transport->generic_msg_cont);
|
|
|
|
// Additional Information
|
|
liblte_mme_unpack_additional_information_ie(&msg_ptr, &dl_generic_nas_transport->add_info);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Uplink Generic NAS Transport
|
|
|
|
Description: Sent by the UE to the network in order to carry an
|
|
application protocol message in encapsulated format.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.2.32
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_uplink_generic_nas_transport_msg(
|
|
LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT* ul_generic_nas_transport,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (ul_generic_nas_transport != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_UPLINK_GENERIC_NAS_TRANSPORT;
|
|
msg_ptr++;
|
|
|
|
// Generic Message Container Type
|
|
liblte_mme_pack_generic_message_container_type_ie(ul_generic_nas_transport->generic_msg_cont_type, &msg_ptr);
|
|
|
|
// Generic Message Container
|
|
liblte_mme_pack_generic_message_container_ie(&ul_generic_nas_transport->generic_msg_cont, &msg_ptr);
|
|
|
|
// Additional Information
|
|
liblte_mme_pack_additional_information_ie(&ul_generic_nas_transport->add_info, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_uplink_generic_nas_transport_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_UPLINK_GENERIC_NAS_TRANSPORT_MSG_STRUCT* ul_generic_nas_transport)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && ul_generic_nas_transport != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 7;
|
|
}
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Generic Message Container Type
|
|
liblte_mme_unpack_generic_message_container_type_ie(&msg_ptr, &ul_generic_nas_transport->generic_msg_cont_type);
|
|
|
|
// Generic Message Container
|
|
liblte_mme_unpack_generic_message_container_ie(&msg_ptr, &ul_generic_nas_transport->generic_msg_cont);
|
|
|
|
// Additional Information
|
|
liblte_mme_unpack_additional_information_ie(&msg_ptr, &ul_generic_nas_transport->add_info);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Dedicated EPS Bearer Context Accept
|
|
|
|
Description: Sent by the UE to the network to acknowledge
|
|
activation of a dedicated EPS bearer context
|
|
associated with the same PDN address(es) and APN as
|
|
an already active EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_accept_msg(
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* act_ded_eps_bearer_context_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_ded_eps_bearer_context_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_ded_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_ded_eps_bearer_context_accept->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_accept_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* act_ded_eps_bearer_context_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_ded_eps_bearer_context_accept != NULL) {
|
|
// EPS Bearer ID
|
|
act_ded_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_ded_eps_bearer_context_accept->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_accept->protocol_cnfg_opts);
|
|
act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_accept->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Dedicated EPS Bearer Context Reject
|
|
|
|
Description: Sent by the UE to the network to reject activation
|
|
of a dedicated EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_reject_msg(
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* act_ded_eps_bearer_context_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_ded_eps_bearer_context_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_ded_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_ded_eps_bearer_context_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(act_ded_eps_bearer_context_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_reject_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* act_ded_eps_bearer_context_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_ded_eps_bearer_context_rej != NULL) {
|
|
// EPS Bearer ID
|
|
act_ded_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_ded_eps_bearer_context_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_ded_eps_bearer_context_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_rej->protocol_cnfg_opts);
|
|
act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Dedicated EPS Bearer Context Request
|
|
|
|
Description: Sent by the network to the UE to request activation
|
|
of a dedicated EPS bearer context associated with
|
|
the same PDN address(es) and APN as an already
|
|
active default EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_dedicated_eps_bearer_context_request_msg(
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* act_ded_eps_bearer_context_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_ded_eps_bearer_context_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_ded_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_ded_eps_bearer_context_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Linked EPS Bearer Identity & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_linked_eps_bearer_identity_ie(act_ded_eps_bearer_context_req->linked_eps_bearer_id, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// EPS QoS
|
|
liblte_mme_pack_eps_quality_of_service_ie(&act_ded_eps_bearer_context_req->eps_qos, &msg_ptr);
|
|
|
|
// TFT
|
|
liblte_mme_pack_traffic_flow_template_ie(&act_ded_eps_bearer_context_req->tft, &msg_ptr);
|
|
|
|
// Transaction Identifier
|
|
if (act_ded_eps_bearer_context_req->transaction_id_present) {
|
|
*msg_ptr = LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_transaction_identifier_ie(&act_ded_eps_bearer_context_req->transaction_id, &msg_ptr);
|
|
}
|
|
|
|
// Negotiated QoS
|
|
if (act_ded_eps_bearer_context_req->negotiated_qos_present) {
|
|
*msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_quality_of_service_ie(&act_ded_eps_bearer_context_req->negotiated_qos, &msg_ptr);
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (act_ded_eps_bearer_context_req->llc_sapi_present) {
|
|
*msg_ptr = LIBLTE_MME_LLC_SAPI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_llc_service_access_point_identifier_ie(act_ded_eps_bearer_context_req->llc_sapi, &msg_ptr);
|
|
}
|
|
|
|
// Radio Priority
|
|
if (act_ded_eps_bearer_context_req->radio_prio_present) {
|
|
*msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4;
|
|
liblte_mme_pack_radio_priority_ie(act_ded_eps_bearer_context_req->radio_prio, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (act_ded_eps_bearer_context_req->packet_flow_id_present) {
|
|
*msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_packet_flow_identifier_ie(act_ded_eps_bearer_context_req->packet_flow_id, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (act_ded_eps_bearer_context_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_ded_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_dedicated_eps_bearer_context_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* act_ded_eps_bearer_context_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_ded_eps_bearer_context_req != NULL) {
|
|
// Security Header Type
|
|
uint8_t sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 6;
|
|
}
|
|
|
|
// EPS Bearer ID
|
|
act_ded_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_ded_eps_bearer_context_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Linked Bearer Identity & Spare Half Octet
|
|
liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &act_ded_eps_bearer_context_req->linked_eps_bearer_id);
|
|
msg_ptr++;
|
|
|
|
// EPS QoS
|
|
liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &act_ded_eps_bearer_context_req->eps_qos);
|
|
|
|
// TFT
|
|
liblte_mme_unpack_traffic_flow_template_ie(&msg_ptr, &act_ded_eps_bearer_context_req->tft);
|
|
|
|
// Transaction Identifier
|
|
if (LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_transaction_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->transaction_id);
|
|
act_ded_eps_bearer_context_req->transaction_id_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->transaction_id_present = false;
|
|
}
|
|
|
|
// Negotiated QoS
|
|
if (LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &act_ded_eps_bearer_context_req->negotiated_qos);
|
|
act_ded_eps_bearer_context_req->negotiated_qos_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->negotiated_qos_present = false;
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->llc_sapi);
|
|
act_ded_eps_bearer_context_req->llc_sapi_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->llc_sapi_present = false;
|
|
}
|
|
|
|
// Radio Priority
|
|
if ((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &act_ded_eps_bearer_context_req->radio_prio);
|
|
msg_ptr++;
|
|
act_ded_eps_bearer_context_req->radio_prio_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->radio_prio_present = false;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &act_ded_eps_bearer_context_req->packet_flow_id);
|
|
act_ded_eps_bearer_context_req->packet_flow_id_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->packet_flow_id_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_ded_eps_bearer_context_req->protocol_cnfg_opts);
|
|
act_ded_eps_bearer_context_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_ded_eps_bearer_context_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Default EPS Bearer Context Accept
|
|
|
|
Description: Sent by the UE to the network to acknowledge
|
|
activation of a default EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_accept_msg(
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* act_def_eps_bearer_context_accept,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_def_eps_bearer_context_accept != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_def_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_def_eps_bearer_context_accept->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (act_def_eps_bearer_context_accept->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_accept_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* act_def_eps_bearer_context_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_def_eps_bearer_context_accept != NULL) {
|
|
// EPS Bearer ID
|
|
act_def_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_def_eps_bearer_context_accept->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_accept->protocol_cnfg_opts);
|
|
act_def_eps_bearer_context_accept->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_accept->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Default EPS Bearer Context Reject
|
|
|
|
Description: Sent by the UE to the network to reject activation
|
|
of a default EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_reject_msg(
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* act_def_eps_bearer_context_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_def_eps_bearer_context_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_def_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_def_eps_bearer_context_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(act_def_eps_bearer_context_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (act_def_eps_bearer_context_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_reject_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* act_def_eps_bearer_context_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_def_eps_bearer_context_rej != NULL) {
|
|
// EPS Bearer ID
|
|
act_def_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_def_eps_bearer_context_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_def_eps_bearer_context_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_rej->protocol_cnfg_opts);
|
|
act_def_eps_bearer_context_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Activate Default EPS Bearer Context Request
|
|
|
|
Description: Sent by the network to the UE to request activation
|
|
of a default EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_activate_default_eps_bearer_context_request_msg(
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* act_def_eps_bearer_context_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (act_def_eps_bearer_context_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (act_def_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = act_def_eps_bearer_context_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// EPS QoS
|
|
liblte_mme_pack_eps_quality_of_service_ie(&act_def_eps_bearer_context_req->eps_qos, &msg_ptr);
|
|
|
|
// Access Point Name
|
|
liblte_mme_pack_access_point_name_ie(&act_def_eps_bearer_context_req->apn, &msg_ptr);
|
|
|
|
// PDN Address
|
|
liblte_mme_pack_pdn_address_ie(&act_def_eps_bearer_context_req->pdn_addr, &msg_ptr);
|
|
|
|
// Transaction Identifier
|
|
if (act_def_eps_bearer_context_req->transaction_id_present) {
|
|
*msg_ptr = LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_transaction_identifier_ie(&act_def_eps_bearer_context_req->transaction_id, &msg_ptr);
|
|
}
|
|
|
|
// Negotiated QoS
|
|
if (act_def_eps_bearer_context_req->negotiated_qos_present) {
|
|
*msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_quality_of_service_ie(&act_def_eps_bearer_context_req->negotiated_qos, &msg_ptr);
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (act_def_eps_bearer_context_req->llc_sapi_present) {
|
|
*msg_ptr = LIBLTE_MME_LLC_SAPI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_llc_service_access_point_identifier_ie(act_def_eps_bearer_context_req->llc_sapi, &msg_ptr);
|
|
}
|
|
|
|
// Radio Priority
|
|
if (act_def_eps_bearer_context_req->radio_prio_present) {
|
|
*msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4;
|
|
liblte_mme_pack_radio_priority_ie(act_def_eps_bearer_context_req->radio_prio, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (act_def_eps_bearer_context_req->packet_flow_id_present) {
|
|
*msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_packet_flow_identifier_ie(act_def_eps_bearer_context_req->packet_flow_id, &msg_ptr);
|
|
}
|
|
|
|
// APN-AMBR
|
|
if (act_def_eps_bearer_context_req->apn_ambr_present) {
|
|
*msg_ptr = LIBLTE_MME_APN_AMBR_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(&act_def_eps_bearer_context_req->apn_ambr, &msg_ptr);
|
|
}
|
|
|
|
// ESM Cause
|
|
if (act_def_eps_bearer_context_req->esm_cause_present) {
|
|
*msg_ptr = LIBLTE_MME_ESM_CAUSE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_esm_cause_ie(act_def_eps_bearer_context_req->esm_cause, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (act_def_eps_bearer_context_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&act_def_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Connectivity Type
|
|
if (act_def_eps_bearer_context_req->connectivity_type_present) {
|
|
*msg_ptr = LIBLTE_MME_CONNECTIVITY_TYPE_IEI << 4;
|
|
liblte_mme_pack_connectivity_type_ie(act_def_eps_bearer_context_req->connectivity_type, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_activate_default_eps_bearer_context_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* act_def_eps_bearer_context_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && act_def_eps_bearer_context_req != NULL) {
|
|
// EPS Bearer ID
|
|
act_def_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
act_def_eps_bearer_context_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EPS QoS
|
|
liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &act_def_eps_bearer_context_req->eps_qos);
|
|
|
|
// Access Point Name
|
|
liblte_mme_unpack_access_point_name_ie(&msg_ptr, &act_def_eps_bearer_context_req->apn);
|
|
|
|
// PDN Address
|
|
liblte_mme_unpack_pdn_address_ie(&msg_ptr, &act_def_eps_bearer_context_req->pdn_addr);
|
|
|
|
// Transaction Identifier
|
|
if (LIBLTE_MME_TRANSACTION_IDENTIFIER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_transaction_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->transaction_id);
|
|
act_def_eps_bearer_context_req->transaction_id_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->transaction_id_present = false;
|
|
}
|
|
|
|
// Negotiated QoS
|
|
if (LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &act_def_eps_bearer_context_req->negotiated_qos);
|
|
act_def_eps_bearer_context_req->negotiated_qos_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->negotiated_qos_present = false;
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->llc_sapi);
|
|
act_def_eps_bearer_context_req->llc_sapi_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->llc_sapi_present = false;
|
|
}
|
|
|
|
// Radio Priority
|
|
if ((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &act_def_eps_bearer_context_req->radio_prio);
|
|
msg_ptr++;
|
|
act_def_eps_bearer_context_req->radio_prio_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->radio_prio_present = false;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &act_def_eps_bearer_context_req->packet_flow_id);
|
|
act_def_eps_bearer_context_req->packet_flow_id_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->packet_flow_id_present = false;
|
|
}
|
|
|
|
// APN-AMBR
|
|
if (LIBLTE_MME_APN_AMBR_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(&msg_ptr, &act_def_eps_bearer_context_req->apn_ambr);
|
|
act_def_eps_bearer_context_req->apn_ambr_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->apn_ambr_present = false;
|
|
}
|
|
|
|
// ESM Cause
|
|
if (LIBLTE_MME_ESM_CAUSE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &act_def_eps_bearer_context_req->esm_cause);
|
|
act_def_eps_bearer_context_req->esm_cause_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->esm_cause_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &act_def_eps_bearer_context_req->protocol_cnfg_opts);
|
|
act_def_eps_bearer_context_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// Connectivity Type
|
|
if ((LIBLTE_MME_CONNECTIVITY_TYPE_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_connectivity_type_ie(&msg_ptr, 0, &act_def_eps_bearer_context_req->connectivity_type);
|
|
msg_ptr++;
|
|
act_def_eps_bearer_context_req->connectivity_type_present = true;
|
|
} else {
|
|
act_def_eps_bearer_context_req->connectivity_type_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Bearer Resource Allocation Reject
|
|
|
|
Description: Sent by the network to the UE to reject the
|
|
allocation of a dedicated bearer resource.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_reject_msg(
|
|
LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT* bearer_res_alloc_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (bearer_res_alloc_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (bearer_res_alloc_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = bearer_res_alloc_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(bearer_res_alloc_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (bearer_res_alloc_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&bearer_res_alloc_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// T3496 Value
|
|
if (bearer_res_alloc_rej->t3496_present) {
|
|
*msg_ptr = LIBLTE_MME_T3496_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_3_ie(&bearer_res_alloc_rej->t3496, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_reject_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REJECT_MSG_STRUCT* bearer_res_alloc_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && bearer_res_alloc_rej != NULL) {
|
|
// EPS Bearer ID
|
|
bearer_res_alloc_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
bearer_res_alloc_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_alloc_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_alloc_rej->protocol_cnfg_opts);
|
|
bearer_res_alloc_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
bearer_res_alloc_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// T3496 Value
|
|
if (LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &bearer_res_alloc_rej->t3496);
|
|
bearer_res_alloc_rej->t3496_present = true;
|
|
} else {
|
|
bearer_res_alloc_rej->t3496_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Bearer Resource Allocation Request
|
|
|
|
Description: Sent by the UE to the network to request the
|
|
allocation of a dedicated bearer resource.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.8
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_allocation_request_msg(
|
|
LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT* bearer_res_alloc_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (bearer_res_alloc_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (bearer_res_alloc_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = bearer_res_alloc_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Linked EPS Bearer Identity & Spare Half Octet
|
|
liblte_mme_pack_linked_eps_bearer_identity_ie(bearer_res_alloc_req->linked_eps_bearer_id, 0, &msg_ptr);
|
|
|
|
// Traffic Flow Aggregate
|
|
liblte_mme_pack_traffic_flow_aggregate_description_ie(&bearer_res_alloc_req->tfa, &msg_ptr);
|
|
|
|
// Required Traffic Flow QoS
|
|
liblte_mme_pack_eps_quality_of_service_ie(&bearer_res_alloc_req->req_tf_qos, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (bearer_res_alloc_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&bearer_res_alloc_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Device Properties
|
|
if (bearer_res_alloc_req->device_properties_present) {
|
|
*msg_ptr = LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_IEI << 4;
|
|
liblte_mme_pack_device_properties_ie(bearer_res_alloc_req->device_properties, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_allocation_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_MSG_STRUCT* bearer_res_alloc_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && bearer_res_alloc_req != NULL) {
|
|
// EPS Bearer ID
|
|
bearer_res_alloc_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
bearer_res_alloc_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Linked EPS Bearer Identity & Spare Half Octet
|
|
liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &bearer_res_alloc_req->linked_eps_bearer_id);
|
|
|
|
// Traffic Flow Aggregate
|
|
liblte_mme_unpack_traffic_flow_aggregate_description_ie(&msg_ptr, &bearer_res_alloc_req->tfa);
|
|
|
|
// Required Traffic Flow QoS
|
|
liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &bearer_res_alloc_req->req_tf_qos);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_alloc_req->protocol_cnfg_opts);
|
|
bearer_res_alloc_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
bearer_res_alloc_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// Device Properties
|
|
if ((LIBLTE_MME_BEARER_RESOURCE_ALLOCATION_REQUEST_DEVICE_PROPERTIES_IEI << 4) == *msg_ptr) {
|
|
liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &bearer_res_alloc_req->device_properties);
|
|
msg_ptr++;
|
|
bearer_res_alloc_req->device_properties_present = true;
|
|
} else {
|
|
bearer_res_alloc_req->device_properties_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Bearer Resource Modification Reject
|
|
|
|
Description: Sent by the network to the UE to reject the
|
|
modification of a dedicated bearer resource.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.9
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_reject_msg(
|
|
LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT* bearer_res_mod_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (bearer_res_mod_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (bearer_res_mod_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = bearer_res_mod_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(bearer_res_mod_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (bearer_res_mod_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&bearer_res_mod_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// T3496 Value
|
|
if (bearer_res_mod_rej->t3496_present) {
|
|
*msg_ptr = LIBLTE_MME_T3496_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_3_ie(&bearer_res_mod_rej->t3496, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_reject_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REJECT_MSG_STRUCT* bearer_res_mod_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && bearer_res_mod_rej != NULL) {
|
|
// EPS Bearer ID
|
|
bearer_res_mod_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
bearer_res_mod_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_mod_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_mod_rej->protocol_cnfg_opts);
|
|
bearer_res_mod_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
bearer_res_mod_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// T3496 Value
|
|
if (LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &bearer_res_mod_rej->t3496);
|
|
bearer_res_mod_rej->t3496_present = true;
|
|
} else {
|
|
bearer_res_mod_rej->t3496_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Bearer Resource Modification Request
|
|
|
|
Description: Sent by the UE to the network to request the
|
|
modification of a dedicated bearer resource.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.10
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_bearer_resource_modification_request_msg(
|
|
LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT* bearer_res_mod_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (bearer_res_mod_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (bearer_res_mod_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = bearer_res_mod_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// EPS Bearer Identity For Packet Filter & Spare Half Octet
|
|
liblte_mme_pack_linked_eps_bearer_identity_ie(bearer_res_mod_req->eps_bearer_id_for_packet_filter, 0, &msg_ptr);
|
|
|
|
// Traffic Flow Aggregate
|
|
liblte_mme_pack_traffic_flow_aggregate_description_ie(&bearer_res_mod_req->tfa, &msg_ptr);
|
|
|
|
// Required Traffic Flow QoS
|
|
if (bearer_res_mod_req->req_tf_qos_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_quality_of_service_ie(&bearer_res_mod_req->req_tf_qos, &msg_ptr);
|
|
}
|
|
|
|
// ESM Cause
|
|
if (bearer_res_mod_req->esm_cause_present) {
|
|
*msg_ptr = LIBLTE_MME_ESM_CAUSE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_esm_cause_ie(bearer_res_mod_req->esm_cause, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (bearer_res_mod_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&bearer_res_mod_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Device Properties
|
|
if (bearer_res_mod_req->device_properties_present) {
|
|
*msg_ptr = LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_IEI << 4;
|
|
liblte_mme_pack_device_properties_ie(bearer_res_mod_req->device_properties, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_bearer_resource_modification_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_MSG_STRUCT* bearer_res_mod_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && bearer_res_mod_req != NULL) {
|
|
// EPS Bearer ID
|
|
bearer_res_mod_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
bearer_res_mod_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// EPS Bearer Identity For Packet Filter & Spare Half Octet
|
|
liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &bearer_res_mod_req->eps_bearer_id_for_packet_filter);
|
|
|
|
// Traffic Flow Aggregate
|
|
liblte_mme_unpack_traffic_flow_aggregate_description_ie(&msg_ptr, &bearer_res_mod_req->tfa);
|
|
|
|
// Required Traffic Flow QoS
|
|
if (LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &bearer_res_mod_req->req_tf_qos);
|
|
bearer_res_mod_req->req_tf_qos_present = true;
|
|
} else {
|
|
bearer_res_mod_req->req_tf_qos_present = false;
|
|
}
|
|
|
|
// ESM Cause
|
|
if (LIBLTE_MME_ESM_CAUSE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &bearer_res_mod_req->esm_cause);
|
|
bearer_res_mod_req->esm_cause_present = true;
|
|
} else {
|
|
bearer_res_mod_req->esm_cause_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &bearer_res_mod_req->protocol_cnfg_opts);
|
|
bearer_res_mod_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
bearer_res_mod_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// Device Properties
|
|
if ((LIBLTE_MME_BEARER_RESOURCE_MODIFICATION_REQUEST_DEVICE_PROPERTIES_IEI << 4) == *msg_ptr) {
|
|
liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &bearer_res_mod_req->device_properties);
|
|
msg_ptr++;
|
|
bearer_res_mod_req->device_properties_present = true;
|
|
} else {
|
|
bearer_res_mod_req->device_properties_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Deactivate EPS Bearer Context Accept
|
|
|
|
Description: Sent by the UE to acknowledge deactivation of the
|
|
EPS bearer context requested in the corresponding
|
|
deactivate EPS bearer context request message.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.11
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_accept_msg(
|
|
LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* deact_eps_bearer_context_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (deact_eps_bearer_context_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (deact_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = deact_eps_bearer_context_accept->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (deact_eps_bearer_context_accept->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&deact_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_accept_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* deact_eps_bearer_context_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && deact_eps_bearer_context_accept != NULL) {
|
|
// EPS Bearer ID
|
|
deact_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
deact_eps_bearer_context_accept->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &deact_eps_bearer_context_accept->protocol_cnfg_opts);
|
|
deact_eps_bearer_context_accept->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
deact_eps_bearer_context_accept->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Deactivate EPS Bearer Context Request
|
|
|
|
Description: Sent by the network to request deactivation of an
|
|
EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.12
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_deactivate_eps_bearer_context_request_msg(
|
|
LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* deact_eps_bearer_context_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (deact_eps_bearer_context_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (deact_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = deact_eps_bearer_context_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(deact_eps_bearer_context_req->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (deact_eps_bearer_context_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&deact_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_deactivate_eps_bearer_context_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* deact_eps_bearer_context_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && deact_eps_bearer_context_req != NULL) {
|
|
// Security Header Type
|
|
uint8_t sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 6;
|
|
}
|
|
|
|
// EPS Bearer ID
|
|
deact_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
deact_eps_bearer_context_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &deact_eps_bearer_context_req->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &deact_eps_bearer_context_req->protocol_cnfg_opts);
|
|
deact_eps_bearer_context_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
deact_eps_bearer_context_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: ESM Information Request
|
|
|
|
Description: Sent by the network to the UE to request the UE to
|
|
provide ESM information, i.e. protocol configuration
|
|
options or APN or both. This function is being added
|
|
to support encryption and integrety protection on
|
|
ESM information transfer.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
srsran_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT* esm_info_req,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (esm_info_req != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = esm_info_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: ESM Information Request
|
|
|
|
Description: Sent by the network to the UE to request the UE to
|
|
provide ESM information, i.e. protocol configuration
|
|
options or APN or both.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.13
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_esm_information_request_msg(LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT* esm_info_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (esm_info_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (esm_info_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = esm_info_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT* esm_info_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && esm_info_req != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 6;
|
|
}
|
|
|
|
// EPS Bearer ID
|
|
esm_info_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
esm_info_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: ESM Information Response
|
|
|
|
Description: Sent by the UE to the network in response to an ESM
|
|
INFORMATION REQUEST message and provides the
|
|
requested ESM information.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.14
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT* esm_info_resp,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (esm_info_resp != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (esm_info_resp->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = esm_info_resp->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE;
|
|
msg_ptr++;
|
|
|
|
// Access Point Name
|
|
if (esm_info_resp->apn_present) {
|
|
*msg_ptr = LIBLTE_MME_ACCESS_POINT_NAME_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_access_point_name_ie(&esm_info_resp->apn, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (esm_info_resp->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&esm_info_resp->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM
|
|
srsran_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT* esm_info_resp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
uint8 sec_hdr_type;
|
|
|
|
if (msg != NULL && esm_info_resp != NULL) {
|
|
// Security Header Type
|
|
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 6;
|
|
}
|
|
// EPS Bearer ID
|
|
esm_info_resp->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
esm_info_resp->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Access Point Name
|
|
if (LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_access_point_name_ie(&msg_ptr, &esm_info_resp->apn);
|
|
esm_info_resp->apn_present = true;
|
|
} else {
|
|
esm_info_resp->apn_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &esm_info_resp->protocol_cnfg_opts);
|
|
esm_info_resp->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
esm_info_resp->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT* esm_info_resp)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && esm_info_resp != NULL) {
|
|
// EPS Bearer ID
|
|
esm_info_resp->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
esm_info_resp->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Access Point Name
|
|
if (LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_access_point_name_ie(&msg_ptr, &esm_info_resp->apn);
|
|
esm_info_resp->apn_present = true;
|
|
} else {
|
|
esm_info_resp->apn_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &esm_info_resp->protocol_cnfg_opts);
|
|
esm_info_resp->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
esm_info_resp->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: ESM Status
|
|
|
|
Description: Sent by the network or the UE to pass information on
|
|
the status of the indicated EPS bearer context and
|
|
report certain error conditions.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.15
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_esm_status_msg(LIBLTE_MME_ESM_STATUS_MSG_STRUCT* esm_status,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (esm_status != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (esm_status->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = esm_status->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ESM_STATUS;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(esm_status->esm_cause, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_status_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_ESM_STATUS_MSG_STRUCT* esm_status)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && esm_status != NULL) {
|
|
// EPS Bearer ID
|
|
esm_status->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
esm_status->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &esm_status->esm_cause);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Modify EPS Bearer Context Accept
|
|
|
|
Description: Sent by the UE to the network to acknowledge the
|
|
modification of an active EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.16
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_accept_msg(
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* mod_eps_bearer_context_accept,
|
|
uint8 sec_hdr_type,
|
|
uint32 count,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (mod_eps_bearer_context_accept != NULL && msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (mod_eps_bearer_context_accept->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = mod_eps_bearer_context_accept->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_ACCEPT;
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (mod_eps_bearer_context_accept->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_accept->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_accept_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT* mod_eps_bearer_context_accept)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && mod_eps_bearer_context_accept != NULL) {
|
|
// EPS Bearer ID
|
|
mod_eps_bearer_context_accept->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
mod_eps_bearer_context_accept->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_accept->protocol_cnfg_opts);
|
|
mod_eps_bearer_context_accept->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_accept->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Modify EPS Bearer Context Reject
|
|
|
|
Description: Sent by the UE or the network to reject a
|
|
modification of an active EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.17
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_reject_msg(
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* mod_eps_bearer_context_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (mod_eps_bearer_context_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (mod_eps_bearer_context_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = mod_eps_bearer_context_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(mod_eps_bearer_context_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (mod_eps_bearer_context_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_reject_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REJECT_MSG_STRUCT* mod_eps_bearer_context_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && mod_eps_bearer_context_rej != NULL) {
|
|
// EPS Bearer ID
|
|
mod_eps_bearer_context_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
mod_eps_bearer_context_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &mod_eps_bearer_context_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_rej->protocol_cnfg_opts);
|
|
mod_eps_bearer_context_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Modify EPS Bearer Context Request
|
|
|
|
Description: Sent by the network to the UE to request modification
|
|
of an active EPS bearer context.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.18
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_modify_eps_bearer_context_request_msg(
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* mod_eps_bearer_context_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (mod_eps_bearer_context_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (mod_eps_bearer_context_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = mod_eps_bearer_context_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// New EPS QoS
|
|
if (mod_eps_bearer_context_req->new_eps_qos_present) {
|
|
*msg_ptr = LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_eps_quality_of_service_ie(&mod_eps_bearer_context_req->new_eps_qos, &msg_ptr);
|
|
}
|
|
|
|
// TFT
|
|
if (mod_eps_bearer_context_req->tft_present) {
|
|
*msg_ptr = LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_traffic_flow_template_ie(&mod_eps_bearer_context_req->tft, &msg_ptr);
|
|
}
|
|
|
|
// New QoS
|
|
if (mod_eps_bearer_context_req->new_qos_present) {
|
|
*msg_ptr = LIBLTE_MME_QUALITY_OF_SERVICE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_quality_of_service_ie(&mod_eps_bearer_context_req->new_qos, &msg_ptr);
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (mod_eps_bearer_context_req->negotiated_llc_sapi_present) {
|
|
*msg_ptr = LIBLTE_MME_LLC_SAPI_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_llc_service_access_point_identifier_ie(mod_eps_bearer_context_req->negotiated_llc_sapi, &msg_ptr);
|
|
}
|
|
|
|
// Radio Priority
|
|
if (mod_eps_bearer_context_req->radio_prio_present) {
|
|
*msg_ptr = LIBLTE_MME_RADIO_PRIORITY_IEI << 4;
|
|
liblte_mme_pack_radio_priority_ie(mod_eps_bearer_context_req->radio_prio, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (mod_eps_bearer_context_req->packet_flow_id_present) {
|
|
*msg_ptr = LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_packet_flow_identifier_ie(mod_eps_bearer_context_req->packet_flow_id, &msg_ptr);
|
|
}
|
|
|
|
// APN-AMBR
|
|
if (mod_eps_bearer_context_req->apn_ambr_present) {
|
|
*msg_ptr = LIBLTE_MME_APN_AMBR_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_apn_aggregate_maximum_bit_rate_ie(&mod_eps_bearer_context_req->apn_ambr, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (mod_eps_bearer_context_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&mod_eps_bearer_context_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_modify_eps_bearer_context_request_msg(
|
|
LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_MODIFY_EPS_BEARER_CONTEXT_REQUEST_MSG_STRUCT* mod_eps_bearer_context_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && mod_eps_bearer_context_req != NULL) {
|
|
// Security Header Type
|
|
uint8_t sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
|
msg_ptr++;
|
|
} else {
|
|
msg_ptr += 6;
|
|
}
|
|
|
|
// EPS Bearer ID
|
|
mod_eps_bearer_context_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
mod_eps_bearer_context_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// New EPS QoS
|
|
if (LIBLTE_MME_EPS_QUALITY_OF_SERVICE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_eps_quality_of_service_ie(&msg_ptr, &mod_eps_bearer_context_req->new_eps_qos);
|
|
mod_eps_bearer_context_req->new_eps_qos_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->new_eps_qos_present = false;
|
|
}
|
|
|
|
// TFT
|
|
if (LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_traffic_flow_template_ie(&msg_ptr, &mod_eps_bearer_context_req->tft);
|
|
mod_eps_bearer_context_req->tft_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->tft_present = false;
|
|
}
|
|
|
|
// New QoS
|
|
if (LIBLTE_MME_QUALITY_OF_SERVICE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_quality_of_service_ie(&msg_ptr, &mod_eps_bearer_context_req->new_qos);
|
|
mod_eps_bearer_context_req->new_qos_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->new_qos_present = false;
|
|
}
|
|
|
|
// Negotiated LLC SAPI
|
|
if (LIBLTE_MME_LLC_SAPI_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_llc_service_access_point_identifier_ie(&msg_ptr,
|
|
&mod_eps_bearer_context_req->negotiated_llc_sapi);
|
|
mod_eps_bearer_context_req->negotiated_llc_sapi_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->negotiated_llc_sapi_present = false;
|
|
}
|
|
|
|
// Radio Priority
|
|
if ((LIBLTE_MME_RADIO_PRIORITY_IEI << 4) == *msg_ptr) {
|
|
liblte_mme_unpack_radio_priority_ie(&msg_ptr, 0, &mod_eps_bearer_context_req->radio_prio);
|
|
msg_ptr++;
|
|
mod_eps_bearer_context_req->radio_prio_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->radio_prio_present = false;
|
|
}
|
|
|
|
// Packet Flow Identifier
|
|
if (LIBLTE_MME_PACKET_FLOW_IDENTIFIER_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_packet_flow_identifier_ie(&msg_ptr, &mod_eps_bearer_context_req->packet_flow_id);
|
|
mod_eps_bearer_context_req->packet_flow_id_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->packet_flow_id_present = false;
|
|
}
|
|
|
|
// APN-AMBR
|
|
if (LIBLTE_MME_APN_AMBR_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_apn_aggregate_maximum_bit_rate_ie(&msg_ptr, &mod_eps_bearer_context_req->apn_ambr);
|
|
mod_eps_bearer_context_req->apn_ambr_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->apn_ambr_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &mod_eps_bearer_context_req->protocol_cnfg_opts);
|
|
mod_eps_bearer_context_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
mod_eps_bearer_context_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Notification
|
|
|
|
Description: Sent by the network to inform the UE about events
|
|
which are relevant for the upper layer using an EPS
|
|
bearer context or having requested a procedure
|
|
transaction.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.18A
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_notification_msg(LIBLTE_MME_NOTIFICATION_MSG_STRUCT* notification,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (notification != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (notification->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = notification->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_NOTIFICATION;
|
|
msg_ptr++;
|
|
|
|
// Notification Indicator
|
|
liblte_mme_pack_notification_indicator_ie(notification->notification_ind, &msg_ptr);
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_mme_unpack_notification_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_NOTIFICATION_MSG_STRUCT* notification)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && notification != NULL) {
|
|
// EPS Bearer ID
|
|
notification->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
notification->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Notification Indicator
|
|
liblte_mme_unpack_notification_indicator_ie(&msg_ptr, ¬ification->notification_ind);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: PDN Connectivity Reject
|
|
|
|
Description: Sent by the network to the UE to reject establishment
|
|
of a PDN connection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.19
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_pdn_connectivity_reject_msg(LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT* pdn_con_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (pdn_con_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (pdn_con_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = pdn_con_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(pdn_con_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (pdn_con_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&pdn_con_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// T3496 Value
|
|
if (pdn_con_rej->t3496_present) {
|
|
*msg_ptr = LIBLTE_MME_T3496_VALUE_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_gprs_timer_3_ie(&pdn_con_rej->t3496, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_pdn_connectivity_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_PDN_CONNECTIVITY_REJECT_MSG_STRUCT* pdn_con_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && pdn_con_rej != NULL) {
|
|
// EPS Bearer ID
|
|
pdn_con_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
pdn_con_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &pdn_con_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_con_rej->protocol_cnfg_opts);
|
|
pdn_con_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
pdn_con_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// T3496 Value
|
|
if (LIBLTE_MME_T3496_VALUE_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_gprs_timer_3_ie(&msg_ptr, &pdn_con_rej->t3496);
|
|
pdn_con_rej->t3496_present = true;
|
|
} else {
|
|
pdn_con_rej->t3496_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: PDN Connectivity Request
|
|
|
|
Description: Sent by the UE to the network to initiate
|
|
establishment of a PDN connection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.20
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_pdn_connectivity_request_msg(LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT* pdn_con_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (pdn_con_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (pdn_con_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = pdn_con_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Request Type & PDN Type
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_request_type_ie(pdn_con_req->request_type, 0, &msg_ptr);
|
|
liblte_mme_pack_pdn_type_ie(pdn_con_req->pdn_type, 4, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// ESM Information Transfer Flag
|
|
if (pdn_con_req->esm_info_transfer_flag_present) {
|
|
*msg_ptr = LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_IEI << 4;
|
|
liblte_mme_pack_esm_info_transfer_flag_ie(pdn_con_req->esm_info_transfer_flag, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Access Point Name
|
|
if (pdn_con_req->apn_present) {
|
|
*msg_ptr = LIBLTE_MME_ACCESS_POINT_NAME_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_access_point_name_ie(&pdn_con_req->apn, &msg_ptr);
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (pdn_con_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&pdn_con_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Device Properties
|
|
if (pdn_con_req->device_properties_present) {
|
|
*msg_ptr = LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_IEI << 4;
|
|
liblte_mme_pack_device_properties_ie(pdn_con_req->device_properties, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_pdn_connectivity_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT* pdn_con_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && pdn_con_req != NULL) {
|
|
// EPS Bearer ID
|
|
pdn_con_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
pdn_con_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Request Type & PDN Type
|
|
liblte_mme_unpack_request_type_ie(&msg_ptr, 0, &pdn_con_req->request_type);
|
|
liblte_mme_unpack_pdn_type_ie(&msg_ptr, 4, &pdn_con_req->pdn_type);
|
|
msg_ptr++;
|
|
|
|
// ESM Information Transfer Flag
|
|
if ((LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_esm_info_transfer_flag_ie(&msg_ptr, 0, &pdn_con_req->esm_info_transfer_flag);
|
|
msg_ptr++;
|
|
pdn_con_req->esm_info_transfer_flag_present = true;
|
|
} else {
|
|
pdn_con_req->esm_info_transfer_flag_present = false;
|
|
}
|
|
|
|
// Access Point Name
|
|
if (LIBLTE_MME_ACCESS_POINT_NAME_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_access_point_name_ie(&msg_ptr, &pdn_con_req->apn);
|
|
pdn_con_req->apn_present = true;
|
|
} else {
|
|
pdn_con_req->apn_present = false;
|
|
}
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_con_req->protocol_cnfg_opts);
|
|
pdn_con_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
pdn_con_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
// Device Properties
|
|
if ((LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_DEVICE_PROPERTIES_IEI << 4) == (*msg_ptr & 0xF0)) {
|
|
liblte_mme_unpack_device_properties_ie(&msg_ptr, 0, &pdn_con_req->device_properties);
|
|
msg_ptr++;
|
|
pdn_con_req->device_properties_present = true;
|
|
} else {
|
|
pdn_con_req->device_properties_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: PDN Disconnect Reject
|
|
|
|
Description: Sent by the network to the UE to reject release of a
|
|
PDN connection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.21
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_mme_pack_pdn_disconnect_reject_msg(LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT* pdn_discon_rej,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (pdn_discon_rej != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (pdn_discon_rej->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = pdn_discon_rej->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REJECT;
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_pack_esm_cause_ie(pdn_discon_rej->esm_cause, &msg_ptr);
|
|
|
|
// Protocol Configuration Options
|
|
if (pdn_discon_rej->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&pdn_discon_rej->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_pdn_disconnect_reject_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_PDN_DISCONNECT_REJECT_MSG_STRUCT* pdn_discon_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && pdn_discon_rej != NULL) {
|
|
// EPS Bearer ID
|
|
pdn_discon_rej->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
pdn_discon_rej->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// ESM Cause
|
|
liblte_mme_unpack_esm_cause_ie(&msg_ptr, &pdn_discon_rej->esm_cause);
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_discon_rej->protocol_cnfg_opts);
|
|
pdn_discon_rej->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
pdn_discon_rej->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: PDN Disconnect Request
|
|
|
|
Description: Sent by the UE to the network to initiate release of
|
|
a PDN connection.
|
|
|
|
Document Reference: 24.301 v10.2.0 Section 8.3.22
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_pdn_disconnect_request_msg(LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT* pdn_discon_req,
|
|
LIBLTE_BYTE_MSG_STRUCT* msg)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (pdn_discon_req != NULL && msg != NULL) {
|
|
// Protocol Discriminator and EPS Bearer ID
|
|
*msg_ptr = (pdn_discon_req->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
*msg_ptr = pdn_discon_req->proc_transaction_id;
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REQUEST;
|
|
msg_ptr++;
|
|
|
|
// Linked EPS Bearer Identity & Spare Half Octet
|
|
*msg_ptr = 0;
|
|
liblte_mme_pack_linked_eps_bearer_identity_ie(pdn_discon_req->linked_eps_bearer_id, 0, &msg_ptr);
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (pdn_discon_req->protocol_cnfg_opts_present) {
|
|
*msg_ptr = LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI;
|
|
msg_ptr++;
|
|
liblte_mme_pack_protocol_config_options_ie(&pdn_discon_req->protocol_cnfg_opts, &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_unpack_pdn_disconnect_request_msg(LIBLTE_BYTE_MSG_STRUCT* msg,
|
|
LIBLTE_MME_PDN_DISCONNECT_REQUEST_MSG_STRUCT* pdn_discon_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL && pdn_discon_req != NULL) {
|
|
// EPS Bearer ID
|
|
pdn_discon_req->eps_bearer_id = (*msg_ptr >> 4);
|
|
msg_ptr++;
|
|
|
|
// Procedure Transaction ID
|
|
pdn_discon_req->proc_transaction_id = *msg_ptr;
|
|
msg_ptr++;
|
|
|
|
// Skip Message Type
|
|
msg_ptr++;
|
|
|
|
// Linked EPS Bearer Identity & Spare Half Octet
|
|
liblte_mme_unpack_linked_eps_bearer_identity_ie(&msg_ptr, 0, &pdn_discon_req->linked_eps_bearer_id);
|
|
msg_ptr++;
|
|
|
|
// Protocol Configuration Options
|
|
if (LIBLTE_MME_PROTOCOL_CONFIGURATION_OPTIONS_IEI == *msg_ptr) {
|
|
msg_ptr++;
|
|
liblte_mme_unpack_protocol_config_options_ie(&msg_ptr, &pdn_discon_req->protocol_cnfg_opts);
|
|
pdn_discon_req->protocol_cnfg_opts_present = true;
|
|
} else {
|
|
pdn_discon_req->protocol_cnfg_opts_present = false;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_activate_test_mode_complete_msg(LIBLTE_BYTE_MSG_STRUCT* msg, uint8 sec_hdr_type, uint32 count)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and skip indicator (always 0x0F)
|
|
*msg_ptr =
|
|
(LIBLTE_MME_MSG_TYPE_TEST_MODE_SKIP_INDICATOR << 4) | (LIBLTE_MME_MSG_TYPE_TEST_MODE_PROTOCOL_DISCRIMINATOR);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_ACTIVATE_TEST_MODE_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM
|
|
liblte_mme_pack_close_ue_test_loop_complete_msg(LIBLTE_BYTE_MSG_STRUCT* msg, uint8 sec_hdr_type, uint32 count)
|
|
{
|
|
bzero(msg, sizeof(LIBLTE_BYTE_MSG_STRUCT));
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8* msg_ptr = msg->msg;
|
|
|
|
if (msg != NULL) {
|
|
if (LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type) {
|
|
// Protocol Discriminator and Security Header Type
|
|
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
|
msg_ptr++;
|
|
|
|
// MAC will be filled in later
|
|
msg_ptr += 4;
|
|
|
|
// Sequence Number
|
|
*msg_ptr = count & 0xFF;
|
|
msg_ptr++;
|
|
}
|
|
|
|
// Protocol Discriminator and skip indicator (always 0x0F)
|
|
*msg_ptr =
|
|
(LIBLTE_MME_MSG_TYPE_TEST_MODE_SKIP_INDICATOR << 4) | (LIBLTE_MME_MSG_TYPE_TEST_MODE_PROTOCOL_DISCRIMINATOR);
|
|
msg_ptr++;
|
|
|
|
// Message Type
|
|
*msg_ptr = LIBLTE_MME_MSG_TYPE_CLOSE_UE_TEST_LOOP_COMPLETE;
|
|
msg_ptr++;
|
|
|
|
// Fill in the number of bytes used
|
|
msg->N_bytes = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
HELPER FUNCTIONS
|
|
*******************************************************************************/
|
|
const char* liblte_nas_sec_hdr_type_to_string(int code)
|
|
{
|
|
switch (code) {
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST);
|
|
default:
|
|
return "NAS Message Type Unknown";
|
|
}
|
|
}
|
|
|
|
const char* liblte_nas_msg_type_to_string(int code)
|
|
{
|
|
switch (code) {
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ATTACH_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ATTACH_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ATTACH_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DETACH_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DETACH_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_COMPLETE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_EXTENDED_SERVICE_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_SERVICE_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMMAND);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_GUTI_REALLOCATION_COMPLETE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_AUTHENTICATION_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_IDENTITY_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMMAND);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_SECURITY_MODE_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_EMM_STATUS);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_EMM_INFORMATION);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DOWNLINK_NAS_TRANSPORT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_UPLINK_NAS_TRANSPORT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_CS_SERVICE_NOTIFICATION);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DOWNLINK_GENERIC_NAS_TRANSPORT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_UPLINK_GENERIC_NAS_TRANSPORT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_MODIFY_EPS_BEARER_CONTEXT_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_PDN_CONNECTIVITY_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_PDN_DISCONNECT_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_ALLOCATION_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_BEARER_RESOURCE_MODIFICATION_REJECT);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_REQUEST);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_NOTIFICATION);
|
|
LIBLTE_CASE_STR(LIBLTE_MME_MSG_TYPE_ESM_STATUS);
|
|
default:
|
|
return "NAS Message Type Unknown";
|
|
}
|
|
}
|