Commit f355cc61 authored by Cedric Roux's avatar Cedric Roux

- Formatted some NAS files

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4553 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 0fdd3f09
......@@ -200,6 +200,7 @@ static void* _nas_user_mngr(void* args)
int exit_loop = FALSE;
int nb_command;
int bytes;
int i;
int *fd = (int*) args;
......@@ -227,7 +228,7 @@ static void* _nas_user_mngr(void* args)
/* Decode the user data message */
nb_command = user_api_decode_data (bytes);
for (int i = 0; i < nb_command; i++)
for (i = 0; i < nb_command; i++)
{
/* Get the user data to be processed */
const void* data = user_api_get_data (i);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source Authentication.c
Source Authentication.c
Version 0.1
Version 0.1
Date 2013/03/04
Date 2013/03/04
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the authentication EMM procedure executed by the
Non-Access Stratum.
Description Defines the authentication EMM procedure executed by the
Non-Access Stratum.
The purpose of the EPS authentication and key agreement (AKA)
procedure is to provide mutual authentication between the user
and the network and to agree on a key KASME. The procedure is
always initiated and controlled by the network. However, the
UE can reject the EPS authentication challenge sent by the
network.
The purpose of the EPS authentication and key agreement (AKA)
procedure is to provide mutual authentication between the user
and the network and to agree on a key KASME. The procedure is
always initiated and controlled by the network. However, the
UE can reject the EPS authentication challenge sent by the
network.
A partial native EPS security context is established in the
UE and the network when an EPS authentication is successfully
performed. The computed key material KASME is used as the
root for the EPS integrity protection and ciphering key
hierarchy.
A partial native EPS security context is established in the
UE and the network when an EPS authentication is successfully
performed. The computed key material KASME is used as the
root for the EPS integrity protection and ciphering key
hierarchy.
*****************************************************************************/
......@@ -45,8 +45,8 @@ Description Defines the authentication EMM procedure executed by the
#include "usim_api.h"
#endif
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy, memcmp, memset
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy, memcmp, memset
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
......@@ -56,10 +56,10 @@ Description Defines the authentication EMM procedure executed by the
/*
* Retransmission timer handlers
*/
extern void* _emm_attach_t3410_handler(void*);
extern void* _emm_service_t3417_handler(void*);
extern void* _emm_detach_t3421_handler(void*);
extern void* _emm_tau_t3430_handler(void*);
extern void *_emm_attach_t3410_handler(void *);
extern void *_emm_service_t3417_handler(void *);
extern void *_emm_detach_t3421_handler(void *);
extern void *_emm_tau_t3430_handler(void *);
#endif // NAS_UE
/****************************************************************************/
......@@ -68,81 +68,84 @@ extern void* _emm_tau_t3430_handler(void*);
/*
* --------------------------------------------------------------------------
* Internal data handled by the authentication procedure in the UE
* Internal data handled by the authentication procedure in the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/*
* Timer handlers
*/
static void* _authentication_t3416_handler(void*);
static void* _authentication_t3418_handler(void*);
static void* _authentication_t3420_handler(void*);
static void *_authentication_t3416_handler(void *);
static void *_authentication_t3418_handler(void *);
static void *_authentication_t3420_handler(void *);
/*
* Internal data used for authentication procedure
*/
static struct {
uint8_t rand[AUTH_RAND_SIZE]; /* Random challenge number */
uint8_t res[AUTH_RES_SIZE]; /* Authentication response */
uint8_t ck[AUTH_CK_SIZE]; /* Ciphering key */
uint8_t ik[AUTH_IK_SIZE]; /* Integrity key */
#define AUTHENTICATION_T3410 0x01
#define AUTHENTICATION_T3417 0x02
#define AUTHENTICATION_T3421 0x04
#define AUTHENTICATION_T3430 0x08
unsigned char timers; /* Timer restart bitmap */
uint8_t rand[AUTH_RAND_SIZE]; /* Random challenge number */
uint8_t res[AUTH_RES_SIZE]; /* Authentication response */
uint8_t ck[AUTH_CK_SIZE]; /* Ciphering key */
uint8_t ik[AUTH_IK_SIZE]; /* Integrity key */
#define AUTHENTICATION_T3410 0x01
#define AUTHENTICATION_T3417 0x02
#define AUTHENTICATION_T3421 0x04
#define AUTHENTICATION_T3430 0x08
unsigned char timers; /* Timer restart bitmap */
#define AUTHENTICATION_COUNTER_MAX 3
unsigned char mac_count:2; /* MAC failure counter (#20) */
unsigned char umts_count:2; /* UMTS challenge failure counter (#26) */
unsigned char sync_count:2; /* Sync failure counter (#21) */
unsigned char mac_count:2; /* MAC failure counter (#20) */
unsigned char umts_count:2; /* UMTS challenge failure counter (#26) */
unsigned char sync_count:2; /* Sync failure counter (#21) */
} _authentication_data;
/*
* Abnormal case authentication procedure
*/
static int _authentication_abnormal_cases_cde(int emm_cause, const OctetString* auts);
static int _authentication_abnormal_cases_cde(int emm_cause,
const OctetString *auts);
static int _authentication_abnormal_case_f(void);
static int _authentication_stop_timers(void);
static int _authentication_start_timers(void);
static int _authentication_kasme(const OctetString* autn, const OctetString* ck, const OctetString* ik, const plmn_t* plmn, OctetString* kasme);
static int _authentication_kasme(const OctetString *autn,
const OctetString *ck, const OctetString *ik, const plmn_t *plmn,
OctetString *kasme);
#endif // NAS_UE
/*
* --------------------------------------------------------------------------
* Internal data handled by the authentication procedure in the MME
* Internal data handled by the authentication procedure in the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/*
* Timer handlers
*/
static void* _authentication_t3460_handler(void*);
static void *_authentication_t3460_handler(void *);
/*
* Function executed whenever the ongoing EMM procedure that initiated
* the authentication procedure is aborted or the maximum value of the
* retransmission timer counter is exceed
*/
static int _authentication_abort(void*);
static int _authentication_abort(void *);
/*
* Internal data used for authentication procedure
*/
typedef struct {
unsigned int ueid; /* UE identifier */
#define AUTHENTICATION_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
int ksi; /* NAS key set identifier */
OctetString rand; /* Random challenge number */
OctetString autn; /* Authentication token */
int notify_failure; /* Indicates whether the authentication
* procedure failure shall be notified
* to the ongoing EMM procedure */
unsigned int ueid; /* UE identifier */
#define AUTHENTICATION_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
int ksi; /* NAS key set identifier */
OctetString rand; /* Random challenge number */
OctetString autn; /* Authentication token */
int notify_failure; /* Indicates whether the authentication
* procedure failure shall be notified
* to the ongoing EMM procedure */
} authentication_data_t;
static int _authentication_request(authentication_data_t* data);
static int _authentication_request(authentication_data_t *data);
static int _authentication_reject(unsigned int ueid);
#endif // NAS_MME
......@@ -152,40 +155,40 @@ static int _authentication_reject(unsigned int ueid);
/*
* --------------------------------------------------------------------------
* Authentication procedure executed by the UE
* Authentication procedure executed by the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_proc_authentication_request() **
** Name: emm_proc_authentication_request() **
** **
** Description: Performs the MME requested authentication procedure. **
** **
** 3GPP TS 24.301, section 5.4.2.3 **
** Upon receiving the AUTHENTICATION REQUEST message, the UE **
** shall store the received RAND together with the RES re- **
** turned from the USIM in the volatile memory of the ME, to **
** avoid a synchronisation failure. The UE shall process the **
** authentication challenge data and respond with an AUTHEN- **
** TICATION RESPONSE message to the network. **
** **
** Inputs: native_ksi: TRUE if the security context is of type **
** native (for KSIASME) **
** ksi: The NAS ket sey identifier **
** rand: Authentication parameter RAND **
** autn: Authentication parameter AUTN **
** Others: _emm_data, _authentication_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, _authentication_data, T3416, **
** T3418, T3420 **
** Upon receiving the AUTHENTICATION REQUEST message, the UE **
** shall store the received RAND together with the RES re- **
** turned from the USIM in the volatile memory of the ME, to **
** avoid a synchronisation failure. The UE shall process the **
** authentication challenge data and respond with an AUTHEN- **
** TICATION RESPONSE message to the network. **
** **
** Inputs: native_ksi: TRUE if the security context is of type **
** native (for KSIASME) **
** ksi: The NAS ket sey identifier **
** rand: Authentication parameter RAND **
** autn: Authentication parameter AUTN **
** Others: _emm_data, _authentication_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, _authentication_data, T3416, **
** T3418, T3420 **
** **
***************************************************************************/
int emm_proc_authentication_request(int native_ksi, int ksi,
const OctetString* rand,
const OctetString* autn)
const OctetString *rand,
const OctetString *autn)
{
LOG_FUNC_IN;
......@@ -198,19 +201,19 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
* USIM is present
*/
if (!_emm_data.usim_is_valid) {
LOG_TRACE(WARNING, "EMM-PROC - USIM is not present or not valid");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING, "EMM-PROC - USIM is not present or not valid");
LOG_FUNC_RETURN (RETURNerror);
}
/* Stop timer T3418, if running */
if (T3418.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3418 (%d)", T3418.id);
T3418.id = nas_timer_stop(T3418.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3418 (%d)", T3418.id);
T3418.id = nas_timer_stop(T3418.id);
}
/* Stop timer T3420, if running */
if (T3420.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3420 (%d)", T3420.id);
T3420.id = nas_timer_stop(T3420.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3420 (%d)", T3420.id);
T3420.id = nas_timer_stop(T3420.id);
}
/* Setup security keys */
......@@ -219,76 +222,76 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
OctetString res = {AUTH_RES_SIZE, _authentication_data.res};
if (memcmp(_authentication_data.rand, rand->value, AUTH_CK_SIZE) != 0) {
/*
* There is no valid stored RAND in the ME or the stored RAND is
* different from the new received value in the AUTHENTICATION
* REQUEST message
*/
OctetString auts;
auts.length = 0;
auts.value = (uint8_t*)malloc(AUTH_AUTS_SIZE);
if (auts.value == NULL) {
LOG_TRACE(WARNING, "EMM-PROC - Failed to allocate AUTS parameter");
LOG_FUNC_RETURN (RETURNerror);
}
/* 3GPP TS 33.401, section 6.1.1
* Get the "separation bit" of the AMF field of AUTN */
int sbit = AUTH_AMF_SEPARATION_BIT(autn->value[AUTH_AMF_INDEX]);
if (sbit != 0) {
/*
* Perform EPS authentication challenge to check the authenticity
* of the core network by means of the received AUTN parameter and
* request the USIM to compute RES, CK and IK for given RAND
*/
rc = usim_api_authenticate(rand, autn, &auts, &res, &ck, &ik);
}
if (rc != RETURNok) {
/*
* Network authentication not accepted by the UE
*/
LOG_TRACE(WARNING, "EMM-PROC - Network authentication failed (%s)",
(auts.length > 0) ? "SQN failure" :
(sbit == 0) ? "Non-EPS authentication unacceptable" :
"MAC code failure");
/* Delete any previously stored RAND and RES and stop timer T3416 */
(void) emm_proc_authentication_delete();
/* Proceed authentication abnormal cases procedure */
if (auts.length > 0) {
/* 3GPP TS 24.301, section 5.4.2.6, case e
* SQN failure */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_SYNCH_FAILURE, &auts);
} else if (sbit == 0) {
/* 3GPP TS 24.301, section 5.4.2.6, case d
* Non-EPS authentication unacceptable */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE, NULL);
} else {
/* 3GPP TS 24.301, section 5.4.2.6, case c
* MAC code failure */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_MAC_FAILURE, NULL);
}
/* Free the AUTS parameter */
free(auts.value);
LOG_FUNC_RETURN (rc);
}
/* Free the AUTS parameter */
free(auts.value);
/* Store the new RAND in the volatile memory */
if (rand->length <= AUTH_RAND_SIZE) {
memcpy(_authentication_data.rand, rand->value, rand->length);
}
/* Start, or reset and restart timer T3416 */
if (T3416.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id);
T3416.id = nas_timer_stop(T3416.id);
}
T3416.id = nas_timer_start(T3416.sec, _authentication_t3416_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3416 (%d) expires in %ld seconds",
T3416.id, T3416.sec);
/*
* There is no valid stored RAND in the ME or the stored RAND is
* different from the new received value in the AUTHENTICATION
* REQUEST message
*/
OctetString auts;
auts.length = 0;
auts.value = (uint8_t *)malloc(AUTH_AUTS_SIZE);
if (auts.value == NULL) {
LOG_TRACE(WARNING, "EMM-PROC - Failed to allocate AUTS parameter");
LOG_FUNC_RETURN (RETURNerror);
}
/* 3GPP TS 33.401, section 6.1.1
* Get the "separation bit" of the AMF field of AUTN */
int sbit = AUTH_AMF_SEPARATION_BIT(autn->value[AUTH_AMF_INDEX]);
if (sbit != 0) {
/*
* Perform EPS authentication challenge to check the authenticity
* of the core network by means of the received AUTN parameter and
* request the USIM to compute RES, CK and IK for given RAND
*/
rc = usim_api_authenticate(rand, autn, &auts, &res, &ck, &ik);
}
if (rc != RETURNok) {
/*
* Network authentication not accepted by the UE
*/
LOG_TRACE(WARNING, "EMM-PROC - Network authentication failed (%s)",
(auts.length > 0) ? "SQN failure" :
(sbit == 0) ? "Non-EPS authentication unacceptable" :
"MAC code failure");
/* Delete any previously stored RAND and RES and stop timer T3416 */
(void) emm_proc_authentication_delete();
/* Proceed authentication abnormal cases procedure */
if (auts.length > 0) {
/* 3GPP TS 24.301, section 5.4.2.6, case e
* SQN failure */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_SYNCH_FAILURE, &auts);
} else if (sbit == 0) {
/* 3GPP TS 24.301, section 5.4.2.6, case d
* Non-EPS authentication unacceptable */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE, NULL);
} else {
/* 3GPP TS 24.301, section 5.4.2.6, case c
* MAC code failure */
rc = _authentication_abnormal_cases_cde(
EMM_CAUSE_MAC_FAILURE, NULL);
}
/* Free the AUTS parameter */
free(auts.value);
LOG_FUNC_RETURN (rc);
}
/* Free the AUTS parameter */
free(auts.value);
/* Store the new RAND in the volatile memory */
if (rand->length <= AUTH_RAND_SIZE) {
memcpy(_authentication_data.rand, rand->value, rand->length);
}
/* Start, or reset and restart timer T3416 */
if (T3416.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id);
T3416.id = nas_timer_stop(T3416.id);
}
T3416.id = nas_timer_start(T3416.sec, _authentication_t3416_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3416 (%d) expires in %ld seconds",
T3416.id, T3416.sec);
}
/*
......@@ -299,17 +302,17 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
/* Start any retransmission timers */
rc = _authentication_start_timers();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - Failed to start retransmission timers");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING, "EMM-PROC - Failed to start retransmission timers");
LOG_FUNC_RETURN (RETURNerror);
}
/* Setup EMM procedure handler to be executed upon receiving
* lower layer notification */
rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL);
if (rc != RETURNok) {
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
}
/*
......@@ -325,38 +328,38 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
emm_sap.u.emm_as.u.security.res = &res;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
_emm_data.security, FALSE, TRUE);
_emm_data.security, FALSE, TRUE);
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
/* Reset the authentication failure counters */
_authentication_data.mac_count = 0;
_authentication_data.umts_count = 0;
_authentication_data.sync_count = 0;
/* Create non-current EPS security context */
if (_emm_data.non_current == NULL) {
_emm_data.non_current =
(emm_security_context_t*)malloc(sizeof(emm_security_context_t));
}
if (_emm_data.non_current) {
memset(_emm_data.non_current, 0, sizeof(emm_security_context_t));
/* Set the security context type */
if (native_ksi) {
_emm_data.non_current->type = EMM_KSI_NATIVE;
} else {
_emm_data.non_current->type = EMM_KSI_MAPPED;
}
/* Set the EPS key set identifier */
_emm_data.non_current->eksi = ksi;
/* Derive the Kasme from the authentication challenge using
* the PLMN identity of the selected PLMN */
_emm_data.non_current->kasme.length = AUTH_KASME_SIZE;
_emm_data.non_current->kasme.value =
(uint8_t*)malloc(sizeof(AUTH_KASME_SIZE));
_authentication_kasme(autn, &ck, &ik, &_emm_data.splmn,
&_emm_data.non_current->kasme);
/* NAS integrity and cyphering keys are not yet available */
}
/* Reset the authentication failure counters */
_authentication_data.mac_count = 0;
_authentication_data.umts_count = 0;
_authentication_data.sync_count = 0;
/* Create non-current EPS security context */
if (_emm_data.non_current == NULL) {
_emm_data.non_current =
(emm_security_context_t *)malloc(sizeof(emm_security_context_t));
}
if (_emm_data.non_current) {
memset(_emm_data.non_current, 0, sizeof(emm_security_context_t));
/* Set the security context type */
if (native_ksi) {
_emm_data.non_current->type = EMM_KSI_NATIVE;
} else {
_emm_data.non_current->type = EMM_KSI_MAPPED;
}
/* Set the EPS key set identifier */
_emm_data.non_current->eksi = ksi;
/* Derive the Kasme from the authentication challenge using
* the PLMN identity of the selected PLMN */
_emm_data.non_current->kasme.length = AUTH_KASME_SIZE;
_emm_data.non_current->kasme.value =
(uint8_t *)malloc(sizeof(AUTH_KASME_SIZE));
_authentication_kasme(autn, &ck, &ik, &_emm_data.splmn,
&_emm_data.non_current->kasme);
/* NAS integrity and cyphering keys are not yet available */
}
}
LOG_FUNC_RETURN (rc);
......@@ -364,24 +367,24 @@ int emm_proc_authentication_request(int native_ksi, int ksi,
/****************************************************************************
** **
** Name: emm_proc_authentication_reject() **
** Name: emm_proc_authentication_reject() **
** **
** Description: Performs the authentication procedure not accepted by the **
** network. **
** network. **
** **
** 3GPP TS 24.301, section 5.4.2.5 **
** Upon receiving an AUTHENTICATION REJECT message, the UE **
** shall abort any EMM signalling procedure, stop any of the **
** timers T3410, T3417 or T3430 (if running) and enter state **
** EMM-DEREGISTERED. **
** Upon receiving an AUTHENTICATION REJECT message, the UE **
** shall abort any EMM signalling procedure, stop any of the **
** timers T3410, T3417 or T3430 (if running) and enter state **
** EMM-DEREGISTERED. **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, _authentication_data, T3410, **
** T3417, T3430 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, _authentication_data, T3410, **
** T3417, T3430 **
** **
***************************************************************************/
int emm_proc_authentication_reject(void)
......@@ -406,25 +409,25 @@ int emm_proc_authentication_reject(void)
_emm_data.tai = NULL;
/* Delete the eKSI */
if (_emm_data.security) {
_emm_data.security->type = EMM_KSI_NOT_AVAILABLE;
_emm_data.security->type = EMM_KSI_NOT_AVAILABLE;
}
/* Consider the USIM invalid */
_emm_data.usim_is_valid = FALSE;
/* Stop timer T3410 */
if (T3410.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id);
T3410.id = nas_timer_stop(T3410.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id);
T3410.id = nas_timer_stop(T3410.id);
}
/* Stop timer T3417 */
if (T3417.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id);
T3417.id = nas_timer_stop(T3417.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id);
T3417.id = nas_timer_stop(T3417.id);
}
/* Stop timer T3430 */
if (T3430.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id);
T3430.id = nas_timer_stop(T3430.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id);
T3430.id = nas_timer_stop(T3430.id);
}
/* Abort any EMM signalling procedure (prevent the retransmission timers to
......@@ -442,24 +445,24 @@ int emm_proc_authentication_reject(void)
/****************************************************************************
** **
** Name: emm_proc_authentication_delete() **
** Name: emm_proc_authentication_delete() **
** **
** Description: Deletes the RAND and RES values stored into the volatile **
** memory of the Mobile Equipment and stop timer T3416, if **
** running, upon receipt of a SECURITY MODE COMMAND, SERVICE **
** REJECT, TRACKING AREA UPDATE REJECT, TRACKING AREA UPDATE **
** ACCEPT or AUTHENTICATION REJECT message; upon expiry of **
** timer T3416; or if the UE enters the EMM state EMM- **
** DEREGISTERED or EMM-NULL. **
** memory of the Mobile Equipment and stop timer T3416, if **
** running, upon receipt of a SECURITY MODE COMMAND, SERVICE **
** REJECT, TRACKING AREA UPDATE REJECT, TRACKING AREA UPDATE **
** ACCEPT or AUTHENTICATION REJECT message; upon expiry of **
** timer T3416; or if the UE enters the EMM state EMM- **
** DEREGISTERED or EMM-NULL. **
** **
** 3GPP TS 24.301, section 5.4.2.3 **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3416 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3416 **
** **
***************************************************************************/
int emm_proc_authentication_delete(void)
......@@ -470,8 +473,8 @@ int emm_proc_authentication_delete(void)
/* Stop timer T3416, if running */
if (T3416.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id);
T3416.id = nas_timer_stop(T3416.id);
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3416 (%d)", T3416.id);
T3416.id = nas_timer_stop(T3416.id);
}
/* Delete any previously stored RAND and RES */
memset(_authentication_data.rand, 0, AUTH_RAND_SIZE);
......@@ -483,47 +486,47 @@ int emm_proc_authentication_delete(void)
/*
* --------------------------------------------------------------------------
* Authentication procedure executed by the MME
* Authentication procedure executed by the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/****************************************************************************
** **
** Name: emm_proc_authentication() **
** Name: emm_proc_authentication() **
** **
** Description: Initiates authentication procedure to establish partial **
** native EPS security context in the UE and the MME. **
** native EPS security context in the UE and the MME. **
** **
** 3GPP TS 24.301, section 5.4.2.2 **
** The network initiates the authentication procedure by **
** sending an AUTHENTICATION REQUEST message to the UE and **
** starting the timer T3460. The AUTHENTICATION REQUEST mes- **
** sage contains the parameters necessary to calculate the **
** authentication response. **
** **
** Inputs: ueid: UE lower layer identifier **
** ksi: NAS key set identifier **
** rand: Random challenge number **
** autn: Authentication token **
** success: Callback function executed when the authen-**
** tication procedure successfully completes **
** reject: Callback function executed when the authen-**
** tication procedure fails or is rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the authenti- **
** cation procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** The network initiates the authentication procedure by **
** sending an AUTHENTICATION REQUEST message to the UE and **
** starting the timer T3460. The AUTHENTICATION REQUEST mes- **
** sage contains the parameters necessary to calculate the **
** authentication response. **
** **
** Inputs: ueid: UE lower layer identifier **
** ksi: NAS key set identifier **
** rand: Random challenge number **
** autn: Authentication token **
** success: Callback function executed when the authen-**
** tication procedure successfully completes **
** reject: Callback function executed when the authen-**
** tication procedure fails or is rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the authenti- **
** cation procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_authentication(unsigned int ueid, int ksi,
const OctetString* _rand, const OctetString* autn,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
const OctetString *_rand, const OctetString *autn,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
{
LOG_FUNC_IN;
......@@ -533,55 +536,55 @@ int emm_proc_authentication(unsigned int ueid, int ksi,
LOG_TRACE(INFO, "EMM-PROC - Initiate authentication KSI = %d", ksi);
/* Allocate parameters of the retransmission timer callback */
authentication_data_t* data =
(authentication_data_t*)malloc(sizeof(authentication_data_t));
authentication_data_t *data =
(authentication_data_t *)malloc(sizeof(authentication_data_t));
if (data != NULL) {
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_authentication_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the key set identifier */
data->ksi = ksi;
/* Set the authentication random challenge number */
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_authentication_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the key set identifier */
data->ksi = ksi;
/* Set the authentication random challenge number */
if (_rand->length > 0) {
data->rand.value = (uint8_t*)malloc(_rand->length);
data->rand.length = 0;
if (data->rand.value) {
data->rand.value = (uint8_t *)malloc(_rand->length);
data->rand.length = 0;
if (data->rand.value) {
memcpy(data->rand.value, _rand->value, _rand->length);
data->rand.length = _rand->length;
}
}
/* Set the authentication token */
if (autn->length > 0) {
data->autn.value = (uint8_t*)malloc(autn->length);
data->autn.length = 0;
if (data->autn.value) {
memcpy(data->autn.value, autn->value, autn->length);
data->autn.length = autn->length;
}
}
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send authentication request message to the UE */
rc = _authentication_request(data);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
}
}
/* Set the authentication token */
if (autn->length > 0) {
data->autn.value = (uint8_t *)malloc(autn->length);
data->autn.length = 0;
if (data->autn.value) {
memcpy(data->autn.value, autn->value, autn->length);
data->autn.length = autn->length;
}
}
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send authentication request message to the UE */
rc = _authentication_request(data);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN (rc);
......@@ -589,28 +592,28 @@ int emm_proc_authentication(unsigned int ueid, int ksi,
/****************************************************************************
** **
** Name: emm_proc_authentication_complete() **
** Name: emm_proc_authentication_complete() **
** **
** Description: Performs the authentication completion procedure executed **
** by the network. **
** by the network. **
** **
** 3GPP TS 24.301, section 5.4.2.4 **
** Upon receiving the AUTHENTICATION RESPONSE message, the **
** MME shall stop timer T3460 and check the correctness of **
** the RES parameter. **
** Upon receiving the AUTHENTICATION RESPONSE message, the **
** MME shall stop timer T3460 and check the correctness of **
** the RES parameter. **
** **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: Authentication failure EMM cause code **
** res: Authentication response parameter **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: Authentication failure EMM cause code **
** res: Authentication response parameter **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, T3460 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, T3460 **
** **
***************************************************************************/
int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
const OctetString* res)
const OctetString *res)
{
LOG_FUNC_IN;
......@@ -618,27 +621,27 @@ int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
emm_sap_t emm_sap;
LOG_TRACE(INFO, "EMM-PROC - Authentication complete (ueid=%u, cause=%d)",
ueid, emm_cause);
ueid, emm_cause);
/* Stop timer T3460 */
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3460 (%d)", T3460.id);
T3460.id = nas_timer_stop(T3460.id);
/* Release retransmission timer paramaters */
authentication_data_t* data =
(authentication_data_t*)(emm_proc_common_get_args(ueid));
authentication_data_t *data =
(authentication_data_t *)(emm_proc_common_get_args(ueid));
if (data) {
if (data->rand.length > 0) {
free(data->rand.value);
}
if (data->autn.length > 0) {
free(data->autn.value);
}
free(data);
if (data->rand.length > 0) {
free(data->rand.value);
}
if (data->autn.length > 0) {
free(data->autn.value);
}
free(data);
}
/* Get the UE context */
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
#if defined(EPC_BUILD)
if (ueid > 0) {
......@@ -646,38 +649,37 @@ int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
}
#else
if (ueid < EMM_DATA_NB_UE_MAX) {
emm_ctx = _emm_data.ctx[ueid];
emm_ctx = _emm_data.ctx[ueid];
}
#endif
if (emm_cause == EMM_CAUSE_SUCCESS) {
/* Check the received RES parameter */
if ( (emm_ctx == NULL) ||
(memcmp(res->value, &emm_ctx->vector.xres, res->length) != 0) ) {
/* RES does not match the XRES parameter */
LOG_TRACE(WARNING, "EMM-PROC - Failed to authentify the UE");
emm_cause = EMM_CAUSE_ILLEGAL_UE;
}
/* Check the received RES parameter */
if ( (emm_ctx == NULL) ||
(memcmp(res->value, &emm_ctx->vector.xres, res->length) != 0) ) {
/* RES does not match the XRES parameter */
LOG_TRACE(WARNING, "EMM-PROC - Failed to authentify the UE");
emm_cause = EMM_CAUSE_ILLEGAL_UE;
}
}
if (emm_cause != EMM_CAUSE_SUCCESS) {
/* The MME received an authentication failure message or the RES
* contained in the Authentication Response message received from
* the UE does not match the XRES parameter computed by the network */
(void) _authentication_reject(ueid);
/*
* Notify EMM that the authentication procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
}
else {
/*
* Notify EMM that the authentication procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
/* The MME received an authentication failure message or the RES
* contained in the Authentication Response message received from
* the UE does not match the XRES parameter computed by the network */
(void) _authentication_reject(ueid);
/*
* Notify EMM that the authentication procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
} else {
/*
* Notify EMM that the authentication procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
}
rc = emm_sap_send(&emm_sap);
......@@ -693,29 +695,29 @@ int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
#ifdef NAS_UE
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _authentication_t3416_handler() **
** Name: _authentication_t3416_handler() **
** **
** Description: T3416 timeout handler **
** Upon T3416 timer expiration, the RAND and RES values sto- **
** red in the ME shall be deleted. **
** Upon T3416 timer expiration, the RAND and RES values sto- **
** red in the ME shall be deleted. **
** **
** 3GPP TS 24.301, section 5.4.2.3 **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: T3416 **
** Outputs: None **
** Return: None **
** Others: T3416 **
** **
***************************************************************************/
static void* _authentication_t3416_handler(void* args)
static void *_authentication_t3416_handler(void *args)
{
LOG_FUNC_IN;
......@@ -731,24 +733,24 @@ static void* _authentication_t3416_handler(void* args)
/****************************************************************************
** **
** Name: _authentication_t3418_handler() **
** Name: _authentication_t3418_handler() **
** **
** Description: T3418 timeout handler **
** Upon T3418 timer expiration, the UE shall deem that the **
** source of the authentication challenge is not genuine **
** (authentication not accepted by the UE). **
** Upon T3418 timer expiration, the UE shall deem that the **
** source of the authentication challenge is not genuine **
** (authentication not accepted by the UE). **
** **
** 3GPP TS 24.301, section 5.4.2.7, case c **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _authentication_data, T3418 **
** Outputs: None **
** Return: None **
** Others: _authentication_data, T3418 **
** **
***************************************************************************/
static void* _authentication_t3418_handler(void* args)
static void *_authentication_t3418_handler(void *args)
{
LOG_FUNC_IN;
......@@ -764,7 +766,7 @@ static void* _authentication_t3418_handler(void* args)
/* 3GPP TS 24.301, section 5.4.2.7, case f */
rc = _authentication_abnormal_case_f();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f");
LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f");
}
LOG_FUNC_RETURN (NULL);
......@@ -772,23 +774,23 @@ static void* _authentication_t3418_handler(void* args)
/****************************************************************************
** **
** Name: _authentication_t3420_handler() **
** Name: _authentication_t3420_handler() **
** **
** Description: T3420 timeout handler **
** Upon T3420 timer expiration, the UE shall deem that the **
** network has failed the authentication check. **
** Upon T3420 timer expiration, the UE shall deem that the **
** network has failed the authentication check. **
** **
** 3GPP TS 24.301, section 5.4.2.7, case e **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _authentication_data, T3420 **
** Outputs: None **
** Return: None **
** Others: _authentication_data, T3420 **
** **
***************************************************************************/
static void* _authentication_t3420_handler(void* args)
static void *_authentication_t3420_handler(void *args)
{
LOG_FUNC_IN;
......@@ -803,7 +805,7 @@ static void* _authentication_t3420_handler(void* args)
/* 3GPP TS 24.301, section 5.4.2.7, case f */
rc = _authentication_abnormal_case_f();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f");
LOG_TRACE(WARNING, "EMM-PROC - Failed to proceed abnormal case f");
}
LOG_FUNC_RETURN (NULL);
......@@ -811,37 +813,37 @@ static void* _authentication_t3420_handler(void* args)
/*
* --------------------------------------------------------------------------
* Abnormal cases in the UE
* Abnormal cases in the UE
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _authentication_abnormal_cases_cde() **
** Name: _authentication_abnormal_cases_cde() **
** **
** Description: Performs the abnormal case authentication procedure. **
** **
** 3GPP TS 24.301, section 5.4.2.7, cases c, d and e **
** 3GPP TS 24.301, section 5.4.2.7, cases c, d and e **
** **
** Inputs: emm_cause: EMM cause code **
** Others: None **
** Inputs: emm_cause: EMM cause code **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3418, T3420 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3418, T3420 **
** **
***************************************************************************/
static int _authentication_abnormal_cases_cde(int emm_cause,
const OctetString* auts)
const OctetString *auts)
{
LOG_FUNC_IN;
int rc;
LOG_TRACE(WARNING, "EMM-PROC - "
"Abnormal case, authentication counters c/d/e = %d/%d/%d",
_authentication_data.mac_count, _authentication_data.umts_count,
_authentication_data.sync_count);
"Abnormal case, authentication counters c/d/e = %d/%d/%d",
_authentication_data.mac_count, _authentication_data.umts_count,
_authentication_data.sync_count);
/*
* Notify EMM-AS SAP that Authentication Failure message has to be sent
......@@ -856,82 +858,81 @@ static int _authentication_abnormal_cases_cde(int emm_cause,
emm_sap.u.emm_as.u.security.auts = auts;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
_emm_data.security, FALSE, TRUE);
_emm_data.security, FALSE, TRUE);
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
/*
* Update the authentication failure counters
*/
switch (emm_cause)
{
case EMM_CAUSE_MAC_FAILURE:
/* 3GPP TS 24.301, section 5.4.2.6, case c
* Update the MAC failure counter */
_authentication_data.mac_count += 1;
/* Start timer T3418 */
T3418.id = nas_timer_start(T3418.sec,
_authentication_t3418_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in "
"%ld seconds", T3418.id, T3418.sec);
break;
case EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE:
/* 3GPP TS 24.301, section 5.4.2.6, case d
* Update the UMTS challenge failure counter */
_authentication_data.umts_count += 1;
/* Start timer T3418 */
T3418.id = nas_timer_start(T3418.sec,
_authentication_t3418_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in "
"%ld seconds", T3418.id, T3418.sec);
break;
case EMM_CAUSE_SYNCH_FAILURE:
/* 3GPP TS 24.301, section 5.4.2.6, case e
* Update the synch failure counter */
_authentication_data.sync_count += 1;
/* Start timer T3420 */
T3420.id = nas_timer_start(T3420.sec,
_authentication_t3420_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3420 (%d) expires in "
"%ld seconds", T3420.id, T3420.sec);
break;
default:
LOG_TRACE(WARNING, "EMM cause code is not valid (%d)",
emm_cause);
LOG_FUNC_RETURN (RETURNerror);
}
/*
* Stop any retransmission timers that are running
*/
rc = _authentication_stop_timers();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - "
"Failed to stop retransmission timers");
LOG_FUNC_RETURN (RETURNerror);
}
/*
* Check whether the network has failed the authentication check
*/
int failure_counter = 0;
if (emm_cause == EMM_CAUSE_MAC_FAILURE) {
failure_counter = _authentication_data.mac_count
+ _authentication_data.sync_count;
} else if (emm_cause == EMM_CAUSE_SYNCH_FAILURE) {
failure_counter = _authentication_data.mac_count
+ _authentication_data.umts_count
+ _authentication_data.sync_count;
}
if (failure_counter >= AUTHENTICATION_COUNTER_MAX) {
/* 3GPP TS 24.301, section 5.4.2.6, case f */
rc = _authentication_abnormal_case_f();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - "
"Failed to proceed abnormal case f");
}
}
/*
* Update the authentication failure counters
*/
switch (emm_cause) {
case EMM_CAUSE_MAC_FAILURE:
/* 3GPP TS 24.301, section 5.4.2.6, case c
* Update the MAC failure counter */
_authentication_data.mac_count += 1;
/* Start timer T3418 */
T3418.id = nas_timer_start(T3418.sec,
_authentication_t3418_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in "
"%ld seconds", T3418.id, T3418.sec);
break;
case EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE:
/* 3GPP TS 24.301, section 5.4.2.6, case d
* Update the UMTS challenge failure counter */
_authentication_data.umts_count += 1;
/* Start timer T3418 */
T3418.id = nas_timer_start(T3418.sec,
_authentication_t3418_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3418 (%d) expires in "
"%ld seconds", T3418.id, T3418.sec);
break;
case EMM_CAUSE_SYNCH_FAILURE:
/* 3GPP TS 24.301, section 5.4.2.6, case e
* Update the synch failure counter */
_authentication_data.sync_count += 1;
/* Start timer T3420 */
T3420.id = nas_timer_start(T3420.sec,
_authentication_t3420_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3420 (%d) expires in "
"%ld seconds", T3420.id, T3420.sec);
break;
default:
LOG_TRACE(WARNING, "EMM cause code is not valid (%d)",
emm_cause);
LOG_FUNC_RETURN (RETURNerror);
}
/*
* Stop any retransmission timers that are running
*/
rc = _authentication_stop_timers();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - "
"Failed to stop retransmission timers");
LOG_FUNC_RETURN (RETURNerror);
}
/*
* Check whether the network has failed the authentication check
*/
int failure_counter = 0;
if (emm_cause == EMM_CAUSE_MAC_FAILURE) {
failure_counter = _authentication_data.mac_count
+ _authentication_data.sync_count;
} else if (emm_cause == EMM_CAUSE_SYNCH_FAILURE) {
failure_counter = _authentication_data.mac_count
+ _authentication_data.umts_count
+ _authentication_data.sync_count;
}
if (failure_counter >= AUTHENTICATION_COUNTER_MAX) {
/* 3GPP TS 24.301, section 5.4.2.6, case f */
rc = _authentication_abnormal_case_f();
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-PROC - "
"Failed to proceed abnormal case f");
}
}
}
LOG_FUNC_RETURN (rc);
......@@ -939,18 +940,18 @@ static int _authentication_abnormal_cases_cde(int emm_cause,
/****************************************************************************
** **
** Name: _authentication_abnormal_case_f() **
** Name: _authentication_abnormal_case_f() **
** **
** Description: Performs the abnormal case authentication procedure. **
** **
** 3GPP TS 24.301, section 5.4.2.7, case f **
** 3GPP TS 24.301, section 5.4.2.7, case f **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _authentication_abnormal_case_f(void)
......@@ -972,11 +973,11 @@ static int _authentication_abnormal_case_f(void)
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
/* Start any retransmission timers (e.g. T3410, T3417, T3421 or
* T3430), if they were running and stopped when the UE received
* the first AUTHENTICATION REQUEST message containing an invalid
* MAC or SQN */
rc = _authentication_start_timers();
/* Start any retransmission timers (e.g. T3410, T3417, T3421 or
* T3430), if they were running and stopped when the UE received
* the first AUTHENTICATION REQUEST message containing an invalid
* MAC or SQN */
rc = _authentication_start_timers();
}
LOG_FUNC_RETURN (rc);
......@@ -984,24 +985,24 @@ static int _authentication_abnormal_case_f(void)
/*
* --------------------------------------------------------------------------
* UE specific local functions
* UE specific local functions
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _authentication_stop_timers() **
** Name: _authentication_stop_timers() **
** **
** Description: Stops any retransmission timers (e.g. T3410, T3417, T3421 **
** or T3430) that are running **
** or T3430) that are running **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3410, T3417, T3421, **
** T3430 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _authentication_data, T3410, T3417, T3421, **
** T3430 **
** **
***************************************************************************/
static int _authentication_stop_timers(void)
......@@ -1010,27 +1011,27 @@ static int _authentication_stop_timers(void)
/* Stop attach timer */
if (T3410.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id);
T3410.id = nas_timer_stop(T3410.id);
_authentication_data.timers |= AUTHENTICATION_T3410;
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3410 (%d)", T3410.id);
T3410.id = nas_timer_stop(T3410.id);
_authentication_data.timers |= AUTHENTICATION_T3410;
}
/* Stop service request timer */
if (T3417.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id);
T3417.id = nas_timer_stop(T3417.id);
_authentication_data.timers |= AUTHENTICATION_T3417;
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3417 (%d)", T3417.id);
T3417.id = nas_timer_stop(T3417.id);
_authentication_data.timers |= AUTHENTICATION_T3417;
}
/* Stop detach timer */
if (T3421.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3421 (%d)", T3421.id);
T3421.id = nas_timer_stop(T3421.id);
_authentication_data.timers |= AUTHENTICATION_T3421;
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3421 (%d)", T3421.id);
T3421.id = nas_timer_stop(T3421.id);
_authentication_data.timers |= AUTHENTICATION_T3421;
}
/* Stop tracking area update timer */
if (T3430.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id);
T3430.id = nas_timer_stop(T3430.id);
_authentication_data.timers |= AUTHENTICATION_T3430;
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3430 (%d)", T3430.id);
T3430.id = nas_timer_stop(T3430.id);
_authentication_data.timers |= AUTHENTICATION_T3430;
}
LOG_FUNC_RETURN (RETURNok);
......@@ -1038,21 +1039,21 @@ static int _authentication_stop_timers(void)
/****************************************************************************
** **
** Name: _authentication_start_timers() **
** Name: _authentication_start_timers() **
** **
** Description: Starts any retransmission timers (e.g. T3410, T3417, **
** T3421 or T3430), if they were running and stopped when **
** the UE received the first AUTHENTICATION REQUEST message **
** containing an invalid MAC or SQN **
** T3421 or T3430), if they were running and stopped when **
** the UE received the first AUTHENTICATION REQUEST message **
** containing an invalid MAC or SQN **
** **
** 3GPP TS 24.301, section 5.4.2.7, case f **
** 3GPP TS 24.301, section 5.4.2.7, case f **
** **
** Inputs: None **
** Others: _authentication_data **
** Inputs: None **
** Others: _authentication_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3410, T3417, T3421, T3430 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3410, T3417, T3421, T3430 **
** **
***************************************************************************/
static int _authentication_start_timers(void)
......@@ -1060,28 +1061,28 @@ static int _authentication_start_timers(void)
LOG_FUNC_IN;
if (_authentication_data.timers & AUTHENTICATION_T3410) {
/* Start attach timer */
T3410.id = nas_timer_start(T3410.sec, _emm_attach_t3410_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3410 (%d) expires in "
"%ld seconds", T3410.id, T3410.sec);
/* Start attach timer */
T3410.id = nas_timer_start(T3410.sec, _emm_attach_t3410_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3410 (%d) expires in "
"%ld seconds", T3410.id, T3410.sec);
}
if (_authentication_data.timers & AUTHENTICATION_T3417) {
/* Start service request timer */
T3417.id = nas_timer_start(T3417.sec, _emm_service_t3417_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3417 (%d) expires in "
"%ld seconds", T3417.id, T3417.sec);
/* Start service request timer */
T3417.id = nas_timer_start(T3417.sec, _emm_service_t3417_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3417 (%d) expires in "
"%ld seconds", T3417.id, T3417.sec);
}
if (_authentication_data.timers & AUTHENTICATION_T3421) {
/* Start detach timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3421 (%d) expires in "
"%ld seconds", T3421.id, T3421.sec);
/* Start detach timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3421 (%d) expires in "
"%ld seconds", T3421.id, T3421.sec);
}
if (_authentication_data.timers & AUTHENTICATION_T3430) {
/* Start tracking area update timer */
T3430.id = nas_timer_start(T3430.sec, _emm_tau_t3430_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3430 (%d) expires in "
"%ld seconds", T3430.id, T3430.sec);
/* Start tracking area update timer */
T3430.id = nas_timer_start(T3430.sec, _emm_tau_t3430_handler, NULL);
LOG_TRACE(INFO,"EMM-PROC - Timer T3430 (%d) expires in "
"%ld seconds", T3430.id, T3430.sec);
}
LOG_FUNC_RETURN (RETURNok);
......@@ -1089,27 +1090,27 @@ static int _authentication_start_timers(void)
/****************************************************************************
** **
** Name: _authentication_kasme() **
** Name: _authentication_kasme() **
** **
** Description: Computes the Key Access Security Management Entity Kasme **
** from the provided authentication challenge data. **
** from the provided authentication challenge data. **
** **
** 3GPP TS 33.401, Annex A.2 **
** **
** Inputs: autn: Authentication token **
** ck: Cipherig key **
** ik: Integrity key **
** plmn: Identifier of the currently selected PLMN **
** Others: None **
** Inputs: autn: Authentication token **
** ck: Cipherig key **
** ik: Integrity key **
** plmn: Identifier of the currently selected PLMN **
** Others: None **
** **
** Outputs: kasme: Key Access Security Management Entity **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: kasme: Key Access Security Management Entity **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _authentication_kasme(const OctetString* autn,
const OctetString* ck, const OctetString* ik,
const plmn_t* plmn, OctetString* kasme)
static int _authentication_kasme(const OctetString *autn,
const OctetString *ck, const OctetString *ik,
const plmn_t *plmn, OctetString *kasme)
{
LOG_FUNC_IN;
......@@ -1125,12 +1126,16 @@ static int _authentication_kasme(const OctetString* autn,
UInt16_t length;
int offset = 0;
int size_of_length = sizeof(length);
input[offset] = 0x10; offset += 1;
input[offset] = 0x10;
offset += 1;
length = AUTH_SNID_SIZE;
memcpy(input + offset, plmn, length); offset += length;
memcpy(input + offset, &length, size_of_length); offset += size_of_length;
memcpy(input + offset, plmn, length);
offset += length;
memcpy(input + offset, &length, size_of_length);
offset += size_of_length;
length = AUTH_SQN_SIZE;
memcpy(input + offset, autn, length); offset += length;
memcpy(input + offset, autn, length);
offset += length;
memcpy(input + offset, &length, size_of_length);
/* TODO !!! Compute the Kasme key */
......@@ -1143,64 +1148,63 @@ static int _authentication_kasme(const OctetString* autn,
#ifdef NAS_MME
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _authentication_t3460_handler() **
** Name: _authentication_t3460_handler() **
** **
** Description: T3460 timeout handler **
** Upon T3460 timer expiration, the authentication request **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** authentication procedure and any ongoing EMM specific **
** procedure and release the NAS signalling connection. **
** Upon T3460 timer expiration, the authentication request **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** authentication procedure and any ongoing EMM specific **
** procedure and release the NAS signalling connection. **
** **
** 3GPP TS 24.301, section 5.4.2.7, case b **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
static void* _authentication_t3460_handler(void* args)
static void *_authentication_t3460_handler(void *args)
{
LOG_FUNC_IN;
int rc;
authentication_data_t* data = (authentication_data_t*)(args);
authentication_data_t *data = (authentication_data_t *)(args);
/* Increment the retransmission counter */
data->retransmission_count += 1;
LOG_TRACE(WARNING, "EMM-PROC - T3460 timer expired, retransmission "
"counter = %d", data->retransmission_count);
"counter = %d", data->retransmission_count);
if (data->retransmission_count < AUTHENTICATION_COUNTER_MAX) {
/* Send authentication request message to the UE */
rc = _authentication_request(data);
}
else {
unsigned int ueid = data->ueid;
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the authentication procedure */
rc = _authentication_abort(data);
/* Release the NAS signalling connection */
if (rc != RETURNerror) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMAS_RELEASE_REQ;
emm_sap.u.emm_as.u.release.guti = NULL;
emm_sap.u.emm_as.u.release.ueid = ueid;
emm_sap.u.emm_as.u.release.cause = EMM_AS_CAUSE_AUTHENTICATION;
rc = emm_sap_send(&emm_sap);
}
/* Send authentication request message to the UE */
rc = _authentication_request(data);
} else {
unsigned int ueid = data->ueid;
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the authentication procedure */
rc = _authentication_abort(data);
/* Release the NAS signalling connection */
if (rc != RETURNerror) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMAS_RELEASE_REQ;
emm_sap.u.emm_as.u.release.guti = NULL;
emm_sap.u.emm_as.u.release.ueid = ueid;
emm_sap.u.emm_as.u.release.cause = EMM_AS_CAUSE_AUTHENTICATION;
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN (NULL);
......@@ -1208,25 +1212,25 @@ static void* _authentication_t3460_handler(void* args)
/*
* --------------------------------------------------------------------------
* MME specific local functions
* MME specific local functions
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _authentication_request() **
** Name: _authentication_request() **
** **
** Description: Sends AUTHENTICATION REQUEST message and start timer T3460**
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** **
***************************************************************************/
int _authentication_request(authentication_data_t* data)
int _authentication_request(authentication_data_t *data)
{
LOG_FUNC_IN;
......@@ -1259,16 +1263,16 @@ int _authentication_request(authentication_data_t* data)
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3460 timer */
T3460.id = nas_timer_restart(T3460.id);
} else {
/* Start T3460 timer */
T3460.id = nas_timer_start(T3460.sec, _authentication_t3460_handler,
data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3460 (%d) expires in %ld seconds",
T3460.id, T3460.sec);
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3460 timer */
T3460.id = nas_timer_restart(T3460.id);
} else {
/* Start T3460 timer */
T3460.id = nas_timer_start(T3460.sec, _authentication_t3460_handler,
data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3460 (%d) expires in %ld seconds",
T3460.id, T3460.sec);
}
LOG_FUNC_RETURN (rc);
......@@ -1276,16 +1280,16 @@ int _authentication_request(authentication_data_t* data)
/****************************************************************************
** **
** Name: _authentication_reject() **
** Name: _authentication_reject() **
** **
** Description: Sends AUTHENTICATION REJECT message **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _authentication_reject(unsigned int ueid)
......@@ -1320,59 +1324,58 @@ static int _authentication_reject(unsigned int ueid)
/****************************************************************************
** **
** Name: _authentication_abort() **
** Name: _authentication_abort() **
** **
** Description: Aborts the authentication procedure currently in progress **
** **
** Inputs: args: Authentication data to be released **
** Others: None **
** Inputs: args: Authentication data to be released **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** **
***************************************************************************/
static int _authentication_abort(void* args)
static int _authentication_abort(void *args)
{
LOG_FUNC_IN;
int rc = RETURNerror;
authentication_data_t* data = (authentication_data_t*)(args);
if (data)
{
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort authentication procedure "
"(ueid=%u)", ueid);
/* Stop timer T3460 */
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3460 (%d)", T3460.id);
T3460.id = nas_timer_stop(T3460.id);
}
/* Release retransmission timer paramaters */
if (data->rand.length > 0) {
free(data->rand.value);
}
if (data->autn.length > 0) {
free(data->autn.value);
}
free(data);
/*
* Notify EMM that the authentication procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
authentication_data_t *data = (authentication_data_t *)(args);
if (data) {
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort authentication procedure "
"(ueid=%u)", ueid);
/* Stop timer T3460 */
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3460 (%d)", T3460.id);
T3460.id = nas_timer_stop(T3460.id);
}
/* Release retransmission timer paramaters */
if (data->rand.length > 0) {
free(data->rand.value);
}
if (data->autn.length > 0) {
free(data->autn.value);
}
free(data);
/*
* Notify EMM that the authentication procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
}
LOG_FUNC_RETURN (rc);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source Detach.c
Source Detach.c
Version 0.1
Version 0.1
Date 2013/05/07
Date 2013/05/07
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the detach related EMM procedure executed by the
Non-Access Stratum.
Description Defines the detach related EMM procedure executed by the
Non-Access Stratum.
The detach procedure is used by the UE to detach for EPS servi-
ces, to disconnect from the last PDN it is connected to; by the
network to inform the UE that it is detached for EPS services
or non-EPS services or both, to disconnect the UE from the last
PDN to which it is connected and to inform the UE to re-attach
to the network and re-establish all PDN connections.
The detach procedure is used by the UE to detach for EPS servi-
ces, to disconnect from the last PDN it is connected to; by the
network to inform the UE that it is detached for EPS services
or non-EPS services or both, to disconnect the UE from the last
PDN to which it is connected and to inform the UE to re-attach
to the network and re-establish all PDN connections.
*****************************************************************************/
......@@ -35,7 +35,7 @@ Description Defines the detach related EMM procedure executed by the
#include "emm_sap.h"
#include "esm_sap.h"
#include <stdlib.h> // free
#include <stdlib.h> // free
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
......@@ -46,21 +46,21 @@ Description Defines the detach related EMM procedure executed by the
/****************************************************************************/
/* String representation of the detach type */
static const char* _emm_detach_type_str[] = {
static const char *_emm_detach_type_str[] = {
"EPS", "IMSI", "EPS/IMSI",
"RE-ATTACH REQUIRED", "RE-ATTACH NOT REQUIRED", "RESERVED"
};
/*
* --------------------------------------------------------------------------
* Internal data handled by the detach procedure in the UE
* Internal data handled by the detach procedure in the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/*
* Timer handlers
*/
void* _emm_detach_t3421_handler(void*);
void *_emm_detach_t3421_handler(void *);
/*
* Abnormal case detach procedures
......@@ -71,18 +71,18 @@ static int _emm_detach_abort(emm_proc_detach_type_t type);
* Internal data used for detach procedure
*/
static struct {
#define EMM_DETACH_COUNTER_MAX 5
unsigned int count; /* Counter used to limit the number of
* subsequently detach attempts */
int switch_off; /* UE switch-off indicator */
#define EMM_DETACH_COUNTER_MAX 5
unsigned int count; /* Counter used to limit the number of
* subsequently detach attempts */
int switch_off; /* UE switch-off indicator */
emm_proc_detach_type_t type; /* Type of the detach procedure
* currently in progress */
* currently in progress */
} _emm_detach_data = {0, FALSE, EMM_DETACH_TYPE_RESERVED};
#endif // NAS_UE
/*
* --------------------------------------------------------------------------
* Internal data handled by the detach procedure in the MME
* Internal data handled by the detach procedure in the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
......@@ -94,31 +94,31 @@ static struct {
/*
* --------------------------------------------------------------------------
* Detach procedure executed by the UE
* Detach procedure executed by the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_proc_detach() **
** Name: emm_proc_detach() **
** **
** Description: Initiates the detach procedure in order for the UE to de- **
** tach for EPS services. **
** tach for EPS services. **
** **
** 3GPP TS 24.301, section 5.5.2.2.1 **
** In state EMM-REGISTERED or EMM-REGISTERED-INITIATED, the **
** UE initiates the detach procedure by sending a DETACH RE- **
** QUEST message to the network, starting timer T3421 and **
** entering state EMM-DEREGISTERED-INITIATED. **
** In state EMM-REGISTERED or EMM-REGISTERED-INITIATED, the **
** UE initiates the detach procedure by sending a DETACH RE- **
** QUEST message to the network, starting timer T3421 and **
** entering state EMM-DEREGISTERED-INITIATED. **
** **
** Inputs: type: Type of the requested detach **
** switch_off: Indicates whether the detach is required **
** because the UE is switched off or not **
** Others: _emm_data **
** Inputs: type: Type of the requested detach **
** switch_off: Indicates whether the detach is required **
** because the UE is switched off or not **
** Others: _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_detach_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_detach_data **
** **
***************************************************************************/
int emm_proc_detach(emm_proc_detach_type_t type, int switch_off)
......@@ -130,7 +130,7 @@ int emm_proc_detach(emm_proc_detach_type_t type, int switch_off)
int rc;
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS detach type = %s (%d)",
_emm_detach_type_str[type], type);
_emm_detach_type_str[type], type);
/* Initialize the detach procedure internal data */
_emm_detach_data.count = 0;
......@@ -140,11 +140,11 @@ int emm_proc_detach(emm_proc_detach_type_t type, int switch_off)
/* Setup EMM procedure handler to be executed upon receiving
* lower layer notification */
rc = emm_proc_lowerlayer_initialize(emm_proc_detach_request,
emm_proc_detach_failure,
emm_proc_detach_release, NULL);
emm_proc_detach_failure,
emm_proc_detach_release, NULL);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING, "Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
}
/* Setup NAS information message to transfer */
......@@ -173,21 +173,21 @@ int emm_proc_detach(emm_proc_detach_type_t type, int switch_off)
/****************************************************************************
** **
** Name: emm_proc_detach_request() **
** Name: emm_proc_detach_request() **
** **
** Description: Performs the detach procedure upon receipt of indication **
** from lower layers that Detach Request message has been **
** successfully delivered to the network. **
** from lower layers that Detach Request message has been **
** successfully delivered to the network. **
** **
** Inputs: args: Not used **
** Others: None **
** Inputs: args: Not used **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** **
***************************************************************************/
int emm_proc_detach_request(void* args)
int emm_proc_detach_request(void *args)
{
LOG_FUNC_IN;
......@@ -195,10 +195,10 @@ int emm_proc_detach_request(void* args)
int rc;
if ( !_emm_detach_data.switch_off ) {
/* Start T3421 timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld seconds",
T3421.id, T3421.sec);
/* Start T3421 timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld seconds",
T3421.id, T3421.sec);
}
/*
......@@ -212,24 +212,24 @@ int emm_proc_detach_request(void* args)
/****************************************************************************
** **
** Name: emm_proc_detach_accept() **
** Name: emm_proc_detach_accept() **
** **
** Description: Performs the UE initiated detach procedure for EPS servi- **
** ces only When the DETACH ACCEPT message is received from **
** the network. **
** ces only When the DETACH ACCEPT message is received from **
** the network. **
** **
** 3GPP TS 24.301, section 5.5.2.2.2 **
** Upon receiving the DETACH ACCEPT message, the UE shall **
** stop timer T3421, locally deactivate all EPS bearer con- **
** texts without peer-to-peer signalling and enter state EMM-**
** DEREGISTERED. **
** stop timer T3421, locally deactivate all EPS bearer con- **
** texts without peer-to-peer signalling and enter state EMM-**
** DEREGISTERED. **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** **
***************************************************************************/
int emm_proc_detach_accept(void)
......@@ -264,24 +264,24 @@ int emm_proc_detach_accept(void)
/****************************************************************************
** **
** Name: emm_proc_detach_failure() **
** Name: emm_proc_detach_failure() **
** **
** Description: Performs the detach procedure abnormal case upon receipt **
** of transmission failure of Detach Request message. **
** of transmission failure of Detach Request message. **
** **
** 3GPP TS 24.301, section 5.5.2.2.4, case h **
** The UE shall restart the detach procedure. **
** The UE shall restart the detach procedure. **
** **
** Inputs: is_initial: Not used **
** args: Not used **
** Others: _emm_detach_data **
** Inputs: is_initial: Not used **
** args: Not used **
** Others: _emm_detach_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_detach_failure(int is_initial, void* args)
int emm_proc_detach_failure(int is_initial, void *args)
{
LOG_FUNC_IN;
......@@ -308,24 +308,24 @@ int emm_proc_detach_failure(int is_initial, void* args)
/****************************************************************************
** **
** Name: emm_proc_detach_release() **
** Name: emm_proc_detach_release() **
** **
** Description: Performs the detach procedure abnormal case upon receipt **
** of NAS signalling connection release indication before **
** reception of Detach Accept message. **
** of NAS signalling connection release indication before **
** reception of Detach Accept message. **
** **
** 3GPP TS 24.301, section 5.5.2.2.4, case b **
** The detach procedure shall be aborted. **
** The detach procedure shall be aborted. **
** **
** Inputs: args: not used **
** Others: _emm_detach_data **
** Inputs: args: not used **
** Others: _emm_detach_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_detach_release(void* args)
int emm_proc_detach_release(void *args)
{
LOG_FUNC_IN;
......@@ -340,31 +340,31 @@ int emm_proc_detach_release(void* args)
/*
* --------------------------------------------------------------------------
* Detach procedure executed by the MME
* Detach procedure executed by the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/****************************************************************************
** **
** Name: emm_proc_detach() **
** Name: emm_proc_detach() **
** **
** Description: Initiate the detach procedure to inform the UE that it is **
** detached for EPS services, or to re-attach to the network **
** and re-establish all PDN connections. **
** detached for EPS services, or to re-attach to the network **
** and re-establish all PDN connections. **
** **
** 3GPP TS 24.301, section 5.5.2.3.1 **
** In state EMM-REGISTERED the network initiates the detach **
** procedure by sending a DETACH REQUEST message to the UE, **
** starting timer T3422 and entering state EMM-DEREGISTERED- **
** INITIATED. **
** In state EMM-REGISTERED the network initiates the detach **
** procedure by sending a DETACH REQUEST message to the UE, **
** starting timer T3422 and entering state EMM-DEREGISTERED- **
** INITIATED. **
** **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested detach **
** Others: _emm_detach_type_str **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested detach **
** Others: _emm_detach_type_str **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3422 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3422 **
** **
***************************************************************************/
int emm_proc_detach(unsigned int ueid, emm_proc_detach_type_t type)
......@@ -374,7 +374,7 @@ int emm_proc_detach(unsigned int ueid, emm_proc_detach_type_t type)
int rc = RETURNerror;
LOG_TRACE(INFO, "EMM-PROC - Initiate detach type = %s (%d)",
_emm_detach_type_str[type], type);
_emm_detach_type_str[type], type);
/* TODO */
......@@ -383,51 +383,51 @@ int emm_proc_detach(unsigned int ueid, emm_proc_detach_type_t type)
/****************************************************************************
** **
** Name: emm_proc_detach_request() **
** Name: emm_proc_detach_request() **
** **
** Description: Performs the UE initiated detach procedure for EPS servi- **
** ces only When the DETACH REQUEST message is received by **
** the network. **
** ces only When the DETACH REQUEST message is received by **
** the network. **
** **
** 3GPP TS 24.301, section 5.5.2.2.2 **
** Upon receiving the DETACH REQUEST message the network **
** shall send a DETACH ACCEPT message to the UE and store **
** the current EPS security context, if the detach type IE **
** does not indicate "switch off". Otherwise, the procedure **
** is completed when the network receives the DETACH REQUEST **
** message. **
** The network shall deactivate the EPS bearer context(s) **
** for this UE locally without peer-to-peer signalling and **
** shall enter state EMM-DEREGISTERED. **
** **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested detach **
** switch_off: Indicates whether the detach is required **
** because the UE is switched off or not **
** native_ksi: TRUE if the security context is of type **
** native **
** ksi: The NAS ket sey identifier **
** guti: The GUTI if provided by the UE **
** imsi: The IMSI if provided by the UE **
** imei: The IMEI if provided by the UE **
** Others: _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Upon receiving the DETACH REQUEST message the network **
** shall send a DETACH ACCEPT message to the UE and store **
** the current EPS security context, if the detach type IE **
** does not indicate "switch off". Otherwise, the procedure **
** is completed when the network receives the DETACH REQUEST **
** message. **
** The network shall deactivate the EPS bearer context(s) **
** for this UE locally without peer-to-peer signalling and **
** shall enter state EMM-DEREGISTERED. **
** **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested detach **
** switch_off: Indicates whether the detach is required **
** because the UE is switched off or not **
** native_ksi: TRUE if the security context is of type **
** native **
** ksi: The NAS ket sey identifier **
** guti: The GUTI if provided by the UE **
** imsi: The IMSI if provided by the UE **
** imei: The IMEI if provided by the UE **
** Others: _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
int switch_off, int native_ksi, int ksi,
GUTI_t* guti, imsi_t* imsi, imei_t* imei)
int switch_off, int native_ksi, int ksi,
GUTI_t *guti, imsi_t *imsi, imei_t *imei)
{
LOG_FUNC_IN;
int rc;
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
LOG_TRACE(INFO, "EMM-PROC - Detach type = %s (%d) requested (ueid=%u)",
_emm_detach_type_str[type], type, ueid);
_emm_detach_type_str[type], type, ueid);
/* Get the UE context */
#if defined(EPC_BUILD)
......@@ -436,82 +436,94 @@ int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
}
#else
if (ueid < EMM_DATA_NB_UE_MAX) {
emm_ctx = _emm_data.ctx[ueid];
emm_ctx = _emm_data.ctx[ueid];
}
#endif
if (emm_ctx == NULL) {
LOG_TRACE(WARNING, "No EMM context exists for the UE (ueid=%u)", ueid);
LOG_FUNC_RETURN(RETURNok);
LOG_TRACE(WARNING, "No EMM context exists for the UE (ueid=%u)", ueid);
LOG_FUNC_RETURN(RETURNok);
}
if (switch_off)
{
/* The UE is switched off */
if (emm_ctx->guti) free(emm_ctx->guti);
if (emm_ctx->imsi) free(emm_ctx->imsi);
if (emm_ctx->imei) free(emm_ctx->imei);
if (emm_ctx->esm_msg.length > 0) free(emm_ctx->esm_msg.value);
/* Release NAS security context */
if (emm_ctx->security) {
emm_security_context_t* security = emm_ctx->security;
if (security->kasme.value) free(security->kasme.value);
if (security->knas_enc.value) free(security->knas_enc.value);
if (security->knas_int.value) free(security->knas_int.value);
free(emm_ctx->security);
}
/* Release the EMM context */
if (switch_off) {
/* The UE is switched off */
if (emm_ctx->guti) {
free(emm_ctx->guti);
}
if (emm_ctx->imsi) {
free(emm_ctx->imsi);
}
if (emm_ctx->imei) {
free(emm_ctx->imei);
}
if (emm_ctx->esm_msg.length > 0) {
free(emm_ctx->esm_msg.value);
}
/* Release NAS security context */
if (emm_ctx->security) {
emm_security_context_t *security = emm_ctx->security;
if (security->kasme.value) {
free(security->kasme.value);
}
if (security->knas_enc.value) {
free(security->knas_enc.value);
}
if (security->knas_int.value) {
free(security->knas_int.value);
}
free(emm_ctx->security);
}
/* Release the EMM context */
#if defined(EPC_BUILD)
emm_data_context_remove(&_emm_data, emm_ctx);
free(emm_ctx);
#else
free(_emm_data.ctx[ueid]);
_emm_data.ctx[ueid] = NULL;
free(_emm_data.ctx[ueid]);
_emm_data.ctx[ueid] = NULL;
#endif
rc = RETURNok;
}
else {
/* Normal detach without UE switch-off */
emm_sap_t emm_sap;
emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data;
/* Setup NAS information message to transfer */
emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH;
emm_as->NASmsg.length = 0;
emm_as->NASmsg.value = NULL;
/* Set the UE identifier */
emm_as->guti = NULL;
emm_as->ueid = ueid;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_as->sctx, emm_ctx->security, FALSE, TRUE);
/*
* Notify EMM-AS SAP that Detach Accept message has to
* be sent to the network
*/
emm_sap.primitive = EMMAS_DATA_REQ;
rc = emm_sap_send(&emm_sap);
rc = RETURNok;
} else {
/* Normal detach without UE switch-off */
emm_sap_t emm_sap;
emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data;
/* Setup NAS information message to transfer */
emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH;
emm_as->NASmsg.length = 0;
emm_as->NASmsg.value = NULL;
/* Set the UE identifier */
emm_as->guti = NULL;
emm_as->ueid = ueid;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_as->sctx, emm_ctx->security, FALSE, TRUE);
/*
* Notify EMM-AS SAP that Detach Accept message has to
* be sent to the network
*/
emm_sap.primitive = EMMAS_DATA_REQ;
rc = emm_sap_send(&emm_sap);
}
if (rc != RETURNerror) {
/*
* Notify ESM that all EPS bearer contexts allocated for this UE have
* to be locally deactivated
*/
esm_sap_t esm_sap;
esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ;
esm_sap.ueid = ueid;
esm_sap.data.eps_bearer_context_deactivate.ebi = ESM_SAP_ALL_EBI;
rc = esm_sap_send(&esm_sap);
if (rc != RETURNerror) {
emm_sap_t emm_sap;
/*
* Notify EMM that the UE has been implicitly detached
*/
emm_sap.primitive = EMMREG_DETACH_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
/*
* Notify ESM that all EPS bearer contexts allocated for this UE have
* to be locally deactivated
*/
esm_sap_t esm_sap;
esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ;
esm_sap.ueid = ueid;
esm_sap.data.eps_bearer_context_deactivate.ebi = ESM_SAP_ALL_EBI;
rc = esm_sap_send(&esm_sap);
if (rc != RETURNerror) {
emm_sap_t emm_sap;
/*
* Notify EMM that the UE has been implicitly detached
*/
emm_sap.primitive = EMMREG_DETACH_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN(rc);
......@@ -525,31 +537,31 @@ int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
#ifdef NAS_UE
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _emm_detach_t3421_handler() **
** Name: _emm_detach_t3421_handler() **
** **
** Description: T3421 timeout handler **
** **
** 3GPP TS 24.301, section 5.5.2.2.4 case c **
** On the first four expiries of the timer, the UE shall re- **
** transmit the DETACH REQUEST message and shall reset and **
** restart timer T3421. On the fifth expiry of timer T3421, **
** the detach procedure shall be aborted. **
** On the first four expiries of the timer, the UE shall re- **
** transmit the DETACH REQUEST message and shall reset and **
** restart timer T3421. On the fifth expiry of timer T3421, **
** the detach procedure shall be aborted. **
** **
** Inputs: args: handler parameters **
** Others: _emm_detach_data **
** Inputs: args: handler parameters **
** Others: _emm_detach_data **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
void* _emm_detach_t3421_handler(void* args)
void *_emm_detach_t3421_handler(void *args)
{
LOG_FUNC_IN;
......@@ -559,49 +571,47 @@ void* _emm_detach_t3421_handler(void* args)
_emm_detach_data.count += 1;
LOG_TRACE(WARNING, "EMM-PROC - T3421 timer expired, "
"retransmission counter = %d", _emm_detach_data.count);
if (_emm_detach_data.count < EMM_DETACH_COUNTER_MAX)
{
/* Retransmit the Detach Request message */
emm_sap_t emm_sap;
emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data;
/* Stop timer T3421 */
T3421.id = nas_timer_stop(T3421.id);
/* Setup NAS information message to transfer */
emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH;
emm_as->NASmsg.length = 0;
emm_as->NASmsg.value = NULL;
/* Set the detach type */
emm_as->type = _emm_detach_data.type;
/* Set the switch-off indicator */
emm_as->switch_off = _emm_detach_data.switch_off;
/* Set the EPS mobile identity */
emm_as->guti = _emm_data.guti;
emm_as->ueid = 0;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_as->sctx, _emm_data.security,
FALSE, TRUE);
/*
* Notify EMM-AS SAP that Detach Request message has to
* be sent to the network
*/
emm_sap.primitive = EMMAS_DATA_REQ;
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
/* Start T3421 timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld "
"seconds", T3421.id, T3421.sec);
}
}
else {
/* Abort the detach procedure */
rc = _emm_detach_abort(_emm_detach_data.type);
"retransmission counter = %d", _emm_detach_data.count);
if (_emm_detach_data.count < EMM_DETACH_COUNTER_MAX) {
/* Retransmit the Detach Request message */
emm_sap_t emm_sap;
emm_as_data_t *emm_as = &emm_sap.u.emm_as.u.data;
/* Stop timer T3421 */
T3421.id = nas_timer_stop(T3421.id);
/* Setup NAS information message to transfer */
emm_as->NASinfo = EMM_AS_NAS_INFO_DETACH;
emm_as->NASmsg.length = 0;
emm_as->NASmsg.value = NULL;
/* Set the detach type */
emm_as->type = _emm_detach_data.type;
/* Set the switch-off indicator */
emm_as->switch_off = _emm_detach_data.switch_off;
/* Set the EPS mobile identity */
emm_as->guti = _emm_data.guti;
emm_as->ueid = 0;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_as->sctx, _emm_data.security,
FALSE, TRUE);
/*
* Notify EMM-AS SAP that Detach Request message has to
* be sent to the network
*/
emm_sap.primitive = EMMAS_DATA_REQ;
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
/* Start T3421 timer */
T3421.id = nas_timer_start(T3421.sec, _emm_detach_t3421_handler, NULL);
LOG_TRACE(INFO, "EMM-PROC - Timer T3421 (%d) expires in %ld "
"seconds", T3421.id, T3421.sec);
}
} else {
/* Abort the detach procedure */
rc = _emm_detach_abort(_emm_detach_data.type);
}
LOG_FUNC_RETURN(NULL);
......@@ -609,22 +619,22 @@ void* _emm_detach_t3421_handler(void* args)
/*
* --------------------------------------------------------------------------
* Abnormal cases in the UE
* Abnormal cases in the UE
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _emm_detach_abort() **
** Name: _emm_detach_abort() **
** **
** Description: Aborts the detach procedure **
** **
** Inputs: type: not used **
** Others: _emm_detach_data **
** Inputs: type: not used **
** Others: _emm_detach_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3421 **
** **
***************************************************************************/
static int _emm_detach_abort(emm_proc_detach_type_t type)
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source EmmCommon.h
Source EmmCommon.h
Version 0.1
Version 0.1
Date 2013/04/19
Date 2013/04/19
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines callback functions executed within EMM common procedures
by the Non-Access Stratum running at the network side.
Description Defines callback functions executed within EMM common procedures
by the Non-Access Stratum running at the network side.
Following EMM common procedures can always be initiated by the
network whilst a NAS signalling connection exists:
Following EMM common procedures can always be initiated by the
network whilst a NAS signalling connection exists:
GUTI reallocation
authentication
security mode control
identification
EMM information
GUTI reallocation
authentication
security mode control
identification
EMM information
*****************************************************************************/
......@@ -36,7 +36,7 @@ Description Defines callback functions executed within EMM common procedures
#include "nas_log.h"
#include "emmData.h"
#include <stdlib.h> // malloc, free
#include <stdlib.h> // malloc, free
#include <string.h>
#include <assert.h>
......@@ -52,10 +52,10 @@ Description Defines callback functions executed within EMM common procedures
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
/* EMM procedure callback cleanup function */
/* EMM procedure callback cleanup function */
static void _emm_common_cleanup(unsigned int ueid);
/* Ongoing EMM procedure callback functions */
/* Ongoing EMM procedure callback functions */
typedef struct emm_common_data_s {
unsigned int ueid;
int ref_count;
......@@ -63,7 +63,7 @@ typedef struct emm_common_data_s {
emm_common_reject_callback_t reject;
emm_common_failure_callback_t failure;
emm_common_abort_callback_t abort;
void* args;
void *args;
#if defined(EPC_BUILD)
RB_ENTRY(emm_common_data_s) entries;
......@@ -117,7 +117,7 @@ struct emm_common_data_s *emm_common_data_context_get(
return RB_FIND(emm_common_data_map, &root->emm_common_data_root, &reference);
}
#else
static emm_common_data_t* _emm_common_data[EMM_DATA_NB_UE_MAX];
static emm_common_data_t *_emm_common_data[EMM_DATA_NB_UE_MAX];
#endif
/****************************************************************************/
......@@ -126,34 +126,34 @@ static emm_common_data_t* _emm_common_data[EMM_DATA_NB_UE_MAX];
/****************************************************************************
** **
** Name: emm_proc_common_initialize() **
** Name: emm_proc_common_initialize() **
** **
** Description: Initialize EMM procedure callback functions executed for **
** the UE with the given identifier **
** **
** Inputs: ueid: UE lower layer identifier **
** success: EMM procedure executed upon successful EMM **
** common procedure completion **
** reject: EMM procedure executed if the EMM common **
** procedure failed or is rejected **
** failure: EMM procedure executed upon transmission **
** failure reported by lower layer **
** abort: EMM common procedure executed when the on- **
** going EMM procedure is aborted **
** args: EMM common procedure argument parameters **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_common_data **
** the UE with the given identifier **
** **
** Inputs: ueid: UE lower layer identifier **
** success: EMM procedure executed upon successful EMM **
** common procedure completion **
** reject: EMM procedure executed if the EMM common **
** procedure failed or is rejected **
** failure: EMM procedure executed upon transmission **
** failure reported by lower layer **
** abort: EMM common procedure executed when the on- **
** going EMM procedure is aborted **
** args: EMM common procedure argument parameters **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_common_data **
** **
***************************************************************************/
int emm_proc_common_initialize(unsigned int ueid,
emm_common_success_callback_t _success,
emm_common_reject_callback_t _reject,
emm_common_failure_callback_t _failure,
emm_common_abort_callback_t _abort,
void* args)
emm_common_success_callback_t _success,
emm_common_reject_callback_t _reject,
emm_common_failure_callback_t _failure,
emm_common_abort_callback_t _abort,
void *args)
{
struct emm_common_data_s *emm_common_data_ctx = NULL;
LOG_FUNC_IN;
......@@ -166,7 +166,7 @@ int emm_proc_common_initialize(unsigned int ueid,
#endif
if (emm_common_data_ctx == NULL) {
emm_common_data_ctx = (emm_common_data_t*)malloc(sizeof(emm_common_data_t));
emm_common_data_ctx = (emm_common_data_t *)malloc(sizeof(emm_common_data_t));
emm_common_data_ctx->ueid = ueid;
#if defined(EPC_BUILD)
RB_INSERT(emm_common_data_map, &emm_common_data_head.emm_common_data_root,
......@@ -191,19 +191,19 @@ int emm_proc_common_initialize(unsigned int ueid,
/****************************************************************************
** **
** Name: emm_proc_common_success() **
** Name: emm_proc_common_success() **
** **
** Description: The EMM common procedure initiated between the UE with **
** the specified identifier and the MME completed success- **
** fully. The network performs required actions related to **
** the ongoing EMM procedure. **
** the specified identifier and the MME completed success- **
** fully. The network performs required actions related to **
** the ongoing EMM procedure. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_common_success(unsigned int ueid)
......@@ -244,19 +244,19 @@ int emm_proc_common_success(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_common_reject() **
** Name: emm_proc_common_reject() **
** **
** Description: The EMM common procedure initiated between the UE with **
** the specified identifier and the MME failed or has been **
** rejected. The network performs required actions related **
** to the ongoing EMM procedure. **
** the specified identifier and the MME failed or has been **
** rejected. The network performs required actions related **
** to the ongoing EMM procedure. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_common_reject(unsigned int ueid)
......@@ -297,20 +297,20 @@ int emm_proc_common_reject(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_common_failure() **
** Name: emm_proc_common_failure() **
** **
** Description: The EMM common procedure has been initiated between the **
** UE with the specified identifier and the MME, and a lower **
** layer failure occurred before the EMM common procedure **
** being completed. The network performs required actions **
** related to the ongoing EMM procedure. **
** UE with the specified identifier and the MME, and a lower **
** layer failure occurred before the EMM common procedure **
** being completed. The network performs required actions **
** related to the ongoing EMM procedure. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data, _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_common_failure(unsigned int ueid)
......@@ -350,19 +350,19 @@ int emm_proc_common_failure(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_common_abort() **
** Name: emm_proc_common_abort() **
** **
** Description: The ongoing EMM procedure has been aborted. The network **
** performs required actions related to the EMM common pro- **
** cedure previously initiated between the UE with the spe- **
** cified identifier and the MME. **
** performs required actions related to the EMM common pro- **
** cedure previously initiated between the UE with the spe- **
** cified identifier and the MME. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_common_abort(unsigned int ueid)
......@@ -402,21 +402,21 @@ int emm_proc_common_abort(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_common_get_args() **
** Name: emm_proc_common_get_args() **
** **
** Description: Returns pointer to the EMM common procedure argument pa- **
** rameters allocated for the UE with the given identifier. **
** rameters allocated for the UE with the given identifier. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data **
** Inputs: ueid: UE lower layer identifier **
** Others: _emm_common_data **
** **
** Outputs: None **
** Return: pointer to the EMM common procedure argu- **
** ment parameters **
** Others: None **
** Outputs: None **
** Return: pointer to the EMM common procedure argu- **
** ment parameters **
** Others: None **
** **
***************************************************************************/
void* emm_proc_common_get_args(unsigned int ueid)
void *emm_proc_common_get_args(unsigned int ueid)
{
emm_common_data_t *emm_common_data_ctx = NULL;
LOG_FUNC_IN;
......@@ -439,19 +439,19 @@ void* emm_proc_common_get_args(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_common_cleanup() **
** Name: emm_proc_common_cleanup() **
** **
** Description: Cleans EMM procedure callback functions upon completion **
** of an EMM common procedure previously initiated within an **
** EMM procedure currently in progress between the network **
** and the UE with the specified identifier. **
** of an EMM common procedure previously initiated within an **
** EMM procedure currently in progress between the network **
** and the UE with the specified identifier. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _emm_common_data **
** Outputs: None **
** Return: None **
** Others: _emm_common_data **
** **
***************************************************************************/
static void _emm_common_cleanup(unsigned int ueid)
......@@ -469,7 +469,7 @@ static void _emm_common_cleanup(unsigned int ueid)
if (emm_common_data_ctx) {
emm_common_data_ctx->ref_count -= 1;
if (emm_common_data_ctx->ref_count == 0) {
/* Release the callback functions */
/* Release the callback functions */
#if defined(EPC_BUILD)
RB_REMOVE(emm_common_data_map,
&emm_common_data_head.emm_common_data_root,
......@@ -477,7 +477,7 @@ static void _emm_common_cleanup(unsigned int ueid)
#endif
free(emm_common_data_ctx);
emm_common_data_ctx = NULL;
}
}
}
}
#endif // NAS_MME
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source EmmCommon.h
Source EmmCommon.h
Version 0.1
Version 0.1
Date 2013/04/19
Date 2013/04/19
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines callback functions executed within EMM common procedures
by the Non-Access Stratum running at the network side.
Description Defines callback functions executed within EMM common procedures
by the Non-Access Stratum running at the network side.
Following EMM common procedures can always be initiated by the
network whilst a NAS signalling connection exists:
Following EMM common procedures can always be initiated by the
network whilst a NAS signalling connection exists:
GUTI reallocation
authentication
security mode control
identification
EMM information
GUTI reallocation
authentication
security mode control
identification
EMM information
*****************************************************************************/
#ifndef __EMM_COMMON_H__
......@@ -47,9 +47,9 @@ Description Defines callback functions executed within EMM common procedures
* - The EMM common procedure failed or is rejected
* - Lower layer failure occured before the EMM common procedure completion
*/
typedef int (*emm_common_success_callback_t)(void*);
typedef int (*emm_common_reject_callback_t) (void*);
typedef int (*emm_common_failure_callback_t)(void*);
typedef int (*emm_common_success_callback_t)(void *);
typedef int (*emm_common_reject_callback_t) (void *);
typedef int (*emm_common_failure_callback_t)(void *);
/*
* Type of EMM common procedure callback function
......@@ -57,7 +57,7 @@ typedef int (*emm_common_failure_callback_t)(void*);
* EMM common procedure to be executed when the ongoing EMM procedure is
* aborted.
*/
typedef int (*emm_common_abort_callback_t)(void*);
typedef int (*emm_common_abort_callback_t)(void *);
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
......@@ -68,17 +68,17 @@ typedef int (*emm_common_abort_callback_t)(void*);
/****************************************************************************/
int emm_proc_common_initialize(unsigned int ueid,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure,
emm_common_abort_callback_t abort,
void* args);
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure,
emm_common_abort_callback_t abort,
void *args);
int emm_proc_common_success(unsigned int ueid);
int emm_proc_common_reject(unsigned int ueid);
int emm_proc_common_failure(unsigned int ueid);
int emm_proc_common_abort(unsigned int ueid);
void* emm_proc_common_get_args(unsigned int ueid);
void *emm_proc_common_get_args(unsigned int ueid);
#endif /* __EMM_COMMON_H__*/
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source Emmstatus.c
Source Emmstatus.c
Version 0.1
Version 0.1
Date 2013/06/26
Date 2013/06/26
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the EMM status procedure executed by the Non-Access
Stratum.
Description Defines the EMM status procedure executed by the Non-Access
Stratum.
The purpose of the sending of the EMM STATUS message is to
report at any time certain error conditions detected upon
receipt of EMM protocol data. The EMM STATUS message can be
sent by both the MME and the UE.
The purpose of the sending of the EMM STATUS message is to
report at any time certain error conditions detected upon
receipt of EMM protocol data. The EMM STATUS message can be
sent by both the MME and the UE.
*****************************************************************************/
......@@ -47,22 +47,22 @@ Description Defines the EMM status procedure executed by the Non-Access
/****************************************************************************
** **
** Name: emm_proc_status_ind() **
** Name: emm_proc_status_ind() **
** **
** Description: Processes received EMM status message. **
** **
** 3GPP TS 24.301, section 5.7 **
** On receipt of an EMM STATUS message no state transition **
** and no specific action shall be taken. Local actions are **
** possible and are implementation dependent. **
** 3GPP TS 24.301, section 5.7 **
** On receipt of an EMM STATUS message no state transition **
** and no specific action shall be taken. Local actions are **
** possible and are implementation dependent. **
** **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: Received EMM cause code **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: Received EMM cause code **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_status_ind(unsigned int ueid, int emm_cause)
......@@ -72,7 +72,7 @@ int emm_proc_status_ind(unsigned int ueid, int emm_cause)
int rc;
LOG_TRACE(INFO,"EMM-PROC - EMM status procedure requested (cause=%d)",
emm_cause);
emm_cause);
LOG_TRACE(DEBUG, "EMM-PROC - To be implemented");
......@@ -84,17 +84,17 @@ int emm_proc_status_ind(unsigned int ueid, int emm_cause)
/****************************************************************************
** **
** Name: emm_proc_status() **
** Name: emm_proc_status() **
** **
** Description: Initiates EMM status procedure. **
** **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: EMM cause code to be reported **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** emm_cause: EMM cause code to be reported **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_status(unsigned int ueid, int emm_cause)
......@@ -133,7 +133,7 @@ int emm_proc_status(unsigned int ueid, int emm_cause)
#endif
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.status.sctx, sctx,
FALSE, TRUE);
FALSE, TRUE);
rc = emm_sap_send(&emm_sap);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source Identification.c
Source Identification.c
Version 0.1
Version 0.1
Date 2013/04/09
Date 2013/04/09
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the identification EMM procedure executed by the
Non-Access Stratum.
Description Defines the identification EMM procedure executed by the
Non-Access Stratum.
The identification procedure is used by the network to request
a particular UE to provide specific identification parameters
(IMSI, IMEI).
The identification procedure is used by the network to request
a particular UE to provide specific identification parameters
(IMSI, IMEI).
*****************************************************************************/
......@@ -31,8 +31,8 @@ Description Defines the identification EMM procedure executed by the
#include "emm_sap.h"
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
......@@ -43,50 +43,50 @@ Description Defines the identification EMM procedure executed by the
/****************************************************************************/
/* String representation of the requested identity type */
static const char* _emm_identity_type_str[] = {
static const char *_emm_identity_type_str[] = {
"NOT AVAILABLE", "IMSI", "IMEI", "IMEISV", "TMSI"
};
/*
* --------------------------------------------------------------------------
* Internal data handled by the identification procedure in the UE
* Internal data handled by the identification procedure in the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
#endif // NAS_UE
#endif // NAS_UE
/*
* --------------------------------------------------------------------------
* Internal data handled by the identification procedure in the MME
* Internal data handled by the identification procedure in the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/*
* Timer handlers
*/
static void* _identification_t3470_handler(void*);
static void *_identification_t3470_handler(void *);
/*
* Function executed whenever the ongoing EMM procedure that initiated
* the identification procedure is aborted or the maximum value of the
* retransmission timer counter is exceed
*/
static int _identification_abort(void*);
static int _identification_abort(void *);
/*
* Internal data used for identification procedure
*/
typedef struct {
unsigned int ueid; /* UE identifier */
#define IDENTIFICATION_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
emm_proc_identity_type_t type; /* Type of UE identity */
int notify_failure; /* Indicates whether the identification
* procedure failure shall be notified
* to the ongoing EMM procedure */
unsigned int ueid; /* UE identifier */
#define IDENTIFICATION_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
emm_proc_identity_type_t type; /* Type of UE identity */
int notify_failure; /* Indicates whether the identification
* procedure failure shall be notified
* to the ongoing EMM procedure */
} identification_data_t;
static int _identification_request(identification_data_t* data);
static int _identification_request(identification_data_t *data);
#endif // NAS_MME
/****************************************************************************/
......@@ -95,28 +95,28 @@ static int _identification_request(identification_data_t* data);
/*
* --------------------------------------------------------------------------
* Identification procedure executed by the UE
* Identification procedure executed by the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_proc_identification_request() **
** Name: emm_proc_identification_request() **
** **
** Description: Performs the MME requested identification procedure. **
** **
** 3GPP TS 24.301, section 5.4.4.3 **
** Upon receiving the IDENTITY REQUEST message, the UE shall **
** send an IDENTITY RESPONSE message to the network. The **
** IDENTITY RESPONSE message shall contain the identifica- **
** tion parameters as requested by the network. **
** Upon receiving the IDENTITY REQUEST message, the UE shall **
** send an IDENTITY RESPONSE message to the network. The **
** IDENTITY RESPONSE message shall contain the identifica- **
** tion parameters as requested by the network. **
** **
** Inputs: type: Type of the requested identity **
** Others: None **
** Inputs: type: Type of the requested identity **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_identification_request(emm_proc_identity_type_t type)
......@@ -127,48 +127,47 @@ int emm_proc_identification_request(emm_proc_identity_type_t type)
emm_sap_t emm_sap;
LOG_TRACE(INFO, "EMM-PROC - Identification requested type = %s (%d)",
_emm_identity_type_str[type], type);
_emm_identity_type_str[type], type);
/* Setup EMM procedure handler to be executed upon receiving
* lower layer notification */
rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL);
if (rc != RETURNok) {
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
}
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_NOT_AVAILABLE;
switch (type)
{
case EMM_IDENT_TYPE_IMSI:
/* International Mobile Subscriber Identity is requested */
if (_emm_data.imsi) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_IMSI;
emm_sap.u.emm_as.u.security.imsi = _emm_data.imsi;
}
break;
case EMM_IDENT_TYPE_IMEI:
/* International Mobile Equipment Identity is requested */
if (_emm_data.imei) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_IMEI;
emm_sap.u.emm_as.u.security.imei = _emm_data.imei;
}
break;
case EMM_IDENT_TYPE_TMSI:
/* Temporary Mobile Subscriber Identity is requested */
if (_emm_data.guti) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_TMSI;
emm_sap.u.emm_as.u.security.tmsi = _emm_data.guti->m_tmsi;
}
break;
default:
/* Other identities are not available */
break;
switch (type) {
case EMM_IDENT_TYPE_IMSI:
/* International Mobile Subscriber Identity is requested */
if (_emm_data.imsi) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_IMSI;
emm_sap.u.emm_as.u.security.imsi = _emm_data.imsi;
}
break;
case EMM_IDENT_TYPE_IMEI:
/* International Mobile Equipment Identity is requested */
if (_emm_data.imei) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_IMEI;
emm_sap.u.emm_as.u.security.imei = _emm_data.imei;
}
break;
case EMM_IDENT_TYPE_TMSI:
/* Temporary Mobile Subscriber Identity is requested */
if (_emm_data.guti) {
emm_sap.u.emm_as.u.security.identType = EMM_IDENT_TYPE_TMSI;
emm_sap.u.emm_as.u.security.tmsi = _emm_data.guti->m_tmsi;
}
break;
default:
/* Other identities are not available */
break;
}
/*
......@@ -181,7 +180,7 @@ int emm_proc_identification_request(emm_proc_identity_type_t type)
emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_IDENT;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
_emm_data.security, FALSE, TRUE);
_emm_data.security, FALSE, TRUE);
rc = emm_sap_send(&emm_sap);
LOG_FUNC_RETURN (rc);
......@@ -190,86 +189,86 @@ int emm_proc_identification_request(emm_proc_identity_type_t type)
/*
* --------------------------------------------------------------------------
* Identification procedure executed by the MME
* Identification procedure executed by the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/****************************************************************************
** **
** Name: emm_proc_identification() **
** Name: emm_proc_identification() **
** **
** Description: Initiates an identification procedure. **
** **
** 3GPP TS 24.301, section 5.4.4.2 **
** The network initiates the identification procedure by **
** sending an IDENTITY REQUEST message to the UE and star- **
** ting the timer T3470. The IDENTITY REQUEST message speci- **
** fies the requested identification parameters in the Iden- **
** tity type information element. **
** **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested identity **
** success: Callback function executed when the identi-**
** fication procedure successfully completes **
** reject: Callback function executed when the identi-**
** fication procedure fails or is rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the identifi- **
** cation procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** The network initiates the identification procedure by **
** sending an IDENTITY REQUEST message to the UE and star- **
** ting the timer T3470. The IDENTITY REQUEST message speci- **
** fies the requested identification parameters in the Iden- **
** tity type information element. **
** **
** Inputs: ueid: UE lower layer identifier **
** type: Type of the requested identity **
** success: Callback function executed when the identi-**
** fication procedure successfully completes **
** reject: Callback function executed when the identi-**
** fication procedure fails or is rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the identifi- **
** cation procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** **
***************************************************************************/
int emm_proc_identification(unsigned int ueid,
emm_data_context_t *emm_ctx,
emm_proc_identity_type_t type,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
{
LOG_FUNC_IN;
int rc = RETURNerror;
LOG_TRACE(INFO, "EMM-PROC - Initiate identification type = %s (%d)",
_emm_identity_type_str[type], type);
_emm_identity_type_str[type], type);
/* Allocate parameters of the retransmission timer callback */
identification_data_t* data =
(identification_data_t*)malloc(sizeof(identification_data_t));
identification_data_t *data =
(identification_data_t *)malloc(sizeof(identification_data_t));
if (data != NULL) {
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_identification_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
free(data);
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the type of the requested identity */
data->type = type;
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send identity request message to the UE */
rc = _identification_request(data);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_identification_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
free(data);
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the type of the requested identity */
data->type = type;
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send identity request message to the UE */
rc = _identification_request(data);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.ctx = emm_ctx;
rc = emm_sap_send(&emm_sap);
}
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN (rc);
......@@ -277,33 +276,33 @@ int emm_proc_identification(unsigned int ueid,
/****************************************************************************
** **
** Name: emm_proc_identification_complete() **
** Name: emm_proc_identification_complete() **
** **
** Description: Performs the identification completion procedure executed **
** by the network. **
** by the network. **
** **
** 3GPP TS 24.301, section 5.4.4.4 **
** Upon receiving the IDENTITY RESPONSE message, the MME **
** shall stop timer T3470. **
** Upon receiving the IDENTITY RESPONSE message, the MME **
** shall stop timer T3470. **
** **
** Inputs: ueid: UE lower layer identifier **
** imsi: The IMSI received from the UE **
** imei: The IMEI received from the UE **
** tmsi: The TMSI received from the UE **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** imsi: The IMSI received from the UE **
** imei: The IMEI received from the UE **
** tmsi: The TMSI received from the UE **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, T3470 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data, T3470 **
** **
***************************************************************************/
int emm_proc_identification_complete(unsigned int ueid, const imsi_t* imsi,
const imei_t* imei, UInt32_t* tmsi)
int emm_proc_identification_complete(unsigned int ueid, const imsi_t *imsi,
const imei_t *imei, UInt32_t *tmsi)
{
int rc = RETURNerror;
emm_sap_t emm_sap;
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
LOG_FUNC_IN;
......@@ -314,9 +313,11 @@ int emm_proc_identification_complete(unsigned int ueid, const imsi_t* imsi,
T3470.id = nas_timer_stop(T3470.id);
/* Release retransmission timer paramaters */
identification_data_t* data =
(identification_data_t*)(emm_proc_common_get_args(ueid));
if (data) free(data);
identification_data_t *data =
(identification_data_t *)(emm_proc_common_get_args(ueid));
if (data) {
free(data);
}
/* Get the UE context */
#if defined(EPC_BUILD)
......@@ -330,49 +331,46 @@ int emm_proc_identification_complete(unsigned int ueid, const imsi_t* imsi,
#endif
if (emm_ctx) {
if (imsi) {
/* Update the IMSI */
if (emm_ctx->imsi == NULL) {
emm_ctx->imsi = (imsi_t*)malloc(sizeof(imsi_t));
}
if (emm_ctx->imsi) {
memcpy(emm_ctx->imsi, imsi, sizeof(imsi_t));
}
}
else if (imei) {
/* Update the IMEI */
if (emm_ctx->imei == NULL) {
emm_ctx->imei = (imei_t*)malloc(sizeof(imei_t));
}
if (emm_ctx->imei) {
memcpy(emm_ctx->imei, imei, sizeof(imei_t));
}
}
else if (tmsi) {
/* Update the GUTI */
if (emm_ctx->guti == NULL) {
emm_ctx->guti = (GUTI_t*)malloc(sizeof(GUTI_t));
}
if (emm_ctx->guti) {
memcpy(&emm_ctx->guti->gummei,
&_emm_data.conf.gummei, sizeof(gummei_t));
emm_ctx->guti->m_tmsi = *tmsi;
}
}
/*
* Notify EMM that the identification procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
}
else {
LOG_TRACE(ERROR, "EMM-PROC - No EMM context exists");
/*
* Notify EMM that the identification procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
if (imsi) {
/* Update the IMSI */
if (emm_ctx->imsi == NULL) {
emm_ctx->imsi = (imsi_t *)malloc(sizeof(imsi_t));
}
if (emm_ctx->imsi) {
memcpy(emm_ctx->imsi, imsi, sizeof(imsi_t));
}
} else if (imei) {
/* Update the IMEI */
if (emm_ctx->imei == NULL) {
emm_ctx->imei = (imei_t *)malloc(sizeof(imei_t));
}
if (emm_ctx->imei) {
memcpy(emm_ctx->imei, imei, sizeof(imei_t));
}
} else if (tmsi) {
/* Update the GUTI */
if (emm_ctx->guti == NULL) {
emm_ctx->guti = (GUTI_t *)malloc(sizeof(GUTI_t));
}
if (emm_ctx->guti) {
memcpy(&emm_ctx->guti->gummei,
&_emm_data.conf.gummei, sizeof(gummei_t));
emm_ctx->guti->m_tmsi = *tmsi;
}
}
/*
* Notify EMM that the identification procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
} else {
LOG_TRACE(ERROR, "EMM-PROC - No EMM context exists");
/*
* Notify EMM that the identification procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
}
rc = emm_sap_send(&emm_sap);
......@@ -389,53 +387,52 @@ int emm_proc_identification_complete(unsigned int ueid, const imsi_t* imsi,
#ifdef NAS_MME
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _identification_t3470_handler() **
** Name: _identification_t3470_handler() **
** **
** Description: T3470 timeout handler **
** Upon T3470 timer expiration, the identification request **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** identification procedure and any ongoing EMM procedure. **
** Upon T3470 timer expiration, the identification request **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** identification procedure and any ongoing EMM procedure. **
** **
** 3GPP TS 24.301, section 5.4.4.6, case b **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
static void* _identification_t3470_handler(void* args)
static void *_identification_t3470_handler(void *args)
{
LOG_FUNC_IN;
int rc;
identification_data_t* data = (identification_data_t*)(args);
identification_data_t *data = (identification_data_t *)(args);
/* Increment the retransmission counter */
data->retransmission_count += 1;
LOG_TRACE(WARNING, "EMM-PROC - T3470 timer expired, retransmission "
"counter = %d", data->retransmission_count);
"counter = %d", data->retransmission_count);
if (data->retransmission_count < IDENTIFICATION_COUNTER_MAX) {
/* Send identity request message to the UE */
rc = _identification_request(data);
}
else {
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the identification procedure */
rc = _identification_abort(data);
/* Send identity request message to the UE */
rc = _identification_request(data);
} else {
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the identification procedure */
rc = _identification_abort(data);
}
LOG_FUNC_RETURN (NULL);
......@@ -443,25 +440,25 @@ static void* _identification_t3470_handler(void* args)
/*
* --------------------------------------------------------------------------
* MME specific local functions
* MME specific local functions
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _identification_request() **
** Name: _identification_request() **
** **
** Description: Sends IDENTITY REQUEST message and start timer T3470. **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: T3470 **
** Outputs: None **
** Return: None **
** Others: T3470 **
** **
***************************************************************************/
int _identification_request(identification_data_t* data)
int _identification_request(identification_data_t *data)
{
emm_sap_t emm_sap;
int rc;
......@@ -495,16 +492,16 @@ int _identification_request(identification_data_t* data)
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
if (T3470.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3470 timer */
T3470.id = nas_timer_restart(T3470.id);
} else {
/* Start T3470 timer */
T3470.id = nas_timer_start(T3470.sec, _identification_t3470_handler,
data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3470 (%d) expires in %ld seconds",
T3470.id, T3470.sec);
if (T3470.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3470 timer */
T3470.id = nas_timer_restart(T3470.id);
} else {
/* Start T3470 timer */
T3470.id = nas_timer_start(T3470.sec, _identification_t3470_handler,
data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3470 (%d) expires in %ld seconds",
T3470.id, T3470.sec);
}
LOG_FUNC_RETURN (rc);
......@@ -512,53 +509,52 @@ int _identification_request(identification_data_t* data)
/****************************************************************************
** **
** Name: _identification_abort() **
** Name: _identification_abort() **
** **
** Description: Aborts the identification procedure currently in progress **
** **
** Inputs: args: Identification data to be released **
** Others: None **
** Inputs: args: Identification data to be released **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: T3470 **
** Outputs: None **
** Return: None **
** Others: T3470 **
** **
***************************************************************************/
static int _identification_abort(void* args)
static int _identification_abort(void *args)
{
LOG_FUNC_IN;
int rc = RETURNerror;
identification_data_t* data = (identification_data_t*)(args);
if (data)
{
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort identification procedure "
"(ueid=%u)", ueid);
/* Stop timer T3470 */
if (T3470.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3470 (%d)", T3470.id);
T3470.id = nas_timer_stop(T3470.id);
}
/* Release retransmission timer paramaters */
free(data);
/*
* Notify EMM that the identification procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
identification_data_t *data = (identification_data_t *)(args);
if (data) {
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort identification procedure "
"(ueid=%u)", ueid);
/* Stop timer T3470 */
if (T3470.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3470 (%d)", T3470.id);
T3470.id = nas_timer_stop(T3470.id);
}
/* Release retransmission timer paramaters */
free(data);
/*
* Notify EMM that the identification procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
}
LOG_FUNC_RETURN(rc);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source IdleMode.c
Source IdleMode.c
Version 0.1
Version 0.1
Date 2012/10/18
Date 2012/10/18
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines EMM procedures executed by the Non-Access Stratum
when the UE is in idle mode.
Description Defines EMM procedures executed by the Non-Access Stratum
when the UE is in idle mode.
When a UE is switched on, a Public Land Mobile Network is
selected and the UE searches for a suitable cell of this PLMN
to camp on. The UE will, if necessary, register its presence
in the registration area of the chosen cell and as outcome of
a successful Location Registration the selected PLMN becomes
the registered PLMN.
When a UE is switched on, a Public Land Mobile Network is
selected and the UE searches for a suitable cell of this PLMN
to camp on. The UE will, if necessary, register its presence
in the registration area of the chosen cell and as outcome of
a successful Location Registration the selected PLMN becomes
the registered PLMN.
If the UE loses coverage of the registered PLMN, either a new
PLMN is selected automatically (automatic mode), or an indi-
cation of which PLMNs are available is given to the user, so
that a manual selection can be made (manual mode).
If the UE loses coverage of the registered PLMN, either a new
PLMN is selected automatically (automatic mode), or an indi-
cation of which PLMNs are available is given to the user, so
that a manual selection can be made (manual mode).
If the UE is unable to find a suitable cell to camp on, or
the USIM is not inserted, or if the location registration
failed under certain conditions, it attempts to camp on a
cell irrespective of the PLMN identity, and enters a "limited
service" state in which it can only attempt to make emergency
calls.
If the UE is unable to find a suitable cell to camp on, or
the USIM is not inserted, or if the location registration
failed under certain conditions, it attempts to camp on a
cell irrespective of the PLMN identity, and enters a "limited
service" state in which it can only attempt to make emergency
calls.
*****************************************************************************/
......@@ -60,8 +60,8 @@ Description Defines EMM procedures executed by the Non-Access Stratum
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
static int _IdleMode_plmn_str(char* plmn_str, const plmn_t* plmn);
static int _IldlMode_get_opnn_id(const plmn_t* plmn);
static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn);
static int _IldlMode_get_opnn_id(const plmn_t *plmn);
static int _IdleMode_get_suitable_cell(int index);
/*
......@@ -92,23 +92,23 @@ static int _IdleMode_get_suitable_cell(int index);
*/
static struct {
int n_plmns;
#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX + \
EMM_DATA_OPLMN_MAX + 2)
plmn_t* plmn[EMM_PLMN_LIST_SIZE];
int index; /* Index of the PLMN for which selection is ongoing */
int hplmn; /* Index of the home PLMN or the highest priority
* equivalent home PLMN */
int fplmn; /* Index of the first forbidden PLMN */
int splmn; /* Index of the currently selected PLMN */
int rplmn; /* Index of the currently registered PLMN */
#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX + \
EMM_DATA_OPLMN_MAX + 2)
plmn_t *plmn[EMM_PLMN_LIST_SIZE];
int index; /* Index of the PLMN for which selection is ongoing */
int hplmn; /* Index of the home PLMN or the highest priority
* equivalent home PLMN */
int fplmn; /* Index of the first forbidden PLMN */
int splmn; /* Index of the currently selected PLMN */
int rplmn; /* Index of the currently registered PLMN */
struct plmn_param_t {
char fullname[NET_FORMAT_LONG_SIZE+1]; /* PLMN full identifier */
char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier */
char num[NET_FORMAT_NUM_SIZE+1]; /* PLMN numeric identifier */
int stat; /* Indication of the PLMN availability */
int tac; /* Location/Tracking Area Code */
int ci; /* Serving cell identifier */
int rat; /* Radio Access Technology supported by the serving cell */
char fullname[NET_FORMAT_LONG_SIZE+1]; /* PLMN full identifier */
char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier */
char num[NET_FORMAT_NUM_SIZE+1]; /* PLMN numeric identifier */
int stat; /* Indication of the PLMN availability */
int tac; /* Location/Tracking Area Code */
int ci; /* Serving cell identifier */
int rat; /* Radio Access Technology supported by the serving cell */
} param[EMM_PLMN_LIST_SIZE];
} _emm_plmn_list;
......@@ -121,18 +121,18 @@ static IdleMode_callback_t _emm_indication_notify;
/****************************************************************************
** **
** Name: IdleMode_initialize() **
** Name: IdleMode_initialize() **
** **
** Description: Initializes EMM internal data used when the UE operates **
** in idle mode **
** in idle mode **
** **
** Inputs: cb: The function to executed whenever a net- **
** work indication is received **
** Others: None **
** Inputs: cb: The function to executed whenever a net- **
** work indication is received **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list, _emm_indication_notify **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list, _emm_indication_notify **
** **
***************************************************************************/
void IdleMode_initialize(IdleMode_callback_t cb)
......@@ -160,17 +160,17 @@ void IdleMode_initialize(IdleMode_callback_t cb)
/****************************************************************************
** **
** Name: IdleMode_get_nb_plmns() **
** Name: IdleMode_get_nb_plmns() **
** **
** Description: Get the number of available PLMNs in the ordered list. **
** **
** Inputs: None **
** Others: _emm_plmn_list **
** Inputs: None **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The number of PLMNs in the ordered list of **
** available PLMNs **
** Others: None **
** Outputs: None **
** Return: The number of PLMNs in the ordered list of **
** available PLMNs **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_nb_plmns(void)
......@@ -180,18 +180,18 @@ int IdleMode_get_nb_plmns(void)
/****************************************************************************
** **
** Name: IdleMode_get_hplmn_index() **
** Name: IdleMode_get_hplmn_index() **
** **
** Description: Get the index of the Home PLMN or the highest priority **
** Equivalent HPLMN in the ordered list of available PLMNs. **
** Equivalent HPLMN in the ordered list of available PLMNs. **
** **
** Inputs: None **
** Others: _emm_plmn_list **
** Inputs: None **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the HPLMN or the first EHPLMN **
** in the list **
** Others: None **
** Outputs: None **
** Return: The index of the HPLMN or the first EHPLMN **
** in the list **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_hplmn_index(void)
......@@ -201,18 +201,18 @@ int IdleMode_get_hplmn_index(void)
/****************************************************************************
** **
** Name: IdleMode_get_rplmn_index() **
** Name: IdleMode_get_rplmn_index() **
** **
** Description: Get the index of the registered PLMN in the ordered list **
** of available PLMNs. **
** of available PLMNs. **
** **
** Inputs: None **
** Others: _emm_plmn_list **
** Inputs: None **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the registered PLMN in the **
** list **
** Others: None **
** Outputs: None **
** Return: The index of the registered PLMN in the **
** list **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_rplmn_index(void)
......@@ -222,17 +222,17 @@ int IdleMode_get_rplmn_index(void)
/****************************************************************************
** **
** Name: IdleMode_get_splmn_index() **
** Name: IdleMode_get_splmn_index() **
** **
** Description: Get the index of the selected PLMN in the ordered list of **
** available PLMNs. **
** available PLMNs. **
** **
** Inputs: None **
** Others: _emm_plmn_list **
** Inputs: None **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the selected PLMN in the list **
** Others: None **
** Outputs: None **
** Return: The index of the selected PLMN in the list **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_splmn_index(void)
......@@ -242,17 +242,17 @@ int IdleMode_get_splmn_index(void)
/****************************************************************************
** **
** Name: IdleMode_update_plmn_list() **
** Name: IdleMode_update_plmn_list() **
** **
** Description: Updates the string representation of the list of opera- **
** tors present in the network **
** tors present in the network **
** **
** Inputs: i: Index of the first operator to update **
** Others: _emm_plmn_list **
** Inputs: i: Index of the first operator to update **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The size of the list in bytes **
** Others: _emm_data.plist **
** Outputs: None **
** Return: The size of the list in bytes **
** Others: _emm_data.plist **
** **
***************************************************************************/
int IdleMode_update_plmn_list(int i)
......@@ -260,24 +260,23 @@ int IdleMode_update_plmn_list(int i)
int offset = 0;
int n = 1;
while ( (i < _emm_plmn_list.n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) )
{
struct plmn_param_t* plmn = &(_emm_plmn_list.param[i++]);
if (n++ > 1) {
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ",");
}
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, "(%d,%s,%s,%s",
plmn->stat, plmn->fullname,
plmn->shortname, plmn->num);
if (plmn->rat != NET_ACCESS_UNAVAILABLE) {
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ",%d",
plmn->rat);
}
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ")");
while ( (i < _emm_plmn_list.n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) ) {
struct plmn_param_t *plmn = &(_emm_plmn_list.param[i++]);
if (n++ > 1) {
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ",");
}
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, "(%d,%s,%s,%s",
plmn->stat, plmn->fullname,
plmn->shortname, plmn->num);
if (plmn->rat != NET_ACCESS_UNAVAILABLE) {
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ",%d",
plmn->rat);
}
offset += snprintf(_emm_data.plist.buffer + offset,
EMM_DATA_BUFFER_SIZE - offset, ")");
}
return (offset);
......@@ -285,195 +284,194 @@ int IdleMode_update_plmn_list(int i)
/****************************************************************************
** **
** Name: IdleMode_get_plmn_fullname() **
** Name: IdleMode_get_plmn_fullname() **
** **
** Description: Get the full name of the PLMN at the given index in the **
** ordered list of available PLMNs. **
** ordered list of available PLMNs. **
** **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the full name of the PLMN **
** Others: None **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the full name of the PLMN **
** Others: None **
** **
***************************************************************************/
const char* IdleMode_get_plmn_fullname(const plmn_t* plmn, int index, size_t* len)
const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index,
size_t *len)
{
if (index < _emm_plmn_list.n_plmns) {
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].fullname);
return _emm_plmn_list.param[index].fullname;
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].fullname);
return _emm_plmn_list.param[index].fullname;
}
return NULL;
}
/****************************************************************************
** **
** Name: IdleMode_get_plmn_shortname() **
** Name: IdleMode_get_plmn_shortname() **
** **
** Description: Get the short name of the PLMN at the given index in the **
** ordered list of available PLMNs. **
** ordered list of available PLMNs. **
** **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the short name of the PLMN **
** Others: None **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the short name of the PLMN **
** Others: None **
** **
***************************************************************************/
const char* IdleMode_get_plmn_shortname(const plmn_t* plmn, int index, size_t* len)
const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index,
size_t *len)
{
if (index < _emm_plmn_list.n_plmns) {
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].shortname);
return _emm_plmn_list.param[index].shortname;
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].shortname);
return _emm_plmn_list.param[index].shortname;
}
return NULL;
}
/****************************************************************************
** **
** Name: IdleMode_get_plmn_id() **
** Name: IdleMode_get_plmn_id() **
** **
** Description: Get the numeric identifier of the PLMN at the given index **
** in the ordered list of available PLMNs. **
** in the ordered list of available PLMNs. **
** **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** Inputs: plmn: The PLMN of which the name is queried **
** index: The index of the PLMN in the ordered list **
** of available PLMNs **
** Others: _emm_plmn_list **
** **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the numeric identifier of the **
** PLMN **
** Others: None **
** Outputs: size: The length of the PLMN's name **
** Return: A pointer to the numeric identifier of the **
** PLMN **
** Others: None **
** **
***************************************************************************/
const char* IdleMode_get_plmn_id(const plmn_t* plmn, int index, size_t* len)
const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len)
{
if (index < _emm_plmn_list.n_plmns) {
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].num);
return _emm_plmn_list.param[index].num;
assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
*len = strlen(_emm_plmn_list.param[index].num);
return _emm_plmn_list.param[index].num;
}
return NULL;
}
/****************************************************************************
** **
** Name: IdleMode_get_plmn_fullname_index() **
** Name: IdleMode_get_plmn_fullname_index() **
** **
** Description: Search the list of available PLMNs for the index of the **
** PLMN identifier given by the specified fullname **
** PLMN identifier given by the specified fullname **
** **
** Inputs: plmn: The full name of the PLMN **
** Others: _emm_plmn_list **
** Inputs: plmn: The full name of the PLMN **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_plmn_fullname_index(const char* plmn)
int IdleMode_get_plmn_fullname_index(const char *plmn)
{
/* Get the index of the PLMN identifier with specified full name */
for (int index = 0; index < _emm_plmn_list.n_plmns; index++)
{
if ( strncmp(plmn, _emm_plmn_list.param[index].fullname,
NET_FORMAT_LONG_SIZE) != 0 ) {
continue;
}
return (index);
for (int index = 0; index < _emm_plmn_list.n_plmns; index++) {
if ( strncmp(plmn, _emm_plmn_list.param[index].fullname,
NET_FORMAT_LONG_SIZE) != 0 ) {
continue;
}
return (index);
}
return (-1);
}
/****************************************************************************
** **
** Name: IdleMode_get_plmn_shortname_index() **
** Name: IdleMode_get_plmn_shortname_index() **
** **
** Description: Search the list of available PLMNs for the index of the **
** PLMN identifier given by the specified shortname **
** PLMN identifier given by the specified shortname **
** **
** Inputs: plmn: The short name of the PLMN **
** Others: _emm_plmn_list **
** Inputs: plmn: The short name of the PLMN **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_plmn_shortname_index(const char* plmn)
int IdleMode_get_plmn_shortname_index(const char *plmn)
{
/* Get the index of the PLMN identifier with specified short name */
for (int index = 0; index < _emm_plmn_list.n_plmns; index++)
{
if ( !strncmp(plmn, _emm_plmn_list.param[index].shortname,
NET_FORMAT_SHORT_SIZE) ) {
continue;
}
return (index);
for (int index = 0; index < _emm_plmn_list.n_plmns; index++) {
if ( !strncmp(plmn, _emm_plmn_list.param[index].shortname,
NET_FORMAT_SHORT_SIZE) ) {
continue;
}
return (index);
}
return (-1);
}
/****************************************************************************
** **
** Name: IdleMode_get_plmn_id_index() **
** Name: IdleMode_get_plmn_id_index() **
** **
** Description: Search the list of available PLMNs for the index of the **
** PLMN identifier given by the specified numeric identifier **
** PLMN identifier given by the specified numeric identifier **
** **
** Inputs: plmn: The numeric identifier of the PLMN **
** Others: _emm_plmn_list **
** Inputs: plmn: The numeric identifier of the PLMN **
** Others: _emm_plmn_list **
** **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** Outputs: None **
** Return: The index of the PLMN, if found in the **
** list of available PLMNs; -1 otherwise. **
** Others: None **
** **
***************************************************************************/
int IdleMode_get_plmn_id_index(const char* plmn)
int IdleMode_get_plmn_id_index(const char *plmn)
{
/* Get the index of the PLMN identifier with specified numeric identifier */
for (int index = 0; index < _emm_plmn_list.n_plmns; index++)
{
if ( !strncmp(plmn, _emm_plmn_list.param[index].num,
NET_FORMAT_LONG_SIZE) ) {
continue;
}
return (index);
for (int index = 0; index < _emm_plmn_list.n_plmns; index++) {
if ( !strncmp(plmn, _emm_plmn_list.param[index].num,
NET_FORMAT_LONG_SIZE) ) {
continue;
}
return (index);
}
return (-1);
}
/*
*---------------------------------------------------------------------------
* Idle mode EMM procedures
* Idle mode EMM procedures
*---------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: emm_proc_initialize() **
** Name: emm_proc_initialize() **
** **
** Description: Initialize the ordered list of available PLMNs candidate **
** to PLMN selection procedure. **
** to PLMN selection procedure. **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_plmn_list **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_plmn_list **
** **
***************************************************************************/
int emm_proc_initialize(void)
......@@ -484,89 +482,85 @@ int emm_proc_initialize(void)
int rc;
if (!_emm_data.usim_is_valid) {
/* The USIM application is not present or not valid */
LOG_TRACE(WARNING, "EMM-IDLE - USIM is not valid");
emm_sap.primitive = EMMREG_NO_IMSI;
}
else
{
/* The highest priority is given to either the "equivalent PLMNs"
* if available, or the last registered PLMN */
if (_emm_data.nvdata.eplmn.n_plmns > 0) {
for (int i=0; i < _emm_data.nvdata.eplmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.nvdata.eplmn.plmn[i];
}
}
else if ( PLMN_IS_VALID(_emm_data.nvdata.rplmn) ) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.nvdata.rplmn;
}
/* Update the index of the HPLMN or EHPLM of highest priority.
* When switched on, the UE will try to automatically register
* to each previous PLMN within the ordered list of available
* PLMNs regardless of the network selection mode of operation */
_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns;
/* Add the highest priority PLMN in the list of "equivalent HPLMNs"
if present and not empty, or the HPLMN derived from the IMSI */
if (_emm_data.ehplmn.n_plmns > 0) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.ehplmn.plmn[0];
}
else {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = &_emm_data.hplmn;
}
/* Each PLMN/access technology combination in the "User
* Controlled PLMN Selector with Access Technology" */
for (int i=0; i < _emm_data.plmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.plmn.plmn[i];
}
/* Each PLMN/access technology combination in the "Operator
* Controlled PLMN Selector with Access Technology" */
for (int i=0; i < _emm_data.oplmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.oplmn.plmn[i];
}
/* Other PLMN/access technology combinations with received
* high quality signal in random order */
/* Other PLMN/access technology combinations in order of
* decreasing signal quality */
/* TODO: Schedule periodic network selection attemps (hpplmn timer) */
/* Initialize the PLMNs' parameters */
for (int i=0; i < _emm_plmn_list.n_plmns; i++) {
struct plmn_param_t* plmn = &(_emm_plmn_list.param[i]);
int id = _IldlMode_get_opnn_id(_emm_plmn_list.plmn[i]);
if (id < 0) {
plmn->fullname[0] = '\0';
plmn->shortname[0] = '\0';
} else {
strncpy(plmn->fullname, _emm_data.opnn[id].fullname,
NET_FORMAT_LONG_SIZE);
strncpy(plmn->shortname, _emm_data.opnn[id].shortname,
NET_FORMAT_SHORT_SIZE);
}
(void)_IdleMode_plmn_str(plmn->num, _emm_plmn_list.plmn[i]);
plmn->stat = NET_OPER_UNKNOWN;
plmn->tac = 0;
plmn->ci = 0;
plmn->rat = NET_ACCESS_UNAVAILABLE;
}
LOG_TRACE(INFO, "EMM-IDLE - %d PLMNs available for network selection",
_emm_plmn_list.n_plmns);
/* Notify EMM that PLMN selection procedure has to be executed */
emm_sap.primitive = EMMREG_REGISTER_REQ;
emm_sap.u.emm_reg.u.regist.index = 0;
/* The USIM application is not present or not valid */
LOG_TRACE(WARNING, "EMM-IDLE - USIM is not valid");
emm_sap.primitive = EMMREG_NO_IMSI;
} else {
/* The highest priority is given to either the "equivalent PLMNs"
* if available, or the last registered PLMN */
if (_emm_data.nvdata.eplmn.n_plmns > 0) {
for (int i=0; i < _emm_data.nvdata.eplmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.nvdata.eplmn.plmn[i];
}
} else if ( PLMN_IS_VALID(_emm_data.nvdata.rplmn) ) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.nvdata.rplmn;
}
/* Update the index of the HPLMN or EHPLM of highest priority.
* When switched on, the UE will try to automatically register
* to each previous PLMN within the ordered list of available
* PLMNs regardless of the network selection mode of operation */
_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns;
/* Add the highest priority PLMN in the list of "equivalent HPLMNs"
if present and not empty, or the HPLMN derived from the IMSI */
if (_emm_data.ehplmn.n_plmns > 0) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.ehplmn.plmn[0];
} else {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = &_emm_data.hplmn;
}
/* Each PLMN/access technology combination in the "User
* Controlled PLMN Selector with Access Technology" */
for (int i=0; i < _emm_data.plmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.plmn.plmn[i];
}
/* Each PLMN/access technology combination in the "Operator
* Controlled PLMN Selector with Access Technology" */
for (int i=0; i < _emm_data.oplmn.n_plmns; i++) {
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
&_emm_data.oplmn.plmn[i];
}
/* Other PLMN/access technology combinations with received
* high quality signal in random order */
/* Other PLMN/access technology combinations in order of
* decreasing signal quality */
/* TODO: Schedule periodic network selection attemps (hpplmn timer) */
/* Initialize the PLMNs' parameters */
for (int i=0; i < _emm_plmn_list.n_plmns; i++) {
struct plmn_param_t *plmn = &(_emm_plmn_list.param[i]);
int id = _IldlMode_get_opnn_id(_emm_plmn_list.plmn[i]);
if (id < 0) {
plmn->fullname[0] = '\0';
plmn->shortname[0] = '\0';
} else {
strncpy(plmn->fullname, _emm_data.opnn[id].fullname,
NET_FORMAT_LONG_SIZE);
strncpy(plmn->shortname, _emm_data.opnn[id].shortname,
NET_FORMAT_SHORT_SIZE);
}
(void)_IdleMode_plmn_str(plmn->num, _emm_plmn_list.plmn[i]);
plmn->stat = NET_OPER_UNKNOWN;
plmn->tac = 0;
plmn->ci = 0;
plmn->rat = NET_ACCESS_UNAVAILABLE;
}
LOG_TRACE(INFO, "EMM-IDLE - %d PLMNs available for network selection",
_emm_plmn_list.n_plmns);
/* Notify EMM that PLMN selection procedure has to be executed */
emm_sap.primitive = EMMREG_REGISTER_REQ;
emm_sap.u.emm_reg.u.regist.index = 0;
}
rc = emm_sap_send(&emm_sap);
......@@ -578,26 +572,26 @@ int emm_proc_initialize(void)
/****************************************************************************
** **
** Name: emm_proc_plmn_selection() **
** Name: emm_proc_plmn_selection() **
** **
** Description: Performs the network selection procedure when the UE is **
** swicthed on. **
** swicthed on. **
** **
** The MS shall select the registered PLMN or equivalent **
** PLMN (if it is available) using all access technologies **
** that the MS is capable. **
** If there is no registered PLMN, or if registration is **
** not possible due to the PLMN being unavailable or regis- **
** tration failure, the MS performs the automatic or the ma- **
** nual procedure depending on its PLMN selection operating **
** mode. **
** The MS shall select the registered PLMN or equivalent **
** PLMN (if it is available) using all access technologies **
** that the MS is capable. **
** If there is no registered PLMN, or if registration is **
** not possible due to the PLMN being unavailable or regis- **
** tration failure, the MS performs the automatic or the ma- **
** nual procedure depending on its PLMN selection operating **
** mode. **
** **
** Inputs: None **
** Others: _emm_plmn_list, _emm_data **
** Inputs: None **
** Others: _emm_plmn_list, _emm_data **
** **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list.index **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list.index **
** **
***************************************************************************/
int emm_proc_plmn_selection(int index)
......@@ -607,45 +601,44 @@ int emm_proc_plmn_selection(int index)
int rc = RETURNok;
if (_emm_data.plmn_mode != EMM_DATA_PLMN_AUTO) {
/*
* Manual or manual/automatic mode of operation
* --------------------------------------------
*/
if (index >= _emm_plmn_list.hplmn) {
/*
* Selection of the last registered or equivalent PLMNs failed
*/
if (_emm_data.plmn_index < 0) {
/*
* The user did not select any PLMN yet; display the ordered
* list of available PLMNs to the user
*/
index = -1;
rc = emm_proc_network_notify(_emm_plmn_list.hplmn);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify "
"network list update");
}
}
else {
/*
* Try to register to the PLMN manually selected by the user
*/
index = _emm_data.plmn_index;
}
}
/*
* Manual or manual/automatic mode of operation
* --------------------------------------------
*/
if (index >= _emm_plmn_list.hplmn) {
/*
* Selection of the last registered or equivalent PLMNs failed
*/
if (_emm_data.plmn_index < 0) {
/*
* The user did not select any PLMN yet; display the ordered
* list of available PLMNs to the user
*/
index = -1;
rc = emm_proc_network_notify(_emm_plmn_list.hplmn);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify "
"network list update");
}
} else {
/*
* Try to register to the PLMN manually selected by the user
*/
index = _emm_data.plmn_index;
}
}
}
if ( !(index < 0) ) {
/*
* Search for a suitable cell of the currently selected PLMN:
* It can be the last registered or one of the equivalent PLMNs
* if available, or the PLMN selected by the user in manual mode,
* or any other PLMN in the ordered list of available PLMNs in
* automatic mode.
*/
_emm_plmn_list.index = index;
rc = _IdleMode_get_suitable_cell(index);
/*
* Search for a suitable cell of the currently selected PLMN:
* It can be the last registered or one of the equivalent PLMNs
* if available, or the PLMN selected by the user in manual mode,
* or any other PLMN in the ordered list of available PLMNs in
* automatic mode.
*/
_emm_plmn_list.index = index;
rc = _IdleMode_get_suitable_cell(index);
}
LOG_FUNC_RETURN (rc);
......@@ -653,38 +646,38 @@ int emm_proc_plmn_selection(int index)
/****************************************************************************
** **
** Name: emm_proc_plmn_end() **
** Name: emm_proc_plmn_end() **
** **
** Description: Completes the network selection procedure or triggers a **
** new one until a suitable or acceptable cell of the chosen **
** PLMN is found. **
** **
** If a suitable cell of the selected PLMN has been found, **
** that cell is chosen to camp on and provide available ser- **
** vices, and tunes to its control channel. **
** The MS will then register its presence in the registra- **
** tion area of the chosen cell, if it is capable of servi- **
** ces which require registration. As outcome of a success- **
** ful Location Registration the selected PLMN becomes the **
** registered PLMN. **
** new one until a suitable or acceptable cell of the chosen **
** PLMN is found. **
** **
** If a suitable cell of the selected PLMN has been found, **
** that cell is chosen to camp on and provide available ser- **
** vices, and tunes to its control channel. **
** The MS will then register its presence in the registra- **
** tion area of the chosen cell, if it is capable of servi- **
** ces which require registration. As outcome of a success- **
** ful Location Registration the selected PLMN becomes the **
** registered PLMN. **
** **
** When no suitable cell can be found, the MS is unable to **
** obtain normal service from a PLMN. Then the MS attempts **
** to camp on an acceptable cell, irrespective of its PLMN **
** identity, so that only emergency calls can be made. **
** **
** Inputs: found: TRUE if a suitable cell of the chosen **
** PLMN has been found; FALSE otherwise. **
** tac: The code of the location/tracking area the **
** chosen PLMN belongs to **
** ci: The identifier of the cell **
** rat: The radio access technology supported by **
** the cell **
** Others: _emm_plmn_list, _emm_data **
** **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list, _emm_data **
** obtain normal service from a PLMN. Then the MS attempts **
** to camp on an acceptable cell, irrespective of its PLMN **
** identity, so that only emergency calls can be made. **
** **
** Inputs: found: TRUE if a suitable cell of the chosen **
** PLMN has been found; FALSE otherwise. **
** tac: The code of the location/tracking area the **
** chosen PLMN belongs to **
** ci: The identifier of the cell **
** rat: The radio access technology supported by **
** the cell **
** Others: _emm_plmn_list, _emm_data **
** **
** Outputs: None **
** Return: None **
** Others: _emm_plmn_list, _emm_data **
** **
***************************************************************************/
int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat)
......@@ -697,217 +690,212 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat)
int select_next_plmn = FALSE;
LOG_TRACE(INFO, "EMM-IDLE - %s cell found for PLMN %d in %s mode",
(found)? "One" : "No", index,
(_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
(_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
"Automatic/manual");
if (found)
{
int is_forbidden = FALSE;
/* Select the PLMN of which a suitable cell has been found */
_emm_data.splmn = *_emm_plmn_list.plmn[index];
/* Update the selected PLMN's parameters */
_emm_plmn_list.param[index].tac = tac;
_emm_plmn_list.param[index].ci = ci;
_emm_plmn_list.param[index].rat = rat;
/* Update the location data and notify EMM that data have changed */
rc = emm_proc_location_notify(tac, ci , rat);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify location update");
}
if (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO) {
/*
* Automatic mode of operation
* ---------------------------
*/
int i;
/* Check if the selected PLMN is in the forbidden list */
for (i = 0; i < _emm_data.fplmn.n_plmns; i++) {
if (PLMNS_ARE_EQUAL(_emm_data.splmn, _emm_data.fplmn.plmn[i])) {
is_forbidden = TRUE;
break;
}
}
if (!is_forbidden) {
for (i = 0; i < _emm_data.fplmn_gprs.n_plmns; i++) {
if (PLMNS_ARE_EQUAL(_emm_data.splmn,
_emm_data.fplmn_gprs.plmn[i])) {
is_forbidden = TRUE;
break;
}
}
}
/* Check if the selected PLMN belongs to a forbidden
* tracking area */
tai_t tai;
tai.plmn = _emm_data.splmn;
tai.tac = tac;
if (!is_forbidden) {
for (i = 0; i < _emm_data.ftai.n_tais; i++) {
if (TAIS_ARE_EQUAL(tai, _emm_data.ftai.tai[i])) {
is_forbidden = TRUE;
break;
}
}
}
if (!is_forbidden) {
for (i = 0; i < _emm_data.ftai_roaming.n_tais; i++) {
if (TAIS_ARE_EQUAL(tai, _emm_data.ftai_roaming.tai[i])) {
is_forbidden = TRUE;
break;
}
}
}
}
if (is_forbidden) {
/* The selected cell is known not to be able to provide normal
* service */
LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this acceptable cell ",
"for limited services");
/* Save the index of the first forbidden PLMN */
if (_emm_plmn_list.fplmn < 0) {
_emm_plmn_list.fplmn = index;
}
_emm_plmn_list.param[index].stat = NET_OPER_FORBIDDEN;
}
else {
/* A suitable cell has been found and the PLMN or tracking area
* is not in the forbidden list */
LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this suitable cell ",
"for normal services");
_emm_plmn_list.fplmn = -1;
_emm_plmn_list.param[index].stat = NET_OPER_CURRENT;
emm_sap.primitive = EMMREG_REGISTER_CNF;
}
/* Duplicate the new selected PLMN at the end of the ordered list */
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns] = &_emm_data.splmn;
(found)? "One" : "No", index,
(_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
(_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
"Automatic/manual");
if (found) {
int is_forbidden = FALSE;
/* Select the PLMN of which a suitable cell has been found */
_emm_data.splmn = *_emm_plmn_list.plmn[index];
/* Update the selected PLMN's parameters */
_emm_plmn_list.param[index].tac = tac;
_emm_plmn_list.param[index].ci = ci;
_emm_plmn_list.param[index].rat = rat;
/* Update the location data and notify EMM that data have changed */
rc = emm_proc_location_notify(tac, ci , rat);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "EMM-IDLE - Failed to notify location update");
}
if (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO) {
/*
* Automatic mode of operation
* ---------------------------
*/
int i;
/* Check if the selected PLMN is in the forbidden list */
for (i = 0; i < _emm_data.fplmn.n_plmns; i++) {
if (PLMNS_ARE_EQUAL(_emm_data.splmn, _emm_data.fplmn.plmn[i])) {
is_forbidden = TRUE;
break;
}
}
if (!is_forbidden) {
for (i = 0; i < _emm_data.fplmn_gprs.n_plmns; i++) {
if (PLMNS_ARE_EQUAL(_emm_data.splmn,
_emm_data.fplmn_gprs.plmn[i])) {
is_forbidden = TRUE;
break;
}
}
}
/* Check if the selected PLMN belongs to a forbidden
* tracking area */
tai_t tai;
tai.plmn = _emm_data.splmn;
tai.tac = tac;
if (!is_forbidden) {
for (i = 0; i < _emm_data.ftai.n_tais; i++) {
if (TAIS_ARE_EQUAL(tai, _emm_data.ftai.tai[i])) {
is_forbidden = TRUE;
break;
}
}
}
if (!is_forbidden) {
for (i = 0; i < _emm_data.ftai_roaming.n_tais; i++) {
if (TAIS_ARE_EQUAL(tai, _emm_data.ftai_roaming.tai[i])) {
is_forbidden = TRUE;
break;
}
}
}
}
if (is_forbidden) {
/* The selected cell is known not to be able to provide normal
* service */
LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this acceptable cell ",
"for limited services");
/* Save the index of the first forbidden PLMN */
if (_emm_plmn_list.fplmn < 0) {
_emm_plmn_list.fplmn = index;
}
_emm_plmn_list.param[index].stat = NET_OPER_FORBIDDEN;
} else {
/* A suitable cell has been found and the PLMN or tracking area
* is not in the forbidden list */
LOG_TRACE(INFO, "EMM-IDLE - UE may camp on this suitable cell ",
"for normal services");
_emm_plmn_list.fplmn = -1;
_emm_plmn_list.param[index].stat = NET_OPER_CURRENT;
emm_sap.primitive = EMMREG_REGISTER_CNF;
}
/* Duplicate the new selected PLMN at the end of the ordered list */
_emm_plmn_list.plmn[_emm_plmn_list.n_plmns] = &_emm_data.splmn;
}
else if (_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO) {
/*
* Automatic mode of operation
* ---------------------------
* No suitable cell of the chosen PLMN has been found;
* Try to select the next PLMN in the ordered list of available PLMNs
*/
index += 1;
select_next_plmn = TRUE;
/* Bypass the previously selected PLMN */
if (index == _emm_plmn_list.splmn) {
index += 1;
}
/*
* Automatic mode of operation
* ---------------------------
* No suitable cell of the chosen PLMN has been found;
* Try to select the next PLMN in the ordered list of available PLMNs
*/
index += 1;
select_next_plmn = TRUE;
/* Bypass the previously selected PLMN */
if (index == _emm_plmn_list.splmn) {
index += 1;
}
}
else if (_emm_data.plmn_index < 0) {
/*
* Manual or manual/automatic mode of operation
* --------------------------------------------
* Attempt to automatically find a suitable cell of the last
* registered or equivalent PLMNs is ongoing
*/
index += 1;
select_next_plmn = TRUE;
}
/*
* Manual or manual/automatic mode of operation
* --------------------------------------------
* Attempt to automatically find a suitable cell of the last
* registered or equivalent PLMNs is ongoing
*/
index += 1;
select_next_plmn = TRUE;
}
else if (_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL) {
/*
* Manual mode of operation
* ------------------------
* No suitable cell of the PLMN selected by the user has been found
*/
emm_sap.primitive = EMMREG_NO_CELL;
/*
* Manual mode of operation
* ------------------------
* No suitable cell of the PLMN selected by the user has been found
*/
emm_sap.primitive = EMMREG_NO_CELL;
}
else {
/*
* Manual/automatic mode of operation
* --------------------------------------------
* Attempt to find a suitable cell of the PLMN selected by the user
* failed; Try to automatically select another PLMN
*/
_emm_data.plmn_mode = EMM_DATA_PLMN_AUTO;
index = _emm_plmn_list.hplmn;
select_next_plmn = TRUE;
/*
* Manual/automatic mode of operation
* --------------------------------------------
* Attempt to find a suitable cell of the PLMN selected by the user
* failed; Try to automatically select another PLMN
*/
_emm_data.plmn_mode = EMM_DATA_PLMN_AUTO;
index = _emm_plmn_list.hplmn;
select_next_plmn = TRUE;
}
/*
* Force an attempt to register to the next PLMN
*/
if (select_next_plmn) {
int last_plmn_index = _emm_plmn_list.n_plmns;
if (_emm_plmn_list.splmn != -1) {
/* The last attempt was to register the previously selected PLMN */
last_plmn_index += 1;
}
if (index < last_plmn_index) {
/* Try to select the next PLMN in the list of available PLMNs */
_emm_plmn_list.index = index;
rc = emm_proc_plmn_selection(index);
}
else {
/* No suitable cell of any PLMN within the ordered list
* of available PLMNs has been found */
select_next_plmn = FALSE;
emm_sap.primitive = EMMREG_NO_CELL;
}
int last_plmn_index = _emm_plmn_list.n_plmns;
if (_emm_plmn_list.splmn != -1) {
/* The last attempt was to register the previously selected PLMN */
last_plmn_index += 1;
}
if (index < last_plmn_index) {
/* Try to select the next PLMN in the list of available PLMNs */
_emm_plmn_list.index = index;
rc = emm_proc_plmn_selection(index);
} else {
/* No suitable cell of any PLMN within the ordered list
* of available PLMNs has been found */
select_next_plmn = FALSE;
emm_sap.primitive = EMMREG_NO_CELL;
}
}
/*
* Or terminate the PLMN selection procedure
*/
if (!select_next_plmn) {
if (!(_emm_plmn_list.fplmn) < 0) {
/* There were one or more PLMNs which were available and allowable,
* but an LR failure made registration on those PLMNs unsuccessful
* or an entry in any of the forbidden area lists prevented a
* registration attempt; select the first such PLMN and enters a
* limited service state. */
index = _emm_plmn_list.fplmn;
_emm_plmn_list.fplmn = -1;
emm_sap.primitive = EMMREG_REGISTER_REJ;
}
/* Update the availability indicator of the previously selected PLMN */
if (_emm_plmn_list.splmn != -1) {
_emm_plmn_list.param[_emm_plmn_list.splmn].stat = NET_OPER_UNKNOWN;
}
/* Update the index of the new selected PLMN */
if (emm_sap.primitive != EMMREG_NO_CELL) {
_emm_plmn_list.splmn = index;
}
else {
_emm_plmn_list.splmn = -1;
}
/*
* Notify EMM that PLMN selection procedure has completed
*/
rc = emm_sap_send(&emm_sap);
if (_emm_plmn_list.splmn != -1) {
if (_emm_plmn_list.splmn == _emm_plmn_list.rplmn) {
/* The selected PLMN is the registered PLMN */
_emm_data.is_rplmn = TRUE;
}
else if (_emm_plmn_list.splmn < _emm_plmn_list.hplmn) {
/* The selected PLMN is in the list of equivalent PLMNs */
_emm_data.is_eplmn = TRUE;
}
/*
* Notify EMM that an attach procedure has to be initiated
* to register the presence of the UE to the selected PLMN
*/
emm_sap.primitive = EMMREG_ATTACH_INIT;
rc = emm_sap_send(&emm_sap);
}
if (!(_emm_plmn_list.fplmn) < 0) {
/* There were one or more PLMNs which were available and allowable,
* but an LR failure made registration on those PLMNs unsuccessful
* or an entry in any of the forbidden area lists prevented a
* registration attempt; select the first such PLMN and enters a
* limited service state. */
index = _emm_plmn_list.fplmn;
_emm_plmn_list.fplmn = -1;
emm_sap.primitive = EMMREG_REGISTER_REJ;
}
/* Update the availability indicator of the previously selected PLMN */
if (_emm_plmn_list.splmn != -1) {
_emm_plmn_list.param[_emm_plmn_list.splmn].stat = NET_OPER_UNKNOWN;
}
/* Update the index of the new selected PLMN */
if (emm_sap.primitive != EMMREG_NO_CELL) {
_emm_plmn_list.splmn = index;
} else {
_emm_plmn_list.splmn = -1;
}
/*
* Notify EMM that PLMN selection procedure has completed
*/
rc = emm_sap_send(&emm_sap);
if (_emm_plmn_list.splmn != -1) {
if (_emm_plmn_list.splmn == _emm_plmn_list.rplmn) {
/* The selected PLMN is the registered PLMN */
_emm_data.is_rplmn = TRUE;
} else if (_emm_plmn_list.splmn < _emm_plmn_list.hplmn) {
/* The selected PLMN is in the list of equivalent PLMNs */
_emm_data.is_eplmn = TRUE;
}
/*
* Notify EMM that an attach procedure has to be initiated
* to register the presence of the UE to the selected PLMN
*/
emm_sap.primitive = EMMREG_ATTACH_INIT;
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN (rc);
......@@ -915,24 +903,24 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat)
/*
*---------------------------------------------------------------------------
* Network indication handlers
* Network indication handlers
*---------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: emm_proc_registration_notify() **
** Name: emm_proc_registration_notify() **
** **
** Description: Updates the current network registration status and noti- **
** fy the EMM main controller that network registration sta- **
** tus has changed. **
** fy the EMM main controller that network registration sta- **
** tus has changed. **
** **
** Inputs: status: The new network registraton status **
** Others: None **
** Inputs: status: The new network registraton status **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** **
***************************************************************************/
int emm_proc_registration_notify(Stat_t status)
......@@ -943,9 +931,9 @@ int emm_proc_registration_notify(Stat_t status)
/* Update the network registration status */
if (_emm_data.stat != status) {
_emm_data.stat = status;
/* Notify EMM that data has changed */
rc = (*_emm_indication_notify)(1);
_emm_data.stat = status;
/* Notify EMM that data has changed */
rc = (*_emm_indication_notify)(1);
}
LOG_FUNC_RETURN (rc);
......@@ -953,20 +941,20 @@ int emm_proc_registration_notify(Stat_t status)
/****************************************************************************
** **
** Name: emm_proc_location_notify() **
** Name: emm_proc_location_notify() **
** **
** Description: Updates the current location information and notify the **
** EMM main controller that location area has changed. **
** EMM main controller that location area has changed. **
** **
** Inputs: tac: The code of the new location/tracking area **
** ci: The identifier of the new serving cell **
** rat: The Radio Access Technology supported by **
** the new serving cell **
** Others: None **
** Inputs: tac: The code of the new location/tracking area **
** ci: The identifier of the new serving cell **
** rat: The Radio Access Technology supported by **
** the new serving cell **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** **
***************************************************************************/
int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat)
......@@ -977,14 +965,13 @@ int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat)
/* Update the location information */
if ( (_emm_data.tac != tac) ||
(_emm_data.ci != ci) ||
(_emm_data.rat != rat) )
{
_emm_data.tac = tac;
_emm_data.ci = ci;
_emm_data.rat = rat;
/* Notify EMM that data has changed */
rc = (*_emm_indication_notify)(0);
(_emm_data.ci != ci) ||
(_emm_data.rat != rat) ) {
_emm_data.tac = tac;
_emm_data.ci = ci;
_emm_data.rat = rat;
/* Notify EMM that data has changed */
rc = (*_emm_indication_notify)(0);
}
LOG_FUNC_RETURN (rc);
......@@ -992,19 +979,19 @@ int emm_proc_location_notify(tac_t tac, ci_t ci, AcT_t rat)
/****************************************************************************
** **
** Name: emm_proc_network_notify() **
** Name: emm_proc_network_notify() **
** **
** Description: Updates the string representation of the list of opera- **
** tors present in the network and notify the EMM main con- **
** troller that the list has to be displayed to the user **
** application. **
** tors present in the network and notify the EMM main con- **
** troller that the list has to be displayed to the user **
** application. **
** **
** Inputs: index: Index of the first operator to update **
** Others: None **
** Inputs: index: Index of the first operator to update **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** **
***************************************************************************/
int emm_proc_network_notify(int index)
......@@ -1028,65 +1015,89 @@ int emm_proc_network_notify(int index)
#ifdef NAS_UE
/****************************************************************************
** **
** Name: _IdleMain_plmn_str() **
** Name: _IdleMain_plmn_str() **
** **
** Description: Converts a PLMN identifier to a string representation in **
** the numeric format **
** the numeric format **
** **
** Inputs: plmn: The PLMN identifier to convert **
** Others: None **
** Inputs: plmn: The PLMN identifier to convert **
** Others: None **
** **
** Outputs: plmn_str: The PLMN identifier in numeric format **
** Return: The size in bytes of the string represen- **
** tation of the PLMN identifier **
** Others: None **
** Outputs: plmn_str: The PLMN identifier in numeric format **
** Return: The size in bytes of the string represen- **
** tation of the PLMN identifier **
** Others: None **
** **
***************************************************************************/
static int _IdleMode_plmn_str(char* plmn_str, const plmn_t* plmn)
static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn)
{
char* p = plmn_str;
char *p = plmn_str;
if (plmn == NULL) {
return 0;
return 0;
}
if (plmn->MCCdigit1 != 0x0F) sprintf(p++, "%u", plmn->MCCdigit1);
if (plmn->MCCdigit2 != 0x0F) sprintf(p++, "%u", plmn->MCCdigit2);
if (plmn->MCCdigit3 != 0x0F) sprintf(p++, "%u", plmn->MCCdigit3);
if (plmn->MNCdigit1 != 0x0F) sprintf(p++, "%u", plmn->MNCdigit1);
if (plmn->MNCdigit2 != 0x0F) sprintf(p++, "%u", plmn->MNCdigit2);
if (plmn->MNCdigit3 != 0x0F) sprintf(p++, "%u", plmn->MNCdigit3);
if (plmn->MCCdigit1 != 0x0F) {
sprintf(p++, "%u", plmn->MCCdigit1);
}
if (plmn->MCCdigit2 != 0x0F) {
sprintf(p++, "%u", plmn->MCCdigit2);
}
if (plmn->MCCdigit3 != 0x0F) {
sprintf(p++, "%u", plmn->MCCdigit3);
}
if (plmn->MNCdigit1 != 0x0F) {
sprintf(p++, "%u", plmn->MNCdigit1);
}
if (plmn->MNCdigit2 != 0x0F) {
sprintf(p++, "%u", plmn->MNCdigit2);
}
if (plmn->MNCdigit3 != 0x0F) {
sprintf(p++, "%u", plmn->MNCdigit3);
}
return (p - plmn_str);
}
/****************************************************************************
** **
** Name: _IldlMode_get_opnn_id() **
** Name: _IldlMode_get_opnn_id() **
** **
** Description: Get the index of the specified PLMN in the list of opera- **
** tor network name records **
** tor network name records **
** **
** Inputs: plmn: The PLMN identifier **
** Others: _emm_data **
** Inputs: plmn: The PLMN identifier **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The index of the PLMN if found in the list **
** of operator network name records; **
** -1 otherwise; **
** Others: None **
** Outputs: None **
** Return: The index of the PLMN if found in the list **
** of operator network name records; **
** -1 otherwise; **
** Others: None **
** **
***************************************************************************/
static int _IldlMode_get_opnn_id(const plmn_t* plmn)
static int _IldlMode_get_opnn_id(const plmn_t *plmn)
{
for (int i = 0; i < _emm_data.n_opnns; i++) {
if (plmn->MCCdigit1 != _emm_data.opnn[i].plmn->MCCdigit1) continue;
if (plmn->MCCdigit2 != _emm_data.opnn[i].plmn->MCCdigit2) continue;
if (plmn->MCCdigit3 != _emm_data.opnn[i].plmn->MCCdigit3) continue;
if (plmn->MNCdigit1 != _emm_data.opnn[i].plmn->MNCdigit1) continue;
if (plmn->MNCdigit2 != _emm_data.opnn[i].plmn->MNCdigit2) continue;
if (plmn->MNCdigit3 != _emm_data.opnn[i].plmn->MNCdigit3) continue;
/* Found */
return (i);
if (plmn->MCCdigit1 != _emm_data.opnn[i].plmn->MCCdigit1) {
continue;
}
if (plmn->MCCdigit2 != _emm_data.opnn[i].plmn->MCCdigit2) {
continue;
}
if (plmn->MCCdigit3 != _emm_data.opnn[i].plmn->MCCdigit3) {
continue;
}
if (plmn->MNCdigit1 != _emm_data.opnn[i].plmn->MNCdigit1) {
continue;
}
if (plmn->MNCdigit2 != _emm_data.opnn[i].plmn->MNCdigit2) {
continue;
}
if (plmn->MNCdigit3 != _emm_data.opnn[i].plmn->MNCdigit3) {
continue;
}
/* Found */
return (i);
}
/* Not found */
return (-1);
......@@ -1094,30 +1105,30 @@ static int _IldlMode_get_opnn_id(const plmn_t* plmn)
/****************************************************************************
** **
** Name: _IdleMode_get_suitable_cell() **
** Name: _IdleMode_get_suitable_cell() **
** **
** Description: Query the Access Stratum to search for a suitable cell **
** that belongs to the selected PLMN. **
** that belongs to the selected PLMN. **
** **
** Inputs: index: Index of the selected PLMN in the ordered **
** list of available PLMNs **
** Others: _emm_plmn_list.plmn **
** Inputs: index: Index of the selected PLMN in the ordered **
** list of available PLMNs **
** Others: _emm_plmn_list.plmn **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _IdleMode_get_suitable_cell(int index)
{
emm_sap_t emm_sap;
const plmn_t* plmn = _emm_plmn_list.plmn[index];
const plmn_t *plmn = _emm_plmn_list.plmn[index];
LOG_TRACE(INFO, "EMM-IDLE - Trying to search a suitable cell "
"of PLMN %d in %s mode", index,
(_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
(_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
"Automatic/manual");
"of PLMN %d in %s mode", index,
(_emm_data.plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
(_emm_data.plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
"Automatic/manual");
/*
* Notify EMM-AS SAP that cell information related to the given
* PLMN are requested from the Access-Stratum
......@@ -1126,9 +1137,9 @@ static int _IdleMode_get_suitable_cell(int index)
emm_sap.u.emm_as.u.cell_info.plmnIDs.n_plmns = 1;
emm_sap.u.emm_as.u.cell_info.plmnIDs.plmn[0] = *plmn;
if (_emm_data.plmn_rat != NET_ACCESS_UNAVAILABLE) {
emm_sap.u.emm_as.u.cell_info.rat = (1 << _emm_data.plmn_rat);
emm_sap.u.emm_as.u.cell_info.rat = (1 << _emm_data.plmn_rat);
} else {
emm_sap.u.emm_as.u.cell_info.rat = NET_ACCESS_UNAVAILABLE;
emm_sap.u.emm_as.u.cell_info.rat = NET_ACCESS_UNAVAILABLE;
}
return emm_sap_send(&emm_sap);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source IdleMode.h
Source IdleMode.h
Version 0.1
Version 0.1
Date 2012/10/23
Date 2012/10/23
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the functions used to get information from the list
of available PLMNs locally maintained when the UE is in
idle mode.
Description Defines the functions used to get information from the list
of available PLMNs locally maintained when the UE is in
idle mode.
*****************************************************************************/
#ifndef __IDLEMODE_H__
......@@ -51,12 +51,14 @@ int IdleMode_get_splmn_index(void);
int IdleMode_update_plmn_list(int index);
const char* IdleMode_get_plmn_fullname(const plmn_t* plmn, int index, size_t* len);
const char* IdleMode_get_plmn_shortname(const plmn_t* plmn, int index, size_t* len);
const char* IdleMode_get_plmn_id(const plmn_t* plmn, int index, size_t* len);
const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index,
size_t *len);
const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index,
size_t *len);
const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len);
int IdleMode_get_plmn_fullname_index(const char* plmn);
int IdleMode_get_plmn_shortname_index(const char* plmn);
int IdleMode_get_plmn_id_index(const char* plmn);
int IdleMode_get_plmn_fullname_index(const char *plmn);
int IdleMode_get_plmn_shortname_index(const char *plmn);
int IdleMode_get_plmn_id_index(const char *plmn);
#endif /* __IDLEMODE_H__*/
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source LowerLayer.c
Source LowerLayer.c
Version 0.1
Version 0.1
Date 2012/03/14
Date 2012/03/14
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines EMM procedures executed by the Non-Access Stratum
upon receiving notifications from lower layers so that data
transfer succeed or failed, or NAS signalling connection is
released, or ESM unit data has been received from under layer,
and to request ESM unit data transfer to under layer.
Description Defines EMM procedures executed by the Non-Access Stratum
upon receiving notifications from lower layers so that data
transfer succeed or failed, or NAS signalling connection is
released, or ESM unit data has been received from under layer,
and to request ESM unit data transfer to under layer.
*****************************************************************************/
......@@ -31,7 +31,7 @@ Description Defines EMM procedures executed by the Non-Access Stratum
#include "emm_sap.h"
#include "esm_sap.h"
#include <string.h> // memset
#include <string.h> // memset
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
......@@ -47,10 +47,10 @@ Description Defines EMM procedures executed by the Non-Access Stratum
* receiving lower layer notifications
*/
static struct {
lowerlayer_success_callback_t success; /* Successful data delivery */
lowerlayer_failure_callback_t failure; /* Lower layer failure */
lowerlayer_release_callback_t release; /* NAS signalling release */
void* args; /* EMM procedure argument parameters */
lowerlayer_success_callback_t success; /* Successful data delivery */
lowerlayer_failure_callback_t failure; /* Lower layer failure */
lowerlayer_release_callback_t release; /* NAS signalling release */
void *args; /* EMM procedure argument parameters */
} _lowerlayer_data;
#endif
......@@ -60,23 +60,23 @@ static struct {
/*
* --------------------------------------------------------------------------
* Lower layer notification handlers
* Lower layer notification handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: lowerlayer_success() **
** Name: lowerlayer_success() **
** **
** Description: Notify the EPS Mobility Management entity that data have **
** been successfully delivered to the network **
** been successfully delivered to the network **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_success(unsigned int ueid)
......@@ -95,17 +95,17 @@ int lowerlayer_success(unsigned int ueid)
/****************************************************************************
** **
** Name: lowerlayer_failure() **
** Name: lowerlayer_failure() **
** **
** Description: Notify the EPS Mobility Management entity that lower la- **
** yers failed to deliver data to the network **
** yers failed to deliver data to the network **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_failure(unsigned int ueid)
......@@ -124,18 +124,18 @@ int lowerlayer_failure(unsigned int ueid)
/****************************************************************************
** **
** Name: lowerlayer_establish() **
** Name: lowerlayer_establish() **
** **
** Description: Update the EPS connection management status upon recei- **
** ving indication so that the NAS signalling connection is **
** established **
** ving indication so that the NAS signalling connection is **
** established **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_establish(void)
......@@ -152,17 +152,17 @@ int lowerlayer_establish(void)
/****************************************************************************
** **
** Name: lowerlayer_release() **
** Name: lowerlayer_release() **
** **
** Description: Notify the EPS Mobility Management entity that NAS signal-**
** ling connection has been released **
** ling connection has been released **
** **
** Inputs: cause: Release cause **
** Others: None **
** Inputs: cause: Release cause **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_release(int cause)
......@@ -186,21 +186,21 @@ int lowerlayer_release(int cause)
/****************************************************************************
** **
** Name: lowerlayer_data_ind() **
** Name: lowerlayer_data_ind() **
** **
** Description: Notify the EPS Session Management entity that data have **
** been received from lower layers **
** been received from lower layers **
** **
** Inputs: ueid: UE lower layer identifier **
** data: Data transfered from lower layers **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** data: Data transfered from lower layers **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_data_ind(unsigned int ueid, const OctetString* data)
int lowerlayer_data_ind(unsigned int ueid, const OctetString *data)
{
LOG_FUNC_IN;
......@@ -218,21 +218,21 @@ int lowerlayer_data_ind(unsigned int ueid, const OctetString* data)
/****************************************************************************
** **
** Name: lowerlayer_data_req() **
** Name: lowerlayer_data_req() **
** **
** Description: Notify the EPS Mobility Management entity that data have **
** to be transfered to lower layers **
** to be transfered to lower layers **
** **
** Inputs: ueid: UE lower layer identifier **
** data: Data to be transfered to lower layers **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** data: Data to be transfered to lower layers **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int lowerlayer_data_req(unsigned int ueid, const OctetString* data)
int lowerlayer_data_req(unsigned int ueid, const OctetString *data)
{
LOG_FUNC_IN;
......@@ -275,35 +275,35 @@ int lowerlayer_data_req(unsigned int ueid, const OctetString* data)
/*
* --------------------------------------------------------------------------
* EMM procedure handlers
* EMM procedure handlers
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_proc_lowerlayer_initialize() **
** Name: emm_proc_lowerlayer_initialize() **
** **
** Description: Initialize EMM procedure handler **
** **
** Inputs: success: EMM procedure executed when data have been **
** successfully delivered by lower layers **
** failure: EMM procedure executed upon transmission **
** failure reported by lower layers **
** release: EMM procedure executed when lower layers **
** report that NAS signalling connection has **
** been released **
** args: EMM procedure argument parameters **
** Others: None **
** Inputs: success: EMM procedure executed when data have been **
** successfully delivered by lower layers **
** failure: EMM procedure executed upon transmission **
** failure reported by lower layers **
** release: EMM procedure executed when lower layers **
** report that NAS signalling connection has **
** been released **
** args: EMM procedure argument parameters **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _lowerlayer_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _lowerlayer_data **
** **
***************************************************************************/
int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success,
lowerlayer_failure_callback_t failure,
lowerlayer_release_callback_t release,
void* args)
lowerlayer_failure_callback_t failure,
lowerlayer_release_callback_t release,
void *args)
{
LOG_FUNC_IN;
......@@ -317,18 +317,18 @@ int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success,
/****************************************************************************
** **
** Name: emm_proc_lowerlayer_success() **
** Name: emm_proc_lowerlayer_success() **
** **
** Description: Handles EMM procedure to be executed upon receiving noti- **
** fication that data have been successfully delivered to **
** the network. **
** fication that data have been successfully delivered to **
** the network. **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_lowerlayer_success(void)
......@@ -340,8 +340,8 @@ int emm_proc_lowerlayer_success(void)
lowerlayer_success_callback_t emm_callback = _lowerlayer_data.success;
if (emm_callback) {
rc = (*emm_callback)(_lowerlayer_data.args);
_lowerlayer_data.success = NULL;
rc = (*emm_callback)(_lowerlayer_data.args);
_lowerlayer_data.success = NULL;
}
LOG_FUNC_RETURN (rc);
......@@ -349,18 +349,18 @@ int emm_proc_lowerlayer_success(void)
/****************************************************************************
** **
** Name: emm_proc_lowerlayer_failure() **
** Name: emm_proc_lowerlayer_failure() **
** **
** Description: Handles EMM procedure to be executed upon receiving noti- **
** fication that data failed to be delivered to the network. **
** fication that data failed to be delivered to the network. **
** **
** Inputs: is_initial: TRUE if the NAS message that failed to be **
** transfered is an initial NAS message **
** Others: None **
** Inputs: is_initial: TRUE if the NAS message that failed to be **
** transfered is an initial NAS message **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_lowerlayer_failure(int is_initial)
......@@ -372,8 +372,8 @@ int emm_proc_lowerlayer_failure(int is_initial)
lowerlayer_failure_callback_t emm_callback = _lowerlayer_data.failure;
if (emm_callback) {
rc = (*emm_callback)(is_initial, _lowerlayer_data.args);
_lowerlayer_data.failure = NULL;
rc = (*emm_callback)(is_initial, _lowerlayer_data.args);
_lowerlayer_data.failure = NULL;
}
LOG_FUNC_RETURN (rc);
......@@ -381,17 +381,17 @@ int emm_proc_lowerlayer_failure(int is_initial)
/****************************************************************************
** **
** Name: emm_proc_lowerlayer_release() **
** Name: emm_proc_lowerlayer_release() **
** **
** Description: Handles EMM procedure to be executed upon receiving noti- **
** fication that NAS signalling connection has been released **
** fication that NAS signalling connection has been released **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_lowerlayer_release(void)
......@@ -403,8 +403,8 @@ int emm_proc_lowerlayer_release(void)
lowerlayer_release_callback_t emm_callback = _lowerlayer_data.release;
if (emm_callback) {
rc = (*emm_callback)(_lowerlayer_data.args);
_lowerlayer_data.release = NULL;
rc = (*emm_callback)(_lowerlayer_data.args);
_lowerlayer_data.release = NULL;
}
LOG_FUNC_RETURN (rc);
......@@ -413,60 +413,59 @@ int emm_proc_lowerlayer_release(void)
/****************************************************************************
** **
** Name: emm_as_set_security_data() **
** Name: emm_as_set_security_data() **
** **
** Description: Setup security data according to the given EPS security **
** context when data transfer to lower layers is requested **
** context when data transfer to lower layers is requested **
** **
** Inputs: args: EPS security context currently in use **
** is_new: Indicates whether a new security context **
** has just been taken into use **
** is_ciphered: Indicates whether the NAS message has to **
** be sent ciphered **
** Others: None **
** Inputs: args: EPS security context currently in use **
** is_new: Indicates whether a new security context **
** has just been taken into use **
** is_ciphered: Indicates whether the NAS message has to **
** be sent ciphered **
** Others: None **
** **
** Outputs: data: EPS NAS security data to be setup **
** Return: None **
** Others: None **
** Outputs: data: EPS NAS security data to be setup **
** Return: None **
** Others: None **
** **
***************************************************************************/
void emm_as_set_security_data(emm_as_security_data_t* data, const void* args,
int is_new, int is_ciphered)
void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
int is_new, int is_ciphered)
{
LOG_FUNC_IN;
const emm_security_context_t* context = (emm_security_context_t*)(args);
const emm_security_context_t *context = (emm_security_context_t *)(args);
memset(data, 0, sizeof(emm_as_security_data_t));
if ( context && (context->type != EMM_KSI_NOT_AVAILABLE) ) {
/* 3GPP TS 24.301, sections 5.4.3.3 and 5.4.3.4
* Once a valid EPS security context exists and has been taken
* into use, UE and MME shall cipher and integrity protect all
* NAS signalling messages with the selected NAS ciphering and
* NAS integrity algorithms */
data->is_new = is_new;
data->ksi = context->eksi;
data->sqn = context->ul_count.seq_num;
data->count = *(UInt32_t*)(&context->ul_count);
/* NAS integrity and cyphering keys may not be available if the
* current security context is a partial EPS security context
* and not a full native EPS security context */
data->k_int = &context->knas_int;
if (is_ciphered) {
/* 3GPP TS 24.301, sections 4.4.5
* When the UE establishes a new NAS signalling connection,
* it shall send initial NAS messages integrity protected
* and unciphered */
/* 3GPP TS 24.301, section 5.4.3.2
* The MME shall send the SECURITY MODE COMMAND message integrity
* protected and unciphered */
data->k_enc = &context->knas_enc;
}
}
else {
/* No valid EPS security context exists */
data->ksi = EMM_AS_NO_KEY_AVAILABLE;
/* 3GPP TS 24.301, sections 5.4.3.3 and 5.4.3.4
* Once a valid EPS security context exists and has been taken
* into use, UE and MME shall cipher and integrity protect all
* NAS signalling messages with the selected NAS ciphering and
* NAS integrity algorithms */
data->is_new = is_new;
data->ksi = context->eksi;
data->sqn = context->ul_count.seq_num;
data->count = *(UInt32_t *)(&context->ul_count);
/* NAS integrity and cyphering keys may not be available if the
* current security context is a partial EPS security context
* and not a full native EPS security context */
data->k_int = &context->knas_int;
if (is_ciphered) {
/* 3GPP TS 24.301, sections 4.4.5
* When the UE establishes a new NAS signalling connection,
* it shall send initial NAS messages integrity protected
* and unciphered */
/* 3GPP TS 24.301, section 5.4.3.2
* The MME shall send the SECURITY MODE COMMAND message integrity
* protected and unciphered */
data->k_enc = &context->knas_enc;
}
} else {
/* No valid EPS security context exists */
data->ksi = EMM_AS_NO_KEY_AVAILABLE;
}
LOG_FUNC_OUT;
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source lowerlayer.h
Source lowerlayer.h
Version 0.1
Version 0.1
Date 2013/06/19
Date 2013/06/19
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines EMM procedures executed by the Non-Access Stratum
upon receiving notifications from lower layers so that data
transfer succeed or failed, or NAS signalling connection is
released, or ESM unit data has been received from under layer,
and to request ESM unit data transfer to under layer.
Description Defines EMM procedures executed by the Non-Access Stratum
upon receiving notifications from lower layers so that data
transfer succeed or failed, or NAS signalling connection is
released, or ESM unit data has been received from under layer,
and to request ESM unit data transfer to under layer.
*****************************************************************************/
#ifndef __LOWERLAYER_H__
......@@ -35,19 +35,19 @@ Description Defines EMM procedures executed by the Non-Access Stratum
* Type of EMM procedure callback function executed whenever data are
* successfully delivered to the network
*/
typedef int (*lowerlayer_success_callback_t)(void*);
typedef int (*lowerlayer_success_callback_t)(void *);
/*
* Type of EMM procedure callback function executed when data are not
* delivered to the network because a lower layer failure occurred
*/
typedef int (*lowerlayer_failure_callback_t)(int, void*);
typedef int (*lowerlayer_failure_callback_t)(int, void *);
/*
* Type of EMM procedure callback function executed when NAS signalling
* connection is released
*/
typedef int (*lowerlayer_release_callback_t)(void*);
typedef int (*lowerlayer_release_callback_t)(void *);
#endif
/****************************************************************************/
......@@ -67,7 +67,7 @@ int lowerlayer_failure(unsigned int ueid);
int lowerlayer_establish(void);
int lowerlayer_release(int cause);
int lowerlayer_data_ind(unsigned int ueid, const OctetString* data);
int lowerlayer_data_req(unsigned int ueid, const OctetString* data);
int lowerlayer_data_ind(unsigned int ueid, const OctetString *data);
int lowerlayer_data_req(unsigned int ueid, const OctetString *data);
#endif /* __LOWERLAYER_H__*/
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source SecurityModeControl.c
Source SecurityModeControl.c
Version 0.1
Version 0.1
Date 2013/04/22
Date 2013/04/22
Product NAS stack
Product NAS stack
Subsystem Template body file
Subsystem Template body file
Author Frederic Maurel
Author Frederic Maurel
Description Defines the security mode control EMM procedure executed by the
Non-Access Stratum.
Description Defines the security mode control EMM procedure executed by the
Non-Access Stratum.
The purpose of the NAS security mode control procedure is to
take an EPS security context into use, and initialise and start
NAS signalling security between the UE and the MME with the
corresponding EPS NAS keys and EPS security algorithms.
The purpose of the NAS security mode control procedure is to
take an EPS security context into use, and initialise and start
NAS signalling security between the UE and the MME with the
corresponding EPS NAS keys and EPS security algorithms.
Furthermore, the network may also initiate a SECURITY MODE COM-
MAND in order to change the NAS security algorithms for a cur-
rent EPS security context already in use.
Furthermore, the network may also initiate a SECURITY MODE COM-
MAND in order to change the NAS security algorithms for a cur-
rent EPS security context already in use.
*****************************************************************************/
......@@ -37,8 +37,8 @@ Description Defines the security mode control EMM procedure executed by the
#include "emm_sap.h"
#include "emm_cause.h"
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
......@@ -54,22 +54,25 @@ Description Defines the security mode control EMM procedure executed by the
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
static int _security_kdf(const OctetString* kasme, OctetString* key,
UInt8_t algo_dist, UInt8_t algo_id);
static int _security_kdf(const OctetString *kasme, OctetString *key,
UInt8_t algo_dist, UInt8_t algo_id);
static int _security_knas_enc(const OctetString* kasme, OctetString* knas_enc, UInt8_t eia);
static int _security_knas_int(const OctetString* kasme, OctetString* knas_int, UInt8_t eea);
static int _security_kenb(const OctetString* kasme, OctetString* kenb, UInt32_t count);
static int _security_knas_enc(const OctetString *kasme, OctetString *knas_enc,
UInt8_t eia);
static int _security_knas_int(const OctetString *kasme, OctetString *knas_int,
UInt8_t eea);
static int _security_kenb(const OctetString *kasme, OctetString *kenb,
UInt32_t count);
/*
* Internal data used for security mode control procedure
*/
static struct {
OctetString kenb; /* eNodeB security key */
OctetString kenb; /* eNodeB security key */
} _security_data;
static void _security_release(emm_security_context_t* ctx);
#endif // NAS_UE
static void _security_release(emm_security_context_t *ctx);
#endif // NAS_UE
/*
* --------------------------------------------------------------------------
......@@ -80,31 +83,31 @@ static void _security_release(emm_security_context_t* ctx);
/*
* Timer handlers
*/
static void* _security_t3460_handler(void*);
static void *_security_t3460_handler(void *);
/*
* Function executed whenever the ongoing EMM procedure that initiated
* the security mode control procedure is aborted or the maximum value of the
* retransmission timer counter is exceed
*/
static int _security_abort(void*);
static int _security_abort(void *);
/*
* Internal data used for security mode control procedure
*/
typedef struct {
unsigned int ueid; /* UE identifier */
#define SECURITY_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
int ksi; /* NAS key set identifier */
int eea; /* Replayed EPS encryption algorithms */
int eia; /* Replayed EPS integrity algorithms */
int notify_failure; /* Indicates whether the security mode control
* procedure failure shall be notified to the
* ongoing EMM procedure */
unsigned int ueid; /* UE identifier */
#define SECURITY_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
int ksi; /* NAS key set identifier */
int eea; /* Replayed EPS encryption algorithms */
int eia; /* Replayed EPS integrity algorithms */
int notify_failure; /* Indicates whether the security mode control
* procedure failure shall be notified to the
* ongoing EMM procedure */
} security_data_t;
static int _security_request(security_data_t* data, int is_new);
static int _security_request(security_data_t *data, int is_new);
#endif // NAS_MME
/****************************************************************************/
......@@ -113,41 +116,41 @@ static int _security_request(security_data_t* data, int is_new);
/*
* --------------------------------------------------------------------------
* Security mode control procedure executed by the UE
* Security mode control procedure executed by the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_proc_security_mode_command() **
** Name: emm_proc_security_mode_command() **
** **
** Description: Performs the MME requested security mode control proce- **
** dure. **
** dure. **
** **
** 3GPP TS 24.301, section 5.4.3.3 **
** Upon receiving the SECURITY MODE COMMAND message, the UE **
** shall check whether the message can be accepted or not. **
** If accepted the UE shall send a SECURITY MODE COMPLETE **
** message integrity protected with the selected NAS inte- **
** grity algorithm and ciphered with the selected NAS ciphe- **
** ring algorithm. **
** **
** Inputs: native_ksi: TRUE if the security context is of type **
** native (for KSIASME) **
** ksi: The NAS ket sey identifier **
** seea: Selected EPS cyphering algorithm **
** seia: Selected EPS integrity algorithm **
** reea: Replayed EPS cyphering algorithm **
** reia: Replayed EPS integrity algorithm **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Upon receiving the SECURITY MODE COMMAND message, the UE **
** shall check whether the message can be accepted or not. **
** If accepted the UE shall send a SECURITY MODE COMPLETE **
** message integrity protected with the selected NAS inte- **
** grity algorithm and ciphered with the selected NAS ciphe- **
** ring algorithm. **
** **
** Inputs: native_ksi: TRUE if the security context is of type **
** native (for KSIASME) **
** ksi: The NAS ket sey identifier **
** seea: Selected EPS cyphering algorithm **
** seia: Selected EPS integrity algorithm **
** reea: Replayed EPS cyphering algorithm **
** reia: Replayed EPS integrity algorithm **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_security_mode_command(int native_ksi, int ksi,
int seea, int seia, int reea, int reia)
int seea, int seia, int reea, int reia)
{
LOG_FUNC_IN;
......@@ -156,7 +159,7 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
int security_context_is_new = FALSE;
LOG_TRACE(INFO, "EMM-PROC - Security mode control requested (ksi=%d)",
ksi);
ksi);
/* Delete any previously stored RAND and RES and stop timer T3416 */
(void) emm_proc_authentication_delete();
......@@ -167,134 +170,134 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
UInt8_t eea = (0x80 >> _emm_data.security->capability.encryption);
UInt8_t eia = (0x80 >> _emm_data.security->capability.integrity);
if ( (reea != eea) || (reia != eia) ) {
LOG_TRACE(WARNING, "EMM-PROC - Replayed UE security capabilities "
"rejected");
emm_cause = EMM_CAUSE_UE_SECURITY_MISMATCH;
/* XXX - For testing purpose UE always accepts EIA0
* The UE shall accept "null integrity protection algorithm" EIA0 only
* if a PDN connection for emergency bearer services is established or
* the UE is establishing a PDN connection for emergency bearer services
*/
LOG_TRACE(WARNING, "EMM-PROC - Replayed UE security capabilities "
"rejected");
emm_cause = EMM_CAUSE_UE_SECURITY_MISMATCH;
/* XXX - For testing purpose UE always accepts EIA0
* The UE shall accept "null integrity protection algorithm" EIA0 only
* if a PDN connection for emergency bearer services is established or
* the UE is establishing a PDN connection for emergency bearer services
*/
}
/*
* Check the non-current EPS security context
*/
else if (_emm_data.non_current == NULL) {
LOG_TRACE(WARNING, "EMM-PROC - Non-current EPS security context "
"is not valid");
emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED;
LOG_TRACE(WARNING, "EMM-PROC - Non-current EPS security context "
"is not valid");
emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED;
}
/*
* Update the non-current EPS security context
*/
else {
/* Update selected cyphering and integrity algorithms */
_emm_data.non_current->capability.encryption = seea;
_emm_data.non_current->capability.integrity = seia;
/* Derive the NAS cyphering key */
if (_emm_data.non_current->knas_enc.value == NULL) {
_emm_data.non_current->knas_enc.value =
(uint8_t*)malloc(AUTH_KNAS_ENC_SIZE);
_emm_data.non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE;
}
if (_emm_data.non_current->knas_enc.value != NULL) {
rc = _security_knas_enc(&_emm_data.non_current->kasme,
&_emm_data.non_current->knas_enc, seea);
}
/* Derive the NAS integrity key */
if (_emm_data.non_current->knas_int.value == NULL) {
_emm_data.non_current->knas_int.value =
(uint8_t*)malloc(AUTH_KNAS_INT_SIZE);
_emm_data.non_current->knas_int.length = AUTH_KNAS_INT_SIZE;
}
if (_emm_data.non_current->knas_int.value != NULL) {
if (rc != RETURNerror) {
rc = _security_knas_int(&_emm_data.non_current->kasme,
&_emm_data.non_current->knas_int, seea);
}
}
/* Derive the eNodeB key */
if (_security_data.kenb.value == NULL) {
_security_data.kenb.value = (uint8_t*)malloc(AUTH_KENB_SIZE);
_security_data.kenb.length = AUTH_KENB_SIZE;
}
if (_security_data.kenb.value != NULL) {
if (rc != RETURNerror) {
rc = _security_kenb(&_security_data.kenb,
&_emm_data.security->kasme,
*(UInt32_t*)(&_emm_data.non_current->ul_count));
}
}
/*
* NAS security mode command accepted by the UE
*/
if (rc != RETURNerror) {
/* Update the current EPS security context */
if ( native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) {
/* The type of security context flag included in the SECURITY
* MODE COMMAND message is set to "native security context" and
* the UE has a mapped EPS security context as the current EPS
* security context */
if ( (_emm_data.non_current->type == EMM_KSI_NATIVE) &&
(_emm_data.non_current->eksi == ksi) ) {
/* The KSI matches the non-current native EPS security
* context; the UE shall take the non-current native EPS
* security context into use which then becomes the
* current native EPS security context and delete the
* mapped EPS security context */
LOG_TRACE(INFO,
"EMM-PROC - Update Current security context");
/* Release non-current security context */
_security_release(_emm_data.security);
_emm_data.security = _emm_data.non_current;
/* Reset the uplink NAS COUNT counter */
_emm_data.security->ul_count.overflow = 0;
_emm_data.security->ul_count.seq_num = 0;
/* Set new security context indicator */
security_context_is_new = TRUE;
}
}
if ( !native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) {
/* The type of security context flag included in the SECURITY
* MODE COMMAND message is set to "mapped security context" and
* the UE has a mapped EPS security context as the current EPS
* security context */
if (ksi != _emm_data.security->eksi) {
/* The KSI does not match the current EPS security context;
* the UE shall reset the uplink NAS COUNT counter */
LOG_TRACE(INFO,
"EMM-PROC - Reset uplink NAS COUNT counter");
_emm_data.security->ul_count.overflow = 0;
_emm_data.security->ul_count.seq_num = 0;
}
}
}
/*
* NAS security mode command not accepted by the UE
*/
else {
/* Setup EMM cause code */
emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED;
/* Release security mode control internal data */
if (_security_data.kenb.value) {
free(_security_data.kenb.value);
_security_data.kenb.value = NULL;
_security_data.kenb.length = 0;
}
}
/* Update selected cyphering and integrity algorithms */
_emm_data.non_current->capability.encryption = seea;
_emm_data.non_current->capability.integrity = seia;
/* Derive the NAS cyphering key */
if (_emm_data.non_current->knas_enc.value == NULL) {
_emm_data.non_current->knas_enc.value =
(uint8_t *)malloc(AUTH_KNAS_ENC_SIZE);
_emm_data.non_current->knas_enc.length = AUTH_KNAS_ENC_SIZE;
}
if (_emm_data.non_current->knas_enc.value != NULL) {
rc = _security_knas_enc(&_emm_data.non_current->kasme,
&_emm_data.non_current->knas_enc, seea);
}
/* Derive the NAS integrity key */
if (_emm_data.non_current->knas_int.value == NULL) {
_emm_data.non_current->knas_int.value =
(uint8_t *)malloc(AUTH_KNAS_INT_SIZE);
_emm_data.non_current->knas_int.length = AUTH_KNAS_INT_SIZE;
}
if (_emm_data.non_current->knas_int.value != NULL) {
if (rc != RETURNerror) {
rc = _security_knas_int(&_emm_data.non_current->kasme,
&_emm_data.non_current->knas_int, seea);
}
}
/* Derive the eNodeB key */
if (_security_data.kenb.value == NULL) {
_security_data.kenb.value = (uint8_t *)malloc(AUTH_KENB_SIZE);
_security_data.kenb.length = AUTH_KENB_SIZE;
}
if (_security_data.kenb.value != NULL) {
if (rc != RETURNerror) {
rc = _security_kenb(&_security_data.kenb,
&_emm_data.security->kasme,
*(UInt32_t *)(&_emm_data.non_current->ul_count));
}
}
/*
* NAS security mode command accepted by the UE
*/
if (rc != RETURNerror) {
/* Update the current EPS security context */
if ( native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) {
/* The type of security context flag included in the SECURITY
* MODE COMMAND message is set to "native security context" and
* the UE has a mapped EPS security context as the current EPS
* security context */
if ( (_emm_data.non_current->type == EMM_KSI_NATIVE) &&
(_emm_data.non_current->eksi == ksi) ) {
/* The KSI matches the non-current native EPS security
* context; the UE shall take the non-current native EPS
* security context into use which then becomes the
* current native EPS security context and delete the
* mapped EPS security context */
LOG_TRACE(INFO,
"EMM-PROC - Update Current security context");
/* Release non-current security context */
_security_release(_emm_data.security);
_emm_data.security = _emm_data.non_current;
/* Reset the uplink NAS COUNT counter */
_emm_data.security->ul_count.overflow = 0;
_emm_data.security->ul_count.seq_num = 0;
/* Set new security context indicator */
security_context_is_new = TRUE;
}
}
if ( !native_ksi && (_emm_data.security->type != EMM_KSI_NATIVE) ) {
/* The type of security context flag included in the SECURITY
* MODE COMMAND message is set to "mapped security context" and
* the UE has a mapped EPS security context as the current EPS
* security context */
if (ksi != _emm_data.security->eksi) {
/* The KSI does not match the current EPS security context;
* the UE shall reset the uplink NAS COUNT counter */
LOG_TRACE(INFO,
"EMM-PROC - Reset uplink NAS COUNT counter");
_emm_data.security->ul_count.overflow = 0;
_emm_data.security->ul_count.seq_num = 0;
}
}
}
/*
* NAS security mode command not accepted by the UE
*/
else {
/* Setup EMM cause code */
emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED;
/* Release security mode control internal data */
if (_security_data.kenb.value) {
free(_security_data.kenb.value);
_security_data.kenb.value = NULL;
_security_data.kenb.length = 0;
}
}
}
/* Setup EMM procedure handler to be executed upon receiving
* lower layer notification */
rc = emm_proc_lowerlayer_initialize(NULL, NULL, NULL, NULL);
if (rc != RETURNok) {
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
LOG_TRACE(WARNING,
"EMM-PROC - Failed to initialize EMM procedure handler");
LOG_FUNC_RETURN (RETURNerror);
}
/*
......@@ -309,7 +312,7 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
emm_sap.u.emm_as.u.security.emm_cause = emm_cause;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
_emm_data.security, security_context_is_new, TRUE);
_emm_data.security, security_context_is_new, TRUE);
rc = emm_sap_send(&emm_sap);
LOG_FUNC_RETURN (rc);
......@@ -318,47 +321,47 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
/*
* --------------------------------------------------------------------------
* Security mode control procedure executed by the MME
* Security mode control procedure executed by the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
/****************************************************************************
** **
** Name: emm_proc_security_mode_control() **
** Name: emm_proc_security_mode_control() **
** **
** Description: Initiates the security mode control procedure. **
** **
** 3GPP TS 24.301, section 5.4.3.2 **
** The MME initiates the NAS security mode control procedure **
** by sending a SECURITY MODE COMMAND message to the UE and **
** starting timer T3460. The message shall be sent unciphe- **
** red but shall be integrity protected using the NAS inte- **
** grity key based on KASME. **
** **
** Inputs: ueid: UE lower layer identifier **
** ksi: NAS key set identifier **
** eea: Replayed EPS encryption algorithms **
** eia: Replayed EPS integrity algorithms **
** success: Callback function executed when the secu- **
** rity mode control procedure successfully **
** completes **
** reject: Callback function executed when the secu- **
** rity mode control procedure fails or is **
** rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the security **
** mode control procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** The MME initiates the NAS security mode control procedure **
** by sending a SECURITY MODE COMMAND message to the UE and **
** starting timer T3460. The message shall be sent unciphe- **
** red but shall be integrity protected using the NAS inte- **
** grity key based on KASME. **
** **
** Inputs: ueid: UE lower layer identifier **
** ksi: NAS key set identifier **
** eea: Replayed EPS encryption algorithms **
** eia: Replayed EPS integrity algorithms **
** success: Callback function executed when the secu- **
** rity mode control procedure successfully **
** completes **
** reject: Callback function executed when the secu- **
** rity mode control procedure fails or is **
** rejected **
** failure: Callback function executed whener a lower **
** layer failure occured before the security **
** mode control procedure comnpletes **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure)
{
LOG_FUNC_IN;
......@@ -366,10 +369,10 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
int security_context_is_new = FALSE;
LOG_TRACE(INFO, "EMM-PROC - Initiate security mode control procedure "
"KSI = %d", ksi);
"KSI = %d", ksi);
/* Get the UE context */
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
#if defined(EPC_BUILD)
if (ueid > 0) {
......@@ -382,62 +385,61 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
#endif
if (emm_ctx && emm_ctx->security) {
if (emm_ctx->security->type == EMM_KSI_NOT_AVAILABLE) {
/* The security mode control procedure is initiated to take into use
* the EPS security context created after a successful execution of
* the EPS authentication procedure */
emm_ctx->security->type = EMM_KSI_NATIVE;
emm_ctx->security->eksi = ksi;
emm_ctx->security->dl_count.overflow = 0;
emm_ctx->security->dl_count.seq_num = 0;
/* TODO !!! Compute Kasme, and NAS cyphering and integrity keys */
/* Set new security context indicator */
security_context_is_new = TRUE;
}
}
else {
LOG_TRACE(WARNING, "EMM-PROC - No EPS security context exists");
LOG_FUNC_RETURN (RETURNerror);
if (emm_ctx->security->type == EMM_KSI_NOT_AVAILABLE) {
/* The security mode control procedure is initiated to take into use
* the EPS security context created after a successful execution of
* the EPS authentication procedure */
emm_ctx->security->type = EMM_KSI_NATIVE;
emm_ctx->security->eksi = ksi;
emm_ctx->security->dl_count.overflow = 0;
emm_ctx->security->dl_count.seq_num = 0;
/* TODO !!! Compute Kasme, and NAS cyphering and integrity keys */
/* Set new security context indicator */
security_context_is_new = TRUE;
}
} else {
LOG_TRACE(WARNING, "EMM-PROC - No EPS security context exists");
LOG_FUNC_RETURN (RETURNerror);
}
/* Allocate parameters of the retransmission timer callback */
security_data_t* data =
(security_data_t*)malloc(sizeof(security_data_t));
security_data_t *data =
(security_data_t *)malloc(sizeof(security_data_t));
if (data != NULL) {
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_security_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
free(data);
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the key set identifier */
data->ksi = ksi;
/* Set the EPS encryption algorithms to be replayed to the UE */
data->eea = eea;
/* Set the EPS integrity algorithms to be replayed to the UE */
data->eia = eia;
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send security mode command message to the UE */
rc = _security_request(data, security_context_is_new);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
/* Setup ongoing EMM procedure callback functions */
rc = emm_proc_common_initialize(ueid, success, reject, failure,
_security_abort, data);
if (rc != RETURNok) {
LOG_TRACE(WARNING, "Failed to initialize EMM callback functions");
free(data);
LOG_FUNC_RETURN (RETURNerror);
}
/* Set the UE identifier */
data->ueid = ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
/* Set the key set identifier */
data->ksi = ksi;
/* Set the EPS encryption algorithms to be replayed to the UE */
data->eea = eea;
/* Set the EPS integrity algorithms to be replayed to the UE */
data->eia = eia;
/* Set the failure notification indicator */
data->notify_failure = FALSE;
/* Send security mode command message to the UE */
rc = _security_request(data, security_context_is_new);
if (rc != RETURNerror) {
/*
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
}
}
LOG_FUNC_RETURN (rc);
......@@ -445,29 +447,29 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
/****************************************************************************
** **
** Name: emm_proc_security_mode_complete() **
** Name: emm_proc_security_mode_complete() **
** **
** Description: Performs the security mode control completion procedure **
** executed by the network. **
** executed by the network. **
** **
** 3GPP TS 24.301, section 5.4.3.4 **
** Upon receiving the SECURITY MODE COMPLETE message, the **
** MME shall stop timer T3460. **
** From this time onward the MME shall integrity protect and **
** encipher all signalling messages with the selected NAS **
** integrity and ciphering algorithms. **
** Upon receiving the SECURITY MODE COMPLETE message, the **
** MME shall stop timer T3460. **
** From this time onward the MME shall integrity protect and **
** encipher all signalling messages with the selected NAS **
** integrity and ciphering algorithms. **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_security_mode_complete(unsigned int ueid)
{
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
int rc = RETURNerror;
emm_sap_t emm_sap;
......@@ -481,8 +483,10 @@ int emm_proc_security_mode_complete(unsigned int ueid)
T3460.id = nas_timer_stop(T3460.id);
/* Release retransmission timer paramaters */
security_data_t* data = (security_data_t*)(emm_proc_common_get_args(ueid));
if (data) free(data);
security_data_t *data = (security_data_t *)(emm_proc_common_get_args(ueid));
if (data) {
free(data);
}
/* Get the UE context */
#if defined(EPC_BUILD)
......@@ -496,20 +500,19 @@ int emm_proc_security_mode_complete(unsigned int ueid)
#endif
if (emm_ctx && emm_ctx->security) {
/*
* Notify EMM that the authentication procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
}
else {
LOG_TRACE(ERROR, "EMM-PROC - No EPS security context exists");
/*
* Notify EMM that the authentication procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
/*
* Notify EMM that the authentication procedure successfully completed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_CNF;
emm_sap.u.emm_reg.ueid = ueid;
emm_sap.u.emm_reg.u.common.is_attached = emm_ctx->is_attached;
} else {
LOG_TRACE(ERROR, "EMM-PROC - No EPS security context exists");
/*
* Notify EMM that the authentication procedure failed
*/
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
}
rc = emm_sap_send(&emm_sap);
......@@ -519,31 +522,31 @@ int emm_proc_security_mode_complete(unsigned int ueid)
/****************************************************************************
** **
** Name: emm_proc_security_mode_reject() **
** Name: emm_proc_security_mode_reject() **
** **
** Description: Performs the security mode control not accepted by the UE **
** **
** 3GPP TS 24.301, section 5.4.3.5 **
** Upon receiving the SECURITY MODE REJECT message, the MME **
** shall stop timer T3460 and abort the ongoing procedure **
** that triggered the initiation of the NAS security mode **
** control procedure. **
** The MME shall apply the EPS security context in use befo- **
** re the initiation of the security mode control procedure, **
** if any, to protect any subsequent messages. **
** Upon receiving the SECURITY MODE REJECT message, the MME **
** shall stop timer T3460 and abort the ongoing procedure **
** that triggered the initiation of the NAS security mode **
** control procedure. **
** The MME shall apply the EPS security context in use befo- **
** re the initiation of the security mode control procedure, **
** if any, to protect any subsequent messages. **
** **
** **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** Inputs: ueid: UE lower layer identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int emm_proc_security_mode_reject(unsigned int ueid)
{
emm_data_context_t* emm_ctx = NULL;
emm_data_context_t *emm_ctx = NULL;
int rc = RETURNerror;
LOG_FUNC_IN;
......@@ -556,8 +559,10 @@ int emm_proc_security_mode_reject(unsigned int ueid)
T3460.id = nas_timer_stop(T3460.id);
/* Release retransmission timer paramaters */
security_data_t* data = (security_data_t*)(emm_proc_common_get_args(ueid));
if (data) free(data);
security_data_t *data = (security_data_t *)(emm_proc_common_get_args(ueid));
if (data) {
free(data);
}
/* Get the UE context */
#if defined(EPC_BUILD)
......@@ -571,13 +576,13 @@ int emm_proc_security_mode_reject(unsigned int ueid)
#endif
/* Set the key set identifier to its previous value */
if (emm_ctx && emm_ctx->security) {
/* XXX - Usually, the MME should be able to maintain a current and
* a non-current EPS security context simultaneously as the UE do.
* This implementation choose to have only one security context by UE
* in the MME, thus security mode control procedure is only performed
* to take into use the first EPS security context created after a
* successful execution of the EPS authentication procedure */
emm_ctx->security->type = EMM_KSI_NOT_AVAILABLE;
/* XXX - Usually, the MME should be able to maintain a current and
* a non-current EPS security context simultaneously as the UE do.
* This implementation choose to have only one security context by UE
* in the MME, thus security mode control procedure is only performed
* to take into use the first EPS security context created after a
* successful execution of the EPS authentication procedure */
emm_ctx->security->type = EMM_KSI_NOT_AVAILABLE;
}
/*
......@@ -599,37 +604,43 @@ int emm_proc_security_mode_reject(unsigned int ueid)
#ifdef NAS_UE
/*
* --------------------------------------------------------------------------
* UE specific local functions
* UE specific local functions
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _security_release() **
** Name: _security_release() **
** **
** Description: Releases the given EPS NAS security context **
** **
** Inputs: ctx: The EPS NAS security context to release **
** Others: None **
** Inputs: ctx: The EPS NAS security context to release **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
static void _security_release(emm_security_context_t* ctx)
static void _security_release(emm_security_context_t *ctx)
{
LOG_FUNC_IN;
if (ctx) {
/* Release Kasme security key */
if (ctx->kasme.value) free(ctx->kasme.value);
/* Release NAS cyphering key */
if (ctx->knas_enc.value) free(ctx->knas_enc.value);
/* Release NAS integrity key */
if (ctx->knas_int.value) free(ctx->knas_int.value);
/* Release the NAS security context */
free(ctx);
/* Release Kasme security key */
if (ctx->kasme.value) {
free(ctx->kasme.value);
}
/* Release NAS cyphering key */
if (ctx->knas_enc.value) {
free(ctx->knas_enc.value);
}
/* Release NAS integrity key */
if (ctx->knas_int.value) {
free(ctx->knas_int.value);
}
/* Release the NAS security context */
free(ctx);
}
LOG_FUNC_OUT;
......@@ -637,24 +648,24 @@ static void _security_release(emm_security_context_t* ctx)
/****************************************************************************
** **
** Name: _security_knas_enc() **
** Name: _security_knas_enc() **
** **
** Description: Algorithm Key generation function used for the derivation **
** of NAS encryption key Knas-enc from the Kasme. **
** of NAS encryption key Knas-enc from the Kasme. **
** **
** 3GPP TS 33.401, Annex A.7 **
** **
** Inputs: kasme: Key Access Security Management Entity **
** eea: Cyphering algorithm identity **
** Others: None **
** Inputs: kasme: Key Access Security Management Entity **
** eea: Cyphering algorithm identity **
** Others: None **
** **
** Outputs: knas_enc: Derived key for NAS cyphering algorithm **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: knas_enc: Derived key for NAS cyphering algorithm **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _security_knas_enc(const OctetString* kasme, OctetString* knas_enc,
UInt8_t eea)
static int _security_knas_enc(const OctetString *kasme, OctetString *knas_enc,
UInt8_t eea)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (_security_kdf(kasme, knas_enc, 0x01, eea));
......@@ -662,24 +673,24 @@ static int _security_knas_enc(const OctetString* kasme, OctetString* knas_enc,
/****************************************************************************
** **
** Name: _security_knas_int() **
** Name: _security_knas_int() **
** **
** Description: Algorithm Key generation function used for the derivation **
** of NAS integrity key Knas-int from the Kasme. **
** of NAS integrity key Knas-int from the Kasme. **
** **
** 3GPP TS 33.401, Annex A.7 **
** **
** Inputs: kasme: Key Access Security Management Entity **
** eia: Integrity algorithm identity **
** Others: None **
** Inputs: kasme: Key Access Security Management Entity **
** eia: Integrity algorithm identity **
** Others: None **
** **
** Outputs: knas_int: Derived key for NAS integrity algorithm **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: knas_int: Derived key for NAS integrity algorithm **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _security_knas_int(const OctetString* kasme, OctetString* knas_int,
UInt8_t eia)
static int _security_knas_int(const OctetString *kasme, OctetString *knas_int,
UInt8_t eia)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (_security_kdf(kasme, knas_int, 0x02, eia));
......@@ -687,24 +698,24 @@ static int _security_knas_int(const OctetString* kasme, OctetString* knas_int,
/****************************************************************************
** **
** Name: _security_kenb() **
** Name: _security_kenb() **
** **
** Description: Computes the eNodeB key from Kasme and the given value of **
** uplink NAS counter. **
** uplink NAS counter. **
** **
** 3GPP TS 33.401, Annex A.3 **
** **
** Inputs: kasme: Key Access Security Management Entity **
** count: Uplink NAS counter value **
** Others: None **
** Inputs: kasme: Key Access Security Management Entity **
** count: Uplink NAS counter value **
** Others: None **
** **
** Outputs: kenb: eNodeB security key **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: kenb: eNodeB security key **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _security_kenb(const OctetString* kasme, OctetString* kenb,
UInt32_t count)
static int _security_kenb(const OctetString *kasme, OctetString *kenb,
UInt32_t count)
{
/* Compute the KDF input parameter
* S = FC(0x11) || UL NAS Count || 0x00 0x04
......@@ -713,8 +724,10 @@ static int _security_kenb(const OctetString* kasme, OctetString* kenb,
UInt16_t length = 4;
int offset = 0;
input[offset] = 0x11; offset += 1;
input[offset] = count; offset += length;
input[offset] = 0x11;
offset += 1;
input[offset] = count;
offset += length;
input[offset] = length;
/* TODO !!! Compute the derived key */
......@@ -724,40 +737,44 @@ static int _security_kenb(const OctetString* kasme, OctetString* kenb,
/****************************************************************************
** **
** Name: _security_kdf() **
** Name: _security_kdf() **
** **
** Description: Algorithm Key generation function used for the derivation **
** of keys for NAS integrity and NAS encryption algorithms **
** from Kasme, algorithm types and algorithm identities. **
** of keys for NAS integrity and NAS encryption algorithms **
** from Kasme, algorithm types and algorithm identities. **
** **
** 3GPP TS 33.401, Annex A.7 **
** **
** Inputs: kasme: Key Access Security Management Entity **
** algo_dist: Algorithm type distinguisher **
** algo_id: Algorithm identity **
** Others: None **
** Inputs: kasme: Key Access Security Management Entity **
** algo_dist: Algorithm type distinguisher **
** algo_id: Algorithm identity **
** Others: None **
** **
** Outputs: key: Derived key for NAS security protection **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: key: Derived key for NAS security protection **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _security_kdf(const OctetString* kasme, OctetString* key,
UInt8_t algo_dist, UInt8_t algo_id)
static int _security_kdf(const OctetString *kasme, OctetString *key,
UInt8_t algo_dist, UInt8_t algo_id)
{
/* Compute the KDF input parameter
* S = FC(0x15) || Algorithm distinguisher || 0x00 0x01
|| Algorithm identity || 0x00 0x01
|| Algorithm identity || 0x00 0x01
*/
UInt8_t input[kasme->length];
UInt16_t length = 1;
int offset = 0;
int size_of_length = sizeof(length);
input[offset] = 0x15; offset += 1;
input[offset] = algo_dist; offset += length;
input[offset] = length; offset += size_of_length;
input[offset] = algo_id; offset += length;
input[offset] = 0x15;
offset += 1;
input[offset] = algo_dist;
offset += length;
input[offset] = length;
offset += size_of_length;
input[offset] = algo_id;
offset += length;
input[offset] = length;
/* TODO !!! Compute the derived key */
......@@ -769,53 +786,52 @@ static int _security_kdf(const OctetString* kasme, OctetString* key,
#ifdef NAS_MME
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _security_t3460_handler() **
** Name: _security_t3460_handler() **
** **
** Description: T3460 timeout handler **
** Upon T3460 timer expiration, the security mode command **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** security mode control procedure. **
** Upon T3460 timer expiration, the security mode command **
** message is retransmitted and the timer restarted. When **
** retransmission counter is exceed, the MME shall abort the **
** security mode control procedure. **
** **
** 3GPP TS 24.301, section 5.4.3.7, case b **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
static void* _security_t3460_handler(void* args)
static void *_security_t3460_handler(void *args)
{
LOG_FUNC_IN;
int rc;
security_data_t* data = (security_data_t*)(args);
security_data_t *data = (security_data_t *)(args);
/* Increment the retransmission counter */
data->retransmission_count += 1;
LOG_TRACE(WARNING, "EMM-PROC - T3460 timer expired, retransmission "
"counter = %d", data->retransmission_count);
"counter = %d", data->retransmission_count);
if (data->retransmission_count < SECURITY_COUNTER_MAX) {
/* Send security mode command message to the UE */
rc = _security_request(data, FALSE);
}
else {
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the security mode control procedure */
rc = _security_abort(data);
/* Send security mode command message to the UE */
rc = _security_request(data, FALSE);
} else {
/* Set the failure notification indicator */
data->notify_failure = TRUE;
/* Abort the security mode control procedure */
rc = _security_abort(data);
}
LOG_FUNC_RETURN (NULL);
......@@ -823,27 +839,27 @@ static void* _security_t3460_handler(void* args)
/*
* --------------------------------------------------------------------------
* MME specific local functions
* MME specific local functions
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _security_request() **
** Name: _security_request() **
** **
** Description: Sends SECURITY MODE COMMAND message and start timer T3460 **
** **
** Inputs: data: Security mode control internal data **
** is_new: Indicates whether a new security context **
** has just been taken into use **
** Others: None **
** Inputs: data: Security mode control internal data **
** is_new: Indicates whether a new security context **
** has just been taken into use **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** **
***************************************************************************/
int _security_request(security_data_t* data, int is_new)
int _security_request(security_data_t *data, int is_new)
{
struct emm_data_context_s *emm_ctx = NULL;
......@@ -880,15 +896,15 @@ int _security_request(security_data_t* data, int is_new)
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3460 timer */
T3460.id = nas_timer_restart(T3460.id);
} else {
/* Start T3460 timer */
T3460.id = nas_timer_start(T3460.sec, _security_t3460_handler, data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3460 (%d) expires in %ld seconds",
T3460.id, T3460.sec);
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
/* Re-start T3460 timer */
T3460.id = nas_timer_restart(T3460.id);
} else {
/* Start T3460 timer */
T3460.id = nas_timer_start(T3460.sec, _security_t3460_handler, data);
}
LOG_TRACE(INFO,"EMM-PROC - Timer T3460 (%d) expires in %ld seconds",
T3460.id, T3460.sec);
}
LOG_FUNC_RETURN (rc);
......@@ -896,54 +912,53 @@ int _security_request(security_data_t* data, int is_new)
/****************************************************************************
** **
** Name: _security_abort() **
** Name: _security_abort() **
** **
** Description: Aborts the security mode control procedure currently in **
** progress **
** progress **
** **
** Inputs: args: Security mode control data to be released **
** Others: None **
** Inputs: args: Security mode control data to be released **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: T3460 **
** **
***************************************************************************/
static int _security_abort(void* args)
static int _security_abort(void *args)
{
LOG_FUNC_IN;
int rc = RETURNerror;
security_data_t* data = (security_data_t*)(args);
if (data)
{
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort security mode control procedure "
"(ueid=%u)", ueid);
/* Stop timer T3460 */
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3460 (%d)", T3460.id);
T3460.id = nas_timer_stop(T3460.id);
}
/* Release retransmission timer paramaters */
free(data);
/*
* Notify EMM that the security mode control procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
security_data_t *data = (security_data_t *)(args);
if (data) {
unsigned int ueid = data->ueid;
int notify_failure = data->notify_failure;
LOG_TRACE(WARNING, "EMM-PROC - Abort security mode control procedure "
"(ueid=%u)", ueid);
/* Stop timer T3460 */
if (T3460.id != NAS_TIMER_INACTIVE_ID) {
LOG_TRACE(INFO, "EMM-PROC - Stop timer T3460 (%d)", T3460.id);
T3460.id = nas_timer_stop(T3460.id);
}
/* Release retransmission timer paramaters */
free(data);
/*
* Notify EMM that the security mode control procedure failed
*/
if (notify_failure) {
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REJ;
emm_sap.u.emm_reg.ueid = ueid;
rc = emm_sap_send(&emm_sap);
} else {
rc = RETURNok;
}
}
LOG_FUNC_RETURN (rc);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source ServiceRequest.c
Source ServiceRequest.c
Version 0.1
Version 0.1
Date 2013/05/07
Date 2013/05/07
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the service request EMM procedure executed by the
Non-Access Stratum.
Description Defines the service request EMM procedure executed by the
Non-Access Stratum.
The purpose of the service request procedure is to transfer
the EMM mode from EMM-IDLE to EMM-CONNECTED mode and establish
the radio and S1 bearers when uplink user data or signalling
is to be sent.
The purpose of the service request procedure is to transfer
the EMM mode from EMM-IDLE to EMM-CONNECTED mode and establish
the radio and S1 bearers when uplink user data or signalling
is to be sent.
This procedure is used when the network has downlink signalling
pending, the UE has uplink signalling pending, the UE or the
network has user data pending and the UE is in EMM-IDLE mode.
This procedure is used when the network has downlink signalling
pending, the UE has uplink signalling pending, the UE or the
network has user data pending and the UE is in EMM-IDLE mode.
*****************************************************************************/
......@@ -46,19 +46,19 @@ Description Defines the service request EMM procedure executed by the
/*
* --------------------------------------------------------------------------
* Internal data handled by the service request procedure in the UE
* Internal data handled by the service request procedure in the UE
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
/*
* Timer handlers
*/
void* _emm_service_t3417_handler(void*);
void *_emm_service_t3417_handler(void *);
#endif // NAS_UE
/*
* --------------------------------------------------------------------------
* Internal data handled by the service request procedure in the MME
* Internal data handled by the service request procedure in the MME
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
......@@ -75,27 +75,27 @@ void* _emm_service_t3417_handler(void*);
#ifdef NAS_UE
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _emm_service_t3417_handler() **
** Name: _emm_service_t3417_handler() **
** **
** Description: T3417 timeout handler **
** **
** 3GPP TS 24.301, section 5.6.1.6 case c **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
void* _emm_service_t3417_handler(void* args)
void *_emm_service_t3417_handler(void *args)
{
LOG_FUNC_IN;
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source TrackingAreaUpdate.c
Source TrackingAreaUpdate.c
Version 0.1
Version 0.1
Date 2013/05/07
Date 2013/05/07
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the tracking area update EMM procedure executed by the
Non-Access Stratum.
Description Defines the tracking area update EMM procedure executed by the
Non-Access Stratum.
The tracking area updating procedure is always initiated by the
UE and is used to update the registration of the actual tracking
area of a UE in the network, to periodically notify the availa-
bility of the UE to the network, for MME load balancing, to up-
date certain UE specific parameters in the network.
The tracking area updating procedure is always initiated by the
UE and is used to update the registration of the actual tracking
area of a UE in the network, to periodically notify the availa-
bility of the UE to the network, for MME load balancing, to up-
date certain UE specific parameters in the network.
*****************************************************************************/
......@@ -50,7 +50,7 @@ Description Defines the tracking area update EMM procedure executed by the
/*
* Timer handlers
*/
void* _emm_tau_t3430_handler(void*);
void *_emm_tau_t3430_handler(void *);
#endif // NAS_UE
/*
......@@ -72,27 +72,27 @@ void* _emm_tau_t3430_handler(void*);
#ifdef NAS_UE
/*
* --------------------------------------------------------------------------
* Timer handlers
* Timer handlers
* --------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _emm_tau_t3430_handler() **
** Name: _emm_tau_t3430_handler() **
** **
** Description: T3430 timeout handler **
** **
** 3GPP TS 24.301, section 5.5.3.2.6 case c **
** **
** Inputs: args: handler parameters **
** Others: None **
** Inputs: args: handler parameters **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
void* _emm_tau_t3430_handler(void* args)
void *_emm_tau_t3430_handler(void *args)
{
LOG_FUNC_IN;
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source emmData.h
Source emmData.h
Version 0.1
Version 0.1
Date 2012/10/18
Date 2012/10/18
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines internal private data handled by EPS Mobility
Management sublayer.
Description Defines internal private data handled by EPS Mobility
Management sublayer.
*****************************************************************************/
#ifndef __EMMDATA_H__
......@@ -45,37 +45,37 @@ Description Defines internal private data handled by EPS Mobility
* The name of the file used as non-volatile memory device to store
* persistent EMM data when the UE is switched off
*/
#define EMM_NVRAM_FILENAME ".ue_emm.nvram"
#define EMM_NVRAM_FILENAME ".ue_emm.nvram"
/*
* The name of the environment variable which defines the directory
* where the EMM data file is located
*/
#define EMM_NVRAM_DIRNAME "NVRAM_DIR"
#define EMM_NVRAM_DIRNAME "NVRAM_DIR"
/* Network selection modes of operation */
#define EMM_DATA_PLMN_AUTO NET_PLMN_AUTO
#define EMM_DATA_PLMN_MANUAL NET_PLMN_MANUAL
#define EMM_DATA_PLMN_AUTO NET_PLMN_AUTO
#define EMM_DATA_PLMN_MANUAL NET_PLMN_MANUAL
#endif // NAS_UE
/* Checks Mobile Country Code equality */
#define MCCS_ARE_EQUAL(n1, n2) (((n1).MCCdigit1 == (n2).MCCdigit1) && \
((n1).MCCdigit2 == (n2).MCCdigit2) && \
((n1).MCCdigit3 == (n2).MCCdigit3))
#define MCCS_ARE_EQUAL(n1, n2) (((n1).MCCdigit1 == (n2).MCCdigit1) && \
((n1).MCCdigit2 == (n2).MCCdigit2) && \
((n1).MCCdigit3 == (n2).MCCdigit3))
/* Checks Mobile Network Code equality */
#define MNCS_ARE_EQUAL(n1, n2) (((n1).MNCdigit1 == (n2).MNCdigit1) && \
((n1).MNCdigit2 == (n2).MNCdigit2) && \
((n1).MNCdigit3 == (n2).MNCdigit3))
#define MNCS_ARE_EQUAL(n1, n2) (((n1).MNCdigit1 == (n2).MNCdigit1) && \
((n1).MNCdigit2 == (n2).MNCdigit2) && \
((n1).MNCdigit3 == (n2).MNCdigit3))
/* Checks PLMNs equality */
#define PLMNS_ARE_EQUAL(p1, p2) ((MCCS_ARE_EQUAL((p1),(p2))) && \
(MNCS_ARE_EQUAL((p1),(p2))))
#define PLMNS_ARE_EQUAL(p1, p2) ((MCCS_ARE_EQUAL((p1),(p2))) && \
(MNCS_ARE_EQUAL((p1),(p2))))
/* Checks TAIs equality */
#define TAIS_ARE_EQUAL(t1, t2) ((PLMNS_ARE_EQUAL((t1).plmn,(t2).plmn)) && \
((t1).tac == (t2).tac))
#define TAIS_ARE_EQUAL(t1, t2) ((PLMNS_ARE_EQUAL((t1).plmn,(t2).plmn)) && \
((t1).tac == (t2).tac))
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
......@@ -96,21 +96,21 @@ typedef enum {
/* EPS NAS security context structure */
typedef struct {
emm_ksi_t type; /* Type of security context */
int eksi; /* NAS key set identifier for E-UTRAN */
OctetString kasme; /* ASME security key (native context) */
//OctetString ksgsn; /* SGSN security key (mapped context) */
OctetString knas_enc; /* NAS cyphering key */
OctetString knas_int; /* NAS integrity key */
emm_ksi_t type; /* Type of security context */
int eksi; /* NAS key set identifier for E-UTRAN */
OctetString kasme; /* ASME security key (native context) */
//OctetString ksgsn; /* SGSN security key (mapped context) */
OctetString knas_enc; /* NAS cyphering key */
OctetString knas_int; /* NAS integrity key */
struct {
UInt32_t spare:8;
UInt32_t overflow:16;
UInt32_t seq_num:8;
} dl_count, ul_count; /* Downlink and uplink count parameters */
UInt32_t spare:8;
UInt32_t overflow:16;
UInt32_t seq_num:8;
} dl_count, ul_count; /* Downlink and uplink count parameters */
struct {
UInt8_t encryption:4; /* algorithm used for ciphering */
UInt8_t integrity:4; /* algorithm used for integrity protection */
} capability; /* UE network capability */
UInt8_t encryption:4; /* algorithm used for ciphering */
UInt8_t integrity:4; /* algorithm used for integrity protection */
} capability; /* UE network capability */
} emm_security_context_t;
/*
......@@ -129,11 +129,11 @@ typedef struct {
*
* EU1: The last attach or tracking area updating attempt was successful.
* EU2: The last attach, service request or tracking area updating attempt
* failed procedurally, i.e. no response or reject message was received
* from the MME.
* failed procedurally, i.e. no response or reject message was received
* from the MME.
* EU3: The last attach, service request or tracking area updating attempt
* was correctly performed, but the answer from the MME was negative
* (because of roaming or subscription restrictions).
* was correctly performed, but the answer from the MME was negative
* (because of roaming or subscription restrictions).
*/
typedef enum {
EU1_UPDATED,
......@@ -144,10 +144,10 @@ typedef enum {
/*
* EPS Connection Management states
* --------------------------------
* ECM-IDLE: No NAS signalling connection between UE and network exists.
* No UE context exists in the network.
* ECM-IDLE: No NAS signalling connection between UE and network exists.
* No UE context exists in the network.
* ECM-CONNECTED: The signalling connection is established between the UE
* and the MME (RRC connection and S1_MME connection).
* and the MME (RRC connection and S1_MME connection).
*/
typedef enum {
ECM_IDLE,
......@@ -171,9 +171,9 @@ typedef enum {
*/
typedef struct {
imsi_t imsi;
plmn_t rplmn; /* The registered PLMN */
/* List of equivalent PLMNs */
#define EMM_DATA_EPLMN_MAX 16
plmn_t rplmn; /* The registered PLMN */
/* List of equivalent PLMNs */
#define EMM_DATA_EPLMN_MAX 16
PLMN_LIST_T(EMM_DATA_EPLMN_MAX) eplmn;
} emm_nvdata_t;
......@@ -182,17 +182,17 @@ typedef struct {
* -------------------------
*/
typedef struct {
int usim_is_valid; /* Indication of USIM data validity */
int usim_is_valid; /* Indication of USIM data validity */
imei_t *imei; /* IMEI read from the UE's non-volatile memory */
const imsi_t *imsi; /* The valid IMSI read from the USIM */
GUTI_t *guti; /* The valid GUTI read from the USIM */
tai_t *tai; /* Last visited registered Tracking Area Id */
imei_t *imei; /* IMEI read from the UE's non-volatile memory */
const imsi_t *imsi; /* The valid IMSI read from the USIM */
GUTI_t *guti; /* The valid GUTI read from the USIM */
tai_t *tai; /* Last visited registered Tracking Area Id */
emm_eps_update_t status; /* The current EPS update status */
emm_ecm_state_t ecm_status; /* The EPS Connection Management status */
int is_attached; /* Network attachment indicator */
int is_emergency; /* Emergency bearer services indicator */
emm_eps_update_t status; /* The current EPS update status */
emm_ecm_state_t ecm_status; /* The EPS Connection Management status */
int is_attached; /* Network attachment indicator */
int is_emergency; /* Emergency bearer services indicator */
/* Tracking Areas list the UE is registered to
* Contains the list of TAIs that identify the tracking areas that
......@@ -200,84 +200,84 @@ typedef struct {
* procedure. The TAIs in a TAI list assigned by an MME to a UE
* pertain to the same MME area.
*/
#define EMM_DATA_TAI_MAX 16
#define EMM_DATA_TAI_MAX 16
TAI_LIST_T(EMM_DATA_TAI_MAX) ltai;
int plmn_mode; /* Network selection operating mode */
int plmn_index; /* Manually selected PLMN */
int plmn_rat; /* Manually selected Radio Access Technology */
int plmn_mode; /* Network selection operating mode */
int plmn_index; /* Manually selected PLMN */
int plmn_rat; /* Manually selected Radio Access Technology */
plmn_t splmn; /* The currently selected PLMN */
int is_rplmn; /* splmn is the registered PLMN */
int is_eplmn; /* splmn is in the list of equivalent PLMNs */
Stat_t stat; /* Current network registration status */
tac_t tac; /* Tracking area code */
ci_t ci; /* GERAN/UTRAN/E-UTRAN serving cell identifier */
AcT_t rat; /* Radio Access Technology of the serving cell */
plmn_t splmn; /* The currently selected PLMN */
int is_rplmn; /* splmn is the registered PLMN */
int is_eplmn; /* splmn is in the list of equivalent PLMNs */
Stat_t stat; /* Current network registration status */
tac_t tac; /* Tracking area code */
ci_t ci; /* GERAN/UTRAN/E-UTRAN serving cell identifier */
AcT_t rat; /* Radio Access Technology of the serving cell */
/* An octet string representation of operators present in the network */
struct {
#define EMM_DATA_BUFFER_SIZE 2048
char buffer[EMM_DATA_BUFFER_SIZE+1];
#define EMM_DATA_BUFFER_SIZE 2048
char buffer[EMM_DATA_BUFFER_SIZE+1];
} plist;
/*
* Data used for PLMN selection procedure
* --------------------------------------
*/
plmn_t hplmn; /* The Home PLMN derived from the IMSI */
/* List of Forbidden PLMNs
* Contains the list of PLMN identities for which a Location
* Registration has been rejected with EMM cause code #11 (PLMN
* not allowed). A PLMN is removed from this list if, after a
* subsequent manual selection of that PLMN, there is a successful
* Location Request. */
#define EMM_DATA_FPLMN_MAX 4
plmn_t hplmn; /* The Home PLMN derived from the IMSI */
/* List of Forbidden PLMNs
* Contains the list of PLMN identities for which a Location
* Registration has been rejected with EMM cause code #11 (PLMN
* not allowed). A PLMN is removed from this list if, after a
* subsequent manual selection of that PLMN, there is a successful
* Location Request. */
#define EMM_DATA_FPLMN_MAX 4
PLMN_LIST_T(EMM_DATA_FPLMN_MAX) fplmn;
/* List of Forbidden PLMNs for GPRS service
* Contains the list of PLMN identities for which an Attach Request
* has been rejected with EMM cause code #14 (GPRS/EPS services not
* allowed in this PLMN). A PLMN is removed from this list if, after
* a subsequent manual selection of that PLMN, there is a successful
* GPRS attach or EPS attach. */
#define EMM_DATA_FPLMN_GPRS_MAX 4
/* List of Forbidden PLMNs for GPRS service
* Contains the list of PLMN identities for which an Attach Request
* has been rejected with EMM cause code #14 (GPRS/EPS services not
* allowed in this PLMN). A PLMN is removed from this list if, after
* a subsequent manual selection of that PLMN, there is a successful
* GPRS attach or EPS attach. */
#define EMM_DATA_FPLMN_GPRS_MAX 4
PLMN_LIST_T(EMM_DATA_FPLMN_GPRS_MAX) fplmn_gprs;
/* List of Equivalent HPLMNs */
#define EMM_DATA_EHPLMN_MAX 4
/* List of Equivalent HPLMNs */
#define EMM_DATA_EHPLMN_MAX 4
PLMN_LIST_T(EMM_DATA_EHPLMN_MAX) ehplmn;
/* List of user controlled PLMNs */
#define EMM_DATA_PLMN_MAX 4
/* List of user controlled PLMNs */
#define EMM_DATA_PLMN_MAX 4
PLMN_LIST_T(EMM_DATA_PLMN_MAX) plmn;
UInt16_t userAcT[EMM_DATA_PLMN_MAX];
/* List of operator controlled PLMNs */
#define EMM_DATA_OPLMN_MAX 4
/* List of operator controlled PLMNs */
#define EMM_DATA_OPLMN_MAX 4
PLMN_LIST_T(EMM_DATA_OPLMN_MAX) oplmn;
UInt16_t operAcT[EMM_DATA_OPLMN_MAX];
/* List of operator network name records */
#define EMM_DATA_OPNN_MAX 16
/* List of operator network name records */
#define EMM_DATA_OPNN_MAX 16
UInt8_t n_opnns;
struct {
const plmn_t *plmn;
const char *fullname;
const char *shortname;
const plmn_t *plmn;
const char *fullname;
const char *shortname;
} opnn[EMM_DATA_OPNN_MAX];
/*
* Data used for roaming service
* -----------------------------
*/
/* List of Forbidden Tracking Areas
* Contains the list of TAIs for which an attach request has been
* rejected with EMM cause code #12 (tracking area not allowed).
*/
#define EMM_DATA_FTAI_MAX 40
/* List of Forbidden Tracking Areas
* Contains the list of TAIs for which an attach request has been
* rejected with EMM cause code #12 (tracking area not allowed).
*/
#define EMM_DATA_FTAI_MAX 40
TAI_LIST_T(EMM_DATA_FTAI_MAX) ftai;
/* List of Forbidden Tracking Areas for roaming
* Contains the list of TAIs for which an attach request has been
* rejected with EMM cause code #13 (roaming not allowed in this
* tracking area).
*/
#define EMM_DATA_FTAI_ROAMING_MAX 40
/* List of Forbidden Tracking Areas for roaming
* Contains the list of TAIs for which an attach request has been
* rejected with EMM cause code #13 (roaming not allowed in this
* tracking area).
*/
#define EMM_DATA_FTAI_ROAMING_MAX 40
TAI_LIST_T(EMM_DATA_FTAI_ROAMING_MAX) ftai_roaming;
/*
......@@ -302,8 +302,8 @@ typedef struct {
* EPS NAS security context
* ------------------------
*/
emm_security_context_t* security; /* current security context */
emm_security_context_t* non_current; /* non-current security context */
emm_security_context_t *security; /* current security context */
emm_security_context_t *non_current; /* non-current security context */
} emm_data_t;
......@@ -320,28 +320,28 @@ typedef struct {
* ---------------------------------------------------------------------------
*/
typedef struct emm_data_context_s {
unsigned int ueid; /* UE identifier */
int is_dynamic; /* Dynamically allocated context indicator */
int is_attached; /* Attachment indicator */
int is_emergency; /* Emergency bearer services indicator */
imsi_t* imsi; /* The IMSI provided by the UE or the MME */
imei_t* imei; /* The IMEI provided by the UE */
int guti_is_new; /* New GUTI indicator */
GUTI_t* guti; /* The GUTI assigned to the UE */
GUTI_t* old_guti; /* The old GUTI */
int n_tacs; /* Number of concecutive tracking areas the UE is
* registered to */
tac_t tac; /* Code of the first tracking area the UE is
* registered to */
int ksi; /* Security key set identifier provided by the UE */
int eea; /* EPS encryption algorithms supported by the UE */
int eia; /* EPS integrity algorithms supported by the UE */
auth_vector_t vector; /* EPS authentication vector */
emm_security_context_t* security; /* Current EPS NAS security context */
unsigned int ueid; /* UE identifier */
int is_dynamic; /* Dynamically allocated context indicator */
int is_attached; /* Attachment indicator */
int is_emergency; /* Emergency bearer services indicator */
imsi_t *imsi; /* The IMSI provided by the UE or the MME */
imei_t *imei; /* The IMEI provided by the UE */
int guti_is_new; /* New GUTI indicator */
GUTI_t *guti; /* The GUTI assigned to the UE */
GUTI_t *old_guti; /* The old GUTI */
int n_tacs; /* Number of concecutive tracking areas the UE is
* registered to */
tac_t tac; /* Code of the first tracking area the UE is
* registered to */
int ksi; /* Security key set identifier provided by the UE */
int eea; /* EPS encryption algorithms supported by the UE */
int eia; /* EPS integrity algorithms supported by the UE */
auth_vector_t vector; /* EPS authentication vector */
emm_security_context_t *security; /* Current EPS NAS security context */
OctetString esm_msg; /* ESM message contained within the initial request */
int emm_cause; /* EMM failure cause code */
int emm_cause; /* EMM failure cause code */
emm_fsm_state_t _emm_fsm_status;
......@@ -368,15 +368,15 @@ typedef struct {
/* Use a tree for ue data context within MME */
RB_HEAD(emm_data_context_map, emm_data_context_s) ctx_map;
# else
# define EMM_DATA_NB_UE_MAX (MME_API_NB_UE_MAX + 1)
emm_data_context_t* ctx [EMM_DATA_NB_UE_MAX];
# define EMM_DATA_NB_UE_MAX (MME_API_NB_UE_MAX + 1)
emm_data_context_t *ctx [EMM_DATA_NB_UE_MAX];
# endif
} emm_data_t;
struct emm_data_context_s *emm_data_context_get(
emm_data_t *_emm_data, unsigned int _ueid);
struct emm_data_context_s * emm_data_context_remove(
struct emm_data_context_s *emm_data_context_remove(
emm_data_t *_emm_data, struct emm_data_context_s *elm);
void emm_data_context_add(emm_data_t *emm_data, struct emm_data_context_s *elm);
......@@ -389,58 +389,58 @@ void emm_data_context_add(emm_data_t *emm_data, struct emm_data_context_s *elm);
/*
* --------------------------------------------------------------------------
* EPS mobility management data (used within EMM only)
* EPS mobility management data (used within EMM only)
* --------------------------------------------------------------------------
*/
emm_data_t _emm_data;
/*
* --------------------------------------------------------------------------
* EPS mobility management timers – UE side
* EPS mobility management timers – UE side
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
#define T3402_DEFAULT_VALUE 720 /* 12 minutes */
#define T3410_DEFAULT_VALUE 15 /* 15 seconds */
#define T3411_DEFAULT_VALUE 10 /* 10 seconds */
#define T3412_DEFAULT_VALUE 3240 /* 54 minutes */
#define T3416_DEFAULT_VALUE 30 /* 30 seconds */
#define T3417_DEFAULT_VALUE 5 /* 5 seconds */
#define T3417ext_DEFAULT_VALUE 10 /* 10 seconds */
#define T3418_DEFAULT_VALUE 20 /* 20 seconds */
#define T3420_DEFAULT_VALUE 15 /* 15 seconds */
#define T3421_DEFAULT_VALUE 15 /* 15 seconds */
#define T3423_DEFAULT_VALUE T3412_DEFAULT_VALUE
#define T3430_DEFAULT_VALUE 15 /* 15 seconds */
#define T3440_DEFAULT_VALUE 10 /* 10 seconds */
struct nas_timer_t T3402; /* attach failure timer */
struct nas_timer_t T3410; /* attach timer */
struct nas_timer_t T3411; /* attach restart timer */
struct nas_timer_t T3412; /* periodic tracking area update timer */
struct nas_timer_t T3416; /* EPS authentication challenge timer */
struct nas_timer_t T3417; /* Service request timer */
struct nas_timer_t T3418; /* MAC authentication failure timer */
struct nas_timer_t T3420; /* Synch authentication failure timer */
struct nas_timer_t T3421; /* Detach timer */
struct nas_timer_t T3430; /* tracking area update timer */
struct nas_timer_t T3423; /* E-UTRAN deactivate ISR timer */
#define T3402_DEFAULT_VALUE 720 /* 12 minutes */
#define T3410_DEFAULT_VALUE 15 /* 15 seconds */
#define T3411_DEFAULT_VALUE 10 /* 10 seconds */
#define T3412_DEFAULT_VALUE 3240 /* 54 minutes */
#define T3416_DEFAULT_VALUE 30 /* 30 seconds */
#define T3417_DEFAULT_VALUE 5 /* 5 seconds */
#define T3417ext_DEFAULT_VALUE 10 /* 10 seconds */
#define T3418_DEFAULT_VALUE 20 /* 20 seconds */
#define T3420_DEFAULT_VALUE 15 /* 15 seconds */
#define T3421_DEFAULT_VALUE 15 /* 15 seconds */
#define T3423_DEFAULT_VALUE T3412_DEFAULT_VALUE
#define T3430_DEFAULT_VALUE 15 /* 15 seconds */
#define T3440_DEFAULT_VALUE 10 /* 10 seconds */
struct nas_timer_t T3402; /* attach failure timer */
struct nas_timer_t T3410; /* attach timer */
struct nas_timer_t T3411; /* attach restart timer */
struct nas_timer_t T3412; /* periodic tracking area update timer */
struct nas_timer_t T3416; /* EPS authentication challenge timer */
struct nas_timer_t T3417; /* Service request timer */
struct nas_timer_t T3418; /* MAC authentication failure timer */
struct nas_timer_t T3420; /* Synch authentication failure timer */
struct nas_timer_t T3421; /* Detach timer */
struct nas_timer_t T3430; /* tracking area update timer */
struct nas_timer_t T3423; /* E-UTRAN deactivate ISR timer */
#endif
/*
* --------------------------------------------------------------------------
* EPS mobility management timers – Network side
* EPS mobility management timers – Network side
* --------------------------------------------------------------------------
*/
#ifdef NAS_MME
#define T3450_DEFAULT_VALUE 6 /* 6 seconds */
#define T3460_DEFAULT_VALUE 6 /* 6 seconds */
#define T3470_DEFAULT_VALUE 6 /* 6 seconds */
#define T3450_DEFAULT_VALUE 6 /* 6 seconds */
#define T3460_DEFAULT_VALUE 6 /* 6 seconds */
#define T3470_DEFAULT_VALUE 6 /* 6 seconds */
struct nas_timer_t T3450; /* EMM message retransmission timer */
struct nas_timer_t T3460; /* Authentication timer */
struct nas_timer_t T3470; /* Identification timer */
struct nas_timer_t T3450; /* EMM message retransmission timer */
struct nas_timer_t T3460; /* Authentication timer */
struct nas_timer_t T3470; /* Identification timer */
/*
* mobile reachable timer
......
......@@ -45,7 +45,7 @@ struct emm_data_context_s *emm_data_context_get(
return RB_FIND(emm_data_context_map, &emm_data->ctx_map, &reference);
}
struct emm_data_context_s * emm_data_context_remove(
struct emm_data_context_s *emm_data_context_remove(
emm_data_t *emm_data, struct emm_data_context_s *elm)
{
return RB_REMOVE(emm_data_context_map, &emm_data->ctx_map, elm);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source emm_main.c
Source emm_main.c
Version 0.1
Version 0.1
Date 2012/10/10
Date 2012/10/10
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the EPS Mobility Management procedure call manager,
the main entry point for elementary EMM processing.
Description Defines the EPS Mobility Management procedure call manager,
the main entry point for elementary EMM processing.
*****************************************************************************/
......@@ -28,9 +28,9 @@ Description Defines the EPS Mobility Management procedure call manager,
#include "usim_api.h"
#include "IdleMode.h"
#include <string.h> // memset, memcpy, strlen
#include <stdio.h> // sprintf
#include <stdlib.h> // malloc, free
#include <string.h> // memset, memcpy, strlen
#include <stdio.h> // sprintf
#include <stdlib.h> // malloc, free
#endif
/****************************************************************************/
......@@ -42,14 +42,14 @@ Description Defines the EPS Mobility Management procedure call manager,
/****************************************************************************/
#ifdef NAS_UE
static int _emm_main_get_imei(imei_t* imei, const char* imei_str);
static int _emm_main_get_imei(imei_t *imei, const char *imei_str);
static int _emm_main_imsi_cmp(imsi_t* imsi1, imsi_t* imsi2);
static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2);
static const char* _emm_main_get_plmn(const plmn_t* plmn, int index,
int format, size_t* size);
static const char *_emm_main_get_plmn(const plmn_t *plmn, int index,
int format, size_t *size);
static int _emm_main_get_plmn_index(const char* plmn, int format);
static int _emm_main_get_plmn_index(const char *plmn, int format);
/*
* USIM application data
......@@ -71,28 +71,28 @@ static int _emm_main_callback(int);
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_main_initialize() **
** Name: emm_main_initialize() **
** **
** Description: Initializes EMM internal data **
** **
** Inputs: cb: The user notification callback **
** imei: The IMEI read from the UE's non-volatile **
** memory **
** Others: _usim_data **
** Inputs: cb: The user notification callback **
** imei: The IMEI read from the UE's non-volatile **
** memory **
** Others: _usim_data **
** **
** Outputs: None **
** Return: None **
** Others: _emm_data **
** Outputs: None **
** Return: None **
** Others: _emm_data **
** **
***************************************************************************/
void emm_main_initialize(emm_indication_callback_t cb, const char* imei)
void emm_main_initialize(emm_indication_callback_t cb, const char *imei)
{
LOG_FUNC_IN;
/* USIM validity indicator */
_emm_data.usim_is_valid = FALSE;
/* The IMEI read from the UE's non-volatile memory */
_emm_data.imei = (imei_t*)malloc(sizeof(imei_t));
/* The IMEI read from the UE's non-volatile memory */
_emm_data.imei = (imei_t *)malloc(sizeof(imei_t));
_emm_data.imei->length = _emm_main_get_imei(_emm_data.imei, imei);
/* The IMSI, valid only if USIM is present */
_emm_data.imsi = NULL;
......@@ -119,9 +119,9 @@ void emm_main_initialize(emm_indication_callback_t cb, const char* imei)
_emm_data.is_attached = FALSE;
_emm_data.is_emergency = FALSE;
/* Location/Tracking area code */
_emm_data.tac = 0; // two byte in hexadecimal format
_emm_data.tac = 0; // two byte in hexadecimal format
/* Identifier of the serving cell */
_emm_data.ci = 0; // four byte in hexadecimal format
_emm_data.ci = 0; // four byte in hexadecimal format
/* List of operators present in the network */
memset(_emm_data.plist.buffer, 0, EMM_DATA_BUFFER_SIZE + 1);
/* Home PLMN */
......@@ -147,172 +147,187 @@ void emm_main_initialize(emm_indication_callback_t cb, const char* imei)
* Get USIM application data
*/
if ( usim_api_read(&_usim_data) != RETURNok ) {
/* The USIM application may not be present or not valid */
LOG_TRACE(WARNING, "EMM-MAIN - Failed to read USIM application data");
}
else
{
int i;
/* The USIM application is present and valid */
LOG_TRACE(INFO, "EMM-MAIN - USIM application data successfully read");
_emm_data.usim_is_valid = TRUE;
/* Get the Home PLMN derived from the IMSI */
_emm_data.hplmn.MCCdigit1 = _usim_data.imsi.u.num.digit1;
_emm_data.hplmn.MCCdigit2 = _usim_data.imsi.u.num.digit2;
_emm_data.hplmn.MCCdigit3 = _usim_data.imsi.u.num.digit3;
_emm_data.hplmn.MNCdigit1 = _usim_data.imsi.u.num.digit4;
_emm_data.hplmn.MNCdigit2 = _usim_data.imsi.u.num.digit5;
_emm_data.hplmn.MNCdigit3 = _usim_data.imsi.u.num.digit6;
/* Get the list of forbidden PLMNs */
for (i=0; (i < EMM_DATA_FPLMN_MAX) && (i < USIM_FPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.fplmn[i]) ) {
_emm_data.fplmn.plmn[i] = _usim_data.fplmn[i];
_emm_data.fplmn.n_plmns += 1;
}
}
/* Get the list of Equivalent HPLMNs */
for (i=0; (i < EMM_DATA_EHPLMN_MAX) && (i < USIM_EHPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.ehplmn[i]) ) {
_emm_data.ehplmn.plmn[i] = _usim_data.ehplmn[i];
_emm_data.ehplmn.n_plmns += 1;
}
}
/* Get the list of User controlled PLMN Selector */
for (i=0; (i < EMM_DATA_PLMN_MAX) && (i < USIM_PLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.plmn[i].plmn) ) {
_emm_data.plmn.plmn[i] = _usim_data.plmn[i].plmn;
_emm_data.userAcT[i] = _usim_data.plmn[i].AcT;
_emm_data.plmn.n_plmns += 1;
}
}
/* Get the list of Operator controlled PLMN Selector */
for (i=0; (i < EMM_DATA_OPLMN_MAX) && (i < USIM_OPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.oplmn[i].plmn) ) {
_emm_data.oplmn.plmn[i] = _usim_data.oplmn[i].plmn;
_emm_data.operAcT[i] = _usim_data.oplmn[i].AcT;
_emm_data.oplmn.n_plmns += 1;
}
}
/* Get the list of Operator network name records */
for (i=0; (i < EMM_DATA_OPNN_MAX) && (i < USIM_OPL_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.opl[i].plmn) ) {
int pnn_id = _usim_data.opl[i].record_id;
_emm_data.opnn[i].plmn = &_usim_data.opl[i].plmn;
_emm_data.opnn[i].fullname = (char*)_usim_data.pnn[pnn_id].fullname.value;
_emm_data.opnn[i].shortname = (char*)_usim_data.pnn[pnn_id].shortname.value;
_emm_data.n_opnns += 1;
}
}
/* TODO: Get the Higher Priority PLMN search period parameter */
/* Get the EPS location information */
if (PLMN_IS_VALID(_usim_data.epsloci.guti.gummei.plmn)) {
_emm_data.guti = &_usim_data.epsloci.guti;
}
if (TAI_IS_VALID(_usim_data.epsloci.tai)) {
_emm_data.tai = &_usim_data.epsloci.tai;
}
_emm_data.status = _usim_data.epsloci.status;
/* Get NAS configuration parameters */
_emm_data.NAS_SignallingPriority = _usim_data.nasconfig.NAS_SignallingPriority.value[0];
_emm_data.NMO_I_Behaviour = _usim_data.nasconfig.NMO_I_Behaviour.value[0];
_emm_data.AttachWithImsi = _usim_data.nasconfig.AttachWithImsi.value[0];
_emm_data.MinimumPeriodicSearchTimer = _usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0];
_emm_data.ExtendedAccessBarring = _usim_data.nasconfig.ExtendedAccessBarring.value[0];
_emm_data.Timer_T3245_Behaviour = _usim_data.nasconfig.Timer_T3245_Behaviour.value[0];
/*
* Get EPS NAS security context
*/
/* Create NAS security context */
_emm_data.security =
(emm_security_context_t*)malloc(sizeof(emm_security_context_t));
if (_emm_data.security != NULL) {
memset(_emm_data.security, 0, sizeof(emm_security_context_t));
/* Type of security context */
if (_usim_data.securityctx.KSIasme.value[0] !=
USIM_KSI_NOT_AVAILABLE) {
_emm_data.security->type = EMM_KSI_NATIVE;
}
else {
_emm_data.security->type = EMM_KSI_NOT_AVAILABLE;
}
/* EPS key set identifier */
_emm_data.security->eksi = _usim_data.securityctx.KSIasme.value[0];
/* ASME security key */
_emm_data.security->kasme.length =
_usim_data.securityctx.Kasme.length;
_emm_data.security->kasme.value =
(uint8_t*)malloc(_emm_data.security->kasme.length);
if (_emm_data.security->kasme.value) {
memcpy(_emm_data.security->kasme.value,
_usim_data.securityctx.Kasme.value,
_emm_data.security->kasme.length);
}
/* Downlink count parameter */
if (_usim_data.securityctx.dlNAScount.length <= sizeof(UInt32_t)) {
memcpy(&_emm_data.security->dl_count,
_usim_data.securityctx.dlNAScount.value,
_usim_data.securityctx.dlNAScount.length);
}
/* Uplink count parameter */
if (_usim_data.securityctx.ulNAScount.length <= sizeof(UInt32_t)) {
memcpy(&_emm_data.security->ul_count,
_usim_data.securityctx.ulNAScount.value,
_usim_data.securityctx.ulNAScount.length);
}
/* Ciphering algorithm */
_emm_data.security->capability.encryption =
((_usim_data.securityctx.algorithmID.value[0] >> 4) & 0xf);
/* Identity protection algorithm */
_emm_data.security->capability.integrity =
(_usim_data.securityctx.algorithmID.value[0] & 0xf);
/* NAS integrity and cyphering keys are not available */
}
else {
LOG_TRACE(WARNING,
"EMM-PROC - Failed to create security context");
}
/*
* Get EMM data from the UE's non-volatile memory
*/
memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t));
_emm_data.nvdata.eplmn.n_plmns = 0;
/* Get EMM data pathname */
char* path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME);
if (path == NULL) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname");
}
else {
/* Get EMM data stored in the non-volatile memory device */
int rc = memory_read(path, &_emm_data.nvdata, sizeof(emm_nvdata_t));
if (rc != RETURNok) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to read %s", path);
}
else {
/* Check the IMSI */
LOG_TRACE(INFO, "EMM-MAIN - EMM data successfully read");
_emm_data.imsi = &_usim_data.imsi;
int imsi_ok = _emm_main_imsi_cmp(&_emm_data.nvdata.imsi,
&_usim_data.imsi);
if (!imsi_ok) {
LOG_TRACE(WARNING, "EMM-MAIN - IMSI checking failed");
memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t));
_emm_data.nvdata.eplmn.n_plmns = 0;
}
}
free(path);
}
/* The USIM application may not be present or not valid */
LOG_TRACE(WARNING, "EMM-MAIN - Failed to read USIM application data");
} else {
int i;
/* The USIM application is present and valid */
LOG_TRACE(INFO, "EMM-MAIN - USIM application data successfully read");
_emm_data.usim_is_valid = TRUE;
/* Get the Home PLMN derived from the IMSI */
_emm_data.hplmn.MCCdigit1 = _usim_data.imsi.u.num.digit1;
_emm_data.hplmn.MCCdigit2 = _usim_data.imsi.u.num.digit2;
_emm_data.hplmn.MCCdigit3 = _usim_data.imsi.u.num.digit3;
_emm_data.hplmn.MNCdigit1 = _usim_data.imsi.u.num.digit4;
_emm_data.hplmn.MNCdigit2 = _usim_data.imsi.u.num.digit5;
_emm_data.hplmn.MNCdigit3 = _usim_data.imsi.u.num.digit6;
/* Get the list of forbidden PLMNs */
for (i=0; (i < EMM_DATA_FPLMN_MAX) && (i < USIM_FPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.fplmn[i]) ) {
_emm_data.fplmn.plmn[i] = _usim_data.fplmn[i];
_emm_data.fplmn.n_plmns += 1;
}
}
/* Get the list of Equivalent HPLMNs */
for (i=0; (i < EMM_DATA_EHPLMN_MAX) && (i < USIM_EHPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.ehplmn[i]) ) {
_emm_data.ehplmn.plmn[i] = _usim_data.ehplmn[i];
_emm_data.ehplmn.n_plmns += 1;
}
}
/* Get the list of User controlled PLMN Selector */
for (i=0; (i < EMM_DATA_PLMN_MAX) && (i < USIM_PLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.plmn[i].plmn) ) {
_emm_data.plmn.plmn[i] = _usim_data.plmn[i].plmn;
_emm_data.userAcT[i] = _usim_data.plmn[i].AcT;
_emm_data.plmn.n_plmns += 1;
}
}
/* Get the list of Operator controlled PLMN Selector */
for (i=0; (i < EMM_DATA_OPLMN_MAX) && (i < USIM_OPLMN_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.oplmn[i].plmn) ) {
_emm_data.oplmn.plmn[i] = _usim_data.oplmn[i].plmn;
_emm_data.operAcT[i] = _usim_data.oplmn[i].AcT;
_emm_data.oplmn.n_plmns += 1;
}
}
/* Get the list of Operator network name records */
for (i=0; (i < EMM_DATA_OPNN_MAX) && (i < USIM_OPL_MAX); i++) {
if ( PLMN_IS_VALID(_usim_data.opl[i].plmn) ) {
int pnn_id = _usim_data.opl[i].record_id;
_emm_data.opnn[i].plmn = &_usim_data.opl[i].plmn;
_emm_data.opnn[i].fullname = (char *)_usim_data.pnn[pnn_id].fullname.value;
_emm_data.opnn[i].shortname = (char *)_usim_data.pnn[pnn_id].shortname.value;
_emm_data.n_opnns += 1;
}
}
/* TODO: Get the Higher Priority PLMN search period parameter */
/* Get the EPS location information */
if (PLMN_IS_VALID(_usim_data.epsloci.guti.gummei.plmn)) {
_emm_data.guti = &_usim_data.epsloci.guti;
}
if (TAI_IS_VALID(_usim_data.epsloci.tai)) {
_emm_data.tai = &_usim_data.epsloci.tai;
}
_emm_data.status = _usim_data.epsloci.status;
/* Get NAS configuration parameters */
_emm_data.NAS_SignallingPriority =
_usim_data.nasconfig.NAS_SignallingPriority.value[0];
_emm_data.NMO_I_Behaviour = _usim_data.nasconfig.NMO_I_Behaviour.value[0];
_emm_data.AttachWithImsi = _usim_data.nasconfig.AttachWithImsi.value[0];
_emm_data.MinimumPeriodicSearchTimer =
_usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0];
_emm_data.ExtendedAccessBarring =
_usim_data.nasconfig.ExtendedAccessBarring.value[0];
_emm_data.Timer_T3245_Behaviour =
_usim_data.nasconfig.Timer_T3245_Behaviour.value[0];
/*
* Get EPS NAS security context
*/
/* Create NAS security context */
_emm_data.security =
(emm_security_context_t *)malloc(sizeof(emm_security_context_t));
if (_emm_data.security != NULL) {
memset(_emm_data.security, 0, sizeof(emm_security_context_t));
/* Type of security context */
if (_usim_data.securityctx.KSIasme.value[0] !=
USIM_KSI_NOT_AVAILABLE) {
_emm_data.security->type = EMM_KSI_NATIVE;
} else {
_emm_data.security->type = EMM_KSI_NOT_AVAILABLE;
}
/* EPS key set identifier */
_emm_data.security->eksi = _usim_data.securityctx.KSIasme.value[0];
/* ASME security key */
_emm_data.security->kasme.length =
_usim_data.securityctx.Kasme.length;
_emm_data.security->kasme.value =
(uint8_t *)malloc(_emm_data.security->kasme.length);
if (_emm_data.security->kasme.value) {
memcpy(_emm_data.security->kasme.value,
_usim_data.securityctx.Kasme.value,
_emm_data.security->kasme.length);
}
/* Downlink count parameter */
if (_usim_data.securityctx.dlNAScount.length <= sizeof(UInt32_t)) {
memcpy(&_emm_data.security->dl_count,
_usim_data.securityctx.dlNAScount.value,
_usim_data.securityctx.dlNAScount.length);
}
/* Uplink count parameter */
if (_usim_data.securityctx.ulNAScount.length <= sizeof(UInt32_t)) {
memcpy(&_emm_data.security->ul_count,
_usim_data.securityctx.ulNAScount.value,
_usim_data.securityctx.ulNAScount.length);
}
/* Ciphering algorithm */
_emm_data.security->capability.encryption =
((_usim_data.securityctx.algorithmID.value[0] >> 4) & 0xf);
/* Identity protection algorithm */
_emm_data.security->capability.integrity =
(_usim_data.securityctx.algorithmID.value[0] & 0xf);
/* NAS integrity and cyphering keys are not available */
} else {
LOG_TRACE(WARNING,
"EMM-PROC - Failed to create security context");
}
/*
* Get EMM data from the UE's non-volatile memory
*/
memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t));
_emm_data.nvdata.eplmn.n_plmns = 0;
/* Get EMM data pathname */
char *path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME);
if (path == NULL) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname");
} else {
/* Get EMM data stored in the non-volatile memory device */
int rc = memory_read(path, &_emm_data.nvdata, sizeof(emm_nvdata_t));
if (rc != RETURNok) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to read %s", path);
} else {
/* Check the IMSI */
LOG_TRACE(INFO, "EMM-MAIN - EMM data successfully read");
_emm_data.imsi = &_usim_data.imsi;
int imsi_ok = _emm_main_imsi_cmp(&_emm_data.nvdata.imsi,
&_usim_data.imsi);
if (!imsi_ok) {
LOG_TRACE(WARNING, "EMM-MAIN - IMSI checking failed nvram: "
"%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x, "
"usim: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
_emm_data.nvdata.imsi.u.value[0],
_emm_data.nvdata.imsi.u.value[1],
_emm_data.nvdata.imsi.u.value[2],
_emm_data.nvdata.imsi.u.value[3],
_emm_data.nvdata.imsi.u.value[4],
_emm_data.nvdata.imsi.u.value[5],
_emm_data.nvdata.imsi.u.value[6],
_emm_data.nvdata.imsi.u.value[7],
_usim_data.imsi.u.value[0],
_usim_data.imsi.u.value[1],
_usim_data.imsi.u.value[2],
_usim_data.imsi.u.value[3],
_usim_data.imsi.u.value[4],
_usim_data.imsi.u.value[5],
_usim_data.imsi.u.value[6], _usim_data.imsi.u.value[7]);
memset(&_emm_data.nvdata.rplmn, 0xFF, sizeof(plmn_t));
_emm_data.nvdata.eplmn.n_plmns = 0;
}
}
free(path);
}
}
/*
......@@ -355,16 +370,16 @@ void emm_main_initialize(emm_indication_callback_t cb, const char* imei)
#ifdef NAS_MME
/****************************************************************************
** **
** Name: emm_main_initialize() **
** Name: emm_main_initialize() **
** **
** Description: Initializes EMM internal data **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: _emm_data **
** Outputs: None **
** Return: None **
** Others: _emm_data **
** **
***************************************************************************/
void emm_main_initialize(void)
......@@ -373,7 +388,7 @@ void emm_main_initialize(void)
/* Retreive MME supported configuration data */
if (mme_api_get_emm_config(&_emm_data.conf) != RETURNok) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get MME configuration data");
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get MME configuration data");
}
#if defined(EPC_BUILD)
......@@ -396,16 +411,16 @@ void emm_main_initialize(void)
/****************************************************************************
** **
** Name: emm_main_cleanup() **
** Name: emm_main_cleanup() **
** **
** Description: Performs the EPS Mobility Management clean up procedure **
** **
** Inputs: None **
** Others: None **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: None **
** Others: None **
** Outputs: None **
** Return: None **
** Others: None **
** **
***************************************************************************/
void emm_main_cleanup(void)
......@@ -415,47 +430,44 @@ void emm_main_cleanup(void)
#ifdef NAS_UE
if (_emm_data.usim_is_valid) {
/*
* TODO: Update USIM application data
*/
/*
* TODO: Update USIM application data
*/
#if 0
int i;
/* Update the list of Forbidden PLMNs */
for (i=0; (i < _emm_data.fplmn.n_plmns) && (i < USIM_FPLMN_MAX); i++)
{
_usim_data.fplmn[i] = _emm_data.fplmn.plmn[i];
}
/* Update the list of Equivalent HPLMNs */
for (i=0; (i < _emm_data.ehplmn.n_plmns) && (i < USIM_EHPLMN_MAX); i++)
{
_usim_data.ehplmn[i] = _emm_data.ehplmn.plmn[i];
}
/* Update the GUTI */
if (_emm_data.guti) {
_usim_data.epsloci.guti = *(_emm_data.guti);
}
/* Update the last visited registered TAI */
if (_emm_data.tai) {
_usim_data.epsloci.tai = *(_emm_data.tai);
}
/* Update the EPS location information */
_usim_data.epsloci.status = _emm_data.status;
if (_emm_data.security && (_emm_data.security->type == EMM_KSI_NATIVE))
{
/* TODO: Update the EPS security context parameters from the full
* native EPS security context */
}
/*
* Store USIM application data
* - List of forbidden PLMNs
*/
if ( usim_api_write(&_usim_data) != RETURNok ) {
/* The USIM application may not be present or not valid */
LOG_TRACE(WARNING, "EMM-MAIN - "
"Failed to write USIM application data");
}
int i;
/* Update the list of Forbidden PLMNs */
for (i=0; (i < _emm_data.fplmn.n_plmns) && (i < USIM_FPLMN_MAX); i++) {
_usim_data.fplmn[i] = _emm_data.fplmn.plmn[i];
}
/* Update the list of Equivalent HPLMNs */
for (i=0; (i < _emm_data.ehplmn.n_plmns) && (i < USIM_EHPLMN_MAX); i++) {
_usim_data.ehplmn[i] = _emm_data.ehplmn.plmn[i];
}
/* Update the GUTI */
if (_emm_data.guti) {
_usim_data.epsloci.guti = *(_emm_data.guti);
}
/* Update the last visited registered TAI */
if (_emm_data.tai) {
_usim_data.epsloci.tai = *(_emm_data.tai);
}
/* Update the EPS location information */
_usim_data.epsloci.status = _emm_data.status;
if (_emm_data.security && (_emm_data.security->type == EMM_KSI_NATIVE)) {
/* TODO: Update the EPS security context parameters from the full
* native EPS security context */
}
/*
* Store USIM application data
* - List of forbidden PLMNs
*/
if ( usim_api_write(&_usim_data) != RETURNok ) {
/* The USIM application may not be present or not valid */
LOG_TRACE(WARNING, "EMM-MAIN - "
"Failed to write USIM application data");
}
#endif
}
......@@ -464,29 +476,34 @@ void emm_main_cleanup(void)
* - Registered PLMN
* - List of equivalent PLMNs
*/
char* path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME);
char *path = memory_get_path(EMM_NVRAM_DIRNAME, EMM_NVRAM_FILENAME);
if (path == NULL) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname");
}
else {
int rc = memory_write(path, &_emm_data.nvdata, sizeof(emm_nvdata_t));
if (rc != RETURNok) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to write %s", path);
}
LOG_TRACE(ERROR, "EMM-MAIN - Failed to get EMM data pathname");
} else {
int rc = memory_write(path, &_emm_data.nvdata, sizeof(emm_nvdata_t));
if (rc != RETURNok) {
LOG_TRACE(ERROR, "EMM-MAIN - Failed to write %s", path);
}
}
/* Release dynamically allocated memory */
if (_emm_data.imei) {
free(_emm_data.imei);
_emm_data.imei = NULL;
free(_emm_data.imei);
_emm_data.imei = NULL;
}
if (_emm_data.security) {
emm_security_context_t* security = _emm_data.security;
if (security->kasme.value) free(security->kasme.value);
if (security->knas_enc.value) free(security->knas_enc.value);
if (security->knas_int.value) free(security->knas_int.value);
free(_emm_data.security);
_emm_data.security = NULL;
emm_security_context_t *security = _emm_data.security;
if (security->kasme.value) {
free(security->kasme.value);
}
if (security->knas_enc.value) {
free(security->knas_enc.value);
}
if (security->knas_int.value) {
free(security->knas_int.value);
}
free(_emm_data.security);
_emm_data.security = NULL;
}
#endif // NAS_UE
......@@ -497,19 +514,19 @@ void emm_main_cleanup(void)
#ifdef NAS_UE
/****************************************************************************
** **
** Name: emm_main_get_imsi() **
** Name: emm_main_get_imsi() **
** **
** Description: Get the International Mobile Subscriber Identity number **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: Pointer to the IMSI **
** Others: None **
** Outputs: None **
** Return: Pointer to the IMSI **
** Others: None **
** **
***************************************************************************/
const imsi_t* emm_main_get_imsi(void)
const imsi_t *emm_main_get_imsi(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (&_emm_data.nvdata.imsi);
......@@ -517,19 +534,19 @@ const imsi_t* emm_main_get_imsi(void)
/****************************************************************************
** **
** Name: emm_main_get_msisdn() **
** Name: emm_main_get_msisdn() **
** **
** Description: Get the Mobile Subscriber Dialing Number from the USIM **
** **
** Inputs: None **
** Others: _usim_data **
** Inputs: None **
** Others: _usim_data **
** **
** Outputs: None **
** Return: Pointer to the subscriber dialing number **
** Others: None **
** Outputs: None **
** Return: Pointer to the subscriber dialing number **
** Others: None **
** **
***************************************************************************/
const msisdn_t* emm_main_get_msisdn(void)
const msisdn_t *emm_main_get_msisdn(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (&_usim_data.msisdn.number);
......@@ -537,57 +554,55 @@ const msisdn_t* emm_main_get_msisdn(void)
/****************************************************************************
** **
** Name: emm_main_set_plmn_selection_mode() **
** Name: emm_main_set_plmn_selection_mode() **
** **
** Description: Set the network selection mode of operation to the given **
** mode and update the manually selected network selection **
** data **
** mode and update the manually selected network selection **
** data **
** **
** Inputs: mode: The specified network selection mode of **
** operation **
** format: The representation format of the PLMN **
** identifier **
** plmn: Identifier of the selected PLMN **
** rat: The selected Radio Access Techonology **
** Others: None **
** Inputs: mode: The specified network selection mode of **
** operation **
** format: The representation format of the PLMN **
** identifier **
** plmn: Identifier of the selected PLMN **
** rat: The selected Radio Access Techonology **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _emm_data **
** **
***************************************************************************/
int emm_main_set_plmn_selection_mode(int mode, int format,
const network_plmn_t* plmn, int rat)
const network_plmn_t *plmn, int rat)
{
LOG_FUNC_IN;
int index;
LOG_TRACE(INFO, "EMM-MAIN - PLMN selection: mode=%d, format=%d, plmn=%s, "
"rat=%d", mode, format, (const char*)&plmn->id, rat);
"rat=%d", mode, format, (const char *)&plmn->id, rat);
_emm_data.plmn_mode = mode;
if (mode != EMM_DATA_PLMN_AUTO) {
/* Get the index of the PLMN in the list of available PLMNs */
index = _emm_main_get_plmn_index((const char*)&plmn->id, format);
if (index < 0) {
LOG_TRACE(WARNING, "EMM-MAIN - PLMN %s not available",
(const char*)&plmn->id);
}
else {
/* Update the manually selected network selection data */
_emm_data.plmn_index = index;
_emm_data.plmn_rat = rat;
}
}
else {
/*
* Get the index of the last PLMN the UE already tried to automatically
* register to when switched on; the equivalent PLMNs list shall not be
* applied to the user reselection in Automatic Network Selection Mode.
*/
index = IdleMode_get_hplmn_index();
/* Get the index of the PLMN in the list of available PLMNs */
index = _emm_main_get_plmn_index((const char *)&plmn->id, format);
if (index < 0) {
LOG_TRACE(WARNING, "EMM-MAIN - PLMN %s not available",
(const char *)&plmn->id);
} else {
/* Update the manually selected network selection data */
_emm_data.plmn_index = index;
_emm_data.plmn_rat = rat;
}
} else {
/*
* Get the index of the last PLMN the UE already tried to automatically
* register to when switched on; the equivalent PLMNs list shall not be
* applied to the user reselection in Automatic Network Selection Mode.
*/
index = IdleMode_get_hplmn_index();
}
LOG_FUNC_RETURN (index);
......@@ -595,17 +610,17 @@ int emm_main_set_plmn_selection_mode(int mode, int format,
/****************************************************************************
** **
** Name: emm_main_get_plmn_selection_mode() **
** Name: emm_main_get_plmn_selection_mode() **
** **
** Description: Get the current value of the network selection mode of **
** operation **
** operation **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The value of the network selection mode **
** Others: None **
** Outputs: None **
** Return: The value of the network selection mode **
** Others: None **
** **
***************************************************************************/
int emm_main_get_plmn_selection_mode(void)
......@@ -616,19 +631,19 @@ int emm_main_get_plmn_selection_mode(void)
/****************************************************************************
** **
** Name: emm_main_get_plmn_list() **
** Name: emm_main_get_plmn_list() **
** **
** Description: Get the list of available PLMNs **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: plist: Pointer to the list of available PLMNs **
** Return: The size of the list in bytes **
** Others: None **
** Outputs: plist: Pointer to the list of available PLMNs **
** Return: The size of the list in bytes **
** Others: None **
** **
***************************************************************************/
int emm_main_get_plmn_list(const char** plist)
int emm_main_get_plmn_list(const char **plist)
{
LOG_FUNC_IN;
......@@ -640,22 +655,22 @@ int emm_main_get_plmn_list(const char** plist)
/****************************************************************************
** **
** Name: emm_main_get_selected_plmn() **
** Name: emm_main_get_selected_plmn() **
** **
** Description: Get the identifier of the currently selected PLMN **
** **
** Inputs: format: The requested format of the string repre- **
** sentation of the PLMN identifier **
** Others: _emm_data **
** Inputs: format: The requested format of the string repre- **
** sentation of the PLMN identifier **
** Others: _emm_data **
** **
** Outputs: plmn: The selected PLMN identifier coded in the **
** requested format **
** Return: A pointer to the string representation of **
** the selected PLMN **
** Others: None **
** Outputs: plmn: The selected PLMN identifier coded in the **
** requested format **
** Return: A pointer to the string representation of **
** the selected PLMN **
** Others: None **
** **
***************************************************************************/
const char* emm_main_get_selected_plmn(network_plmn_t* plmn, int format)
const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format)
{
LOG_FUNC_IN;
......@@ -665,11 +680,11 @@ const char* emm_main_get_selected_plmn(network_plmn_t* plmn, int format)
*/
int index = IdleMode_get_splmn_index();
if ( !(index < 0) ) {
const char* name = _emm_main_get_plmn(&_emm_data.splmn, index,
format, &size);
if (size > 0) {
LOG_FUNC_RETURN ((char*) memcpy(&plmn->id, name, size));
}
const char *name = _emm_main_get_plmn(&_emm_data.splmn, index,
format, &size);
if (size > 0) {
LOG_FUNC_RETURN ((char *) memcpy(&plmn->id, name, size));
}
}
LOG_FUNC_RETURN (NULL);
......@@ -677,22 +692,22 @@ const char* emm_main_get_selected_plmn(network_plmn_t* plmn, int format)
/****************************************************************************
** **
** Name: emm_main_get_registered_plmn() **
** Name: emm_main_get_registered_plmn() **
** **
** Description: Get the identifier of the currently registered PLMN **
** **
** Inputs: format: The requested format of the string repre- **
** sentation of the PLMN identifier **
** Others: _emm_data **
** Inputs: format: The requested format of the string repre- **
** sentation of the PLMN identifier **
** Others: _emm_data **
** **
** Outputs: plmn: The registered PLMN identifier coded in **
** the requested format **
** Return: A pointer to the string representation of **
** the registered PLMN **
** Others: None **
** Outputs: plmn: The registered PLMN identifier coded in **
** the requested format **
** Return: A pointer to the string representation of **
** the registered PLMN **
** Others: None **
** **
***************************************************************************/
const char* emm_main_get_registered_plmn(network_plmn_t* plmn, int format)
const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format)
{
LOG_FUNC_IN;
......@@ -703,11 +718,11 @@ const char* emm_main_get_registered_plmn(network_plmn_t* plmn, int format)
*/
int index = IdleMode_get_rplmn_index();
if ( !(index < 0) ) {
const char* name = _emm_main_get_plmn(&_emm_data.nvdata.rplmn,
index, format, &size);
if (size > 0) {
LOG_FUNC_RETURN ((char*) memcpy(&plmn->id, name, size));
}
const char *name = _emm_main_get_plmn(&_emm_data.nvdata.rplmn,
index, format, &size);
if (size > 0) {
LOG_FUNC_RETURN ((char *) memcpy(&plmn->id, name, size));
}
}
LOG_FUNC_RETURN (NULL);
......@@ -715,18 +730,18 @@ const char* emm_main_get_registered_plmn(network_plmn_t* plmn, int format)
/****************************************************************************
** **
** Name: emm_main_get_plmn_status() **
** Name: emm_main_get_plmn_status() **
** **
** Description: Get the value of the network registration status which **
** shows whether the network has currently indicated the **
** registration of the UE **
** shows whether the network has currently indicated the **
** registration of the UE **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The current network registration status **
** Others: None **
** Outputs: None **
** Return: The current network registration status **
** Others: None **
** **
***************************************************************************/
Stat_t emm_main_get_plmn_status(void)
......@@ -737,17 +752,17 @@ Stat_t emm_main_get_plmn_status(void)
/****************************************************************************
** **
** Name: emm_main_get_plmn_tac() **
** Name: emm_main_get_plmn_tac() **
** **
** Description: Get the code of the Tracking area the registered PLMN **
** belongs to **
** belongs to **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The Location/Tracking area code **
** Others: None **
** Outputs: None **
** Return: The Location/Tracking area code **
** Others: None **
** **
***************************************************************************/
tac_t emm_main_get_plmn_tac(void)
......@@ -758,16 +773,16 @@ tac_t emm_main_get_plmn_tac(void)
/****************************************************************************
** **
** Name: emm_main_get_plmn_ci() **
** Name: emm_main_get_plmn_ci() **
** **
** Description: Get the identifier of the serving cell **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The serving cell identifier **
** Others: None **
** Outputs: None **
** Return: The serving cell identifier **
** Others: None **
** **
***************************************************************************/
ci_t emm_main_get_plmn_ci(void)
......@@ -778,18 +793,18 @@ ci_t emm_main_get_plmn_ci(void)
/****************************************************************************
** **
** Name: emm_main_get_plmn_rat() **
** Name: emm_main_get_plmn_rat() **
** **
** Description: Get the value of the Radio Access Technology of the ser- **
** ving cell **
** ving cell **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: The value of the Radio Access Technology **
** of the serving cell **
** Others: None **
** Outputs: None **
** Return: The value of the Radio Access Technology **
** of the serving cell **
** Others: None **
** **
***************************************************************************/
AcT_t emm_main_get_plmn_rat(void)
......@@ -800,18 +815,18 @@ AcT_t emm_main_get_plmn_rat(void)
/****************************************************************************
** **
** Name: emm_main_is_attached() **
** Name: emm_main_is_attached() **
** **
** Description: Indicates whether the UE is currently attached to the **
** network for EPS services or emergency service only **
** network for EPS services or emergency service only **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: TRUE if the UE is currently attached to **
** the network; FALSE otherwise. **
** Others: None **
** Outputs: None **
** Return: TRUE if the UE is currently attached to **
** the network; FALSE otherwise. **
** Others: None **
** **
***************************************************************************/
int emm_main_is_attached(void)
......@@ -822,19 +837,19 @@ int emm_main_is_attached(void)
/****************************************************************************
** **
** Name: emm_main_get_plmn_rat() **
** Name: emm_main_get_plmn_rat() **
** **
** Description: Indicates whether the UE is currently attached to the **
** network for emergency bearer services **
** network for emergency bearer services **
** **
** Inputs: None **
** Others: _emm_data **
** Inputs: None **
** Others: _emm_data **
** **
** Outputs: None **
** Return: TRUE if the UE is currently attached or is **
** attempting to attach to the network for **
** emergency bearer services; FALSE otherwise **
** Others: None **
** Outputs: None **
** Return: TRUE if the UE is currently attached or is **
** attempting to attach to the network for **
** emergency bearer services; FALSE otherwise **
** Others: None **
** **
***************************************************************************/
int emm_main_is_emergency(void)
......@@ -851,21 +866,21 @@ int emm_main_is_emergency(void)
#ifdef NAS_UE
/****************************************************************************
** **
** Name: _emm_main_callback() **
** Name: _emm_main_callback() **
** **
** Description: Forwards the network indication to the upper control la- **
** yer (user API) to notify that network registration and/or **
** location information has changed. **
** yer (user API) to notify that network registration and/or **
** location information has changed. **
** **
** Inputs: size: Size in byte of the list of operators **
** present in the network. The list has to be **
** displayed to the user application when **
** size > 0. **
** Others: _emm_data **
** Inputs: size: Size in byte of the list of operators **
** present in the network. The list has to be **
** displayed to the user application when **
** size > 0. **
** Others: _emm_data **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
static int _emm_main_callback(int size)
......@@ -874,34 +889,34 @@ static int _emm_main_callback(int size)
/* Forward the notification to the user API */
int rc = (*_emm_main_user_callback)(_emm_data.stat, _emm_data.tac,
_emm_data.ci, _emm_data.rat,
_emm_data.plist.buffer, size);
_emm_data.ci, _emm_data.rat,
_emm_data.plist.buffer, size);
LOG_FUNC_RETURN (rc);
}
/****************************************************************************
** **
** Name: _emm_main_get_imei() **
** Name: _emm_main_get_imei() **
** **
** Description: Returns the International Mobile Equipment Identity con- **
** tained in the given string representation **
** tained in the given string representation **
** **
** Inputs: imei: The string representation of the IMEI **
** Others: None **
** Inputs: imei: The string representation of the IMEI **
** Others: None **
** **
** Outputs: imei: The IMEI of the UE **
** Return: The number of digits in the IMEI **
** Others: None **
** Outputs: imei: The IMEI of the UE **
** Return: The number of digits in the IMEI **
** Others: None **
** **
***************************************************************************/
static int _emm_main_get_imei(imei_t* imei, const char* imei_str)
static int _emm_main_get_imei(imei_t *imei, const char *imei_str)
{
int len = strlen(imei_str);
if (len % 2) {
imei->u.num.parity = ODD_PARITY;
imei->u.num.parity = ODD_PARITY;
} else {
imei->u.num.parity = EVEN_PARITY;
imei->u.num.parity = EVEN_PARITY;
}
imei->u.num.digit1 = imei_str[0] - '0';
imei->u.num.digit2 = imei_str[1] - '0';
......@@ -923,125 +938,123 @@ static int _emm_main_get_imei(imei_t* imei, const char* imei_str)
/****************************************************************************
** **
** Name: _emm_main_imsi_cmp() **
** Name: _emm_main_imsi_cmp() **
** **
** Description: Compares two International Mobile Subscriber Identifiers **
** **
** Inputs: imsi1: The first IMSI **
** imsi2: The second IMSI to compare to **
** Others: None **
** Inputs: imsi1: The first IMSI **
** imsi2: The second IMSI to compare to **
** Others: None **
** **
** Outputs: None **
** Return: TRUE if the first IMSI is found to match **
** the second; FALSE otherwise. **
** Others: None **
** Outputs: None **
** Return: TRUE if the first IMSI is found to match **
** the second; FALSE otherwise. **
** Others: None **
** **
***************************************************************************/
static int _emm_main_imsi_cmp(imsi_t* imsi1, imsi_t* imsi2)
static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2)
{
if (imsi1->length != imsi2->length) {
return FALSE;
return FALSE;
}
for (int i = 0; i < imsi1->length; i++) {
if (imsi1->u.value[i] != imsi2->u.value[i]) {
return FALSE;
}
if (imsi1->u.value[i] != imsi2->u.value[i]) {
return FALSE;
}
}
return TRUE;
}
/****************************************************************************
** **
** Name: _emm_main_get_plmn() **
** Name: _emm_main_get_plmn() **
** **
** Description: Get the identifier of the PLMN at the given index in the **
** list of available PLMNs. **
** list of available PLMNs. **
** **
** Inputs: plmn: The PLMN to search for **
** index: The index of the PLMN in the list of PLMNs **
** format: The requested representation format of the **
** PLMN identifier **
** Others: None **
** Inputs: plmn: The PLMN to search for **
** index: The index of the PLMN in the list of PLMNs **
** format: The requested representation format of the **
** PLMN identifier **
** Others: None **
** **
** Outputs: size: The size in bytes of the PLMN identifier **
** coded in the requested format **
** Return: A pointer to the identifier of the PLMN **
** Others: None **
** Outputs: size: The size in bytes of the PLMN identifier **
** coded in the requested format **
** Return: A pointer to the identifier of the PLMN **
** Others: None **
** **
***************************************************************************/
static const char* _emm_main_get_plmn(const plmn_t* plmn, int index,
int format, size_t* size)
static const char *_emm_main_get_plmn(const plmn_t *plmn, int index,
int format, size_t *size)
{
if ( PLMN_IS_VALID(*plmn) ) {
switch (format)
{
case NET_FORMAT_LONG:
/* Get the long alpha-numeric representation of the PLMN */
return IdleMode_get_plmn_fullname(plmn, index, size);
break;
case NET_FORMAT_SHORT:
/* Get the short alpha-numeric representation of the PLMN */
return IdleMode_get_plmn_shortname(plmn, index, size);
break;
case NET_FORMAT_NUM:
/* Get the numeric representation of the PLMN */
return IdleMode_get_plmn_id(plmn, index, size);
break;
default:
LOG_TRACE(WARNING, "EMM-MAIN - Format is not valid (%d)",
format);
*size = 0;
break;
}
switch (format) {
case NET_FORMAT_LONG:
/* Get the long alpha-numeric representation of the PLMN */
return IdleMode_get_plmn_fullname(plmn, index, size);
break;
case NET_FORMAT_SHORT:
/* Get the short alpha-numeric representation of the PLMN */
return IdleMode_get_plmn_shortname(plmn, index, size);
break;
case NET_FORMAT_NUM:
/* Get the numeric representation of the PLMN */
return IdleMode_get_plmn_id(plmn, index, size);
break;
default:
LOG_TRACE(WARNING, "EMM-MAIN - Format is not valid (%d)",
format);
*size = 0;
break;
}
}
return (NULL);
}
/****************************************************************************
** **
** Name: _emm_main_get_plmn_index() **
** Name: _emm_main_get_plmn_index() **
** **
** Description: Get the index of the given PLMN in the ordered list of **
** available PLMNs **
** available PLMNs **
** **
** Inputs: plmn: Identifier of the PLMN **
** format: The representation format of the PLMN **
** identifier **
** Others: None **
** Inputs: plmn: Identifier of the PLMN **
** format: The representation format of the PLMN **
** identifier **
** Others: None **
** **
** Outputs: None **
** Return: The index of the selected PLMN in the list **
** of available PLMNs; -1 if the PLMN is not **
** found **
** Others: None **
** Outputs: None **
** Return: The index of the selected PLMN in the list **
** of available PLMNs; -1 if the PLMN is not **
** found **
** Others: None **
** **
***************************************************************************/
static int _emm_main_get_plmn_index(const char* plmn, int format)
static int _emm_main_get_plmn_index(const char *plmn, int format)
{
int index = -1;
switch (format)
{
case NET_FORMAT_LONG:
/* Get the index of the long alpha-numeric PLMN identifier */
index = IdleMode_get_plmn_fullname_index(plmn);
break;
case NET_FORMAT_SHORT:
/* Get the index of the short alpha-numeric PLMN identifier */
index = IdleMode_get_plmn_shortname_index(plmn);
break;
case NET_FORMAT_NUM:
/* Get the index of the numeric PLMN identifier */
index = IdleMode_get_plmn_id_index(plmn);
break;
default:
LOG_TRACE(WARNING, "EMM-MAIN - Format is not valid (%d)", format);
break;
switch (format) {
case NET_FORMAT_LONG:
/* Get the index of the long alpha-numeric PLMN identifier */
index = IdleMode_get_plmn_fullname_index(plmn);
break;
case NET_FORMAT_SHORT:
/* Get the index of the short alpha-numeric PLMN identifier */
index = IdleMode_get_plmn_shortname_index(plmn);
break;
case NET_FORMAT_NUM:
/* Get the index of the numeric PLMN identifier */
index = IdleMode_get_plmn_id_index(plmn);
break;
default:
LOG_TRACE(WARNING, "EMM-MAIN - Format is not valid (%d)", format);
break;
}
return (index);
}
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source emm_main.h
Source emm_main.h
Version 0.1
Version 0.1
Date 2012/10/10
Date 2012/10/10
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the EPS Mobility Management procedure call manager,
the main entry point for elementary EMM processing.
Description Defines the EPS Mobility Management procedure call manager,
the main entry point for elementary EMM processing.
*****************************************************************************/
#ifndef __EMM_MAIN_H__
......@@ -41,7 +41,7 @@ Description Defines the EPS Mobility Management procedure call manager,
/****************************************************************************/
#ifdef NAS_UE
void emm_main_initialize(emm_indication_callback_t cb, const char* imei);
void emm_main_initialize(emm_indication_callback_t cb, const char *imei);
#endif
#ifdef NAS_MME
void emm_main_initialize(void);
......@@ -51,24 +51,24 @@ void emm_main_cleanup(void);
#ifdef NAS_UE
/* User's getter of UE's identity */
const imsi_t* emm_main_get_imsi(void);
const imsi_t *emm_main_get_imsi(void);
/* User's getter of the subscriber dialing number */
const msisdn_t* emm_main_get_msisdn(void);
const msisdn_t *emm_main_get_msisdn(void);
/* User's getter/setter for network selection */
int emm_main_set_plmn_selection_mode(int mode, int format,
const network_plmn_t* plmn, int rat);
const network_plmn_t *plmn, int rat);
int emm_main_get_plmn_selection_mode(void);
int emm_main_get_plmn_list(const char** plist);
const char* emm_main_get_selected_plmn(network_plmn_t* plmn, int format);
int emm_main_get_plmn_list(const char **plist);
const char *emm_main_get_selected_plmn(network_plmn_t *plmn, int format);
/* User's getter for network registration */
Stat_t emm_main_get_plmn_status(void);
tac_t emm_main_get_plmn_tac(void);
ci_t emm_main_get_plmn_ci(void);
AcT_t emm_main_get_plmn_rat(void);
const char* emm_main_get_registered_plmn(network_plmn_t* plmn, int format);
const char *emm_main_get_registered_plmn(network_plmn_t *plmn, int format);
/* User's getter for network attachment */
int emm_main_is_attached(void);
......
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source emm_proc.h
Source emm_proc.h
Version 0.1
Version 0.1
Date 2012/10/16
Date 2012/10/16
Product NAS stack
Product NAS stack
Subsystem EPS Mobility Management
Subsystem EPS Mobility Management
Author Frederic Maurel
Author Frederic Maurel
Description Defines the EPS Mobility Management procedures executed at
the EMM Service Access Points.
Description Defines the EPS Mobility Management procedures executed at
the EMM Service Access Points.
*****************************************************************************/
#ifndef __EMM_PROC_H__
......@@ -78,7 +78,7 @@ typedef enum {
/*
*---------------------------------------------------------------------------
* EMM status procedure
* EMM status procedure
*---------------------------------------------------------------------------
*/
int emm_proc_status_ind(unsigned int ueid, int emm_cause);
......@@ -86,14 +86,14 @@ int emm_proc_status(unsigned int ueid, int emm_cause);
/*
*---------------------------------------------------------------------------
* Lower layer procedure
* Lower layer procedure
*---------------------------------------------------------------------------
*/
#ifdef NAS_UE
int emm_proc_lowerlayer_initialize(lowerlayer_success_callback_t success,
lowerlayer_failure_callback_t failure,
lowerlayer_release_callback_t release,
void* args);
lowerlayer_failure_callback_t failure,
lowerlayer_release_callback_t release,
void *args);
int emm_proc_lowerlayer_success(void);
int emm_proc_lowerlayer_failure(int is_initial);
int emm_proc_lowerlayer_release(void);
......@@ -101,7 +101,7 @@ int emm_proc_lowerlayer_release(void);
/*
*---------------------------------------------------------------------------
* UE's Idle mode procedure
* UE's Idle mode procedure
*---------------------------------------------------------------------------
*/
#ifdef NAS_UE
......@@ -112,17 +112,19 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat);
/*
* --------------------------------------------------------------------------
* Attach procedure
* Attach procedure
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
int emm_proc_attach(emm_proc_attach_type_t type);
int emm_proc_attach_request(void* args);
int emm_proc_attach_accept(long T3412, long T3402, long T3423, int n_tais, tai_t* tai, GUTI_t* guti, int n_eplmns, plmn_t* eplmn, const OctetString* esm_msg);
int emm_proc_attach_reject(int emm_cause, const OctetString* esm_msg);
int emm_proc_attach_complete(void* args);
int emm_proc_attach_failure(int is_initial, void* args);
int emm_proc_attach_release(void* args);
int emm_proc_attach_request(void *args);
int emm_proc_attach_accept(long T3412, long T3402, long T3423, int n_tais,
tai_t *tai, GUTI_t *guti, int n_eplmns, plmn_t *eplmn,
const OctetString *esm_msg);
int emm_proc_attach_reject(int emm_cause, const OctetString *esm_msg);
int emm_proc_attach_complete(void *args);
int emm_proc_attach_failure(int is_initial, void *args);
int emm_proc_attach_release(void *args);
int emm_proc_attach_restart(void);
int emm_proc_attach_set_emergency(void);
......@@ -130,32 +132,36 @@ int emm_proc_attach_set_detach(void);
#endif
#ifdef NAS_MME
int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type, int native_ksi, int ksi, int native_guti, GUTI_t* guti, imsi_t* imsi, imei_t* imei, tai_t* tai, int eea, int eia, const OctetString* esm_msg);
int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
int native_ksi, int ksi, int native_guti, GUTI_t *guti, imsi_t *imsi,
imei_t *imei, tai_t *tai, int eea, int eia, const OctetString *esm_msg);
int emm_proc_attach_reject(unsigned int ueid, int emm_cause);
int emm_proc_attach_complete(unsigned int ueid, const OctetString* esm_msg);
int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg);
#endif
/*
* --------------------------------------------------------------------------
* Detach procedure
* Detach procedure
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
int emm_proc_detach(emm_proc_detach_type_t type, int switch_off);
int emm_proc_detach_request(void* args);
int emm_proc_detach_request(void *args);
int emm_proc_detach_accept(void);
int emm_proc_detach_failure(int is_initial, void* args);
int emm_proc_detach_release(void* args);
int emm_proc_detach_failure(int is_initial, void *args);
int emm_proc_detach_release(void *args);
#endif
#ifdef NAS_MME
int emm_proc_detach(unsigned int ueid, emm_proc_detach_type_t type);
int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type, int switch_off, int native_ksi, int ksi, GUTI_t* guti, imsi_t* imsi, imei_t* imei);
int emm_proc_detach_request(unsigned int ueid, emm_proc_detach_type_t type,
int switch_off, int native_ksi, int ksi, GUTI_t *guti, imsi_t *imsi,
imei_t *imei);
#endif
/*
* --------------------------------------------------------------------------
* Identification procedure
* Identification procedure
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
......@@ -169,50 +175,54 @@ int emm_proc_identification(unsigned int ueid,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure);
int emm_proc_identification_complete(unsigned int ueid, const imsi_t* imsi, const imei_t* imei, UInt32_t* tmsi);
int emm_proc_identification_complete(unsigned int ueid, const imsi_t *imsi,
const imei_t *imei, UInt32_t *tmsi);
#endif
/*
* --------------------------------------------------------------------------
* Authentication procedure
* Authentication procedure
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
int emm_proc_authentication_request(int native_ksi, int ksi, const OctetString* rand, const OctetString* autn);
int emm_proc_authentication_request(int native_ksi, int ksi,
const OctetString *rand, const OctetString *autn);
int emm_proc_authentication_reject(void);
int emm_proc_authentication_delete(void);
#endif
#ifdef NAS_MME
int emm_proc_authentication(unsigned int ueid, int ksi,
const OctetString* rand, const OctetString* autn,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure);
int emm_proc_authentication_complete(unsigned int ueid, int emm_cause, const OctetString* res);
const OctetString *rand, const OctetString *autn,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure);
int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
const OctetString *res);
#endif
/*
* --------------------------------------------------------------------------
* Security mode control procedure
* Security mode control procedure
* --------------------------------------------------------------------------
*/
#ifdef NAS_UE
int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia, int reea, int reia);
int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia,
int reea, int reia);
#endif
#ifdef NAS_MME
int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure);
emm_common_success_callback_t success,
emm_common_reject_callback_t reject,
emm_common_failure_callback_t failure);
int emm_proc_security_mode_complete(unsigned int ueid);
int emm_proc_security_mode_reject(unsigned int ueid);
#endif
/*
*---------------------------------------------------------------------------
* Network indication handlers
* Network indication handlers
*---------------------------------------------------------------------------
*/
#ifdef NAS_UE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment