Files
openairinterface5g/openair3/UTILS/conversions.h
T

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_ */