blob: 38620470b8764f0cddfa9358d12c548a6ee4a445 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file gsm_utils.c */
Harald Welteec8b4502010-02-20 20:34:29 +01002/*
3 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +02004 * (C) 2009,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte622b7182010-03-07 17:50:21 +01005 * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
Nico Goldec56a56d2012-09-18 14:29:40 +02006 * (C) 2010-2012 by Nico Golde <nico@ngolde.de>
Harald Welteec8b4502010-02-20 20:34:29 +01007 *
8 * All Rights Reserved
9 *
Harald Weltee08da972017-11-13 01:00:26 +090010 * SPDX-License-Identifier: GPL-2.0+
11 *
Harald Welteec8b4502010-02-20 20:34:29 +010012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 *
26 */
27
Harald Welted38c8b82011-08-30 11:32:56 +020028/*! \mainpage libosmogsm Documentation
29 *
30 * \section sec_intro Introduction
31 * This library is a collection of common code used in various
32 * GSM related sub-projects inside the Osmocom family of projects. It
33 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +020034 * a GSM TLV parser, SMS utility routines as well as
Harald Welted38c8b82011-08-30 11:32:56 +020035 * protocol definitions for a series of protocols:
36 * * Um L2 (04.06)
37 * * Um L3 (04.08)
38 * * A-bis RSL (08.58)
39 * * A-bis OML (08.59, 12.21)
40 * * A (08.08)
41 * \n\n
42 * Please note that C language projects inside Osmocom are typically
43 * single-threaded event-loop state machine designs. As such,
44 * routines in libosmogsm are not thread-safe. If you must use them in
45 * a multi-threaded context, you have to add your own locking.
46 *
Harald Welte71658802017-06-12 15:40:52 +020047 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
48 * Communications) project, a community-based, collaborative development
49 * project to create Free and Open Source implementations of mobile
50 * communications systems. For more information about Osmocom, please
51 * see https://osmocom.org/
52 *
Harald Welted38c8b82011-08-30 11:32:56 +020053 * \section sec_copyright Copyright and License
54 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
55 * All rights reserved. \n\n
56 * The source code of libosmogsm is licensed under the terms of the GNU
57 * General Public License as published by the Free Software Foundation;
58 * either version 2 of the License, or (at your option) any later
59 * version.\n
60 * See <http://www.gnu.org/licenses/> or COPYING included in the source
61 * code package istelf.\n
62 * The information detailed here is provided AS IS with NO WARRANTY OF
63 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
64 * FITNESS FOR A PARTICULAR PURPOSE.
65 * \n\n
66 *
Harald Welte71658802017-06-12 15:40:52 +020067 * \section sec_tracker Homepage + Issue Tracker
68 * libosmogsm is distributed as part of libosmocore and shares its
69 * project page at http://osmocom.org/projects/libosmocore
70 *
71 * An Issue Tracker can be found at
72 * https://osmocom.org/projects/libosmocore/issues
73 *
Harald Welted38c8b82011-08-30 11:32:56 +020074 * \section sec_contact Contact and Support
75 * Community-based support is available at the OpenBSC mailing list
76 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
77 * Commercial support options available upon request from
78 * <http://sysmocom.de/>
79 */
80
Harald Welteec8b4502010-02-20 20:34:29 +010081//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010082#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020083#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010084#include <osmocom/gsm/gsm_utils.h>
Max764b0222016-05-11 17:33:17 +020085#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020086#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010087
88#include <stdlib.h>
89#include <stdint.h>
90#include <string.h>
Max764b0222016-05-11 17:33:17 +020091#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010092#include <stdio.h>
93#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010094#include <ctype.h>
Pau Espin Pedrol363130f2017-07-03 10:42:42 +020095#include <inttypes.h>
Max4b2b0cc2017-07-10 14:32:48 +020096#include <time.h>
97#include <unistd.h>
Harald Welteec8b4502010-02-20 20:34:29 +010098
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010099#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +0100100
Max4b2b0cc2017-07-10 14:32:48 +0200101/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
102#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
Pau Espin Pedrole2640ef2017-11-16 16:29:36 +0100103#include <sys/random.h>
Max4b2b0cc2017-07-10 14:32:48 +0200104#elif HAVE_DECL_SYS_GETRANDOM
105#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200106#ifndef GRND_NONBLOCK
107#define GRND_NONBLOCK 0x0001
108#endif
Max4b2b0cc2017-07-10 14:32:48 +0200109#endif
110
Maxed029df2017-10-26 10:56:04 +0200111#if (USE_GNUTLS)
112#pragma message ("including GnuTLS for getrandom fallback.")
113#include <gnutls/gnutls.h>
114#include <gnutls/crypto.h>
Alexander Couzens500d6332018-04-24 14:00:24 +0200115
116/* gnutls < 3.3.0 requires global init.
117 * gnutls >= 3.3.0 does it automatic.
118 * It doesn't hurt calling it twice,
119 * as long it's not done at the same time (threads).
120 */
121__attribute__((constructor))
122static void on_dso_load_gnutls(void)
123{
124 if (!gnutls_check_version("3.3.0"))
125 gnutls_global_init();
126}
127
128__attribute__((destructor))
129static void on_dso_unload_gnutls(void)
130{
131 if (!gnutls_check_version("3.3.0"))
132 gnutls_global_deinit();
133}
Maxed029df2017-10-26 10:56:04 +0200134#endif
135
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800136/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
137 * Greek symbols at hex positions 0x10 and 0x12-0x1a
138 * left out as they can't be handled with a char and
139 * since most phones don't display or write these
140 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200141 * more complex.
142 *
143 * Note that this table contains the latin1->7bit mapping _and_ has
144 * been merged with the reverse mapping (7bit->latin1) for the
145 * extended characters at offset 0x7f.
146 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800147static unsigned char gsm_7bit_alphabet[] = {
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
151 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
152 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
153 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
154 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
155 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
156 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
159 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
161 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
162 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
163 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
164 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
165};
166
Nico Golde28de0532010-07-09 17:19:12 +0200167/* GSM 03.38 6.2.1 Character lookup for decoding */
168static int gsm_septet_lookup(uint8_t ch)
169{
170 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200171 for (; i < sizeof(gsm_7bit_alphabet); i++) {
172 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200173 return i;
174 }
175 return -1;
176}
177
Harald Welte96e2a002017-06-12 21:44:18 +0200178/*! \brife Compute number of octets from number of septets,
179 * for instance: 47 septets needs 41,125 = 42 octets
180 * \param[in sept_len Number of Septets
181 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200182uint8_t gsm_get_octet_len(const uint8_t sept_len){
183 int octet_len = (sept_len * 7) / 8;
184 if ((sept_len * 7) % 8 != 0)
185 octet_len++;
186
187 return octet_len;
188}
189
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200190/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200191 * \param[out] text Caller-provided output text buffer
192 * \param[in] n Length of \a text
193 * \param[in] user_data Input Data (septets)
194 * \param[in] septet_l Number of septets in \a user_data
195 * \param[in] ud_hdr_ind User Data Header present in data
196 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200197int gsm_7bit_decode_n_hdr(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l, uint8_t ud_hdr_ind)
Harald Welteec8b4502010-02-20 20:34:29 +0100198{
Maxcf37c4c2016-01-21 16:52:40 +0100199 unsigned shift = 0;
200 uint8_t c7, c8, next_is_ext = 0, lu, ru;
201 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200202 const char *text_buf_begin = text;
203 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200204
205 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100206
Dennis Wehrle291e6132011-07-24 20:14:13 +0200207 /* skip the user data header */
208 if (ud_hdr_ind) {
209 /* get user data header length + 1 (for the 'user data header length'-field) */
210 shift = ((user_data[0] + 1) * 8) / 7;
211 if ((((user_data[0] + 1) * 8) % 7) != 0)
212 shift++;
213 septet_l = septet_l - shift;
214 }
215
Maxcf37c4c2016-01-21 16:52:40 +0100216 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200217 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100218
219 l = ((i + shift) * 7 + 7) >> 3;
220 r = ((i + shift) * 7) >> 3;
221
222 /* the left side index is always >= right side index
223 sometimes it even gets beyond array boundary
224 check for that explicitly and force 0 instead
225 */
226 if (l >= maxlen)
227 lu = 0;
228 else
229 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
230
231 ru = user_data[r] >> (((i + shift) * 7) & 7);
232
233 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200234
Harald Weltebe55a8b2012-09-20 10:00:25 +0200235 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200236 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200237 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200238 c8 = gsm_7bit_alphabet[0x7f + c7];
239 } else if (c7 == 0x1b && i + 1 < septet_l) {
240 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200241 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200242 } else {
243 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200244 }
245
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200246 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100247 }
248
Nico Golde28de0532010-07-09 17:19:12 +0200249 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200250
Maxcf37c4c2016-01-21 16:52:40 +0100251 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200252}
253
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200254/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200255int gsm_7bit_decode_n(char *text, size_t n, const uint8_t *user_data, uint8_t septet_l)
Dennis Wehrle291e6132011-07-24 20:14:13 +0200256{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200257 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200258}
259
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200260/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200261int gsm_7bit_decode_n_ussd(char *text, size_t n, const uint8_t *user_data, uint8_t length)
Andreas Eversberg95975552013-08-08 12:38:53 +0200262{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200263 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200264
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200265 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200266 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200267 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
268 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200269
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200270 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200271}
272
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200273/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200274 *
275 * This function converts a zero-terminated input string \a data from
276 * ASCII into octet-aligned 7-bit GSM characters. No packing is
277 * performed.
278 *
279 * \param[out] result caller-allocated output buffer
280 * \param[in] data input data, ASCII
281 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200282int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200283{
284 int i, y = 0;
285 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200286 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200287 ch = data[i];
288 switch(ch){
289 /* fall-through for extension characters */
290 case 0x0c:
291 case 0x5e:
292 case 0x7b:
293 case 0x7d:
294 case 0x5c:
295 case 0x5b:
296 case 0x7e:
297 case 0x5d:
298 case 0x7c:
299 result[y++] = 0x1b;
300 default:
301 result[y] = gsm_7bit_alphabet[ch];
302 break;
303 }
304 y++;
305 }
306
307 return y;
308}
309
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200310/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200311 * \param[out] result Caller-provided output buffer
312 * \param[in] rdata Input data septets
313 * \param[in] septet_len Length of \a rdata
314 * \param[in] padding padding bits at start
315 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100316int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
317{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200318 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200319 uint8_t cb, nb;
320 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200321 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200322
Dennis Wehrle291e6132011-07-24 20:14:13 +0200323 if (padding) {
324 shift = 7 - padding;
325 /* the first zero is needed for padding */
326 memcpy(data + 1, rdata, septet_len);
327 septet_len++;
328 } else
329 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200330
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200331 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200332 if (shift == 7) {
333 /*
334 * special end case with the. This is necessary if the
335 * last septet fits into the previous octet. E.g. 48
336 * non-extension characters:
337 * ....ag ( a = 1100001, g = 1100111)
338 * result[40] = 100001 XX, result[41] = 1100111 1 */
339 if (i + 1 < septet_len) {
340 shift = 0;
341 continue;
342 } else if (i + 1 == septet_len)
343 break;
Nico Golde28de0532010-07-09 17:19:12 +0200344 }
345
Dennis Wehrle291e6132011-07-24 20:14:13 +0200346 cb = (data[i] & 0x7f) >> shift;
347 if (i + 1 < septet_len) {
348 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200349 cb = cb | nb;
350 }
351
352 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200353 shift++;
354 }
355
Dennis Wehrle291e6132011-07-24 20:14:13 +0200356 free(data);
357
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200358 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100359}
360
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200361/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200362 * \param[out] result Caller-provided output buffer
363 * \param[in] n Maximum length of \a result in bytes
364 * \param[in] data octet-aligned string
365 * \param[out] octets Number of octets encoded
366 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200367int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200368{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200369 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200370 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100371 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200372
Dennis Wehrle291e6132011-07-24 20:14:13 +0200373 /* prepare for the worst case, every character expanding to two bytes */
374 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
375 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200376
377 if (y > max_septets) {
378 /*
379 * Limit the number of septets to avoid the generation
380 * of more than n octets.
381 */
382 y = max_septets;
383 }
384
385 o = gsm_septets2octets(result, rdata, y, 0);
386
387 if (octets)
388 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200389
390 free(rdata);
391
392 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200393 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200394 * unique. E.g.:
395 * 1.) 46 non-extension characters + 1 extension character
396 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
397 * 2.) 47 non-extension characters
398 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
399 * 3.) 48 non-extension characters
400 * => (48 * 7 bit) / 8 bit = 42 octects
401 */
402 return y;
403}
404
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200405/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200406 * \param[out] result Caller-provided output buffer
407 * \param[in] n Maximum length of \a result in bytes
408 * \param[in] data octet-aligned string
409 * \param[out] octets Number of octets encoded
410 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200411int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
412{
413 int y;
414
415 y = gsm_7bit_encode_n(result, n, data, octets);
416 /* if last octet contains only one bit, add <CR> */
417 if (((y * 7) & 7) == 1)
418 result[(*octets) - 1] |= ('\r' << 1);
419 /* if last character is <CR> and completely fills last octet, add
420 * another <CR>. */
421 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
422 result[(*octets)++] = '\r';
423 y++;
424 }
425
426 return y;
427}
428
Max4b2b0cc2017-07-10 14:32:48 +0200429/*! Generate random identifier
430 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
431 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
432 * See also RFC4086.
433 * \param[out] out Buffer to be filled with random data
434 * \param[in] len Number of random bytes required
435 * \returns 0 on success, or a negative error code on error.
436 */
437int osmo_get_rand_id(uint8_t *out, size_t len)
438{
Maxed029df2017-10-26 10:56:04 +0200439 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200440
441 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
442 if (len > OSMO_MAX_RAND_ID_LEN)
443 return -E2BIG;
444
445#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
446 rc = getrandom(out, len, GRND_NONBLOCK);
447#elif HAVE_DECL_SYS_GETRANDOM
448#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
449 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
450 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200451#endif
Maxed029df2017-10-26 10:56:04 +0200452
Max4b2b0cc2017-07-10 14:32:48 +0200453 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200454 if (rc < 0) {
455#if (USE_GNUTLS)
456#pragma message ("Secure random failed: using GnuTLS fallback.")
457 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
458#endif
Max4b2b0cc2017-07-10 14:32:48 +0200459 return -errno;
Maxed029df2017-10-26 10:56:04 +0200460 }
Max4b2b0cc2017-07-10 14:32:48 +0200461
462 /* getrandom() failed partially due to signal interruption:
463 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
464 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
465 if (rc != len)
466 return -EAGAIN;
467
468 return 0;
469}
470
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200471/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200472 * \param[in] mru Unidirectional measurement report structure
473 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
474 * period
475 * \param[out] buf Pre-allocated bufer for storing IE
476 * \returns Number of bytes filled in buf
477 */
478size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
479 uint8_t *buf)
480{
481 buf[0] = dtxd_used ? (1 << 6) : 0;
482 buf[0] |= (mru->full.rx_lev & 0x3f);
483 buf[1] = (mru->sub.rx_lev & 0x3f);
484 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
485
486 return 3;
487}
488
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200489/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200490 * \param[in] band GSM frequency band
491 * \param[in] class GSM power class
492 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200493unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
494{
495 switch (band) {
496 case GSM_BAND_450:
497 case GSM_BAND_480:
498 case GSM_BAND_750:
499 case GSM_BAND_900:
500 case GSM_BAND_810:
501 case GSM_BAND_850:
502 if (class == 1)
503 return 43; /* 20W */
504 if (class == 2)
505 return 39; /* 8W */
506 if (class == 3)
507 return 37; /* 5W */
508 if (class == 4)
509 return 33; /* 2W */
510 if (class == 5)
511 return 29; /* 0.8W */
512 break;
513 case GSM_BAND_1800:
514 if (class == 1)
515 return 30; /* 1W */
516 if (class == 2)
517 return 24; /* 0.25W */
518 if (class == 3)
519 return 36; /* 4W */
520 break;
521 case GSM_BAND_1900:
522 if (class == 1)
523 return 30; /* 1W */
524 if (class == 2)
525 return 24; /* 0.25W */
526 if (class == 3)
527 return 33; /* 2W */
528 break;
529 }
530 return -EINVAL;
531}
532
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200533/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200534 * by the tables in chapter 4.1.1 of GSM TS 05.05
535 * \param[in] GSM frequency band
536 * \param[in] dbm RF power value in dBm
537 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100538int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
539{
540 switch (band) {
541 case GSM_BAND_450:
542 case GSM_BAND_480:
543 case GSM_BAND_750:
544 case GSM_BAND_900:
545 case GSM_BAND_810:
546 case GSM_BAND_850:
547 if (dbm >= 39)
548 return 0;
549 else if (dbm < 5)
550 return 19;
551 else {
552 /* we are guaranteed to have (5 <= dbm < 39) */
553 return 2 + ((39 - dbm) / 2);
554 }
555 break;
556 case GSM_BAND_1800:
557 if (dbm >= 36)
558 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200559 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100560 return 30;
561 else if (dbm >= 32)
562 return 31;
563 else if (dbm == 31)
564 return 0;
565 else {
566 /* we are guaranteed to have (0 <= dbm < 31) */
567 return (30 - dbm) / 2;
568 }
569 break;
570 case GSM_BAND_1900:
571 if (dbm >= 33)
572 return 30;
573 else if (dbm >= 32)
574 return 31;
575 else if (dbm == 31)
576 return 0;
577 else {
578 /* we are guaranteed to have (0 <= dbm < 31) */
579 return (30 - dbm) / 2;
580 }
581 break;
582 }
583 return -EINVAL;
584}
585
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200586/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200587 * \param[in] band GSM frequency band
588 * \param[in] lvl TS 05.05 power control level
589 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100590int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
591{
592 lvl &= 0x1f;
593
594 switch (band) {
595 case GSM_BAND_450:
596 case GSM_BAND_480:
597 case GSM_BAND_750:
598 case GSM_BAND_900:
599 case GSM_BAND_810:
600 case GSM_BAND_850:
601 if (lvl < 2)
602 return 39;
603 else if (lvl < 20)
604 return 39 - ((lvl - 2) * 2) ;
605 else
606 return 5;
607 break;
608 case GSM_BAND_1800:
609 if (lvl < 16)
610 return 30 - (lvl * 2);
611 else if (lvl < 29)
612 return 0;
613 else
614 return 36 - ((lvl - 29) * 2);
615 break;
616 case GSM_BAND_1900:
617 if (lvl < 16)
618 return 30 - (lvl * 2);
619 else if (lvl < 30)
620 return -EINVAL;
621 else
622 return 33 - (lvl - 30);
623 break;
624 }
625 return -EINVAL;
626}
627
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200628/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200629 * \param[in] rxlev TS 05.08 RxLev value
630 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100631int rxlev2dbm(uint8_t rxlev)
632{
633 if (rxlev > 63)
634 rxlev = 63;
635
636 return -110 + rxlev;
637}
638
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200639/*! Convert RF signal level in dBm to TS 05.08 RxLev (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200640 * \param[in] dbm RF signal level in dBm
641 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100642uint8_t dbm2rxlev(int dbm)
643{
644 int rxlev = dbm + 110;
645
646 if (rxlev > 63)
647 rxlev = 63;
648 else if (rxlev < 0)
649 rxlev = 0;
650
651 return rxlev;
652}
653
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200654/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800655const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100656{
657 switch (band) {
658 case GSM_BAND_450:
659 return "GSM450";
660 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200661 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100662 case GSM_BAND_750:
663 return "GSM750";
664 case GSM_BAND_810:
665 return "GSM810";
666 case GSM_BAND_850:
667 return "GSM850";
668 case GSM_BAND_900:
669 return "GSM900";
670 case GSM_BAND_1800:
671 return "DCS1800";
672 case GSM_BAND_1900:
673 return "PCS1900";
674 }
675 return "invalid";
676}
677
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200678/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100679enum gsm_band gsm_band_parse(const char* mhz)
680{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200681 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100682 mhz++;
683
684 if (*mhz == '\0')
685 return -EINVAL;
686
Harald Welted3ff15f2010-03-07 18:23:47 +0100687 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100688 case 450:
689 return GSM_BAND_450;
690 case 480:
691 return GSM_BAND_480;
692 case 750:
693 return GSM_BAND_750;
694 case 810:
695 return GSM_BAND_810;
696 case 850:
697 return GSM_BAND_850;
698 case 900:
699 return GSM_BAND_900;
700 case 1800:
701 return GSM_BAND_1800;
702 case 1900:
703 return GSM_BAND_1900;
704 default:
705 return -EINVAL;
706 }
707}
708
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100709/*! Resolve GSM band from ARFCN.
Harald Welte96e2a002017-06-12 21:44:18 +0200710 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
711 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100712 * \param[out] band GSM Band containing \arfcn if arfcn is valid, undetermined otherwise
713 * \returns 0 if arfcn is valid and \a band was set, negative on error */
714int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band)
Harald Welte622b7182010-03-07 17:50:21 +0100715{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100716 int is_pcs = arfcn & ARFCN_PCS;
717
718 arfcn &= ~ARFCN_FLAG_MASK;
719
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100720 if (is_pcs) {
721 *band = GSM_BAND_1900;
722 return 0;
723 } else if (arfcn <= 124) {
724 *band = GSM_BAND_900;
725 return 0;
726 } else if (arfcn >= 955 && arfcn <= 1023) {
727 *band = GSM_BAND_900;
728 return 0;
729 } else if (arfcn >= 128 && arfcn <= 251) {
730 *band = GSM_BAND_850;
731 return 0;
732 } else if (arfcn >= 512 && arfcn <= 885) {
733 *band = GSM_BAND_1800;
734 return 0;
735 } else if (arfcn >= 259 && arfcn <= 293) {
736 *band = GSM_BAND_450;
737 return 0;
738 } else if (arfcn >= 306 && arfcn <= 340) {
739 *band = GSM_BAND_480;
740 return 0;
741 } else if (arfcn >= 350 && arfcn <= 425) {
742 *band = GSM_BAND_810;
743 return 0;
744 } else if (arfcn >= 438 && arfcn <= 511) {
745 *band = GSM_BAND_750;
746 return 0;
747 }
748 return -1;
749}
750
751/*! Resolve GSM band from ARFCN, aborts process on invalid ARFCN.
752 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS.
753 * DEPRECATED: Use gsm_arfcn2band_rc instead.
754 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
755 * \returns GSM Band if ARFCN is valid (part of any valid band), aborts otherwise */
756enum gsm_band gsm_arfcn2band(uint16_t arfcn)
757{
758 enum gsm_band band;
759 if (gsm_arfcn2band_rc(arfcn, &band) == 0)
760 return band;
761
762 osmo_panic("%s:%d Invalid arfcn %" PRIu16 " passed to gsm_arfcn2band\n",
763 __FILE__, __LINE__, arfcn);
Harald Welte622b7182010-03-07 17:50:21 +0100764}
765
Sylvain Munaut55720312012-12-11 23:44:41 +0100766struct gsm_freq_range {
767 uint16_t arfcn_first;
768 uint16_t arfcn_last;
769 uint16_t freq_ul_first;
770 uint16_t freq_dl_offset;
771 uint16_t flags;
772};
773
774static struct gsm_freq_range gsm_ranges[] = {
775 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
776 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
777 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
778 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
779 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
780 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
781 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
782 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
783 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
784 { /* Guard */ }
785};
786
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200787/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200788 * \param[in] arfcn GSM ARFCN to convert
789 * \param[in] uplink Uplink (1) or Downlink (0) frequency
790 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100791uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
792{
Sylvain Munaut55720312012-12-11 23:44:41 +0100793 struct gsm_freq_range *r;
794 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
795 uint16_t freq10_ul = 0xffff;
796 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100797
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100798 arfcn &= ~ARFCN_FLAG_MASK;
799
Sylvain Munaut55720312012-12-11 23:44:41 +0100800 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
801 if ((flags == r->flags) &&
802 (arfcn >= r->arfcn_first) &&
803 (arfcn <= r->arfcn_last))
804 {
805 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
806 freq10_dl = freq10_ul + r->freq_dl_offset;
807 break;
808 }
809 }
810
811 return uplink ? freq10_ul : freq10_dl;
812}
813
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200814/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200815 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
816 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
817 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100818uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
819{
820 struct gsm_freq_range *r;
821 uint16_t freq10_lo, freq10_hi;
822 uint16_t arfcn = 0xffff;
823
824 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
825 /* Generate frequency limits */
826 freq10_lo = r->freq_ul_first;
827 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
828 if (!uplink) {
829 freq10_lo += r->freq_dl_offset;
830 freq10_hi += r->freq_dl_offset;
831 }
832
833 /* Check if this fits */
834 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
835 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
836 arfcn |= r->flags;
837 break;
838 }
839 }
Harald Welte622b7182010-03-07 17:50:21 +0100840
841 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100842 arfcn |= ARFCN_UPLINK;
843
844 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100845}
846
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200847/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200848 * \param[out] time Caller-provided memory for \ref gsm_time
849 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100850void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
851{
852 time->fn = fn;
853 time->t1 = time->fn / (26*51);
854 time->t2 = time->fn % 26;
855 time->t3 = time->fn % 51;
856 time->tc = (time->fn / 51) % 8;
857}
858
Philipp Maierb808da42017-06-26 10:50:28 +0200859/*! Parse GSM Frame Number into printable string
860 * \param[in] fn GSM Frame Number
861 * \returns pointer to printable string */
862char *gsm_fn_as_gsmtime_str(uint32_t fn)
863{
864 struct gsm_time time;
865
866 gsm_fn2gsmtime(&time, fn);
867 return osmo_dump_gsmtime(&time);
868}
869
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200870/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200871 * \param[in] time GSM Time in decoded structure
872 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100873uint32_t gsm_gsmtime2fn(struct gsm_time *time)
874{
875 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
876 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
877}
Harald Weltea1c4f762010-05-01 11:59:42 +0200878
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200879char *osmo_dump_gsmtime(const struct gsm_time *tm)
880{
881 static char buf[64];
882
883 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
884 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
885 buf[sizeof(buf)-1] = '\0';
886 return buf;
887}
888
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200889/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200890 * \param[out] bv Caller-provided output bit-vector
891 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200892void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
893{
894 bitvec_set_uint(bv, r->w1_hi, 2);
895 bitvec_set_uint(bv, r->w1_lo, 8);
896 bitvec_set_uint(bv, r->w2_hi, 8);
897 bitvec_set_uint(bv, r->w2_lo, 1);
898 bitvec_set_uint(bv, r->w3_hi, 7);
899 bitvec_set_uint(bv, r->w3_lo, 2);
900 bitvec_set_uint(bv, r->w4_hi, 6);
901 bitvec_set_uint(bv, r->w4_lo, 2);
902 bitvec_set_uint(bv, r->w5_hi, 6);
903 bitvec_set_uint(bv, r->w5_lo, 2);
904 bitvec_set_uint(bv, r->w6_hi, 6);
905 bitvec_set_uint(bv, r->w6_lo, 2);
906 bitvec_set_uint(bv, r->w7_hi, 6);
907 bitvec_set_uint(bv, r->w7_lo, 2);
908 bitvec_set_uint(bv, r->w8_hi, 6);
909 bitvec_set_uint(bv, r->w8_lo, 1);
910 bitvec_set_uint(bv, r->w9, 7);
911 bitvec_set_uint(bv, r->w10, 7);
912 bitvec_set_uint(bv, r->w11_hi, 1);
913 bitvec_set_uint(bv, r->w11_lo, 6);
914 bitvec_set_uint(bv, r->w12_hi, 2);
915 bitvec_set_uint(bv, r->w12_lo, 5);
916 bitvec_set_uint(bv, r->w13_hi, 3);
917 bitvec_set_uint(bv, r->w13_lo, 4);
918 bitvec_set_uint(bv, r->w14_hi, 4);
919 bitvec_set_uint(bv, r->w14_lo, 3);
920 bitvec_set_uint(bv, r->w15_hi, 5);
921 bitvec_set_uint(bv, r->w15_lo, 2);
922 bitvec_set_uint(bv, r->w16, 6);
923}
924
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200925/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200926int gprs_tlli_type(uint32_t tlli)
927{
928 if ((tlli & 0xc0000000) == 0xc0000000)
929 return TLLI_LOCAL;
930 else if ((tlli & 0xc0000000) == 0x80000000)
931 return TLLI_FOREIGN;
932 else if ((tlli & 0xf8000000) == 0x78000000)
933 return TLLI_RANDOM;
934 else if ((tlli & 0xf8000000) == 0x70000000)
935 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200936 else if ((tlli & 0xf0000000) == 0x00000000)
937 return TLLI_G_RNTI;
938 else if ((tlli & 0xf0000000) == 0x10000000)
939 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200940
941 return TLLI_RESERVED;
942}
Harald Weltec2263172010-06-01 10:47:07 +0200943
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200944/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200945 * \param[in] p_tmsi P-TMSI
946 * \param[in] type TLLI Type we want to derive from \a p_tmsi
947 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200948uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
949{
950 uint32_t tlli;
951 switch (type) {
952 case TLLI_LOCAL:
953 tlli = p_tmsi | 0xc0000000;
954 break;
955 case TLLI_FOREIGN:
956 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
957 break;
958 default:
959 tlli = 0;
960 break;
961 }
962 return tlli;
963}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200964
965/* Wrappers for deprecated functions: */
966
967int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
968{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100969 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
970 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200971
972 /* Mimic the original behaviour. */
973 return septet_l;
974}
975
976int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
977{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100978 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
979 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200980}
981
982int gsm_7bit_encode(uint8_t *result, const char *data)
983{
984 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100985 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
986 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200987}
988
989int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
990{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100991 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
992 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200993}
994
995int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
996{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100997 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
998 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200999}
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001000
1001/* This is also used by osmo-hlr's db schema */
1002const struct value_string osmo_rat_type_names[] = {
1003 { OSMO_RAT_UNKNOWN, "unknown" },
1004 { OSMO_RAT_GERAN_A, "GERAN-A" },
1005 { OSMO_RAT_UTRAN_IU, "UTRAN-Iu" },
1006 {}
1007};