blob: 134b47520d0e2c41c81b2560d399a5e28da27f3e [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 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
Harald Welted38c8b82011-08-30 11:32:56 +020026/*! \mainpage libosmogsm Documentation
27 *
28 * \section sec_intro Introduction
29 * This library is a collection of common code used in various
30 * GSM related sub-projects inside the Osmocom family of projects. It
31 * includes A5/1 and A5/2 ciphers, COMP128v1, a LAPDm implementation,
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +020032 * a GSM TLV parser, SMS utility routines as well as
Harald Welted38c8b82011-08-30 11:32:56 +020033 * protocol definitions for a series of protocols:
34 * * Um L2 (04.06)
35 * * Um L3 (04.08)
36 * * A-bis RSL (08.58)
37 * * A-bis OML (08.59, 12.21)
38 * * A (08.08)
39 * \n\n
40 * Please note that C language projects inside Osmocom are typically
41 * single-threaded event-loop state machine designs. As such,
42 * routines in libosmogsm are not thread-safe. If you must use them in
43 * a multi-threaded context, you have to add your own locking.
44 *
Harald Welte71658802017-06-12 15:40:52 +020045 * libosmogsm is developed as part of the Osmocom (Open Source Mobile
46 * Communications) project, a community-based, collaborative development
47 * project to create Free and Open Source implementations of mobile
48 * communications systems. For more information about Osmocom, please
49 * see https://osmocom.org/
50 *
Harald Welted38c8b82011-08-30 11:32:56 +020051 * \section sec_copyright Copyright and License
52 * Copyright © 2008-2011 - Harald Welte, Holger Freyther and contributors\n
53 * All rights reserved. \n\n
54 * The source code of libosmogsm is licensed under the terms of the GNU
55 * General Public License as published by the Free Software Foundation;
56 * either version 2 of the License, or (at your option) any later
57 * version.\n
58 * See <http://www.gnu.org/licenses/> or COPYING included in the source
59 * code package istelf.\n
60 * The information detailed here is provided AS IS with NO WARRANTY OF
61 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
62 * FITNESS FOR A PARTICULAR PURPOSE.
63 * \n\n
64 *
Harald Welte71658802017-06-12 15:40:52 +020065 * \section sec_tracker Homepage + Issue Tracker
66 * libosmogsm is distributed as part of libosmocore and shares its
67 * project page at http://osmocom.org/projects/libosmocore
68 *
69 * An Issue Tracker can be found at
70 * https://osmocom.org/projects/libosmocore/issues
71 *
Harald Welted38c8b82011-08-30 11:32:56 +020072 * \section sec_contact Contact and Support
73 * Community-based support is available at the OpenBSC mailing list
74 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
75 * Commercial support options available upon request from
76 * <http://sysmocom.de/>
77 */
78
Harald Welteec8b4502010-02-20 20:34:29 +010079//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010080#include <osmocom/core/utils.h>
Max8a5346b2016-04-22 19:28:09 +020081#include <osmocom/core/bitvec.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010082#include <osmocom/gsm/gsm_utils.h>
Max764b0222016-05-11 17:33:17 +020083#include <osmocom/gsm/meas_rep.h>
Max8a5346b2016-04-22 19:28:09 +020084#include <osmocom/gsm/protocol/gsm_04_08.h>
Harald Welteec8b4502010-02-20 20:34:29 +010085
86#include <stdlib.h>
87#include <stdint.h>
88#include <string.h>
Max764b0222016-05-11 17:33:17 +020089#include <stdbool.h>
Harald Welteec8b4502010-02-20 20:34:29 +010090#include <stdio.h>
91#include <errno.h>
Harald Welteaebe08c2010-03-04 10:39:17 +010092#include <ctype.h>
Pau Espin Pedrol363130f2017-07-03 10:42:42 +020093#include <inttypes.h>
Max4b2b0cc2017-07-10 14:32:48 +020094#include <time.h>
95#include <unistd.h>
Harald Welteec8b4502010-02-20 20:34:29 +010096
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010097#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010098
Max4b2b0cc2017-07-10 14:32:48 +020099/* FIXME: this can be removed once we bump glibc requirements to 2.25: */
100#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
101#include <linux/random.h>
102#elif HAVE_DECL_SYS_GETRANDOM
103#include <sys/syscall.h>
Maxf6245462017-10-09 14:35:03 +0200104#ifndef GRND_NONBLOCK
105#define GRND_NONBLOCK 0x0001
106#endif
Max4b2b0cc2017-07-10 14:32:48 +0200107#endif
108
Maxed029df2017-10-26 10:56:04 +0200109#if (USE_GNUTLS)
110#pragma message ("including GnuTLS for getrandom fallback.")
111#include <gnutls/gnutls.h>
112#include <gnutls/crypto.h>
113#endif
114
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800115/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
116 * Greek symbols at hex positions 0x10 and 0x12-0x1a
117 * left out as they can't be handled with a char and
118 * since most phones don't display or write these
119 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200120 * more complex.
121 *
122 * Note that this table contains the latin1->7bit mapping _and_ has
123 * been merged with the reverse mapping (7bit->latin1) for the
124 * extended characters at offset 0x7f.
125 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800126static unsigned char gsm_7bit_alphabet[] = {
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
130 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
131 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
132 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
133 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
134 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
135 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
138 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
140 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
141 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
142 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
143 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
144};
145
Nico Golde28de0532010-07-09 17:19:12 +0200146/* GSM 03.38 6.2.1 Character lookup for decoding */
147static int gsm_septet_lookup(uint8_t ch)
148{
149 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200150 for (; i < sizeof(gsm_7bit_alphabet); i++) {
151 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200152 return i;
153 }
154 return -1;
155}
156
Harald Welte96e2a002017-06-12 21:44:18 +0200157/*! \brife Compute number of octets from number of septets,
158 * for instance: 47 septets needs 41,125 = 42 octets
159 * \param[in sept_len Number of Septets
160 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200161uint8_t gsm_get_octet_len(const uint8_t sept_len){
162 int octet_len = (sept_len * 7) / 8;
163 if ((sept_len * 7) % 8 != 0)
164 octet_len++;
165
166 return octet_len;
167}
168
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200169/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200170 * \param[out] text Caller-provided output text buffer
171 * \param[in] n Length of \a text
172 * \param[in] user_data Input Data (septets)
173 * \param[in] septet_l Number of septets in \a user_data
174 * \param[in] ud_hdr_ind User Data Header present in data
175 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200176int 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 +0100177{
Maxcf37c4c2016-01-21 16:52:40 +0100178 unsigned shift = 0;
179 uint8_t c7, c8, next_is_ext = 0, lu, ru;
180 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200181 const char *text_buf_begin = text;
182 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200183
184 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100185
Dennis Wehrle291e6132011-07-24 20:14:13 +0200186 /* skip the user data header */
187 if (ud_hdr_ind) {
188 /* get user data header length + 1 (for the 'user data header length'-field) */
189 shift = ((user_data[0] + 1) * 8) / 7;
190 if ((((user_data[0] + 1) * 8) % 7) != 0)
191 shift++;
192 septet_l = septet_l - shift;
193 }
194
Maxcf37c4c2016-01-21 16:52:40 +0100195 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200196 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100197
198 l = ((i + shift) * 7 + 7) >> 3;
199 r = ((i + shift) * 7) >> 3;
200
201 /* the left side index is always >= right side index
202 sometimes it even gets beyond array boundary
203 check for that explicitly and force 0 instead
204 */
205 if (l >= maxlen)
206 lu = 0;
207 else
208 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
209
210 ru = user_data[r] >> (((i + shift) * 7) & 7);
211
212 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200213
Harald Weltebe55a8b2012-09-20 10:00:25 +0200214 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200215 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200216 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200217 c8 = gsm_7bit_alphabet[0x7f + c7];
218 } else if (c7 == 0x1b && i + 1 < septet_l) {
219 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200220 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200221 } else {
222 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200223 }
224
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200225 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100226 }
227
Nico Golde28de0532010-07-09 17:19:12 +0200228 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200229
Maxcf37c4c2016-01-21 16:52:40 +0100230 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200231}
232
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200233/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200234int 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 +0200235{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200236 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200237}
238
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200239/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200240int 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 +0200241{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200242 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200243
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200244 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200245 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200246 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
247 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200248
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200249 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200250}
251
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200252/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200253 *
254 * This function converts a zero-terminated input string \a data from
255 * ASCII into octet-aligned 7-bit GSM characters. No packing is
256 * performed.
257 *
258 * \param[out] result caller-allocated output buffer
259 * \param[in] data input data, ASCII
260 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200261int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200262{
263 int i, y = 0;
264 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200265 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200266 ch = data[i];
267 switch(ch){
268 /* fall-through for extension characters */
269 case 0x0c:
270 case 0x5e:
271 case 0x7b:
272 case 0x7d:
273 case 0x5c:
274 case 0x5b:
275 case 0x7e:
276 case 0x5d:
277 case 0x7c:
278 result[y++] = 0x1b;
279 default:
280 result[y] = gsm_7bit_alphabet[ch];
281 break;
282 }
283 y++;
284 }
285
286 return y;
287}
288
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200289/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200290 * \param[out] result Caller-provided output buffer
291 * \param[in] rdata Input data septets
292 * \param[in] septet_len Length of \a rdata
293 * \param[in] padding padding bits at start
294 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100295int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
296{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200297 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200298 uint8_t cb, nb;
299 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200300 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200301
Dennis Wehrle291e6132011-07-24 20:14:13 +0200302 if (padding) {
303 shift = 7 - padding;
304 /* the first zero is needed for padding */
305 memcpy(data + 1, rdata, septet_len);
306 septet_len++;
307 } else
308 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200309
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200310 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200311 if (shift == 7) {
312 /*
313 * special end case with the. This is necessary if the
314 * last septet fits into the previous octet. E.g. 48
315 * non-extension characters:
316 * ....ag ( a = 1100001, g = 1100111)
317 * result[40] = 100001 XX, result[41] = 1100111 1 */
318 if (i + 1 < septet_len) {
319 shift = 0;
320 continue;
321 } else if (i + 1 == septet_len)
322 break;
Nico Golde28de0532010-07-09 17:19:12 +0200323 }
324
Dennis Wehrle291e6132011-07-24 20:14:13 +0200325 cb = (data[i] & 0x7f) >> shift;
326 if (i + 1 < septet_len) {
327 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200328 cb = cb | nb;
329 }
330
331 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200332 shift++;
333 }
334
Dennis Wehrle291e6132011-07-24 20:14:13 +0200335 free(data);
336
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200337 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100338}
339
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200340/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200341 * \param[out] result Caller-provided output buffer
342 * \param[in] n Maximum length of \a result in bytes
343 * \param[in] data octet-aligned string
344 * \param[out] octets Number of octets encoded
345 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200346int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200347{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200348 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200349 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100350 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200351
Dennis Wehrle291e6132011-07-24 20:14:13 +0200352 /* prepare for the worst case, every character expanding to two bytes */
353 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
354 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200355
356 if (y > max_septets) {
357 /*
358 * Limit the number of septets to avoid the generation
359 * of more than n octets.
360 */
361 y = max_septets;
362 }
363
364 o = gsm_septets2octets(result, rdata, y, 0);
365
366 if (octets)
367 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200368
369 free(rdata);
370
371 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200372 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200373 * unique. E.g.:
374 * 1.) 46 non-extension characters + 1 extension character
375 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
376 * 2.) 47 non-extension characters
377 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
378 * 3.) 48 non-extension characters
379 * => (48 * 7 bit) / 8 bit = 42 octects
380 */
381 return y;
382}
383
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200384/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200385 * \param[out] result Caller-provided output buffer
386 * \param[in] n Maximum length of \a result in bytes
387 * \param[in] data octet-aligned string
388 * \param[out] octets Number of octets encoded
389 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200390int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
391{
392 int y;
393
394 y = gsm_7bit_encode_n(result, n, data, octets);
395 /* if last octet contains only one bit, add <CR> */
396 if (((y * 7) & 7) == 1)
397 result[(*octets) - 1] |= ('\r' << 1);
398 /* if last character is <CR> and completely fills last octet, add
399 * another <CR>. */
400 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
401 result[(*octets)++] = '\r';
402 y++;
403 }
404
405 return y;
406}
407
Max4b2b0cc2017-07-10 14:32:48 +0200408/*! Generate random identifier
409 * We use /dev/urandom (default when GRND_RANDOM flag is not set).
410 * Both /dev/(u)random numbers are coming from the same CSPRNG anyway (at least on GNU/Linux >= 4.8).
411 * See also RFC4086.
412 * \param[out] out Buffer to be filled with random data
413 * \param[in] len Number of random bytes required
414 * \returns 0 on success, or a negative error code on error.
415 */
416int osmo_get_rand_id(uint8_t *out, size_t len)
417{
Maxed029df2017-10-26 10:56:04 +0200418 int rc = -ENOTSUP;
Max4b2b0cc2017-07-10 14:32:48 +0200419
420 /* this function is intended for generating short identifiers only, not arbitrary-length random data */
421 if (len > OSMO_MAX_RAND_ID_LEN)
422 return -E2BIG;
423
424#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
425 rc = getrandom(out, len, GRND_NONBLOCK);
426#elif HAVE_DECL_SYS_GETRANDOM
427#pragma message ("Using direct syscall access for getrandom(): consider upgrading to glibc >= 2.25")
428 /* FIXME: this can be removed once we bump glibc requirements to 2.25: */
429 rc = syscall(SYS_getrandom, out, len, GRND_NONBLOCK);
Max4b2b0cc2017-07-10 14:32:48 +0200430#endif
Maxed029df2017-10-26 10:56:04 +0200431
Max4b2b0cc2017-07-10 14:32:48 +0200432 /* getrandom() failed entirely: */
Maxed029df2017-10-26 10:56:04 +0200433 if (rc < 0) {
434#if (USE_GNUTLS)
435#pragma message ("Secure random failed: using GnuTLS fallback.")
436 return gnutls_rnd(GNUTLS_RND_RANDOM, out, len);
437#endif
Max4b2b0cc2017-07-10 14:32:48 +0200438 return -errno;
Maxed029df2017-10-26 10:56:04 +0200439 }
Max4b2b0cc2017-07-10 14:32:48 +0200440
441 /* getrandom() failed partially due to signal interruption:
442 this should never happen (according to getrandom(2)) as long as OSMO_MAX_RAND_ID_LEN < 256
443 because we do not set GRND_RANDOM but it's better to be paranoid and check anyway */
444 if (rc != len)
445 return -EAGAIN;
446
447 return 0;
448}
449
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200450/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200451 * \param[in] mru Unidirectional measurement report structure
452 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
453 * period
454 * \param[out] buf Pre-allocated bufer for storing IE
455 * \returns Number of bytes filled in buf
456 */
457size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
458 uint8_t *buf)
459{
460 buf[0] = dtxd_used ? (1 << 6) : 0;
461 buf[0] |= (mru->full.rx_lev & 0x3f);
462 buf[1] = (mru->sub.rx_lev & 0x3f);
463 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
464
465 return 3;
466}
467
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200468/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200469 * \param[in] band GSM frequency band
470 * \param[in] class GSM power class
471 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200472unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
473{
474 switch (band) {
475 case GSM_BAND_450:
476 case GSM_BAND_480:
477 case GSM_BAND_750:
478 case GSM_BAND_900:
479 case GSM_BAND_810:
480 case GSM_BAND_850:
481 if (class == 1)
482 return 43; /* 20W */
483 if (class == 2)
484 return 39; /* 8W */
485 if (class == 3)
486 return 37; /* 5W */
487 if (class == 4)
488 return 33; /* 2W */
489 if (class == 5)
490 return 29; /* 0.8W */
491 break;
492 case GSM_BAND_1800:
493 if (class == 1)
494 return 30; /* 1W */
495 if (class == 2)
496 return 24; /* 0.25W */
497 if (class == 3)
498 return 36; /* 4W */
499 break;
500 case GSM_BAND_1900:
501 if (class == 1)
502 return 30; /* 1W */
503 if (class == 2)
504 return 24; /* 0.25W */
505 if (class == 3)
506 return 33; /* 2W */
507 break;
508 }
509 return -EINVAL;
510}
511
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200512/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200513 * by the tables in chapter 4.1.1 of GSM TS 05.05
514 * \param[in] GSM frequency band
515 * \param[in] dbm RF power value in dBm
516 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100517int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
518{
519 switch (band) {
520 case GSM_BAND_450:
521 case GSM_BAND_480:
522 case GSM_BAND_750:
523 case GSM_BAND_900:
524 case GSM_BAND_810:
525 case GSM_BAND_850:
526 if (dbm >= 39)
527 return 0;
528 else if (dbm < 5)
529 return 19;
530 else {
531 /* we are guaranteed to have (5 <= dbm < 39) */
532 return 2 + ((39 - dbm) / 2);
533 }
534 break;
535 case GSM_BAND_1800:
536 if (dbm >= 36)
537 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200538 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100539 return 30;
540 else if (dbm >= 32)
541 return 31;
542 else if (dbm == 31)
543 return 0;
544 else {
545 /* we are guaranteed to have (0 <= dbm < 31) */
546 return (30 - dbm) / 2;
547 }
548 break;
549 case GSM_BAND_1900:
550 if (dbm >= 33)
551 return 30;
552 else if (dbm >= 32)
553 return 31;
554 else if (dbm == 31)
555 return 0;
556 else {
557 /* we are guaranteed to have (0 <= dbm < 31) */
558 return (30 - dbm) / 2;
559 }
560 break;
561 }
562 return -EINVAL;
563}
564
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200565/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200566 * \param[in] band GSM frequency band
567 * \param[in] lvl TS 05.05 power control level
568 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100569int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
570{
571 lvl &= 0x1f;
572
573 switch (band) {
574 case GSM_BAND_450:
575 case GSM_BAND_480:
576 case GSM_BAND_750:
577 case GSM_BAND_900:
578 case GSM_BAND_810:
579 case GSM_BAND_850:
580 if (lvl < 2)
581 return 39;
582 else if (lvl < 20)
583 return 39 - ((lvl - 2) * 2) ;
584 else
585 return 5;
586 break;
587 case GSM_BAND_1800:
588 if (lvl < 16)
589 return 30 - (lvl * 2);
590 else if (lvl < 29)
591 return 0;
592 else
593 return 36 - ((lvl - 29) * 2);
594 break;
595 case GSM_BAND_1900:
596 if (lvl < 16)
597 return 30 - (lvl * 2);
598 else if (lvl < 30)
599 return -EINVAL;
600 else
601 return 33 - (lvl - 30);
602 break;
603 }
604 return -EINVAL;
605}
606
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200607/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200608 * \param[in] rxlev TS 05.08 RxLev value
609 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100610int rxlev2dbm(uint8_t rxlev)
611{
612 if (rxlev > 63)
613 rxlev = 63;
614
615 return -110 + rxlev;
616}
617
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200618/*! 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 +0200619 * \param[in] dbm RF signal level in dBm
620 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100621uint8_t dbm2rxlev(int dbm)
622{
623 int rxlev = dbm + 110;
624
625 if (rxlev > 63)
626 rxlev = 63;
627 else if (rxlev < 0)
628 rxlev = 0;
629
630 return rxlev;
631}
632
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200633/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800634const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100635{
636 switch (band) {
637 case GSM_BAND_450:
638 return "GSM450";
639 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200640 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100641 case GSM_BAND_750:
642 return "GSM750";
643 case GSM_BAND_810:
644 return "GSM810";
645 case GSM_BAND_850:
646 return "GSM850";
647 case GSM_BAND_900:
648 return "GSM900";
649 case GSM_BAND_1800:
650 return "DCS1800";
651 case GSM_BAND_1900:
652 return "PCS1900";
653 }
654 return "invalid";
655}
656
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200657/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100658enum gsm_band gsm_band_parse(const char* mhz)
659{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200660 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100661 mhz++;
662
663 if (*mhz == '\0')
664 return -EINVAL;
665
Harald Welted3ff15f2010-03-07 18:23:47 +0100666 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100667 case 450:
668 return GSM_BAND_450;
669 case 480:
670 return GSM_BAND_480;
671 case 750:
672 return GSM_BAND_750;
673 case 810:
674 return GSM_BAND_810;
675 case 850:
676 return GSM_BAND_850;
677 case 900:
678 return GSM_BAND_900;
679 case 1800:
680 return GSM_BAND_1800;
681 case 1900:
682 return GSM_BAND_1900;
683 default:
684 return -EINVAL;
685 }
686}
687
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200688/*! Resolve GSM band from ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200689 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
690 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
691 * \returns GSM Band */
Harald Welte622b7182010-03-07 17:50:21 +0100692enum gsm_band gsm_arfcn2band(uint16_t arfcn)
693{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100694 int is_pcs = arfcn & ARFCN_PCS;
695
696 arfcn &= ~ARFCN_FLAG_MASK;
697
698 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100699 return GSM_BAND_1900;
700 else if (arfcn <= 124)
701 return GSM_BAND_900;
702 else if (arfcn >= 955 && arfcn <= 1023)
703 return GSM_BAND_900;
704 else if (arfcn >= 128 && arfcn <= 251)
705 return GSM_BAND_850;
706 else if (arfcn >= 512 && arfcn <= 885)
707 return GSM_BAND_1800;
708 else if (arfcn >= 259 && arfcn <= 293)
709 return GSM_BAND_450;
710 else if (arfcn >= 306 && arfcn <= 340)
711 return GSM_BAND_480;
712 else if (arfcn >= 350 && arfcn <= 425)
713 return GSM_BAND_810;
714 else if (arfcn >= 438 && arfcn <= 511)
715 return GSM_BAND_750;
716 else
717 return GSM_BAND_1800;
718}
719
Sylvain Munaut55720312012-12-11 23:44:41 +0100720struct gsm_freq_range {
721 uint16_t arfcn_first;
722 uint16_t arfcn_last;
723 uint16_t freq_ul_first;
724 uint16_t freq_dl_offset;
725 uint16_t flags;
726};
727
728static struct gsm_freq_range gsm_ranges[] = {
729 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
730 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
731 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
732 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
733 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
734 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
735 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
736 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
737 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
738 { /* Guard */ }
739};
740
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200741/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200742 * \param[in] arfcn GSM ARFCN to convert
743 * \param[in] uplink Uplink (1) or Downlink (0) frequency
744 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100745uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
746{
Sylvain Munaut55720312012-12-11 23:44:41 +0100747 struct gsm_freq_range *r;
748 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
749 uint16_t freq10_ul = 0xffff;
750 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100751
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100752 arfcn &= ~ARFCN_FLAG_MASK;
753
Sylvain Munaut55720312012-12-11 23:44:41 +0100754 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
755 if ((flags == r->flags) &&
756 (arfcn >= r->arfcn_first) &&
757 (arfcn <= r->arfcn_last))
758 {
759 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
760 freq10_dl = freq10_ul + r->freq_dl_offset;
761 break;
762 }
763 }
764
765 return uplink ? freq10_ul : freq10_dl;
766}
767
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200768/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200769 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
770 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
771 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100772uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
773{
774 struct gsm_freq_range *r;
775 uint16_t freq10_lo, freq10_hi;
776 uint16_t arfcn = 0xffff;
777
778 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
779 /* Generate frequency limits */
780 freq10_lo = r->freq_ul_first;
781 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
782 if (!uplink) {
783 freq10_lo += r->freq_dl_offset;
784 freq10_hi += r->freq_dl_offset;
785 }
786
787 /* Check if this fits */
788 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
789 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
790 arfcn |= r->flags;
791 break;
792 }
793 }
Harald Welte622b7182010-03-07 17:50:21 +0100794
795 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100796 arfcn |= ARFCN_UPLINK;
797
798 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100799}
800
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200801/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200802 * \param[out] time Caller-provided memory for \ref gsm_time
803 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100804void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
805{
806 time->fn = fn;
807 time->t1 = time->fn / (26*51);
808 time->t2 = time->fn % 26;
809 time->t3 = time->fn % 51;
810 time->tc = (time->fn / 51) % 8;
811}
812
Philipp Maierb808da42017-06-26 10:50:28 +0200813/*! Parse GSM Frame Number into printable string
814 * \param[in] fn GSM Frame Number
815 * \returns pointer to printable string */
816char *gsm_fn_as_gsmtime_str(uint32_t fn)
817{
818 struct gsm_time time;
819
820 gsm_fn2gsmtime(&time, fn);
821 return osmo_dump_gsmtime(&time);
822}
823
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200824/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200825 * \param[in] time GSM Time in decoded structure
826 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100827uint32_t gsm_gsmtime2fn(struct gsm_time *time)
828{
829 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
830 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
831}
Harald Weltea1c4f762010-05-01 11:59:42 +0200832
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200833char *osmo_dump_gsmtime(const struct gsm_time *tm)
834{
835 static char buf[64];
836
837 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
838 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
839 buf[sizeof(buf)-1] = '\0';
840 return buf;
841}
842
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200843/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200844 * \param[out] bv Caller-provided output bit-vector
845 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200846void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
847{
848 bitvec_set_uint(bv, r->w1_hi, 2);
849 bitvec_set_uint(bv, r->w1_lo, 8);
850 bitvec_set_uint(bv, r->w2_hi, 8);
851 bitvec_set_uint(bv, r->w2_lo, 1);
852 bitvec_set_uint(bv, r->w3_hi, 7);
853 bitvec_set_uint(bv, r->w3_lo, 2);
854 bitvec_set_uint(bv, r->w4_hi, 6);
855 bitvec_set_uint(bv, r->w4_lo, 2);
856 bitvec_set_uint(bv, r->w5_hi, 6);
857 bitvec_set_uint(bv, r->w5_lo, 2);
858 bitvec_set_uint(bv, r->w6_hi, 6);
859 bitvec_set_uint(bv, r->w6_lo, 2);
860 bitvec_set_uint(bv, r->w7_hi, 6);
861 bitvec_set_uint(bv, r->w7_lo, 2);
862 bitvec_set_uint(bv, r->w8_hi, 6);
863 bitvec_set_uint(bv, r->w8_lo, 1);
864 bitvec_set_uint(bv, r->w9, 7);
865 bitvec_set_uint(bv, r->w10, 7);
866 bitvec_set_uint(bv, r->w11_hi, 1);
867 bitvec_set_uint(bv, r->w11_lo, 6);
868 bitvec_set_uint(bv, r->w12_hi, 2);
869 bitvec_set_uint(bv, r->w12_lo, 5);
870 bitvec_set_uint(bv, r->w13_hi, 3);
871 bitvec_set_uint(bv, r->w13_lo, 4);
872 bitvec_set_uint(bv, r->w14_hi, 4);
873 bitvec_set_uint(bv, r->w14_lo, 3);
874 bitvec_set_uint(bv, r->w15_hi, 5);
875 bitvec_set_uint(bv, r->w15_lo, 2);
876 bitvec_set_uint(bv, r->w16, 6);
877}
878
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200879/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200880int gprs_tlli_type(uint32_t tlli)
881{
882 if ((tlli & 0xc0000000) == 0xc0000000)
883 return TLLI_LOCAL;
884 else if ((tlli & 0xc0000000) == 0x80000000)
885 return TLLI_FOREIGN;
886 else if ((tlli & 0xf8000000) == 0x78000000)
887 return TLLI_RANDOM;
888 else if ((tlli & 0xf8000000) == 0x70000000)
889 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200890 else if ((tlli & 0xf0000000) == 0x00000000)
891 return TLLI_G_RNTI;
892 else if ((tlli & 0xf0000000) == 0x10000000)
893 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200894
895 return TLLI_RESERVED;
896}
Harald Weltec2263172010-06-01 10:47:07 +0200897
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200898/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200899 * \param[in] p_tmsi P-TMSI
900 * \param[in] type TLLI Type we want to derive from \a p_tmsi
901 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200902uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
903{
904 uint32_t tlli;
905 switch (type) {
906 case TLLI_LOCAL:
907 tlli = p_tmsi | 0xc0000000;
908 break;
909 case TLLI_FOREIGN:
910 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
911 break;
912 default:
913 tlli = 0;
914 break;
915 }
916 return tlli;
917}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200918
919/* Wrappers for deprecated functions: */
920
921int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
922{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100923 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
924 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200925
926 /* Mimic the original behaviour. */
927 return septet_l;
928}
929
930int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
931{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100932 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
933 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200934}
935
936int gsm_7bit_encode(uint8_t *result, const char *data)
937{
938 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100939 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
940 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200941}
942
943int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
944{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100945 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
946 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200947}
948
949int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
950{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100951 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
952 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200953}