blob: 02cb3d554f5208c22706f6113361e6f43e2a6e37 [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
Max0187c3a2018-11-09 13:08:42 +0100101#if (!EMBEDDED)
Max4b2b0cc2017-07-10 14:32:48 +0200102/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
Max0187c3a2018-11-09 13:08:42 +0100103#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,25)
104#pragma message ("glibc " OSMO_STRINGIFY_VAL(__GLIBC__) "." OSMO_STRINGIFY_VAL(__GLIBC_MINOR__) " random detected")
Pau Espin Pedrole2640ef2017-11-16 16:29:36 +0100105#include <sys/random.h>
Max42e567c2018-11-09 13:13:45 +0100106#undef USE_GNUTLS
Max4b2b0cc2017-07-10 14:32:48 +0200107#elif HAVE_DECL_SYS_GETRANDOM
108#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200109#ifndef GRND_NONBLOCK
110#define GRND_NONBLOCK 0x0001
Max0187c3a2018-11-09 13:08:42 +0100111#endif /* ifndef GRND_NONBLOCK */
112#endif /* if __GLIBC_PREREQ */
113#endif /* !EMBEDDED */
Max4b2b0cc2017-07-10 14:32:48 +0200114
Maxed029df2017-10-26 10:56:04 +0200115#if (USE_GNUTLS)
116#pragma message ("including GnuTLS for getrandom fallback.")
117#include <gnutls/gnutls.h>
118#include <gnutls/crypto.h>
Alexander Couzens500d6332018-04-24 14:00:24 +0200119
120/* gnutls < 3.3.0 requires global init.
121 * gnutls >= 3.3.0 does it automatic.
122 * It doesn't hurt calling it twice,
123 * as long it's not done at the same time (threads).
124 */
125__attribute__((constructor))
126static void on_dso_load_gnutls(void)
127{
128 if (!gnutls_check_version("3.3.0"))
129 gnutls_global_init();
130}
131
132__attribute__((destructor))
133static void on_dso_unload_gnutls(void)
134{
135 if (!gnutls_check_version("3.3.0"))
136 gnutls_global_deinit();
137}
Max0187c3a2018-11-09 13:08:42 +0100138
139#endif /* if (USE_GNUTLS) */
Maxed029df2017-10-26 10:56:04 +0200140
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800141/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
142 * Greek symbols at hex positions 0x10 and 0x12-0x1a
143 * left out as they can't be handled with a char and
144 * since most phones don't display or write these
145 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200146 * more complex.
147 *
148 * Note that this table contains the latin1->7bit mapping _and_ has
149 * been merged with the reverse mapping (7bit->latin1) for the
150 * extended characters at offset 0x7f.
151 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800152static unsigned char gsm_7bit_alphabet[] = {
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
156 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
157 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
158 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
159 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
160 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
161 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
162 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
164 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
166 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
167 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
168 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
169 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
170};
171
Nico Golde28de0532010-07-09 17:19:12 +0200172/* GSM 03.38 6.2.1 Character lookup for decoding */
173static int gsm_septet_lookup(uint8_t ch)
174{
175 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200176 for (; i < sizeof(gsm_7bit_alphabet); i++) {
177 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200178 return i;
179 }
180 return -1;
181}
182
Harald Welte96e2a002017-06-12 21:44:18 +0200183/*! \brife Compute number of octets from number of septets,
184 * for instance: 47 septets needs 41,125 = 42 octets
185 * \param[in sept_len Number of Septets
186 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200187uint8_t gsm_get_octet_len(const uint8_t sept_len){
188 int octet_len = (sept_len * 7) / 8;
189 if ((sept_len * 7) % 8 != 0)
190 octet_len++;
191
192 return octet_len;
193}
194
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200195/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200196 * \param[out] text Caller-provided output text buffer
197 * \param[in] n Length of \a text
198 * \param[in] user_data Input Data (septets)
199 * \param[in] septet_l Number of septets in \a user_data
200 * \param[in] ud_hdr_ind User Data Header present in data
201 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200202int 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 +0100203{
Maxcf37c4c2016-01-21 16:52:40 +0100204 unsigned shift = 0;
205 uint8_t c7, c8, next_is_ext = 0, lu, ru;
206 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200207 const char *text_buf_begin = text;
208 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200209
210 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100211
Dennis Wehrle291e6132011-07-24 20:14:13 +0200212 /* skip the user data header */
213 if (ud_hdr_ind) {
214 /* get user data header length + 1 (for the 'user data header length'-field) */
215 shift = ((user_data[0] + 1) * 8) / 7;
216 if ((((user_data[0] + 1) * 8) % 7) != 0)
217 shift++;
218 septet_l = septet_l - shift;
219 }
220
Maxcf37c4c2016-01-21 16:52:40 +0100221 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200222 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100223
224 l = ((i + shift) * 7 + 7) >> 3;
225 r = ((i + shift) * 7) >> 3;
226
227 /* the left side index is always >= right side index
228 sometimes it even gets beyond array boundary
229 check for that explicitly and force 0 instead
230 */
231 if (l >= maxlen)
232 lu = 0;
233 else
234 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
235
236 ru = user_data[r] >> (((i + shift) * 7) & 7);
237
238 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200239
Harald Weltebe55a8b2012-09-20 10:00:25 +0200240 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200241 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200242 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200243 c8 = gsm_7bit_alphabet[0x7f + c7];
244 } else if (c7 == 0x1b && i + 1 < septet_l) {
245 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200246 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200247 } else {
248 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200249 }
250
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200251 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100252 }
253
Nico Golde28de0532010-07-09 17:19:12 +0200254 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200255
Maxcf37c4c2016-01-21 16:52:40 +0100256 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200257}
258
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200259/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200260int 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 +0200261{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200262 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200263}
264
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200265/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200266int 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 +0200267{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200268 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200269
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200270 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200271 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200272 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
273 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200274
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200275 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200276}
277
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200278/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200279 *
280 * This function converts a zero-terminated input string \a data from
281 * ASCII into octet-aligned 7-bit GSM characters. No packing is
282 * performed.
283 *
284 * \param[out] result caller-allocated output buffer
285 * \param[in] data input data, ASCII
286 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200287int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200288{
289 int i, y = 0;
290 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200291 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200292 ch = data[i];
293 switch(ch){
294 /* fall-through for extension characters */
295 case 0x0c:
296 case 0x5e:
297 case 0x7b:
298 case 0x7d:
299 case 0x5c:
300 case 0x5b:
301 case 0x7e:
302 case 0x5d:
303 case 0x7c:
304 result[y++] = 0x1b;
305 default:
306 result[y] = gsm_7bit_alphabet[ch];
307 break;
308 }
309 y++;
310 }
311
312 return y;
313}
314
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200315/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200316 * \param[out] result Caller-provided output buffer
317 * \param[in] rdata Input data septets
318 * \param[in] septet_len Length of \a rdata
319 * \param[in] padding padding bits at start
320 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100321int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
322{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200323 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200324 uint8_t cb, nb;
325 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200326 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200327
Dennis Wehrle291e6132011-07-24 20:14:13 +0200328 if (padding) {
329 shift = 7 - padding;
330 /* the first zero is needed for padding */
331 memcpy(data + 1, rdata, septet_len);
332 septet_len++;
333 } else
334 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200335
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200336 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200337 if (shift == 7) {
338 /*
339 * special end case with the. This is necessary if the
340 * last septet fits into the previous octet. E.g. 48
341 * non-extension characters:
342 * ....ag ( a = 1100001, g = 1100111)
343 * result[40] = 100001 XX, result[41] = 1100111 1 */
344 if (i + 1 < septet_len) {
345 shift = 0;
346 continue;
347 } else if (i + 1 == septet_len)
348 break;
Nico Golde28de0532010-07-09 17:19:12 +0200349 }
350
Dennis Wehrle291e6132011-07-24 20:14:13 +0200351 cb = (data[i] & 0x7f) >> shift;
352 if (i + 1 < septet_len) {
353 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200354 cb = cb | nb;
355 }
356
357 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200358 shift++;
359 }
360
Dennis Wehrle291e6132011-07-24 20:14:13 +0200361 free(data);
362
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200363 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100364}
365
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200366/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200367 * \param[out] result Caller-provided output buffer
368 * \param[in] n Maximum length of \a result in bytes
369 * \param[in] data octet-aligned string
370 * \param[out] octets Number of octets encoded
371 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200372int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200373{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200374 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200375 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100376 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200377
Dennis Wehrle291e6132011-07-24 20:14:13 +0200378 /* prepare for the worst case, every character expanding to two bytes */
379 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
380 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200381
382 if (y > max_septets) {
383 /*
384 * Limit the number of septets to avoid the generation
385 * of more than n octets.
386 */
387 y = max_septets;
388 }
389
390 o = gsm_septets2octets(result, rdata, y, 0);
391
392 if (octets)
393 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200394
395 free(rdata);
396
397 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200398 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200399 * unique. E.g.:
400 * 1.) 46 non-extension characters + 1 extension character
401 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
402 * 2.) 47 non-extension characters
403 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
404 * 3.) 48 non-extension characters
405 * => (48 * 7 bit) / 8 bit = 42 octects
406 */
407 return y;
408}
409
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200410/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200411 * \param[out] result Caller-provided output buffer
412 * \param[in] n Maximum length of \a result in bytes
413 * \param[in] data octet-aligned string
414 * \param[out] octets Number of octets encoded
415 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200416int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
417{
418 int y;
419
420 y = gsm_7bit_encode_n(result, n, data, octets);
421 /* if last octet contains only one bit, add <CR> */
422 if (((y * 7) & 7) == 1)
423 result[(*octets) - 1] |= ('\r' << 1);
424 /* if last character is <CR> and completely fills last octet, add
425 * another <CR>. */
426 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
427 result[(*octets)++] = '\r';
428 y++;
429 }
430
431 return y;
432}
433
Max4b2b0cc2017-07-10 14:32:48 +0200434/*! Generate random identifier
435 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
436 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
437 * See also RFC4086.
438 * \param[out] out Buffer to be filled with random data
439 * \param[in] len Number of random bytes required
440 * \returns 0 on success, or a negative error code on error.
441 */
442int osmo_get_rand_id(uint8_t *out, size_t len)
443{
Maxed029df2017-10-26 10:56:04 +0200444 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200445
446 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
447 if (len > OSMO_MAX_RAND_ID_LEN)
448 return -E2BIG;
Max0187c3a2018-11-09 13:08:42 +0100449#if (!EMBEDDED)
450#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,25)
Max4b2b0cc2017-07-10 14:32:48 +0200451 rc = getrandom(out, len, GRND_NONBLOCK);
452#elif HAVE_DECL_SYS_GETRANDOM
453#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
454 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
455 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200456#endif
Max0187c3a2018-11-09 13:08:42 +0100457#endif /* !EMBEDDED */
Maxed029df2017-10-26 10:56:04 +0200458
Max4b2b0cc2017-07-10 14:32:48 +0200459 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200460 if (rc < 0) {
461#if (USE_GNUTLS)
Maxed029df2017-10-26 10:56:04 +0200462 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
463#endif
Max4b2b0cc2017-07-10 14:32:48 +0200464 return -errno;
Maxed029df2017-10-26 10:56:04 +0200465 }
Max4b2b0cc2017-07-10 14:32:48 +0200466
467 /* getrandom() failed partially due to signal interruption:
468 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
469 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
470 if (rc != len)
471 return -EAGAIN;
472
473 return 0;
474}
475
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200476/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200477 * \param[in] mru Unidirectional measurement report structure
478 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
479 * period
480 * \param[out] buf Pre-allocated bufer for storing IE
481 * \returns Number of bytes filled in buf
482 */
483size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
484 uint8_t *buf)
485{
486 buf[0] = dtxd_used ? (1 << 6) : 0;
487 buf[0] |= (mru->full.rx_lev & 0x3f);
488 buf[1] = (mru->sub.rx_lev & 0x3f);
489 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
490
491 return 3;
492}
493
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200494/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200495 * \param[in] band GSM frequency band
496 * \param[in] class GSM power class
497 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200498unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
499{
500 switch (band) {
501 case GSM_BAND_450:
502 case GSM_BAND_480:
503 case GSM_BAND_750:
504 case GSM_BAND_900:
505 case GSM_BAND_810:
506 case GSM_BAND_850:
507 if (class == 1)
508 return 43; /* 20W */
509 if (class == 2)
510 return 39; /* 8W */
511 if (class == 3)
512 return 37; /* 5W */
513 if (class == 4)
514 return 33; /* 2W */
515 if (class == 5)
516 return 29; /* 0.8W */
517 break;
518 case GSM_BAND_1800:
519 if (class == 1)
520 return 30; /* 1W */
521 if (class == 2)
522 return 24; /* 0.25W */
523 if (class == 3)
524 return 36; /* 4W */
525 break;
526 case GSM_BAND_1900:
527 if (class == 1)
528 return 30; /* 1W */
529 if (class == 2)
530 return 24; /* 0.25W */
531 if (class == 3)
532 return 33; /* 2W */
533 break;
534 }
535 return -EINVAL;
536}
537
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200538/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200539 * by the tables in chapter 4.1.1 of GSM TS 05.05
540 * \param[in] GSM frequency band
541 * \param[in] dbm RF power value in dBm
542 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100543int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
544{
545 switch (band) {
546 case GSM_BAND_450:
547 case GSM_BAND_480:
548 case GSM_BAND_750:
549 case GSM_BAND_900:
550 case GSM_BAND_810:
551 case GSM_BAND_850:
552 if (dbm >= 39)
553 return 0;
554 else if (dbm < 5)
555 return 19;
556 else {
557 /* we are guaranteed to have (5 <= dbm < 39) */
558 return 2 + ((39 - dbm) / 2);
559 }
560 break;
561 case GSM_BAND_1800:
562 if (dbm >= 36)
563 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200564 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100565 return 30;
566 else if (dbm >= 32)
567 return 31;
568 else if (dbm == 31)
569 return 0;
570 else {
571 /* we are guaranteed to have (0 <= dbm < 31) */
572 return (30 - dbm) / 2;
573 }
574 break;
575 case GSM_BAND_1900:
576 if (dbm >= 33)
577 return 30;
578 else if (dbm >= 32)
579 return 31;
580 else if (dbm == 31)
581 return 0;
582 else {
583 /* we are guaranteed to have (0 <= dbm < 31) */
584 return (30 - dbm) / 2;
585 }
586 break;
587 }
588 return -EINVAL;
589}
590
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200591/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200592 * \param[in] band GSM frequency band
593 * \param[in] lvl TS 05.05 power control level
594 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100595int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
596{
597 lvl &= 0x1f;
598
599 switch (band) {
600 case GSM_BAND_450:
601 case GSM_BAND_480:
602 case GSM_BAND_750:
603 case GSM_BAND_900:
604 case GSM_BAND_810:
605 case GSM_BAND_850:
606 if (lvl < 2)
607 return 39;
608 else if (lvl < 20)
609 return 39 - ((lvl - 2) * 2) ;
610 else
611 return 5;
612 break;
613 case GSM_BAND_1800:
614 if (lvl < 16)
615 return 30 - (lvl * 2);
616 else if (lvl < 29)
617 return 0;
618 else
619 return 36 - ((lvl - 29) * 2);
620 break;
621 case GSM_BAND_1900:
622 if (lvl < 16)
623 return 30 - (lvl * 2);
624 else if (lvl < 30)
625 return -EINVAL;
626 else
627 return 33 - (lvl - 30);
628 break;
629 }
630 return -EINVAL;
631}
632
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200633/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200634 * \param[in] rxlev TS 05.08 RxLev value
635 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100636int rxlev2dbm(uint8_t rxlev)
637{
638 if (rxlev > 63)
639 rxlev = 63;
640
641 return -110 + rxlev;
642}
643
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200644/*! 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 +0200645 * \param[in] dbm RF signal level in dBm
646 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100647uint8_t dbm2rxlev(int dbm)
648{
649 int rxlev = dbm + 110;
650
651 if (rxlev > 63)
652 rxlev = 63;
653 else if (rxlev < 0)
654 rxlev = 0;
655
656 return rxlev;
657}
658
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200659/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800660const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100661{
662 switch (band) {
663 case GSM_BAND_450:
664 return "GSM450";
665 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200666 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100667 case GSM_BAND_750:
668 return "GSM750";
669 case GSM_BAND_810:
670 return "GSM810";
671 case GSM_BAND_850:
672 return "GSM850";
673 case GSM_BAND_900:
674 return "GSM900";
675 case GSM_BAND_1800:
676 return "DCS1800";
677 case GSM_BAND_1900:
678 return "PCS1900";
679 }
680 return "invalid";
681}
682
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200683/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100684enum gsm_band gsm_band_parse(const char* mhz)
685{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200686 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100687 mhz++;
688
689 if (*mhz == '\0')
690 return -EINVAL;
691
Harald Welted3ff15f2010-03-07 18:23:47 +0100692 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100693 case 450:
694 return GSM_BAND_450;
695 case 480:
696 return GSM_BAND_480;
697 case 750:
698 return GSM_BAND_750;
699 case 810:
700 return GSM_BAND_810;
701 case 850:
702 return GSM_BAND_850;
703 case 900:
704 return GSM_BAND_900;
705 case 1800:
706 return GSM_BAND_1800;
707 case 1900:
708 return GSM_BAND_1900;
709 default:
710 return -EINVAL;
711 }
712}
713
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100714/*! Resolve GSM band from ARFCN.
Harald Welte96e2a002017-06-12 21:44:18 +0200715 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
716 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100717 * \param[out] band GSM Band containing \arfcn if arfcn is valid, undetermined otherwise
718 * \returns 0 if arfcn is valid and \a band was set, negative on error */
719int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band)
Harald Welte622b7182010-03-07 17:50:21 +0100720{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100721 int is_pcs = arfcn & ARFCN_PCS;
722
723 arfcn &= ~ARFCN_FLAG_MASK;
724
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100725 if (is_pcs) {
726 *band = GSM_BAND_1900;
727 return 0;
728 } else if (arfcn <= 124) {
729 *band = GSM_BAND_900;
730 return 0;
731 } else if (arfcn >= 955 && arfcn <= 1023) {
732 *band = GSM_BAND_900;
733 return 0;
734 } else if (arfcn >= 128 && arfcn <= 251) {
735 *band = GSM_BAND_850;
736 return 0;
737 } else if (arfcn >= 512 && arfcn <= 885) {
738 *band = GSM_BAND_1800;
739 return 0;
740 } else if (arfcn >= 259 && arfcn <= 293) {
741 *band = GSM_BAND_450;
742 return 0;
743 } else if (arfcn >= 306 && arfcn <= 340) {
744 *band = GSM_BAND_480;
745 return 0;
746 } else if (arfcn >= 350 && arfcn <= 425) {
747 *band = GSM_BAND_810;
748 return 0;
749 } else if (arfcn >= 438 && arfcn <= 511) {
750 *band = GSM_BAND_750;
751 return 0;
752 }
753 return -1;
754}
755
756/*! Resolve GSM band from ARFCN, aborts process on invalid ARFCN.
757 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS.
758 * DEPRECATED: Use gsm_arfcn2band_rc instead.
759 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
760 * \returns GSM Band if ARFCN is valid (part of any valid band), aborts otherwise */
761enum gsm_band gsm_arfcn2band(uint16_t arfcn)
762{
763 enum gsm_band band;
764 if (gsm_arfcn2band_rc(arfcn, &band) == 0)
765 return band;
766
767 osmo_panic("%s:%d Invalid arfcn %" PRIu16 " passed to gsm_arfcn2band\n",
768 __FILE__, __LINE__, arfcn);
Harald Welte622b7182010-03-07 17:50:21 +0100769}
770
Sylvain Munaut55720312012-12-11 23:44:41 +0100771struct gsm_freq_range {
772 uint16_t arfcn_first;
773 uint16_t arfcn_last;
774 uint16_t freq_ul_first;
775 uint16_t freq_dl_offset;
776 uint16_t flags;
777};
778
779static struct gsm_freq_range gsm_ranges[] = {
780 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
781 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
782 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
783 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
784 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
785 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
786 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
787 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
788 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
789 { /* Guard */ }
790};
791
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200792/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200793 * \param[in] arfcn GSM ARFCN to convert
794 * \param[in] uplink Uplink (1) or Downlink (0) frequency
795 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100796uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
797{
Sylvain Munaut55720312012-12-11 23:44:41 +0100798 struct gsm_freq_range *r;
799 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
800 uint16_t freq10_ul = 0xffff;
801 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100802
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100803 arfcn &= ~ARFCN_FLAG_MASK;
804
Sylvain Munaut55720312012-12-11 23:44:41 +0100805 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
806 if ((flags == r->flags) &&
807 (arfcn >= r->arfcn_first) &&
808 (arfcn <= r->arfcn_last))
809 {
810 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
811 freq10_dl = freq10_ul + r->freq_dl_offset;
812 break;
813 }
814 }
815
816 return uplink ? freq10_ul : freq10_dl;
817}
818
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200819/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200820 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
821 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
822 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100823uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
824{
825 struct gsm_freq_range *r;
826 uint16_t freq10_lo, freq10_hi;
827 uint16_t arfcn = 0xffff;
828
829 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
830 /* Generate frequency limits */
831 freq10_lo = r->freq_ul_first;
832 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
833 if (!uplink) {
834 freq10_lo += r->freq_dl_offset;
835 freq10_hi += r->freq_dl_offset;
836 }
837
838 /* Check if this fits */
839 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
840 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
841 arfcn |= r->flags;
842 break;
843 }
844 }
Harald Welte622b7182010-03-07 17:50:21 +0100845
846 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100847 arfcn |= ARFCN_UPLINK;
848
849 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100850}
851
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200852/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200853 * \param[out] time Caller-provided memory for \ref gsm_time
854 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100855void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
856{
857 time->fn = fn;
858 time->t1 = time->fn / (26*51);
859 time->t2 = time->fn % 26;
860 time->t3 = time->fn % 51;
861 time->tc = (time->fn / 51) % 8;
862}
863
Philipp Maierb808da42017-06-26 10:50:28 +0200864/*! Parse GSM Frame Number into printable string
865 * \param[in] fn GSM Frame Number
866 * \returns pointer to printable string */
867char *gsm_fn_as_gsmtime_str(uint32_t fn)
868{
869 struct gsm_time time;
870
871 gsm_fn2gsmtime(&time, fn);
872 return osmo_dump_gsmtime(&time);
873}
874
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200875/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200876 * \param[in] time GSM Time in decoded structure
877 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100878uint32_t gsm_gsmtime2fn(struct gsm_time *time)
879{
880 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
881 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
882}
Harald Weltea1c4f762010-05-01 11:59:42 +0200883
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200884char *osmo_dump_gsmtime(const struct gsm_time *tm)
885{
886 static char buf[64];
887
888 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
889 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
890 buf[sizeof(buf)-1] = '\0';
891 return buf;
892}
893
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200894/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200895 * \param[out] bv Caller-provided output bit-vector
896 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200897void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
898{
899 bitvec_set_uint(bv, r->w1_hi, 2);
900 bitvec_set_uint(bv, r->w1_lo, 8);
901 bitvec_set_uint(bv, r->w2_hi, 8);
902 bitvec_set_uint(bv, r->w2_lo, 1);
903 bitvec_set_uint(bv, r->w3_hi, 7);
904 bitvec_set_uint(bv, r->w3_lo, 2);
905 bitvec_set_uint(bv, r->w4_hi, 6);
906 bitvec_set_uint(bv, r->w4_lo, 2);
907 bitvec_set_uint(bv, r->w5_hi, 6);
908 bitvec_set_uint(bv, r->w5_lo, 2);
909 bitvec_set_uint(bv, r->w6_hi, 6);
910 bitvec_set_uint(bv, r->w6_lo, 2);
911 bitvec_set_uint(bv, r->w7_hi, 6);
912 bitvec_set_uint(bv, r->w7_lo, 2);
913 bitvec_set_uint(bv, r->w8_hi, 6);
914 bitvec_set_uint(bv, r->w8_lo, 1);
915 bitvec_set_uint(bv, r->w9, 7);
916 bitvec_set_uint(bv, r->w10, 7);
917 bitvec_set_uint(bv, r->w11_hi, 1);
918 bitvec_set_uint(bv, r->w11_lo, 6);
919 bitvec_set_uint(bv, r->w12_hi, 2);
920 bitvec_set_uint(bv, r->w12_lo, 5);
921 bitvec_set_uint(bv, r->w13_hi, 3);
922 bitvec_set_uint(bv, r->w13_lo, 4);
923 bitvec_set_uint(bv, r->w14_hi, 4);
924 bitvec_set_uint(bv, r->w14_lo, 3);
925 bitvec_set_uint(bv, r->w15_hi, 5);
926 bitvec_set_uint(bv, r->w15_lo, 2);
927 bitvec_set_uint(bv, r->w16, 6);
928}
929
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200930/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200931int gprs_tlli_type(uint32_t tlli)
932{
933 if ((tlli & 0xc0000000) == 0xc0000000)
934 return TLLI_LOCAL;
935 else if ((tlli & 0xc0000000) == 0x80000000)
936 return TLLI_FOREIGN;
937 else if ((tlli & 0xf8000000) == 0x78000000)
938 return TLLI_RANDOM;
939 else if ((tlli & 0xf8000000) == 0x70000000)
940 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200941 else if ((tlli & 0xf0000000) == 0x00000000)
942 return TLLI_G_RNTI;
943 else if ((tlli & 0xf0000000) == 0x10000000)
944 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200945
946 return TLLI_RESERVED;
947}
Harald Weltec2263172010-06-01 10:47:07 +0200948
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200949/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200950 * \param[in] p_tmsi P-TMSI
951 * \param[in] type TLLI Type we want to derive from \a p_tmsi
952 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200953uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
954{
955 uint32_t tlli;
956 switch (type) {
957 case TLLI_LOCAL:
958 tlli = p_tmsi | 0xc0000000;
959 break;
960 case TLLI_FOREIGN:
961 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
962 break;
963 default:
964 tlli = 0;
965 break;
966 }
967 return tlli;
968}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200969
970/* Wrappers for deprecated functions: */
971
972int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
973{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100974 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
975 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200976
977 /* Mimic the original behaviour. */
978 return septet_l;
979}
980
981int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
982{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100983 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
984 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200985}
986
987int gsm_7bit_encode(uint8_t *result, const char *data)
988{
989 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100990 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
991 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200992}
993
994int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
995{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100996 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
997 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200998}
999
1000int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
1001{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001002 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1003 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001004}
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001005
1006/* This is also used by osmo-hlr's db schema */
1007const struct value_string osmo_rat_type_names[] = {
1008 { OSMO_RAT_UNKNOWN, "unknown" },
1009 { OSMO_RAT_GERAN_A, "GERAN-A" },
1010 { OSMO_RAT_UTRAN_IU, "UTRAN-Iu" },
Neels Hofmeyr0d39a8d2019-01-04 04:37:00 +01001011 { OSMO_RAT_EUTRAN_SGS, "EUTRAN-SGs" },
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001012 {}
1013};