blob: 07e082d359ab4ef7f933bc1ccdaac0851e45ec2b [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: */
Karl Koscher76f025e2019-03-11 13:19:46 -0700103#ifdef __GLIBC_PREREQ
104#if __GLIBC_PREREQ(2,25)
105#define HAVE_GLIBC_GETRANDOM
106#endif /* if __GLIBC_PREREQ(2,25) */
107#endif /* ifdef __GLIBC_PREREQ */
108#ifdef HAVE_GLIBC_GETRANDOM
Max0187c3a2018-11-09 13:08:42 +0100109#pragma message ("glibc " OSMO_STRINGIFY_VAL(__GLIBC__) "." OSMO_STRINGIFY_VAL(__GLIBC_MINOR__) " random detected")
Pau Espin Pedrole2640ef2017-11-16 16:29:36 +0100110#include <sys/random.h>
Max42e567c2018-11-09 13:13:45 +0100111#undef USE_GNUTLS
Max4b2b0cc2017-07-10 14:32:48 +0200112#elif HAVE_DECL_SYS_GETRANDOM
113#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200114#ifndef GRND_NONBLOCK
115#define GRND_NONBLOCK 0x0001
Max0187c3a2018-11-09 13:08:42 +0100116#endif /* ifndef GRND_NONBLOCK */
Karl Koscher76f025e2019-03-11 13:19:46 -0700117#endif /* ifdef HAVE_GLIBC_GETRANDOM */
Max0187c3a2018-11-09 13:08:42 +0100118#endif /* !EMBEDDED */
Max4b2b0cc2017-07-10 14:32:48 +0200119
Maxed029df2017-10-26 10:56:04 +0200120#if (USE_GNUTLS)
121#pragma message ("including GnuTLS for getrandom fallback.")
122#include <gnutls/gnutls.h>
123#include <gnutls/crypto.h>
Alexander Couzens500d6332018-04-24 14:00:24 +0200124
125/* gnutls < 3.3.0 requires global init.
126 * gnutls >= 3.3.0 does it automatic.
127 * It doesn't hurt calling it twice,
128 * as long it's not done at the same time (threads).
129 */
130__attribute__((constructor))
131static void on_dso_load_gnutls(void)
132{
133 if (!gnutls_check_version("3.3.0"))
134 gnutls_global_init();
135}
136
137__attribute__((destructor))
138static void on_dso_unload_gnutls(void)
139{
140 if (!gnutls_check_version("3.3.0"))
141 gnutls_global_deinit();
142}
Max0187c3a2018-11-09 13:08:42 +0100143
144#endif /* if (USE_GNUTLS) */
Maxed029df2017-10-26 10:56:04 +0200145
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800146/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
147 * Greek symbols at hex positions 0x10 and 0x12-0x1a
148 * left out as they can't be handled with a char and
149 * since most phones don't display or write these
150 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200151 * more complex.
152 *
153 * Note that this table contains the latin1->7bit mapping _and_ has
154 * been merged with the reverse mapping (7bit->latin1) for the
155 * extended characters at offset 0x7f.
156 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800157static unsigned char gsm_7bit_alphabet[] = {
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
161 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
162 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
163 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
164 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
165 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
166 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
167 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
169 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
171 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
172 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
173 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
174 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
175};
176
Nico Golde28de0532010-07-09 17:19:12 +0200177/* GSM 03.38 6.2.1 Character lookup for decoding */
178static int gsm_septet_lookup(uint8_t ch)
179{
180 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200181 for (; i < sizeof(gsm_7bit_alphabet); i++) {
182 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200183 return i;
184 }
185 return -1;
186}
187
Vadim Yanitskiyed8e2632019-04-07 03:20:55 +0700188/*! Compute number of octets from number of septets.
189 * For instance: 47 septets need 41,125 = 42 octets.
190 * \param[in] sept_len Number of septets
191 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200192uint8_t gsm_get_octet_len(const uint8_t sept_len){
193 int octet_len = (sept_len * 7) / 8;
194 if ((sept_len * 7) % 8 != 0)
195 octet_len++;
196
197 return octet_len;
198}
199
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200200/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200201 * \param[out] text Caller-provided output text buffer
202 * \param[in] n Length of \a text
203 * \param[in] user_data Input Data (septets)
204 * \param[in] septet_l Number of septets in \a user_data
205 * \param[in] ud_hdr_ind User Data Header present in data
206 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200207int 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 +0100208{
Maxcf37c4c2016-01-21 16:52:40 +0100209 unsigned shift = 0;
210 uint8_t c7, c8, next_is_ext = 0, lu, ru;
211 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200212 const char *text_buf_begin = text;
213 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200214
215 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100216
Dennis Wehrle291e6132011-07-24 20:14:13 +0200217 /* skip the user data header */
218 if (ud_hdr_ind) {
219 /* get user data header length + 1 (for the 'user data header length'-field) */
220 shift = ((user_data[0] + 1) * 8) / 7;
221 if ((((user_data[0] + 1) * 8) % 7) != 0)
222 shift++;
223 septet_l = septet_l - shift;
224 }
225
Maxcf37c4c2016-01-21 16:52:40 +0100226 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200227 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100228
229 l = ((i + shift) * 7 + 7) >> 3;
230 r = ((i + shift) * 7) >> 3;
231
232 /* the left side index is always >= right side index
233 sometimes it even gets beyond array boundary
234 check for that explicitly and force 0 instead
235 */
236 if (l >= maxlen)
237 lu = 0;
238 else
239 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
240
241 ru = user_data[r] >> (((i + shift) * 7) & 7);
242
243 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200244
Harald Weltebe55a8b2012-09-20 10:00:25 +0200245 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200246 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200247 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200248 c8 = gsm_7bit_alphabet[0x7f + c7];
249 } else if (c7 == 0x1b && i + 1 < septet_l) {
250 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200251 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200252 } else {
253 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200254 }
255
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200256 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100257 }
258
Nico Golde28de0532010-07-09 17:19:12 +0200259 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200260
Maxcf37c4c2016-01-21 16:52:40 +0100261 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200262}
263
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200264/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200265int 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 +0200266{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200267 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200268}
269
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200270/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200271int 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 +0200272{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200273 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200274
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200275 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200276 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200277 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
278 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200279
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200280 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200281}
282
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200283/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200284 *
285 * This function converts a zero-terminated input string \a data from
286 * ASCII into octet-aligned 7-bit GSM characters. No packing is
287 * performed.
288 *
289 * \param[out] result caller-allocated output buffer
290 * \param[in] data input data, ASCII
291 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200292int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200293{
294 int i, y = 0;
295 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200296 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200297 ch = data[i];
298 switch(ch){
299 /* fall-through for extension characters */
300 case 0x0c:
301 case 0x5e:
302 case 0x7b:
303 case 0x7d:
304 case 0x5c:
305 case 0x5b:
306 case 0x7e:
307 case 0x5d:
308 case 0x7c:
309 result[y++] = 0x1b;
Vadim Yanitskiy46914742019-04-12 22:42:42 +0700310 /* fall-through */
Nico Golde28de0532010-07-09 17:19:12 +0200311 default:
312 result[y] = gsm_7bit_alphabet[ch];
313 break;
314 }
315 y++;
316 }
317
318 return y;
319}
320
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200321/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200322 * \param[out] result Caller-provided output buffer
323 * \param[in] rdata Input data septets
324 * \param[in] septet_len Length of \a rdata
325 * \param[in] padding padding bits at start
326 * \returns number of bytes used in \a result */
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100327int gsm_septet_pack(uint8_t *result, const uint8_t *rdata, size_t septet_len, uint8_t padding)
Harald Welteca693882013-03-13 15:10:55 +0100328{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200329 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200330 uint8_t cb, nb;
331 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200332 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200333
Dennis Wehrle291e6132011-07-24 20:14:13 +0200334 if (padding) {
335 shift = 7 - padding;
336 /* the first zero is needed for padding */
337 memcpy(data + 1, rdata, septet_len);
338 septet_len++;
339 } else
340 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200341
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200342 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200343 if (shift == 7) {
344 /*
345 * special end case with the. This is necessary if the
346 * last septet fits into the previous octet. E.g. 48
347 * non-extension characters:
348 * ....ag ( a = 1100001, g = 1100111)
349 * result[40] = 100001 XX, result[41] = 1100111 1 */
350 if (i + 1 < septet_len) {
351 shift = 0;
352 continue;
353 } else if (i + 1 == septet_len)
354 break;
Nico Golde28de0532010-07-09 17:19:12 +0200355 }
356
Dennis Wehrle291e6132011-07-24 20:14:13 +0200357 cb = (data[i] & 0x7f) >> shift;
358 if (i + 1 < septet_len) {
359 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200360 cb = cb | nb;
361 }
362
363 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200364 shift++;
365 }
366
Dennis Wehrle291e6132011-07-24 20:14:13 +0200367 free(data);
368
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200369 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100370}
371
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100372/*! Backwards compatibility wrapper for gsm_septets_pack(), deprecated. */
373int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
374{
375 return gsm_septet_pack(result, rdata, septet_len, padding);
376}
377
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200378/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200379 * \param[out] result Caller-provided output buffer
380 * \param[in] n Maximum length of \a result in bytes
381 * \param[in] data octet-aligned string
382 * \param[out] octets Number of octets encoded
383 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200384int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200385{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200386 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200387 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100388 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200389
Dennis Wehrle291e6132011-07-24 20:14:13 +0200390 /* prepare for the worst case, every character expanding to two bytes */
391 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
392 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200393
394 if (y > max_septets) {
395 /*
396 * Limit the number of septets to avoid the generation
397 * of more than n octets.
398 */
399 y = max_septets;
400 }
401
Vadim Yanitskiy943133c2021-01-30 01:31:32 +0100402 o = gsm_septet_pack(result, rdata, y, 0);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200403
404 if (octets)
405 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200406
407 free(rdata);
408
409 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200410 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200411 * unique. E.g.:
412 * 1.) 46 non-extension characters + 1 extension character
413 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
414 * 2.) 47 non-extension characters
415 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
416 * 3.) 48 non-extension characters
417 * => (48 * 7 bit) / 8 bit = 42 octects
418 */
419 return y;
420}
421
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200422/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200423 * \param[out] result Caller-provided output buffer
424 * \param[in] n Maximum length of \a result in bytes
425 * \param[in] data octet-aligned string
426 * \param[out] octets Number of octets encoded
427 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200428int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
429{
430 int y;
431
432 y = gsm_7bit_encode_n(result, n, data, octets);
433 /* if last octet contains only one bit, add <CR> */
434 if (((y * 7) & 7) == 1)
435 result[(*octets) - 1] |= ('\r' << 1);
436 /* if last character is <CR> and completely fills last octet, add
437 * another <CR>. */
438 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
439 result[(*octets)++] = '\r';
440 y++;
441 }
442
443 return y;
444}
445
Max4b2b0cc2017-07-10 14:32:48 +0200446/*! Generate random identifier
447 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
448 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
449 * See also RFC4086.
450 * \param[out] out Buffer to be filled with random data
451 * \param[in] len Number of random bytes required
452 * \returns 0 on success, or a negative error code on error.
453 */
454int osmo_get_rand_id(uint8_t *out, size_t len)
455{
Maxed029df2017-10-26 10:56:04 +0200456 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200457
458 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
459 if (len > OSMO_MAX_RAND_ID_LEN)
460 return -E2BIG;
Max0187c3a2018-11-09 13:08:42 +0100461#if (!EMBEDDED)
Karl Koscher76f025e2019-03-11 13:19:46 -0700462#ifdef HAVE_GLIBC_GETRANDOM
Max4b2b0cc2017-07-10 14:32:48 +0200463 rc = getrandom(out, len, GRND_NONBLOCK);
464#elif HAVE_DECL_SYS_GETRANDOM
465#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
466 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
467 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200468#endif
Max0187c3a2018-11-09 13:08:42 +0100469#endif /* !EMBEDDED */
Maxed029df2017-10-26 10:56:04 +0200470
Max4b2b0cc2017-07-10 14:32:48 +0200471 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200472 if (rc < 0) {
473#if (USE_GNUTLS)
Maxed029df2017-10-26 10:56:04 +0200474 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
Harald Weltedd0d76b2019-07-21 12:08:22 +0200475#else
Max4b2b0cc2017-07-10 14:32:48 +0200476 return -errno;
Harald Weltedd0d76b2019-07-21 12:08:22 +0200477#endif
Maxed029df2017-10-26 10:56:04 +0200478 }
Max4b2b0cc2017-07-10 14:32:48 +0200479
480 /* getrandom() failed partially due to signal interruption:
481 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
482 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
483 if (rc != len)
484 return -EAGAIN;
485
486 return 0;
487}
488
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200489/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200490 * \param[in] mru Unidirectional measurement report structure
491 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
492 * period
493 * \param[out] buf Pre-allocated bufer for storing IE
494 * \returns Number of bytes filled in buf
495 */
496size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
497 uint8_t *buf)
498{
499 buf[0] = dtxd_used ? (1 << 6) : 0;
500 buf[0] |= (mru->full.rx_lev & 0x3f);
501 buf[1] = (mru->sub.rx_lev & 0x3f);
502 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
503
504 return 3;
505}
506
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200507/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200508 * \param[in] band GSM frequency band
509 * \param[in] class GSM power class
Pau Espin Pedrole40b9632019-10-31 15:38:30 +0100510 * \returns maximum transmit power of power class in dBm, negative on error */
511int ms_class_gmsk_dbm(enum gsm_band band, int class)
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200512{
513 switch (band) {
514 case GSM_BAND_450:
515 case GSM_BAND_480:
516 case GSM_BAND_750:
517 case GSM_BAND_900:
518 case GSM_BAND_810:
519 case GSM_BAND_850:
520 if (class == 1)
521 return 43; /* 20W */
522 if (class == 2)
523 return 39; /* 8W */
524 if (class == 3)
525 return 37; /* 5W */
526 if (class == 4)
527 return 33; /* 2W */
528 if (class == 5)
529 return 29; /* 0.8W */
530 break;
531 case GSM_BAND_1800:
532 if (class == 1)
533 return 30; /* 1W */
534 if (class == 2)
535 return 24; /* 0.25W */
536 if (class == 3)
537 return 36; /* 4W */
538 break;
539 case GSM_BAND_1900:
540 if (class == 1)
541 return 30; /* 1W */
542 if (class == 2)
543 return 24; /* 0.25W */
544 if (class == 3)
545 return 33; /* 2W */
546 break;
547 }
548 return -EINVAL;
549}
550
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200551/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200552 * by the tables in chapter 4.1.1 of GSM TS 05.05
553 * \param[in] GSM frequency band
554 * \param[in] dbm RF power value in dBm
555 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100556int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
557{
558 switch (band) {
559 case GSM_BAND_450:
560 case GSM_BAND_480:
561 case GSM_BAND_750:
562 case GSM_BAND_900:
563 case GSM_BAND_810:
564 case GSM_BAND_850:
565 if (dbm >= 39)
566 return 0;
567 else if (dbm < 5)
568 return 19;
569 else {
570 /* we are guaranteed to have (5 <= dbm < 39) */
571 return 2 + ((39 - dbm) / 2);
572 }
573 break;
574 case GSM_BAND_1800:
575 if (dbm >= 36)
576 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200577 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100578 return 30;
579 else if (dbm >= 32)
580 return 31;
581 else if (dbm == 31)
582 return 0;
583 else {
584 /* we are guaranteed to have (0 <= dbm < 31) */
585 return (30 - dbm) / 2;
586 }
587 break;
588 case GSM_BAND_1900:
589 if (dbm >= 33)
590 return 30;
591 else if (dbm >= 32)
592 return 31;
593 else if (dbm == 31)
594 return 0;
595 else {
596 /* we are guaranteed to have (0 <= dbm < 31) */
597 return (30 - dbm) / 2;
598 }
599 break;
600 }
601 return -EINVAL;
602}
603
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200604/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200605 * \param[in] band GSM frequency band
606 * \param[in] lvl TS 05.05 power control level
607 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100608int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
609{
610 lvl &= 0x1f;
611
612 switch (band) {
613 case GSM_BAND_450:
614 case GSM_BAND_480:
615 case GSM_BAND_750:
616 case GSM_BAND_900:
617 case GSM_BAND_810:
618 case GSM_BAND_850:
619 if (lvl < 2)
620 return 39;
621 else if (lvl < 20)
622 return 39 - ((lvl - 2) * 2) ;
623 else
624 return 5;
625 break;
626 case GSM_BAND_1800:
627 if (lvl < 16)
628 return 30 - (lvl * 2);
629 else if (lvl < 29)
630 return 0;
631 else
632 return 36 - ((lvl - 29) * 2);
633 break;
634 case GSM_BAND_1900:
635 if (lvl < 16)
636 return 30 - (lvl * 2);
637 else if (lvl < 30)
638 return -EINVAL;
639 else
640 return 33 - (lvl - 30);
641 break;
642 }
643 return -EINVAL;
644}
645
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200646/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200647 * \param[in] rxlev TS 05.08 RxLev value
648 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100649int rxlev2dbm(uint8_t rxlev)
650{
651 if (rxlev > 63)
652 rxlev = 63;
653
654 return -110 + rxlev;
655}
656
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200657/*! 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 +0200658 * \param[in] dbm RF signal level in dBm
659 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100660uint8_t dbm2rxlev(int dbm)
661{
662 int rxlev = dbm + 110;
663
664 if (rxlev > 63)
665 rxlev = 63;
666 else if (rxlev < 0)
667 rxlev = 0;
668
669 return rxlev;
670}
671
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200672/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800673const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100674{
675 switch (band) {
676 case GSM_BAND_450:
677 return "GSM450";
678 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200679 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100680 case GSM_BAND_750:
681 return "GSM750";
682 case GSM_BAND_810:
683 return "GSM810";
684 case GSM_BAND_850:
685 return "GSM850";
686 case GSM_BAND_900:
687 return "GSM900";
688 case GSM_BAND_1800:
689 return "DCS1800";
690 case GSM_BAND_1900:
691 return "PCS1900";
692 }
693 return "invalid";
694}
695
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200696/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100697enum gsm_band gsm_band_parse(const char* mhz)
698{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200699 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100700 mhz++;
701
702 if (*mhz == '\0')
703 return -EINVAL;
704
Harald Welted3ff15f2010-03-07 18:23:47 +0100705 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100706 case 450:
707 return GSM_BAND_450;
708 case 480:
709 return GSM_BAND_480;
710 case 750:
711 return GSM_BAND_750;
712 case 810:
713 return GSM_BAND_810;
714 case 850:
715 return GSM_BAND_850;
716 case 900:
717 return GSM_BAND_900;
718 case 1800:
719 return GSM_BAND_1800;
720 case 1900:
721 return GSM_BAND_1900;
722 default:
723 return -EINVAL;
724 }
725}
726
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100727/*! Resolve GSM band from ARFCN.
Harald Welte96e2a002017-06-12 21:44:18 +0200728 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
729 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100730 * \param[out] band GSM Band containing \arfcn if arfcn is valid, undetermined otherwise
731 * \returns 0 if arfcn is valid and \a band was set, negative on error */
732int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band)
Harald Welte622b7182010-03-07 17:50:21 +0100733{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100734 int is_pcs = arfcn & ARFCN_PCS;
735
736 arfcn &= ~ARFCN_FLAG_MASK;
737
Pau Espin Pedrolc8772512018-11-16 12:59:46 +0100738 if (is_pcs) {
739 *band = GSM_BAND_1900;
740 return 0;
741 } else if (arfcn <= 124) {
742 *band = GSM_BAND_900;
743 return 0;
744 } else if (arfcn >= 955 && arfcn <= 1023) {
745 *band = GSM_BAND_900;
746 return 0;
747 } else if (arfcn >= 128 && arfcn <= 251) {
748 *band = GSM_BAND_850;
749 return 0;
750 } else if (arfcn >= 512 && arfcn <= 885) {
751 *band = GSM_BAND_1800;
752 return 0;
753 } else if (arfcn >= 259 && arfcn <= 293) {
754 *band = GSM_BAND_450;
755 return 0;
756 } else if (arfcn >= 306 && arfcn <= 340) {
757 *band = GSM_BAND_480;
758 return 0;
759 } else if (arfcn >= 350 && arfcn <= 425) {
760 *band = GSM_BAND_810;
761 return 0;
762 } else if (arfcn >= 438 && arfcn <= 511) {
763 *band = GSM_BAND_750;
764 return 0;
765 }
766 return -1;
767}
768
769/*! Resolve GSM band from ARFCN, aborts process on invalid ARFCN.
770 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS.
771 * DEPRECATED: Use gsm_arfcn2band_rc instead.
772 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
773 * \returns GSM Band if ARFCN is valid (part of any valid band), aborts otherwise */
774enum gsm_band gsm_arfcn2band(uint16_t arfcn)
775{
776 enum gsm_band band;
777 if (gsm_arfcn2band_rc(arfcn, &band) == 0)
778 return band;
779
780 osmo_panic("%s:%d Invalid arfcn %" PRIu16 " passed to gsm_arfcn2band\n",
781 __FILE__, __LINE__, arfcn);
Harald Welte622b7182010-03-07 17:50:21 +0100782}
783
Sylvain Munaut55720312012-12-11 23:44:41 +0100784struct gsm_freq_range {
785 uint16_t arfcn_first;
786 uint16_t arfcn_last;
787 uint16_t freq_ul_first;
788 uint16_t freq_dl_offset;
789 uint16_t flags;
790};
791
792static struct gsm_freq_range gsm_ranges[] = {
793 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
794 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
795 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
796 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
797 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
798 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
799 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
800 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
801 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
802 { /* Guard */ }
803};
804
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200805/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200806 * \param[in] arfcn GSM ARFCN to convert
807 * \param[in] uplink Uplink (1) or Downlink (0) frequency
808 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100809uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
810{
Sylvain Munaut55720312012-12-11 23:44:41 +0100811 struct gsm_freq_range *r;
812 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
813 uint16_t freq10_ul = 0xffff;
814 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100815
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100816 arfcn &= ~ARFCN_FLAG_MASK;
817
Sylvain Munaut55720312012-12-11 23:44:41 +0100818 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
819 if ((flags == r->flags) &&
820 (arfcn >= r->arfcn_first) &&
821 (arfcn <= r->arfcn_last))
822 {
823 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
824 freq10_dl = freq10_ul + r->freq_dl_offset;
825 break;
826 }
827 }
828
829 return uplink ? freq10_ul : freq10_dl;
830}
831
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200832/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200833 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
834 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
835 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100836uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
837{
838 struct gsm_freq_range *r;
839 uint16_t freq10_lo, freq10_hi;
840 uint16_t arfcn = 0xffff;
841
842 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
843 /* Generate frequency limits */
844 freq10_lo = r->freq_ul_first;
845 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
846 if (!uplink) {
847 freq10_lo += r->freq_dl_offset;
848 freq10_hi += r->freq_dl_offset;
849 }
850
851 /* Check if this fits */
852 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
853 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
854 arfcn |= r->flags;
855 break;
856 }
857 }
Harald Welte622b7182010-03-07 17:50:21 +0100858
859 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100860 arfcn |= ARFCN_UPLINK;
861
862 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100863}
864
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200865/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200866 * \param[out] time Caller-provided memory for \ref gsm_time
867 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100868void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
869{
870 time->fn = fn;
871 time->t1 = time->fn / (26*51);
872 time->t2 = time->fn % 26;
873 time->t3 = time->fn % 51;
874 time->tc = (time->fn / 51) % 8;
875}
876
Philipp Maierb808da42017-06-26 10:50:28 +0200877/*! Parse GSM Frame Number into printable string
878 * \param[in] fn GSM Frame Number
879 * \returns pointer to printable string */
880char *gsm_fn_as_gsmtime_str(uint32_t fn)
881{
882 struct gsm_time time;
883
884 gsm_fn2gsmtime(&time, fn);
885 return osmo_dump_gsmtime(&time);
886}
887
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200888/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200889 * \param[in] time GSM Time in decoded structure
890 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100891uint32_t gsm_gsmtime2fn(struct gsm_time *time)
892{
893 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
894 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
895}
Harald Weltea1c4f762010-05-01 11:59:42 +0200896
Harald Welte4a62eda2019-03-18 18:27:00 +0100897char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm)
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200898{
Harald Welte4a62eda2019-03-18 18:27:00 +0100899 snprintf(buf, buf_len, "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200900 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
Philipp Maiere8461e42019-04-08 12:07:36 +0200901 buf[buf_len-1] = '\0';
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200902 return buf;
903}
904
Harald Welte4a62eda2019-03-18 18:27:00 +0100905char *osmo_dump_gsmtime(const struct gsm_time *tm)
906{
Harald Welte171ef822019-03-28 10:49:05 +0100907 static __thread char buf[64];
Harald Welte4a62eda2019-03-18 18:27:00 +0100908 return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm);
909}
910
Harald Welte179f3572019-03-18 18:38:47 +0100911char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm)
912{
913 char *buf = talloc_size(ctx, 64);
914 if (!buf)
915 return NULL;
916 return osmo_dump_gsmtime_buf(buf, 64, tm);
917}
Harald Welte4a62eda2019-03-18 18:27:00 +0100918
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200919/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200920 * \param[out] bv Caller-provided output bit-vector
921 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200922void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
923{
924 bitvec_set_uint(bv, r->w1_hi, 2);
925 bitvec_set_uint(bv, r->w1_lo, 8);
926 bitvec_set_uint(bv, r->w2_hi, 8);
927 bitvec_set_uint(bv, r->w2_lo, 1);
928 bitvec_set_uint(bv, r->w3_hi, 7);
929 bitvec_set_uint(bv, r->w3_lo, 2);
930 bitvec_set_uint(bv, r->w4_hi, 6);
931 bitvec_set_uint(bv, r->w4_lo, 2);
932 bitvec_set_uint(bv, r->w5_hi, 6);
933 bitvec_set_uint(bv, r->w5_lo, 2);
934 bitvec_set_uint(bv, r->w6_hi, 6);
935 bitvec_set_uint(bv, r->w6_lo, 2);
936 bitvec_set_uint(bv, r->w7_hi, 6);
937 bitvec_set_uint(bv, r->w7_lo, 2);
938 bitvec_set_uint(bv, r->w8_hi, 6);
939 bitvec_set_uint(bv, r->w8_lo, 1);
940 bitvec_set_uint(bv, r->w9, 7);
941 bitvec_set_uint(bv, r->w10, 7);
942 bitvec_set_uint(bv, r->w11_hi, 1);
943 bitvec_set_uint(bv, r->w11_lo, 6);
944 bitvec_set_uint(bv, r->w12_hi, 2);
945 bitvec_set_uint(bv, r->w12_lo, 5);
946 bitvec_set_uint(bv, r->w13_hi, 3);
947 bitvec_set_uint(bv, r->w13_lo, 4);
948 bitvec_set_uint(bv, r->w14_hi, 4);
949 bitvec_set_uint(bv, r->w14_lo, 3);
950 bitvec_set_uint(bv, r->w15_hi, 5);
951 bitvec_set_uint(bv, r->w15_lo, 2);
952 bitvec_set_uint(bv, r->w16, 6);
953}
954
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200955/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200956int gprs_tlli_type(uint32_t tlli)
957{
958 if ((tlli & 0xc0000000) == 0xc0000000)
959 return TLLI_LOCAL;
960 else if ((tlli & 0xc0000000) == 0x80000000)
961 return TLLI_FOREIGN;
962 else if ((tlli & 0xf8000000) == 0x78000000)
963 return TLLI_RANDOM;
964 else if ((tlli & 0xf8000000) == 0x70000000)
965 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200966 else if ((tlli & 0xf0000000) == 0x00000000)
967 return TLLI_G_RNTI;
968 else if ((tlli & 0xf0000000) == 0x10000000)
969 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200970
971 return TLLI_RESERVED;
972}
Harald Weltec2263172010-06-01 10:47:07 +0200973
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200974/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200975 * \param[in] p_tmsi P-TMSI
976 * \param[in] type TLLI Type we want to derive from \a p_tmsi
977 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200978uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
979{
980 uint32_t tlli;
981 switch (type) {
982 case TLLI_LOCAL:
983 tlli = p_tmsi | 0xc0000000;
984 break;
985 case TLLI_FOREIGN:
986 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
987 break;
988 default:
989 tlli = 0;
990 break;
991 }
992 return tlli;
993}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200994
995/* Wrappers for deprecated functions: */
996
997int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
998{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100999 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1000 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001001
1002 /* Mimic the original behaviour. */
1003 return septet_l;
1004}
1005
1006int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
1007{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001008 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1009 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001010}
1011
1012int gsm_7bit_encode(uint8_t *result, const char *data)
1013{
1014 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001015 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1016 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001017}
1018
1019int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
1020{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001021 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1022 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001023}
1024
1025int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
1026{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +01001027 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
1028 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +02001029}
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001030
1031/* This is also used by osmo-hlr's db schema */
1032const struct value_string osmo_rat_type_names[] = {
1033 { OSMO_RAT_UNKNOWN, "unknown" },
1034 { OSMO_RAT_GERAN_A, "GERAN-A" },
1035 { OSMO_RAT_UTRAN_IU, "UTRAN-Iu" },
Neels Hofmeyr0d39a8d2019-01-04 04:37:00 +01001036 { OSMO_RAT_EUTRAN_SGS, "EUTRAN-SGs" },
Neels Hofmeyr5b5c3492018-12-26 18:03:17 +01001037 {}
1038};