1409 lines
62 KiB
C
1409 lines
62 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
Source nas_proc.c
|
|
|
|
Version 0.1
|
|
|
|
Date 2012/09/20
|
|
|
|
Product NAS stack
|
|
|
|
Subsystem NAS main process
|
|
|
|
Author Frederic Maurel
|
|
|
|
Description NAS procedure call manager
|
|
|
|
*****************************************************************************/
|
|
|
|
#include "nas_proc.h"
|
|
#include "nas_log.h"
|
|
#include "nas_user.h"
|
|
#include "utils.h"
|
|
|
|
#include "emm_main.h"
|
|
#include "emm_sap.h"
|
|
|
|
#include "esm_main.h"
|
|
#include "esm_sap.h"
|
|
|
|
#include <stdio.h> // sprintf
|
|
|
|
/****************************************************************************/
|
|
/**************** E X T E R N A L D E F I N I T I O N S ****************/
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/******************* L O C A L D E F I N I T I O N S *******************/
|
|
/****************************************************************************/
|
|
|
|
/*
|
|
* Signal strength/quality value not known or not detectable
|
|
*/
|
|
#define NAS_PROC_RSRQ_UNKNOWN 255
|
|
#define NAS_PROC_RSRP_UNKNOWN 255
|
|
|
|
|
|
static int _nas_proc_activate(nas_user_t *user, int cid, bool apply_to_all);
|
|
static int _nas_proc_deactivate(nas_user_t *user, int cid, bool apply_to_all);
|
|
|
|
/****************************************************************************/
|
|
/****************** E X P O R T E D F U N C T I O N S ******************/
|
|
/****************************************************************************/
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_initialize() **
|
|
** **
|
|
** Description: **
|
|
** **
|
|
** Inputs: emm_cb: Mobility Management indication callback **
|
|
** esm_cb: Session Management indication callback **
|
|
** imei: The IMEI read from the UE's non-volatile **
|
|
** memory **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: None **
|
|
** Others: _nas_proc_data **
|
|
** **
|
|
***************************************************************************/
|
|
void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb,
|
|
esm_indication_callback_t esm_cb, const char *imei)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
/* Initialize local NAS data */
|
|
user->proc.EPS_capability_status = false;
|
|
user->proc.rsrq = NAS_PROC_RSRQ_UNKNOWN;
|
|
user->proc.rsrp = NAS_PROC_RSRP_UNKNOWN;
|
|
|
|
user->authentication_data = calloc_or_fail(1, sizeof(authentication_data_t));
|
|
user->security_data = calloc_or_fail(1, sizeof(security_data_t));
|
|
|
|
/* Initialize the EMM procedure manager */
|
|
emm_main_initialize(user, emm_cb, imei);
|
|
|
|
/* Initialize the ESM procedure manager */
|
|
esm_main_initialize(user, esm_cb);
|
|
|
|
LOG_FUNC_OUT;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_cleanup() **
|
|
** **
|
|
** Description: Performs clean up procedure before the system is shutdown **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: None **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
void nas_proc_cleanup(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
/* Detach the UE from the EPS network */
|
|
int rc = nas_proc_detach(user, true);
|
|
|
|
if (rc != RETURNok) {
|
|
LOG_TRACE(ERROR, "NAS-PROC - Failed to detach from the network");
|
|
}
|
|
|
|
|
|
/* Perform the EPS Mobility Manager's clean up procedure */
|
|
emm_main_cleanup(user);
|
|
|
|
/* Perform the EPS Session Manager's clean up procedure */
|
|
esm_main_cleanup(user->esm_data);
|
|
|
|
LOG_FUNC_OUT;
|
|
}
|
|
|
|
/*
|
|
* --------------------------------------------------------------------------
|
|
* NAS procedures triggered by the user
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_enable_s1_mode() **
|
|
** **
|
|
** Description: Notify the EPS Mobility Manager that the UE can be **
|
|
** operated **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_enable_s1_mode(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that EPS capability
|
|
* of the UE is enabled
|
|
*/
|
|
user->proc.EPS_capability_status = true;
|
|
emm_sap.primitive = EMMREG_S1_ENABLED;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_disable_s1_mode() **
|
|
** **
|
|
** Description: Notify the EPS Mobility Manager that the S1 mode is no **
|
|
** longer activated **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_disable_s1_mode(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that EPS capability
|
|
* of the UE is disabled
|
|
*/
|
|
user->proc.EPS_capability_status = false;
|
|
emm_sap.primitive = EMMREG_S1_DISABLED;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_eps() **
|
|
** **
|
|
** Description: Get the current value of the EPS capability status **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: _nas_proc_data **
|
|
** **
|
|
** Outputs: stat: The current value of the EPS capability **
|
|
** status **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_eps(nas_user_t *user, bool *stat)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
*stat = user->proc.EPS_capability_status;
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_imsi() **
|
|
** **
|
|
** Description: Get the International Mobile Subscriber Identity number **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: imsi: The value of the IMSI **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_imsi(emm_data_t *emm_data, char *imsi_str)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
const imsi_t *imsi = emm_main_get_imsi(emm_data);
|
|
|
|
if (imsi != NULL) {
|
|
int offset = 0;
|
|
offset += sprintf(imsi_str + offset, "%u%u%u%u%u",
|
|
imsi->u.num.digit1, imsi->u.num.digit2,
|
|
imsi->u.num.digit3, imsi->u.num.digit4,
|
|
imsi->u.num.digit5);
|
|
|
|
if (imsi->u.num.digit6 != 0xf) {
|
|
offset += sprintf(imsi_str + offset, "%u", imsi->u.num.digit6);
|
|
}
|
|
|
|
offset += sprintf(imsi_str + offset, "%u%u%u%u%u%u%u%u",
|
|
imsi->u.num.digit7, imsi->u.num.digit8,
|
|
imsi->u.num.digit9, imsi->u.num.digit10,
|
|
imsi->u.num.digit11, imsi->u.num.digit12,
|
|
imsi->u.num.digit13, imsi->u.num.digit14);
|
|
|
|
if (imsi->u.num.digit15 != 0xf) {
|
|
offset += sprintf(imsi_str + offset, "%u", imsi->u.num.digit15);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (RETURNerror);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_msisdn() **
|
|
** **
|
|
** Description: Get the Mobile Subscriber dialing number **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: msisdn: The value of the subscriber dialing number **
|
|
** ton_npi: Type Of Number / Numbering Plan Indicator **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_msisdn(nas_user_t *user, char *msisdn_str, int *ton_npi)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
const msisdn_t *msisdn = emm_main_get_msisdn(user);
|
|
|
|
if (msisdn != NULL) {
|
|
union {
|
|
struct {
|
|
uint8_t ext: 1;
|
|
uint8_t ton: 3;
|
|
uint8_t npi: 4;
|
|
} ext_ton_npi;
|
|
uint8_t type;
|
|
} converter;
|
|
converter.ext_ton_npi.ext = msisdn->ext;
|
|
converter.ext_ton_npi.ton = msisdn->ton;
|
|
converter.ext_ton_npi.npi = msisdn->npi;
|
|
*ton_npi = converter.type;
|
|
|
|
sprintf(msisdn_str, "%u%u%u%u%u%u%u%u%u%u%u",
|
|
msisdn->digit[0].msb, msisdn->digit[0].lsb,
|
|
msisdn->digit[1].msb, msisdn->digit[1].lsb,
|
|
msisdn->digit[2].msb, msisdn->digit[2].lsb,
|
|
msisdn->digit[3].msb, msisdn->digit[3].lsb,
|
|
msisdn->digit[4].msb, msisdn->digit[4].lsb,
|
|
msisdn->digit[5].msb);
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (RETURNerror);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_signal_quality() **
|
|
** **
|
|
** Description: Get the signal strength/quality parameters **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: _nas_proc_data **
|
|
** **
|
|
** Outputs: rsrq: Reference signal received quality value **
|
|
** rsrp: Reference signal received power value **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_signal_quality(nas_user_t *user, int *rsrq, int *rsrp)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
*rsrq = user->proc.rsrq;
|
|
*rsrp = user->proc.rsrp;
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_register() **
|
|
** **
|
|
** Description: Execute the network selection and registration procedure. **
|
|
** **
|
|
** Inputs: mode: Network selection mode of operation **
|
|
** format: Represention format of the operator iden- **
|
|
** tifier **
|
|
** oper: Identifier of the network operator to re- **
|
|
** gister **
|
|
** AcT: The selected Access Technology **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_register(nas_user_t *user, int mode, int format, const network_plmn_t *oper, int AcT)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc = RETURNerror;
|
|
|
|
/*
|
|
* Set the PLMN selection mode of operation
|
|
*/
|
|
int index = emm_main_set_plmn_selection_mode(user, mode, format, oper, AcT);
|
|
|
|
if ( !(index < 0) ) {
|
|
/*
|
|
* Notify the EMM procedure call manager that network (re)selection
|
|
* procedure has to be executed
|
|
*/
|
|
emm_sap_t emm_sap;
|
|
emm_sap.primitive = EMMREG_REGISTER_REQ;
|
|
emm_sap.u.emm_reg.u.regist.index = index;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_deregister() **
|
|
** **
|
|
** Description: Execute the network deregistration procedure. **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_deregister(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
/* TODO: Force an attempt to deregister from the network */
|
|
LOG_TRACE(ERROR, "NAS-PROC - Network deregistration procedure is "
|
|
"not implemented");
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_reg_data() **
|
|
** **
|
|
** Description: Gets network registration data from EMM **
|
|
** **
|
|
** Inputs: format: Format of the representation of the net- **
|
|
** work operator identifier **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: mode: The current network selection mode of ope- **
|
|
** ration **
|
|
** oper: The identifier of the selected network **
|
|
** operator **
|
|
** AcT: The access technology currently used **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_reg_data(nas_user_t *user, int *mode, bool *selected, int format,
|
|
network_plmn_t *oper, int *AcT)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
/* Get the PLMN selection mode of operation */
|
|
*mode = emm_main_get_plmn_selection_mode(user->emm_data);
|
|
|
|
/* Get the currently selected operator */
|
|
const char *oper_name = emm_main_get_selected_plmn(user->emm_plmn_list, user->emm_data, oper, format);
|
|
|
|
if (oper_name != NULL) {
|
|
/* An operator is currently selected */
|
|
*selected = true;
|
|
/* Get the supported Radio Access Technology */
|
|
*AcT = emm_main_get_plmn_rat(user->emm_data);
|
|
} else {
|
|
/* No any operator is selected */
|
|
*selected = false;
|
|
*AcT = NET_ACCESS_UNAVAILABLE;
|
|
}
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_oper_list() **
|
|
** **
|
|
** Description: Gets the list of operators present in the network **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: oper_list: The list of operators **
|
|
** Return: The size of the list in bytes **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_oper_list(nas_user_t *user, const char **oper_list)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int size = emm_main_get_plmn_list(user->emm_plmn_list, user->emm_data, oper_list);
|
|
|
|
LOG_FUNC_RETURN (size);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_reg_status() **
|
|
** **
|
|
** Description: Get the value of the network registration status which **
|
|
** shows whether the network has currently indicated the **
|
|
** registration of the UE **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: stat: The current network registration status **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_reg_status(nas_user_t *user, int *stat)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
*stat = emm_main_get_plmn_status(user->emm_data);
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_loc_info() **
|
|
** **
|
|
** Description: Get the location information when the UE is registered in **
|
|
** the Network **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: tac: The code of the tracking area the registe- **
|
|
** red PLMN belongs to **
|
|
** ci: The identifier of the serving cell **
|
|
** AcT: The access technology in used **
|
|
** rac: The GPRS routing area code, if available **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
sprintf(tac, "%.4x", emm_main_get_plmn_tac(user->emm_data)); // two byte
|
|
sprintf(ci, "%.8x", emm_main_get_plmn_ci(user->emm_data)); // four byte
|
|
*AcT = emm_main_get_plmn_rat(user->emm_data); // E-UTRAN
|
|
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_detach() **
|
|
** **
|
|
** Description: Initiates a detach procedure **
|
|
** **
|
|
** Inputs: switch_off: true if the detach is due to UE switch-off **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_detach(nas_user_t *user, bool switch_off)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc = RETURNok;
|
|
|
|
if ( emm_main_is_attached(user->emm_data) ) {
|
|
/* Initiate an Detach procedure */
|
|
emm_sap.primitive = EMMREG_DETACH_INIT;
|
|
emm_sap.u.emm_reg.u.detach.switch_off = switch_off;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_attach() **
|
|
** **
|
|
** Description: Initiates an attach procedure **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_attach(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc = RETURNok;
|
|
|
|
if ( !emm_main_is_attached(user->emm_data) ) {
|
|
/* Initiate an Attach procedure */
|
|
emm_sap.primitive = EMMREG_ATTACH_INIT;
|
|
emm_sap.u.emm_reg.u.attach.is_emergency = false;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_attach_status() **
|
|
** **
|
|
** Description: Gets the current network attachment status **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: true if the UE is currently attached to **
|
|
** the network **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
bool nas_proc_get_attach_status(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
bool is_attached = emm_main_is_attached(user->emm_data);
|
|
|
|
LOG_FUNC_RETURN (is_attached);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_pdn_range() **
|
|
** **
|
|
** Description: Gets the maximum value of a PDN context identifier **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: The PDN context identifier maximum value **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_pdn_range(esm_data_t *esm_data)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int max_pdn_id = esm_main_get_nb_pdns_max(esm_data);
|
|
|
|
LOG_FUNC_RETURN (max_pdn_id);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_pdn_status() **
|
|
** **
|
|
** Description: Gets the activation state of every defined PDN contexts **
|
|
** **
|
|
** Inputs: n_pdn_max: Maximum number of PDN contexts **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: cids: List of PDN context identifiers **
|
|
** states: List of PDN context activation states **
|
|
** Return: The number of PDN contexts that are cur- **
|
|
** rently in a defined state **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_max)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int cid;
|
|
int n_defined_pdn = 0;
|
|
|
|
/* Get the maximum number of supported PDN contexts */
|
|
int n_pdn = esm_main_get_nb_pdns_max(user->esm_data);
|
|
|
|
/* For all PDN contexts */
|
|
for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) {
|
|
/* Get the status of this PDN */
|
|
bool state = false;
|
|
bool is_defined = esm_main_get_pdn_status(user, cid, &state);
|
|
|
|
if (is_defined != false) {
|
|
/* This PDN has been defined */
|
|
*(cids++) = cid;
|
|
*(states++) = state;
|
|
n_defined_pdn += 1;
|
|
}
|
|
}
|
|
|
|
LOG_FUNC_RETURN (n_defined_pdn);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_pdn_param() **
|
|
** **
|
|
** Description: Gets the parameters of every defined PDN contexts **
|
|
** **
|
|
** Inputs: n_pdn_max: Maximum number of PDN contexts **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: cids: List of PDN context identifiers **
|
|
** types: List of PDN types (IPv4, IPv6, IPv4v6) **
|
|
** apns: List of Access Point Names **
|
|
** Return: The number of PDN contexts that are cur- **
|
|
** rently in a defined state **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const char **apns,
|
|
int n_pdn_max)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int cid;
|
|
int n_defined_pdn = 0;
|
|
|
|
/* Get the maximum number of supported PDN contexts */
|
|
int n_pdn = esm_main_get_nb_pdns_max(esm_data);
|
|
|
|
/* For all PDN contexts */
|
|
for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) {
|
|
bool emergency, active;
|
|
/* Get PDN connection parameters */
|
|
int rc = esm_main_get_pdn(esm_data, cid, types, apns, &emergency, &active);
|
|
|
|
if (rc != RETURNerror) {
|
|
/* This PDN has been defined */
|
|
*(cids++) = cid;
|
|
types++;
|
|
apns++;
|
|
n_defined_pdn += 1;
|
|
}
|
|
}
|
|
|
|
LOG_FUNC_RETURN (n_defined_pdn);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_get_pdn_addr() **
|
|
** **
|
|
** Description: When the cid parameter value is positive, gets the addres-**
|
|
** s(es) assigned to the specified PDN context. **
|
|
** When the cid parameter value is negative, gets the addres-**
|
|
** s(es) assigned to each defined PDN context. **
|
|
** When the cid parameter value is null, gets the list of **
|
|
** defined PDN contexts. **
|
|
** **
|
|
** Inputs: cid: PDN context identifier **
|
|
** n_pdn_max: Maximum number of PDN contexts **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: cids: List of PDN context identifiers **
|
|
** addr1: List of IPv4 addresses **
|
|
** addr2: List of IPv6 addresses **
|
|
** Return: The number PDN contexts that have at least **
|
|
** one IP address assigned **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_get_pdn_addr(nas_user_t *user, int cid, int *cids, const char **addr1,
|
|
const char **addr2, int n_pdn_max)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc;
|
|
int n_defined_pdn = 0;
|
|
|
|
if (cid > 0) {
|
|
/* Get addresses assigned to the specified PDN */
|
|
rc = esm_main_get_pdn_addr(user->esm_data, cid, addr1, addr2);
|
|
|
|
if (rc != RETURNerror) {
|
|
*cids = cid;
|
|
n_defined_pdn = 1;
|
|
}
|
|
} else if (cid < 0) {
|
|
/* Get the maximum number of supported PDN contexts */
|
|
int n_pdn = esm_main_get_nb_pdns_max(user->esm_data);
|
|
|
|
/* For all PDN contexts */
|
|
for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) {
|
|
/* Get PDN connection addresses */
|
|
rc = esm_main_get_pdn_addr(user->esm_data, cid, addr1, addr2);
|
|
|
|
if (rc != RETURNerror) {
|
|
/* This PDN has been defined */
|
|
*(cids++) = cid;
|
|
addr1++;
|
|
addr2++;
|
|
n_defined_pdn += 1;
|
|
}
|
|
}
|
|
} else {
|
|
/* Get the list of defined PDN contexts */
|
|
|
|
}
|
|
|
|
LOG_FUNC_RETURN (n_defined_pdn);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_set_pdn() **
|
|
** **
|
|
** Description: Setup parameters of a specified PDN context **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context to setup **
|
|
** type: Type of PDN (IPv4, IPv6,IPv4v6) **
|
|
** apn: Access Point Name of the external network **
|
|
** to connect to **
|
|
** ipv4_addr: IPv4 address allocation (NAS, DHCP) **
|
|
** emergency: Emergency bearer support indication **
|
|
** p_cscf: Preference of P-CSCF address discovery **
|
|
** im_cn_signal: IM CN subsystem-related signalling indica- **
|
|
** tion parameter **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr,
|
|
int emergency, int p_cscf, int im_cn_signal)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc;
|
|
|
|
esm_sap_t esm_sap;
|
|
esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ;
|
|
esm_sap.is_standalone = true;
|
|
esm_sap.data.pdn_connect.is_defined = false;
|
|
esm_sap.data.pdn_connect.cid = cid;
|
|
esm_sap.data.pdn_connect.pdn_type = type;
|
|
esm_sap.data.pdn_connect.apn = apn;
|
|
esm_sap.data.pdn_connect.is_emergency = emergency;
|
|
/*
|
|
* Notify ESM that a new PDN context has to be defined for
|
|
* the specified APN
|
|
*/
|
|
rc = esm_sap_send(user, &esm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_reset_pdn() **
|
|
** **
|
|
** Description: Reset parameters of a specified PDN context **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context to setup **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_reset_pdn(nas_user_t *user, int cid)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc;
|
|
|
|
esm_sap_t esm_sap;
|
|
esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ;
|
|
esm_sap.is_standalone = true;
|
|
esm_sap.data.pdn_connect.is_defined = true;
|
|
esm_sap.data.pdn_connect.cid = cid;
|
|
/*
|
|
* Notify ESM that the specified PDN context has to be undefined
|
|
*/
|
|
rc = esm_sap_send(user, &esm_sap);
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_deactivate_pdn() **
|
|
** **
|
|
** Description: Deactivates specified PDN context or all PDN contexts if **
|
|
** specified cid is negative **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context to be deac- **
|
|
** tivate **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_deactivate_pdn(nas_user_t *user, int cid)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc = RETURNok;
|
|
|
|
if (cid > 0) {
|
|
/* Deactivate only the specified PDN context */
|
|
rc = _nas_proc_deactivate(user, cid, false);
|
|
} else {
|
|
/* Do not deactivate the PDN connection established during initial
|
|
* network attachment (identifier 1) */
|
|
cid = 2;
|
|
|
|
/* Deactivate all active PDN contexts */
|
|
while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) {
|
|
rc = _nas_proc_deactivate(user, cid++, true);
|
|
}
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_activate_pdn() **
|
|
** **
|
|
** Description: Activates specified PDN context or all PDN contexts if **
|
|
** specified cid is negative **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context to be act- **
|
|
** tivate **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_activate_pdn(nas_user_t *user, int cid)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc = RETURNok;
|
|
|
|
if ( !emm_main_is_attached(user->emm_data) ) {
|
|
/*
|
|
* If the UE is not attached to the network, perform EPS attach
|
|
* procedure prior to attempt to request any PDN connectivity
|
|
*/
|
|
LOG_TRACE(WARNING, "NAS-PROC - UE is not attached to the network");
|
|
rc = nas_proc_attach(user);
|
|
} else if (emm_main_is_emergency(user->emm_data)) {
|
|
/* The UE is attached for emergency bearer services; It shall not
|
|
* request a PDN connection to any other PDN */
|
|
LOG_TRACE(WARNING,"NAS-PROC - Attached for emergency bearer services");
|
|
rc = RETURNerror;
|
|
}
|
|
|
|
if (rc != RETURNerror) {
|
|
if (cid > 0) {
|
|
/* Activate only the specified PDN context */
|
|
rc = _nas_proc_activate(user, cid, false);
|
|
} else {
|
|
cid = 1;
|
|
|
|
/* Activate all defined PDN contexts */
|
|
while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) {
|
|
rc = _nas_proc_activate(user, cid++, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/*
|
|
* --------------------------------------------------------------------------
|
|
* NAS procedures triggered by the network
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_cell_info() **
|
|
** **
|
|
** Description: Processes the cell information received from the network **
|
|
** **
|
|
** Inputs: found: Indicates whether a suitable cell is found **
|
|
** for the selected PLMN to camp on **
|
|
** tac: The code of the tracking area the PLMN **
|
|
** belongs to **
|
|
** ci: The identifier of a cell serving this PLMN **
|
|
** AcT: The access technology supported by the **
|
|
** serving cell **
|
|
** rsrq: Reference signal received quality measure- **
|
|
** ment **
|
|
** rsrp: Reference signal received power measure- **
|
|
** ment **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: _nas_proc_data **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_cell_info(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t AcT, uint8_t rsrq, uint8_t rsrp)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/* Store LTE signal strength/quality measurement data */
|
|
user->proc.rsrq = rsrq;
|
|
user->proc.rsrp = rsrp;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that cell information
|
|
* have been received from the Access-Stratum sublayer
|
|
*/
|
|
emm_sap.primitive = EMMAS_CELL_INFO_RES;
|
|
emm_sap.u.emm_as.u.cell_info.found = found;
|
|
emm_sap.u.emm_as.u.cell_info.plmnIDs.n_plmns = 0;
|
|
emm_sap.u.emm_as.u.cell_info.rat = AcT;
|
|
emm_sap.u.emm_as.u.cell_info.tac = tac;
|
|
emm_sap.u.emm_as.u.cell_info.cellID = ci;
|
|
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_establish_cnf() **
|
|
** **
|
|
** Description: Processes the NAS signalling connection establishment **
|
|
** confirm message received from the network **
|
|
** **
|
|
** Inputs: data: The initial NAS message transfered within **
|
|
** the message **
|
|
** len: The length of the initial NAS message **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_establish_cnf(nas_user_t *user, const uint8_t *data, uint32_t len)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that NAS signalling
|
|
* connection establishment confirm message has been received
|
|
* from the Access-Stratum sublayer
|
|
*/
|
|
emm_sap.primitive = EMMAS_ESTABLISH_CNF;
|
|
emm_sap.u.emm_as.u.establish.NASmsg.length = len;
|
|
emm_sap.u.emm_as.u.establish.NASmsg.value = (uint8_t *)data;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_establish_rej() **
|
|
** **
|
|
** Description: Processes the NAS signalling connection establishment **
|
|
** confirm message received from the network while initial **
|
|
** NAS message has not been delivered to the NAS sublayer on **
|
|
** the receiver side. **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_establish_rej(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that transmission
|
|
* failure of initial NAS message indication has been received
|
|
* from lower layers
|
|
*/
|
|
emm_sap.primitive = EMMAS_ESTABLISH_REJ;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_release_ind() **
|
|
** **
|
|
** Description: Processes the NAS signalling connection release indica- **
|
|
** tion message received from the network **
|
|
** **
|
|
** Inputs: cause: The release cause **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_release_ind(nas_user_t *user, int cause)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that the NAS signalling
|
|
* connection has been terminated by the network
|
|
*/
|
|
emm_sap.primitive = EMMAS_RELEASE_IND;
|
|
emm_sap.u.emm_as.u.release.cause = cause;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_ul_transfer_cnf() **
|
|
** **
|
|
** Description: Processes the uplink data transfer confirm message recei- **
|
|
** ved from the network while NAS message has been success- **
|
|
** fully delivered to the NAS sublayer on the receiver side. **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_ul_transfer_cnf(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that uplink NAS message
|
|
* has been successfully delivered to the NAS sublayer on the
|
|
* receiver side
|
|
*/
|
|
emm_sap.primitive = EMMAS_DATA_IND;
|
|
emm_sap.u.emm_as.u.data.ueid = user->ueid;
|
|
emm_sap.u.emm_as.u.data.delivered = true;
|
|
emm_sap.u.emm_as.u.data.NASmsg.length = 0;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_ul_transfer_rej() **
|
|
** **
|
|
** Description: Processes the uplink data transfer confirm message recei- **
|
|
** ved from the network while NAS message has not been deli- **
|
|
** vered to the NAS sublayer on the receiver side. **
|
|
** **
|
|
** Inputs: None **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_ul_transfer_rej(nas_user_t *user)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
emm_sap_t emm_sap;
|
|
int rc;
|
|
|
|
/*
|
|
* Notify the EMM procedure call manager that transmission
|
|
* failure of uplink NAS message indication has been received
|
|
* from lower layers
|
|
*/
|
|
emm_sap.primitive = EMMAS_DATA_IND;
|
|
emm_sap.u.emm_as.u.data.ueid = user->ueid;
|
|
emm_sap.u.emm_as.u.data.delivered = false;
|
|
emm_sap.u.emm_as.u.data.NASmsg.length = 0;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: nas_proc_dl_transfer_ind() **
|
|
** **
|
|
** Description: Processes downlink data transfer indication message re- **
|
|
** ceived from the network **
|
|
** **
|
|
** Inputs: data: The transfered NAS message **
|
|
** len: The length of the NAS message **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
int nas_proc_dl_transfer_ind(nas_user_t *user, const uint8_t *data, uint32_t len)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc = RETURNerror;
|
|
|
|
if (len > 0) {
|
|
emm_sap_t emm_sap;
|
|
/*
|
|
* Notify the EMM procedure call manager that data transfer
|
|
* indication has been received from the Access-Stratum sublayer
|
|
*/
|
|
emm_sap.primitive = EMMAS_DATA_IND;
|
|
emm_sap.u.emm_as.u.data.ueid = user->ueid;
|
|
emm_sap.u.emm_as.u.data.delivered = true;
|
|
emm_sap.u.emm_as.u.data.NASmsg.length = len;
|
|
emm_sap.u.emm_as.u.data.NASmsg.value = (uint8_t *)data;
|
|
rc = emm_sap_send(user, &emm_sap);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
/********************* L O C A L F U N C T I O N S *********************/
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: _nas_proc_activate() **
|
|
** **
|
|
** Description: Initiates a PDN connectivity procedure **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context used to es- **
|
|
** tablished connectivity to specified PDN **
|
|
** apply_to_all: true if the PDN connectivity procedure is **
|
|
** initiated to establish connectivity to all **
|
|
** defined PDNs **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
static int _nas_proc_activate(nas_user_t *user, int cid, bool apply_to_all)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc;
|
|
bool active = false;
|
|
|
|
esm_sap_t esm_sap;
|
|
|
|
/* Get PDN context parameters */
|
|
rc = esm_main_get_pdn(user->esm_data, cid, &esm_sap.data.pdn_connect.pdn_type,
|
|
&esm_sap.data.pdn_connect.apn,
|
|
&esm_sap.data.pdn_connect.is_emergency, &active);
|
|
|
|
if (rc != RETURNok) {
|
|
/* No any context is defined for the specified PDN */
|
|
if (apply_to_all) {
|
|
/* Go ahead to activate next PDN context */
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
/* Return an error */
|
|
LOG_FUNC_RETURN (RETURNerror);
|
|
}
|
|
|
|
if (active) {
|
|
/* The PDN context is already active */
|
|
LOG_TRACE(WARNING, "NAS-PROC - PDN connection %d is active", cid);
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
if (esm_sap.data.pdn_connect.is_emergency) {
|
|
if (esm_main_has_emergency(user->esm_data)) {
|
|
/* There is already a PDN connection for emergency
|
|
* bearer services established; the UE shall not
|
|
* request an additional PDN connection for emer-
|
|
* gency bearer services */
|
|
LOG_TRACE(WARNING, "NAS-PROC - PDN connection for emergency "
|
|
"bearer services is already established (cid=%d)", cid);
|
|
LOG_FUNC_RETURN (RETURNerror);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Notify ESM that a default EPS bearer has to be established
|
|
* for the specified PDN
|
|
*/
|
|
esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ;
|
|
esm_sap.is_standalone = true;
|
|
esm_sap.data.pdn_connect.is_defined = true;
|
|
esm_sap.data.pdn_connect.cid = cid;
|
|
rc = esm_sap_send(user, &esm_sap);
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
** **
|
|
** Name: _nas_proc_deactivate() **
|
|
** **
|
|
** Description: Initiates a PDN disconnect procedure **
|
|
** **
|
|
** Inputs: cid: Identifier of the PDN context **
|
|
** apply_to_all: true if the PDN disconnect procedure is **
|
|
** initiated to request disconnection from **
|
|
** all active PDNs **
|
|
** Others: None **
|
|
** **
|
|
** Outputs: None **
|
|
** Return: RETURNok, RETURNerror **
|
|
** Others: None **
|
|
** **
|
|
***************************************************************************/
|
|
static int _nas_proc_deactivate(nas_user_t *user, int cid, bool apply_to_all)
|
|
{
|
|
LOG_FUNC_IN;
|
|
|
|
int rc;
|
|
int pdn_type;
|
|
const char *apn;
|
|
bool emergency = false;
|
|
bool active = false;
|
|
|
|
/* Get PDN context parameters */
|
|
rc = esm_main_get_pdn(user->esm_data, cid, &pdn_type, &apn, &emergency, &active);
|
|
|
|
if (rc != RETURNok) {
|
|
/* No any context is defined for the specified PDN */
|
|
if (apply_to_all) {
|
|
/* Go ahead to deactivate next PDN connection */
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
LOG_FUNC_RETURN (RETURNerror);
|
|
}
|
|
|
|
if (!active) {
|
|
/* The PDN connection is already inactive */
|
|
LOG_TRACE(WARNING, "NAS-PROC - PDN connection %d is not active", cid);
|
|
LOG_FUNC_RETURN (RETURNok);
|
|
}
|
|
|
|
if (esm_main_get_nb_pdns(user->esm_data) > 1) {
|
|
/*
|
|
* Notify ESM that all EPS bearers towards the specified PDN
|
|
* has to be released
|
|
*/
|
|
esm_sap_t esm_sap;
|
|
esm_sap.primitive = ESM_PDN_DISCONNECT_REQ;
|
|
esm_sap.data.pdn_disconnect.cid = cid;
|
|
rc = esm_sap_send(user, &esm_sap);
|
|
} else {
|
|
/* For EPS, if an attempt is made to disconnect the last PDN
|
|
* connection, then the MT responds with an error */
|
|
LOG_TRACE(WARNING,"NAS-PROC - "
|
|
"Attempt to disconnect from the last PDN is not allowed");
|
|
rc = RETURNerror;
|
|
}
|
|
|
|
LOG_FUNC_RETURN (rc);
|
|
}
|
|
|
|
|