307 lines
13 KiB
C
307 lines
13 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
#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 IN_ADDR_TO_BUFFER(X,bUFF) INT32_TO_BUFFER((X).s_addr,(char*)bUFF)
|
|
|
|
#define IN6_ADDR_TO_BUFFER(X,bUFF) \
|
|
do { \
|
|
((uint8_t*)(bUFF))[0] = (X).s6_addr[0]; \
|
|
((uint8_t*)(bUFF))[1] = (X).s6_addr[1]; \
|
|
((uint8_t*)(bUFF))[2] = (X).s6_addr[2]; \
|
|
((uint8_t*)(bUFF))[3] = (X).s6_addr[3]; \
|
|
((uint8_t*)(bUFF))[4] = (X).s6_addr[4]; \
|
|
((uint8_t*)(bUFF))[5] = (X).s6_addr[5]; \
|
|
((uint8_t*)(bUFF))[6] = (X).s6_addr[6]; \
|
|
((uint8_t*)(bUFF))[7] = (X).s6_addr[7]; \
|
|
((uint8_t*)(bUFF))[8] = (X).s6_addr[8]; \
|
|
((uint8_t*)(bUFF))[9] = (X).s6_addr[9]; \
|
|
((uint8_t*)(bUFF))[10] = (X).s6_addr[10]; \
|
|
((uint8_t*)(bUFF))[11] = (X).s6_addr[11]; \
|
|
((uint8_t*)(bUFF))[12] = (X).s6_addr[12]; \
|
|
((uint8_t*)(bUFF))[13] = (X).s6_addr[13]; \
|
|
((uint8_t*)(bUFF))[14] = (X).s6_addr[14]; \
|
|
((uint8_t*)(bUFF))[15] = (X).s6_addr[15]; \
|
|
} while(0)
|
|
|
|
#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, vALUE) \
|
|
do { \
|
|
DevCheck((aSN)->bits_unused == 4, (aSN)->bits_unused, 4, 0); \
|
|
vALUE = ((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, mNCdIGITlENGTH) \
|
|
( mNCdIGITlENGTH == 2 ? 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, mNCdIGITlENGTH, 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,mNCdIGITlENGTH) << 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, mNCdIGITlENGTH, tBCDsTRING) \
|
|
do { \
|
|
char _buf[3]; \
|
|
DevAssert((mNCdIGITlENGTH == 3) || (mNCdIGITlENGTH == 2)); \
|
|
_buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC); \
|
|
_buf[1] = (MNC_HUNDREDS(mNC,mNCdIGITlENGTH) << 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, mNCdIGITlENGTH) \
|
|
do { \
|
|
int mNC_hundred; \
|
|
DevAssert((tBCDsTRING)->size == 3); \
|
|
mNC_hundred = (((tBCDsTRING)->buf[1] & 0xf0) >> 4); \
|
|
if (mNC_hundred == 0xf) { \
|
|
mNC_hundred = 0; \
|
|
mNCdIGITlENGTH = 2; \
|
|
} else { \
|
|
mNCdIGITlENGTH = 3; \
|
|
} \
|
|
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, mNClENGTH) \
|
|
do { \
|
|
tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit1; \
|
|
/* ambiguous (think about len 2) */ \
|
|
if (mNClENGTH == 2) { \
|
|
tBCDsTRING[1] = (0x0F << 4) | pLMN.MCCdigit3; \
|
|
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit1; \
|
|
} else { \
|
|
tBCDsTRING[1] = (pLMN.MNCdigit3 << 4) | pLMN.MCCdigit3; \
|
|
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit1; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH) \
|
|
do { \
|
|
mCC = pLMN.MCCdigit3 * 100 + pLMN.MCCdigit2 * 10 + pLMN.MCCdigit1; \
|
|
mNCdIGITlENGTH = (pLMN.MNCdigit3 == 0xF ? 2 : 3); \
|
|
mNC = (mNCdIGITlENGTH == 2 ? 0 : pLMN.MNCdigit3 * 100) \
|
|
+ pLMN.MNCdigit2 * 10 + pLMN.MNCdigit1; \
|
|
} while(0)
|
|
|
|
/* TS 36.413 v10.9.0 section 9.2.1.37:
|
|
* Macro eNB ID:
|
|
* Equal to the 20 leftmost bits of the Cell
|
|
* Identity IE contained in the E-UTRAN CGI
|
|
* IE (see subclause 9.2.1.38) of each cell
|
|
* served by the eNB.
|
|
*/
|
|
#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)
|
|
/* TS 36.413 v10.9.0 section 9.2.1.38:
|
|
* E-UTRAN CGI/Cell Identity
|
|
* The leftmost bits of the Cell
|
|
* Identity correspond to the eNB
|
|
* ID (defined in subclause 9.2.1.37).
|
|
*/
|
|
#define MACRO_ENB_ID_TO_CELL_IDENTITY(mACRO, cELL_iD, bITsTRING) \
|
|
do { \
|
|
(bITsTRING)->buf = calloc(4, sizeof(uint8_t)); \
|
|
(bITsTRING)->buf[0] = ((mACRO) >> 12); \
|
|
(bITsTRING)->buf[1] = (mACRO) >> 4; \
|
|
(bITsTRING)->buf[2] = (((mACRO) & 0x0f) << 4) | ((cELL_iD) >> 4); \
|
|
(bITsTRING)->buf[3] = ((cELL_iD) & 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
|
|
|
|
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_ */
|