git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4234 818b1a75-f10b-46b9-bf7c-635c3b92a50f

This commit is contained in:
Cedric Roux
2013-10-21 08:08:15 +00:00
parent ff4360527c
commit d7c8c99e2d
860 changed files with 212101 additions and 0 deletions
@@ -0,0 +1,47 @@
ifndef PROJDIR
export PROJDIR = $(PWD)/../..
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
export INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR)
TARGET = $(LIBAPI)
TARGETS = $(TARGET).a $(TARGET).so
OBJS = $(USERAPIDIR)/*.o $(NETAPIDIR)/*.o $(USIMAPIDIR)/*.o $(MMEAPIDIR)/*.o
all:
@$(CD) $(NETAPIDIR) && $(MAKE)
@$(CD) $(USERAPIDIR) && $(MAKE)
@$(CD) $(USIMAPIDIR) && $(MAKE)
@$(CD) $(MMEAPIDIR) && $(MAKE)
@$(MAKE) $(TARGETS)
$(TARGET).a: $(OBJS)
@$(RM) $@
@$(AR) $(ARFLAGS) $@ $^
@echo Replacing $@ to $(LIBPROCESS)
@$(RM) $(LIBPROCESS)/$@
@$(CP) $@ $(LIBPROCESS)
$(TARGET).so: $(OBJS)
@$(LD) -G -o $@ $^
@echo Replacing $@ to $(LIBPROCESS)
@$(RM) $(LIBPROCESS)/$@
@$(CP) $@ $(LIBPROCESS)
clean:
$(RM) *.bak *~
@$(CD) $(USERAPIDIR) && $(MAKE) $@
@$(CD) $(NETAPIDIR) && $(MAKE) $@
@$(CD) $(USIMAPIDIR) && $(MAKE) $@
@$(CD) $(MMEAPIDIR) && $(MAKE) $@
veryclean: clean
$(RM) $(TARGETS)
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
@@ -0,0 +1,21 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../..
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR)
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
all: $(OBJS)
%.o: %.c Makefile
@echo Compiling $<
@$(CC) $(CFLAGS) -c $< -o $@
clean:
$(RM) $(OBJS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
@@ -0,0 +1,501 @@
/*****************************************************************************
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
@@ -0,0 +1,105 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source mme_api.h
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
*****************************************************************************/
#ifndef __MME_API_H__
#define __MME_API_H__
#ifdef NAS_MME
#include "commonDef.h"
#include "securityDef.h"
#include "OctetString.h"
#endif
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/* Maximum number of UEs the MME may simultaneously support */
#define MME_API_NB_UE_MAX 1
#ifdef NAS_MME
/* Features supported by the MME */
typedef enum {
MME_API_NO_FEATURE_SUPPORTED = 0,
MME_API_EMERGENCY_ATTACH = (1<<0),
MME_API_UNAUTHENTICATED_IMSI = (1<<1),
MME_API_IPV4 = (1<<2),
MME_API_IPV6 = (1<<3),
MME_API_SINGLE_ADDR_BEARERS = (1<<4),
} mme_api_feature_t;
/*
* EPS Mobility Management configuration data
* ------------------------------------------
*/
typedef struct {
mme_api_feature_t features; /* Supported features */
gummei_t gummei; /* EPS Globally Unique MME Identity */
} mme_api_emm_config_t;
/*
* EPS Session Management configuration data
* -----------------------------------------
*/
typedef struct {
mme_api_feature_t features; /* Supported features */
} mme_api_esm_config_t;
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* EPS subscribed QoS profile */
typedef struct {
#define MME_API_UPLINK 0
#define MME_API_DOWNLINK 1
#define MME_API_DIRECTION 2
int gbr[MME_API_DIRECTION]; /* Guaranteed Bit Rate */
int mbr[MME_API_DIRECTION]; /* Maximum Bit Rate */
int qci; /* QoS Class Identifier */
} mme_api_qos_t;
/* Traffic Flow Template */
typedef struct {
} mme_api_tft_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int mme_api_get_emm_config(mme_api_emm_config_t* config);
int mme_api_get_esm_config(mme_api_esm_config_t* config);
int mme_api_identify_guti(const GUTI_t* guti, auth_vector_t* vector);
int mme_api_identify_imsi(const imsi_t* imsi, auth_vector_t* vector);
int mme_api_identify_imei(const imei_t* imei, auth_vector_t* vector);
int mme_api_new_guti(const imsi_t* imsi, GUTI_t* guti, tac_t* tac, int* n_tacs);
int mme_api_subscribe(OctetString* apn, OctetString* pdn_addr, int is_emergency, mme_api_qos_t* qos);
int mme_api_unsubscribe(OctetString* apn);
#endif // NAS_MME
#endif /* __MME_API_H__*/
@@ -0,0 +1,185 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../..
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR)
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
all: $(OBJS)
%.o: %.c Makefile
@echo Compiling $<
@$(CC) $(CFLAGS) -c $< -o $@
clean:
$(RM) $(OBJS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
as_message.o: as_message.h
as_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/include/commonDef.h
as_message.o: /usr/include/stdint.h /usr/include/features.h
as_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/include/networkDef.h
as_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/nas_log.h
as_message.o: /usr/include/string.h /usr/include/xlocale.h
as_message.o: /usr/include/stdlib.h /usr/include/alloca.h
nas_message.o: nas_message.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/include/commonDef.h
nas_message.o: /usr/include/stdint.h /usr/include/features.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/emm_msg.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/emm_msgDef.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AttachRequest.h
nas_message.o: /usr/include/stdio.h /usr/include/libio.h
nas_message.o: /usr/include/_G_config.h /usr/include/wchar.h
nas_message.o: /usr/include/stdlib.h /usr/include/alloca.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ProtocolDiscriminator.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/OctetString.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/SecurityHeaderType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/MessageType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsAttachType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/NasKeySetIdentifier.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsMobileIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EsmMessageContainer.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PTmsiSignature.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TrackingAreaIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/DrxParameter.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/MsNetworkCapability.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/LocationAreaIdentification.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TmsiStatus.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/MobileStationClassmark2.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/MobileStationClassmark3.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/SupportedCodecList.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AdditionalUpdateType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/GutiType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AttachAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsAttachResult.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/GprsTimer.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TrackingAreaIdentityList.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/MobileIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EmmCause.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PlmnList.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EmergencyNumberList.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsNetworkFeatureSupport.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AdditionalUpdateResult.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AttachComplete.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AttachReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/DetachRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/DetachType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/DetachAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/TrackingAreaUpdateRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsUpdateType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/CipheringKeySequenceNumber.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/Nonce.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/UeRadioCapabilityInformationUpdateNeeded.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsBearerContextStatus.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/TrackingAreaUpdateAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsUpdateResult.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/TrackingAreaUpdateComplete.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/TrackingAreaUpdateReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/ExtendedServiceRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ServiceType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/CsfbResponse.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/ServiceRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/KsiAndSequenceNumber.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ShortMac.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/ServiceReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/GutiReallocationCommand.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/GutiReallocationComplete.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AuthenticationRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AuthenticationParameterRand.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AuthenticationParameterAutn.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AuthenticationResponse.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AuthenticationResponseParameter.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AuthenticationReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/AuthenticationFailure.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AuthenticationFailureParameter.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/IdentityRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/IdentityType2.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/IdentityResponse.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/SecurityModeCommand.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/NasSecurityAlgorithms.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ImeisvRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/SecurityModeComplete.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/SecurityModeReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/EmmStatus.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/EmmInformation.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/NetworkName.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TimeZone.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TimeZoneAndTime.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/DaylightSavingTime.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/DownlinkNasTransport.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/NasMessageContainer.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/UplinkNasTransport.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/emm/msg/CsServiceNotification.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PagingIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/Cli.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/SsCode.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/LcsIndicator.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/LcsClientIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/esm_msg.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/esm_msgDef.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDedicatedEpsBearerContextRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsBearerIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ProcedureTransactionIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/LinkedEpsBearerIdentity.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EpsQualityOfService.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TrafficFlowTemplate.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TransactionIdentifier.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/QualityOfService.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/LlcServiceAccessPointIdentifier.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/RadioPriority.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PacketFlowIdentifier.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ProtocolConfigurationOptions.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDedicatedEpsBearerContextAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDedicatedEpsBearerContextReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EsmCause.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/AccessPointName.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PdnAddress.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/ApnAggregateMaximumBitRate.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ActivateDefaultEpsBearerContextReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ModifyEpsBearerContextRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ModifyEpsBearerContextAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/ModifyEpsBearerContextReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/DeactivateEpsBearerContextRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/DeactivateEpsBearerContextAccept.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/PdnDisconnectRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/PdnDisconnectReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/PdnConnectivityRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/RequestType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/PdnType.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/EsmInformationTransferFlag.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/PdnConnectivityReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/BearerResourceAllocationRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/ies/TrafficFlowAggregateDescription.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/BearerResourceAllocationReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/BearerResourceModificationRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/BearerResourceModificationReject.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/EsmInformationRequest.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/EsmInformationResponse.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/esm/msg/EsmStatus.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/nas_log.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/TLVDecoder.h
nas_message.o: /usr/include/arpa/inet.h /usr/include/netinet/in.h
nas_message.o: /usr/include/endian.h
nas_message.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/TLVEncoder.h
nas_message.o: /usr/include/string.h /usr/include/xlocale.h
network_api.o: network_api.h
network_api.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/include/commonDef.h
network_api.o: /usr/include/stdint.h /usr/include/features.h
network_api.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/nas_log.h
network_api.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/util/socket.h
network_api.o: as_message.h
network_api.o: /homes/roux/lte-epc/openair3/OPENAIRMME/NAS/EURECOM-NAS/src/include/networkDef.h
network_api.o: /usr/include/string.h /usr/include/xlocale.h
network_api.o: /usr/include/netdb.h /usr/include/netinet/in.h
network_api.o: /usr/include/endian.h /usr/include/rpc/netdb.h
network_api.o: /usr/include/errno.h /usr/include/unistd.h
network_api.o: /usr/include/getopt.h
@@ -0,0 +1,347 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source as_message.c
Version 0.1
Date 2012/11/06
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the messages supported by the Access Stratum sublayer
protocol (usually RRC and S1AP for E-UTRAN) and functions used
to encode and decode
*****************************************************************************/
#include "as_message.h"
#include "commonDef.h"
#include "nas_log.h"
#include <string.h> // memcpy
#include <stdlib.h> // free
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: as_message_decode() **
** **
** Description: Decode AS message and accordingly fills data structure **
** **
** Inputs: buffer: Pointer to the buffer containing the **
** message **
** length: Number of bytes that should be decoded **
** Others: None **
** **
** Outputs: msg: AS message structure to be filled **
** Return: The AS message identifier when the buffer **
** has been successfully decoded; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
int as_message_decode(const char* buffer, as_message_t* msg, int length)
{
LOG_FUNC_IN;
int bytes;
Byte_t** data = NULL;
/* Get the message type */
msg->msgID = *(UInt16_t*)(buffer);
bytes = sizeof(UInt16_t);
switch (msg->msgID)
{
case AS_NAS_ESTABLISH_REQ:
/* NAS signalling connection establish request */
bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*);
data = &msg->msg.nas_establish_req.initialNasMsg.data;
break;
case AS_NAS_ESTABLISH_IND:
/* NAS signalling connection establishment indication */
bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
data = &msg->msg.nas_establish_ind.initialNasMsg.data;
break;
case AS_NAS_ESTABLISH_RSP:
/* NAS signalling connection establishment response */
bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*);
data = &msg->msg.nas_establish_rsp.nasMsg.data;
break;
case AS_NAS_ESTABLISH_CNF:
/* NAS signalling connection establishment confirm */
bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
data = &msg->msg.nas_establish_cnf.nasMsg.data;
break;
case AS_UL_INFO_TRANSFER_REQ:
/* Uplink L3 data transfer request */
bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*);
data = &msg->msg.ul_info_transfer_req.nasMsg.data;
break;
case AS_UL_INFO_TRANSFER_IND:
/* Uplink L3 data transfer indication */
bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*);
data = &msg->msg.ul_info_transfer_ind.nasMsg.data;
break;
case AS_DL_INFO_TRANSFER_REQ:
/* Downlink L3 data transfer request */
bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
data = &msg->msg.dl_info_transfer_req.nasMsg.data;
break;
case AS_DL_INFO_TRANSFER_IND:
/* Downlink L3 data transfer indication */
bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*);
data = &msg->msg.dl_info_transfer_ind.nasMsg.data;
break;
case AS_BROADCAST_INFO_IND:
case AS_CELL_INFO_REQ:
case AS_CELL_INFO_CNF:
case AS_CELL_INFO_IND:
case AS_PAGING_REQ:
case AS_PAGING_IND:
case AS_NAS_RELEASE_REQ:
case AS_UL_INFO_TRANSFER_CNF:
case AS_DL_INFO_TRANSFER_CNF:
case AS_NAS_RELEASE_IND:
case AS_RAB_ESTABLISH_REQ:
case AS_RAB_ESTABLISH_IND:
case AS_RAB_ESTABLISH_RSP:
case AS_RAB_ESTABLISH_CNF:
case AS_RAB_RELEASE_REQ:
case AS_RAB_RELEASE_IND:
/* Messages without dedicated NAS information */
bytes = length;
break;
default:
bytes = 0;
LOG_TRACE(WARNING, "NET-API - AS message 0x%x is not valid",
msg->msgID);
break;
}
if (bytes > 0) {
if (data) {
/* Set the pointer to dedicated NAS information */
*data = (Byte_t*)(buffer + bytes);
}
/* Decode the message */
memcpy(msg, (as_message_t*)buffer, bytes);
LOG_FUNC_RETURN (msg->msgID);
}
LOG_TRACE(WARNING, "NET-API - Failed to decode AS message 0x%x",
msg->msgID);
LOG_FUNC_RETURN (RETURNerror);
}
/****************************************************************************
** **
** Name: as_message_encode() **
** **
** Description: Encode AS message **
** **
** Inputs: msg: AS message structure to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of characters in the buffer **
** when data have been successfully encoded; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
int as_message_encode(char* buffer, as_message_t* msg, int length)
{
LOG_FUNC_IN;
int bytes = sizeof(msg->msgID);
as_nas_info_t* nas_msg = NULL;
switch (msg->msgID)
{
case AS_BROADCAST_INFO_IND:
/* Broadcast information */
bytes += sizeof(broadcast_info_ind_t);
break;
case AS_CELL_INFO_REQ:
/* Cell information request */
bytes += sizeof(cell_info_req_t);
break;
case AS_CELL_INFO_CNF:
/* Cell information response */
bytes += sizeof(cell_info_cnf_t);
break;
case AS_CELL_INFO_IND:
/* Cell information indication */
bytes += sizeof(cell_info_ind_t);
break;
case AS_PAGING_REQ:
/* Paging information request */
bytes += sizeof(paging_req_t);
break;
case AS_PAGING_IND:
/* Paging information indication */
bytes += sizeof(paging_ind_t);
break;
case AS_NAS_ESTABLISH_REQ:
/* NAS signalling connection establish request */
bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.nas_establish_req.initialNasMsg;
break;
case AS_NAS_ESTABLISH_IND:
/* NAS signalling connection establish indication */
bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.nas_establish_ind.initialNasMsg;
break;
case AS_NAS_ESTABLISH_RSP:
/* NAS signalling connection establish response */
bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.nas_establish_rsp.nasMsg;
break;
case AS_NAS_ESTABLISH_CNF:
/* NAS signalling connection establish confirm */
bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.nas_establish_cnf.nasMsg;
break;
case AS_NAS_RELEASE_REQ:
/* NAS signalling connection release request */
bytes += sizeof(nas_release_req_t);
break;
case AS_NAS_RELEASE_IND:
/* NAS signalling connection release indication */
bytes += sizeof(nas_release_ind_t);
break;
case AS_UL_INFO_TRANSFER_REQ:
/* Uplink L3 data transfer request */
bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.ul_info_transfer_req.nasMsg;
break;
case AS_UL_INFO_TRANSFER_CNF:
/* Uplink L3 data transfer confirm */
bytes += sizeof(ul_info_transfer_cnf_t);
break;
case AS_UL_INFO_TRANSFER_IND:
/* Uplink L3 data transfer indication */
bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.ul_info_transfer_ind.nasMsg;
break;
case AS_DL_INFO_TRANSFER_REQ:
/* Downlink L3 data transfer */
bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.dl_info_transfer_req.nasMsg;
break;
case AS_DL_INFO_TRANSFER_CNF:
/* Downlink L3 data transfer confirm */
bytes += sizeof(dl_info_transfer_cnf_t);
break;
case AS_DL_INFO_TRANSFER_IND:
/* Downlink L3 data transfer indication */
bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*);
nas_msg = &msg->msg.dl_info_transfer_ind.nasMsg;
break;
case AS_RAB_ESTABLISH_REQ:
/* Radio Access Bearer establishment request */
bytes += sizeof(rab_establish_req_t);
break;
case AS_RAB_ESTABLISH_IND:
/* Radio Access Bearer establishment indication */
bytes += sizeof(rab_establish_ind_t);
break;
case AS_RAB_ESTABLISH_RSP:
/* Radio Access Bearer establishment response */
bytes += sizeof(rab_establish_rsp_t);
break;
case AS_RAB_ESTABLISH_CNF:
/* Radio Access Bearer establishment confirm */
bytes += sizeof(rab_establish_cnf_t);
break;
case AS_RAB_RELEASE_REQ:
/* Radio Access Bearer release request */
bytes += sizeof(rab_release_req_t);
break;
case AS_RAB_RELEASE_IND:
/* Radio Access Bearer release indication */
bytes += sizeof(rab_release_ind_t);
break;
default:
LOG_TRACE(WARNING, "NET-API - AS message 0x%x is not valid",
msg->msgID);
bytes = length;
break;
}
if (length > bytes) {
/* Encode the AS message */
memcpy(buffer, (unsigned char*)msg, bytes);
if ( nas_msg && (nas_msg->length > 0) ) {
/* Copy the NAS message */
memcpy(buffer + bytes, nas_msg->data, nas_msg->length);
bytes += nas_msg->length;
/* Release NAS message memory */
free(nas_msg->data);
nas_msg->length = 0;
nas_msg->data = NULL;
}
LOG_FUNC_RETURN (bytes);
}
LOG_TRACE(WARNING, "NET-API - Failed to encode AS message 0x%x",
msg->msgID);
LOG_FUNC_RETURN (RETURNerror);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
@@ -0,0 +1,515 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source as_message.h
Version 0.1
Date 2012/10/18
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the messages supported by the Access Stratum sublayer
protocol (usually RRC and S1AP for E-UTRAN) and functions used
to encode and decode
*****************************************************************************/
#ifndef __AS_MESSAGE_H__
#define __AS_MESSAGE_H__
#include "commonDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/*
* --------------------------------------------------------------------------
* Access Stratum message types
* --------------------------------------------------------------------------
*/
#define AS_REQUEST 0x0100
#define AS_RESPONSE 0x0200
#define AS_INDICATION 0x0400
#define AS_CONFIRM 0x0800
/*
* --------------------------------------------------------------------------
* Access Stratum message identifiers
* --------------------------------------------------------------------------
*/
/* Broadcast information */
#define AS_BROADCAST_INFO 0x01
#define AS_BROADCAST_INFO_IND (AS_BROADCAST_INFO | AS_INDICATION)
/* Cell information relevant for cell selection processing */
#define AS_CELL_INFO 0x02
#define AS_CELL_INFO_REQ (AS_CELL_INFO | AS_REQUEST)
#define AS_CELL_INFO_CNF (AS_CELL_INFO | AS_CONFIRM)
#define AS_CELL_INFO_IND (AS_CELL_INFO | AS_INDICATION)
/* Paging information */
#define AS_PAGING 0x03
#define AS_PAGING_REQ (AS_PAGING | AS_REQUEST)
#define AS_PAGING_IND (AS_PAGING | AS_INDICATION)
/* NAS signalling connection establishment */
#define AS_NAS_ESTABLISH 0x04
#define AS_NAS_ESTABLISH_REQ (AS_NAS_ESTABLISH | AS_REQUEST)
#define AS_NAS_ESTABLISH_IND (AS_NAS_ESTABLISH | AS_INDICATION)
#define AS_NAS_ESTABLISH_RSP (AS_NAS_ESTABLISH | AS_RESPONSE)
#define AS_NAS_ESTABLISH_CNF (AS_NAS_ESTABLISH | AS_CONFIRM)
/* NAS signalling connection release */
#define AS_NAS_RELEASE 0x05
#define AS_NAS_RELEASE_REQ (AS_NAS_RELEASE | AS_REQUEST)
#define AS_NAS_RELEASE_IND (AS_NAS_RELEASE | AS_INDICATION)
/* Uplink information transfer */
#define AS_UL_INFO_TRANSFER 0x06
#define AS_UL_INFO_TRANSFER_REQ (AS_UL_INFO_TRANSFER | AS_REQUEST)
#define AS_UL_INFO_TRANSFER_CNF (AS_UL_INFO_TRANSFER | AS_CONFIRM)
#define AS_UL_INFO_TRANSFER_IND (AS_UL_INFO_TRANSFER | AS_INDICATION)
/* Downlink information transfer */
#define AS_DL_INFO_TRANSFER 0x07
#define AS_DL_INFO_TRANSFER_REQ (AS_DL_INFO_TRANSFER | AS_REQUEST)
#define AS_DL_INFO_TRANSFER_CNF (AS_DL_INFO_TRANSFER | AS_CONFIRM)
#define AS_DL_INFO_TRANSFER_IND (AS_DL_INFO_TRANSFER | AS_INDICATION)
/* Radio Access Bearer establishment */
#define AS_RAB_ESTABLISH 0x08
#define AS_RAB_ESTABLISH_REQ (AS_RAB_ESTABLISH | AS_REQUEST)
#define AS_RAB_ESTABLISH_IND (AS_RAB_ESTABLISH | AS_INDICATION)
#define AS_RAB_ESTABLISH_RSP (AS_RAB_ESTABLISH | AS_RESPONSE)
#define AS_RAB_ESTABLISH_CNF (AS_RAB_ESTABLISH | AS_CONFIRM)
/* Radio Access Bearer release */
#define AS_RAB_RELEASE 0x09
#define AS_RAB_RELEASE_REQ (AS_RAB_RELEASE | AS_REQUEST)
#define AS_RAB_RELEASE_IND (AS_RAB_RELEASE | AS_INDICATION)
/*
* --------------------------------------------------------------------------
* Access Stratum message global parameters
* --------------------------------------------------------------------------
*/
/* Error code */
enum {
AS_SUCCESS = 1, /* Success code, transaction is going on */
AS_TERMINATED_NAS, /* Transaction terminated by NAS */
AS_TERMINATED_AS, /* Transaction terminated by AS */
AS_FAILURE /* Failure code */
};
/* Core network domain */
enum {
AS_PS = 1, /* Packet-Switched */
AS_CS /* Circuit-Switched */
};
/* SAE Temporary Mobile Subscriber Identity */
typedef struct {
UInt8_t MMEcode; /* MME code that allocated the GUTI */
UInt32_t m_tmsi; /* M-Temporary Mobile Subscriber Identity */
} as_stmsi_t;
/* Dedicated NAS information */
typedef struct {
UInt32_t length; /* Length of the NAS information data */
Byte_t* data; /* Dedicated NAS information data container */
} as_nas_info_t;
/* Radio Access Bearer identity */
typedef UInt8_t as_rab_id_t;
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* --------------------------------------------------------------------------
* Broadcast information
* --------------------------------------------------------------------------
*/
/*
* AS->NAS - Broadcast information indication
* AS may asynchronously report to NAS available PLMNs within specific
* location area
*/
typedef struct {
#define PLMN_LIST_MAX_SIZE 6
PLMN_LIST_T(PLMN_LIST_MAX_SIZE) plmnIDs; /* List of PLMN identifiers */
ci_t cellID; /* Identity of the cell serving the listed PLMNs */
tac_t tac; /* Code of the tracking area the cell belongs to */
} broadcast_info_ind_t;
/*
* --------------------------------------------------------------------------
* Cell information relevant for cell selection processing
* --------------------------------------------------------------------------
*/
/* Radio access technologies supported by the network */
#define AS_GSM (1 << NET_ACCESS_GSM)
#define AS_COMPACT (1 << NET_ACCESS_COMPACT)
#define AS_UTRAN (1 << NET_ACCESS_UTRAN)
#define AS_EGPRS (1 << NET_ACCESS_EGPRS)
#define AS_HSDPA (1 << NET_ACCESS_HSDPA)
#define AS_HSUPA (1 << NET_ACCESS_HSUPA)
#define AS_HSDUPA (1 << NET_ACCESS_HSDUPA)
#define AS_EUTRAN (1 << NET_ACCESS_EUTRAN)
/*
* NAS->AS - Cell Information request
* NAS request AS to search for a suitable cell belonging to the selected
* PLMN to camp on.
*/
typedef struct {
plmn_t plmnID; /* Selected PLMN identity */
Byte_t rat; /* Bitmap - set of radio access technologies */
} cell_info_req_t;
/*
* AS->NAS - Cell Information confirm
* AS search for a suitable cell and respond to NAS. If found, the cell
* is selected to camp on.
*/
typedef struct {
UInt8_t errCode; /* Error code */
ci_t cellID; /* Identity of the cell serving the selected PLMN */
tac_t tac; /* Code of the tracking area the cell belongs to */
AcT_t rat; /* Radio access technology supported by the cell */
UInt8_t rsrq; /* Reference signal received quality */
UInt8_t rsrp; /* Reference signal received power */
} cell_info_cnf_t;
/*
* AS->NAS - Cell Information indication
* AS may change cell selection if a more suitable cell is found.
*/
typedef struct {
ci_t cellID; /* Identity of the new serving cell */
tac_t tac; /* Code of the tracking area the cell belongs to */
} cell_info_ind_t;
/*
* --------------------------------------------------------------------------
* Paging information
* --------------------------------------------------------------------------
*/
/* Paging cause */
enum {
AS_CONNECTION_ESTABLISH, /* Establish NAS signalling connection */
AS_EPS_ATTACH, /* Perform local detach and initiate EPS
* attach procedure */
AS_CS_FALLBACK /* Inititate CS fallback procedure */
};
/*
* NAS->AS - Paging Information request
* NAS requests the AS that NAS signalling messages or user data is pending
* to be sent.
*/
typedef struct {
as_stmsi_t s_tmsi; /* UE identity */
UInt8_t CN_domain; /* Core network domain */
} paging_req_t;
/*
* AS->NAS - Paging Information indication
* AS reports to the NAS that appropriate procedure has to be initiated.
*/
typedef struct {
UInt8_t cause; /* Paging cause */
} paging_ind_t;
/*
* --------------------------------------------------------------------------
* NAS signalling connection establishment
* --------------------------------------------------------------------------
*/
/* Cause of RRC connection establishment */
#define AS_CAUSE_EMERGENCY (NET_ESTABLISH_CAUSE_EMERGENCY)
#define AS_CAUSE_HIGH_PRIO (NET_ESTABLISH_CAUSE_HIGH_PRIO)
#define AS_CAUSE_MT_ACCESS (NET_ESTABLISH_CAUSE_MT_ACCESS)
#define AS_CAUSE_MO_SIGNAL (NET_ESTABLISH_CAUSE_MO_SIGNAL)
#define AS_CAUSE_MO_DATA (NET_ESTABLISH_CAUSE_MO_DATA)
#define AS_CAUSE_V1020 (NET_ESTABLISH_CAUSE_V1020)
/* Type of the call associated to the RRC connection establishment */
#define AS_TYPE_ORIGINATING_SIGNAL (NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL)
#define AS_TYPE_EMERGENCY_CALLS (NET_ESTABLISH_TYPE_EMERGENCY_CALLS)
#define AS_TYPE_ORIGINATING_CALLS (NET_ESTABLISH_TYPE_ORIGINATING_CALLS)
#define AS_TYPE_TERMINATING_CALLS (NET_ESTABLISH_TYPE_TERMINATING_CALLS)
#define AS_TYPE_MO_CS_FALLBACK (NET_ESTABLISH_TYPE_MO_CS_FALLBACK)
/*
* NAS->AS - NAS signalling connection establishment request
* NAS requests the AS to perform the RRC connection establishment procedure
* to transfer initial NAS message to the network while UE is in IDLE mode.
*/
typedef struct {
UInt8_t cause; /* RRC connection establishment cause */
UInt8_t type; /* RRC associated call type */
as_stmsi_t s_tmsi; /* UE identity */
plmn_t plmnID; /* Selected PLMN identity */
as_nas_info_t initialNasMsg; /* Initial NAS message to transfer */
} nas_establish_req_t;
/*
* AS->NAS - NAS signalling connection establishment indication
* AS transfers the initial NAS message to the NAS.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
tac_t tac; /* Code of the tracking area the initiating
* UE belongs to */
as_nas_info_t initialNasMsg; /* Initial NAS message to transfer */
} nas_establish_ind_t;
/*
* NAS->AS - NAS signalling connection establishment response
* NAS responds to the AS that initial answer message has to be provided to
* the UE.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
as_stmsi_t s_tmsi; /* UE identity */
UInt8_t errCode; /* Transaction status */
as_nas_info_t nasMsg; /* NAS message to transfer */
} nas_establish_rsp_t;
/*
* AS->NAS - NAS signalling connection establishment confirm
* AS transfers the initial answer message to the NAS.
*/
typedef struct {
UInt8_t errCode; /* Transaction status */
as_nas_info_t nasMsg; /* NAS message to transfer */
} nas_establish_cnf_t;
/*
* --------------------------------------------------------------------------
* NAS signalling connection release
* --------------------------------------------------------------------------
*/
/* Release cause */
enum {
AS_AUTHENTICATION_FAILURE = 1, /* Authentication procedure failed */
AS_DETACH /* Detach requested */
};
/*
* NAS->AS - NAS signalling connection release request
* NAS requests the termination of the connection with the UE.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
as_stmsi_t s_tmsi; /* UE identity */
UInt8_t cause; /* Release cause */
} nas_release_req_t;
/*
* AS->NAS - NAS signalling connection release indication
* AS reports that connection has been terminated by the network.
*/
typedef struct {
UInt8_t cause; /* Release cause */
} nas_release_ind_t;
/*
* --------------------------------------------------------------------------
* NAS information transfer
* --------------------------------------------------------------------------
*/
/*
* NAS->AS - Uplink data transfer request
* NAS requests the AS to transfer uplink information to the NAS that
* operates at the network side.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
as_stmsi_t s_tmsi; /* UE identity */
as_nas_info_t nasMsg; /* Uplink NAS message */
} ul_info_transfer_req_t;
/*
* AS->NAS - Uplink data transfer confirm
* AS immediately notifies the NAS whether uplink information has been
* successfully sent to the network or not.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
UInt8_t errCode; /* Transaction status */
} ul_info_transfer_cnf_t;
/*
* AS->NAS - Uplink data transfer indication
* AS delivers the uplink information message to the NAS that operates
* at the network side.
*/
typedef struct {
UInt32_t UEid; /* UE lower layer identifier */
as_nas_info_t nasMsg; /* Uplink NAS message */
} ul_info_transfer_ind_t;
/*
* NAS->AS - Downlink data transfer request
* NAS requests the AS to transfer downlink information to the NAS that
* operates at the UE side.
*/
typedef ul_info_transfer_req_t dl_info_transfer_req_t;
/*
* AS->NAS - Downlink data transfer confirm
* AS immediately notifies the NAS whether downlink information has been
* successfully sent to the network or not.
*/
typedef ul_info_transfer_cnf_t dl_info_transfer_cnf_t;
/*
* AS->NAS - Downlink data transfer indication
* AS delivers the downlink information message to the NAS that operates
* at the UE side.
*/
typedef ul_info_transfer_ind_t dl_info_transfer_ind_t;
/*
* --------------------------------------------------------------------------
* Radio Access Bearer establishment
* --------------------------------------------------------------------------
*/
/* TODO: Quality of Service parameters */
typedef struct {} as_qos_t;
/*
* NAS->AS - Radio access bearer establishment request
* NAS requests the AS to allocate transmission resources to radio access
* bearer initialized at the network side.
*/
typedef struct {
as_stmsi_t s_tmsi; /* UE identity */
as_rab_id_t rabID; /* Radio access bearer identity */
as_qos_t QoS; /* Requested Quality of Service */
} rab_establish_req_t;
/*
* AS->NAS - Radio access bearer establishment indication
* AS notifies the NAS that specific radio access bearer has to be setup.
*/
typedef struct {
as_rab_id_t rabID; /* Radio access bearer identity */
} rab_establish_ind_t;
/*
* NAS->AS - Radio access bearer establishment response
* NAS responds to AS whether the specified radio access bearer has been
* successfully setup or not.
*/
typedef struct {
as_stmsi_t s_tmsi; /* UE identity */
as_rab_id_t rabID; /* Radio access bearer identity */
UInt8_t errCode; /* Transaction status */
} rab_establish_rsp_t;
/*
* AS->NAS - Radio access bearer establishment confirm
* AS notifies NAS whether the specified radio access bearer has been
* successfully setup at the UE side or not.
*/
typedef struct {
as_rab_id_t rabID; /* Radio access bearer identity */
UInt8_t errCode; /* Transaction status */
} rab_establish_cnf_t;
/*
* --------------------------------------------------------------------------
* Radio Access Bearer release
* --------------------------------------------------------------------------
*/
/*
* NAS->AS - Radio access bearer release request
* NAS requests the AS to release transmission resources previously allocated
* to specific radio access bearer at the network side.
*/
typedef struct {
as_stmsi_t s_tmsi; /* UE identity */
as_rab_id_t rabID; /* Radio access bearer identity */
} rab_release_req_t;
/*
* AS->NAS - Radio access bearer release indication
* AS notifies NAS that specific radio access bearer has been released.
*/
typedef struct {
as_rab_id_t rabID; /* Radio access bearer identity */
} rab_release_ind_t;
/*
* --------------------------------------------------------------------------
* Structure of the AS messages handled by the network sublayer
* --------------------------------------------------------------------------
*/
typedef struct {
UInt16_t msgID;
union {
broadcast_info_ind_t broadcast_info_ind;
cell_info_req_t cell_info_req;
cell_info_cnf_t cell_info_cnf;
cell_info_ind_t cell_info_ind;
paging_req_t paging_req;
paging_ind_t paging_ind;
nas_establish_req_t nas_establish_req;
nas_establish_ind_t nas_establish_ind;
nas_establish_rsp_t nas_establish_rsp;
nas_establish_cnf_t nas_establish_cnf;
nas_release_req_t nas_release_req;
nas_release_ind_t nas_release_ind;
ul_info_transfer_req_t ul_info_transfer_req;
ul_info_transfer_cnf_t ul_info_transfer_cnf;
ul_info_transfer_ind_t ul_info_transfer_ind;
dl_info_transfer_req_t dl_info_transfer_req;
dl_info_transfer_cnf_t dl_info_transfer_cnf;
dl_info_transfer_ind_t dl_info_transfer_ind;
rab_establish_req_t rab_establish_req;
rab_establish_ind_t rab_establish_ind;
rab_establish_rsp_t rab_establish_rsp;
rab_establish_cnf_t rab_establish_cnf;
rab_release_req_t rab_release_req;
rab_release_ind_t rab_release_ind;
} __attribute__((__packed__)) msg;
} as_message_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int as_message_decode(const char* buffer, as_message_t* msg, int length);
int as_message_encode(char* buffer, as_message_t* msg, int length);
/* Implemented in the network_api.c body file */
int as_message_send(as_message_t* as_msg);
#endif /* __AS_MESSAGE_H__*/
@@ -0,0 +1,283 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source as_message.h
Version 0.1
Date 2012/10/18
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the messages supported by the Access Stratum sublayer
protocol (usually RRC and S1AP for E-UTRAN) and functions used
to encode and decode
*****************************************************************************/
#ifndef __AS_MESSAGE_H__
#define __AS_MESSAGE_H__
#include "commonDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/* Access Stratum Message types */
#define AS_REQUEST 0x0100
#define AS_RESPONSE 0x0200
#define AS_INDICATION 0x0400
#define AS_CONFIRM 0x0800
/*
* Access Stratum Message identifiers
* ----------------------------------
*/
/* Cell information relevant for cell selection processing */
#define AS_CELL_INFO 0x01
#define AS_CELL_INFO_REQ (AS_CELL_INFO | AS_REQUEST)
#define AS_CELL_INFO_RSP (AS_CELL_INFO | AS_RESPONSE)
#define AS_CELL_INFO_IND (AS_CELL_INFO | AS_INDICATION)
/* Security mode control */
#define AS_SECURITY 0x02
#define AS_SECURITY_REQ (AS_SECURITY | AS_REQUEST)
#define AS_SECURITY_RSP (AS_SECURITY | AS_RESPONSE)
/* Paging information */
#define AS_PAGING 0x03
#define AS_PAGING_IND (AS_PAGING | AS_INDICATION)
/* NAS signalling connection establishment */
#define AS_NAS_ESTABLISH 0x04
#define AS_NAS_ESTABLISH_REQ (AS_NAS_ESTABLISH | AS_REQUEST)
#define AS_NAS_ESTABLISH_RSP (AS_NAS_ESTABLISH | AS_RESPONSE)
/* NAS signalling connection release */
#define AS_NAS_RELEASE 0x05
#define AS_NAS_RELEASE_REQ (AS_NAS_RELEASE | AS_REQUEST)
#define AS_NAS_RELEASE_IND (AS_NAS_RELEASE | AS_INDICATION)
/* NAS information transfer */
#define AS_INFO_TRANSFER 0x10
#define AS_UL_INFO_TRANSFER (AS_INFO_TRANSFER | AS_REQUEST)
#define AS_DL_INFO_TRANSFER (AS_INFO_TRANSFER | AS_INDICATION)
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* --------------------------------------------------------------------------
* Available PLMNs and cell Information
* --------------------------------------------------------------------------
*/
/* Radio access technologies supported by the network */
#define AS_GSM (1 << NET_ACCESS_GSM)
#define AS_COMPACT (1 << NET_ACCESS_COMPACT)
#define AS_UTRAN (1 << NET_ACCESS_UTRAN)
#define AS_EGPRS (1 << NET_ACCESS_EGPRS)
#define AS_HSDPA (1 << NET_ACCESS_HSDPA)
#define AS_HSUPA (1 << NET_ACCESS_HSUPA)
#define AS_HSDUPA (1 << NET_ACCESS_HSDUPA)
#define AS_EUTRAN (1 << NET_ACCESS_EUTRAN)
/*
* NAS->AS - Cell Information request
* NAS request AS to search for a suitable cell belonging to the selected
* PLMN to camp on.
*/
typedef struct {
plmn_t plmnID; /* PLMN identifier */
Byte_t rat; /* Bitmap - set of radio access technologies */
} cell_info_req_t;
/*
* AS->NAS - Cell Information response
* AS search for a suitable cell and respond to NAS. If found, the cell
* is selected to camp on.
*/
typedef struct {
plmn_t plmnID; /* PLMN identifier */
TAC_t tac; /* identifies a tracking area the PLMN belongs to */
CI_t cellID; /* identifies a cell within a PLMN */
AcT_t rat; /* radio access technology supported by the cell */
} cell_info_rsp_t;
/*
* AS->NAS - Cell Information indication
* AS Reports available PLMNs with associated Radio Access Technologies
* to NAS on request from NAS or autonomously.
*/
typedef struct {
#define PLMN_LIST_MAX_SIZE 6
PLMN_LIST_T(PLMN_LIST_MAX_SIZE) plmnIDs; /* List of PLMN identifiers */
Byte_t rat[PLMN_LIST_MAX_SIZE]; /* Radio access technologies */
TAC_t tac; /* identifies a tracking area within a scope of PLMNs */
CI_t cellID; /* identifies a cell within a PLMN */
} cell_info_ind_t;
/*
* --------------------------------------------------------------------------
* Security mode control
* --------------------------------------------------------------------------
*/
/*
* TODO: NAS->AS - Security command request
*/
typedef struct {} security_req_t;
/*
* TODO: AS->NAS - Security command response
*/
typedef struct {} security_rsp_t;
/*
* --------------------------------------------------------------------------
* Paging information
* --------------------------------------------------------------------------
*/
/*
* TODO: AS->NAS - Paging Information indication
*/
typedef struct {} paging_ind_t;
/*
* --------------------------------------------------------------------------
* NAS signalling connection establishment
* --------------------------------------------------------------------------
*/
/* Cause of RRC connection establishment */
#define AS_CAUSE_EMERGENCY (NET_ESTABLISH_CAUSE_EMERGENCY)
#define AS_CAUSE_HIGH_PRIO (NET_ESTABLISH_CAUSE_HIGH_PRIO)
#define AS_CAUSE_MT_ACCESS (NET_ESTABLISH_CAUSE_MT_ACCESS)
#define AS_CAUSE_MO_SIGNAL (NET_ESTABLISH_CAUSE_MO_SIGNAL)
#define AS_CAUSE_MO_DATA (NET_ESTABLISH_CAUSE_MO_DATA)
#define AS_CAUSE_V1020 (NET_ESTABLISH_CAUSE_V1020)
/* Type of the call associated to the RRC connection establishment */
#define AS_TYPE_ORIGINATING_SIGNAL (NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL)
#define AS_TYPE_EMERGENCY_CALLS (NET_ESTABLISH_TYPE_EMERGENCY_CALLS)
#define AS_TYPE_ORIGINATING_CALLS (NET_ESTABLISH_TYPE_ORIGINATING_CALLS)
#define AS_TYPE_TERMINATING_CALLS (NET_ESTABLISH_TYPE_TERMINATING_CALLS)
#define AS_TYPE_MO_CS_FALLBACK (NET_ESTABLISH_TYPE_MO_CS_FALLBACK)
/* Structure of the SAE Temporary Mobile Subscriber Identity */
typedef struct {
UInt8_t MMEcode; /* MME code that allocated the GUTI */
UInt32_t m_tmsi; /* M-Temporary Mobile Subscriber Identity */
} as_stmsi_t;
/* Structure of the dedicated NAS information */
typedef struct {
UInt32_t length; /* Length of the NAS information data */
Byte_t* data; /* Dedicated NAS information data container */
} as_nas_info_t;
/*
* NAS->AS - NAS signalling connection establishment request
* NAS request AS to perform the RRC connection establishment procedure
* to transfer initial NAS message to the network while UE is in IDLE mode.
*/
typedef struct {
UInt8_t cause; /* Connection establishment cause */
UInt8_t type; /* Associated call type */
plmn_t plmnID; /* Identifier of the selected PLMN */
as_stmsi_t s_tmsi; /* SAE Temporary Mobile Subscriber Identity */
as_nas_info_t initialNasMsg;/* Initial NAS message to transfer */
} nas_establish_req_t;
/*
* TODO: AS->NAS - NAS signalling connection establishment response
*/
typedef struct {} nas_establish_rsp_t;
/*
* --------------------------------------------------------------------------
* NAS signalling connection release
* --------------------------------------------------------------------------
*/
/*
* TODO: NAS->AS - NAS signalling connection release request
*/
typedef struct {} nas_release_req_t;
/*
* TODO: AS->NAS - NAS signalling connection release indication
*/
typedef struct {} nas_release_ind_t;
/*
* --------------------------------------------------------------------------
* NAS information transfer
* --------------------------------------------------------------------------
*/
/*
* AS->NAS - Downlink data transfer
* AS notifies upper layer that NAS or non-3GPP dedicated downlink information
* has to be transfered to NAS.
*/
typedef as_nas_info_t dl_info_transfer_t;
/*
* NAS->AS - Uplink data transfer request
* NAS requests under layer to transfer NAS or non-3GPP dedicated uplink
* information to AS.
*/
typedef as_nas_info_t ul_info_transfer_t;
/*
* --------------------------------------------------------------------------
* Structure of the AS messages handled by the network sublayer
* --------------------------------------------------------------------------
*/
typedef struct {
UInt16_t msgID;
union {
cell_info_req_t cell_info_req;
cell_info_rsp_t cell_info_rsp;
cell_info_ind_t cell_info_ind;
security_req_t security_req;
security_rsp_t security_rsp;
paging_ind_t paging_ind;
nas_establish_req_t nas_establish_req;
nas_establish_rsp_t nas_establish_rsp;
nas_release_req_t nas_release_req;
nas_release_ind_t nas_release_ind;
ul_info_transfer_t ul_info_transfer;
dl_info_transfer_t dl_info_transfer;
} __attribute__((__packed__)) msg;
} as_message_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int as_message_decode(const char* buffer, int length, as_message_t* msg);
int as_message_encode(char* buffer, int length, const as_message_t* msg);
/* Implemented in the network_api.c body file */
int as_message_send(as_message_t* as_msg, const void* nas_msg);
#endif /* __AS_MESSAGE_H__*/
@@ -0,0 +1,725 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source nas_message.h
Version 0.1
Date 2012/26/09
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the layer 3 messages supported by the NAS sublayer
protocol and functions used to encode and decode
*****************************************************************************/
#include "nas_message.h"
#include "nas_log.h"
#include "TLVDecoder.h"
#include "TLVEncoder.h"
#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 ****************/
/****************************************************************************/
/****************************************************************************/
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
/* Functions used to decode layer 3 NAS messages */
static int _nas_message_header_decode(const char* buffer,
nas_message_security_header_t* header, int length);
static int _nas_message_plain_decode(const char* buffer,
const nas_message_security_header_t* header,
nas_message_plain_t* msg, int length);
static int _nas_message_protected_decode(const char* buffer,
nas_message_security_header_t* header,
nas_message_plain_t* msg, int length);
/* Functions used to encode layer 3 NAS messages */
static int _nas_message_header_encode(char* buffer,
const nas_message_security_header_t* header, int length);
static int _nas_message_plain_encode(char* buffer,
const nas_message_security_header_t* header,
const nas_message_plain_t* msg, int length);
static int _nas_message_protected_encode(char* buffer,
const nas_message_security_protected_t* msg, int length);
/* Functions used to decrypt and encrypt layer 3 NAS messages */
static int _nas_message_decrypt(char* dest, const char* src, UInt8_t type,
UInt32_t code, UInt8_t seq, int length);
static int _nas_message_encrypt(char* dest, const char* src, UInt8_t type,
UInt32_t code, UInt8_t seq, int length);
/* Functions used for integrity protection of layer 3 NAS messages */
static UInt32_t _nas_message_get_mac(const char* buffer, UInt32_t count,
int length);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: nas_message_encrypt() **
** **
** Description: Encripts plain NAS message into security protected NAS **
** message **
** **
** Inputs: inbuf: Input buffer containing plain NAS message **
** header: Security protected header to be applied **
** length: Number of bytes that should be encrypted **
** Others: None **
** **
** Outputs: outbuf: Output buffer containing security protec- **
** ted message **
** Return: The number of bytes in the output buffer **
** if the input buffer has been successfully **
** encrypted; Negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_message_encrypt(const char* inbuf, char* outbuf,
const nas_message_security_header_t* header, int length)
{
LOG_FUNC_IN;
int bytes = length;
/* Encode the header */
int size = _nas_message_header_encode(outbuf, header, length);
if (size < 0) {
LOG_FUNC_RETURN (TLV_ENCODE_BUFFER_TOO_SHORT);
}
else if (size > 1) {
/* Encrypt the plain NAS message */
bytes = _nas_message_encrypt(outbuf + size, inbuf,
header->security_header_type,
header->message_authentication_code,
header->sequence_number,
length - size);
/* Integrity protected the NAS message */
if (bytes > 0) {
/* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */
UInt32_t mac = _nas_message_get_mac(outbuf + offset,
0, // TODO !!! ul counter
length - offset);
/* Set the message authentication code of the NAS message */
*(UInt32_t*)(outbuf + sizeof(UInt8_t)) = mac;
}
}
else {
/* The input buffer does not need to be encrypted */
memcpy(outbuf, inbuf, length);
}
if (bytes < 0) {
LOG_FUNC_RETURN (bytes);
}
if (size > 1) {
LOG_FUNC_RETURN (size + bytes);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: nas_message_decrypt() **
** **
** Description: Decripts security protected NAS message into plain NAS **
** message **
** **
** Inputs: inbuf: Input buffer containing security protected **
** NAS message **
** length: Number of bytes that should be decrypted **
** Others: None **
** **
** Outputs: outbuf: Output buffer containing plain NAS message **
** header: Security protected header applied **
** Return: The number of bytes in the output buffer **
** if the input buffer has been successfully **
** decrypted; Negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_message_decrypt(const char* inbuf, char* outbuf,
nas_message_security_header_t* header, int length)
{
LOG_FUNC_IN;
int bytes = length;
/* Decode the header */
int size = _nas_message_header_decode(inbuf, header, length);
if (size < 0) {
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
}
else if (size > 1) {
/* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */
UInt32_t mac = _nas_message_get_mac(inbuf + offset,
0, // TODO !!! dl counter
length - offset);
/* Check NAS message integrity */
if (mac != header->message_authentication_code) {
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
}
/* Decrypt the security protected NAS message */
header->protocol_discriminator =
_nas_message_decrypt(outbuf, inbuf + size,
header->security_header_type,
header->message_authentication_code,
header->sequence_number,
length - size);
bytes = length - size;
}
else {
/* The input buffer contains a plain NAS message */
memcpy(outbuf, inbuf, length);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: nas_message_decode() **
** **
** Description: Decode layer 3 NAS message **
** **
** Inputs: buffer: Pointer to the buffer containing layer 3 **
** NAS message data **
** length: Number of bytes that should be decoded **
** Others: None **
** **
** Outputs: msg: L3 NAS message structure to be filled **
** Return: The number of bytes in the buffer if the **
** data have been successfully decoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_message_decode(const char* buffer, nas_message_t* msg, int length)
{
LOG_FUNC_IN;
int bytes;
/* Decode the header */
int size = _nas_message_header_decode(buffer, &msg->header, length);
if (size < 0) {
LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
}
else if (size > 1) {
/* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */
UInt32_t mac = _nas_message_get_mac(buffer + offset,
0, // TODO !!! dl counter
length - offset);
/* Check NAS message integrity */
if (mac != msg->header.message_authentication_code) {
LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
}
/* Decode security protected NAS message */
bytes = _nas_message_protected_decode(buffer + size, &msg->header,
&msg->plain, length - size);
}
else {
/* Decode plain NAS message */
bytes = _nas_message_plain_decode(buffer, &msg->header,
&msg->plain, length);
}
if (bytes < 0) {
LOG_FUNC_RETURN (bytes);
}
if (size > 1) {
LOG_FUNC_RETURN (size + bytes);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: nas_message_encode() **
** **
** Description: Encode layer 3 NAS message **
** **
** Inputs msg: L3 NAS message structure to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
int nas_message_encode(char* buffer, const nas_message_t* msg, int length)
{
LOG_FUNC_IN;
int bytes;
/* Encode the header */
int size = _nas_message_header_encode(buffer, &msg->header, length);
if (size < 0) {
LOG_FUNC_RETURN (TLV_ENCODE_BUFFER_TOO_SHORT);
}
else if (size > 1) {
/* Encode security protected NAS message */
bytes = _nas_message_protected_encode(buffer + size, &msg->protected,
length - size);
/* Integrity protect the NAS message */
if (bytes > 0) {
/* Compute offset of the sequence number field */
int offset = size - sizeof(UInt8_t);
/* Compute the NAS message authentication code */
UInt32_t mac = _nas_message_get_mac(buffer + offset,
0, // TODO !!! ul counter
length - offset);
/* Set the message authentication code of the NAS message */
*(UInt32_t*)(buffer + sizeof(UInt8_t)) = mac;
}
}
else {
/* Encode plain NAS message */
bytes = _nas_message_plain_encode(buffer, &msg->header,
&msg->plain, length);
}
if (bytes < 0) {
LOG_FUNC_RETURN (bytes);
}
if (size > 1) {
LOG_FUNC_RETURN (size + bytes);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/*
* -----------------------------------------------------------------------------
* Functions used to decode layer 3 NAS messages
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_message_header_decode() **
** **
** Description: Decode header of a security protected NAS message **
** **
** Inputs: buffer: Pointer to the buffer containing layer 3 **
** message data **
** length: Number of bytes that should be decoded **
** Others: None **
** **
** Outputs: header: Security header structure to be filled **
** Return: The size in bytes of the security header **
** if data have been successfully decoded; **
** 1, if the header is not a security header **
** (header of plain NAS message); **
** -1 otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_header_decode(const char* buffer,
nas_message_security_header_t* header,
int length)
{
LOG_FUNC_IN;
int size = 0;
/* Decode the first octet of the header (security header type or EPS bearer
* identity, and protocol discriminator) */
DECODE_U8(buffer, *(UInt8_t*)(header), size);
if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED)
{
if (length < NAS_MESSAGE_SECURITY_HEADER_SIZE) {
/* The buffer is not big enough to contain security header */
LOG_TRACE(WARNING, "NET-API - The size of the header (%u) "
"exceeds the buffer length (%u)",
NAS_MESSAGE_SECURITY_HEADER_SIZE, length);
LOG_FUNC_RETURN (-1);
}
/* Decode the message authentication code */
DECODE_U32(buffer+size, header->message_authentication_code, size);
/* Decode the sequence number */
DECODE_U8(buffer+size, header->sequence_number, size);
}
}
LOG_FUNC_RETURN (size);
}
/****************************************************************************
** **
** Name: _nas_message_plain_decode() **
** **
** Description: Decode plain NAS message **
** **
** Inputs: buffer: Pointer to the buffer containing plain NAS **
** message data **
** header: Header of the plain NAS message **
** length: Number of bytes that should be decoded **
** Others: None **
** **
** Outputs: msg: Decoded NAS message **
** Return: The number of bytes in the buffer if the **
** data have been successfully decoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_plain_decode(const char* buffer,
const nas_message_security_header_t* header,
nas_message_plain_t* msg, int length)
{
LOG_FUNC_IN;
int bytes = TLV_DECODE_PROTOCOL_NOT_SUPPORTED;
if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
/* Decode EPS Mobility Management L3 message */
bytes = emm_msg_decode(&msg->emm, (uint8_t *)buffer, length);
}
else if (header->protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) {
/* Decode EPS Session Management L3 message */
bytes = esm_msg_decode(&msg->esm, (uint8_t *)buffer, length);
}
else {
/* Discard L3 messages with not supported protocol discriminator */
LOG_TRACE(WARNING,"NET-API - Protocol discriminator 0x%x is "
"not supported", header->protocol_discriminator);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _nas_message_protected_decode() **
** **
** Description: Decode security protected NAS message **
** **
** Inputs: buffer: Pointer to the buffer containing the secu- **
** rity protected NAS message data **
** header: Header of the security protected NAS mes- **
** sage **
** length: Number of bytes that should be decoded **
** Others: None **
** **
** Outputs: msg: Decoded NAS message **
** Return: The number of bytes in the buffer if the **
** data have been successfully decoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_protected_decode(const char* buffer,
nas_message_security_header_t* header,
nas_message_plain_t* msg, int length)
{
LOG_FUNC_IN;
int bytes = TLV_DECODE_BUFFER_TOO_SHORT;
char* plain_msg = (char*)malloc(length);
if (plain_msg)
{
/* Decrypt the security protected NAS message */
header->protocol_discriminator =
_nas_message_decrypt(plain_msg, buffer,
header->security_header_type,
header->message_authentication_code,
header->sequence_number, length);
/* Decode the decrypted message as plain NAS message */
bytes = _nas_message_plain_decode(plain_msg, header, msg, length);
free(plain_msg);
}
LOG_FUNC_RETURN (bytes);
}
/*
* -----------------------------------------------------------------------------
* Functions used to encode layer 3 NAS messages
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_message_header_encode() **
** **
** Description: Encode header of a security protected NAS message **
** **
** Inputs header: Security header structure to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** 1, if the header is not a security header **
** (header of plain NAS message); **
** -1 otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_header_encode(char* buffer,
const nas_message_security_header_t* header, int length)
{
LOG_FUNC_IN;
int size = 0;
/* Encode the first octet of the header (security header type or EPS bearer
* identity, and protocol discriminator) */
ENCODE_U8(buffer, *(UInt8_t*)(header), size);
if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED)
{
if (length < NAS_MESSAGE_SECURITY_HEADER_SIZE) {
/* The buffer is not big enough to contain security header */
LOG_TRACE(WARNING, "NET-API - The size of the header (%u) "
"exceeds the buffer length (%u)",
NAS_MESSAGE_SECURITY_HEADER_SIZE, length);
LOG_FUNC_RETURN (-1);
}
/* Encode the message authentication code */
ENCODE_U32(buffer+size, header->message_authentication_code, size);
/* Encode the sequence number */
ENCODE_U8(buffer+size, header->sequence_number, size);
}
}
LOG_FUNC_RETURN (size);
}
/****************************************************************************
** **
** Name: _nas_message_plain_encode() **
** **
** Description: Encode plain NAS message **
** **
** Inputs: pd: Protocol discriminator of the NAS message **
** to encode **
** msg: Plain NAS message structure to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_plain_encode(char* buffer,
const nas_message_security_header_t* header,
const nas_message_plain_t* msg, int length)
{
LOG_FUNC_IN;
int bytes = TLV_ENCODE_PROTOCOL_NOT_SUPPORTED;
if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
/* Encode EPS Mobility Management L3 message */
bytes = emm_msg_encode((EMM_msg*)(&msg->emm), (uint8_t*)buffer, length);
}
else if (header->protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) {
/* Encode EPS Session Management L3 message */
bytes = esm_msg_encode((ESM_msg*)(&msg->esm), (uint8_t*)buffer, length);
}
else {
/* Discard L3 messages with not supported protocol discriminator */
LOG_TRACE(WARNING,"NET-API - Protocol discriminator 0x%x is "
"not supported", header->protocol_discriminator);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _nas_message_protected_encode() **
** **
** Description: Encode security protected NAS message **
** **
** Inputs msg: Security protected NAS message structure **
** to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_protected_encode(char* buffer,
const nas_message_security_protected_t* msg, int length)
{
LOG_FUNC_IN;
int bytes = TLV_ENCODE_BUFFER_TOO_SHORT;
char* plain_msg = (char*)malloc(length);
if (plain_msg) {
/* Encode the security protected NAS message as plain NAS message */
int size = _nas_message_plain_encode(plain_msg, &msg->header,
&msg->plain, length);
if (size > 0) {
/* Encrypt the encoded plain NAS message */
bytes = _nas_message_encrypt(buffer, plain_msg,
msg->header.security_header_type,
msg->header.message_authentication_code,
msg->header.sequence_number, size);
}
free(plain_msg);
}
LOG_FUNC_RETURN (bytes);
}
/*
* -----------------------------------------------------------------------------
* Functions used to decrypt and encrypt layer 3 NAS messages
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_message_decrypt() **
** **
** Description: Decrypt security protected NAS message **
** **
** Inputs src: Pointer to the encrypted data buffer **
** type: The security header type **
** code: The message authentication code **
** seq: The sequence number **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: dest: Pointer to the decrypted data buffer **
** Return: The protocol discriminator of the message **
** that has been decrypted; **
** Others: None **
** **
***************************************************************************/
static int _nas_message_decrypt(char* dest, const char* src, UInt8_t type,
UInt32_t code, UInt8_t seq, int length)
{
LOG_FUNC_IN;
int size = 0;
nas_message_security_header_t header;
/* TODO: run the uncyphering algorithm */
memcpy(dest, src, length);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(src, *(UInt8_t*)(&header), size);
LOG_FUNC_RETURN (header.protocol_discriminator);
}
/****************************************************************************
** **
** Name: _nas_message_encrypt() **
** **
** Description: Encrypt plain NAS message **
** **
** Inputs src: Pointer to the decrypted data buffer **
** type: The security header type **
** code: The message authentication code **
** seq: The sequence number **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: dest: Pointer to the encrypted data buffer **
** Return: The number of bytes in the output buffer **
** if data have been successfully encrypted; **
** RETURNerror otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_encrypt(char* dest, const char* src, UInt8_t type,
UInt32_t code, UInt8_t seq, int length)
{
LOG_FUNC_IN;
int size = length;
/* TODO: run the cyphering algorithm */
memcpy(dest, src, length);
LOG_FUNC_RETURN (size);
}
/*
* -----------------------------------------------------------------------------
* Functions used for integrity protection of layer 3 NAS messages
* -----------------------------------------------------------------------------
*/
/****************************************************************************
** **
** Name: _nas_message_get_mac() **
** **
** Description: Run integrity algorithm onto cyphered or uncyphered NAS **
** message encoded in the input buffer and return the compu- **
** ted message authentication code **
** **
** Inputs buffer: Pointer to the integrity protected data **
** buffer **
** count: Value of the uplink NAS counter **
** length: Length of the input buffer **
** Others: None **
** **
** Outputs: None **
** Return: The message authentication code **
** Others: None **
** **
***************************************************************************/
static UInt32_t _nas_message_get_mac(const char* buffer, UInt32_t count,
int length)
{
LOG_FUNC_IN;
/* TODO: run integrity protection algorithm */
/* TODO: Return the message authentication code */
LOG_FUNC_RETURN (0xabababab);
}
@@ -0,0 +1,89 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source nas_message.h
Version 0.1
Date 2012/26/09
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the layer 3 messages supported by the NAS sublayer
protocol and functions used to encode and decode
*****************************************************************************/
#ifndef __NAS_MESSAGE_H__
#define __NAS_MESSAGE_H__
#include "commonDef.h"
#include "emm_msg.h"
#include "esm_msg.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
#define NAS_MESSAGE_SECURITY_HEADER_SIZE 6
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/* Structure of security protected header */
typedef struct {
#ifdef __LITTLE_ENDIAN_BITFIELD
UInt8_t protocol_discriminator:4;
UInt8_t security_header_type:4;
#endif
#ifdef __BIG_ENDIAN_BITFIELD
UInt8_t security_header_type:4;
UInt8_t protocol_discriminator:4;
#endif
UInt32_t message_authentication_code;
UInt8_t sequence_number;
} nas_message_security_header_t;
/* Structure of plain NAS message */
typedef union {
EMM_msg emm; /* EPS Mobility Management messages */
ESM_msg esm; /* EPS Session Management messages */
} nas_message_plain_t;
/* Structure of security protected NAS message */
typedef struct {
nas_message_security_header_t header;
nas_message_plain_t plain;
} nas_message_security_protected_t;
/*
* Structure of a layer 3 NAS message
*/
typedef union {
nas_message_security_header_t header;
nas_message_security_protected_t protected;
nas_message_plain_t plain;
} nas_message_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int nas_message_encrypt(const char* inbuf, char* outbuf, const nas_message_security_header_t* header, int length);
int nas_message_decrypt(const char* inbuf, char* outbuf, nas_message_security_header_t* header, int length);
int nas_message_decode(const char* buffer, nas_message_t* msg, int length);
int nas_message_encode(char* buffer, const nas_message_t* msg, int length);
#endif /* __NAS_MESSAGE_H__*/
@@ -0,0 +1,416 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source network_api.c
Version 0.1
Date 2012/03/01
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer to send/receive
message to/from the network sublayer
*****************************************************************************/
#include "network_api.h"
#include "commonDef.h"
#include "nas_log.h"
#include "socket.h"
#include "as_message.h"
#include <string.h> // strerror, memset
#include <netdb.h> // gai_strerror
#include <errno.h> // errno
#include <unistd.h> // gethostname
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/* -------------------
* Connection endpoint
* -------------------
* The connection endpoint is used to send/receive data to/from the
* network sublayer. Its definition depends on the underlaying mechanism
* chosen to communicate (network socket, I/O terminal device, async FIFO).
* A connection endpoint is handled using an identifier, and functions
* used to retreive the file descriptor actually allocated by the system,
* to receive data, to send data, and to perform clean up when connection
* is shut down.
* Only one single end to end connection with the network sublayer is
* managed at a time.
*/
static struct {
/* Connection endpoint reference */
void* endpoint;
/* Connection endpoint handlers */
void* (*open) (int, const char*, const char*);
int (*getfd)(const void*);
ssize_t (*recv) (void*, char*, size_t);
ssize_t (*send) (const void*, const char*, size_t);
void (*close)(void*);
} _network_api_id;
#define NETWORK_API_OPEN(a, b, c) _network_api_id.open(a, b, c)
#define NETWORK_API_GETFD() _network_api_id.getfd(_network_api_id.endpoint)
#define NETWORK_API_RECV(a, b) _network_api_id.recv(_network_api_id.endpoint, a, b)
#define NETWORK_API_SEND(a, b) _network_api_id.send(_network_api_id.endpoint, a, b)
#define NETWORK_API_CLOSE() _network_api_id.close(_network_api_id.endpoint)
/*
* The buffer used to receive data from the network sublayer
*/
#define NETWORK_API_RECV_BUFFER_SIZE 4096
static char _network_api_recv_buffer[NETWORK_API_RECV_BUFFER_SIZE];
/*
* The buffer used to send data to the network sublayer
*/
#define NETWORK_API_SEND_BUFFER_SIZE NETWORK_API_RECV_BUFFER_SIZE
static char _network_api_send_buffer[NETWORK_API_SEND_BUFFER_SIZE];
/*
* The decoded data received from the network sublayer
*/
static as_message_t _as_data = {}; /* Access Stratum message */
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: network_api_initialize() **
** **
** Description: Initializes the network API from which the NAS layer **
** will send/receive messages to/from the network sublayer **
** **
** Inputs: host: The name of the host from which the net- **
** work sublayer will connect **
** port: The local port number **
** Others: None **
** **
** Outputs: Return: RETURNerror, RETURNok **
** Others: _network_api_id **
** **
***************************************************************************/
int network_api_initialize(const char* host, const char* port)
{
LOG_FUNC_IN;
/* Initialize network socket handlers */
_network_api_id.open = socket_udp_open;
_network_api_id.getfd = socket_get_fd;
_network_api_id.recv = socket_recv;
_network_api_id.send = socket_send;
_network_api_id.close = socket_close;
/* Initialize UDP communication channel with the network layer */
#ifdef NAS_UE
_network_api_id.endpoint = NETWORK_API_OPEN(SOCKET_CLIENT, host, port);
#endif
#ifdef NAS_MME
_network_api_id.endpoint = NETWORK_API_OPEN(SOCKET_SERVER, NULL, port);
#endif
if (_network_api_id.endpoint == NULL) {
const char* error = ( (errno < 0) ?
gai_strerror(errno) : strerror(errno) );
LOG_TRACE(ERROR, "NET-API - Failed to open connection endpoint, %s",
error);
LOG_FUNC_RETURN (RETURNerror);
}
gethostname(_network_api_send_buffer, NETWORK_API_SEND_BUFFER_SIZE);
LOG_TRACE(INFO, "NET-API - Network's UDP socket %d is BOUND to %s/%s",
network_api_get_fd(), _network_api_send_buffer, port);
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: network_api_get_fd() **
** **
** Description: Get the file descriptor of the connection endpoint used **
** to send/receive messages to/from the network sublayer **
** **
** Inputs: None **
** Others: _network_api_id **
** **
** Outputs: Return: The file descriptor of the connection end- **
** point used by the network sublayer **
** Others: None **
** **
***************************************************************************/
int network_api_get_fd(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (NETWORK_API_GETFD());
}
/****************************************************************************
** **
** Name: network_api_get_data() **
** **
** Description: Get a generic pointer to the network data structure. **
** Casting to the proper type is necessary before its usage. **
** **
** Inputs: None **
** Others: _as_data **
** **
** Outputs: Return: A generic pointer to the network data **
** structure **
** Others: None **
** **
***************************************************************************/
const void* network_api_get_data(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN ((void*)(&_as_data));
}
/****************************************************************************
** **
** Name: network_api_read_data() **
** **
** Description: Read data received from the network sublayer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** from which data have been received **
** Others: _network_api_id **
** **
** Outputs: Return: The number of bytes read when success; **
** RETURNerror otherwise **
** Others: _network_api_recv_buffer, _network_api_id **
** **
***************************************************************************/
int network_api_read_data(int fd)
{
LOG_FUNC_IN;
int rbytes;
/* Sanity check */
int sfd = network_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
LOG_FUNC_RETURN (RETURNerror);
}
memset(_network_api_recv_buffer, 0, NETWORK_API_RECV_BUFFER_SIZE);
/* Receive data from the network sublayer */
rbytes = NETWORK_API_RECV(_network_api_recv_buffer,
NETWORK_API_RECV_BUFFER_SIZE);
if (rbytes == RETURNerror) {
LOG_TRACE(ERROR, "NET-API - recv() failed, %s", strerror(errno));
LOG_FUNC_RETURN (RETURNerror);
}
else if (rbytes == 0) {
LOG_TRACE(WARNING, "NET-API - A signal was caught");
}
else {
LOG_TRACE(INFO, "NET-API - %d bytes received from the network "
"sublayer", rbytes);
LOG_DUMP(_network_api_recv_buffer, rbytes);
}
LOG_FUNC_RETURN (rbytes);
}
/****************************************************************************
** **
** Name: network_api_send_data() **
** **
** Description: Send data to the network sublayer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** to which data have to be sent **
** length: Number of bytes to send **
** Others: _network_api_send_buffer, _network_api_id **
** **
** Outputs: Return: The number of bytes sent when success; **
** RETURNerror otherwise **
** Others: None **
** **
***************************************************************************/
int network_api_send_data(int fd, int length)
{
LOG_FUNC_IN;
int sbytes;
/* Sanity check */
int sfd = network_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
LOG_FUNC_RETURN (RETURNerror);
}
/* Send data to the network sublayer */
sbytes = NETWORK_API_SEND(_network_api_send_buffer, length);
if (sbytes == RETURNerror) {
LOG_TRACE(ERROR, "NET-API - send() failed, %s", strerror(errno));
LOG_FUNC_RETURN (RETURNerror);
}
else if (sbytes == 0) {
LOG_TRACE(WARNING, "NET-API - A signal was caught");
}
else {
LOG_TRACE(INFO, "NET-API - %d bytes sent to the network sublayer",
sbytes);
LOG_DUMP(_network_api_send_buffer, sbytes);
}
LOG_FUNC_RETURN (sbytes);
}
/****************************************************************************
** **
** Name: network_api_close() **
** **
** Description: Clean the network API from which the NAS layer sent/recei-**
** ved messages to/from the network sublayer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** allocated by the system to communicate **
** with the network sublayer **
** Others: None **
** **
** Outputs: Return: None **
** Others: _network_api_id **
** **
***************************************************************************/
void network_api_close(int fd)
{
LOG_FUNC_IN;
/* Sanity check */
int sfd = network_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "NET-API - Endpoint %d is not the one created for communication with the network sublayer (%d)", fd, sfd);
LOG_FUNC_OUT;
return;
}
/* Cleanup the connection endpoint */
NETWORK_API_CLOSE();
_network_api_id.endpoint = NULL;
LOG_FUNC_OUT;
}
/****************************************************************************
** **
** Name: network_api_decode_data() **
** **
** Description: Decodes the message received from the network and fills **
** the corresponding network data structure. **
** **
** Inputs: length: Number of bytes to decode **
** Others: _network_api_recv_buffer **
** **
** Outputs: Return: The identifier of the received AS **
** message when successfully decoded; **
** RETURNerror otherwise **
** Others: _as_data **
** **
***************************************************************************/
int network_api_decode_data(int length)
{
LOG_FUNC_IN;
/* Decode the Access Stratum message received from the network */
int as_id = as_message_decode(_network_api_recv_buffer, &_as_data, length);
if (as_id != RETURNerror) {
LOG_TRACE(INFO, "NET-API - AS message id=0x%x successfully decoded",
as_id);
}
LOG_FUNC_RETURN (as_id);
}
/****************************************************************************
** **
** Name: network_api_encode_data() **
** **
** Description: Encodes Access Stratum message to be sent to the network **
** **
** Inputs data: Generic pointer to the AS data to encode **
** Others: None **
** **
** Outputs: Return: The number of characters that have been **
** successfully encoded; **
** RETURNerror otherwise. **
** Others: _network_api_send_buffer **
** **
***************************************************************************/
int network_api_encode_data(void* data)
{
LOG_FUNC_IN;
/* Encode the Access Stratum message */
int bytes = as_message_encode(_network_api_send_buffer,
(as_message_t*)(data),
NETWORK_API_SEND_BUFFER_SIZE);
if (bytes != RETURNerror) {
LOG_TRACE(INFO, "NET-API - %d bytes encoded", bytes);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: as_message_send() **
** **
** Description: Service provided to the EPS Mobility Management protocol **
** at the EMMAS Access Point (EMMAS-SAP) to send AS messages **
** to the Access Stratum sublayer. **
** **
** Inputs: as_msg: The AS message to send **
** Others: _network_api_send_buffer, _network_api_id **
** **
** Outputs: Return: The number of bytes sent when success; **
** RETURNerror Otherwise **
** Others: _network_api_send_buffer **
** **
***************************************************************************/
int as_message_send(as_message_t* as_msg)
{
int bytes;
LOG_FUNC_IN;
LOG_TRACE(INFO, "NET-API - Send message 0x%.4x to the Access Stratum "
"layer", as_msg->msgID);
/* Encode the AS message */
bytes = network_api_encode_data(as_msg);
if (bytes > 0) {
/* Get the network file descriptor */
int fd = network_api_get_fd();
if (fd != RETURNerror) {
/* Send the AS message to the network */
bytes = network_api_send_data(fd, bytes);
}
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
@@ -0,0 +1,52 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source network_api.h
Version 0.1
Date 2012/03/01
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer to send/receive
message to/from the network layer
*****************************************************************************/
#ifndef __NETWORK_API_H__
#define __NETWORK_API_H__
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int network_api_initialize(const char* host, const char* port);
int network_api_get_fd(void);
const void* network_api_get_data(void);
int network_api_read_data(int fd);
int network_api_send_data(int fd, int length);
void network_api_close(int fd);
int network_api_decode_data(int length);
int network_api_encode_data(void* data);
#endif /* __NETWORK_API_H__*/
@@ -0,0 +1,21 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../..
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR)
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
all: $(OBJS)
%.o: %.c Makefile
@echo Compiling $<
@$(CC) $(CFLAGS) -c $< -o $@
clean:
$(RM) $(OBJS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,839 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source at_command.h
Version 0.1
Date 2012/03/07
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines the ATtention (AT) command set supported by the NAS
sublayer protocol
*****************************************************************************/
#ifndef __AT_COMMAND_H__
#define __AT_COMMAND_H__
#include "userDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/* Bit masks indicating presence of AT command's optional parameters */
#define AT_COMMAND_PARAM0 0x0000 /* no any parameter is present */
#define AT_COMMAND_PARAM1 0x0001 /* first parameter is present */
#define AT_COMMAND_PARAM2 0x0002 /* 2nd parameter is present */
#define AT_COMMAND_PARAM3 0x0004 /* 3rd parameter is present */
#define AT_COMMAND_PARAM4 0x0008 /* 4th parameter is present */
#define AT_COMMAND_PARAM5 0x0010 /* 5th parameter is present */
#define AT_COMMAND_PARAM6 0x0020 /* 6th parameter is present */
#define AT_COMMAND_PARAM7 0x0040 /* 7th parameter is present */
#define AT_COMMAND_PARAM8 0x0080 /* 8th parameter is present */
#define AT_COMMAND_PARAM9 0x0100 /* 9th parameter is present */
#define AT_COMMAND_PARAM10 0x0200 /* 10th parameter is present */
#define AT_COMMAND_PARAM11 0x0400 /* 11th parameter is present */
#define AT_COMMAND_PARAM12 0x0800 /* 12th parameter is present */
#define AT_COMMAND_PARAM13 0x1000 /* 13th parameter is present */
#define AT_COMMAND_PARAM14 0x2000 /* 14th parameter is present */
#define AT_COMMAND_PARAM15 0x4000 /* 15th parameter is present */
#define AT_COMMAND_PARAM16 0x8000 /* 16th parameter is present */
/* Value of the mask parameter for AT commands without any parameters */
#define AT_COMMAND_NO_PARAM AT_COMMAND_PARAM0
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* AT command identifiers
* ----------------------
* Those currently supported by our Mobile Equipment (ME)
*/
typedef enum {
/*
* General commands
* ----------------
*/
AT_CGSN=1, /* Request Product Serial Number identification (IMEI) */
AT_CGMI, /* Request manufacturer identification */
AT_CGMM, /* Request model identification */
AT_CGMR, /* Request revision identification */
AT_CIMI, /* Request International Mobile Subscriber Identity */
/*
* Mobile Termination control and status commands
* ----------------------------------------------
*/
AT_CFUN, /* Set phone functionality */
AT_CPIN, /* Enter PIN */
AT_CSQ, /* Signal quality */
AT_CESQ, /* Extented signal quality */
AT_CLAC, /* List all available AT commands */
/*
* Mobile Termination errors
* -------------------------
*/
AT_CMEE, /* Report mobile termination error */
/*
* Network service related commands
* ---------------------------------
*/
AT_CNUM, /* Subscriber number */
AT_CLCK, /* Facility lock */
AT_COPS, /* PLMN selection */
AT_CREG, /* Network registration */
/*
* Commands for Packet Domain
* ---------------------------
*/
AT_CGATT, /* PS attach/detach */
AT_CGREG, /* GPRS network registration status */
AT_CEREG, /* EPS network registration status */
AT_CGDCONT, /* Define PDP Context */
AT_CGACT, /* PDP context activate or deactivate */
AT_CGPADDR, /* Show PDP address(es) */
AT_CGEV, /* Packet Domain event unsolicited result code */
AT_COMMAND_ID_MAX
} at_command_id_t;
/*
* AT command types
* ----------------
* - AT action command, used to execute a particular function, which
* generally involves more than the simple storage of a value.
* - AT set parameter command, used to store a value or values of
* subparameters.
* - AT read parameter command, used to check the current values of
* subparameters.
* - AT test parameter command, used to test the existence of the
* command and to give information about the type of its subparameters.
*/
typedef enum {
AT_COMMAND_ACT, /* AT action command (ATCMD) */
AT_COMMAND_SET, /* AT set parameter command (ATCMD=) */
AT_COMMAND_GET, /* AT read parameter command (ATCMD?) */
AT_COMMAND_TST, /* AT test parameter command (ATCMD=?) */
AT_COMMAND_TYPE_MAX
} at_command_type_t;
/*
* ================
* General commands
* ================
*/
/* CGSN: Request Product Serial Number identification (IMEI)
* ---------------------------------------------------------
* Returns information text intended to permit the user to identify the
* individual Mobile Equipment to which it is connected to.
* Action command:
* no parameters
*/
/* CGSN AT command type */
#define AT_COMMAND_CGSN_MASK AT_COMMAND_NO_PARAM
typedef struct at_cgsn_s {} at_cgsn_t;
/* CGMI: Request manufacturer identification
* -----------------------------------------
* Returns information text intended to permit the user to identify the
* manufacturer of the Mobile Equipment to which it is connected to.
* Action command:
* no parameters
*/
/* CGMI AT command type */
#define AT_COMMAND_CGMI_MASK AT_COMMAND_NO_PARAM
typedef struct at_cgmi_s {} at_cgmi_t;
/* CGMM: Request model identification
* ----------------------------------
* Returns information text intended to permit the user to identify the
* specific model of the Mobile Equipment to which it is connected to.
* Action command:
* no parameters
*/
/* CGMM AT command type */
#define AT_COMMAND_CGMM_MASK AT_COMMAND_NO_PARAM
typedef struct at_cgmm_s {} at_cgmm_t;
/* CGMR: Request revision identification
* -------------------------------------
* Returns information text intended to permit the user to identify the
* version, revision level or date, or other pertinent information of the
* Mobile Equipment to which it is connected to.
* Action command:
* no parameters
*/
/* CGMR AT command type */
#define AT_COMMAND_CGMR_MASK AT_COMMAND_NO_PARAM
typedef struct at_cgmr_s {} at_cgmr_t;
/* CIMI: Request International Mobile Subscriber Identity
* ------------------------------------------------------
* Returns <IMSI>, which is intended to permit the user to identify the
* individual SIM card or active application in the UICC (GSM or USIM)
* which is attached to the Mobile Equipment to which it is connected to.
* Action command:
* no parameters
*/
/* CIMI AT command type */
#define AT_COMMAND_CIMI_MASK AT_COMMAND_NO_PARAM
typedef struct at_cimi_s {} at_cimi_t;
/*
* ==============================================
* Mobile Termination control and status commands
* ==============================================
*/
/* CFUN: Set phone functionality
* -----------------------------
* Used to set the Mobile Equipment to different power consumption states
* Parameter command:
* +CFUN=[<fun>[,<rst>]]
* <fun> level of functionality
* <rst> resetting parameter
*/
/* Functionality levels */
#define AT_CFUN_MIN 0 /* minimum functionality */
#define AT_CFUN_FULL 1 /* full functionality */
#define AT_CFUN_SEND 2 /* disable phone transmit RF circuits only */
#define AT_CFUN_RECV 3 /* disable phone receive RF circuits only */
#define AT_CFUN_BOTH 4 /* disable phone both transmit and receive
* RF circuits */
#define AT_CFUN_MAX AT_CFUN_BOTH
/* Maximum value of supported functionality
* level */
#define AT_CFUN_FUN_DEFAULT AT_CFUN_MIN
/* Default functionality level applied when
* no value is given */
/* Resetting parameter values */
#define AT_CFUN_NORST 0 /* do not reset the ME before setting it
* to <fun> power level (default when <rst>
* is not given) */
#define AT_CFUN_RST 1 /* reset the ME before setting it to <fun>
* power level */
#define AT_CFUN_RST_DEFAULT AT_CFUN_NORST
/* Default resetting action applied when
* no value is given */
/* Optional parameter bitmask */
#define AT_CFUN_FUN_MASK AT_COMMAND_PARAM1
#define AT_CFUN_RST_MASK AT_COMMAND_PARAM2
/* CFUN AT command type */
typedef struct {
int fun;
int rst;
} at_cfun_t;
/* CPIN: Enter PIN
* ---------------
* Used to enter MT passwords which are needed before any other
* functionality of the MT can be used
* Parameter command:
* +CPIN=<pin>[,<newpin>]
* <pin> personal identification number
* <newpin> new personal identification number
*/
/* Optional parameter bitmask */
#define AT_CPIN_NEWPIN_MASK AT_COMMAND_PARAM2
/* CPIN AT command type */
typedef struct {
#define AT_CPIN_SIZE USER_PIN_SIZE /* Number of characters in pin parameter */
char pin[AT_CPIN_SIZE+1];
char newpin[AT_CPIN_SIZE+1];
} at_cpin_t;
/* CSQ: Signal quality
* -------------------
* Returns received signal strength indication and channel bit error rate
* from the Mobile Equipment
* Action command:
* no parameters
*/
/* CSQ AT command type */
#define AT_COMMAND_CSQ_MASK AT_COMMAND_NO_PARAM
typedef struct at_csq_s {} at_csq_t;
/* CESQ: Extented signal quality
* -----------------------------
* Returns received signal quality parameters.
* Action command:
* no parameters
*/
/* CESQ AT command type */
#define AT_COMMAND_CESQ_MASK AT_COMMAND_NO_PARAM
typedef struct at_cesq_s {} at_cesq_t;
/* CLAC: List all available AT commands
* ------------------------------------
* Returns one or more lines of AT Commands that are available for the user.
* Action command:
* no parameters
*/
/* CLAC AT command type */
#define AT_COMMAND_CLAC_MASK AT_COMMAND_NO_PARAM
typedef struct at_clac_s {} at_clac_t;
/*
* =========================
* Mobile Termination errors
* =========================
*/
/*
* CMEE: Report mobile termination error
* -------------------------------------
* Disables or enables the use of final result code +CME ERROR: <err> as an
* indication of an error relating to the functionality of the MT.
* <n> = 0, disables result code and displays ERROR instead.
* <n> = 1, enables result code and displays numeric <err>
* <n> = 2, enables result code and displays verbose <err>
* Parameter command:
* +CMEE=[<n>]
* <n> numeric parameter
*/
/* Numeric parameter values */
#define AT_CMEE_OFF 0 /* disable result code */
#define AT_CMEE_NUMERIC 1 /* enable numeric result code */
#define AT_CMEE_VERBOSE 2 /* enable verbose result code */
#define AT_CMEE_N_MIN AT_CMEE_OFF
/* Minimum value of supported numeric parameter */
#define AT_CMEE_N_MAX AT_CMEE_VERBOSE
/* Maximum value of supported numeric parameter */
#define AT_CMEE_N_DEFAULT AT_CMEE_OFF
/* Default value of supported numeric parameter */
/* Optional parameter bitmask */
#define AT_CMEE_N_MASK AT_COMMAND_PARAM1
/* CMEE AT command type */
typedef struct {
int n;
} at_cmee_t;
/*
* ================================
* Network service related commands
* ================================
*/
/* CNUM: Subscriber number
* -----------------------
* Returns the MSISDNs related to the subscriber.
* Action command:
* no parameters
*/
/* CNUM AT command type */
#define AT_COMMAND_CNUM_MASK AT_COMMAND_NO_PARAM
typedef struct at_cnum_s {} at_cnum_t;
/* CLCK: Facility lock
* -------------------
* Used to lock, unlock or interrogate a MT or a network facility <fac>.
* Action command:
* +CLCK=<fac>,<mode>[,<passwd>]
* <fac> facility value
* <mode> operation mode
* <passwd> password (pin code)
*/
/* Facility values */
#define AT_CLCK_SC "SC" /* SIM lock/unlock */
/* Operation mode */
#define AT_CLCK_UNLOCK 0 /* Unlock (enable) a service */
#define AT_CLCK_LOCK 1 /* Lock (disable) a service */
#define AT_CLCK_STATUS 2 /* Query the status of a network service */
/* Optional parameter bitmask */
#define AT_CLCK_PASSWD_MASK AT_COMMAND_PARAM3
/* CLCK AT command type */
typedef struct {
#define AT_CLCK_FAC_SIZE 2
char fac[AT_CLCK_FAC_SIZE+1];
int mode;
#define AT_CLCK_PASSWD_SIZE USER_PIN_SIZE
char passwd[AT_CLCK_PASSWD_SIZE+1];
} at_clck_t;
/* COPS: PLMN selection
* --------------------
* Forces an attempt to select and register the GSM/UMTS/EPS network operator
* using the SIM/USIM card installed in the currently selected card slot.
* Parameter command:
* +COPS=[<mode>[,<format>[,<oper>[,<AcT>]]]]
* <mode> operation mode of the network selection
* <format> representation format of the network operator
* <oper> APN operator identifier
* <AcT> access technology
*/
/* Network selection operation modes */
#define AT_COPS_AUTO 0 /* automatic mode */
#define AT_COPS_MANUAL 1 /* manual mode */
#define AT_COPS_DEREG 2 /* deregister from network */
#define AT_COPS_FORMAT 3 /* set only <format> for read command +COPS? */
#define AT_COPS_MANAUTO 4 /* manual/automatic mode; if manual selection
* fails, automatic mode is entered */
#define AT_COPS_MODE_DEFAULT AT_COPS_AUTO
/* Default operation mode applied when no
* value is given */
/* Representation formats */
#define AT_COPS_LONG NET_FORMAT_LONG /* long format alphanumeric */
#define AT_COPS_SHORT NET_FORMAT_SHORT /* short format alphanumeric */
#define AT_COPS_NUM NET_FORMAT_NUM /* numeric */
#define AT_COPS_FORMAT_MIN AT_COPS_LONG
/* Minimum value of supported representation
* format */
#define AT_COPS_FORMAT_MAX AT_COPS_NUM
/* Maximum value of supported representation
* format */
#define AT_COPS_FORMAT_DEFAULT AT_COPS_LONG
/* Default representation format applied when
* no value is given */
/* Access technology indicators */
#define AT_COPS_GSM NET_ACCESS_GSM /* GSM */
#define AT_COPS_COMPACT NET_ACCESS_COMPACT /* GSM Compact */
#define AT_COPS_UTRAN NET_ACCESS_UTRAN /* UTRAN */
#define AT_COPS_EGPRS NET_ACCESS_EGPRS /* GSM w/EGPRS */
#define AT_COPS_HSDPA NET_ACCESS_HSDPA /* UTRAN w/HSDPA */
#define AT_COPS_HSUPA NET_ACCESS_HSUPA /* UTRAN w/HSUPA */
#define AT_COPS_HSDUPA NET_ACCESS_HSDUPA /* w/HSDPA and HSUPA */
#define AT_COPS_EUTRAN NET_ACCESS_EUTRAN /* E-UTRAN */
#define AT_COPS_ACT_MIN AT_COPS_GSM
/* Minimum value of supported access
* technology */
#define AT_COPS_ACT_MAX AT_COPS_EUTRAN
/* Maximum value of supported access
* technology */
#define AT_COPS_ACT_DEFAULT AT_COPS_GSM
/* Default access technology applied when
* no value is given */
/* Optional parameter bitmask */
#define AT_COPS_MODE_MASK AT_COMMAND_PARAM1
#define AT_COPS_FORMAT_MASK AT_COMMAND_PARAM2
#define AT_COPS_OPER_MASK AT_COMMAND_PARAM3
#define AT_COPS_ACT_MASK AT_COMMAND_PARAM4
/* COPS AT command type */
typedef struct {
int mode;
int format;
#define AT_COPS_NUM_SIZE NET_FORMAT_NUM_SIZE
/* Size of numeric representation format */
#define AT_COPS_LONG_SIZE NET_FORMAT_LONG_SIZE
/* Size of long alphanumeric representation format */
#define AT_COPS_SHORT_SIZE NET_FORMAT_SHORT_SIZE
/* Size of short alphanumeric representation format */
network_plmn_t plmn;
int AcT;
} at_cops_t;
/* CREG: network registration
* --------------------------
* When <n>=1, returns +CREG: <stat>, the Mobile Equipment's circuit mode
* network registration status in GERA/UTRA/E-UTRA Network.
* When <n>=2, returns +CREG: <stat>[,<lac>,<ci>[,<AcT>]], the Mobile
* Equipment's circuit mode network registration status and location information
* in GERA/UTRA/E-UTRA Network.
* Parameter command:
* +CREG=[<n>]
* <n> numeric parameter
*/
/* Numeric parameter values */
#define AT_CREG_OFF 0 /* disable network registration unsolicited
* result code */
#define AT_CREG_ON 1 /* enable network registration unsolicited
* result code +CREG: <stat> */
#define AT_CREG_BOTH 2 /* enable network registration and location
* information unsolicited result code
* +CREG: <stat>[,<lac>,<ci>[,<AcT>]] */
#define AT_CREG_N_MIN AT_CREG_OFF
/* Minimum value of supported unsolicited
* result code */
#define AT_CREG_N_MAX AT_CREG_BOTH
/* Maximum value of supported unsolicited
* result code */
#define AT_CREG_N_DEFAULT AT_CREG_OFF
/* Default unsolicited result code applied
* when no value is given */
/* Optional parameter bitmask */
#define AT_CREG_N_MASK AT_COMMAND_PARAM1
/* CREG AT command type */
typedef struct {
int n;
} at_creg_t;
/*
* ==========================
* Commands for Packet Domain
* ==========================
*/
/* CGATT: EPS service attach/detach
* --------------------------------
* Used to attach the MT to, or detach the MT from, the EPS service.
* Action command (with optional parameters):
* +CGATT=[<state>]
* <state> numeric parameter that indicates the state of EPS attachment
*/
/* PS attachment status */
#define AT_CGATT_DETACHED 0 /* To detach from EPS service */
#define AT_CGATT_ATTACHED 1 /* To attach from EPS service */
#define AT_CGATT_STATE_MIN AT_CGATT_DETACHED
/* Minimum value of EPS attachment code */
#define AT_CGATT_STATE_MAX AT_CGATT_ATTACHED
/* Maximum value of EPS attachment code */
/* Optional parameter bitmask */
#define AT_CGATT_STATE_MASK AT_COMMAND_PARAM1
/* CGATT AT command type */
typedef struct {
int state;
} at_cgatt_t;
/* CGREG: GPRS network registration status
* ---------------------------------------
* When <n>=1, returns +CGREG: <stat>, the Mobile Equipment's GPRS network
* registration status in GERA/UTRA Network.
* When <n>=2, returns +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]], the Mobile
* Equipment's GPRS network registration status and location information in
* GERA/UTRA Network.
* Parameter command:
* +CGREG=[<n>]
* <n> numeric parameter
*/
/* Numeric parameter values */
#define AT_CGREG_OFF 0 /* disable network registration unsolicited
* result code */
#define AT_CGREG_ON 1 /* enable network registration unsolicited
* result code +CGREG: <stat> */
#define AT_CGREG_BOTH 2 /* enable network registration and location
* information unsolicited result code
* +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]] */
#define AT_CGREG_N_MIN AT_CGREG_OFF
/* Minimum value of supported unsolicited
* result code */
#define AT_CGREG_N_MAX AT_CGREG_BOTH
/* Maximum value of supported unsolicited
* result code */
#define AT_CGREG_N_DEFAULT AT_CGREG_OFF
/* Default unsolicited result code applied
* when no value is given */
/* Optional parameter bitmask */
#define AT_CGREG_N_MASK AT_COMMAND_PARAM1
/* CGREG AT command type */
typedef struct {
int n;
} at_cgreg_t;
/* CEREG: EPS network registration status
* --------------------------------------
* When <n>=1, returns +CEREG: <stat>, the Mobile Equipment's EPS services
* registration status in EUTRA Network.
* When <n>=2, returns +CEREG: <stat>[,<tac>,<ci>[,<AcT>]], the Mobile
* Equipment's EPS services registration status and location information in
* EUTRA Network.
* Parameter command:
* +CEREG=[<n>]
* <n> numeric parameter
*/
/* Numeric parameter values */
#define AT_CEREG_OFF 0 /* disable network registration unsolicited
* result code */
#define AT_CEREG_ON 1 /* enable network registration unsolicited
* result code +CEREG: <stat> */
#define AT_CEREG_BOTH 2 /* enable network registration and location
* information unsolicited result code
* +CEREG: <stat>[,<tac>,<ci>[,<AcT>]] */
#define AT_CEREG_N_MIN AT_CEREG_OFF
/* Minimum value of supported unsolicited
* result code */
#define AT_CEREG_N_MAX AT_CEREG_BOTH
/* Maximum value of supported unsolicited
* result code */
#define AT_CEREG_N_DEFAULT AT_CEREG_OFF
/* Default unsolicited result code applied
* when no value is given */
/* Optional parameter bitmask */
#define AT_CEREG_N_MASK AT_COMMAND_PARAM1
/* CEREG AT command type */
typedef struct {
int n;
} at_cereg_t;
/* CGDCONT: Define PDP Context
* ---------------------------
* Specifies PDP context parameter values for a PDP context identified by
* the (local) context identification parameter, <cid>.
* Parameter command:
* +CGDCONT=[<cid>[,<PDP_type>[,<APN>[,<PDP_addr>[,<d_comp>[,<h_comp>
* [,<IPv4AddrAlloc>[,<emergency indication>[,<P-CSCF_discovery>
* [,<IM_CN_Signalling_Flag_Ind>]]]]]]]]]]
* <cid> a numeric parameter which specifies a particular PDP
* context definition
* <PDP_type> type of packet data protocol ("IP", "IPV6", "IPV4V6")
* <APN> Access Point logical Name
* <PDP_addr> Mobile Equipment PDP address (not applicable to EPS)
* <d_comp> PDP data compression parameter
* <h_comp> PDP header compression parameter
* <IPv4AddrAlloc> IPv4 address allocation parameter
* <emergency indication> emergency bearer services support indication
* <P-CSCF_discovery> P-CSCF address discovery parameter
* <IM_CN_Signalling_Flag_Ind> IM CN subsystem-related signalling
* support indication
*/
/* PDP context identifier */
#define AT_CGDCONT_CID_MIN 1 /* Minimum value of context identifier */
#define AT_CGDCONT_CID_DEFAULT AT_CGDCONT_CID_MIN
/* PDP data compression parameter values */
#define AT_CGDCONT_D_COMP_OFF 0 /* PDP data compression is disabled */
#define AT_CGDCONT_D_COMP_ON 1 /* manufacturer preferred compression */
#define AT_CGDCONT_D_COMP_V42B 2 /* V.42bis */
#define AT_CGDCONT_D_COMP_V44 3 /* V.44 */
#define AT_CGDCONT_D_COMP_MIN AT_CGDCONT_D_COMP_OFF
#define AT_CGDCONT_D_COMP_MAX AT_CGDCONT_D_COMP_V44
#define AT_CGDCONT_D_COMP_DEFAULT AT_CGDCONT_D_COMP_OFF
/* PDP header compression parameter values */
#define AT_CGDCONT_H_COMP_OFF 0 /* PDP header compression is disabled */
#define AT_CGDCONT_H_COMP_ON 1 /* manufacturer preferred compression */
#define AT_CGDCONT_H_COMP_1144 2 /* RFC1144 (applicable for SNDCP only) */
#define AT_CGDCONT_H_COMP_2507 3 /* RFC2507 */
#define AT_CGDCONT_H_COMP_3095 4 /* RFC3095 (applicable for PDCP only) */
#define AT_CGDCONT_H_COMP_MIN AT_CGDCONT_H_COMP_OFF
#define AT_CGDCONT_H_COMP_MAX AT_CGDCONT_H_COMP_3095
#define AT_CGDCONT_H_COMP_DEFAULT AT_CGDCONT_H_COMP_OFF
/* IPv4AddrAlloc parameter values */
#define AT_CGDCONT_IPV4_NAS 0 /* IPv4 Address Allocation through NAS
* Signalling */
#define AT_CGDCONT_IPV4_DHCP 1 /* IPv4 Address Allocation through DHCP */
#define AT_CGDCONT_IPV4_MIN AT_CGDCONT_IPV4_NAS
#define AT_CGDCONT_IPV4_MAX AT_CGDCONT_IPV4_DHCP
#define AT_CGDCONT_IPV4_DEFAULT AT_CGDCONT_IPV4_NAS
/* emergency_indication parameter values */
#define AT_CGDCONT_EBS_OFF 0 /* PDP context is not for emergency bearer
* services */
#define AT_CGDCONT_EBS_ON 1 /* PDP context is for emergency bearer
* services */
#define AT_CGDCONT_EBS_MIN AT_CGDCONT_EBS_OFF
#define AT_CGDCONT_EBS_MAX AT_CGDCONT_EBS_ON
#define AT_CGDCONT_EBS_DEFAULT AT_CGDCONT_EBS_OFF
/* P_CSCF_discovery parameter values */
#define AT_CGDCONT_PCSCF_OFF 0 /* Preference of P-CSCF address discovery
* not influenced by +CGDCONTPDP */
#define AT_CGDCONT_PCSCF_NAS 1 /* Preference of P-CSCF address discovery
* through NAS Signalling */
#define AT_CGDCONT_PCSCF_DHCP 2 /* Preference of P-CSCF address discovery
* through DHCP */
#define AT_CGDCONT_PCSCF_MIN AT_CGDCONT_PCSCF_OFF
#define AT_CGDCONT_PCSCF_MAX AT_CGDCONT_PCSCF_DHCP
#define AT_CGDCONT_PCSCF_DEFAULT AT_CGDCONT_PCSCF_OFF
/* IM_CN_Signalling_Flag_Ind parameter values */
#define AT_CGDCONT_IM_CN_OFF 0 /* UE indicates that the PDP context is not
* for IM CN subsystem-related signalling
* only */
#define AT_CGDCONT_IM_CN_ON 1 /* UE indicates that the PDP context is for
* IM CN subsystem-related signalling
* only */
#define AT_CGDCONT_IM_CM_MIN AT_CGDCONT_IM_CN_OFF
#define AT_CGDCONT_IM_CM_MAX AT_CGDCONT_IM_CN_ON
#define AT_CGDCONT_IM_CM_DEFAULT AT_CGDCONT_IM_CN_OFF
/* Optional parameter bitmask */
#define AT_CGDCONT_CID_MASK AT_COMMAND_PARAM1
#define AT_CGDCONT_PDP_TYPE_MASK AT_COMMAND_PARAM2
#define AT_CGDCONT_APN_MASK AT_COMMAND_PARAM3
#define AT_CGDCONT_PDP_ADDR_MASK AT_COMMAND_PARAM4
#define AT_CGDCONT_D_COMP_MASK AT_COMMAND_PARAM5
#define AT_CGDCONT_H_COMP_MASK AT_COMMAND_PARAM6
#define AT_CGDCONT_IPV4ADDRALLOC_MASK AT_COMMAND_PARAM7
#define AT_CGDCONT_EMERGECY_INDICATION_MASK AT_COMMAND_PARAM8
#define AT_CGDCONT_P_CSCF_DISCOVERY_MASK AT_COMMAND_PARAM9
#define AT_CGDCONT_IM_CN_SIGNALLING_FLAG_IND_MASK AT_COMMAND_PARAM10
/* CGDCONT AT command type */
typedef struct {
int cid;
#define AT_CGDCONT_PDP_SIZE 6 /* PDP_type may be "IP", "IPV6", "IPV4V6" */
char PDP_type[AT_CGDCONT_PDP_SIZE+1];
#define AT_CGDCONT_APN_SIZE 100 /* number of characters in APN parameter */
char APN[AT_CGDCONT_APN_SIZE+1];
#define AT_CGDCONT_ADDR_SIZE 63 /* number of characters in PDP addr
* parameter (IPv6 address notation) */
char PDP_addr[AT_CGDCONT_ADDR_SIZE+1]; /* Does not apply to EPS */
int d_comp;
int h_comp;
int IPv4AddrAlloc;
int emergency_indication;
int P_CSCF_discovery;
int IM_CN_Signalling_Flag_Ind;
} at_cgdcont_t;
/* CGACT: PDP context activate or deactivate
* -----------------------------------------
* Used to activate or deactivate the specified PDP context(s).
* Action command (with optional parameters):
* +CGACT=[<state>[,<cid>[,<cid>[,...]]]]
* <state> numeric parameter that indicates the state of PDP context
* activation
* <cid> a numeric parameter which specifies a particular PDP context
* definition
*/
/* PDP context identifier */
#define AT_CGACT_CID_MIN 1 /* Minimum value of context identifier */
/* PDP context activation status */
#define AT_CGACT_DEACTIVATED 0 /* To deactivate the PDP context */
#define AT_CGACT_ACTIVATED 1 /* To activate the PDP context */
#define AT_CGACT_STATE_MIN AT_CGACT_DEACTIVATED
#define AT_CGACT_STATE_MAX AT_CGACT_ACTIVATED
#define AT_CGACT_STATE_DEFAULT AT_CGACT_DEACTIVATED
/* Optional parameter bitmask */
#define AT_CGACT_STATE_MASK AT_COMMAND_PARAM1
#define AT_CGACT_CID_MASK AT_COMMAND_PARAM2
/* CGACT AT command type */
typedef struct {
int state;
int cid;
} at_cgact_t;
/* CGPADDR: Show PDP address(es)
* -----------------------------
* Returns a list of PDP addresses for the specified context identifiers.
* +CGPADDR=[<cid>[,<cid>[,...]]]
* <cid> a numeric parameter which specifies a particular PDP
* context definition
*/
/* PDP context identifier */
#define AT_CGPADDR_CID_MIN 1 /* Minimum value of context identifier */
/* Optional parameter bitmask */
#define AT_CGPADDR_CID_MASK AT_COMMAND_PARAM1
/* CGPADDR AT command type */
typedef struct {
int cid;
} at_cgpaddr_t;
/*
* =================================
* Global AT command type definition
* =================================
*/
/* AT command type */
typedef struct {
at_command_id_t id; /* AT command identifier */
at_command_type_t type; /* AT command type */
int mask; /* Optional parameter bitmask */
union {
at_cgsn_t cgsn;
at_cgmm_t cgmm;
at_cgmr_t cgmr;
at_cimi_t cimi;
at_cfun_t cfun;
at_cpin_t cpin;
at_csq_t csq;
at_cesq_t cesq;
at_clac_t clac;
at_cmee_t cmee;
at_cnum_t cnum;
at_clck_t clck;
at_cops_t cops;
at_cgatt_t cgatt;
at_creg_t creg;
at_cgreg_t cgreg;
at_cereg_t cereg;
at_cgdcont_t cgdcont;
at_cgact_t cgact;
at_cgpaddr_t cgpaddr;
} command;
} at_command_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: at_command_decode() **
** **
** Description: Parses AT command line and accordingly fills data struc- **
** ture. The main functions of the AT command parser are: **
** - check the AT command syntax **
** - fill parameter values into the data structure **
** **
** Inputs: buffer: Pointer to the buffer containing AT com- **
** mand line **
** length: Number of bytes that should be processed **
** Others: None **
** **
** Outputs: at_command: AT command data structure to be filled **
** Return: The number of AT commands successfully **
** decoded; RETURNerror if an error occurred **
** Others: None **
** **
***************************************************************************/
int at_command_decode(const char* buffer, int length, at_command_t* at_command);
/****************************************************************************
** **
** Name: at_command_get_list() **
** **
** Description: Returns the list of supported AT commands. **
** **
** Inputs: buffer: Pointer to the buffer containing the **
** string representaton of the first AT com- **
** mand that is supported by the NAS sublayer **
** n_max: Maximum number of AT commands the buffer **
** may contain **
** Others: None **
** **
** Outputs: None **
** Return: The number of AT commands actually suppor- **
** ted by the NAS sublayer **
** Others: None **
** **
***************************************************************************/
int at_command_get_list(const char** buffer, int n_max);
#endif /* __AT_COMMAND_H__*/
@@ -0,0 +1,420 @@
/*****************************************************************************
Source at_error.c
Version 0.1
Date 2012/03/12
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines error codes returned when execution of AT command
failed.
*****************************************************************************/
#include "at_error.h"
#include "commonDef.h"
#include "nas_log.h"
#include <string.h> // strcpy
#include <stdio.h> // sprintf
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
extern int at_response_format_v1;
/*
* Result code suppression indicator (set by ATQ0 and ATQ1)
* -------------------------------------------------------
* FALSE - Result codes are transmitted to the user application
* TRUE - Result codes are suppressed and not transmitted
*/
int at_error_code_suppression_q1 = FALSE;
/*
* Verbose mode indicator (set by ATV0, ATV1 and AT+CMEE)
* ------------------------------------------------------
*/
at_error_format_t at_error_format = AT_ERROR_OFF;
/****************************************************************************/
/******************* L O C A L D E F I N I T I O N S *******************/
/****************************************************************************/
/*
* General errors
* --------------
*/
static const char * _at_error_str[] = {
"phone failure",
"no connection to phone",
"phone-adaptor link reserved",
"operation not allowed",
"operation not supported",
"PH-SIM PIN required",
"PH-FSIM PIN required",
"PH-FSIM PUK required",
NULL,
NULL,
"SIM not inserted",
"SIM PIN required",
"SIM PUK required",
"SIM failure",
"SIM busy",
"SIM wrong",
"incorrect password",
"SIM PIN2 required",
"SIM PUK2 required",
NULL,
"memory full",
"invalid index",
"not found",
"memory failure",
"text string too long",
"invalid characters in text string",
"dial string too long",
"invalid characters in dial string",
NULL,
NULL,
"no network service",
"network timeout",
"network not allowed - emergency calls only",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"network personalization PIN required",
"network personalization PUK required",
"network subset personalization PIN required",
"network subset personalization PUK required",
"service provider personalization PIN required",
"service provider personalization PUK required",
"corporate personalization PIN required",
"corporate personalization PUK required",
"hidden key required",
"EAP method not supported",
"Incorrect parameters",
};
/*
* GPRS-related errors
* -------------------
*/
static const char* _at_error_gprs[] = {
"Illegal MS",
NULL,
NULL,
"Illegal ME",
"GPRS services not allowed",
NULL,
NULL,
NULL,
"PLMN not allowed",
"Location area not allowed",
"Roaming not allowed in this location area",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"service option not supported",
"requested service option not subscribed",
"service option temporarily out of order",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
"unspecified GPRS error",
"PDP authentication failure",
"invalid mobile class",
"Last PDN disconnection not allowed",
};
/*
* VBS / VGCS and eMLPP -related errors
* ------------------------------------
*/
static const char* _at_error_vbs[] = {
/* 151 "VBS/VGCS not supported by the network" */
"No service subscription on SIM",
"No subscription for group ID",
"Group Id not activated on SIM",
"No matching notification",
"VBS/VGCS call already present",
"Congestion",
"Network failure",
"Uplink busy",
"No access rights for SIM file",
"No subscription for priority",
"operation not applicable or not possible",
"Group Id prefixes not supported",
"Group Id prefixes not usable for VBS",
"Group Id prefix value invalid",
};
/* Returns the verbose value of AT command error */
static const char* _at_error_to_string(int error);
static int _at_error_encode_ok(char* buffer);
static int _at_error_encode_ko(char* buffer, at_error_type_t type, int error);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: at_error_set_format() **
** **
** Description: Sets the format of the error code **
** **
** Inputs: format: Format of the error code **
** Others: None **
** **
** Outputs: Return: None **
** Others: at_error_format **
** **
***************************************************************************/
void at_error_set_format(at_error_format_t format)
{
LOG_FUNC_IN;
at_error_format = format;
LOG_FUNC_OUT;
}
/****************************************************************************
** **
** Name: at_error_get_format() **
** **
** Description: Gets the format of the error code **
** **
** Inputs: format: Format of the error code **
** Others: None **
** **
** Outputs: Return: None **
** Others: at_error_format **
** **
***************************************************************************/
at_error_format_t at_error_get_format(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (at_error_format);
}
/****************************************************************************
** **
** Name: at_error_encode() **
** **
** Description: Encodes result code returned when AT command has been **
** processed. Result code can be OK or 0, if the command **
** succeed, ERROR or 4, if the command failed; depending of **
** the response format selected by the user. **
** **
** Inputs type: Type of the error code to encode **
** error: Error code to encode **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of characters that have been **
** successfully encoded; **
** Others: None **
** **
***************************************************************************/
int at_error_encode(char* buffer, at_error_type_t type, int error)
{
LOG_FUNC_IN;
int bytes = 0;
/* Result code suppression (ATQ0, ATQ1) */
if (at_error_code_suppression_q1) {
LOG_FUNC_RETURN (0);
}
if (type == AT_ERROR_OK) {
/* Encode success return code */
bytes = _at_error_encode_ok(buffer);
}
else {
/* Encode failure return code */
bytes = _at_error_encode_ko(buffer, type, error);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _at_error_encode_ok() **
** **
** Description: Encodes AT command success result code message **
** **
** Inputs None **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of characters that have been **
** successfully encoded; **
** Others: None **
** **
***************************************************************************/
static int _at_error_encode_ok(char* buffer)
{
LOG_FUNC_IN;
int offset = 0;
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
offset += sprintf(buffer + offset, "OK\r\n");
LOG_FUNC_RETURN (offset);
}
/****************************************************************************
** **
** Name: _at_error_encode_ko() **
** **
** Description: Encodes AT command error code message **
** **
** Inputs type: Type of the error code to encode **
** error: Error code to encode **
** Others: at_error_format **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of characters that have been **
** successfully encoded; **
** Others: None **
** **
***************************************************************************/
static int _at_error_encode_ko(char* buffer, at_error_type_t type, int error)
{
LOG_FUNC_IN;
int offset = 0;
if (at_response_format_v1) {
offset += sprintf(buffer, "\r\n");
}
/* Result code is disabled */
if (at_error_format == AT_ERROR_OFF) {
offset += sprintf(buffer + offset, "ERROR\r\n");
}
else
{
/* Error related to execution of AT command operation */
if (type == AT_ERROR_CME) {
offset += sprintf(buffer + offset, "+CME ERROR: ");
}
/* Result code is enabled for numeric values */
if (at_error_format == AT_ERROR_NUMERIC) {
offset += sprintf(buffer + offset, "%d\r\n", error);
}
/* Result code is enabled for verbose values */
else {
const char* error_str = _at_error_to_string(error);
if (error_str != NULL) {
offset += sprintf(buffer + offset, "%s\r\n", error_str);
}
else {
/* Error code is not valid */
offset += sprintf(buffer + offset, "invalid error code\r\n");
}
}
}
LOG_FUNC_RETURN (offset);
}
/****************************************************************************
** **
** Name: at_error_to_string() **
** **
** Description: Returns the verbose value of AT command error **
** **
** Inputs: error: AT command error identifier **
** Others: None **
** **
** Outputs: Return: The error's verbose value **
** NULL if the error code is not valid **
** Others: None **
** **
***************************************************************************/
static const char* _at_error_to_string(int error)
{
if (error < AT_ERROR_LAST_GENERAL_ERROR + 1)
{
/* General errors */
if (error > AT_ERROR_FIRST_GENERAL_ERROR - 1) {
return _at_error_str[error];
}
else {
return NULL;
}
}
else if (error < AT_ERROR_LAST_GPRS_RELATED_ERROR + 1)
{
/* GPRS-related errors */
if (error > AT_ERROR_FIRST_GPRS_RELATED_ERROR - 1) {
return _at_error_gprs[error - AT_ERROR_FIRST_GPRS_RELATED_ERROR];
}
else {
return NULL;
}
}
else if (error < AT_ERROR_LAST_VBS_RELATED_ERROR + 1)
{
/* VBS / VGCS and eMLPP -related errors */
if (error > AT_ERROR_FIRST_VBS_RELATED_ERROR - 1) {
return _at_error_vbs[error - AT_ERROR_FIRST_VBS_RELATED_ERROR];
}
else {
return NULL;
}
}
return NULL;
}
@@ -0,0 +1,173 @@
/*****************************************************************************
Source at_error.h
Version 0.1
Date 2012/03/12
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines error codes returned when execution of AT command
failed.
*****************************************************************************/
#ifndef __AT_ERROR_H__
#define __AT_ERROR_H__
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/*
* Cause code used to notify that the NAS procedure has been successfully
* processed
*/
#define AT_ERROR_SUCCESS (-1)
/*
* General errors
* --------------
*/
#define AT_ERROR_FIRST_GENERAL_ERROR AT_ERROR_PHONE_FAILURE
#define AT_ERROR_PHONE_FAILURE 0
#define AT_ERROR_NO_CONNECTION_TO_PHONE 1
#define AT_ERROR_PHONE_ADAPTOR_LINK_RESERVED 2
#define AT_ERROR_OPERATION_NOT_ALLOWED 3
#define AT_ERROR_OPERATION_NOT_SUPPORTED 4
#define AT_ERROR_PHSIM_PIN_REQUIRED 5
#define AT_ERROR_PHFSIM_PIN_REQUIRED 6
#define AT_ERROR_PHFSIM_PUK_REQUIRED 7
#define AT_ERROR_SIM_NOT_INSERTED 10
#define AT_ERROR_SIM_PIN_REQUIRED 11
#define AT_ERROR_SIM_PUK_REQUIRED 12
#define AT_ERROR_SIM_FAILURE 13
#define AT_ERROR_SIM_BUSY 14
#define AT_ERROR_SIM_WRONG 15
#define AT_ERROR_INCORRECT_PASSWD 16
#define AT_ERROR_SIM_PIN2_REQUIRED 17
#define AT_ERROR_SIM_PUK2_REQUIRED 18
#define AT_ERROR_MEMORY_FULL 20
#define AT_ERROR_INVALID_INDEX 21
#define AT_ERROR_NOT_FOUND 22
#define AT_ERROR_MEMORY_FAILURE 23
#define AT_ERROR_TEXT_STRING_TOO_LONG 24
#define AT_ERROR_TEXT_STRING_INVALID_CHAR 25
#define AT_ERROR_DIAL_STRING_TOO_LONG 26
#define AT_ERROR_DIAL_STRING_INVALID_CHAR 27
#define AT_ERROR_NO_NETWORK_SERVICE 30
#define AT_ERROR_TIMEOUT 31
#define AT_ERROR_NETWORK_NOT_ALLOWED 32
#define AT_ERROR_NETWORK_PERSO_PIN_REQUIRED 40
#define AT_ERROR_NETWORK_PERSO_PUK_REQUIRED 41
#define AT_ERROR_NETWORK_SUBNET_PERSO_PIN_REQUIRED 42
#define AT_ERROR_SUBNET_PERSO_PUK_REQUIRED 43
#define AT_ERROR_PROVIDER_PERSO_PIN_REQUIRED 44
#define AT_ERROR_PROVIDER_PERSO_PUK_REQUIRED 45
#define AT_ERROR_CORPORATE_PERSO_PIN_REQUIRED 46
#define AT_ERROR_CORPORATE_PERSO_PUK_REQUIRED 47
#define AT_ERROR_HIDDEN_KEY_REQUIRED 48
#define AT_ERROR_EAP_METHOD_NOT_SUPPORTED 49
#define AT_ERROR_INCORRECT_PARAMETERS 50
#define AT_ERROR_LAST_GENERAL_ERROR AT_ERROR_INCORRECT_PARAMETERS
#define AT_ERROR_UNKNOWN 100
/*
* GPRS-related errors
* -------------------
*/
/* Errors related to a failure to perform an attach */
#define AT_ERROR_FIRST_GPRS_RELATED_ERROR AT_ERROR_ILLEGAL_MS
#define AT_ERROR_ILLEGAL_MS 103
#define AT_ERROR_ILLEGAL_ME 106
#define AT_ERROR_GPRS_NOT_ALLOWED 107
#define AT_ERROR_PLMN_NOT_ALLOWED 111
#define AT_ERROR_LOCATION_AREA_NOT_ALLOWED 112
#define AT_ERROR_ROAMING_NOT_ALLOWED 113
/* Errors related to a failure to activate a context */
#define AT_ERROR_OPTION_NOT_SUPPORTED 132
#define AT_ERROR_OPTION_NOT_SUBSCRIBED 133
#define AT_ERROR_OPTION_TEMPORARILY_OUT_OF_ORDER 134
#define AT_ERROR_PDP_AUTHENTICATION_FAILURE 149
/* Errors related to a failure to disconnect a PDN */
#define AT_ERROR_LAST_PDP_DISCONNECT_NOT_ALLOWED 151
/* Other GPRS errors */
#define AT_ERROR_UNSPECIFIED_GPRS_ERROR 148
#define AT_ERROR_INVALID_MOBILE_CLASS 150
#define AT_ERROR_LAST_GPRS_RELATED_ERROR AT_ERROR_LAST_PDP_DISCONNECT_NOT_ALLOWED
/*
* VBS / VGCS and eMLPP -related errors
* ------------------------------------
*/
#define AT_ERROR_FIRST_VBS_RELATED_ERROR AT_ERROR_NO_SERVICE_SUBSCRIPTION_ON_SIM
/* AT_ERROR_VBS_VGCS_NOT_SUPPORTED=151,*/ /* !!! Conflict with AT_ERROR_LAST_PDP_DISCONNECT_NOT_ALLOWED !!! */
#define AT_ERROR_NO_SERVICE_SUBSCRIPTION_ON_SIM 152
#define AT_ERROR_NO_SUBSCRIPTION_FOR_GROUP_ID 153
#define AT_ERROR_GROUP_ID_NOT_ACTIVATED_ON_SIM 154
#define AT_ERROR_NO_MATCHING_NOTIFICATION 155
#define AT_ERROR_VBS_VGCS_CALL_ALREADY_PRESENT 156
#define AT_ERROR_CONGESTION 157
#define AT_ERROR_NETWORK_FAILURE 158
#define AT_ERROR_UPLINK_BUSY 159
#define AT_ERROR_NO_ACCESS_RIGHTS_FOR_SIM_FILE 160
#define AT_ERROR_NO_SUBSCRIPTION_FOR_PRIORITY 161
#define AT_ERROR_OPERATION_NOT_APPLICABLE_OR_NOT_POSSIBLE 162
#define AT_ERROR_GROUP_ID_PREFIXES_NOT_SUPPORTED 163
#define AT_ERROR_GROUP_ID_PREFIXES_NOT_USABLE_FOR_VBS 164
#define AT_ERROR_GROUP_ID_PREFIX_VALUE_INVALID 165
#define AT_ERROR_LAST_VBS_RELATED_ERROR AT_ERROR_GROUP_ID_PREFIX_VALUE_INVALID
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* Error type identifiers
*/
typedef enum {
AT_ERROR_NONE, /* No error code displayed */
AT_ERROR_OK, /* AT command successfully processed */
AT_ERROR_SYNTAX, /* AT command syntax error */
AT_ERROR_CME, /* Error related to execution of AT command
* operation */
} at_error_type_t;
/*
* Error code format identifiers
*/
typedef enum {
AT_ERROR_OFF, /* disable result code and use ERROR instead */
AT_ERROR_NUMERIC, /* enable result code and use numeric error values */
AT_ERROR_VERBOSE, /* enable result code and use verbose error values */
} at_error_format_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
void at_error_set_format(at_error_format_t format);
at_error_format_t at_error_get_format(void);
int at_error_encode(char* buffer, at_error_type_t type, int error);
#endif /* __AT_ERROR_H__*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,761 @@
/*****************************************************************************
Source at_response.h
Version 0.1
Date 2012/03/09
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines structure of the AT command response returned after
completion of AT command processing.
*****************************************************************************/
#ifndef __AT_RESPONSE_H__
#define __AT_RESPONSE_H__
#include "at_command.h"
#include "commonDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/*
* Total number of characters, including line terminators, in information text
*/
#define AT_RESPONSE_INFO_TEXT_SIZE 2048
/*
* Value of the mask parameter for AT command reponses without any optional
* parameters
*/
#define AT_RESPONSE_NO_PARAM AT_COMMAND_PARAM0
/*
* Maximum value of an AT command response identifier
*/
#define AT_RESPONSE_ID_MAX AT_COMMAND_ID_MAX
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* ================
* General commands
* ================
*/
/* CGSN: Request Product Serial Number identification (IMEI)
* ---------------------------------------------------------
* Returns information text intended to permit the user to identify the
* individual Mobile Equipment to which it is connected to.
* Action command:
* +CGSN returns <sn>
* <sn> information text containing the IMEI
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGSN_MASK AT_RESPONSE_NO_PARAM
/* CGSN AT command response type */
typedef struct {
char sn[AT_RESPONSE_INFO_TEXT_SIZE+1];
} at_cgsn_resp_t;
/* CGMI: Request manufacturer identification
* -----------------------------------------
* Returns information text intended to permit the user to identify the
* manufacturer of the Mobile Equipment to which it is connected to.
* Action command:
* +CGMI returns <manufacturer>
* <manufacturer> information text containing the manufacturer id
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGMI_MASK AT_RESPONSE_NO_PARAM
/* CGMI AT command response type */
typedef struct {
char manufacturer[AT_RESPONSE_INFO_TEXT_SIZE+1];
} at_cgmi_resp_t;
/* CGMM: Request model identification
* ----------------------------------
* Returns information text intended to permit the user to identify the
* specific model of the Mobile Equipment to which it is connected to.
* +CGMM returns <model>
* <model> information text containing the model id
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGMM_MASK AT_RESPONSE_NO_PARAM
/* CGMM AT command response type */
typedef struct {
char model[AT_RESPONSE_INFO_TEXT_SIZE+1];
} at_cgmm_resp_t;
/* CGMR: Request revision identification
* -------------------------------------
* Returns information text intended to permit the user to identify the
* version, revision level or date, or other pertinent information of the
* Mobile Equipment to which it is connected to.
* +CGMR returns <revision>
* <revision> information text containing the revision of the firmware
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGMR_MASK AT_RESPONSE_NO_PARAM
/* CGMR AT command response type */
typedef struct {
char revision[AT_RESPONSE_INFO_TEXT_SIZE+1];
} at_cgmr_resp_t;
/* CIMI: Request International Mobile Subscriber Identity
* ------------------------------------------------------
* Returns <IMSI>, which is intended to permit the user to identify the
* individual SIM card or active application in the UICC (GSM or USIM)
* which is attached to the Mobile Equipment to which it is connected to.
* Action command:
* +CIMI returns <IMSI>
* <IMSI> International Mobile Subscriber Identity (string without
* double quotes)
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CIMI_MASK AT_RESPONSE_NO_PARAM
/* CIMI AT command response type */
typedef struct {
char IMSI[AT_RESPONSE_INFO_TEXT_SIZE+1];
} at_cimi_resp_t;
/*
* ==============================================
* Mobile Termination control and status commands
* ==============================================
*/
/* CFUN: Set phone functionality
* -----------------------------
* Used to set the Mobile Equipment to different power consumption states
* Read parameter command:
* +CFUN? returns +CFUN: <fun>
* <fun> integer type - level of functionality
* Test parameter command:
* +CFUN=? returns +CFUN: (list of supported <fun>s),(list of supported <rst>s)
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CFUN_MASK AT_RESPONSE_NO_PARAM
/* CFUN AT command response type */
typedef struct {
int fun;
} at_cfun_resp_t;
/* CPIN: Enter PIN
* ---------------
* Used to enter MT passwords which are needed before any other
* functionality of the MT can be used
* Read parameter command:
* +CPIN? returns +CPIN: <code>
* <code> string - value may be: "READY", "SIM PIN"
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CPIN_MASK AT_RESPONSE_NO_PARAM
/* CPIN AT command response type */
typedef struct {
#define AT_CPIN_RESP_SIZE 16
char code[AT_CPIN_RESP_SIZE+1];
} at_cpin_resp_t;
/* CSQ: Signal quality
* -------------------
* Returns received signal strength indication and channel bit error rate
* from the Mobile Equipment
* Action command:
* +CSQ returns +CSQ: <rssi>, <ber>
* <rssi> integer type - received signal strength indication (in dBm)
* <ber> integer type - channel bit error rate (in percent)
*/
/* Received signal strength indicator */
#define AT_CSQ_RSSI_0 0 /* -113 dBm or less */
#define AT_CSQ_RSSI_31 31 /* -51 dBm or greater */
#define AT_CSQ_RSSI_UNKNOWN 99 /* not known or not detectable */
/* Channel bit error rate */
#define AT_CSQ_BER_0 0 /* BER < 0.2 % */
#define AT_CSQ_BER_1 1 /* 0.2 % < BER < 0.4 % */
#define AT_CSQ_BER_2 2 /* 0.4 % < BER < 0.8 % */
#define AT_CSQ_BER_3 3 /* 0.8 % < BER < 1.6 % */
#define AT_CSQ_BER_4 4 /* 1.6 % < BER < 3.2 % */
#define AT_CSQ_BER_5 5 /* 3.2 % < BER < 6.4 % */
#define AT_CSQ_BER_6 6 /* 6.4 % < BER < 12.8 % */
#define AT_CSQ_BER_7 7 /* 12.8 % < BER */
#define AT_CSQ_BER_UNKNOWN 99 /* not known or not detectable */
/* Optional parameter bitmask */
#define AT_RESPONSE_CSQ_MASK AT_RESPONSE_NO_PARAM
/* CSQ AT command response type */
typedef struct {
int rssi;
int ber;
} at_csq_resp_t;
/* CESQ: Extended signal quality
* -----------------------------
* Returns received signal quality parameters.
* Action command:
* +CESQ returns +CESQ: <rssi>,<ber>,<rscp>,<ecno>,<rsrq>,<rsrp>
* <rssi> integer type - received signal strength indication (in dBm)
* <ber> integer type - channel bit error rate (in percent)
* <rscp> integer type - received signal code power (in dBm)
* <ecno> integer type - ratio of the received energy per PN chip (in dBm)
* <rsrq> integer type - reference signal received quality (in dBm)
* <rsrp> integer type - reference signal received power (in dBm)
*/
/* Received signal strength indicator */
#define AT_CESQ_RSSI_0 0 /* -113 dBm or less */
#define AT_CESQ_RSSI_31 31 /* -51 dBm or greater */
#define AT_CESQ_RSSI_UNKNOWN 99 /* not known or not detectable */
/* Channel bit error rate */
#define AT_CESQ_BER_0 0 /* BER < 0.2 % */
#define AT_CESQ_BER_1 1 /* 0.2 % < BER < 0.4 % */
#define AT_CESQ_BER_2 2 /* 0.4 % < BER < 0.8 % */
#define AT_CESQ_BER_3 3 /* 0.8 % < BER < 1.6 % */
#define AT_CESQ_BER_4 4 /* 1.6 % < BER < 3.2 % */
#define AT_CESQ_BER_5 5 /* 3.2 % < BER < 6.4 % */
#define AT_CESQ_BER_6 6 /* 6.4 % < BER < 12.8 % */
#define AT_CESQ_BER_7 7 /* 12.8 % < BER */
#define AT_CESQ_BER_UNKNOWN 99 /* not known or not detectable */
/* Received signal code power */
#define AT_CESQ_RSCP_0 0 /* -120 dBm or less */
#define AT_CESQ_RSCP_96 96 /* -24 dBm or greater */
#define AT_CESQ_RSCP_UNKNOWN 255 /* not known or not detectable */
/* Ratio of the received energy per PN chip (Ec/No) */
#define AT_CESQ_ECNO_0 0 /* -24 dBm or less */
#define AT_CESQ_ECNO_49 49 /* 0,5 dBm or greater */
#define AT_CESQ_ECNO_UNKNOWN 255 /* not known or not detectable */
/* Reference signal received quality */
#define AT_CESQ_RSRQ_0 0 /* -19,5 dBm or less */
#define AT_CESQ_RSRQ_34 34 /* -2,5 dBm or greater */
#define AT_CESQ_RSRQ_UNKNOWN 255 /* not known or not detectable */
/* Reference signal received power */
#define AT_CESQ_RSRP_0 0 /* -140 dBm or less */
#define AT_CESQ_RSRP_97 97 /* -43 dBm or greater */
#define AT_CESQ_RSRP_UNKNOWN 255 /* not known or not detectable */
/* Optional parameter bitmask */
#define AT_RESPONSE_CESQ_MASK AT_RESPONSE_NO_PARAM
/* CSQ AT command response type */
typedef struct {
int rssi;
int ber;
int rscp;
int ecno;
int rsrq;
int rsrp;
} at_cesq_resp_t;
/* CLAC: List all available AT commands
* ------------------------------------
* Returns one or more lines of AT Commands that are available for the user.
* Action command:
* +CLAC returns +CLAC: <AT Command1>[<CR><LF><AT Command2>[...]]
* <AT Command> string - defines the AT command including the prefix AT
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CLAC_MASK AT_RESPONSE_NO_PARAM
/* CLAC AT command response type */
typedef struct {
int n_acs;
#define AT_CLAC_RESP_SIZE 100
const char* ac[AT_CLAC_RESP_SIZE];
} at_clac_resp_t;
/*
* =========================
* Mobile Termination errors
* =========================
*/
/*
* CMEE: Report mobile termination error
* -------------------------------------
* Disables or enables the use of final result code +CME ERROR: <err> as an
* indication of an error relating to the functionality of the MT.
* Read parameter command:
* +CMEE? returns +CMEE: <n>
* <n> numeric parameter
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CMEE_MASK AT_RESPONSE_NO_PARAM
/* CMEE AT command response type */
typedef at_cmee_t at_cmee_resp_t;
/*
* ================================
* Network service related commands
* ================================
*/
/* CNUM: Subscriber number
* -----------------------
* Returns the MSISDNs related to the subscriber.
* Action command:
* +CNUM returns +CNUM: <number1>,<type1>[<CR><LF>
* +CNUM: <number2>,<type2>[...]]
* <numberx> string type phone number of format specified by <typex>
* <typex> type of address octet in integer format
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CNUM_MASK AT_RESPONSE_NO_PARAM
/* CNUM AT command response type */
typedef struct {
#define AT_CNUM_NUMBER_SIZE MSISDN_DIGIT_SIZE
char number[AT_CNUM_NUMBER_SIZE];
int type;
} at_cnum_resp_t;
/* CLCK: Facility lock
* -------------------
* Used to lock, unlock or interrogate a MT or a network facility <fac>.
* When <mode>=2, returns +CLCK: <status>
* <status> state of the network service
*/
/* Network service status */
#define AT_CLCK_RESP_STATUS_NOT_ACTIVE 0
#define AT_CLCK_RESP_STATUS_ACTIVE 1
/* Optional parameter bitmask */
#define AT_RESPONSE_CLCK_MASK AT_RESPONSE_NO_PARAM
/* CLCK AT command response type */
typedef struct {
int status;
} at_clck_resp_t;
/* COPS: PLMN selection
* --------------------
* Forces an attempt to select and register the GSM/UMTS/EPS network operator
* using the SIM/USIM card installed in the currently selected card slot.
* Read parameter command:
* +COPS? returns +COPS:<mode>[,<format>,<oper>[,<AcT>]]
* <mode> operation mode of the network selection
* <format> representation format of the network operator
* <oper> APN operator identifier
* <AcT> access technology
* Test command returns a set of parameters, each representing an operator
* present in the network:
* +COPS=? returns +COPS: [list of supported (<stat>,long alphanumeric <oper>,
* short alphanumeric <oper>,numeric <oper>[,<AcT>])s][,,(list of supported
* <mode>s),(list of supported <format>s)]
* <stat> network operator availability
*/
/* Optional parameter bitmask */
#define AT_COPS_RESP_FORMAT_MASK AT_COMMAND_PARAM2
#define AT_COPS_RESP_OPER_MASK AT_COMMAND_PARAM3
#define AT_COPS_RESP_ACT_MASK AT_COMMAND_PARAM4
/* Structure of COPS AT test parameter command */
typedef struct {
const char* data; /* String representation of the list of operators */
int size; /* Size in byte of the data to be dislayed */
} at_cops_tst_t;
/* Structure of COPS AT read parameter command */
typedef at_cops_t at_cops_get_t;
/* COPS AT command response type */
typedef union {
at_cops_tst_t tst;
at_cops_get_t get;
} at_cops_resp_t;
/* CREG: network registration
* --------------------------
* When <n>=1, returns +CREG: <stat>, the Mobile Equipment's circuit mode
* network registration status in GERA/UTRA/E-UTRA Network.
* When <n>=2, returns +CREG: <stat>[,<lac>,<ci>[,<AcT>]], the Mobile
* Equipment's circuit mode network registration status and location information
* in GERA/UTRA/E-UTRA Network.
* Read parameter command:
* +CREG? returns +CREG:<n>,<stat>[,<lac>,<ci>[,<AcT>]]
* <n> numeric parameter
* <stat> numeric parameter that indicates the circuit mode registration
* status
* <lac> string type; two byte location area code in hexadecimal format
* <ci> string type; four byte GERAN/UTRAN/E-UTRAN cell ID in hexadeci-
* mal format
* <AcT> a numeric parameter that indicates the access technology of
* the serving cell
*/
/* Network registration status */
#define AT_CREG_RESP_REG_OFF NET_REG_STATE_OFF
#define AT_CREG_RESP_REG_HN NET_REG_STATE_HN
#define AT_CREG_RESP_REG_ON NET_REG_STATE_ON
#define AT_CREG_RESP_REG_DENIED NET_REG_STATE_DENIED
#define AT_CREG_RESP_REG_UNKNOWN NET_REG_STATE_UNKNOWN
#define AT_CREG_RESP_REG_SMS_HN NET_REG_STATE_SMS_HN
#define AT_CREG_RESP_REG_SMS_ROAMING NET_REG_STATE_SMS_ROAMING
#define AT_CREG_RESP_REG_ROAMING NET_REG_STATE_ROAMING
/* Access technology indicators */
#define AT_CREG_RESP_GSM NET_ACCESS_GSM /* GSM */
#define AT_CREG_RESP_COMPACT NET_ACCESS_COMPACT /* GSM Compact */
#define AT_CREG_RESP_UTRAN NET_ACCESS_UTRAN /* UTRAN */
#define AT_CREG_RESP_EGPRS NET_ACCESS_EGPRS /* GSM w/EGPRS */
#define AT_CREG_RESP_HSDPA NET_ACCESS_HSDPA /* UTRAN w/HSDPA */
#define AT_CREG_RESP_HSUPA NET_ACCESS_HSUPA /* UTRAN w/HSUPA */
#define AT_CREG_RESP_HSDUPA NET_ACCESS_HSDUPA /* w/HSDPA and HSUPA */
#define AT_CREG_RESP_EUTRAN NET_ACCESS_EUTRAN /* E-UTRAN */
/* Optional parameter bitmask */
//#define AT_CREG_RESP_N_MASK AT_COMMAND_PARAM1
#define AT_CREG_RESP_LAC_MASK AT_COMMAND_PARAM3
#define AT_CREG_RESP_CI_MASK AT_COMMAND_PARAM4
#define AT_CREG_RESP_ACT_MASK AT_COMMAND_PARAM5
/* CREG AT command response type */
typedef struct {
int n;
int stat;
#define AT_CREG_RESP_LAC_SIZE 4
char lac[AT_CREG_RESP_LAC_SIZE+1];
#define AT_CREG_RESP_CI_SIZE 8
char ci[AT_CREG_RESP_CI_SIZE+1];
int AcT;
} at_creg_resp_t;
/*
* ==========================
* Commands for Packet Domain
* ==========================
*/
/* CGATT: GPRS service attach/detach
* ---------------------------------
* Used to attach the MT to, or detach the MT from, the GPRS service.
* Read parameter command:
* +CGATT? returns CGATT: <state>
* <state> numeric parameter that indicates the state of GPRS attachment
* Test parameter command:
* +CGATT=? returns CGATT: (list of supported <state>s)
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGATT_MASK AT_RESPONSE_NO_PARAM
/* CGATT AT command response type */
typedef struct {
int state;
} at_cgatt_resp_t;
/* CGREG: GPRS network registration status
* ---------------------------------------
* When <n>=1, returns +CGREG: <stat>, the Mobile Equipment's GPRS network
* registration status in GERA/UTRA Network.
* When <n>=2, returns +CGREG: <stat>[,<lac>,<ci>[,<AcT>,<rac>]], the Mobile
* Equipment's GPRS network registration status and location information in
* GERA/UTRA Network.
* Read parameter command:
* +CGREG? returns +CGREG:<n>,<stat>[,<lac>,<ci>[,<AcT>,<rac>]]
* <n> numeric parameter
* <stat> numeric parameter that indicates the GPRS registration status
* <lac> string type; two byte location area code in hexadecimal format
* <ci> string type; four byte GERAN/UTRAN cell ID in hexadecimal format
* <AcT> a numeric parameter that indicates the access technology of
* the serving cell
* <rac> string type; one byte routing area code in hexadecimal format
*/
/* Network registration status */
#define AT_CGREG_RESP_REG_OFF NET_REG_STATE_OFF
#define AT_CGREG_RESP_REG_HN NET_REG_STATE_HN
#define AT_CGREG_RESP_REG_ON NET_REG_STATE_ON
#define AT_CGREG_RESP_REG_DENIED NET_REG_STATE_DENIED
#define AT_CGREG_RESP_REG_UNKNOWN NET_REG_STATE_UNKNOWN
#define AT_CGREG_RESP_REG_ROAMING NET_REG_STATE_ROAMING
#define AT_CGREG_RESP_REG_EMERGENCY NET_REG_STATE_EMERGENCY
/* Access technology indicators */
#define AT_CGREG_RESP_GSM NET_ACCESS_GSM /* GSM */
#define AT_CGREG_RESP_COMPACT NET_ACCESS_COMPACT /* GSM Compact */
#define AT_CGREG_RESP_UTRAN NET_ACCESS_UTRAN /* UTRAN */
#define AT_CGREG_RESP_EGPRS NET_ACCESS_EGPRS /* GSM w/EGPRS */
#define AT_CGREG_RESP_HSDPA NET_ACCESS_HSDPA /* UTRAN w/HSDPA */
#define AT_CGREG_RESP_HSUPA NET_ACCESS_HSUPA /* UTRAN w/HSUPA */
#define AT_CGREG_RESP_HSDUPA NET_ACCESS_HSDUPA /* w/HSDPA and HSUPA */
/* Optional parameter bitmask */
//#define AT_CGREG_RESP_N_MASK AT_COMMAND_PARAM1
#define AT_CGREG_RESP_LAC_MASK AT_COMMAND_PARAM3
#define AT_CGREG_RESP_CI_MASK AT_COMMAND_PARAM4
#define AT_CGREG_RESP_ACT_MASK AT_COMMAND_PARAM5
#define AT_CGREG_RESP_RAC_MASK AT_COMMAND_PARAM6
/* CGREG AT command response type */
typedef struct {
int n;
int stat;
#define AT_CGREG_RESP_LAC_SIZE 4
char lac[AT_CGREG_RESP_LAC_SIZE+1];
#define AT_CGREG_RESP_CI_SIZE 8
char ci[AT_CGREG_RESP_CI_SIZE+1];
int AcT;
#define AT_CGREG_RESP_RAC_SIZE 2
char rac[AT_CGREG_RESP_RAC_SIZE+1];
} at_cgreg_resp_t;
/* CEREG: EPS network registration status
* --------------------------------------
* When <n>=1, returns +CEREG: <stat>, the Mobile Equipment's EPS services
* registration status in EUTRA Network.
* When <n>=2, returns +CEREG: <stat>[,<tac>,<ci>[,<AcT>]], the Mobile
* Equipment's EPS services registration status and location information in
* EUTRA Network.
* Read parameter command:
* +CEREG? returns +CEREG:<n>,<stat>[,<tac>,<ci>[,<AcT>]]
* <n> numeric parameter
* <stat> numeric parameter that indicates the EPS registration status
* <tac> string type; two byte tracking area code in hexadecimal format
* <ci> string type; four byte E-UTRAN cell ID in hexadecimal format
* <AcT> a numeric parameter that indicates the access technology of
* the serving cell
*/
/* Network registration status */
#define AT_CEREG_RESP_REG_OFF NET_REG_STATE_OFF
#define AT_CEREG_RESP_REG_HN NET_REG_STATE_HN
#define AT_CEREG_RESP_REG_ON NET_REG_STATE_ON
#define AT_CEREG_RESP_REG_DENIED NET_REG_STATE_DENIED
#define AT_CEREG_RESP_REG_UNKNOWN NET_REG_STATE_UNKNOWN
#define AT_CEREG_RESP_REG_ROAMING NET_REG_STATE_ROAMING
#define AT_CEREG_RESP_REG_EMERGENCY NET_REG_STATE_EMERGENCY
/* Access technology indicators */
#define AT_CEREG_RESP_EUTRAN NET_ACCESS_EUTRAN /* E-UTRAN */
/* Optional parameter bitmask */
//#define AT_CEREG_RESP_N_MASK AT_COMMAND_PARAM1
#define AT_CEREG_RESP_TAC_MASK AT_COMMAND_PARAM3
#define AT_CEREG_RESP_CI_MASK AT_COMMAND_PARAM4
#define AT_CEREG_RESP_ACT_MASK AT_COMMAND_PARAM5
/* CEREG AT command response type */
typedef struct {
int n;
int stat;
#define AT_CEREG_RESP_TAC_SIZE 4
char tac[AT_CEREG_RESP_TAC_SIZE+1];
#define AT_CEREG_RESP_CI_SIZE 8
char ci[AT_CEREG_RESP_CI_SIZE+1];
int AcT;
} at_cereg_resp_t;
/* CGDCONT: Define PDP Context
* ---------------------------
* Specifies PDP context parameter values for a PDP context identified by
* the (local) context identification parameter, <cid>.
* Read parameter command:
* +CGDCONT? returns +CGDCONT: <cid>,<PDP_type>,<APN>,<PDP_addr>,<d_comp>,
* <h_comp>[,<IPv4AddrAlloc>[,<emergency indication>[,<P-CSCF_
* discovery>[,<IM_CN_Signalling_Flag_Ind>]]]][<CR><LF>
* +CGDCONT: <cid>,<PDP_type>,<APN>,<PDP_addr>,<d_comp>,
* <h_comp>[,<IPv4AddrAlloc>[,<emergency indication>[,<P-CSCF_
* discovery>[,<IM_CN_Signalling_Flag_Ind>]]]]
* [...]]
* <cid> a numeric parameter which specifies a particular PDP
* context definition
* <PDP_type> type of packet data protocol ("IP", "IPV6", "IPV4V6")
* <APN> Access Point logical Name
* <PDP_addr> Mobile Equipment PDP address (not applicable to EPS)
* <d_comp> PDP data compression parameter
* <h_comp> PDP header compression parameter
* <IPv4AddrAlloc> IPv4 address allocation parameter
* <emergency indication> emergency bearer services support indication
* <P-CSCF_discovery> P-CSCF address discovery parameter
* <IM_CN_Signalling_Flag_Ind> IM CN subsystem-related signalling
* support indication
*/
/* Optional parameter bitmask */
#define AT_CGDCONT_RESP_IPV4ADDRALLOC_MASK AT_COMMAND_PARAM7
#define AT_CGDCONT_RESP_EMERGECY_INDICATION_MASK AT_COMMAND_PARAM8
#define AT_CGDCONT_RESP_P_CSCF_DISCOVERY_MASK AT_COMMAND_PARAM9
#define AT_CGDCONT_RESP_IM_CN_SIGNALLING_FLAG_IND_MASK AT_COMMAND_PARAM10
/* Structure of CGDCONT AT read parameter command */
typedef struct {
#define AT_CGDCONT_RESP_SIZE 8
int n_pdns; /* Number of defined PDN contexts in the lists */
int cid[AT_CGDCONT_RESP_SIZE]; /* List of PDN context identifiers */
int PDP_type[AT_CGDCONT_RESP_SIZE];
const char* APN[AT_CGDCONT_RESP_SIZE];
int d_comp[AT_CGDCONT_RESP_SIZE];
int h_comp[AT_CGDCONT_RESP_SIZE];
} at_cgdcont_get_t;
/* Structure of CGDCONT AT read parameter command */
typedef struct {
int n_cid; /* Range of supported PDN context identifiers */
} at_cgdcont_tst_t;
/* CGDCONT AT command response type */
typedef union {
at_cgdcont_tst_t tst;
at_cgdcont_get_t get;
} at_cgdcont_resp_t;
/* CGACT: PDP context activate or deactivate
* -----------------------------------------
* Read command returns the current activation states for all the defined
* PDP contexts.
* Read parameter command:
* +CGACT? returns +CGACT: <cid>,<state>[<CR><LF>+CGACT: <cid>,<state>[...]]
* <cid> a numeric parameter which specifies a particular PDP context
* definition
* <state> numeric parameter that indicates the state of PDP context
* activation
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGACT_MASK AT_RESPONSE_NO_PARAM
/* CGACT AT command response type */
typedef struct {
#define AT_CGACT_RESP_SIZE AT_CGDCONT_RESP_SIZE
int n_pdns; /* Number of defined PDN contexts in the lists */
int cid[AT_CGACT_RESP_SIZE]; /* List of PDN context identifiers */
int state[AT_CGACT_RESP_SIZE]; /* List of PDN context states */
} at_cgact_resp_t;
/* CGPADDR: Show PDP address(es)
* -----------------------------
* Returns a list of PDP addresses for the specified context identifiers.
* +CGPADDR= returns +CGPADDR: <cid>[,PDP_addr_1[,PDP_addr_2]][<CR><LF>
* +CGPADDR: <cid>[,PDP_addr_1[,PDP_addr_2]][...]]
* <cid> a numeric parameter which specifies a particular PDP
* context definition
* <PDP_addr_x> string that identifies the MT in the address space
* applicable to the PDP
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGPADDR_MASK AT_RESPONSE_NO_PARAM
/* CGPADDR AT command response type */
typedef struct {
#define AT_CGPADDR_RESP_SIZE AT_CGDCONT_RESP_SIZE
int n_pdns; /* Number of defined PDP addresses in the lists */
int cid[AT_CGPADDR_RESP_SIZE]; /* List of PDN context identifiers */
/* List of IPv4 addresses */
const char* PDP_addr_1[AT_CGPADDR_RESP_SIZE];
/* List of IPv6 addresses */
const char* PDP_addr_2[AT_CGPADDR_RESP_SIZE];
} at_cgpaddr_resp_t;
/* CGEV: Unsolicited result
* ------------------------
* Returns unsolicited result codes in case of certain events occurring
* in the Packet Domain MT or the network.
* +CGREV: <code> <cid>
* <code> unsolicited result code
* <cid> a numeric parameter which specifies a particular PDP
* context definition
*/
/* Optional parameter bitmask */
#define AT_RESPONSE_CGEV_MASK AT_RESPONSE_NO_PARAM
/* Unsolicited result codes */
#define AT_CGEV_RESP_NW_PDN_ACT (-1) /* Not applicable for LTE */
#define AT_CGEV_RESP_ME_PDN_ACT NET_PDN_MT_DEFAULT_ACT
#define AT_CGEV_RESP_NW_PDN_DEACT NET_PDN_NW_DEFAULT_DEACT
#define AT_CGEV_RESP_ME_PDN_DEACT NET_PDN_MT_DEFAULT_DEACT
#define AT_CGEV_RESP_NW_ACT NET_PDN_NW_DEDICATED_ACT
#define AT_CGEV_RESP_ME_ACT NET_PDN_MT_DEDICATED_ACT
#define AT_CGEV_RESP_NW_DEACT NET_PDN_NW_DEDICATED_DEACT
#define AT_CGEV_RESP_ME_DEACT NET_PDN_MT_DEDICATED_DEACT
/* CGEV unsolicited result type */
typedef struct {
int code;
int cid;
} at_cgev_resp_t;
/*
* ==========================================
* Global AT command response type definition
* ==========================================
*/
/* AT command response type */
typedef struct {
at_command_id_t id; /* AT command identifier */
at_command_type_t type; /* AT command type */
int mask; /* Optional parameter bitmask */
int cause_code; /* AT command error cause code */
union {
at_cgsn_resp_t cgsn;
at_cgmi_resp_t cgmi;
at_cgmm_resp_t cgmm;
at_cgmr_resp_t cgmr;
at_cimi_resp_t cimi;
at_cfun_resp_t cfun;
at_cpin_resp_t cpin;
at_csq_resp_t csq;
at_cesq_resp_t cesq;
at_clac_resp_t clac;
at_cmee_resp_t cmee;
at_cnum_resp_t cnum;
at_clck_resp_t clck;
at_cops_resp_t cops;
at_cgatt_resp_t cgatt;
at_creg_resp_t creg;
at_cgreg_resp_t cgreg;
at_cereg_resp_t cereg;
at_cgdcont_resp_t cgdcont;
at_cgact_resp_t cgact;
at_cgpaddr_resp_t cgpaddr;
at_cgev_resp_t cgev;
} response;
} at_response_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int at_response_encode(char* buffer, const at_response_t* at_response);
#endif /* __AT_RESPONSE_H__*/
@@ -0,0 +1,37 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../../..
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
LIBS = -lutil -lapi -lEMMmsg -lESMmsg -lies
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(USERAPIDIR)
LIBSAPI = $(LIBDIR)/$(LIBAPI).a $(LIBDIR)/$(LIBAPI).so
TST_OBJ = at_parser.o
TST_TARGET = at_parser
TARGETS = $(TST_TARGET)
all: $(TARGETS)
%.o: %.c Makefile
$(CC) $(CFLAGS) -c $< -o $@
$(TST_TARGET): $(TST_OBJ)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
$(RM) $(OBJS) $(TARGETS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
at_parser.o: $(USERAPIDIR)/at_command.h
at_parser.o: $(INCDIR)/commonDef.h $(INCDIR)/userDef.h
at_parser.o: $(INCDIR)/networkDef.h $(UTILDIR)/log.h
@@ -0,0 +1,130 @@
/*****************************************************************************
Source main.c
Version 0.1
Date 01/04/2012
Product NAS stack
Subsystem Application Programming Interface
Author Baris Demiray
Description Interacts with AT parser for testing purposes
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "at_command.h"
#include "nas_log.h"
int main() {
const char * sample_at_commands[] = {
"AT+CGSN\r", "AT+CGSN=?\r", "AT+CGMI\r", "AT+CGMI=?\r", "AT+CGMM\r",
"AT+CGMM=?\r", "AT+CIMI\r", "AT+CIMI=?\r", "AT+CFUN=1,1\r",
"AT+CFUN=2\r", "AT+CFUN?\r", "AT+CFUN=?\r", "AT+CPIN=1234\r",
"AT+CPIN=1234,4321\r", "AT+CPIN?\r", "AT+CPIN=?\r", "AT+CSQ\r",
"AT+CSQ=?\r", "AT+COPS=1,1,EURECOM\r", "AT+COPS=2,3\r", "AT+COPS=5\r",
"AT+COPS?\r", "AT+COPS=?\r", "AT+CGREG=1\r", "AT+CGREG?\r",
"AT+CGREG=?\r", "AT+CGDCONT=1\r", "AT+CGDCONT?\r", "AT+CGDCONT=?\r",
"AT+CGACT=1\r", "AT+CGACT?\r", "AT+CGACT=?\r", "AT+CGMR\r",
"AT+CGMR=?\r", "AT+CESQ\r", "AT+CESQ=?\r", "AT+CMEE=2\r",
"AT+CMEE?\r", "AT+CMEE=?\r", "AT+CLCK=SC,2\r", "AT+CLCK=?\r",
"AT+CREG=1\r", "AT+CREG?\r", "AT+CREG=?\r",
"AT+CEREG=1\r", "AT+CEREG?\r", "AT+CEREG=?\r",
"AT+CGATT=1\r", "AT+CGATT?\r", "AT+CGATT=?\r",
"AT\r", "null"
};
const char * sample_faulty_at_commands[] = {
"AT+CGSN=3,4\r", "AT+CGSN=??\r", "AT+CGMI=1,b\r", "AT+CGMI==\r",
"AT+CGMM?\r", "AT+CGMM==n\r", "AT+CIMI=4\r", "AT+CIMI=?t\r",
"AT+CFUN=n1,1\r", "AT+CFUN??\r", "AT+CFUN=a?\r", "AT+CPIN=1fd4\r",
"AT+CPIN=1sd+,432\r", "AT+CPIN?4\r", "AT+CPIN=?,?\r", "AT+CSQ=AT\r",
"AT+CSQ=q\r",
"AT+COPS=123121123123123123,EURECOMEURECOMEURECOMEURECOM\r",
"AT+COPS=2asd3,33ads1\r", "AT+COPS.=5\r", "AT+COPS?/r\\r",
"AT+COPS=?\n\r\r", "AT+CGREG=da1243\42r", "AT+CGREG.?\r",
"AT+CGREG1=?\r", "AT+CGDCONT=d31\r", "AT+CGDCONTxc?\\crca",
"AT+CGDCONcTc=c?\r", "AT+CGA12C3T=11\123r", "AT+CGACT';;.,?\r",
"AT+CGACT=?]\\;e23\r", "\r\r\r", "AT+COP\r", "null"
};
at_command_t at_command;
unsigned int at_command_index;
//log_init(0x2f);
/* Parse valid AT commands */
at_command_index = 0;
while (strncmp(sample_at_commands[at_command_index], "null", 4) != 0) {
if (at_command_decode(sample_at_commands[at_command_index],
strlen(sample_at_commands[at_command_index]),
&at_command) > 0)
{
printf("INFO: Fine, parser interpreted valid command %s\n",
sample_at_commands[at_command_index]);
} else {
printf("ERROR: Parser rejected valid command %s\n",
sample_at_commands[at_command_index]);
}
at_command_index++;
}
/* Parse invalid AT commands */
at_command_index = 0;
while (strncmp(sample_faulty_at_commands[at_command_index], "null", 4) != 0)
{
if (at_command_decode(sample_faulty_at_commands[at_command_index],
strlen(sample_faulty_at_commands[at_command_index]),
&at_command) > 0)
{
printf("ERROR: Parser interpreted invalid command %s\n",
sample_faulty_at_commands[at_command_index]);
} else {
printf("INFO: Fine, parser rejected the command %s\n",
sample_faulty_at_commands[at_command_index]);
}
at_command_index++;
}
/*
* Provide a console to the user
*/
int bytes_read;
size_t input_size = 100;
char *input;
printf("Note 1: Carriage return will be appended to every command by default\n");
printf("Note 2: Enter 'quit' to exit\n");
printf("AT Command> ");
input = (char *)malloc(input_size + 1);
bytes_read = getline(&input, &input_size, stdin);
while (strncmp(input, "quit", 4) != 0)
{
if (bytes_read == -1) {
puts("Cannot read user input!\n");
}
else {
input[bytes_read - 1] = '\r';
if (at_command_decode(input, bytes_read, &at_command) > 0)
printf("INFO: Parser interpreted command %s\n", input);
else
printf("ERROR: Parser rejected command %s\n", input);
}
printf("\nAT Command> ");
memset(input, 0x00, input_size);
bytes_read = getline(&input, &input_size, stdin);
}
free(input);
printf("Exiting...\n");
return 0;
}
@@ -0,0 +1,2 @@
AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
quit
@@ -0,0 +1,59 @@
ATE0Q0V1
ATE0Q0V1
ATS0=0
AT+CMEE=1
AT+CREG=2
AT+CGREG=1
AT+CCWA=1
AT+CMOD=0
AT+CSSN=0,1
AT+COLP=0
AT+CSCS="HEX"
AT+CUSD=1
AT+CGEREP=1,0
AT+CMGF=0
AT+CFUN?
AT+CPIN?
AT+CSMS=1
AT+CNMI=1,2,2,1,0
AT+CFUN=0
AT+CFUN=1
AT+CPIN?
AT+CSMS=1
AT+CNMI=1,2,2,1,0
AT+CGSN
AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT+CGREG?
AT+CREG?
AT+COPS?
AT+CLCC
AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT+CGREG?
AT+CREG?
AT+COPS?
AT+COPS=0
AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT+CGREG?
AT+CREG?
AT+COPS?
AT+CIMI
AT+CRSM=192,12258,0,0,15
AT+CRSM=192,28480,0,0,15
AT+CRSM=192,28617,0,0,15
AT+CRSM=192,28589,0,0,15
AT+CRSM=192,28618,0,0,15
AT+CRSM=192,28433,0,0,15
AT+CRSM=192,28619,0,0,15
AT+CRSM=192,28435,0,0,15
AT+CRSM=192,28486,0,0,15
AT+CRSM=192,28621,0,0,15
AT+CRSM=192,28613,0,0,15
AT+CRSM=192,28472,0,0,15
AT+CRSM=192,28438,0,0,15
AT+CRSM=192,28437,0,0,15
AT+CPIN?
AT+CRSM=192,28439,0,0,15
AT+CRSM=192,28436,0,0,15
AT+CRSM=192,28440,0,0,15
AT+CSQ
quit
@@ -0,0 +1,90 @@
INFO: Fine, parser interpreted valid command AT+CGSN
INFO: Fine, parser interpreted valid command AT+CGSN=?
INFO: Fine, parser interpreted valid command AT+CGMI
INFO: Fine, parser interpreted valid command AT+CGMI=?
INFO: Fine, parser interpreted valid command AT+CGMM
INFO: Fine, parser interpreted valid command AT+CGMM=?
INFO: Fine, parser interpreted valid command AT+CIMI
INFO: Fine, parser interpreted valid command AT+CIMI=?
INFO: Fine, parser interpreted valid command AT+CFUN=1,1
INFO: Fine, parser interpreted valid command AT+CFUN=2
INFO: Fine, parser interpreted valid command AT+CFUN?
INFO: Fine, parser interpreted valid command AT+CFUN=?
INFO: Fine, parser interpreted valid command AT+CPIN=1234
INFO: Fine, parser interpreted valid command AT+CPIN=1234,4321
INFO: Fine, parser interpreted valid command AT+CPIN?
INFO: Fine, parser interpreted valid command AT+CPIN=?
INFO: Fine, parser interpreted valid command AT+CSQ
INFO: Fine, parser interpreted valid command AT+CSQ=?
INFO: Fine, parser interpreted valid command AT+COPS=1,1,EURECOM
INFO: Fine, parser interpreted valid command AT+COPS=2,3
INFO: Fine, parser interpreted valid command AT+COPS=5
INFO: Fine, parser interpreted valid command AT+COPS?
INFO: Fine, parser interpreted valid command AT+COPS=?
INFO: Fine, parser interpreted valid command AT+CGREG=1
INFO: Fine, parser interpreted valid command AT+CGREG?
INFO: Fine, parser interpreted valid command AT+CGREG=?
INFO: Fine, parser interpreted valid command AT+CGDCONT=1
INFO: Fine, parser interpreted valid command AT+CGDCONT?
INFO: Fine, parser interpreted valid command AT+CGDCONT=?
INFO: Fine, parser interpreted valid command AT+CGACT=1
INFO: Fine, parser interpreted valid command AT+CGACT?
INFO: Fine, parser interpreted valid command AT+CGACT=?
INFO: Fine, parser interpreted valid command AT+CGMR
INFO: Fine, parser interpreted valid command AT+CGMR=?
INFO: Fine, parser interpreted valid command AT+CESQ
INFO: Fine, parser interpreted valid command AT+CESQ=?
INFO: Fine, parser interpreted valid command AT+CMEE=2
INFO: Fine, parser interpreted valid command AT+CMEE?
INFO: Fine, parser interpreted valid command AT+CMEE=?
INFO: Fine, parser interpreted valid command AT+CLCK=SC,2
INFO: Fine, parser interpreted valid command AT+CLCK=?
INFO: Fine, parser interpreted valid command AT+CREG=1
INFO: Fine, parser interpreted valid command AT+CREG?
INFO: Fine, parser interpreted valid command AT+CREG=?
INFO: Fine, parser interpreted valid command AT+CEREG=1
INFO: Fine, parser interpreted valid command AT+CEREG?
INFO: Fine, parser interpreted valid command AT+CEREG=?
INFO: Fine, parser interpreted valid command AT+CGATT=1
INFO: Fine, parser interpreted valid command AT+CGATT?
INFO: Fine, parser interpreted valid command AT+CGATT=?
INFO: Fine, parser interpreted valid command AT
INFO: Fine, parser rejected the command AT+CGSN=3,4
INFO: Fine, parser rejected the command AT+CGSN=??
INFO: Fine, parser rejected the command AT+CGMI=1,b
INFO: Fine, parser rejected the command AT+CGMI==
INFO: Fine, parser rejected the command AT+CGMM?
INFO: Fine, parser rejected the command AT+CGMM==n
INFO: Fine, parser rejected the command AT+CIMI=4
INFO: Fine, parser rejected the command AT+CIMI=?t
INFO: Fine, parser rejected the command AT+CFUN=n1,1
INFO: Fine, parser rejected the command AT+CFUN??
INFO: Fine, parser rejected the command AT+CFUN=a?
INFO: Fine, parser rejected the command AT+CPIN=1fd4
INFO: Fine, parser rejected the command AT+CPIN=1sd+,432
INFO: Fine, parser rejected the command AT+CPIN?4
INFO: Fine, parser rejected the command AT+CPIN=?,?
INFO: Fine, parser rejected the command AT+CSQ=AT
INFO: Fine, parser rejected the command AT+CSQ=q
INFO: Fine, parser rejected the command AT+COPS=123121123123123123,EURECOMEURECOMEURECOMEURECOM
INFO: Fine, parser rejected the command AT+COPS=2asd3,33ads1
INFO: Fine, parser rejected the command AT+COPS.=5
INFO: Fine, parser rejected the command AT+COPS?/r\r
INFO: Fine, parser rejected the command AT+COPS=?
␍
INFO: Fine, parser rejected the command AT+CGREG=da1243"r
INFO: Fine, parser rejected the command AT+CGREG.?
INFO: Fine, parser rejected the command AT+CGREG1=?
INFO: Fine, parser rejected the command AT+CGDCONT=d31
INFO: Fine, parser rejected the command AT+CGDCONTxc?\crca
INFO: Fine, parser rejected the command AT+CGDCONcTc=c?
INFO: Fine, parser rejected the command AT+CGA12C3T=11Sr
INFO: Fine, parser rejected the command AT+CGACT';;.,?
INFO: Fine, parser rejected the command AT+CGACT=?]\;e23
INFO: Fine, parser rejected the command ␍␍
INFO: Fine, parser rejected the command AT+COP
Note 1: Carriage return will be appended to every command by default
Note 2: Enter 'quit' to exit
AT Command> INFO: Parser interpreted command AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT Command> Exiting...
@@ -0,0 +1,204 @@
INFO: Fine, parser interpreted valid command AT+CGSN
INFO: Fine, parser interpreted valid command AT+CGSN=?
INFO: Fine, parser interpreted valid command AT+CGMI
INFO: Fine, parser interpreted valid command AT+CGMI=?
INFO: Fine, parser interpreted valid command AT+CGMM
INFO: Fine, parser interpreted valid command AT+CGMM=?
INFO: Fine, parser interpreted valid command AT+CIMI
INFO: Fine, parser interpreted valid command AT+CIMI=?
INFO: Fine, parser interpreted valid command AT+CFUN=1,1
INFO: Fine, parser interpreted valid command AT+CFUN=2
INFO: Fine, parser interpreted valid command AT+CFUN?
INFO: Fine, parser interpreted valid command AT+CFUN=?
INFO: Fine, parser interpreted valid command AT+CPIN=1234
INFO: Fine, parser interpreted valid command AT+CPIN=1234,4321
INFO: Fine, parser interpreted valid command AT+CPIN?
INFO: Fine, parser interpreted valid command AT+CPIN=?
INFO: Fine, parser interpreted valid command AT+CSQ
INFO: Fine, parser interpreted valid command AT+CSQ=?
INFO: Fine, parser interpreted valid command AT+COPS=1,1,EURECOM
INFO: Fine, parser interpreted valid command AT+COPS=2,3
INFO: Fine, parser interpreted valid command AT+COPS=5
INFO: Fine, parser interpreted valid command AT+COPS?
INFO: Fine, parser interpreted valid command AT+COPS=?
INFO: Fine, parser interpreted valid command AT+CGREG=1
INFO: Fine, parser interpreted valid command AT+CGREG?
INFO: Fine, parser interpreted valid command AT+CGREG=?
INFO: Fine, parser interpreted valid command AT+CGDCONT=1
INFO: Fine, parser interpreted valid command AT+CGDCONT?
INFO: Fine, parser interpreted valid command AT+CGDCONT=?
INFO: Fine, parser interpreted valid command AT+CGACT=1
INFO: Fine, parser interpreted valid command AT+CGACT?
INFO: Fine, parser interpreted valid command AT+CGACT=?
INFO: Fine, parser interpreted valid command AT+CGMR
INFO: Fine, parser interpreted valid command AT+CGMR=?
INFO: Fine, parser interpreted valid command AT+CESQ
INFO: Fine, parser interpreted valid command AT+CESQ=?
INFO: Fine, parser interpreted valid command AT+CMEE=2
INFO: Fine, parser interpreted valid command AT+CMEE?
INFO: Fine, parser interpreted valid command AT+CMEE=?
INFO: Fine, parser interpreted valid command AT+CLCK=SC,2
INFO: Fine, parser interpreted valid command AT+CLCK=?
INFO: Fine, parser interpreted valid command AT+CREG=1
INFO: Fine, parser interpreted valid command AT+CREG?
INFO: Fine, parser interpreted valid command AT+CREG=?
INFO: Fine, parser interpreted valid command AT+CEREG=1
INFO: Fine, parser interpreted valid command AT+CEREG?
INFO: Fine, parser interpreted valid command AT+CEREG=?
INFO: Fine, parser interpreted valid command AT+CGATT=1
INFO: Fine, parser interpreted valid command AT+CGATT?
INFO: Fine, parser interpreted valid command AT+CGATT=?
INFO: Fine, parser interpreted valid command AT
INFO: Fine, parser rejected the command AT+CGSN=3,4
INFO: Fine, parser rejected the command AT+CGSN=??
INFO: Fine, parser rejected the command AT+CGMI=1,b
INFO: Fine, parser rejected the command AT+CGMI==
INFO: Fine, parser rejected the command AT+CGMM?
INFO: Fine, parser rejected the command AT+CGMM==n
INFO: Fine, parser rejected the command AT+CIMI=4
INFO: Fine, parser rejected the command AT+CIMI=?t
INFO: Fine, parser rejected the command AT+CFUN=n1,1
INFO: Fine, parser rejected the command AT+CFUN??
INFO: Fine, parser rejected the command AT+CFUN=a?
INFO: Fine, parser rejected the command AT+CPIN=1fd4
INFO: Fine, parser rejected the command AT+CPIN=1sd+,432
INFO: Fine, parser rejected the command AT+CPIN?4
INFO: Fine, parser rejected the command AT+CPIN=?,?
INFO: Fine, parser rejected the command AT+CSQ=AT
INFO: Fine, parser rejected the command AT+CSQ=q
INFO: Fine, parser rejected the command AT+COPS=123121123123123123,EURECOMEURECOMEURECOMEURECOM
INFO: Fine, parser rejected the command AT+COPS=2asd3,33ads1
INFO: Fine, parser rejected the command AT+COPS.=5
INFO: Fine, parser rejected the command AT+COPS?/r\r
INFO: Fine, parser rejected the command AT+COPS=?
␍
INFO: Fine, parser rejected the command AT+CGREG=da1243"r
INFO: Fine, parser rejected the command AT+CGREG.?
INFO: Fine, parser rejected the command AT+CGREG1=?
INFO: Fine, parser rejected the command AT+CGDCONT=d31
INFO: Fine, parser rejected the command AT+CGDCONTxc?\crca
INFO: Fine, parser rejected the command AT+CGDCONcTc=c?
INFO: Fine, parser rejected the command AT+CGA12C3T=11Sr
INFO: Fine, parser rejected the command AT+CGACT';;.,?
INFO: Fine, parser rejected the command AT+CGACT=?]\;e23
INFO: Fine, parser rejected the command ␍␍
INFO: Fine, parser rejected the command AT+COP
Note 1: Carriage return will be appended to every command by default
Note 2: Enter 'quit' to exit
AT Command> INFO: Parser interpreted command ATE0Q0V1
AT Command> INFO: Parser interpreted command ATE0Q0V1
AT Command> ERROR: Parser rejected command ATS0=0
AT Command> INFO: Parser interpreted command AT+CMEE=1
AT Command> INFO: Parser interpreted command AT+CREG=2
AT Command> INFO: Parser interpreted command AT+CGREG=1
AT Command> ERROR: Parser rejected command AT+CCWA=1
AT Command> ERROR: Parser rejected command AT+CMOD=0
AT Command> ERROR: Parser rejected command AT+CSSN=0,1
AT Command> ERROR: Parser rejected command AT+COLP=0
AT Command> ERROR: Parser rejected command AT+CSCS="HEX"
AT Command> ERROR: Parser rejected command AT+CUSD=1
AT Command> ERROR: Parser rejected command AT+CGEREP=1,0
AT Command> ERROR: Parser rejected command AT+CMGF=0
AT Command> INFO: Parser interpreted command AT+CFUN?
AT Command> INFO: Parser interpreted command AT+CPIN?
AT Command> ERROR: Parser rejected command AT+CSMS=1
AT Command> ERROR: Parser rejected command AT+CNMI=1,2,2,1,0
AT Command> INFO: Parser interpreted command AT+CFUN=0
AT Command> INFO: Parser interpreted command AT+CFUN=1
AT Command> INFO: Parser interpreted command AT+CPIN?
AT Command> ERROR: Parser rejected command AT+CSMS=1
AT Command> ERROR: Parser rejected command AT+CNMI=1,2,2,1,0
AT Command> INFO: Parser interpreted command AT+CGSN
AT Command> INFO: Parser interpreted command AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT Command> INFO: Parser interpreted command AT+CGREG?
AT Command> INFO: Parser interpreted command AT+CREG?
AT Command> INFO: Parser interpreted command AT+COPS?
AT Command> ERROR: Parser rejected command AT+CLCC
AT Command> INFO: Parser interpreted command AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT Command> INFO: Parser interpreted command AT+CGREG?
AT Command> INFO: Parser interpreted command AT+CREG?
AT Command> INFO: Parser interpreted command AT+COPS?
AT Command> INFO: Parser interpreted command AT+COPS=0
AT Command> INFO: Parser interpreted command AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?
AT Command> INFO: Parser interpreted command AT+CGREG?
AT Command> INFO: Parser interpreted command AT+CREG?
AT Command> INFO: Parser interpreted command AT+COPS?
AT Command> INFO: Parser interpreted command AT+CIMI
AT Command> ERROR: Parser rejected command AT+CRSM=192,12258,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28480,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28617,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28589,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28618,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28433,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28619,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28435,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28486,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28621,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28613,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28472,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28438,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28437,0,0,15
AT Command> INFO: Parser interpreted command AT+CPIN?
AT Command> ERROR: Parser rejected command AT+CRSM=192,28439,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28436,0,0,15
AT Command> ERROR: Parser rejected command AT+CRSM=192,28440,0,0,15
AT Command> INFO: Parser interpreted command AT+CSQ
AT Command> Exiting...
@@ -0,0 +1,23 @@
Fully implemented:
AT Command> INFO: Parser interpreted command AT+CGSN
AT Command> INFO: Parser interpreted command AT+CGMM
AT Command> INFO: Parser interpreted command AT+CGMI
AT Command> INFO: Parser interpreted command AT+CPIN?
AT Command> INFO: Parser interpreted command ATE0Q0V1+CMEE=1
AT Command> INFO: Parser interpreted command AT+CFUN?
AT Command> INFO: Parser interpreted command AT+CFUN=1
AT Command> INFO: Parser interpreted command AT+CIMI
AT Command> INFO: Parser interpreted command AT+COPS?
AT Command> ERROR: Parser rejected command AT+CREG
AT Command> INFO: Parser interpreted command AT+CGACT=1,1
AT Command> INFO: Parser interpreted command AT+CGDCONT?
Not implemented:
AT Command> ERROR: Parser rejected command AT+CNUM
AT Command> ERROR: Parser rejected command AT+CRSM
AT Command> ERROR: Parser rejected command AT+CGMR
AT Command> ERROR: Parser rejected command AT+CESQ
AT Command> ERROR: Parser rejected command AT+CNTI
AT Command> ERROR: Parser rejected command AT!BAND?
AT Command> ERROR: Parser rejected command AT+PACSP?
@@ -0,0 +1,799 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source user_api.c
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer running in the UE
to send/receive message to/from the user application layer
*****************************************************************************/
#ifdef NAS_UE
#include "user_api.h"
#include "nas_log.h"
#include "socket.h"
#include "device.h"
#include "at_command.h"
#include "at_response.h"
#include "at_error.h"
#include "user_indication.h"
#include <string.h> // strerror, memset
#include <netdb.h> // gai_strerror
#include <errno.h> // errno
#include <stdio.h> // sprintf
#include <unistd.h> // gethostname
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/*
* Asynchronous notification procedure handlers
*/
static int _user_api_registration_handler(unsigned char id, const void* data, size_t size);
static int _user_api_location_handler(unsigned char id, const void* data, size_t size);
static int _user_api_network_handler(unsigned char id, const void* data, size_t size);
static int _user_api_pdn_connection_handler(unsigned char id, const void* data, size_t size);
static int _user_api_send(at_response_t* data);
/* -------------------
* Connection endpoint
* -------------------
* The connection endpoint is used to send/receive data to/from the
* user application layer. Its definition depends on the underlaying
* mechanism chosen to communicate (network socket, I/O terminal device).
* A connection endpoint is handled using an identifier, and functions
* used to retreive the file descriptor actually allocated by the system,
* to receive data, to send data, and to perform clean up when connection
* is shut down.
* Only one single end to end connection with the user is managed at a
* time.
*/
static struct {
/* Connection endpoint reference */
void* endpoint;
/* Connection endpoint handlers */
void* (*open) (int, const char*, const char*);
int (*getfd)(const void*);
ssize_t (*recv) (void*, char*, size_t);
ssize_t (*send) (const void*, const char*, size_t);
void (*close)(void*);
} _user_api_id;
#define USER_API_OPEN(a, b, c) _user_api_id.open(a, b, c)
#define USER_API_GETFD() _user_api_id.getfd(_user_api_id.endpoint)
#define USER_API_RECV(a, b) _user_api_id.recv(_user_api_id.endpoint, a, b)
#define USER_API_SEND(a, b) _user_api_id.send(_user_api_id.endpoint, a, b)
#define USER_API_CLOSE() _user_api_id.close(_user_api_id.endpoint)
/*
* The buffer used to receive data from the user application layer
*/
#define USER_API_RECV_BUFFER_SIZE 4096
static char _user_api_recv_buffer[USER_API_RECV_BUFFER_SIZE];
/*
* The buffer used to send data to the user application layer
*/
#define USER_API_SEND_BUFFER_SIZE USER_API_RECV_BUFFER_SIZE
static char _user_api_send_buffer[USER_API_SEND_BUFFER_SIZE];
/*
* The decoded data received from the user application layer
*/
static struct {
int n_cmd; /* number of user data to be processed */
#define USER_DATA_MAX 10
at_command_t cmd[USER_DATA_MAX]; /* user data to be processed */
} _user_data = {};
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: user_api_initialize() **
** **
** Description: Initializes the user API from which the NAS layer **
** will send/receive messages to/from the user application **
** layer **
** **
** Inputs: host: The name of the host from which the user **
** application layer will connect **
** port: The local port number **
** Others: None **
** **
** Outputs: Return: RETURNerror, RETURNok **
** Others: _user_api_id **
** **
***************************************************************************/
int user_api_initialize(const char* host, const char* port,
const char* devname, const char* devparams)
{
LOG_FUNC_IN;
gethostname(_user_api_send_buffer, USER_API_SEND_BUFFER_SIZE);
if (devname != NULL) {
/* Initialize device handlers */
_user_api_id.open = device_open;
_user_api_id.getfd = device_get_fd;
_user_api_id.recv = device_read;
_user_api_id.send = device_write;
_user_api_id.close = device_close;
/* Initialize communication channel */
_user_api_id.endpoint = USER_API_OPEN(DEVICE, devname, devparams);
if (_user_api_id.endpoint == NULL) {
LOG_TRACE(ERROR, "USR-API - Failed to open connection endpoint, "
"%s", strerror(errno));
LOG_FUNC_RETURN (RETURNerror);
}
LOG_TRACE(INFO, "USR-API - User's communication device %d is OPENED "
"on %s/%s", user_api_get_fd(), _user_api_send_buffer, devname);
}
else {
/* Initialize network socket handlers */
_user_api_id.open = socket_udp_open;
_user_api_id.getfd = socket_get_fd;
_user_api_id.recv = socket_recv;
_user_api_id.send = socket_send;
_user_api_id.close = socket_close;
/* Initialize communication channel */
_user_api_id.endpoint = USER_API_OPEN(SOCKET_SERVER, host, port);
if (_user_api_id.endpoint == NULL) {
const char* error = ( (errno < 0) ?
gai_strerror(errno) : strerror(errno) );
LOG_TRACE(ERROR, "USR-API - Failed to open connection endpoint, "
"%s", error);
LOG_FUNC_RETURN (RETURNerror);
}
LOG_TRACE(INFO, "USR-API - User's UDP socket %d is BOUND to %s/%s",
user_api_get_fd(), _user_api_send_buffer, port);
}
/* Register the asynchronous notification handlers */
if (user_ind_register(USER_IND_REG, 0, _user_api_registration_handler) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - "
"Failed to register registration notification");
}
else if (user_ind_register(USER_IND_LOC, 0, _user_api_location_handler) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - "
"Failed to register location notification");
}
else if (user_ind_register(USER_IND_PLMN, 0, _user_api_network_handler) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - "
"Failed to register network notification");
}
else if (user_ind_register(USER_IND_PLMN, 0, NULL) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - Failed to enable network notification");
}
else if (user_ind_register(USER_IND_PDN, 0, _user_api_pdn_connection_handler) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - "
"Failed to register PDN connection notification");
}
else if (user_ind_register(USER_IND_PDN, AT_CGACT, NULL) != RETURNok) {
LOG_TRACE(WARNING, "USR-API - "
"Failed to enable PDN connection notification");
}
else {
LOG_TRACE(INFO, "USR-API - "
"Notification handlers successfully registered");
}
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: user_api_get_fd() **
** **
** Description: Get the file descriptor of the connection endpoint used **
** to send/receive messages to/from the user application **
** layer **
** **
** Inputs: None **
** Others: _user_api_id **
** **
** Outputs: Return: The file descriptor of the connection end- **
** point used by the user application layer **
** Others: None **
** **
***************************************************************************/
int user_api_get_fd(void)
{
LOG_FUNC_IN;
LOG_FUNC_RETURN (USER_API_GETFD());
}
/****************************************************************************
** **
** Name: user_api_get_data() **
** **
** Description: Get a generic pointer to the user data structure at the **
** given index. Casting to the proper type is necessary **
** before its usage. **
** **
** Inputs: index: Index of the user data structure to get **
** Others: _user_data **
** **
** Outputs: Return: A generic pointer to the user data **
** structure **
** Others: None **
** **
***************************************************************************/
const void* user_api_get_data(int index)
{
LOG_FUNC_IN;
if (index < _user_data.n_cmd) {
LOG_FUNC_RETURN ((void*)(&_user_data.cmd[index]));
}
LOG_FUNC_RETURN (NULL);
}
/****************************************************************************
** **
** Name: user_api_read_data() **
** **
** Description: Read data received from the user application layer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** from which data have been received **
** Others: _user_api_id **
** **
** Outputs: Return: The number of bytes read when success; **
** RETURNerror Otherwise **
** Others: _user_api_recv_buffer, _user_api_id **
** **
***************************************************************************/
int user_api_read_data(int fd)
{
LOG_FUNC_IN;
int rbytes;
/* Sanity check */
int sfd = user_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd);
LOG_FUNC_RETURN (RETURNerror);
}
memset(_user_api_recv_buffer, 0, USER_API_RECV_BUFFER_SIZE);
/* Receive data from the user application layer */
rbytes = USER_API_RECV(_user_api_recv_buffer, USER_API_RECV_BUFFER_SIZE);
if (rbytes == RETURNerror) {
LOG_TRACE(ERROR, "USR-API - recv() failed, %s", strerror(errno));
LOG_FUNC_RETURN (RETURNerror);
}
else if (rbytes == 0) {
//LOG_TRACE(WARNING, "USR-API - A signal was caught");
}
else {
LOG_TRACE(INFO, "USR-API - %d bytes received "
"from the user application layer", rbytes);
LOG_DUMP(_user_api_recv_buffer, rbytes);
}
LOG_FUNC_RETURN (rbytes);
}
/****************************************************************************
** **
** Name: user_api_send_data() **
** **
** Description: Send data to the user application layer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** to which data have to be sent **
** length: Number of bytes to send **
** Others: _user_api_send_buffer, _user_api_id **
** **
** Outputs: Return: The number of bytes sent when success; **
** RETURNerror Otherwise **
** Others: None **
** **
***************************************************************************/
static int _user_api_send_data(int length)
{
int sbytes = USER_API_SEND(_user_api_send_buffer, length);
if (sbytes == RETURNerror) {
LOG_TRACE(ERROR, "USR-API - send() failed, %s", strerror(errno));
return RETURNerror;
}
else if (sbytes == 0) {
LOG_TRACE(WARNING, "USR-API - A signal was caught");
}
else {
LOG_TRACE(INFO, "USR-API - %d bytes sent "
"to the user application layer", sbytes);
LOG_DUMP(_user_api_send_buffer, sbytes);
}
return sbytes;
}
int user_api_send_data(int fd, int length)
{
LOG_FUNC_IN;
/* Sanity check */
int sfd = user_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd);
LOG_FUNC_RETURN (RETURNerror);
}
/* Send data to the user application layer */
int sbytes = 0;
if (length > 0) {
sbytes = _user_api_send_data(length);
}
LOG_FUNC_RETURN (sbytes);
}
/****************************************************************************
** **
** Name: user_api_close() **
** **
** Description: Close the user API from which the NAS layer sent/received **
** messages to/from the user application layer **
** **
** Inputs: fd: File descriptor of the connection endpoint **
** allocated by the system to communicate **
** with the user application layer **
** Others: None **
** **
** Outputs: Return: None **
** Others: _user_api_id **
** **
***************************************************************************/
void user_api_close(int fd)
{
LOG_FUNC_IN;
/* Sanity check */
int sfd = user_api_get_fd();
if (fd != sfd) {
LOG_TRACE(ERROR, "USR-API - Endpoint %d is not the one created for communication with the user application layer (%d)", fd, sfd);
LOG_FUNC_OUT;
return;
}
/* Cleanup the connection endpoint */
USER_API_CLOSE();
_user_api_id.endpoint = NULL;
LOG_FUNC_OUT;
}
/****************************************************************************
** **
** Name: user_api_decode_data() **
** **
** Description: Parses the message received from the user application **
** (mainly AT commands) and fills the user data structure. **
** Returns an AT syntax error code to the user application **
** layer when the AT command failed to be decoded. **
** **
** Inputs: length: Number of bytes to decode **
** Others: _user_api_recv_buffer **
** **
** Outputs: Return: The number of AT commands succeessfully **
** decoded **
** Others: _user_api_send_buffer, _user_data **
** **
***************************************************************************/
int user_api_decode_data(int length)
{
LOG_FUNC_IN;
/* Parse the AT command line */
LOG_TRACE(INFO, "USR-API - Decode user data: %s", _user_api_recv_buffer);
_user_data.n_cmd = at_command_decode(_user_api_recv_buffer, length,
_user_data.cmd);
if (_user_data.n_cmd > 0) {
/* AT command data received from the user application layer
* has been successfully decoded */
LOG_TRACE(INFO, "USR-API - %d AT command%s ha%s been successfully "
"decoded", _user_data.n_cmd,
(_user_data.n_cmd > 1) ? "s" : "",
(_user_data.n_cmd > 1) ? "ve" : "s");
}
else
{
int bytes;
/* Failed to decode AT command data received from the user
* application layer; Return syntax error code message */
LOG_TRACE(ERROR, "USR-API - Syntax error: Failed to decode "
"AT command data %s", _user_api_recv_buffer);
/* Encode the syntax error code message */
bytes = at_error_encode(_user_api_send_buffer, AT_ERROR_SYNTAX,
AT_ERROR_OPERATION_NOT_SUPPORTED);
/* Send the syntax error code message */
(void) _user_api_send_data(bytes);
}
LOG_FUNC_RETURN (_user_data.n_cmd);
}
/****************************************************************************
** **
** Name: user_api_encode_data() **
** **
** Description: Encodes AT command response message **
** **
** Inputs data: Generic pointer to the data to encode **
** success_code: Indicates whether success code has to be **
** displayed or not (covers the case where **
** more than one AT command is executed in **
** the same user command line). **
** Others: None **
** **
** Outputs: Return: The number of characters that have been **
** successfully encoded; **
** RETURNerror otherwise. **
** Others: _user_api_send_buffer **
** **
***************************************************************************/
int user_api_encode_data(const void* data, int success_code)
{
LOG_FUNC_IN;
const at_response_t* user_data = (at_response_t*)(data);
int bytes;
/* Encode AT command error message */
if (user_data->cause_code != AT_ERROR_SUCCESS)
{
bytes = at_error_encode(_user_api_send_buffer, AT_ERROR_CME,
user_data->cause_code);
}
/* Encode AT command response message */
else
{
bytes = at_response_encode(_user_api_send_buffer, user_data);
/* Add success result code */
if ( (success_code) && (bytes != RETURNerror) ) {
bytes += at_error_encode(&_user_api_send_buffer[bytes],
AT_ERROR_OK, 0);
}
}
if (bytes != RETURNerror) {
LOG_TRACE(INFO, "USR-API - %d bytes encoded", bytes);
}
else {
LOG_TRACE(ERROR, "USR-API - Syntax error: Failed to encode AT "
"response data (%d)", user_data->id);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: user_api_callback() **
** **
** Description: Notifies the user application that asynchronous notifica- **
** tion has been received from the EPS Mobility Management **
** sublayer. **
** **
** Inputs: stat: Network registration status **
** tac: Location/Tracking Area Code **
** ci: Indentifier of the serving cell **
** AcT: Access Technology supported by the cell **
** data: Data string to display to the user **
** size: Size of the notification data (only used **
** to display string information to the user **
** application) **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT,
const char* data, size_t size)
{
LOG_FUNC_IN;
int rc = RETURNok;
if (size > 1) {
/*
* The list of available operators present in the network has to be
* displayed to the user application
*/
rc = user_ind_notify(USER_IND_PLMN, (void*)data, size);
}
else {
user_indication_t ind;
ind.notification.reg.status = stat;
if (size > 0) {
/* The UE's network registration status has changed */
rc = user_ind_notify(USER_IND_REG, (void*)&ind, 0);
}
if (rc != RETURNerror) {
/* The UE's location area has changed or,
* the UE's network registration status has changed and
* only location information notification is enabled */
ind.notification.loc.tac = tac;
ind.notification.loc.ci = ci;
ind.notification.loc.AcT = AcT;
rc = user_ind_notify(USER_IND_LOC, (void*)&ind, 0);
}
}
if (rc != RETURNerror) {
LOG_FUNC_RETURN (RETURNok);
}
LOG_FUNC_RETURN (rc);
}
/****************************************************************************
** **
** Name: user_api_esm_callback() **
** **
** Description: Notifies the user application that asynchronous notifica- **
** tion has been received from the EPS Session Management **
** sublayer. **
** **
** Inputs: cid: PDN connection identifier **
** state: PDN connection status **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int user_api_esm_callback(int cid, network_pdn_state_t state)
{
LOG_FUNC_IN;
int rc = RETURNok;
user_indication_t ind;
ind.notification.pdn.cid = cid;
ind.notification.pdn.status = state;
/* The status of the specified PDN connection has changed */
rc = user_ind_notify(USER_IND_PDN, (void*)&ind, 0);
LOG_FUNC_RETURN (rc);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _user_api_send() **
** **
** Description: Encodes and sends data to the user application layer **
** **
** Inputs: data: The data to send **
** Others: _user_api_send_buffer, _user_api_id **
** **
** Outputs: Return: The number of bytes sent when success; **
** RETURNerror Otherwise **
** Others: None **
** **
***************************************************************************/
static int _user_api_send(at_response_t* data)
{
LOG_FUNC_IN;
/* Encode AT command response message */
int bytes = at_response_encode(_user_api_send_buffer, data);
/* Send the AT command response message to the user application */
if (bytes != RETURNerror) {
bytes = _user_api_send_data(bytes);
}
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _user_api_registration_handler() **
** **
** Description: Procedure executed upon receiving registration notifica- **
** tion whenever there is a change in the UE's network re- **
** gistration status in GERAN/UTRAN/E-UTRAN. **
** The network registration data are then displayed to the **
** user. **
** **
** Inputs: id: Network registration AT command identifier **
** data: Generic pointer to the registration data **
** size: Not used **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes actually sent to the **
** user application **
** Others: None **
** **
***************************************************************************/
static int _user_api_registration_handler(unsigned char id, const void* data,
size_t size)
{
LOG_FUNC_IN;
/* Get registration notification data */
user_ind_reg_t* reg = (user_ind_reg_t*)data;
/* Setup AT command response message for AT+CEREG? read command */
at_response_t at_response;
at_response.id = id; // may be +CREG, +CGREG, +CEREG
at_response.type = AT_COMMAND_GET;
at_response.mask = AT_RESPONSE_NO_PARAM;
at_response.response.cereg.n = AT_CEREG_ON;
at_response.response.cereg.stat = reg->status;
/* Encode and send the AT command response message to the user */
int bytes = _user_api_send(&at_response);
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _user_api_location_handler() **
** **
** Description: Procedure executed upon receiving location notification **
** whenever there is a change in the network serving cell **
** in GERAN/UTRAN/E-UTRAN. **
** The location data are then displayed to the user. **
** **
** Inputs: id: Network registration AT command identifier **
** data: Generic pointer to the registration data **
** size: Not used **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes actually sent to the **
** user application **
** Others: None **
** **
***************************************************************************/
static int _user_api_location_handler(unsigned char id, const void* data,
size_t size)
{
LOG_FUNC_IN;
/* Get location notification data */
user_ind_loc_t* loc = (user_ind_loc_t*)data;
/* Setup AT command response message for AT+CEREG? read command */
at_response_t at_response;
at_response.id = id; // may be +CREG, +CGREG, +CEREG
at_response.type = AT_COMMAND_GET;
at_response.mask = (AT_CEREG_RESP_TAC_MASK | AT_CEREG_RESP_CI_MASK);
at_response.response.cereg.n = AT_CEREG_BOTH;
at_response.response.cereg.stat = loc->status;
sprintf(at_response.response.cereg.tac, "%.4x", loc->tac); // two byte
sprintf(at_response.response.cereg.ci, "%.8x", loc->ci); // four byte
if (at_response.response.cereg.AcT != NET_ACCESS_UNAVAILABLE) {
at_response.response.cereg.AcT = loc->AcT;
at_response.mask |= AT_CEREG_RESP_ACT_MASK;
}
/* Encode and send the AT command response message to the user */
int bytes = _user_api_send(&at_response);
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _user_api_network_handler() **
** **
** Description: Procedure executed whenever the list of operators present **
** in the network has to be displayed to the user. **
** **
** Inputs: id: Not used **
** data: Generic pointer to the list of operators **
** size: The size of the data to display **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes actually sent to the **
** user application **
** Others: None **
** **
***************************************************************************/
static int _user_api_network_handler(unsigned char id, const void* data,
size_t size)
{
LOG_FUNC_IN;
/* Setup AT command response message for AT+COPS=? test command */
at_response_t at_response;
at_response.id = AT_COPS;
at_response.type = AT_COMMAND_TST;
at_response.response.cops.tst.data = (char*)data;
at_response.response.cops.tst.size = size;
/* Encode and send the AT command response message to the user */
int bytes = _user_api_send(&at_response);
LOG_FUNC_RETURN (bytes);
}
/****************************************************************************
** **
** Name: _user_api_pdn_connection_handler() **
** **
** Description: Procedure executed upon receiving PDN connection notifi- **
** cation whenever the user or the network has activated or **
** desactivated a PDN connection. **
** The PDN connection data are then displayed to the user. **
** **
** Inputs: id: Not used **
** data: Generic pointer to the PDN connection data **
** size: Not used **
** Others: None **
** **
** Outputs: None **
** Return: The number of bytes actually sent to the **
** user application **
** Others: None **
** **
***************************************************************************/
static int _user_api_pdn_connection_handler(unsigned char id, const void* data,
size_t size)
{
LOG_FUNC_IN;
/* Get PDN connection notification data */
user_ind_pdn_t* pdn = (user_ind_pdn_t*)data;
/* Setup AT command unsolicited result response message for +CGEV */
at_response_t at_response;
at_response.id = AT_CGEV;
at_response.type = AT_COMMAND_GET;
at_response.mask = AT_RESPONSE_CGEV_MASK;
at_response.response.cgev.cid = pdn->cid;
at_response.response.cgev.code = pdn->status;
/* Encode and send the AT command response message to the user */
int bytes = _user_api_send(&at_response);
LOG_FUNC_RETURN (bytes);
}
#endif // NAS_UE
@@ -0,0 +1,58 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source user_api.h
Version 0.1
Date 2012/02/28
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer running in the UE
to send/receive message to/from the user application layer
*****************************************************************************/
#ifndef __USER_API_H__
#define __USER_API_H__
#include "commonDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int user_api_initialize(const char* host, const char* port, const char* devname, const char* devparams);
int user_api_emm_callback(Stat_t stat, tac_t tac, ci_t ci, AcT_t AcT, const char* data, size_t size);
int user_api_esm_callback(int cid, network_pdn_state_t state);
int user_api_get_fd(void);
const void* user_api_get_data(int index);
int user_api_read_data(int fd);
int user_api_send_data(int fd, int length);
void user_api_close(int fd);
int user_api_decode_data(int length);
int user_api_encode_data(const void* data, int add_success_code);
#endif /* __USER_API_H__ */
@@ -0,0 +1,156 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source user_indication.c
Version 0.1
Date 2012/10/25
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines functions which allow the user application to register
procedures to be executed upon receiving asynchronous notifi-
cation.
*****************************************************************************/
#include "user_indication.h"
#include "nas_log.h"
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/* Notification handler */
static struct {
unsigned char id;
unsigned char mask;
user_ind_callback_t callback[USER_IND_MAX];
} _user_ind_handler = {};
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: user_ind_register() **
** **
** Description: Register the specified procedure to be executed upon **
** receiving the given asynchronous notification **
** **
** Inputs: ind: The notification type **
** id: The notification identifier **
** cb: The procedure to register **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _user_ind_handler **
** **
***************************************************************************/
int user_ind_register(user_ind_t ind, unsigned char id, user_ind_callback_t cb)
{
LOG_FUNC_IN;
int rc = RETURNerror;
if (ind < USER_IND_MAX) {
/* Register the notification callback */
if (cb != NULL) {
_user_ind_handler.callback[ind] = cb;
}
else {
_user_ind_handler.id = id;
_user_ind_handler.mask |= (1 << ind);
}
rc = RETURNok;
}
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: user_ind_deregister() **
** **
** Description: Prevent a registered procedure from being executed upon **
** receiving the given asynchronous notification **
** **
** Inputs: ind: The notification identifier **
** Others: None **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: _user_ind_handler **
** **
***************************************************************************/
int user_ind_deregister(user_ind_t ind)
{
LOG_FUNC_IN;
int rc = RETURNerror;
if (ind < USER_IND_MAX) {
_user_ind_handler.mask &= ~(1 << ind);
rc = RETURNok;
}
LOG_FUNC_RETURN(rc);
}
/****************************************************************************
** **
** Name: user_ind_notify() **
** **
** Description: Execute the procedure if registered for the received **
** notification identifier **
** **
** Inputs: ind: The notification identifier **
** data: Generic pointer to the notification data **
** size: The size parameter of the registered call- **
** back procedure to execute **
** Others: _user_ind_handler **
** **
** Outputs: None **
** Return: RETURNok, RETURNerror **
** Others: None **
** **
***************************************************************************/
int user_ind_notify(user_ind_t ind, const void* data, size_t size)
{
LOG_FUNC_IN;
int rc = RETURNerror;
if (ind < USER_IND_MAX) {
if (_user_ind_handler.mask & (1 << ind)) {
/* Execute the notification callback */
user_ind_callback_t notify = _user_ind_handler.callback[ind];
if (notify != NULL) {
rc = (*notify)(_user_ind_handler.id, data, size);
}
}
else {
/* Silently discard not registered notification */
rc = RETURNok;
}
}
LOG_FUNC_RETURN(rc);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
@@ -0,0 +1,103 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source user_indication.h
Version 0.1
Date 2012/10/25
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Defines functions which allow the user application to register
procedures to be executed upon receiving asynchronous notifi-
cation.
*****************************************************************************/
#ifndef __USER_IND_H__
#define __USER_IND_H__
#include "commonDef.h"
#include "networkDef.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/*
* Type of notification that may be asynchronously received by the user
*/
typedef enum {
USER_IND_REG = 0, /* Registration notification */
USER_IND_LOC, /* Location notification */
USER_IND_PLMN, /* Network notification */
USER_IND_PDN, /* PDN connection notification */
USER_IND_MAX
} user_ind_t;
/*
* Registration notification are received whenever there is a change in the
* UE's network registration status in GERAN/UTRAN/E-UTRAN
*/
typedef struct {
Stat_t status; /* network registration status */
} user_ind_reg_t;
/*
* Location notification are received whenever there is a change in the
* network serving cell in GERAN/UTRAN/E-UTRAN
*/
typedef struct {
Stat_t status; /* network registration status */
tac_t tac; /* Location/Tracking area code */
ci_t ci; /* GERAN/UTRAN/E-UTRAN cell ID */
AcT_t AcT; /* Supported Access Technology */
} user_ind_loc_t;
/*
* PDN connection notification are received whenever the user or the network
* has activated or desactivated a PDN connection
*/
typedef struct {
UInt8_t cid; /* PDN connection identifier */
network_pdn_state_t status; /* PDN connection status */
} user_ind_pdn_t;
/*
* Structure of asynchronous notification received by the user
*/
typedef struct {
union {
user_ind_reg_t reg; /* Registration notification */
user_ind_loc_t loc; /* Location notification */
user_ind_pdn_t pdn; /* PDN connection notification */
} notification;
} user_indication_t;
/*
* Type of procedure executed upon receiving registered notification
*/
typedef int (*user_ind_callback_t) (unsigned char, const void*, size_t);
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int user_ind_register(user_ind_t ind, unsigned char id, user_ind_callback_t cb);
int user_ind_deregister(user_ind_t ind);
int user_ind_notify(user_ind_t ind, const void* data, size_t size);
#endif /* __USER_IND_H__*/
@@ -0,0 +1,21 @@
ifndef PROJDIR
PROJDIR = $(PWD)/../../..
INCLUDES = -I. -I$(INCDIR) -I$(UTILDIR) -I$(IESDIR) -I$(EMMMSGDIR) -I$(ESMMSGDIR)
endif
include $(PROJDIR)/Makerules
include $(PROJDIR)/Makefile.inc
all: $(OBJS)
%.o: %.c Makefile
@echo Compiling $<
@$(CC) $(CFLAGS) -c $< -o $@
clean:
$(RM) $(OBJS) *.bak *~
depend:
makedepend -- ${CFLAGS} -- ${SRCS}
# DO NOT DELETE THIS LINE -- make depend depends on it.
@@ -0,0 +1,399 @@
/*-------------------------------------------------------------------
* Example algorithms f1, f1*, f2, f3, f4, f5, f5*
*-------------------------------------------------------------------
*
* A sample implementation of the example 3GPP authentication and
* key agreement functions f1, f1*, f2, f3, f4, f5 and f5*. This is
* a byte-oriented implementation of the functions, and of the block
* cipher kernel function Rijndael.
*
* This has been coded for clarity, not necessarily for efficiency.
*
* The functions f2, f3, f4 and f5 share the same inputs and have
* been coded together as a single function. f1, f1* and f5* are
* all coded separately.
*
*-----------------------------------------------------------------*/
#include "aka_functions.h"
/*--------- Operator Variant Algorithm Configuration Field --------*/
/*------- Insert your value of OP here -------*/
u8 OP[16] = {0x63, 0xbf, 0xa5, 0x0e, 0xe6, 0x52, 0x33, 0x65,
0xff, 0x14, 0xc1, 0xf4, 0x5f, 0x88, 0x73, 0x7d};
/*------- Insert your value of OP here -------*/
/*-------------------------------------------------------------------
* Algorithm f1
*-------------------------------------------------------------------
*
* Computes network authentication code MAC-A from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_a[8] )
{
u8 op_c[16];
u8 temp[16];
u8 in1[16];
u8 out1[16];
u8 rijndaelInput[16];
u8 i;
RijndaelKeySchedule( k );
ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++)
{
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++)
{
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= op_c[i];
for (i=0; i<8; i++)
mac_a[i] = out1[i];
return;
} /* end of function f1 */
/*-------------------------------------------------------------------
* Algorithms f2-f5
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns response RES,
* confidentiality key CK, integrity key IK and anonymity key AK.
*
*-----------------------------------------------------------------*/
void f2345 ( u8 k[16], u8 rand[16],
u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6] )
{
u8 op_c[16];
u8 temp[16];
u8 out[16];
u8 rijndaelInput[16];
u8 i;
RijndaelKeySchedule( k );
ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT2: XOR OPc and TEMP, *
* rotate by r2=0, and XOR on the constant c2 (which *
* is all zeroes except that the last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[i] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 1;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<8; i++)
res[i] = out[i+8];
for (i=0; i<6; i++)
ak[i] = out[i];
/* To obtain output block OUT3: XOR OPc and TEMP, *
* rotate by r3=32, and XOR on the constant c3 (which *
* is all zeroes except that the next to last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+12) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 2;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<16; i++)
ck[i] = out[i];
/* To obtain output block OUT4: XOR OPc and TEMP, *
* rotate by r4=64, and XOR on the constant c4 (which *
* is all zeroes except that the 2nd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 4;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<16; i++)
ik[i] = out[i];
return;
} /* end of function f2345 */
/*-------------------------------------------------------------------
* Algorithm f1*
*-------------------------------------------------------------------
*
* Computes resynch authentication code MAC-S from key K, random
* challenge RAND, sequence number SQN and authentication management
* field AMF.
*
*-----------------------------------------------------------------*/
void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_s[8] )
{
u8 op_c[16];
u8 temp[16];
u8 in1[16];
u8 out1[16];
u8 rijndaelInput[16];
u8 i;
RijndaelKeySchedule( k );
ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
RijndaelEncrypt( rijndaelInput, temp );
for (i=0; i<6; i++)
{
in1[i] = sqn[i];
in1[i+8] = sqn[i];
}
for (i=0; i<2; i++)
{
in1[i+6] = amf[i];
in1[i+14] = amf[i];
}
/* XOR op_c and in1, rotate by r1=64, and XOR *
* on the constant c1 (which is all zeroes) */
for (i=0; i<16; i++)
rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
/* XOR on the value temp computed before */
for (i=0; i<16; i++)
rijndaelInput[i] ^= temp[i];
RijndaelEncrypt( rijndaelInput, out1 );
for (i=0; i<16; i++)
out1[i] ^= op_c[i];
for (i=0; i<8; i++)
mac_s[i] = out1[i+8];
return;
} /* end of function f1star */
/*-------------------------------------------------------------------
* Algorithm f5*
*-------------------------------------------------------------------
*
* Takes key K and random challenge RAND, and returns resynch
* anonymity key AK.
*
*-----------------------------------------------------------------*/
void f5star( u8 k[16], u8 rand[16],
u8 ak[6] )
{
u8 op_c[16];
u8 temp[16];
u8 out[16];
u8 rijndaelInput[16];
u8 i;
RijndaelKeySchedule( k );
ComputeOPc( op_c );
for (i=0; i<16; i++)
rijndaelInput[i] = rand[i] ^ op_c[i];
RijndaelEncrypt( rijndaelInput, temp );
/* To obtain output block OUT5: XOR OPc and TEMP, *
* rotate by r5=96, and XOR on the constant c5 (which *
* is all zeroes except that the 3rd from last bit is 1). */
for (i=0; i<16; i++)
rijndaelInput[(i+4) % 16] = temp[i] ^ op_c[i];
rijndaelInput[15] ^= 8;
RijndaelEncrypt( rijndaelInput, out );
for (i=0; i<16; i++)
out[i] ^= op_c[i];
for (i=0; i<6; i++)
ak[i] = out[i];
return;
} /* end of function f5star */
/*-------------------------------------------------------------------
* Function to compute OPc from OP and K. Assumes key schedule has
already been performed.
*-----------------------------------------------------------------*/
void ComputeOPc( u8 op_c[16] )
{
u8 i;
RijndaelEncrypt( OP, op_c );
for (i=0; i<16; i++)
op_c[i] ^= OP[i];
return;
} /* end of function ComputeOPc */
/*-------------------- Rijndael round subkeys ---------------------*/
u8 roundKeys[11][4][4];
/*--------------------- Rijndael S box table ----------------------*/
u8 S[256] = {
99,124,119,123,242,107,111,197, 48, 1,103, 43,254,215,171,118,
202,130,201,125,250, 89, 71,240,173,212,162,175,156,164,114,192,
183,253,147, 38, 54, 63,247,204, 52,165,229,241,113,216, 49, 21,
4,199, 35,195, 24,150, 5,154, 7, 18,128,226,235, 39,178,117,
9,131, 44, 26, 27,110, 90,160, 82, 59,214,179, 41,227, 47,132,
83,209, 0,237, 32,252,177, 91,106,203,190, 57, 74, 76, 88,207,
208,239,170,251, 67, 77, 51,133, 69,249, 2,127, 80, 60,159,168,
81,163, 64,143,146,157, 56,245,188,182,218, 33, 16,255,243,210,
205, 12, 19,236, 95,151, 68, 23,196,167,126, 61,100, 93, 25,115,
96,129, 79,220, 34, 42,144,136, 70,238,184, 20,222, 94, 11,219,
224, 50, 58, 10, 73, 6, 36, 92,194,211,172, 98,145,149,228,121,
231,200, 55,109,141,213, 78,169,108, 86,244,234,101,122,174, 8,
186,120, 37, 46, 28,166,180,198,232,221,116, 31, 75,189,139,138,
112, 62,181,102, 72, 3,246, 14, 97, 53, 87,185,134,193, 29,158,
225,248,152, 17,105,217,142,148,155, 30,135,233,206, 85, 40,223,
140,161,137, 13,191,230, 66,104, 65,153, 45, 15,176, 84,187, 22,
};
/*------- This array does the multiplication by x in GF(2^8) ------*/
u8 Xtime[256] = {
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
96, 98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,
128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,
160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,
192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,
224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,
27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5,
59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, 33, 39, 37,
91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69,
123,121,127,125,115,113,119,117,107,105,111,109, 99, 97,103,101,
155,153,159,157,147,145,151,149,139,137,143,141,131,129,135,133,
187,185,191,189,179,177,183,181,171,169,175,173,163,161,167,165,
219,217,223,221,211,209,215,213,203,201,207,205,195,193,199,197,
251,249,255,253,243,241,247,245,235,233,239,237,227,225,231,229
};
/*-------------------------------------------------------------------
* Rijndael key schedule function. Takes 16-byte key and creates
* all Rijndael's internal subkeys ready for encryption.
*-----------------------------------------------------------------*/
void RijndaelKeySchedule( u8 key[16] )
{
u8 roundConst;
int i, j;
/* first round key equals key */
for (i=0; i<16; i++)
roundKeys[0][i & 0x03][i>>2] = key[i];
roundConst = 1;
/* now calculate round keys */
for (i=1; i<11; i++)
{
roundKeys[i][0][0] = S[roundKeys[i-1][1][3]]
^ roundKeys[i-1][0][0] ^ roundConst;
roundKeys[i][1][0] = S[roundKeys[i-1][2][3]]
^ roundKeys[i-1][1][0];
roundKeys[i][2][0] = S[roundKeys[i-1][3][3]]
^ roundKeys[i-1][2][0];
roundKeys[i][3][0] = S[roundKeys[i-1][0][3]]
^ roundKeys[i-1][3][0];
for (j=0; j<4; j++)
{
roundKeys[i][j][1] = roundKeys[i-1][j][1] ^ roundKeys[i][j][0];
roundKeys[i][j][2] = roundKeys[i-1][j][2] ^ roundKeys[i][j][1];
roundKeys[i][j][3] = roundKeys[i-1][j][3] ^ roundKeys[i][j][2];
}
/* update round constant */
roundConst = Xtime[roundConst];
}
return;
} /* end of function RijndaelKeySchedule */
/* Round key addition function */
void KeyAdd(u8 state[4][4], u8 roundKeys[11][4][4], int round)
{
int i, j;
for (i=0; i<4; i++)
for (j=0; j<4; j++)
state[i][j] ^= roundKeys[round][i][j];
return;
}
/* Byte substitution transformation */
int ByteSub(u8 state[4][4])
{
int i, j;
for (i=0; i<4; i++)
for (j=0; j<4; j++)
state[i][j] = S[state[i][j]];
return 0;
}
/* Row shift transformation */
void ShiftRow(u8 state[4][4])
{
u8 temp;
/* left rotate row 1 by 1 */
temp = state[1][0];
state[1][0] = state[1][1];
state[1][1] = state[1][2];
state[1][2] = state[1][3];
state[1][3] = temp;
/* left rotate row 2 by 2 */
temp = state[2][0];
state[2][0] = state[2][2];
state[2][2] = temp;
temp = state[2][1];
state[2][1] = state[2][3];
state[2][3] = temp;
/* left rotate row 3 by 3 */
temp = state[3][0];
state[3][0] = state[3][3];
state[3][3] = state[3][2];
state[3][2] = state[3][1];
state[3][1] = temp;
return;
}
/* MixColumn transformation*/
void MixColumn(u8 state[4][4])
{
u8 temp, tmp, tmp0;
int i;
/* do one column at a time */
for (i=0; i<4;i++)
{
temp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
tmp0 = state[0][i];
/* Xtime array does multiply by x in GF2^8 */
tmp = Xtime[state[0][i] ^ state[1][i]];
state[0][i] ^= temp ^ tmp;
tmp = Xtime[state[1][i] ^ state[2][i]];
state[1][i] ^= temp ^ tmp;
tmp = Xtime[state[2][i] ^ state[3][i]];
state[2][i] ^= temp ^ tmp;
tmp = Xtime[state[3][i] ^ tmp0];
state[3][i] ^= temp ^ tmp;
}
return;
}
/*-------------------------------------------------------------------
* Rijndael encryption function. Takes 16-byte input and creates
* 16-byte output (using round keys already derived from 16-byte
* key).
*-----------------------------------------------------------------*/
void RijndaelEncrypt( u8 input[16], u8 output[16] )
{
u8 state[4][4];
int i, r;
/* initialise state array from input byte string */
for (i=0; i<16; i++)
state[i & 0x3][i>>2] = input[i];
/* add first round_key */
KeyAdd(state, roundKeys, 0);
/* do lots of full rounds */
for (r=1; r<=9; r++)
{
ByteSub(state);
ShiftRow(state);
MixColumn(state);
KeyAdd(state, roundKeys, r);
}
/* final round */
ByteSub(state);
ShiftRow(state);
KeyAdd(state, roundKeys, r);
/* produce output byte string from state array */
for (i=0; i<16; i++)
{
output[i] = state[i & 0x3][i>>2];
}
return;
} /* end of function RijndaelEncrypt */
@@ -0,0 +1,14 @@
typedef unsigned char u8;
/*--------------------------- prototypes --------------------------*/
void f1 ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_a[8] );
void f2345 ( u8 k[16], u8 rand[16],
u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6] );
void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
u8 mac_s[8] );
void f5star( u8 k[16], u8 rand[16],
u8 ak[6] );
void ComputeOPc( u8 op_c[16] );
void RijndaelKeySchedule( u8 key[16] );
void RijndaelEncrypt( u8 input[16], u8 output[16] );
@@ -0,0 +1,292 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source usim_api.h
Version 0.1
Date 2012/10/09
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer to read/write
data to/from the USIM application
*****************************************************************************/
#ifdef NAS_UE
#include "usim_api.h"
#include "nas_log.h"
#include "memory.h"
#include "aka_functions.h"
#include <string.h> // memcpy, memset
#include <stdlib.h> // malloc, free
/****************************************************************************/
/**************** 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 *******************/
/****************************************************************************/
/*
* The name of the file where are stored data of the USIM application
*/
#define USIM_API_NVRAM_FILENAME ".usim.nvram"
/*
* The name of the environment variable which defines the directory
* where the USIM application file is located
*/
#define USIM_API_NVRAM_DIRNAME "USIM_DIR"
/*
* Subscriber authentication security key
*/
#define USIM_API_K_SIZE 16
#define USIM_API_K_VALUE "8BAF473F2F8FD09487CCCBD7097C6862"
static UInt8_t _usim_api_k[USIM_API_K_SIZE];
/*
* List of last used Sequence Numbers SQN
*/
static struct {
/* Highest sequence number the USIM has ever accepted */
UInt32_t sqn_ms;
/* List of the last used sequence numbers */
#define USIM_API_SQN_LIST_SIZE 32
UInt8_t n_sqns;
UInt32_t sqn[USIM_API_SQN_LIST_SIZE];
} _usim_api_data;
static int _usim_api_check_sqn(UInt32_t seq, UInt8_t ind);
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
/****************************************************************************
** **
** Name: usim_api_read() **
** **
** Description: Reads data from the USIM application **
** **
** Inputs: None **
** Others: File where are stored USIM data **
** **
** Outputs: data: Pointer to the USIM application data **
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
int usim_api_read(usim_data_t* data)
{
LOG_FUNC_IN;
/* Get USIM application pathname */
char* path = memory_get_path(USIM_API_NVRAM_DIRNAME,
USIM_API_NVRAM_FILENAME);
if (path == NULL) {
LOG_TRACE(ERROR, "USIM-API - Failed to get USIM pathname");
LOG_FUNC_RETURN (RETURNerror);
}
/* Read USIM application data */
if (memory_read(path, data, sizeof(usim_data_t)) != RETURNok) {
LOG_TRACE(ERROR, "USIM-API - %s file is either not valid "
"or not present", path);
free(path);
LOG_FUNC_RETURN (RETURNerror);
}
/* initialize the subscriber authentication security key */
memcpy(_usim_api_k, USIM_API_K_VALUE, USIM_API_K_SIZE);
free(path);
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: usim_api_write() **
** **
** Description: Writes data to the USIM application **
** **
** Inputs: data: Pointer to the USIM application data **
** Others: None **
** **
** Outputs: None **
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
int usim_api_write(const usim_data_t* data)
{
LOG_FUNC_IN;
/* Get USIM application pathname */
char* path = memory_get_path(USIM_API_NVRAM_DIRNAME,
USIM_API_NVRAM_FILENAME);
if (path == NULL) {
LOG_TRACE(ERROR, "USIM-API - Failed to get USIM pathname");
LOG_FUNC_RETURN (RETURNerror);
}
/* Write USIM application data */
if (memory_write(path, data, sizeof(usim_data_t)) != RETURNok) {
LOG_TRACE(ERROR, "USIM-API - Unable to write USIM file %s", path);
free(path);
LOG_FUNC_RETURN (RETURNerror);
}
free(path);
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************
** **
** Name: usim_api_authenticate() **
** **
** Description: Performs mutual authentication of the USIM to the network,**
** checking whether authentication token AUTN can be accep- **
** ted. If so, returns an authentication response RES and **
** the ciphering and integrity keys. **
** In case of synch failure, returns a re-synchronization **
** token AUTS. **
** **
** 3GPP TS 31.102, section 7.1.1.1 **
** **
** Authentication and key generating function algorithms are **
** specified in 3GPP TS 35.206. **
** **
** Inputs: rand: Random challenge number **
** autn: Authentication token **
** AUTN = (SQN xor AK) || AMF || MAC **
** 48 16 64 bits **
** Others: Security key **
** **
** Outputs: auts: Re-synchronization token **
** res: Authentication response **
** ck: Cipherig key **
** ik: Integrity key **
**
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
int usim_api_authenticate(const OctetString* rand, const OctetString* autn,
OctetString* auts, OctetString* res,
OctetString* ck, OctetString* ik)
{
LOG_FUNC_IN;
int rc;
/* Compute the authentication response RES = f2K (RAND) */
/* Compute the cipher key CK = f3K (RAND) */
/* Compute the integrity key IK = f4K (RAND) */
/* Compute the anonymity key AK = f5K (RAND) */
#define USIM_API_AK_SIZE 6
u8 ak[USIM_API_AK_SIZE];
f2345(_usim_api_k, rand->value,
res->value, ck->value, ik->value, ak);
/* Retrieve the sequence number SQN = (SQN ⊕ AK) ⊕ AK */
#define USIM_API_SQN_SIZE USIM_API_AK_SIZE
u8 sqn[USIM_API_SQN_SIZE];
for (int i = 0; i < USIM_API_SQN_SIZE; i++) {
sqn[i] = rand->value[i] ^ ak[i];
}
/* Compute XMAC = f1K (SQN || RAND || AMF) */
#define USIM_API_XMAC_SIZE 8
u8 xmac[USIM_API_XMAC_SIZE];
f1(_usim_api_k, rand->value, sqn, &rand->value[USIM_API_SQN_SIZE], xmac);
/* Compare the XMAC with the MAC included in AUTN */
#if 0 // TODO !!! TO BE REMOVED
#define USIM_API_AMF_SIZE 2
if ( memcmp(xmac, &rand->value[USIM_API_SQN_SIZE + USIM_API_AMF_SIZE],
USIM_API_XMAC_SIZE) != 0 ) {
LOG_FUNC_RETURN (RETURNerror);
}
#endif // TODO !!! TO BE REMOVED
/* Verify that the received sequence number SQN is in the correct range */
rc = _usim_api_check_sqn(*(UInt32_t*)(sqn), sqn[USIM_API_SQN_SIZE - 1]);
if (rc != RETURNok) {
/* Synchronisation failure; compute the AUTS parameter */
/* Concealed value of the counter SQNms in the USIM:
* Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) */
f5star(_usim_api_k, rand->value, ak);
#define USIM_API_SQNMS_SIZE USIM_API_SQN_SIZE
u8 sqn_ms[USIM_API_SQNMS_SIZE];
memset(sqn_ms, 0, USIM_API_SQNMS_SIZE);
#define USIM_API_SQN_MS_SIZE 3
for (int i = 0; i < USIM_API_SQN_MS_SIZE; i++) {
sqn_ms[USIM_API_SQNMS_SIZE - i] =
((UInt8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQN_MS_SIZE - i];
}
u8 sqnms[USIM_API_SQNMS_SIZE];
for (int i = 0; i < USIM_API_SQNMS_SIZE; i++) {
sqnms[i] = sqn_ms[i] ^ ak[i];
}
/* Synchronisation message authentication code:
* MACS = f1*K(SQNMS || RAND || AMF) */
#define USIM_API_MACS_SIZE USIM_API_XMAC_SIZE
u8 macs[USIM_API_MACS_SIZE];
f1star(_usim_api_k, rand->value, sqn_ms,
&rand->value[USIM_API_SQN_SIZE], macs);
/* Synchronisation authentication token:
* AUTS = Conc(SQNMS) || MACS */
memcpy(&auts->value[0], sqnms, USIM_API_SQNMS_SIZE);
memcpy(&auts->value[USIM_API_SQNMS_SIZE], macs, USIM_API_MACS_SIZE);
}
LOG_FUNC_RETURN (RETURNok);
}
/****************************************************************************/
/********************* L O C A L F U N C T I O N S *********************/
/****************************************************************************/
/****************************************************************************
** **
** Name: _usim_api_check_sqn() **
** **
** Description: Verifies the freshness of sequence numbers to determine **
** whether the specified sequence number is in the correct **
** range and acceptabled by the USIM. **
** **
** 3GPP TS 31.102, Annex C.2 **
** **
** Inputs: seq: Sequence number value **
** ind: Index value **
** Others: None **
** **
** Outputs: None **
** Return: RETURNerror, RETURNok **
** Others: None **
** **
***************************************************************************/
static int _usim_api_check_sqn(UInt32_t seq, UInt8_t ind)
{
/* TODO */
return (RETURNok);
}
#endif // NAS_UE
@@ -0,0 +1,329 @@
/*****************************************************************************
Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom
Source usim_api.h
Version 0.1
Date 2012/10/09
Product NAS stack
Subsystem Application Programming Interface
Author Frederic Maurel
Description Implements the API used by the NAS layer to read/write
data to/from the USIM application
*****************************************************************************/
#ifndef __USIM_API_H__
#define __USIM_API_H__
#include "commonDef.h"
#include "networkDef.h"
#include "OctetString.h"
/****************************************************************************/
/********************* G L O B A L C O N S T A N T S *******************/
/****************************************************************************/
/****************************************************************************/
/************************ G L O B A L T Y P E S ************************/
/****************************************************************************/
/*
* USIM TLV parameter structure
* ----------------------------
*/
#define USIM_TLV_T(SIZE) struct {UInt8_t type; UInt8_t length; Byte_t value[SIZE];}
/*
* Non Access Stratum Configuration
* --------------------------------
* TODO: To be encoded as BER-TLV
*/
typedef struct {
/* Determines the NAS signalling priority included in NAS
* messages */
#define USIM_NAS_SIGNALLING_PRIORITY_TAG 0x80U
USIM_TLV_T(1) NAS_SignallingPriority;
/* Indicates whether the "NMO I, Network Mode of Operation I"
* indication is applied by the UE */
#define USIM_NMO_I_BEHAVIOUR_TAG 0x81U
USIM_TLV_T(1) NMO_I_Behaviour;
/* Indicates whether attach with IMSI is performed when moving
* to a non-equivalent PLMN */
#define USIM_ATTACH_WITH_IMSI_TAG 0x82U
USIM_TLV_T(1) AttachWithImsi;
/* Minimum value in minutes for the timer T controlling the
* periodic search for higher prioritized PLMNs */
#define USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG 0x83U
USIM_TLV_T(1) MinimumPeriodicSearchTimer;
/* Indicates whether the extended access barring is applicable
* for the UE */
#define USIM_EXTENDED_ACCESS_BARRING_TAG 0x84U
USIM_TLV_T(1) ExtendedAccessBarring;
/* Indicates whether the timer T3245 and the related
* functionality is used by the UE */
#define USIM_TIMER_T3245_BEHAVIOUR_TAG 0x85U
USIM_TLV_T(1) Timer_T3245_Behaviour;
} usim_nasconfig_t;
/*
* Ciphering and Integrity Keys
* ----------------------------
*/
typedef struct {
/* Key set identifier */
#define USIM_KSI_MIN 0b000
#define USIM_KSI_MAX 0b110
#define USIM_KSI_NOT_AVAILABLE 0b111
Byte_t ksi;
/* Cyphering key */
#define USIM_CK_SIZE 16
Byte_t ck[USIM_CK_SIZE];
/* Integrity key */
#define USIM_IK_SIZE 16
Byte_t ik[USIM_IK_SIZE];
} usim_keys_t;
/*
* EPS NAS Security Context
* ------------------------
* TODO: To be encoded as BER-TLV
*/
typedef struct {
/* Length of all subsequent data */
#define USIM_EPS_NAS_SECURITY_CONTEXT_TAG 0xA0U
UInt8_t length;
/* Key set identifier KSI_ASME */
#define USIM_KSI_ASME_TAG 0x80U
USIM_TLV_T(1) KSIasme;
/* ASME key (K_ASME) */
#define USIM_K_ASME_TAG 0x81U
#define USIM_K_ASME_SIZE 32
USIM_TLV_T(USIM_K_ASME_SIZE) Kasme;
/* Uplink NAS count */
#define USIM_UL_NAS_COUNT_TAG 0x82U
#define USIM_UL_NAS_COUNT_SIZE 4
USIM_TLV_T(USIM_UL_NAS_COUNT_SIZE) ulNAScount;
/* Downlink NAS count */
#define USIM_DL_NAS_COUNT_TAG 0x83U
#define USIM_DL_NAS_COUNT_SIZE 4
USIM_TLV_T(USIM_DL_NAS_COUNT_SIZE) dlNAScount;
/* Identifiers of selected NAS integrity and encryption
* algorithms */
#define USIM_INT_ENC_ALGORITHMS_TAG 0x84U
#define USIM_INT_EIA0 0x00
#define USIM_INT_EIA1 0x01
#define USIM_INT_EIA2 0x02
#define USIM_INT_EIA3 0x03
#define USIM_INT_EIA4 0x04
#define USIM_INT_EIA5 0x05
#define USIM_INT_EIA6 0x06
#define USIM_INT_EIA7 0x07
#define USIM_ENC_EEA0 0x00
#define USIM_ENC_EEA1 0x10
#define USIM_ENC_EEA2 0x20
#define USIM_ENC_EEA3 0x30
#define USIM_ENC_EEA4 0x40
#define USIM_ENC_EEA5 0x50
#define USIM_ENC_EEA6 0x60
#define USIM_ENC_EEA7 0x70
USIM_TLV_T(1) algorithmID;
} usim_securityctx_t;
/*
* Subcriber's Number structure
* ----------------------------
*/
typedef struct {
Byte_t length; /* Length of BCD number/SSC contents */
msisdn_t number; /* Mobile subscriber dialing number */
Byte_t conf1_record_id; /* Configuration1 Record Identifier */
Byte_t ext1_record_id; /* Extension1 Record Identifier */
} usim_msisdn_t;
/*
* PLMN Network Name structure
* ---------------------------
*/
typedef struct {
/* PLMN Full Name */
#define USIM_PNN_FULLNAME_TAG 0x43U
#define USIM_PNN_FULLNAME_SIZE NET_FORMAT_LONG_SIZE
USIM_TLV_T(USIM_PNN_FULLNAME_SIZE) fullname;
/* PLMN Short Name */
#define USIM_PNN_SHORTNAME_TAG 0x45U
#define USIM_PNN_SHORTNAME_SIZE NET_FORMAT_SHORT_SIZE
USIM_TLV_T(USIM_PNN_SHORTNAME_SIZE) shortname;
} usim_pnn_t;
/*
* Operator PLMN List structure
* ----------------------------
*/
typedef struct {
/* Tracking Area Identity range */
plmn_t plmn;
tac_t start;
tac_t end;
/* PLMN Network Name Record Identifier */
UInt8_t record_id;
} usim_opl_t;
/*
* PLMN with Access Technology structure
* -------------------------------------
*/
typedef struct {
plmn_t plmn;
#define USIM_ACT_GSM 0x8000
#define USIM_ACT_COMPACT 0x4000
#define USIM_ACT_CDMA_HRPD 0x2000
#define USIM_ACT_CDMA_1xRTT 0x1000
#define USIM_ACT_UTRAN 0x0080
#define USIM_ACT_EUTRAN 0x0040
UInt16_t AcT;
} usim_plmn_act_t;
/*
* Location information structure
* ------------------------------
*/
typedef struct {
UInt32_t tmsi; /* Temporary Mobile Subscriber Identity */
lai_t lai; /* Location Area Identity */
Byte_t reserved; /* Reserved for future use */
#define USIM_LOCI_UPDATED 0x00
#define USIM_LOCI_NOT_UPDATED 0x01
#define USIM_LOCI_PLMN_NOT_ALLOWED 0x02
#define USIM_LOCI_LA_NOT_ALLOWED 0x03
Byte_t status; /* Location update status */
} usim_loci_t;
/*
* Packet Switched location information structure
* ----------------------------------------------
*/
typedef struct {
UInt32_t p_tmsi; /* Packet Temporary Mobile Subscriber Identity */
Byte_t signature[3]; /* P-TMSI signature value */
RAI_t rai; /* Routing Area Identity */
#define USIM_PSLOCI_UPDATED 0x00
#define USIM_PSLOCI_NOT_UPDATED 0x01
#define USIM_PSLOCI_PLMN_NOT_ALLOWED 0x02
#define USIM_PSLOCI_LA_NOT_ALLOWED 0x03
Byte_t status; /* Routing Area update status */
} usim_psloci_t;
/*
* EPS location information structure
* ----------------------------------
*/
typedef struct {
GUTI_t guti; /* Globally Unique Temporary UE Identity */
tai_t tai; /* Last visited registered Tracking Area Id */
#define USIM_EPSLOCI_UPDATED 0x00
#define USIM_EPSLOCI_NOT_UPDATED 0x01
#define USIM_EPSLOCI_ROAMING_NOT_ALLOWED 0x02
Byte_t status; /* EPS update status */
} usim_epsloci_t;
/*
* Administrative Data
* -------------------
* Defines information concerning the mode of operation according to the
* type of USIM, such as normal (to be used by PLMN subscribers for 3G
* operations), type approval (to allow specific use of the ME during
* type approval procedures of e.g. the radio equipment), cell testing
* (to allow testing of a cell before commercial use of this cell),
* manufacturer specific (to allow the ME manufacturer to perform specific
* proprietary auto-test in its ME during e.g. maintenance phases).
* It also provides an indication about how some ME features shall work
* during normal operation as well as information about the length of the
* MNC, which is part of the International Mobile Subscriber Identity (IMSI).
*/
typedef struct {
#define USIM_NORMAL_MODE 0x00U
#define USIM_TYPE_APPROVAL_MODE 0x80U
#define USIM_NORMAL_SPECIFIC_MODE 0x01U
#define USIM_TYPE_APPROVAL_SPECIFIC_MODE 0x81U
#define USIM_MAINTENANCE_MODE 0x02U
#define USIM_CELL_TEST_MODE 0x04U
Byte_t UE_Operation_Mode; /* Mode of operation for the UE */
UInt16_t Additional_Info; /* Additional information depending on
* the UE operation mode */
Byte_t MNC_Length; /* Number of digits used for extracting
* the MNC from the IMSI */
} usim_ad_t;
/*
*---------------------------------------------------------------------------
* Structure of the data handled by the USIM application
*---------------------------------------------------------------------------
*/
typedef struct {
/*
* Mandatory USIM configuration parameters
* ---------------------------------------
*/
imsi_t imsi; /* International Mobile Subscriber Identity */
usim_keys_t keys; /* Ciphering and Integrity Keys */
Byte_t hpplmn; /* Higher Priority PLMN search period */
#define USIM_FPLMN_MAX 4
plmn_t fplmn[USIM_FPLMN_MAX]; /* List of Forbidden PLMNs */
usim_loci_t loci; /* Location Information */
usim_psloci_t psloci; /* PS Location Information */
usim_ad_t ad; /* Administrative Data */
/*
* Optional USIM configuration parameters
* --------------------------------------
*/
/* EPS NAS security context */
usim_securityctx_t securityctx;
/* Subcriber's Number */
usim_msisdn_t msisdn;
/* PLMN Network Name */
#define USIM_PNN_MAX 8
usim_pnn_t pnn[USIM_PNN_MAX];
/* Operator PLMN List */
#define USIM_OPL_MAX USIM_PNN_MAX
usim_opl_t opl[USIM_OPL_MAX];
/* List of Equivalent HPLMNs */
#define USIM_EHPLMN_MAX 2
plmn_t ehplmn[USIM_EHPLMN_MAX];
/* Home PLMN Selector with Access Technology */
usim_plmn_act_t hplmn;
/* User controlled PLMN Selector with Access Technology */
#define USIM_PLMN_MAX 8
usim_plmn_act_t plmn[USIM_PLMN_MAX];
/* Operator controlled PLMN Selector with Access Technology */
#define USIM_OPLMN_MAX 8
usim_plmn_act_t oplmn[USIM_OPLMN_MAX];
/* EPS Location Information */
usim_epsloci_t epsloci;
/* Non-Access Stratum configuration */
usim_nasconfig_t nasconfig;
} usim_data_t;
/****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/
/****************************************************************************/
/****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/
int usim_api_read(usim_data_t* data);
int usim_api_write(const usim_data_t* data);
int usim_api_authenticate(const OctetString* rand, const OctetString* autn,
OctetString* auts, OctetString* res,
OctetString* ck, OctetString* ik);
#endif /* __USIM_API_H__*/