blob: 61d3f83352d018b958dd5bf049f687edd0fb5584 [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>
Harald Welteec8b4502010-02-20 20:34:29 +010093
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010094#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010095
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080096/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
97 * Greek symbols at hex positions 0x10 and 0x12-0x1a
98 * left out as they can't be handled with a char and
99 * since most phones don't display or write these
100 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200101 * more complex.
102 *
103 * Note that this table contains the latin1->7bit mapping _and_ has
104 * been merged with the reverse mapping (7bit->latin1) for the
105 * extended characters at offset 0x7f.
106 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800107static unsigned char gsm_7bit_alphabet[] = {
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
111 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
112 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
113 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
114 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
115 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
116 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
119 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
121 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
122 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
123 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
124 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
125};
126
Nico Golde28de0532010-07-09 17:19:12 +0200127/* GSM 03.38 6.2.1 Character lookup for decoding */
128static int gsm_septet_lookup(uint8_t ch)
129{
130 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200131 for (; i < sizeof(gsm_7bit_alphabet); i++) {
132 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200133 return i;
134 }
135 return -1;
136}
137
Harald Welte96e2a002017-06-12 21:44:18 +0200138/*! \brife Compute number of octets from number of septets,
139 * for instance: 47 septets needs 41,125 = 42 octets
140 * \param[in sept_len Number of Septets
141 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200142uint8_t gsm_get_octet_len(const uint8_t sept_len){
143 int octet_len = (sept_len * 7) / 8;
144 if ((sept_len * 7) % 8 != 0)
145 octet_len++;
146
147 return octet_len;
148}
149
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200150/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200151 * \param[out] text Caller-provided output text buffer
152 * \param[in] n Length of \a text
153 * \param[in] user_data Input Data (septets)
154 * \param[in] septet_l Number of septets in \a user_data
155 * \param[in] ud_hdr_ind User Data Header present in data
156 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200157int 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 +0100158{
Maxcf37c4c2016-01-21 16:52:40 +0100159 unsigned shift = 0;
160 uint8_t c7, c8, next_is_ext = 0, lu, ru;
161 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200162 const char *text_buf_begin = text;
163 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200164
165 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100166
Dennis Wehrle291e6132011-07-24 20:14:13 +0200167 /* skip the user data header */
168 if (ud_hdr_ind) {
169 /* get user data header length + 1 (for the 'user data header length'-field) */
170 shift = ((user_data[0] + 1) * 8) / 7;
171 if ((((user_data[0] + 1) * 8) % 7) != 0)
172 shift++;
173 septet_l = septet_l - shift;
174 }
175
Maxcf37c4c2016-01-21 16:52:40 +0100176 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200177 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100178
179 l = ((i + shift) * 7 + 7) >> 3;
180 r = ((i + shift) * 7) >> 3;
181
182 /* the left side index is always >= right side index
183 sometimes it even gets beyond array boundary
184 check for that explicitly and force 0 instead
185 */
186 if (l >= maxlen)
187 lu = 0;
188 else
189 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
190
191 ru = user_data[r] >> (((i + shift) * 7) & 7);
192
193 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200194
Harald Weltebe55a8b2012-09-20 10:00:25 +0200195 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200196 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200197 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200198 c8 = gsm_7bit_alphabet[0x7f + c7];
199 } else if (c7 == 0x1b && i + 1 < septet_l) {
200 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200201 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200202 } else {
203 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200204 }
205
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200206 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100207 }
208
Nico Golde28de0532010-07-09 17:19:12 +0200209 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200210
Maxcf37c4c2016-01-21 16:52:40 +0100211 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200212}
213
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200214/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200215int 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 +0200216{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200217 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200218}
219
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200220/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200221int 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 +0200222{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200223 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200224
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200225 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200226 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200227 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
228 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200229
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200230 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200231}
232
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200233/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200234 *
235 * This function converts a zero-terminated input string \a data from
236 * ASCII into octet-aligned 7-bit GSM characters. No packing is
237 * performed.
238 *
239 * \param[out] result caller-allocated output buffer
240 * \param[in] data input data, ASCII
241 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200242int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200243{
244 int i, y = 0;
245 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200246 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200247 ch = data[i];
248 switch(ch){
249 /* fall-through for extension characters */
250 case 0x0c:
251 case 0x5e:
252 case 0x7b:
253 case 0x7d:
254 case 0x5c:
255 case 0x5b:
256 case 0x7e:
257 case 0x5d:
258 case 0x7c:
259 result[y++] = 0x1b;
260 default:
261 result[y] = gsm_7bit_alphabet[ch];
262 break;
263 }
264 y++;
265 }
266
267 return y;
268}
269
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200270/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200271 * \param[out] result Caller-provided output buffer
272 * \param[in] rdata Input data septets
273 * \param[in] septet_len Length of \a rdata
274 * \param[in] padding padding bits at start
275 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100276int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
277{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200278 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200279 uint8_t cb, nb;
280 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200281 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200282
Dennis Wehrle291e6132011-07-24 20:14:13 +0200283 if (padding) {
284 shift = 7 - padding;
285 /* the first zero is needed for padding */
286 memcpy(data + 1, rdata, septet_len);
287 septet_len++;
288 } else
289 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200290
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200291 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200292 if (shift == 7) {
293 /*
294 * special end case with the. This is necessary if the
295 * last septet fits into the previous octet. E.g. 48
296 * non-extension characters:
297 * ....ag ( a = 1100001, g = 1100111)
298 * result[40] = 100001 XX, result[41] = 1100111 1 */
299 if (i + 1 < septet_len) {
300 shift = 0;
301 continue;
302 } else if (i + 1 == septet_len)
303 break;
Nico Golde28de0532010-07-09 17:19:12 +0200304 }
305
Dennis Wehrle291e6132011-07-24 20:14:13 +0200306 cb = (data[i] & 0x7f) >> shift;
307 if (i + 1 < septet_len) {
308 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200309 cb = cb | nb;
310 }
311
312 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200313 shift++;
314 }
315
Dennis Wehrle291e6132011-07-24 20:14:13 +0200316 free(data);
317
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200318 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100319}
320
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200321/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200322 * \param[out] result Caller-provided output buffer
323 * \param[in] n Maximum length of \a result in bytes
324 * \param[in] data octet-aligned string
325 * \param[out] octets Number of octets encoded
326 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200327int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200328{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200329 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200330 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100331 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200332
Dennis Wehrle291e6132011-07-24 20:14:13 +0200333 /* prepare for the worst case, every character expanding to two bytes */
334 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
335 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200336
337 if (y > max_septets) {
338 /*
339 * Limit the number of septets to avoid the generation
340 * of more than n octets.
341 */
342 y = max_septets;
343 }
344
345 o = gsm_septets2octets(result, rdata, y, 0);
346
347 if (octets)
348 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200349
350 free(rdata);
351
352 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200353 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200354 * unique. E.g.:
355 * 1.) 46 non-extension characters + 1 extension character
356 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
357 * 2.) 47 non-extension characters
358 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
359 * 3.) 48 non-extension characters
360 * => (48 * 7 bit) / 8 bit = 42 octects
361 */
362 return y;
363}
364
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200365/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200366 * \param[out] result Caller-provided output buffer
367 * \param[in] n Maximum length of \a result in bytes
368 * \param[in] data octet-aligned string
369 * \param[out] octets Number of octets encoded
370 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200371int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
372{
373 int y;
374
375 y = gsm_7bit_encode_n(result, n, data, octets);
376 /* if last octet contains only one bit, add <CR> */
377 if (((y * 7) & 7) == 1)
378 result[(*octets) - 1] |= ('\r' << 1);
379 /* if last character is <CR> and completely fills last octet, add
380 * another <CR>. */
381 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
382 result[(*octets)++] = '\r';
383 y++;
384 }
385
386 return y;
387}
388
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200389/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200390 * \param[in] mru Unidirectional measurement report structure
391 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
392 * period
393 * \param[out] buf Pre-allocated bufer for storing IE
394 * \returns Number of bytes filled in buf
395 */
396size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
397 uint8_t *buf)
398{
399 buf[0] = dtxd_used ? (1 << 6) : 0;
400 buf[0] |= (mru->full.rx_lev & 0x3f);
401 buf[1] = (mru->sub.rx_lev & 0x3f);
402 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
403
404 return 3;
405}
406
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200407/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200408 * \param[in] band GSM frequency band
409 * \param[in] class GSM power class
410 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200411unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
412{
413 switch (band) {
414 case GSM_BAND_450:
415 case GSM_BAND_480:
416 case GSM_BAND_750:
417 case GSM_BAND_900:
418 case GSM_BAND_810:
419 case GSM_BAND_850:
420 if (class == 1)
421 return 43; /* 20W */
422 if (class == 2)
423 return 39; /* 8W */
424 if (class == 3)
425 return 37; /* 5W */
426 if (class == 4)
427 return 33; /* 2W */
428 if (class == 5)
429 return 29; /* 0.8W */
430 break;
431 case GSM_BAND_1800:
432 if (class == 1)
433 return 30; /* 1W */
434 if (class == 2)
435 return 24; /* 0.25W */
436 if (class == 3)
437 return 36; /* 4W */
438 break;
439 case GSM_BAND_1900:
440 if (class == 1)
441 return 30; /* 1W */
442 if (class == 2)
443 return 24; /* 0.25W */
444 if (class == 3)
445 return 33; /* 2W */
446 break;
447 }
448 return -EINVAL;
449}
450
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200451/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200452 * by the tables in chapter 4.1.1 of GSM TS 05.05
453 * \param[in] GSM frequency band
454 * \param[in] dbm RF power value in dBm
455 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100456int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
457{
458 switch (band) {
459 case GSM_BAND_450:
460 case GSM_BAND_480:
461 case GSM_BAND_750:
462 case GSM_BAND_900:
463 case GSM_BAND_810:
464 case GSM_BAND_850:
465 if (dbm >= 39)
466 return 0;
467 else if (dbm < 5)
468 return 19;
469 else {
470 /* we are guaranteed to have (5 <= dbm < 39) */
471 return 2 + ((39 - dbm) / 2);
472 }
473 break;
474 case GSM_BAND_1800:
475 if (dbm >= 36)
476 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200477 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100478 return 30;
479 else if (dbm >= 32)
480 return 31;
481 else if (dbm == 31)
482 return 0;
483 else {
484 /* we are guaranteed to have (0 <= dbm < 31) */
485 return (30 - dbm) / 2;
486 }
487 break;
488 case GSM_BAND_1900:
489 if (dbm >= 33)
490 return 30;
491 else if (dbm >= 32)
492 return 31;
493 else if (dbm == 31)
494 return 0;
495 else {
496 /* we are guaranteed to have (0 <= dbm < 31) */
497 return (30 - dbm) / 2;
498 }
499 break;
500 }
501 return -EINVAL;
502}
503
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200504/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200505 * \param[in] band GSM frequency band
506 * \param[in] lvl TS 05.05 power control level
507 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100508int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
509{
510 lvl &= 0x1f;
511
512 switch (band) {
513 case GSM_BAND_450:
514 case GSM_BAND_480:
515 case GSM_BAND_750:
516 case GSM_BAND_900:
517 case GSM_BAND_810:
518 case GSM_BAND_850:
519 if (lvl < 2)
520 return 39;
521 else if (lvl < 20)
522 return 39 - ((lvl - 2) * 2) ;
523 else
524 return 5;
525 break;
526 case GSM_BAND_1800:
527 if (lvl < 16)
528 return 30 - (lvl * 2);
529 else if (lvl < 29)
530 return 0;
531 else
532 return 36 - ((lvl - 29) * 2);
533 break;
534 case GSM_BAND_1900:
535 if (lvl < 16)
536 return 30 - (lvl * 2);
537 else if (lvl < 30)
538 return -EINVAL;
539 else
540 return 33 - (lvl - 30);
541 break;
542 }
543 return -EINVAL;
544}
545
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200546/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200547 * \param[in] rxlev TS 05.08 RxLev value
548 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100549int rxlev2dbm(uint8_t rxlev)
550{
551 if (rxlev > 63)
552 rxlev = 63;
553
554 return -110 + rxlev;
555}
556
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200557/*! 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 +0200558 * \param[in] dbm RF signal level in dBm
559 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100560uint8_t dbm2rxlev(int dbm)
561{
562 int rxlev = dbm + 110;
563
564 if (rxlev > 63)
565 rxlev = 63;
566 else if (rxlev < 0)
567 rxlev = 0;
568
569 return rxlev;
570}
571
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200572/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800573const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100574{
575 switch (band) {
576 case GSM_BAND_450:
577 return "GSM450";
578 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200579 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100580 case GSM_BAND_750:
581 return "GSM750";
582 case GSM_BAND_810:
583 return "GSM810";
584 case GSM_BAND_850:
585 return "GSM850";
586 case GSM_BAND_900:
587 return "GSM900";
588 case GSM_BAND_1800:
589 return "DCS1800";
590 case GSM_BAND_1900:
591 return "PCS1900";
592 }
593 return "invalid";
594}
595
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200596/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100597enum gsm_band gsm_band_parse(const char* mhz)
598{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200599 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100600 mhz++;
601
602 if (*mhz == '\0')
603 return -EINVAL;
604
Harald Welted3ff15f2010-03-07 18:23:47 +0100605 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100606 case 450:
607 return GSM_BAND_450;
608 case 480:
609 return GSM_BAND_480;
610 case 750:
611 return GSM_BAND_750;
612 case 810:
613 return GSM_BAND_810;
614 case 850:
615 return GSM_BAND_850;
616 case 900:
617 return GSM_BAND_900;
618 case 1800:
619 return GSM_BAND_1800;
620 case 1900:
621 return GSM_BAND_1900;
622 default:
623 return -EINVAL;
624 }
625}
626
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200627/*! Resolve GSM band from ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200628 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
629 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
630 * \returns GSM Band */
Harald Welte622b7182010-03-07 17:50:21 +0100631enum gsm_band gsm_arfcn2band(uint16_t arfcn)
632{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100633 int is_pcs = arfcn & ARFCN_PCS;
634
635 arfcn &= ~ARFCN_FLAG_MASK;
636
637 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100638 return GSM_BAND_1900;
639 else if (arfcn <= 124)
640 return GSM_BAND_900;
641 else if (arfcn >= 955 && arfcn <= 1023)
642 return GSM_BAND_900;
643 else if (arfcn >= 128 && arfcn <= 251)
644 return GSM_BAND_850;
645 else if (arfcn >= 512 && arfcn <= 885)
646 return GSM_BAND_1800;
647 else if (arfcn >= 259 && arfcn <= 293)
648 return GSM_BAND_450;
649 else if (arfcn >= 306 && arfcn <= 340)
650 return GSM_BAND_480;
651 else if (arfcn >= 350 && arfcn <= 425)
652 return GSM_BAND_810;
653 else if (arfcn >= 438 && arfcn <= 511)
654 return GSM_BAND_750;
655 else
656 return GSM_BAND_1800;
657}
658
Sylvain Munaut55720312012-12-11 23:44:41 +0100659struct gsm_freq_range {
660 uint16_t arfcn_first;
661 uint16_t arfcn_last;
662 uint16_t freq_ul_first;
663 uint16_t freq_dl_offset;
664 uint16_t flags;
665};
666
667static struct gsm_freq_range gsm_ranges[] = {
668 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
669 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
670 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
671 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
672 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
673 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
674 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
675 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
676 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
677 { /* Guard */ }
678};
679
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200680/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200681 * \param[in] arfcn GSM ARFCN to convert
682 * \param[in] uplink Uplink (1) or Downlink (0) frequency
683 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100684uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
685{
Sylvain Munaut55720312012-12-11 23:44:41 +0100686 struct gsm_freq_range *r;
687 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
688 uint16_t freq10_ul = 0xffff;
689 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100690
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100691 arfcn &= ~ARFCN_FLAG_MASK;
692
Sylvain Munaut55720312012-12-11 23:44:41 +0100693 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
694 if ((flags == r->flags) &&
695 (arfcn >= r->arfcn_first) &&
696 (arfcn <= r->arfcn_last))
697 {
698 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
699 freq10_dl = freq10_ul + r->freq_dl_offset;
700 break;
701 }
702 }
703
704 return uplink ? freq10_ul : freq10_dl;
705}
706
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200707/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200708 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
709 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
710 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100711uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
712{
713 struct gsm_freq_range *r;
714 uint16_t freq10_lo, freq10_hi;
715 uint16_t arfcn = 0xffff;
716
717 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
718 /* Generate frequency limits */
719 freq10_lo = r->freq_ul_first;
720 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
721 if (!uplink) {
722 freq10_lo += r->freq_dl_offset;
723 freq10_hi += r->freq_dl_offset;
724 }
725
726 /* Check if this fits */
727 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
728 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
729 arfcn |= r->flags;
730 break;
731 }
732 }
Harald Welte622b7182010-03-07 17:50:21 +0100733
734 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100735 arfcn |= ARFCN_UPLINK;
736
737 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100738}
739
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200740/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200741 * \param[out] time Caller-provided memory for \ref gsm_time
742 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100743void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
744{
745 time->fn = fn;
746 time->t1 = time->fn / (26*51);
747 time->t2 = time->fn % 26;
748 time->t3 = time->fn % 51;
749 time->tc = (time->fn / 51) % 8;
750}
751
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200752/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200753 * \param[in] time GSM Time in decoded structure
754 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100755uint32_t gsm_gsmtime2fn(struct gsm_time *time)
756{
757 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
758 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
759}
Harald Weltea1c4f762010-05-01 11:59:42 +0200760
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200761/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200762 * \param[out] bv Caller-provided output bit-vector
763 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200764void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
765{
766 bitvec_set_uint(bv, r->w1_hi, 2);
767 bitvec_set_uint(bv, r->w1_lo, 8);
768 bitvec_set_uint(bv, r->w2_hi, 8);
769 bitvec_set_uint(bv, r->w2_lo, 1);
770 bitvec_set_uint(bv, r->w3_hi, 7);
771 bitvec_set_uint(bv, r->w3_lo, 2);
772 bitvec_set_uint(bv, r->w4_hi, 6);
773 bitvec_set_uint(bv, r->w4_lo, 2);
774 bitvec_set_uint(bv, r->w5_hi, 6);
775 bitvec_set_uint(bv, r->w5_lo, 2);
776 bitvec_set_uint(bv, r->w6_hi, 6);
777 bitvec_set_uint(bv, r->w6_lo, 2);
778 bitvec_set_uint(bv, r->w7_hi, 6);
779 bitvec_set_uint(bv, r->w7_lo, 2);
780 bitvec_set_uint(bv, r->w8_hi, 6);
781 bitvec_set_uint(bv, r->w8_lo, 1);
782 bitvec_set_uint(bv, r->w9, 7);
783 bitvec_set_uint(bv, r->w10, 7);
784 bitvec_set_uint(bv, r->w11_hi, 1);
785 bitvec_set_uint(bv, r->w11_lo, 6);
786 bitvec_set_uint(bv, r->w12_hi, 2);
787 bitvec_set_uint(bv, r->w12_lo, 5);
788 bitvec_set_uint(bv, r->w13_hi, 3);
789 bitvec_set_uint(bv, r->w13_lo, 4);
790 bitvec_set_uint(bv, r->w14_hi, 4);
791 bitvec_set_uint(bv, r->w14_lo, 3);
792 bitvec_set_uint(bv, r->w15_hi, 5);
793 bitvec_set_uint(bv, r->w15_lo, 2);
794 bitvec_set_uint(bv, r->w16, 6);
795}
796
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200797/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200798int gprs_tlli_type(uint32_t tlli)
799{
800 if ((tlli & 0xc0000000) == 0xc0000000)
801 return TLLI_LOCAL;
802 else if ((tlli & 0xc0000000) == 0x80000000)
803 return TLLI_FOREIGN;
804 else if ((tlli & 0xf8000000) == 0x78000000)
805 return TLLI_RANDOM;
806 else if ((tlli & 0xf8000000) == 0x70000000)
807 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200808 else if ((tlli & 0xf0000000) == 0x00000000)
809 return TLLI_G_RNTI;
810 else if ((tlli & 0xf0000000) == 0x10000000)
811 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200812
813 return TLLI_RESERVED;
814}
Harald Weltec2263172010-06-01 10:47:07 +0200815
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200816/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200817 * \param[in] p_tmsi P-TMSI
818 * \param[in] type TLLI Type we want to derive from \a p_tmsi
819 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200820uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
821{
822 uint32_t tlli;
823 switch (type) {
824 case TLLI_LOCAL:
825 tlli = p_tmsi | 0xc0000000;
826 break;
827 case TLLI_FOREIGN:
828 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
829 break;
830 default:
831 tlli = 0;
832 break;
833 }
834 return tlli;
835}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200836
837/* Wrappers for deprecated functions: */
838
839int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
840{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100841 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
842 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200843
844 /* Mimic the original behaviour. */
845 return septet_l;
846}
847
848int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
849{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100850 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
851 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200852}
853
854int gsm_7bit_encode(uint8_t *result, const char *data)
855{
856 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100857 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
858 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200859}
860
861int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
862{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100863 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
864 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200865}
866
867int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
868{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100869 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
870 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200871}