blob: 8464090af458a307a89ff2b926e5c1c05ef7890a [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file gsm_utils.c */
Harald Welteec8b4502010-02-20 20:34:29 +01002/*
3 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +02004 * (C) 2009,2013 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte622b7182010-03-07 17:50:21 +01005 * (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
Nico Goldec56a56d2012-09-18 14:29:40 +02006 * (C) 2010-2012 by Nico Golde <nico@ngolde.de>
Harald Welteec8b4502010-02-20 20:34:29 +01007 *
8 * All Rights Reserved
9 *
Harald Weltee08da972017-11-13 01:00:26 +090010 * SPDX-License-Identifier: GPL-2.0+
11 *
Harald Welteec8b4502010-02-20 20:34:29 +010012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 *
26 */
27
Harald Welted38c8b82011-08-30 11:32:56 +020028/*! \mainpage libosmogsm Documentation
29 *
30 * \section sec_intro Introduction
31 * This library is a collection of common code used in various
32 * GSM related sub-projects inside the Osmocom family of projects. It
33 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +020034 * a GSM TLV parser, SMS utility routines as well as
Harald Welted38c8b82011-08-30 11:32:56 +020035 * protocol definitions for a series of protocols:
36 * * Um L2 (04.06)
37 * * Um L3 (04.08)
38 * * A-bis RSL (08.58)
39 * * A-bis OML (08.59, 12.21)
40 * * A (08.08)
41 * \n\n
42 * Please note that C language projects inside Osmocom are typically
43 * single-threaded event-loop state machine designs. As such,
44 * routines in libosmogsm are not thread-safe. If you must use them in
45 * a multi-threaded context, you have to add your own locking.
46 *
Harald Welte71658802017-06-12 15:40:52 +020047 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
48 * Communications) project, a community-based, collaborative development
49 * project to create Free and Open Source implementations of mobile
50 * communications systems. For more information about Osmocom, please
51 * see https://osmocom.org/
52 *
Harald Welted38c8b82011-08-30 11:32:56 +020053 * \section sec_copyright Copyright and License
54 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
55 * All rights reserved. \n\n
56 * The source code of libosmogsm is licensed under the terms of the GNU
57 * General Public License as published by the Free Software Foundation;
58 * either version 2 of the License, or (at your option) any later
59 * version.\n
60 * See <http://www.gnu.org/licenses/> or COPYING included in the source
61 * code package istelf.\n
62 * The information detailed here is provided AS IS with NO WARRANTY OF
63 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
64 * FITNESS FOR A PARTICULAR PURPOSE.
65 * \n\n
66 *
Harald Welte71658802017-06-12 15:40:52 +020067 * \section sec_tracker Homepage + Issue Tracker
68 * libosmogsm is distributed as part of libosmocore and shares its
69 * project page at http://osmocom.org/projects/libosmocore
70 *
71 * An Issue Tracker can be found at
72 * https://osmocom.org/projects/libosmocore/issues
73 *
Harald Welted38c8b82011-08-30 11:32:56 +020074 * \section sec_contact Contact and Support
75 * Community-based support is available at the OpenBSC mailing list
76 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
77 * Commercial support options available upon request from
78 * <http://sysmocom.de/>
79 */
80
Harald Welteec8b4502010-02-20 20:34:29 +010081//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010082#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020083#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010084#include <osmocom/gsm/gsm_utils.h>
Max764b0222016-05-11 17:33:17 +020085#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020086#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010087
88#include <stdlib.h>
89#include <stdint.h>
90#include <string.h>
Max764b0222016-05-11 17:33:17 +020091#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010092#include <stdio.h>
93#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010094#include <ctype.h>
Pau Espin Pedrol363130f2017-07-03 10:42:42 +020095#include <inttypes.h>
Max4b2b0cc2017-07-10 14:32:48 +020096#include <time.h>
97#include <unistd.h>
Harald Welteec8b4502010-02-20 20:34:29 +010098
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010099#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +0100100
Max4b2b0cc2017-07-10 14:32:48 +0200101/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
102#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
103#include <linux/random.h>
104#elif HAVE_DECL_SYS_GETRANDOM
105#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200106#ifndef GRND_NONBLOCK
107#define GRND_NONBLOCK 0x0001
108#endif
Max4b2b0cc2017-07-10 14:32:48 +0200109#endif
110
Maxed029df2017-10-26 10:56:04 +0200111#if (USE_GNUTLS)
112#pragma message ("including GnuTLS for getrandom fallback.")
113#include <gnutls/gnutls.h>
114#include <gnutls/crypto.h>
115#endif
116
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800117/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
118 * Greek symbols at hex positions 0x10 and 0x12-0x1a
119 * left out as they can't be handled with a char and
120 * since most phones don't display or write these
121 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200122 * more complex.
123 *
124 * Note that this table contains the latin1->7bit mapping _and_ has
125 * been merged with the reverse mapping (7bit->latin1) for the
126 * extended characters at offset 0x7f.
127 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800128static unsigned char gsm_7bit_alphabet[] = {
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
132 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
133 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
134 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
135 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
136 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
137 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
140 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
142 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
143 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
144 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
145 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
146};
147
Nico Golde28de0532010-07-09 17:19:12 +0200148/* GSM 03.38 6.2.1 Character lookup for decoding */
149static int gsm_septet_lookup(uint8_t ch)
150{
151 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200152 for (; i < sizeof(gsm_7bit_alphabet); i++) {
153 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200154 return i;
155 }
156 return -1;
157}
158
Harald Welte96e2a002017-06-12 21:44:18 +0200159/*! \brife Compute number of octets from number of septets,
160 * for instance: 47 septets needs 41,125 = 42 octets
161 * \param[in sept_len Number of Septets
162 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200163uint8_t gsm_get_octet_len(const uint8_t sept_len){
164 int octet_len = (sept_len * 7) / 8;
165 if ((sept_len * 7) % 8 != 0)
166 octet_len++;
167
168 return octet_len;
169}
170
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200171/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200172 * \param[out] text Caller-provided output text buffer
173 * \param[in] n Length of \a text
174 * \param[in] user_data Input Data (septets)
175 * \param[in] septet_l Number of septets in \a user_data
176 * \param[in] ud_hdr_ind User Data Header present in data
177 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200178int 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 +0100179{
Maxcf37c4c2016-01-21 16:52:40 +0100180 unsigned shift = 0;
181 uint8_t c7, c8, next_is_ext = 0, lu, ru;
182 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200183 const char *text_buf_begin = text;
184 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200185
186 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100187
Dennis Wehrle291e6132011-07-24 20:14:13 +0200188 /* skip the user data header */
189 if (ud_hdr_ind) {
190 /* get user data header length + 1 (for the 'user data header length'-field) */
191 shift = ((user_data[0] + 1) * 8) / 7;
192 if ((((user_data[0] + 1) * 8) % 7) != 0)
193 shift++;
194 septet_l = septet_l - shift;
195 }
196
Maxcf37c4c2016-01-21 16:52:40 +0100197 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200198 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100199
200 l = ((i + shift) * 7 + 7) >> 3;
201 r = ((i + shift) * 7) >> 3;
202
203 /* the left side index is always >= right side index
204 sometimes it even gets beyond array boundary
205 check for that explicitly and force 0 instead
206 */
207 if (l >= maxlen)
208 lu = 0;
209 else
210 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
211
212 ru = user_data[r] >> (((i + shift) * 7) & 7);
213
214 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200215
Harald Weltebe55a8b2012-09-20 10:00:25 +0200216 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200217 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200218 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200219 c8 = gsm_7bit_alphabet[0x7f + c7];
220 } else if (c7 == 0x1b && i + 1 < septet_l) {
221 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200222 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200223 } else {
224 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200225 }
226
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200227 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100228 }
229
Nico Golde28de0532010-07-09 17:19:12 +0200230 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200231
Maxcf37c4c2016-01-21 16:52:40 +0100232 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200233}
234
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200235/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200236int 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 +0200237{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200238 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200239}
240
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200241/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200242int 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 +0200243{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200244 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200245
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200246 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200247 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200248 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
249 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200250
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200251 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200252}
253
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200254/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200255 *
256 * This function converts a zero-terminated input string \a data from
257 * ASCII into octet-aligned 7-bit GSM characters. No packing is
258 * performed.
259 *
260 * \param[out] result caller-allocated output buffer
261 * \param[in] data input data, ASCII
262 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200263int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200264{
265 int i, y = 0;
266 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200267 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200268 ch = data[i];
269 switch(ch){
270 /* fall-through for extension characters */
271 case 0x0c:
272 case 0x5e:
273 case 0x7b:
274 case 0x7d:
275 case 0x5c:
276 case 0x5b:
277 case 0x7e:
278 case 0x5d:
279 case 0x7c:
280 result[y++] = 0x1b;
281 default:
282 result[y] = gsm_7bit_alphabet[ch];
283 break;
284 }
285 y++;
286 }
287
288 return y;
289}
290
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200291/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200292 * \param[out] result Caller-provided output buffer
293 * \param[in] rdata Input data septets
294 * \param[in] septet_len Length of \a rdata
295 * \param[in] padding padding bits at start
296 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100297int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
298{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200299 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200300 uint8_t cb, nb;
301 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200302 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200303
Dennis Wehrle291e6132011-07-24 20:14:13 +0200304 if (padding) {
305 shift = 7 - padding;
306 /* the first zero is needed for padding */
307 memcpy(data + 1, rdata, septet_len);
308 septet_len++;
309 } else
310 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200311
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200312 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200313 if (shift == 7) {
314 /*
315 * special end case with the. This is necessary if the
316 * last septet fits into the previous octet. E.g. 48
317 * non-extension characters:
318 * ....ag ( a = 1100001, g = 1100111)
319 * result[40] = 100001 XX, result[41] = 1100111 1 */
320 if (i + 1 < septet_len) {
321 shift = 0;
322 continue;
323 } else if (i + 1 == septet_len)
324 break;
Nico Golde28de0532010-07-09 17:19:12 +0200325 }
326
Dennis Wehrle291e6132011-07-24 20:14:13 +0200327 cb = (data[i] & 0x7f) >> shift;
328 if (i + 1 < septet_len) {
329 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200330 cb = cb | nb;
331 }
332
333 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200334 shift++;
335 }
336
Dennis Wehrle291e6132011-07-24 20:14:13 +0200337 free(data);
338
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200339 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100340}
341
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200342/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200343 * \param[out] result Caller-provided output buffer
344 * \param[in] n Maximum length of \a result in bytes
345 * \param[in] data octet-aligned string
346 * \param[out] octets Number of octets encoded
347 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200348int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200349{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200350 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200351 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100352 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200353
Dennis Wehrle291e6132011-07-24 20:14:13 +0200354 /* prepare for the worst case, every character expanding to two bytes */
355 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
356 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200357
358 if (y > max_septets) {
359 /*
360 * Limit the number of septets to avoid the generation
361 * of more than n octets.
362 */
363 y = max_septets;
364 }
365
366 o = gsm_septets2octets(result, rdata, y, 0);
367
368 if (octets)
369 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200370
371 free(rdata);
372
373 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200374 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200375 * unique. E.g.:
376 * 1.) 46 non-extension characters + 1 extension character
377 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
378 * 2.) 47 non-extension characters
379 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
380 * 3.) 48 non-extension characters
381 * => (48 * 7 bit) / 8 bit = 42 octects
382 */
383 return y;
384}
385
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200386/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200387 * \param[out] result Caller-provided output buffer
388 * \param[in] n Maximum length of \a result in bytes
389 * \param[in] data octet-aligned string
390 * \param[out] octets Number of octets encoded
391 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200392int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
393{
394 int y;
395
396 y = gsm_7bit_encode_n(result, n, data, octets);
397 /* if last octet contains only one bit, add <CR> */
398 if (((y * 7) & 7) == 1)
399 result[(*octets) - 1] |= ('\r' << 1);
400 /* if last character is <CR> and completely fills last octet, add
401 * another <CR>. */
402 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
403 result[(*octets)++] = '\r';
404 y++;
405 }
406
407 return y;
408}
409
Max4b2b0cc2017-07-10 14:32:48 +0200410/*! Generate random identifier
411 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
412 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
413 * See also RFC4086.
414 * \param[out] out Buffer to be filled with random data
415 * \param[in] len Number of random bytes required
416 * \returns 0 on success, or a negative error code on error.
417 */
418int osmo_get_rand_id(uint8_t *out, size_t len)
419{
Maxed029df2017-10-26 10:56:04 +0200420 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200421
422 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
423 if (len > OSMO_MAX_RAND_ID_LEN)
424 return -E2BIG;
425
426#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
427 rc = getrandom(out, len, GRND_NONBLOCK);
428#elif HAVE_DECL_SYS_GETRANDOM
429#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
430 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
431 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200432#endif
Maxed029df2017-10-26 10:56:04 +0200433
Max4b2b0cc2017-07-10 14:32:48 +0200434 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200435 if (rc < 0) {
436#if (USE_GNUTLS)
437#pragma message ("Secure random failed: using GnuTLS fallback.")
438 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
439#endif
Max4b2b0cc2017-07-10 14:32:48 +0200440 return -errno;
Maxed029df2017-10-26 10:56:04 +0200441 }
Max4b2b0cc2017-07-10 14:32:48 +0200442
443 /* getrandom() failed partially due to signal interruption:
444 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
445 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
446 if (rc != len)
447 return -EAGAIN;
448
449 return 0;
450}
451
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200452/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200453 * \param[in] mru Unidirectional measurement report structure
454 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
455 * period
456 * \param[out] buf Pre-allocated bufer for storing IE
457 * \returns Number of bytes filled in buf
458 */
459size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
460 uint8_t *buf)
461{
462 buf[0] = dtxd_used ? (1 << 6) : 0;
463 buf[0] |= (mru->full.rx_lev & 0x3f);
464 buf[1] = (mru->sub.rx_lev & 0x3f);
465 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
466
467 return 3;
468}
469
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200470/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200471 * \param[in] band GSM frequency band
472 * \param[in] class GSM power class
473 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200474unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
475{
476 switch (band) {
477 case GSM_BAND_450:
478 case GSM_BAND_480:
479 case GSM_BAND_750:
480 case GSM_BAND_900:
481 case GSM_BAND_810:
482 case GSM_BAND_850:
483 if (class == 1)
484 return 43; /* 20W */
485 if (class == 2)
486 return 39; /* 8W */
487 if (class == 3)
488 return 37; /* 5W */
489 if (class == 4)
490 return 33; /* 2W */
491 if (class == 5)
492 return 29; /* 0.8W */
493 break;
494 case GSM_BAND_1800:
495 if (class == 1)
496 return 30; /* 1W */
497 if (class == 2)
498 return 24; /* 0.25W */
499 if (class == 3)
500 return 36; /* 4W */
501 break;
502 case GSM_BAND_1900:
503 if (class == 1)
504 return 30; /* 1W */
505 if (class == 2)
506 return 24; /* 0.25W */
507 if (class == 3)
508 return 33; /* 2W */
509 break;
510 }
511 return -EINVAL;
512}
513
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200514/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200515 * by the tables in chapter 4.1.1 of GSM TS 05.05
516 * \param[in] GSM frequency band
517 * \param[in] dbm RF power value in dBm
518 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100519int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
520{
521 switch (band) {
522 case GSM_BAND_450:
523 case GSM_BAND_480:
524 case GSM_BAND_750:
525 case GSM_BAND_900:
526 case GSM_BAND_810:
527 case GSM_BAND_850:
528 if (dbm >= 39)
529 return 0;
530 else if (dbm < 5)
531 return 19;
532 else {
533 /* we are guaranteed to have (5 <= dbm < 39) */
534 return 2 + ((39 - dbm) / 2);
535 }
536 break;
537 case GSM_BAND_1800:
538 if (dbm >= 36)
539 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200540 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100541 return 30;
542 else if (dbm >= 32)
543 return 31;
544 else if (dbm == 31)
545 return 0;
546 else {
547 /* we are guaranteed to have (0 <= dbm < 31) */
548 return (30 - dbm) / 2;
549 }
550 break;
551 case GSM_BAND_1900:
552 if (dbm >= 33)
553 return 30;
554 else if (dbm >= 32)
555 return 31;
556 else if (dbm == 31)
557 return 0;
558 else {
559 /* we are guaranteed to have (0 <= dbm < 31) */
560 return (30 - dbm) / 2;
561 }
562 break;
563 }
564 return -EINVAL;
565}
566
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200567/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200568 * \param[in] band GSM frequency band
569 * \param[in] lvl TS 05.05 power control level
570 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100571int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
572{
573 lvl &= 0x1f;
574
575 switch (band) {
576 case GSM_BAND_450:
577 case GSM_BAND_480:
578 case GSM_BAND_750:
579 case GSM_BAND_900:
580 case GSM_BAND_810:
581 case GSM_BAND_850:
582 if (lvl < 2)
583 return 39;
584 else if (lvl < 20)
585 return 39 - ((lvl - 2) * 2) ;
586 else
587 return 5;
588 break;
589 case GSM_BAND_1800:
590 if (lvl < 16)
591 return 30 - (lvl * 2);
592 else if (lvl < 29)
593 return 0;
594 else
595 return 36 - ((lvl - 29) * 2);
596 break;
597 case GSM_BAND_1900:
598 if (lvl < 16)
599 return 30 - (lvl * 2);
600 else if (lvl < 30)
601 return -EINVAL;
602 else
603 return 33 - (lvl - 30);
604 break;
605 }
606 return -EINVAL;
607}
608
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200609/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200610 * \param[in] rxlev TS 05.08 RxLev value
611 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100612int rxlev2dbm(uint8_t rxlev)
613{
614 if (rxlev > 63)
615 rxlev = 63;
616
617 return -110 + rxlev;
618}
619
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200620/*! 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 +0200621 * \param[in] dbm RF signal level in dBm
622 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100623uint8_t dbm2rxlev(int dbm)
624{
625 int rxlev = dbm + 110;
626
627 if (rxlev > 63)
628 rxlev = 63;
629 else if (rxlev < 0)
630 rxlev = 0;
631
632 return rxlev;
633}
634
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200635/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800636const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100637{
638 switch (band) {
639 case GSM_BAND_450:
640 return "GSM450";
641 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200642 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100643 case GSM_BAND_750:
644 return "GSM750";
645 case GSM_BAND_810:
646 return "GSM810";
647 case GSM_BAND_850:
648 return "GSM850";
649 case GSM_BAND_900:
650 return "GSM900";
651 case GSM_BAND_1800:
652 return "DCS1800";
653 case GSM_BAND_1900:
654 return "PCS1900";
655 }
656 return "invalid";
657}
658
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200659/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100660enum gsm_band gsm_band_parse(const char* mhz)
661{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200662 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100663 mhz++;
664
665 if (*mhz == '\0')
666 return -EINVAL;
667
Harald Welted3ff15f2010-03-07 18:23:47 +0100668 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100669 case 450:
670 return GSM_BAND_450;
671 case 480:
672 return GSM_BAND_480;
673 case 750:
674 return GSM_BAND_750;
675 case 810:
676 return GSM_BAND_810;
677 case 850:
678 return GSM_BAND_850;
679 case 900:
680 return GSM_BAND_900;
681 case 1800:
682 return GSM_BAND_1800;
683 case 1900:
684 return GSM_BAND_1900;
685 default:
686 return -EINVAL;
687 }
688}
689
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200690/*! Resolve GSM band from ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200691 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
692 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
693 * \returns GSM Band */
Harald Welte622b7182010-03-07 17:50:21 +0100694enum gsm_band gsm_arfcn2band(uint16_t arfcn)
695{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100696 int is_pcs = arfcn & ARFCN_PCS;
697
698 arfcn &= ~ARFCN_FLAG_MASK;
699
700 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100701 return GSM_BAND_1900;
702 else if (arfcn <= 124)
703 return GSM_BAND_900;
704 else if (arfcn >= 955 && arfcn <= 1023)
705 return GSM_BAND_900;
706 else if (arfcn >= 128 && arfcn <= 251)
707 return GSM_BAND_850;
708 else if (arfcn >= 512 && arfcn <= 885)
709 return GSM_BAND_1800;
710 else if (arfcn >= 259 && arfcn <= 293)
711 return GSM_BAND_450;
712 else if (arfcn >= 306 && arfcn <= 340)
713 return GSM_BAND_480;
714 else if (arfcn >= 350 && arfcn <= 425)
715 return GSM_BAND_810;
716 else if (arfcn >= 438 && arfcn <= 511)
717 return GSM_BAND_750;
718 else
719 return GSM_BAND_1800;
720}
721
Sylvain Munaut55720312012-12-11 23:44:41 +0100722struct gsm_freq_range {
723 uint16_t arfcn_first;
724 uint16_t arfcn_last;
725 uint16_t freq_ul_first;
726 uint16_t freq_dl_offset;
727 uint16_t flags;
728};
729
730static struct gsm_freq_range gsm_ranges[] = {
731 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
732 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
733 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
734 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
735 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
736 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
737 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
738 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
739 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
740 { /* Guard */ }
741};
742
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200743/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200744 * \param[in] arfcn GSM ARFCN to convert
745 * \param[in] uplink Uplink (1) or Downlink (0) frequency
746 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100747uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
748{
Sylvain Munaut55720312012-12-11 23:44:41 +0100749 struct gsm_freq_range *r;
750 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
751 uint16_t freq10_ul = 0xffff;
752 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100753
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100754 arfcn &= ~ARFCN_FLAG_MASK;
755
Sylvain Munaut55720312012-12-11 23:44:41 +0100756 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
757 if ((flags == r->flags) &&
758 (arfcn >= r->arfcn_first) &&
759 (arfcn <= r->arfcn_last))
760 {
761 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
762 freq10_dl = freq10_ul + r->freq_dl_offset;
763 break;
764 }
765 }
766
767 return uplink ? freq10_ul : freq10_dl;
768}
769
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200770/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200771 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
772 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
773 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100774uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
775{
776 struct gsm_freq_range *r;
777 uint16_t freq10_lo, freq10_hi;
778 uint16_t arfcn = 0xffff;
779
780 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
781 /* Generate frequency limits */
782 freq10_lo = r->freq_ul_first;
783 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
784 if (!uplink) {
785 freq10_lo += r->freq_dl_offset;
786 freq10_hi += r->freq_dl_offset;
787 }
788
789 /* Check if this fits */
790 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
791 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
792 arfcn |= r->flags;
793 break;
794 }
795 }
Harald Welte622b7182010-03-07 17:50:21 +0100796
797 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100798 arfcn |= ARFCN_UPLINK;
799
800 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100801}
802
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200803/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200804 * \param[out] time Caller-provided memory for \ref gsm_time
805 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100806void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
807{
808 time->fn = fn;
809 time->t1 = time->fn / (26*51);
810 time->t2 = time->fn % 26;
811 time->t3 = time->fn % 51;
812 time->tc = (time->fn / 51) % 8;
813}
814
Philipp Maierb808da42017-06-26 10:50:28 +0200815/*! Parse GSM Frame Number into printable string
816 * \param[in] fn GSM Frame Number
817 * \returns pointer to printable string */
818char *gsm_fn_as_gsmtime_str(uint32_t fn)
819{
820 struct gsm_time time;
821
822 gsm_fn2gsmtime(&time, fn);
823 return osmo_dump_gsmtime(&time);
824}
825
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200826/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200827 * \param[in] time GSM Time in decoded structure
828 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100829uint32_t gsm_gsmtime2fn(struct gsm_time *time)
830{
831 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
832 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
833}
Harald Weltea1c4f762010-05-01 11:59:42 +0200834
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200835char *osmo_dump_gsmtime(const struct gsm_time *tm)
836{
837 static char buf[64];
838
839 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
840 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
841 buf[sizeof(buf)-1] = '\0';
842 return buf;
843}
844
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200845/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200846 * \param[out] bv Caller-provided output bit-vector
847 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200848void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
849{
850 bitvec_set_uint(bv, r->w1_hi, 2);
851 bitvec_set_uint(bv, r->w1_lo, 8);
852 bitvec_set_uint(bv, r->w2_hi, 8);
853 bitvec_set_uint(bv, r->w2_lo, 1);
854 bitvec_set_uint(bv, r->w3_hi, 7);
855 bitvec_set_uint(bv, r->w3_lo, 2);
856 bitvec_set_uint(bv, r->w4_hi, 6);
857 bitvec_set_uint(bv, r->w4_lo, 2);
858 bitvec_set_uint(bv, r->w5_hi, 6);
859 bitvec_set_uint(bv, r->w5_lo, 2);
860 bitvec_set_uint(bv, r->w6_hi, 6);
861 bitvec_set_uint(bv, r->w6_lo, 2);
862 bitvec_set_uint(bv, r->w7_hi, 6);
863 bitvec_set_uint(bv, r->w7_lo, 2);
864 bitvec_set_uint(bv, r->w8_hi, 6);
865 bitvec_set_uint(bv, r->w8_lo, 1);
866 bitvec_set_uint(bv, r->w9, 7);
867 bitvec_set_uint(bv, r->w10, 7);
868 bitvec_set_uint(bv, r->w11_hi, 1);
869 bitvec_set_uint(bv, r->w11_lo, 6);
870 bitvec_set_uint(bv, r->w12_hi, 2);
871 bitvec_set_uint(bv, r->w12_lo, 5);
872 bitvec_set_uint(bv, r->w13_hi, 3);
873 bitvec_set_uint(bv, r->w13_lo, 4);
874 bitvec_set_uint(bv, r->w14_hi, 4);
875 bitvec_set_uint(bv, r->w14_lo, 3);
876 bitvec_set_uint(bv, r->w15_hi, 5);
877 bitvec_set_uint(bv, r->w15_lo, 2);
878 bitvec_set_uint(bv, r->w16, 6);
879}
880
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200881/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200882int gprs_tlli_type(uint32_t tlli)
883{
884 if ((tlli & 0xc0000000) == 0xc0000000)
885 return TLLI_LOCAL;
886 else if ((tlli & 0xc0000000) == 0x80000000)
887 return TLLI_FOREIGN;
888 else if ((tlli & 0xf8000000) == 0x78000000)
889 return TLLI_RANDOM;
890 else if ((tlli & 0xf8000000) == 0x70000000)
891 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200892 else if ((tlli & 0xf0000000) == 0x00000000)
893 return TLLI_G_RNTI;
894 else if ((tlli & 0xf0000000) == 0x10000000)
895 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200896
897 return TLLI_RESERVED;
898}
Harald Weltec2263172010-06-01 10:47:07 +0200899
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200900/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200901 * \param[in] p_tmsi P-TMSI
902 * \param[in] type TLLI Type we want to derive from \a p_tmsi
903 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200904uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
905{
906 uint32_t tlli;
907 switch (type) {
908 case TLLI_LOCAL:
909 tlli = p_tmsi | 0xc0000000;
910 break;
911 case TLLI_FOREIGN:
912 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
913 break;
914 default:
915 tlli = 0;
916 break;
917 }
918 return tlli;
919}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200920
921/* Wrappers for deprecated functions: */
922
923int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
924{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100925 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
926 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200927
928 /* Mimic the original behaviour. */
929 return septet_l;
930}
931
932int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
933{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100934 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
935 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200936}
937
938int gsm_7bit_encode(uint8_t *result, const char *data)
939{
940 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100941 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
942 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200943}
944
945int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
946{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100947 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
948 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200949}
950
951int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
952{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100953 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
954 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200955}