git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4566 818b1a75-f10b-46b9-bf7c-635c3b92a50f
271 lines
11 KiB
C
271 lines
11 KiB
C
/*******************************************************************************
|
|
|
|
Eurecom OpenAirInterface
|
|
Copyright(c) 1999 - 2013 Eurecom
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms and conditions of the GNU General Public License,
|
|
version 2, as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
The full GNU General Public License is included in this distribution in
|
|
the file called "COPYING".
|
|
|
|
Contact Information
|
|
Openair Admin: openair_admin@eurecom.fr
|
|
Openair Tech : openair_tech@eurecom.fr
|
|
Forums : http://forums.eurecom.fr/openairinterface
|
|
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
|
|
06410 Biot FRANCE
|
|
|
|
*******************************************************************************/
|
|
|
|
#include "assertions.h"
|
|
|
|
#ifndef CONVERSIONS_H_
|
|
#define CONVERSIONS_H_
|
|
|
|
/* Endianness conversions for 16 and 32 bits integers from host to network order */
|
|
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
|
# define hton_int32(x) \
|
|
(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | \
|
|
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
|
|
|
|
# define hton_int16(x) \
|
|
(((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)
|
|
|
|
# define ntoh_int32_buf(bUF) \
|
|
((*(bUF)) << 24) | ((*((bUF) + 1)) << 16) | ((*((bUF) + 2)) << 8) \
|
|
| (*((bUF) + 3))
|
|
#else
|
|
# define hton_int32(x) (x)
|
|
# define hton_int16(x) (x)
|
|
#endif
|
|
|
|
#define BUFFER_TO_INT8(buf, x) (x = ((buf)[0]))
|
|
|
|
#define INT8_TO_BUFFER(x, buf) ((buf)[0] = (x))
|
|
|
|
/* Convert an integer on 16 bits to the given bUFFER */
|
|
#define INT16_TO_BUFFER(x, buf) \
|
|
do { \
|
|
(buf)[0] = (x) >> 8; \
|
|
(buf)[1] = (x); \
|
|
} while(0)
|
|
|
|
/* Convert an array of char containing vALUE to x */
|
|
#define BUFFER_TO_INT16(buf, x) \
|
|
do { \
|
|
x = ((buf)[0] << 8) | \
|
|
((buf)[1]); \
|
|
} while(0)
|
|
|
|
/* Convert an integer on 32 bits to the given bUFFER */
|
|
#define INT32_TO_BUFFER(x, buf) \
|
|
do { \
|
|
(buf)[0] = (x) >> 24; \
|
|
(buf)[1] = (x) >> 16; \
|
|
(buf)[2] = (x) >> 8; \
|
|
(buf)[3] = (x); \
|
|
} while(0)
|
|
|
|
/* Convert an array of char containing vALUE to x */
|
|
#define BUFFER_TO_INT32(buf, x) \
|
|
do { \
|
|
x = ((buf)[0] << 24) | \
|
|
((buf)[1] << 16) | \
|
|
((buf)[2] << 8) | \
|
|
((buf)[3]); \
|
|
} while(0)
|
|
|
|
/* Convert an integer on 32 bits to an octet string from asn1c tool */
|
|
#define INT32_TO_OCTET_STRING(x, asn) \
|
|
do { \
|
|
(asn)->buf = calloc(4, sizeof(uint8_t)); \
|
|
INT32_TO_BUFFER(x, ((asn)->buf)); \
|
|
(asn)->size = 4; \
|
|
} while(0)
|
|
|
|
#define INT32_TO_BIT_STRING(x, asn) \
|
|
do { \
|
|
INT32_TO_OCTET_STRING(x, asn); \
|
|
(asn)->bits_unused = 0; \
|
|
} while(0)
|
|
|
|
#define INT16_TO_OCTET_STRING(x, asn) \
|
|
do { \
|
|
(asn)->buf = calloc(2, sizeof(uint8_t)); \
|
|
(asn)->size = 2; \
|
|
INT16_TO_BUFFER(x, (asn)->buf); \
|
|
} while(0)
|
|
|
|
#define INT8_TO_OCTET_STRING(x, asn) \
|
|
do { \
|
|
(asn)->buf = calloc(1, sizeof(uint8_t)); \
|
|
(asn)->size = 1; \
|
|
INT8_TO_BUFFER(x, (asn)->buf); \
|
|
} while(0)
|
|
|
|
#define MME_CODE_TO_OCTET_STRING INT8_TO_OCTET_STRING
|
|
#define M_TMSI_TO_OCTET_STRING INT32_TO_OCTET_STRING
|
|
#define MME_GID_TO_OCTET_STRING INT16_TO_OCTET_STRING
|
|
|
|
#define OCTET_STRING_TO_INT8(asn, x) \
|
|
do { \
|
|
DevCheck((asn)->size == 1, (asn)->size, 0, 0); \
|
|
BUFFER_TO_INT8((asn)->buf, x); \
|
|
} while(0)
|
|
|
|
#define OCTET_STRING_TO_INT16(asn, x) \
|
|
do { \
|
|
DevCheck((asn)->size == 2, (asn)->size, 0, 0); \
|
|
BUFFER_TO_INT16((asn)->buf, x); \
|
|
} while(0)
|
|
|
|
#define OCTET_STRING_TO_INT32(asn, x) \
|
|
do { \
|
|
DevCheck((asn)->size == 4, (asn)->size, 0, 0); \
|
|
BUFFER_TO_INT32((asn)->buf, x); \
|
|
} while(0)
|
|
|
|
#define BIT_STRING_TO_INT32(asn, x) \
|
|
do { \
|
|
DevCheck((asn)->bits_unused == 0, (asn)->bits_unused, 0, 0); \
|
|
OCTET_STRING_TO_INT32(asn, x); \
|
|
} while(0)
|
|
|
|
#define BIT_STRING_TO_CELL_IDENTITY(asn, x) \
|
|
do { \
|
|
DevCheck((asn)->bits_unused == 4, (asn)->bits_unused, 4, 0); \
|
|
x = ((asn)->buf[0] << 20) | ((asn)->buf[1] << 12) | \
|
|
((asn)->buf[2] << 4) | (asn)->buf[3]; \
|
|
} while(0)
|
|
|
|
#define MCC_HUNDREDS(vALUE) \
|
|
((vALUE) / 100)
|
|
/* When MNC is only composed of 2 digits, set the hundreds unit to 0xf */
|
|
#define MNC_HUNDREDS(vALUE) \
|
|
(((vALUE) / 100) == 0 ? 15 : (vALUE) / 100)
|
|
#define MCC_MNC_DECIMAL(vALUE) \
|
|
(((vALUE) / 10) % 10)
|
|
#define MCC_MNC_DIGIT(vALUE) \
|
|
((vALUE) % 10)
|
|
|
|
#define MCC_TO_BUFFER(mCC, bUFFER) \
|
|
do { \
|
|
DevAssert(bUFFER != NULL); \
|
|
(bUFFER)[0] = MCC_HUNDREDS(mCC); \
|
|
(bUFFER)[1] = MCC_MNC_DECIMAL(mCC); \
|
|
(bUFFER)[2] = MCC_MNC_DIGIT(mCC); \
|
|
} while(0)
|
|
|
|
#define MCC_MNC_TO_PLMNID(mCC, mNC, oCTETsTRING) \
|
|
do { \
|
|
(oCTETsTRING)->buf = calloc(3, sizeof(uint8_t)); \
|
|
(oCTETsTRING)->buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC); \
|
|
(oCTETsTRING)->buf[1] = (MNC_HUNDREDS(mNC) << 4) | MCC_MNC_DIGIT(mCC); \
|
|
(oCTETsTRING)->buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC); \
|
|
(oCTETsTRING)->size = 3; \
|
|
} while(0)
|
|
|
|
#define MCC_MNC_TO_TBCD(mCC, mNC, tBCDsTRING) \
|
|
do { \
|
|
char _buf[3]; \
|
|
_buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC); \
|
|
_buf[1] = (MNC_HUNDREDS(mNC) << 4) | MCC_MNC_DIGIT(mCC); \
|
|
_buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC); \
|
|
OCTET_STRING_fromBuf(tBCDsTRING, _buf, 3); \
|
|
} while(0)
|
|
|
|
#define TBCD_TO_MCC_MNC(tBCDsTRING, mCC, mNC) \
|
|
do { \
|
|
int mNC_hundred; \
|
|
DevAssert((tBCDsTRING)->size == 3); \
|
|
mNC_hundred = (((tBCDsTRING)->buf[1] & 0xf0) >> 4); \
|
|
if (mNC_hundred == 0xf) mNC_hundred = 0; \
|
|
mCC = (((((tBCDsTRING)->buf[0]) & 0xf0) >> 4) * 10) + \
|
|
((((tBCDsTRING)->buf[0]) & 0x0f) * 100) + \
|
|
(((tBCDsTRING)->buf[1]) & 0x0f); \
|
|
mNC = (mNC_hundred * 100) + \
|
|
((((tBCDsTRING)->buf[2]) & 0xf0) >> 4) + \
|
|
((((tBCDsTRING)->buf[2]) & 0x0f) * 10); \
|
|
} while(0)
|
|
|
|
#define TBCD_TO_PLMN_T(tBCDsTRING, pLMN) \
|
|
do { \
|
|
DevAssert((tBCDsTRING)->size == 3); \
|
|
(pLMN)->MCCdigit2 = (((tBCDsTRING)->buf[0] & 0xf0) >> 4); \
|
|
(pLMN)->MCCdigit3 = ((tBCDsTRING)->buf[0] & 0x0f); \
|
|
(pLMN)->MCCdigit1 = (tBCDsTRING)->buf[1] & 0x0f; \
|
|
(pLMN)->MNCdigit3 = (((tBCDsTRING)->buf[1] & 0xf0) >> 4) == 0xF \
|
|
? 0 : (((tBCDsTRING)->buf[1] & 0xf0) >> 4); \
|
|
(pLMN)->MNCdigit2 = (((tBCDsTRING)->buf[2] & 0xf0) >> 4); \
|
|
(pLMN)->MNCdigit1 = ((tBCDsTRING)->buf[2] & 0x0f); \
|
|
} while(0)
|
|
|
|
#define PLMN_T_TO_TBCD(pLMN, tBCDsTRING) \
|
|
do { \
|
|
tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit3; \
|
|
tBCDsTRING[1] = ((pLMN.MNCdigit1 == 0 ? 0xF : pLMN.MNCdigit1) << 4) \
|
|
| pLMN.MCCdigit1; \
|
|
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit3; \
|
|
} while(0)
|
|
|
|
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC) \
|
|
do { \
|
|
mCC = pLMN.MCCdigit3 * 100 + pLMN.MCCdigit2 * 10 + pLMN.MCCdigit1; \
|
|
mNC = (pLMN.MNCdigit3 == 0xF ? 0 : pLMN.MNCdigit3 * 100) \
|
|
+ pLMN.MNCdigit2 * 10 + pLMN.MNCdigit1; \
|
|
} while(0)
|
|
|
|
#define MACRO_ENB_ID_TO_BIT_STRING(mACRO, bITsTRING) \
|
|
do { \
|
|
(bITsTRING)->buf = calloc(3, sizeof(uint8_t)); \
|
|
(bITsTRING)->buf[0] = ((mACRO) >> 12); \
|
|
(bITsTRING)->buf[1] = (mACRO) >> 4; \
|
|
(bITsTRING)->buf[2] = ((mACRO) & 0x0f) << 4; \
|
|
(bITsTRING)->size = 3; \
|
|
(bITsTRING)->bits_unused = 4; \
|
|
} while(0)
|
|
|
|
#define MACRO_ENB_ID_TO_CELL_IDENTITY(mACRO, bITsTRING) \
|
|
do { \
|
|
(bITsTRING)->buf = calloc(4, sizeof(uint8_t)); \
|
|
(bITsTRING)->buf[0] = 0; \
|
|
(bITsTRING)->buf[1] = ((mACRO) >> 12); \
|
|
(bITsTRING)->buf[2] = (mACRO) >> 4; \
|
|
(bITsTRING)->buf[3] = ((mACRO) & 0x0f) << 4; \
|
|
(bITsTRING)->size = 4; \
|
|
(bITsTRING)->bits_unused = 4; \
|
|
} while(0)
|
|
|
|
/* Used to format an uint32_t containing an ipv4 address */
|
|
#define IPV4_ADDR "%u.%u.%u.%u"
|
|
#define IPV4_ADDR_FORMAT(aDDRESS) \
|
|
(uint8_t)((aDDRESS) & 0x000000ff), \
|
|
(uint8_t)(((aDDRESS) & 0x0000ff00) >> 8 ), \
|
|
(uint8_t)(((aDDRESS) & 0x00ff0000) >> 16), \
|
|
(uint8_t)(((aDDRESS) & 0xff000000) >> 24)
|
|
|
|
#define IPV4_ADDR_DISPLAY_8(aDDRESS) \
|
|
(aDDRESS)[0], (aDDRESS)[1], (aDDRESS)[2], (aDDRESS)[3]
|
|
|
|
#define TAC_TO_ASN1 INT16_TO_OCTET_STRING
|
|
#define GTP_TEID_TO_ASN1 INT32_TO_OCTET_STRING
|
|
#define OCTET_STRING_TO_TAC OCTET_STRING_TO_INT16
|
|
|
|
inline
|
|
void hexa_to_ascii(uint8_t *from, char *to, size_t length);
|
|
|
|
int ascii_to_hex(uint8_t *dst, const char *h);
|
|
|
|
#endif /* CONVERSIONS_H_ */
|