Files
openairinterface5g/openair-cn/NAS/EURECOM-NAS/src/api/mme/mme_api.c
T

502 lines
21 KiB
C

/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source mme_api.c
Version 0.1
Date 2013/02/28
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer running in the MME
to interact with a Mobility Management Entity
*****************************************************************************/
#ifdef NAS_MME
#include "mme_api.h"
#include "nas_log.h"
#include <string.h> // memcpy
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/* Maximum number of PDN connections the MME may simultaneously support */
#define MME_API_PDN_MAX 10
/* MME group identifier */
#define MME_API_MME_GID 0x0102
/* MME code */
#define MME_API_MME_CODE 0x12
/* Default APN */
static const OctetString mme_api_default_apn = {
14, (uint8_t*)("www.eurecom.fr")};
/* APN configured for emergency bearer services */
static const OctetString mme_api_emergency_apn = {
18, (uint8_t*)("www.eurecom_sos.fr")};
/* Public Land Mobile Network identifier */
static const plmn_t mme_api_plmn = {0, 2, 0xf, 8, 0, 1}; // 20810
/* Number of concecutive tracking areas */
#define MME_API_NB_TACS 4
/* Code of the first tracking area belonging to the PLMN */
#define MME_API_FIRST_TAC 0x0001
/* NAS security key */
#define MME_API_KASME "CAFECAFECAFECAFECAFECAFECAFECAFE"
/* Authentication parameter RAND */
static const UInt8_t _mme_api_rand[AUTH_RAND_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x03, 0x04
};
/* Authentication parameter AUTN */
static const UInt8_t _mme_api_autn[AUTH_AUTN_SIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x05, 0x04, 0x03, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00
};
/* Authentication response parameter */
static const UInt8_t _mme_api_xres[AUTH_XRES_SIZE] = {
0x67, 0x70, 0x3a, 0x31, 0xf2, 0x2a, 0x2d, 0x51, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
/* Network IP version capability */
enum {
MME_API_IPV4_ADDR,
MME_API_IPV6_ADDR,
MME_API_IPV4V6_ADDR,
MME_API_ADDR_MAX
} _mme_api_ip_capability = MME_API_IPV4V6_ADDR;
/* Pool of IPv4 addresses */
static uint8_t _mme_api_ipv4_addr[MME_API_PDN_MAX][4] = {
{0xC0, 0xA8, 0x02, 0x3C}, /* 192.168.02.60 */
{0xC0, 0xA8, 0x0C, 0xBB}, /* 192.168.12.187 */
{0xC0, 0xA8, 0x0C, 0xBC}, /* 192.168.12.188 */
{0xC0, 0xA8, 0x0C, 0xBD}, /* 192.168.12.189 */
{0xC0, 0xA8, 0x0C, 0xBE}, /* 192.168.12.190 */
{0xC0, 0xA8, 0x0C, 0xBF}, /* 192.168.12.191 */
{0xC0, 0xA8, 0x0C, 0xC0}, /* 192.168.12.192 */
{0xC0, 0xA8, 0x0C, 0xC1}, /* 192.168.12.193 */
{0xC0, 0xA8, 0x0C, 0xC2}, /* 192.168.12.194 */
{0xC0, 0xA8, 0x0C, 0xC3}, /* 192.168.12.195 */
};
/* Pool of IPv6 addresses */
static uint8_t _mme_api_ipv6_addr[MME_API_PDN_MAX][8] = {
/* FE80::221:70FF:C0A8:023C/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x02, 0x3C},
/* FE80::221:70FF:C0A8:0CBB/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBB},
/* FE80::221:70FF:C0A8:0CBC/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBC},
/* FE80::221:70FF:C0A8:0CBD/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBD},
/* FE80::221:70FF:C0A8:0CBE/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBE},
/* FE80::221:70FF:C0A8:0CBF/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBF},
/* FE80::221:70FF:C0A8:0CC0/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC0},
/* FE80::221:70FF:C0A8:0CC1/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC1},
/* FE80::221:70FF:C0A8:0CC2/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC2},
/* FE80::221:70FF:C0A8:0CC3/64 */
{0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC3},
};
/* Pool of IPv4v6 addresses */
static uint8_t _mme_api_ipv4v6_addr[MME_API_PDN_MAX][12] = {
/* 192.168.02.60, FE80::221:70FF:C0A8:023C/64 */
{0xC0, 0xA8, 0x02, 0x3C, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x02, 0x3C},
/* 192.168.12.187, FE80::221:70FF:C0A8:0CBB/64 */
{0xC0, 0xA8, 0x0C, 0xBB, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBB},
/* 192.168.12.188, FE80::221:70FF:C0A8:0CBC/64 */
{0xC0, 0xA8, 0x0C, 0xBC, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBC},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CBD/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBD},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CBE/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBE},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CBF/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xBF},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CC0/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC0},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CC1/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC1},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CC2/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC2},
/* 192.168.12.189, FE80::221:70FF:C0A8:0CC3/64 */
{0xC0, 0xA8, 0x0C, 0xBD, 0x02, 0x21, 0x70, 0xFF, 0xC0, 0xA8, 0x0C, 0xC3},
};
static const OctetString _mme_api_pdn_addr[MME_API_ADDR_MAX][MME_API_PDN_MAX] =
{
{ /* IPv4 network capability */
{4, _mme_api_ipv4_addr[0]},
{4, _mme_api_ipv4_addr[1]},
{4, _mme_api_ipv4_addr[2]},
{4, _mme_api_ipv4_addr[3]},
{4, _mme_api_ipv4_addr[4]},
{4, _mme_api_ipv4_addr[5]},
{4, _mme_api_ipv4_addr[6]},
{4, _mme_api_ipv4_addr[7]},
{4, _mme_api_ipv4_addr[8]},
{4, _mme_api_ipv4_addr[9]},
},
{ /* IPv6 network capability */
{8, _mme_api_ipv6_addr[0]},
{8, _mme_api_ipv6_addr[1]},
{8, _mme_api_ipv6_addr[2]},
{8, _mme_api_ipv6_addr[3]},
{8, _mme_api_ipv6_addr[4]},
{8, _mme_api_ipv6_addr[5]},
{8, _mme_api_ipv6_addr[6]},
{8, _mme_api_ipv6_addr[7]},
{8, _mme_api_ipv6_addr[8]},
{8, _mme_api_ipv6_addr[9]},
},
{ /* IPv4v6 network capability */
{12, _mme_api_ipv4v6_addr[0]},
{12, _mme_api_ipv4v6_addr[1]},
{12, _mme_api_ipv4v6_addr[2]},
{12, _mme_api_ipv4v6_addr[3]},
{12, _mme_api_ipv4v6_addr[4]},
{12, _mme_api_ipv4v6_addr[5]},
{12, _mme_api_ipv4v6_addr[6]},
{12, _mme_api_ipv4v6_addr[7]},
{12, _mme_api_ipv4v6_addr[8]},
{12, _mme_api_ipv4v6_addr[9]},
},
};
/* Subscribed QCI */
#define MME_API_QCI 3
/* Data bit rates */
#define MME_API_BIT_RATE_64K 0x40
#define MME_API_BIT_RATE_128K 0x48
#define MME_API_BIT_RATE_512K 0x78
#define MME_API_BIT_RATE_1024K 0x87
/* Total number of PDN connections (should not exceed MME_API_PDN_MAX) */
static int _mme_api_pdn_id = 0;
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: mme_api_get_emm_config() **
** **
** Description: Retreives MME configuration data related to EPS mobility **
** management **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_get_emm_config(mme_api_emm_config_t* config)
{
LOG_FUNC_IN;
config->gummei.plmn.MCCdigit1 = 2;
config->gummei.plmn.MCCdigit2 = 0;
config->gummei.plmn.MCCdigit3 = 8;
config->gummei.plmn.MNCdigit1 = 1;
config->gummei.plmn.MNCdigit2 = 0;
config->gummei.plmn.MNCdigit3 = 0xf;
config->gummei.MMEgid = MME_API_MME_GID;
config->gummei.MMEcode = MME_API_MME_CODE;
config->features = MME_API_EMERGENCY_ATTACH | MME_API_UNAUTHENTICATED_IMSI;
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: mme_api_get_config() **
** **
** Description: Retreives MME configuration data related to EPS session **
** management **
** **
** Inputs: None **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_get_esm_config(mme_api_esm_config_t* config)
{
LOG_FUNC_IN;
if (_mme_api_ip_capability == MME_API_IPV4_ADDR) {
config->features = MME_API_IPV4;
} else if (_mme_api_ip_capability == MME_API_IPV6_ADDR) {
config->features = MME_API_IPV6;
} else if (_mme_api_ip_capability == MME_API_IPV4V6_ADDR) {
config->features = MME_API_IPV4 | MME_API_IPV6;
} else {
config->features = 0;
}
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: mme_api_identify_guti() **
** **
** Description: Requests the MME to identify the UE using the specified **
** GUTI. If the UE is known by the MME (a Mobility Manage- **
** ment context exists for this UE in the MME), its se- **
** curity context is returned. **
** **
** Inputs: guti: EPS Globally Unique Temporary UE Identity **
** Others: None **
** **
** Outputs: vector: The EPS authentication vector of the UE if **
** known by the network; NULL otherwise. **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_identify_guti(const GUTI_t* guti, auth_vector_t* vector)
{
LOG_FUNC_IN;
int rc = RETURNerror;
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: mme_api_identify_imsi() **
** **
** Description: Requests the MME to identify the UE using the specified **
** IMSI. If the UE is known by the MME (a Mobility Manage- **
** ment context exists for this UE in the MME), its se- **
** curity context is returned. **
** **
** Inputs: imsi: International Mobile Subscriber Identity **
** Others: None **
** **
** Outputs: vector: The EPS authentication vector of the UE if **
** known by the network; NULL otherwise. **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_identify_imsi(const imsi_t* imsi, auth_vector_t* vector)
{
LOG_FUNC_IN;
int rc = RETURNok;
memcpy(vector->rand, _mme_api_rand, AUTH_RAND_SIZE);
memcpy(vector->autn, _mme_api_autn, AUTH_AUTN_SIZE);
memcpy(vector->xres, _mme_api_xres, AUTH_XRES_SIZE);
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: mme_api_identify_imei() **
** **
** Description: Requests the MME to identify the UE using the specified **
** IMEI. If the UE is known by the MME (a Mobility Manage- **
** ment context exists for this UE in the MME), its se- **
** curity context is returned. **
** **
** Inputs: imei: International Mobile Equipment Identity **
** Others: None **
** **
** Outputs: vector: The EPS authentication vector of the UE if **
** known by the network; NULL otherwise. **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_identify_imei(const imei_t* imei, auth_vector_t* vector)
{
LOG_FUNC_IN;
int rc = RETURNerror;
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: mme_api_new_guti() **
** **
** Description: Requests the MME to assign a new GUTI to the UE identi- **
** fied by the given IMSI. **
** **
** Description: Requests the MME to assign a new GUTI to the UE identi- **
** fied by the given IMSI and returns the list of consecu- **
** tive tracking areas the UE is registered to. **
** **
** Inputs: imsi: International Mobile Subscriber Identity **
** Others: None **
** **
** Outputs: guti: The new assigned GUTI **
** tac: Code of the first tracking area belonging **
** to the PLMN **
** n_tacs: Number of concecutive tracking areas **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_new_guti(const imsi_t* imsi, GUTI_t* guti, tac_t* tac, int* n_tacs)
{
LOG_FUNC_IN;
int rc = RETURNok;
static unsigned int tmsi = 1;
guti->gummei.plmn = mme_api_plmn;
guti->gummei.MMEgid = MME_API_MME_GID;
guti->gummei.MMEcode = MME_API_MME_CODE;
guti->m_tmsi = tmsi++;
*tac = MME_API_FIRST_TAC;
*n_tacs = MME_API_NB_TACS;
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: mme_api_subscribe() **
** **
** Description: Requests the MME to check whether connectivity with the **
** requested PDN can be established using the specified APN. **
** If accepted the MME returns PDN subscription context con- **
** taining EPS subscribed QoS profile, the default APN if **
** required and UE's IPv4 address and/or the IPv6 prefix. **
** **
** Inputs: apn: If not NULL, Access Point Name of the PDN **
** to connect to **
** is_emergency: TRUE if the PDN connectivity is requested **
** for emergency bearer services **
** Others: None **
** **
** Outputs: apn: If NULL, default APN or APN configured for **
** emergency bearer services **
** pdn_addr: PDN connection IPv4 address or IPv6 inter- **
** face identifier to be used to build the **
** IPv6 link local address **
** qos: EPS subscribed QoS profile **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_subscribe(OctetString* apn, OctetString* pdn_addr,
int is_emergency, mme_api_qos_t* qos)
{
LOG_FUNC_IN;
int rc = RETURNok;
if ( apn && (apn->length == 0) ) {
/* PDN connectivity to default APN */
if (is_emergency) {
apn->length = mme_api_emergency_apn.length;
apn->value = mme_api_emergency_apn.value;
} else {
apn->length = mme_api_default_apn.length;
apn->value = mme_api_default_apn.value;
}
}
/* Assign PDN address */
if ( pdn_addr && (_mme_api_pdn_id < MME_API_PDN_MAX) ) {
pdn_addr->length =
_mme_api_pdn_addr[_mme_api_ip_capability][_mme_api_pdn_id].length;
pdn_addr->value =
_mme_api_pdn_addr[_mme_api_ip_capability][_mme_api_pdn_id].value;
/* Increment the total number of PDN connections */
_mme_api_pdn_id += 1;
} else {
/* Maximum number of PDN connections exceeded */
rc = RETURNerror;
}
/* Setup EPS subscribed QoS profile */
if (qos) {
qos->qci = MME_API_QCI;
/* Uplink bit rate */
qos->gbr[MME_API_UPLINK] = MME_API_BIT_RATE_64K;
qos->mbr[MME_API_UPLINK] = MME_API_BIT_RATE_128K;
/* Downlink bit rate */
qos->gbr[MME_API_DOWNLINK] = MME_API_BIT_RATE_512K;
qos->mbr[MME_API_DOWNLINK] = MME_API_BIT_RATE_1024K;
} else {
rc = RETURNerror;
}
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: mme_api_unsubscribe() **
** **
** Description: Requests the MME to release connectivity with the reques- **
** ted PDN using the specified APN. **
** **
** Inputs: apn: Access Point Name of the PDN to disconnect **
** from **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int mme_api_unsubscribe(OctetString* apn)
{
LOG_FUNC_IN;
int rc = RETURNok;
/* Decrement the total number of PDN connections */
_mme_api_pdn_id -= 1;
LOG_FUNC_RETURN(rc);
}
#endif // NAS_MME