conversions.h 14.1 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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
 */

Cedric Roux's avatar
 
Cedric Roux committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
#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

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#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)

Cedric Roux's avatar
 
Cedric Roux committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#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)

Cedric Roux's avatar
Cedric Roux committed
102 103
/* Convert an integer on 32 bits to an octet string from aSN1c tool */
#define INT32_TO_OCTET_STRING(x, aSN)           \
Cedric Roux's avatar
 
Cedric Roux committed
104
do {                                            \
Cedric Roux's avatar
Cedric Roux committed
105 106 107
    (aSN)->buf = calloc(4, sizeof(uint8_t));    \
    INT32_TO_BUFFER(x, ((aSN)->buf));           \
    (aSN)->size = 4;                            \
Cedric Roux's avatar
 
Cedric Roux committed
108 109
} while(0)

Cedric Roux's avatar
Cedric Roux committed
110
#define INT32_TO_BIT_STRING(x, aSN) \
Cedric Roux's avatar
 
Cedric Roux committed
111
do {                                \
Cedric Roux's avatar
Cedric Roux committed
112 113
    INT32_TO_OCTET_STRING(x, aSN);  \
    (aSN)->bits_unused = 0;         \
Cedric Roux's avatar
 
Cedric Roux committed
114 115
} while(0)

Cedric Roux's avatar
Cedric Roux committed
116
#define INT16_TO_OCTET_STRING(x, aSN)           \
Cedric Roux's avatar
 
Cedric Roux committed
117
do {                                            \
Cedric Roux's avatar
Cedric Roux committed
118
    (aSN)->buf = calloc(2, sizeof(uint8_t));    \
119
    (aSN)->size = 2;              \
Cedric Roux's avatar
Cedric Roux committed
120
    INT16_TO_BUFFER(x, (aSN)->buf);             \
Cedric Roux's avatar
 
Cedric Roux committed
121 122
} while(0)

Cedric Roux's avatar
Cedric Roux committed
123
#define INT8_TO_OCTET_STRING(x, aSN)            \
Cedric Roux's avatar
 
Cedric Roux committed
124
do {                                            \
Cedric Roux's avatar
Cedric Roux committed
125 126 127
    (aSN)->buf = calloc(1, sizeof(uint8_t));    \
    (aSN)->size = 1;                            \
    INT8_TO_BUFFER(x, (aSN)->buf);              \
Cedric Roux's avatar
 
Cedric Roux committed
128 129 130 131 132 133
} 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

Cedric Roux's avatar
Cedric Roux committed
134
#define OCTET_STRING_TO_INT8(aSN, x)    \
Cedric Roux's avatar
 
Cedric Roux committed
135
do {                                    \
Cedric Roux's avatar
Cedric Roux committed
136 137
    DevCheck((aSN)->size == 1, (aSN)->size, 0, 0);           \
    BUFFER_TO_INT8((aSN)->buf, x);    \
Cedric Roux's avatar
 
Cedric Roux committed
138 139
} while(0)

Cedric Roux's avatar
Cedric Roux committed
140
#define OCTET_STRING_TO_INT16(aSN, x)   \
Cedric Roux's avatar
 
Cedric Roux committed
141
do {                                    \
Cedric Roux's avatar
Cedric Roux committed
142 143
    DevCheck((aSN)->size == 2, (aSN)->size, 0, 0);           \
    BUFFER_TO_INT16((aSN)->buf, x);    \
Cedric Roux's avatar
 
Cedric Roux committed
144 145
} while(0)

Cedric Roux's avatar
Cedric Roux committed
146
#define OCTET_STRING_TO_INT32(aSN, x)   \
Cedric Roux's avatar
 
Cedric Roux committed
147
do {                                    \
Cedric Roux's avatar
Cedric Roux committed
148 149
    DevCheck((aSN)->size == 4, (aSN)->size, 0, 0);           \
    BUFFER_TO_INT32((aSN)->buf, x);    \
Cedric Roux's avatar
 
Cedric Roux committed
150 151
} while(0)

Cedric Roux's avatar
Cedric Roux committed
152
#define BIT_STRING_TO_INT32(aSN, x)     \
Cedric Roux's avatar
 
Cedric Roux committed
153
do {                                    \
Cedric Roux's avatar
Cedric Roux committed
154 155
    DevCheck((aSN)->bits_unused == 0, (aSN)->bits_unused, 0, 0);    \
    OCTET_STRING_TO_INT32(aSN, x);      \
Cedric Roux's avatar
 
Cedric Roux committed
156 157
} while(0)

Cedric Roux's avatar
Cedric Roux committed
158
#define BIT_STRING_TO_CELL_IDENTITY(aSN, vALUE)                     \
Cedric Roux's avatar
 
Cedric Roux committed
159
do {                                                                \
Cedric Roux's avatar
Cedric Roux committed
160 161 162
    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];                       \
Cedric Roux's avatar
 
Cedric Roux committed
163 164 165 166 167
} while(0)

#define MCC_HUNDREDS(vALUE) \
    ((vALUE) / 100)
/* When MNC is only composed of 2 digits, set the hundreds unit to 0xf */
168 169
#define MNC_HUNDREDS(vALUE, mNCdIGITlENGTH) \
    ( mNCdIGITlENGTH == 2 ? 15 : (vALUE) / 100)
Cedric Roux's avatar
 
Cedric Roux committed
170 171 172 173 174 175 176 177 178 179 180 181 182
#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)

183
#define MCC_MNC_TO_PLMNID(mCC, mNC, mNCdIGITlENGTH, oCTETsTRING)               \
Cedric Roux's avatar
 
Cedric Roux committed
184 185 186
do {                                                                           \
    (oCTETsTRING)->buf = calloc(3, sizeof(uint8_t));                           \
    (oCTETsTRING)->buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC);   \
187
    (oCTETsTRING)->buf[1] = (MNC_HUNDREDS(mNC,mNCdIGITlENGTH) << 4) | MCC_MNC_DIGIT(mCC);     \
Cedric Roux's avatar
 
Cedric Roux committed
188 189 190 191
    (oCTETsTRING)->buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC);  \
    (oCTETsTRING)->size = 3;                                                   \
} while(0)

192
#define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING)        \
Cedric Roux's avatar
 
Cedric Roux committed
193 194
do {                                                                 \
    char _buf[3];                                                    \
195
     DevAssert((mNCdIGITlENGTH == 3) || (mNCdIGITlENGTH == 2));      \
Cedric Roux's avatar
 
Cedric Roux committed
196
    _buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC);       \
197
    _buf[1] = (MNC_HUNDREDS(mNC,mNCdIGITlENGTH) << 4) | MCC_MNC_DIGIT(mCC);\
Cedric Roux's avatar
 
Cedric Roux committed
198 199 200 201
    _buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC);      \
    OCTET_STRING_fromBuf(tBCDsTRING, _buf, 3);                       \
} while(0)

202
#define TBCD_TO_MCC_MNC(tBCDsTRING, mCC, mNC, mNCdIGITlENGTH)    \
Cedric Roux's avatar
 
Cedric Roux committed
203 204 205 206
do {                                                             \
    int mNC_hundred;                                             \
    DevAssert((tBCDsTRING)->size == 3);                          \
    mNC_hundred = (((tBCDsTRING)->buf[1] & 0xf0) >> 4);          \
207 208 209 210 211 212
    if (mNC_hundred == 0xf) {                                    \
        mNC_hundred = 0;                                         \
        mNCdIGITlENGTH = 2;                                      \
    } else {                                                     \
            mNCdIGITlENGTH = 3;                                  \
    }                                                            \
Cedric Roux's avatar
 
Cedric Roux committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    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)

233
#define PLMN_T_TO_TBCD(pLMN, tBCDsTRING, mNClENGTH)                 \
Cedric Roux's avatar
 
Cedric Roux committed
234
do {                                                                \
235
    tBCDsTRING[0] = (pLMN.MCCdigit2 << 4) | pLMN.MCCdigit1;         \
236
    /* ambiguous (think about len 2) */                             \
237 238 239
    if (mNClENGTH == 2) {                                      \
        tBCDsTRING[1] = (0x0F << 4) | pLMN.MCCdigit3;               \
        tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit1;     \
240
    } else {                                                        \
241
        tBCDsTRING[1] = (pLMN.MNCdigit3 << 4) | pLMN.MCCdigit3;     \
242 243
        tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit1;     \
    }                                                               \
Cedric Roux's avatar
 
Cedric Roux committed
244 245
} while(0)

246 247
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH)               \
do {                                                                    \
Cedric Roux's avatar
 
Cedric Roux committed
248
    mCC = pLMN.MCCdigit3 * 100 + pLMN.MCCdigit2 * 10 + pLMN.MCCdigit1;  \
249 250 251
    mNCdIGITlENGTH = (pLMN.MNCdigit3 == 0xF ? 2 : 3);                   \
    mNC = (mNCdIGITlENGTH == 2 ? 0 : pLMN.MNCdigit3 * 100)              \
          + pLMN.MNCdigit2 * 10 + pLMN.MNCdigit1;                       \
Cedric Roux's avatar
 
Cedric Roux committed
252 253
} while(0)

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

/* TS 38.473 v15.1.1 section 9.3.2.1:
 * NR CELL ID
 */
#define TRANSPORT_LAYER_ADDRESS_TO_BIT_STRING(mACRO, bITsTRING)    \
do {                                                    \
    (bITsTRING)->buf = calloc(5, sizeof(uint8_t));      \
    (bITsTRING)->buf[0] = (mACRO) >> 28;                \
    (bITsTRING)->buf[1] = (mACRO) >> 20;                \
    (bITsTRING)->buf[2] = (mACRO) >> 12;                \
    (bITsTRING)->buf[3] = (mACRO) >> 4;                 \
    (bITsTRING)->buf[4] = ((mACRO) & 0x0f) << 4;        \
    (bITsTRING)->size = 5;                              \
    (bITsTRING)->bits_unused = 4;                       \
} while(0)

/* TS 38.473 v15.1.1 section 9.3.1.12:
 * NR CELL ID
 */
#define NR_CELL_ID_TO_BIT_STRING(mACRO, bITsTRING)      \
do {                                                    \
    (bITsTRING)->buf = calloc(5, sizeof(uint8_t));      \
    (bITsTRING)->buf[0] = (mACRO) >> 28;                \
    (bITsTRING)->buf[1] = (mACRO) >> 20;                \
    (bITsTRING)->buf[2] = (mACRO) >> 12;                \
    (bITsTRING)->buf[3] = (mACRO) >> 4;                 \
    (bITsTRING)->buf[4] = ((mACRO) & 0x0f) << 4;        \
    (bITsTRING)->size = 5;                              \
    (bITsTRING)->bits_unused = 4;                       \
} while(0)

285 286 287 288 289 290 291
/* 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.
 */
Cedric Roux's avatar
 
Cedric Roux committed
292 293 294 295 296
#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;                 \
winckel's avatar
winckel committed
297
    (bITsTRING)->buf[2] = ((mACRO) & 0x0f) << 4;        \
Cedric Roux's avatar
 
Cedric Roux committed
298 299 300
    (bITsTRING)->size = 3;                              \
    (bITsTRING)->bits_unused = 4;                       \
} while(0)
301 302 303 304 305 306 307
/* 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) \
Cedric Roux's avatar
 
Cedric Roux committed
308 309
do {                                                    \
    (bITsTRING)->buf = calloc(4, sizeof(uint8_t));      \
310 311 312 313
    (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;        \
Cedric Roux's avatar
 
Cedric Roux committed
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    (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_ */