blob: 48341ae5d20f08ef97b652e3e062891040171c7d [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 *
Harald Welteec8b4502010-02-20 20:34:29 +010022 */
23
Harald Welted38c8b82011-08-30 11:32:56 +020024/*! \mainpage libosmogsm Documentation
25 *
26 * \section sec_intro Introduction
27 * This library is a collection of common code used in various
28 * GSM related sub-projects inside the Osmocom family of projects. It
29 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +020030 * a GSM TLV parser, SMS utility routines as well as
Harald Welted38c8b82011-08-30 11:32:56 +020031 * protocol definitions for a series of protocols:
32 * * Um L2 (04.06)
33 * * Um L3 (04.08)
34 * * A-bis RSL (08.58)
35 * * A-bis OML (08.59, 12.21)
36 * * A (08.08)
37 * \n\n
38 * Please note that C language projects inside Osmocom are typically
39 * single-threaded event-loop state machine designs. As such,
40 * routines in libosmogsm are not thread-safe. If you must use them in
41 * a multi-threaded context, you have to add your own locking.
42 *
Harald Welte71658802017-06-12 15:40:52 +020043 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
44 * Communications) project, a community-based, collaborative development
45 * project to create Free and Open Source implementations of mobile
46 * communications systems. For more information about Osmocom, please
47 * see https://osmocom.org/
48 *
Harald Welted38c8b82011-08-30 11:32:56 +020049 * \section sec_copyright Copyright and License
50 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
51 * All rights reserved. \n\n
52 * The source code of libosmogsm is licensed under the terms of the GNU
53 * General Public License as published by the Free Software Foundation;
54 * either version 2 of the License, or (at your option) any later
55 * version.\n
56 * See <http://www.gnu.org/licenses/> or COPYING included in the source
57 * code package istelf.\n
58 * The information detailed here is provided AS IS with NO WARRANTY OF
59 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
60 * FITNESS FOR A PARTICULAR PURPOSE.
61 * \n\n
62 *
Harald Welte71658802017-06-12 15:40:52 +020063 * \section sec_tracker Homepage + Issue Tracker
64 * libosmogsm is distributed as part of libosmocore and shares its
65 * project page at http://osmocom.org/projects/libosmocore
66 *
67 * An Issue Tracker can be found at
68 * https://osmocom.org/projects/libosmocore/issues
69 *
Harald Welted38c8b82011-08-30 11:32:56 +020070 * \section sec_contact Contact and Support
71 * Community-based support is available at the OpenBSC mailing list
72 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
73 * Commercial support options available upon request from
74 * <http://sysmocom.de/>
75 */
76
Harald Welteec8b4502010-02-20 20:34:29 +010077//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010078#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020079#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010080#include <osmocom/gsm/gsm_utils.h>
Max764b0222016-05-11 17:33:17 +020081#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020082#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010083
84#include <stdlib.h>
85#include <stdint.h>
86#include <string.h>
Max764b0222016-05-11 17:33:17 +020087#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010088#include <stdio.h>
89#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010090#include <ctype.h>
Pau Espin Pedrol363130f2017-07-03 10:42:42 +020091#include <inttypes.h>
Max4b2b0cc2017-07-10 14:32:48 +020092#include <time.h>
93#include <unistd.h>
Harald Welteec8b4502010-02-20 20:34:29 +010094
Pau Espin Pedrol88955fb2023-01-18 18:54:00 +010095#include "config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010096
Max0187c3a2018-11-09 13:08:42 +010097#if (!EMBEDDED)
Max4b2b0cc2017-07-10 14:32:48 +020098/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
Karl Koscher76f025e2019-03-11 13:19:46 -070099#ifdef __GLIBC_PREREQ
100#if __GLIBC_PREREQ(2,25)
101#define HAVE_GLIBC_GETRANDOM
102#endif /* if __GLIBC_PREREQ(2,25) */
103#endif /* ifdef __GLIBC_PREREQ */
104#ifdef HAVE_GLIBC_GETRANDOM
Max0187c3a2018-11-09 13:08:42 +0100105#pragma message ("glibc " OSMO_STRINGIFY_VAL(__GLIBC__) "." OSMO_STRINGIFY_VAL(__GLIBC_MINOR__) " random detected")
Pau Espin Pedrole2640ef2017-11-16 16:29:36 +0100106#include <sys/random.h>
Max42e567c2018-11-09 13:13:45 +0100107#undef USE_GNUTLS
Max4b2b0cc2017-07-10 14:32:48 +0200108#elif HAVE_DECL_SYS_GETRANDOM
109#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200110#ifndef GRND_NONBLOCK
111#define GRND_NONBLOCK 0x0001
Max0187c3a2018-11-09 13:08:42 +0100112#endif /* ifndef GRND_NONBLOCK */
Karl Koscher76f025e2019-03-11 13:19:46 -0700113#endif /* ifdef HAVE_GLIBC_GETRANDOM */
Max0187c3a2018-11-09 13:08:42 +0100114#endif /* !EMBEDDED */
Max4b2b0cc2017-07-10 14:32:48 +0200115
Maxed029df2017-10-26 10:56:04 +0200116#if (USE_GNUTLS)
117#pragma message ("including GnuTLS for getrandom fallback.")
118#include <gnutls/gnutls.h>
119#include <gnutls/crypto.h>
Alexander Couzens500d6332018-04-24 14:00:24 +0200120
121/* gnutls < 3.3.0 requires global init.
122 * gnutls >= 3.3.0 does it automatic.
123 * It doesn't hurt calling it twice,
124 * as long it's not done at the same time (threads).
125 */
126__attribute__((constructor))
127static void on_dso_load_gnutls(void)
128{
129 if (!gnutls_check_version("3.3.0"))
130 gnutls_global_init();
131}
132
133__attribute__((destructor))
134static void on_dso_unload_gnutls(void)
135{
136 if (!gnutls_check_version("3.3.0"))
137 gnutls_global_deinit();
138}
Max0187c3a2018-11-09 13:08:42 +0100139
140#endif /* if (USE_GNUTLS) */
Maxed029df2017-10-26 10:56:04 +0200141
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800142/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
143 * Greek symbols at hex positions 0x10 and 0x12-0x1a
144 * left out as they can't be handled with a char and
145 * since most phones don't display or write these
146 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200147 * more complex.
148 *
149 * Note that this table contains the latin1->7bit mapping _and_ has
150 * been merged with the reverse mapping (7bit->latin1) for the
151 * extended characters at offset 0x7f.
152 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800153static unsigned char gsm_7bit_alphabet[] = {
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
157 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
158 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
159 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
160 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
161 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
162 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
163 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
165 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
167 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
168 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
169 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
170 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
171};
172
Nico Golde28de0532010-07-09 17:19:12 +0200173/* GSM 03.38 6.2.1 Character lookup for decoding */
174static int gsm_septet_lookup(uint8_t ch)
175{
176 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200177 for (; i < sizeof(gsm_7bit_alphabet); i++) {
178 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200179 return i;
180 }
181 return -1;
182}
183
Vadim Yanitskiyed8e2632019-04-07 03:20:55 +0700184/*! Compute number of octets from number of septets.
185 * For instance: 47 septets need 41,125 = 42 octets.
186 * \param[in] sept_len Number of septets
187 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200188uint8_t gsm_get_octet_len(const uint8_t sept_len){
189 int octet_len = (sept_len * 7) / 8;
190 if ((sept_len * 7) % 8 != 0)
191 octet_len++;
192
193 return octet_len;
194}
195
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200196/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200197 * \param[out] text Caller-provided output text buffer
198 * \param[in] n Length of \a text
199 * \param[in] user_data Input Data (septets)
200 * \param[in] septet_l Number of septets in \a user_data
201 * \param[in] ud_hdr_ind User Data Header present in data
202 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200203int 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 +0100204{
Maxcf37c4c2016-01-21 16:52:40 +0100205 unsigned shift = 0;
206 uint8_t c7, c8, next_is_ext = 0, lu, ru;
207 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200208 const char *text_buf_begin = text;
209 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200210
211 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100212
Dennis Wehrle291e6132011-07-24 20:14:13 +0200213 /* skip the user data header */
214 if (ud_hdr_ind) {
215 /* get user data header length + 1 (for the 'user data header length'-field) */
216 shift = ((user_data[0] + 1) * 8) / 7;
217 if ((((user_data[0] + 1) * 8) % 7) != 0)
218 shift++;
219 septet_l = septet_l - shift;
220 }
221
Maxcf37c4c2016-01-21 16:52:40 +0100222 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200223 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100224
225 l = ((i + shift) * 7 + 7) >> 3;
226 r = ((i + shift) * 7) >> 3;
227
228 /* the left side index is always >= right side index
229 sometimes it even gets beyond array boundary
230 check for that explicitly and force 0 instead
231 */
232 if (l >= maxlen)
233 lu = 0;
234 else
235 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
236
237 ru = user_data[r] >> (((i + shift) * 7) & 7);
238
239 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200240
Harald Weltebe55a8b2012-09-20 10:00:25 +0200241 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200242 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200243 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200244 c8 = gsm_7bit_alphabet[0x7f + c7];
245 } else if (c7 == 0x1b && i + 1 < septet_l) {
246 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200247 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200248 } else {
249 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200250 }
251
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200252 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100253 }
254
Nico Golde28de0532010-07-09 17:19:12 +0200255 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200256
Maxcf37c4c2016-01-21 16:52:40 +0100257 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200258}
259
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200260/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200261int 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 +0200262{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200263 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200264}
265
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200266/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200267int 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 +0200268{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200269 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200270
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200271 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200272 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200273 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
274 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200275
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200276 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200277}
278
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200279/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200280 *
281 * This function converts a zero-terminated input string \a data from
282 * ASCII into octet-aligned 7-bit GSM characters. No packing is
283 * performed.
284 *
285 * \param[out] result caller-allocated output buffer
286 * \param[in] data input data, ASCII
287 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200288int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200289{
290 int i, y = 0;
291 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200292 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200293 ch = data[i];
294 switch(ch){
295 /* fall-through for extension characters */
296 case 0x0c:
297 case 0x5e:
298 case 0x7b:
299 case 0x7d:
300 case 0x5c:
301 case 0x5b:
302 case 0x7e:
303 case 0x5d:
304 case 0x7c:
305 result[y++] = 0x1b;
Vadim Yanitskiy46914742019-04-12 22:42:42 +0700306 /* fall-through */
Nico Golde28de0532010-07-09 17:19:12 +0200307 default:
308 result[y] = gsm_7bit_alphabet[ch];
309 break;
310 }
311 y++;
312 }
313
314 return y;
315}
316
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200317/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200318 * \param[out] result Caller-provided output buffer
319 * \param[in] rdata Input data septets
320 * \param[in] septet_len Length of \a rdata
321 * \param[in] padding padding bits at start
322 * \returns number of bytes used in \a result */
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100323int gsm_septet_pack(uint8_t *result, const uint8_t *rdata, size_t septet_len, uint8_t padding)
Harald Welteca693882013-03-13 15:10:55 +0100324{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200325 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200326 uint8_t cb, nb;
327 int shift = 0;
Vadim Yanitskiy846db1b2021-01-30 01:22:03 +0100328 uint8_t *data = malloc(septet_len + 1);
Nico Golde28de0532010-07-09 17:19:12 +0200329
Dennis Wehrle291e6132011-07-24 20:14:13 +0200330 if (padding) {
331 shift = 7 - padding;
332 /* the first zero is needed for padding */
333 memcpy(data + 1, rdata, septet_len);
Vadim Yanitskiy846db1b2021-01-30 01:22:03 +0100334 data[0] = 0x00;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200335 septet_len++;
336 } else
337 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200338
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200339 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200340 if (shift == 7) {
341 /*
342 * special end case with the. This is necessary if the
343 * last septet fits into the previous octet. E.g. 48
344 * non-extension characters:
345 * ....ag ( a = 1100001, g = 1100111)
346 * result[40] = 100001 XX, result[41] = 1100111 1 */
347 if (i + 1 < septet_len) {
348 shift = 0;
349 continue;
350 } else if (i + 1 == septet_len)
351 break;
Nico Golde28de0532010-07-09 17:19:12 +0200352 }
353
Dennis Wehrle291e6132011-07-24 20:14:13 +0200354 cb = (data[i] & 0x7f) >> shift;
355 if (i + 1 < septet_len) {
356 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200357 cb = cb | nb;
358 }
359
360 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200361 shift++;
362 }
363
Dennis Wehrle291e6132011-07-24 20:14:13 +0200364 free(data);
365
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200366 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100367}
368
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100369/*! Backwards compatibility wrapper for gsm_septets_pack(), deprecated. */
370int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
371{
372 return gsm_septet_pack(result, rdata, septet_len, padding);
373}
374
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200375/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200376 * \param[out] result Caller-provided output buffer
377 * \param[in] n Maximum length of \a result in bytes
378 * \param[in] data octet-aligned string
379 * \param[out] octets Number of octets encoded
380 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200381int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200382{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200383 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200384 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100385 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200386
Dennis Wehrle291e6132011-07-24 20:14:13 +0200387 /* prepare for the worst case, every character expanding to two bytes */
Vadim Yanitskiy846db1b2021-01-30 01:22:03 +0100388 uint8_t *rdata = malloc(strlen(data) * 2);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200389 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200390
391 if (y > max_septets) {
392 /*
393 * Limit the number of septets to avoid the generation
394 * of more than n octets.
395 */
396 y = max_septets;
397 }
398
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100399 o = gsm_septet_pack(result, rdata, y, 0);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200400
401 if (octets)
402 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200403
404 free(rdata);
405
406 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200407 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200408 * unique. E.g.:
409 * 1.) 46 non-extension characters + 1 extension character
410 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
411 * 2.) 47 non-extension characters
412 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
413 * 3.) 48 non-extension characters
414 * => (48 * 7 bit) / 8 bit = 42 octects
415 */
416 return y;
417}
418
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200419/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200420 * \param[out] result Caller-provided output buffer
421 * \param[in] n Maximum length of \a result in bytes
422 * \param[in] data octet-aligned string
423 * \param[out] octets Number of octets encoded
424 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200425int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
426{
427 int y;
428
429 y = gsm_7bit_encode_n(result, n, data, octets);
430 /* if last octet contains only one bit, add <CR> */
431 if (((y * 7) & 7) == 1)
432 result[(*octets) - 1] |= ('\r' << 1);
433 /* if last character is <CR> and completely fills last octet, add
434 * another <CR>. */
435 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
436 result[(*octets)++] = '\r';
437 y++;
438 }
439
440 return y;
441}
442
Max4b2b0cc2017-07-10 14:32:48 +0200443/*! Generate random identifier
444 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
445 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
446 * See also RFC4086.
447 * \param[out] out Buffer to be filled with random data
448 * \param[in] len Number of random bytes required
449 * \returns 0 on success, or a negative error code on error.
450 */
451int osmo_get_rand_id(uint8_t *out, size_t len)
452{
Maxed029df2017-10-26 10:56:04 +0200453 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200454
455 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
456 if (len > OSMO_MAX_RAND_ID_LEN)
457 return -E2BIG;
Max0187c3a2018-11-09 13:08:42 +0100458#if (!EMBEDDED)
Karl Koscher76f025e2019-03-11 13:19:46 -0700459#ifdef HAVE_GLIBC_GETRANDOM
Max4b2b0cc2017-07-10 14:32:48 +0200460 rc = getrandom(out, len, GRND_NONBLOCK);
461#elif HAVE_DECL_SYS_GETRANDOM
462#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
463 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
464 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200465#endif
Max0187c3a2018-11-09 13:08:42 +0100466#endif /* !EMBEDDED */
Maxed029df2017-10-26 10:56:04 +0200467
Max4b2b0cc2017-07-10 14:32:48 +0200468 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200469 if (rc < 0) {
470#if (USE_GNUTLS)
Maxed029df2017-10-26 10:56:04 +0200471 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
Harald Weltedd0d76b2019-07-21 12:08:22 +0200472#else
Max4b2b0cc2017-07-10 14:32:48 +0200473 return -errno;
Harald Weltedd0d76b2019-07-21 12:08:22 +0200474#endif
Maxed029df2017-10-26 10:56:04 +0200475 }
Max4b2b0cc2017-07-10 14:32:48 +0200476
477 /* getrandom() failed partially due to signal interruption:
478 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
479 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
480 if (rc != len)
481 return -EAGAIN;
482
483 return 0;
484}
485
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200486/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200487 * \param[in] mru Unidirectional measurement report structure
488 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
489 * period
490 * \param[out] buf Pre-allocated bufer for storing IE
491 * \returns Number of bytes filled in buf
492 */
Pau Espin Pedrol50e6f062021-09-28 11:32:00 +0200493size_t gsm0858_rsl_ul_meas_enc(const struct gsm_meas_rep_unidir *mru, bool dtxd_used,
Max764b0222016-05-11 17:33:17 +0200494 uint8_t *buf)
495{
496 buf[0] = dtxd_used ? (1 << 6) : 0;
497 buf[0] |= (mru->full.rx_lev & 0x3f);
498 buf[1] = (mru->sub.rx_lev & 0x3f);
499 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
500
501 return 3;
502}
503
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200504/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200505 * \param[in] band GSM frequency band
506 * \param[in] class GSM power class
Pau Espin Pedrole40b9632019-10-31 15:38:30 +0100507 * \returns maximum transmit power of power class in dBm, negative on error */
508int ms_class_gmsk_dbm(enum gsm_band band, int class)
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200509{
510 switch (band) {
511 case GSM_BAND_450:
512 case GSM_BAND_480:
513 case GSM_BAND_750:
514 case GSM_BAND_900:
515 case GSM_BAND_810:
516 case GSM_BAND_850:
517 if (class == 1)
518 return 43; /* 20W */
519 if (class == 2)
520 return 39; /* 8W */
521 if (class == 3)
522 return 37; /* 5W */
523 if (class == 4)
524 return 33; /* 2W */
525 if (class == 5)
526 return 29; /* 0.8W */
527 break;
528 case GSM_BAND_1800:
529 if (class == 1)
530 return 30; /* 1W */
531 if (class == 2)
532 return 24; /* 0.25W */
533 if (class == 3)
534 return 36; /* 4W */
535 break;
536 case GSM_BAND_1900:
537 if (class == 1)
538 return 30; /* 1W */
539 if (class == 2)
540 return 24; /* 0.25W */
541 if (class == 3)
542 return 33; /* 2W */
543 break;
544 }
545 return -EINVAL;
546}
547
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200548/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200549 * by the tables in chapter 4.1.1 of GSM TS 05.05
550 * \param[in] GSM frequency band
551 * \param[in] dbm RF power value in dBm
552 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100553int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
554{
555 switch (band) {
556 case GSM_BAND_450:
557 case GSM_BAND_480:
558 case GSM_BAND_750:
559 case GSM_BAND_900:
560 case GSM_BAND_810:
561 case GSM_BAND_850:
562 if (dbm >= 39)
563 return 0;
564 else if (dbm < 5)
565 return 19;
566 else {
567 /* we are guaranteed to have (5 <= dbm < 39) */
568 return 2 + ((39 - dbm) / 2);
569 }
570 break;
571 case GSM_BAND_1800:
572 if (dbm >= 36)
573 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200574 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100575 return 30;
576 else if (dbm >= 32)
577 return 31;
578 else if (dbm == 31)
579 return 0;
580 else {
581 /* we are guaranteed to have (0 <= dbm < 31) */
582 return (30 - dbm) / 2;
583 }
584 break;
585 case GSM_BAND_1900:
586 if (dbm >= 33)
587 return 30;
588 else if (dbm >= 32)
589 return 31;
590 else if (dbm == 31)
591 return 0;
592 else {
593 /* we are guaranteed to have (0 <= dbm < 31) */
594 return (30 - dbm) / 2;
595 }
596 break;
597 }
598 return -EINVAL;
599}
600
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200601/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200602 * \param[in] band GSM frequency band
603 * \param[in] lvl TS 05.05 power control level
604 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100605int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
606{
607 lvl &= 0x1f;
608
609 switch (band) {
610 case GSM_BAND_450:
611 case GSM_BAND_480:
612 case GSM_BAND_750:
613 case GSM_BAND_900:
614 case GSM_BAND_810:
615 case GSM_BAND_850:
616 if (lvl < 2)
617 return 39;
618 else if (lvl < 20)
619 return 39 - ((lvl - 2) * 2) ;
620 else
621 return 5;
622 break;
623 case GSM_BAND_1800:
624 if (lvl < 16)
625 return 30 - (lvl * 2);
626 else if (lvl < 29)
627 return 0;
628 else
629 return 36 - ((lvl - 29) * 2);
630 break;
631 case GSM_BAND_1900:
632 if (lvl < 16)
633 return 30 - (lvl * 2);
634 else if (lvl < 30)
635 return -EINVAL;
636 else
637 return 33 - (lvl - 30);
638 break;
639 }
640 return -EINVAL;
641}
642
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200643/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200644 * \param[in] rxlev TS 05.08 RxLev value
645 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100646int rxlev2dbm(uint8_t rxlev)
647{
648 if (rxlev > 63)
649 rxlev = 63;
650
651 return -110 + rxlev;
652}
653
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200654/*! 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 +0200655 * \param[in] dbm RF signal level in dBm
656 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100657uint8_t dbm2rxlev(int dbm)
658{
659 int rxlev = dbm + 110;
660
661 if (rxlev > 63)
662 rxlev = 63;
663 else if (rxlev < 0)
664 rxlev = 0;
665
666 return rxlev;
667}
668
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200669/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800670const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100671{
672 switch (band) {
673 case GSM_BAND_450:
674 return "GSM450";
675 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200676 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100677 case GSM_BAND_750:
678 return "GSM750";
679 case GSM_BAND_810:
680 return "GSM810";
681 case GSM_BAND_850:
682 return "GSM850";
683 case GSM_BAND_900:
684 return "GSM900";
685 case GSM_BAND_1800:
686 return "DCS1800";
687 case GSM_BAND_1900:
688 return "PCS1900";
689 }
690 return "invalid";
691}
692
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200693/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100694enum gsm_band gsm_band_parse(const char* mhz)
695{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200696 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100697 mhz++;
698
699 if (*mhz == '\0')
700 return -EINVAL;
701
Harald Welted3ff15f2010-03-07 18:23:47 +0100702 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100703 case 450:
704 return GSM_BAND_450;
705 case 480:
706 return GSM_BAND_480;
707 case 750:
708 return GSM_BAND_750;
709 case 810:
710 return GSM_BAND_810;
711 case 850:
712 return GSM_BAND_850;
713 case 900:
714 return GSM_BAND_900;
715 case 1800:
716 return GSM_BAND_1800;
717 case 1900:
718 return GSM_BAND_1900;
719 default:
720 return -EINVAL;
721 }
722}
723
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100724/*! Resolve GSM band from ARFCN.
Harald Welte96e2a002017-06-12 21:44:18 +0200725 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
726 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100727 * \param[out] band GSM Band containing \arfcn if arfcn is valid, undetermined otherwise
728 * \returns 0 if arfcn is valid and \a band was set, negative on error */
729int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band)
Harald Welte622b7182010-03-07 17:50:21 +0100730{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100731 int is_pcs = arfcn & ARFCN_PCS;
732
733 arfcn &= ~ARFCN_FLAG_MASK;
734
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100735 if (is_pcs) {
736 *band = GSM_BAND_1900;
737 return 0;
738 } else if (arfcn <= 124) {
739 *band = GSM_BAND_900;
740 return 0;
741 } else if (arfcn >= 955 && arfcn <= 1023) {
742 *band = GSM_BAND_900;
743 return 0;
744 } else if (arfcn >= 128 && arfcn <= 251) {
745 *band = GSM_BAND_850;
746 return 0;
747 } else if (arfcn >= 512 && arfcn <= 885) {
748 *band = GSM_BAND_1800;
749 return 0;
750 } else if (arfcn >= 259 && arfcn <= 293) {
751 *band = GSM_BAND_450;
752 return 0;
753 } else if (arfcn >= 306 && arfcn <= 340) {
754 *band = GSM_BAND_480;
755 return 0;
756 } else if (arfcn >= 350 && arfcn <= 425) {
757 *band = GSM_BAND_810;
758 return 0;
759 } else if (arfcn >= 438 && arfcn <= 511) {
760 *band = GSM_BAND_750;
761 return 0;
762 }
763 return -1;
764}
765
766/*! Resolve GSM band from ARFCN, aborts process on invalid ARFCN.
767 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS.
768 * DEPRECATED: Use gsm_arfcn2band_rc instead.
769 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
770 * \returns GSM Band if ARFCN is valid (part of any valid band), aborts otherwise */
771enum gsm_band gsm_arfcn2band(uint16_t arfcn)
772{
773 enum gsm_band band;
774 if (gsm_arfcn2band_rc(arfcn, &band) == 0)
775 return band;
776
777 osmo_panic("%s:%d Invalid arfcn %" PRIu16 " passed to gsm_arfcn2band\n",
778 __FILE__, __LINE__, arfcn);
Harald Welte622b7182010-03-07 17:50:21 +0100779}
780
Sylvain Munaut55720312012-12-11 23:44:41 +0100781struct gsm_freq_range {
782 uint16_t arfcn_first;
783 uint16_t arfcn_last;
784 uint16_t freq_ul_first;
785 uint16_t freq_dl_offset;
786 uint16_t flags;
787};
788
789static struct gsm_freq_range gsm_ranges[] = {
790 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
791 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
792 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
793 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
794 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
795 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
796 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
797 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
798 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
799 { /* Guard */ }
800};
801
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200802/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200803 * \param[in] arfcn GSM ARFCN to convert
804 * \param[in] uplink Uplink (1) or Downlink (0) frequency
805 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100806uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
807{
Sylvain Munaut55720312012-12-11 23:44:41 +0100808 struct gsm_freq_range *r;
809 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
810 uint16_t freq10_ul = 0xffff;
811 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100812
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100813 arfcn &= ~ARFCN_FLAG_MASK;
814
Sylvain Munaut55720312012-12-11 23:44:41 +0100815 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
816 if ((flags == r->flags) &&
817 (arfcn >= r->arfcn_first) &&
818 (arfcn <= r->arfcn_last))
819 {
820 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
821 freq10_dl = freq10_ul + r->freq_dl_offset;
822 break;
823 }
824 }
825
826 return uplink ? freq10_ul : freq10_dl;
827}
828
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200829/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200830 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
831 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
832 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100833uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
834{
835 struct gsm_freq_range *r;
836 uint16_t freq10_lo, freq10_hi;
837 uint16_t arfcn = 0xffff;
838
839 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
840 /* Generate frequency limits */
841 freq10_lo = r->freq_ul_first;
842 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
843 if (!uplink) {
844 freq10_lo += r->freq_dl_offset;
845 freq10_hi += r->freq_dl_offset;
846 }
847
848 /* Check if this fits */
849 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
850 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
851 arfcn |= r->flags;
852 break;
853 }
854 }
Harald Welte622b7182010-03-07 17:50:21 +0100855
856 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100857 arfcn |= ARFCN_UPLINK;
858
859 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100860}
861
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200862/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200863 * \param[out] time Caller-provided memory for \ref gsm_time
864 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100865void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
866{
867 time->fn = fn;
868 time->t1 = time->fn / (26*51);
869 time->t2 = time->fn % 26;
870 time->t3 = time->fn % 51;
871 time->tc = (time->fn / 51) % 8;
872}
873
Philipp Maierb808da42017-06-26 10:50:28 +0200874/*! Parse GSM Frame Number into printable string
875 * \param[in] fn GSM Frame Number
876 * \returns pointer to printable string */
877char *gsm_fn_as_gsmtime_str(uint32_t fn)
878{
879 struct gsm_time time;
880
881 gsm_fn2gsmtime(&time, fn);
882 return osmo_dump_gsmtime(&time);
883}
884
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200885/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200886 * \param[in] time GSM Time in decoded structure
887 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100888uint32_t gsm_gsmtime2fn(struct gsm_time *time)
889{
Philipp Maiera13d5662023-01-12 12:58:11 +0100890 uint32_t fn;
891
892 /* See also:
893 * 3GPP TS 44.018, section 10.5.2.38, 3GPP TS 45.002 section 4.3.3, and
894 * 3GPP TS 48.058, section 9.3.8 */
895 fn = 51 * OSMO_MOD_FLR((time->t3-time->t2), 26) + time->t3 + 51 * 26 * time->t1;
896
897 /* Note: Corrupted input values may cause a resulting frame number
898 * larger then the maximum permitted value of GSM_MAX_FN. Even though
899 * the caller is expected to check the input values beforehand we must
900 * make sure that the result cannot exceed the value range of a valid
901 * GSM frame number. */
902 return fn % GSM_MAX_FN;
Harald Welte622b7182010-03-07 17:50:21 +0100903}
Harald Weltea1c4f762010-05-01 11:59:42 +0200904
Harald Welte4a62eda2019-03-18 18:27:00 +0100905char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm)
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200906{
Harald Welte4a62eda2019-03-18 18:27:00 +0100907 snprintf(buf, buf_len, "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200908 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
Philipp Maiere8461e42019-04-08 12:07:36 +0200909 buf[buf_len-1] = '\0';
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200910 return buf;
911}
912
Harald Welte4a62eda2019-03-18 18:27:00 +0100913char *osmo_dump_gsmtime(const struct gsm_time *tm)
914{
Harald Welte171ef822019-03-28 10:49:05 +0100915 static __thread char buf[64];
Harald Welte4a62eda2019-03-18 18:27:00 +0100916 return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm);
917}
918
Harald Welte179f3572019-03-18 18:38:47 +0100919char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm)
920{
921 char *buf = talloc_size(ctx, 64);
922 if (!buf)
923 return NULL;
924 return osmo_dump_gsmtime_buf(buf, 64, tm);
925}
Harald Welte4a62eda2019-03-18 18:27:00 +0100926
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200927/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200928 * \param[out] bv Caller-provided output bit-vector
929 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200930void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
931{
932 bitvec_set_uint(bv, r->w1_hi, 2);
933 bitvec_set_uint(bv, r->w1_lo, 8);
934 bitvec_set_uint(bv, r->w2_hi, 8);
935 bitvec_set_uint(bv, r->w2_lo, 1);
936 bitvec_set_uint(bv, r->w3_hi, 7);
937 bitvec_set_uint(bv, r->w3_lo, 2);
938 bitvec_set_uint(bv, r->w4_hi, 6);
939 bitvec_set_uint(bv, r->w4_lo, 2);
940 bitvec_set_uint(bv, r->w5_hi, 6);
941 bitvec_set_uint(bv, r->w5_lo, 2);
942 bitvec_set_uint(bv, r->w6_hi, 6);
943 bitvec_set_uint(bv, r->w6_lo, 2);
944 bitvec_set_uint(bv, r->w7_hi, 6);
945 bitvec_set_uint(bv, r->w7_lo, 2);
946 bitvec_set_uint(bv, r->w8_hi, 6);
947 bitvec_set_uint(bv, r->w8_lo, 1);
948 bitvec_set_uint(bv, r->w9, 7);
949 bitvec_set_uint(bv, r->w10, 7);
950 bitvec_set_uint(bv, r->w11_hi, 1);
951 bitvec_set_uint(bv, r->w11_lo, 6);
952 bitvec_set_uint(bv, r->w12_hi, 2);
953 bitvec_set_uint(bv, r->w12_lo, 5);
954 bitvec_set_uint(bv, r->w13_hi, 3);
955 bitvec_set_uint(bv, r->w13_lo, 4);
956 bitvec_set_uint(bv, r->w14_hi, 4);
957 bitvec_set_uint(bv, r->w14_lo, 3);
958 bitvec_set_uint(bv, r->w15_hi, 5);
959 bitvec_set_uint(bv, r->w15_lo, 2);
960 bitvec_set_uint(bv, r->w16, 6);
961}
962
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200963/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200964int gprs_tlli_type(uint32_t tlli)
965{
966 if ((tlli & 0xc0000000) == 0xc0000000)
967 return TLLI_LOCAL;
968 else if ((tlli & 0xc0000000) == 0x80000000)
969 return TLLI_FOREIGN;
970 else if ((tlli & 0xf8000000) == 0x78000000)
971 return TLLI_RANDOM;
972 else if ((tlli & 0xf8000000) == 0x70000000)
973 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200974 else if ((tlli & 0xf0000000) == 0x00000000)
975 return TLLI_G_RNTI;
976 else if ((tlli & 0xf0000000) == 0x10000000)
977 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200978
979 return TLLI_RESERVED;
980}
Harald Weltec2263172010-06-01 10:47:07 +0200981
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200982/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200983 * \param[in] p_tmsi P-TMSI
984 * \param[in] type TLLI Type we want to derive from \a p_tmsi
985 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200986uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
987{
988 uint32_t tlli;
989 switch (type) {
990 case TLLI_LOCAL:
991 tlli = p_tmsi | 0xc0000000;
992 break;
993 case TLLI_FOREIGN:
994 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
995 break;
996 default:
997 tlli = 0;
998 break;
999 }
1000 return tlli;
1001}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001002
1003/* Wrappers for deprecated functions: */
1004
1005int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
1006{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001007 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1008 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001009
1010 /* Mimic the original behaviour. */
1011 return septet_l;
1012}
1013
1014int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
1015{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001016 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1017 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001018}
1019
1020int gsm_7bit_encode(uint8_t *result, const char *data)
1021{
1022 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001023 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1024 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001025}
1026
1027int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
1028{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001029 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1030 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001031}
1032
1033int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
1034{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001035 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1036 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001037}
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001038
1039/* This is also used by osmo-hlr's db schema */
1040const struct value_string osmo_rat_type_names[] = {
1041 { OSMO_RAT_UNKNOWN, "unknown" },
1042 { OSMO_RAT_GERAN_A, "GERAN-A" },
1043 { OSMO_RAT_UTRAN_IU, "UTRAN-Iu" },
Neels Hofmeyr0d39a8d2019-01-04 04:37:00 +01001044 { OSMO_RAT_EUTRAN_SGS, "EUTRAN-SGs" },
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001045 {}
1046};