blob: 477f076d90766d4a9897be6ebcc177bc2ce59ca9 [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>
Harald Welteec8b4502010-02-20 20:34:29 +010094
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010095#include "../../config.h"
Harald Welteec8b4502010-02-20 20:34:29 +010096
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +080097/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet
98 * Greek symbols at hex positions 0x10 and 0x12-0x1a
99 * left out as they can't be handled with a char and
100 * since most phones don't display or write these
101 * characters this would only needlessly make the code
Jacob Erlbeck18109252013-08-12 17:07:54 +0200102 * more complex.
103 *
104 * Note that this table contains the latin1->7bit mapping _and_ has
105 * been merged with the reverse mapping (7bit->latin1) for the
106 * extended characters at offset 0x7f.
107 */
Holger Hans Peter Freytherdd02a472010-07-23 16:35:00 +0800108static unsigned char gsm_7bit_alphabet[] = {
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
112 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
113 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
114 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
115 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
116 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
117 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff,
119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff,
120 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff,
122 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d,
123 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f,
124 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
125 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff
126};
127
Nico Golde28de0532010-07-09 17:19:12 +0200128/* GSM 03.38 6.2.1 Character lookup for decoding */
129static int gsm_septet_lookup(uint8_t ch)
130{
131 int i = 0;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200132 for (; i < sizeof(gsm_7bit_alphabet); i++) {
133 if (gsm_7bit_alphabet[i] == ch)
Nico Golde28de0532010-07-09 17:19:12 +0200134 return i;
135 }
136 return -1;
137}
138
Harald Welte96e2a002017-06-12 21:44:18 +0200139/*! \brife Compute number of octets from number of septets,
140 * for instance: 47 septets needs 41,125 = 42 octets
141 * \param[in sept_len Number of Septets
142 * \returns Number of octets required */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200143uint8_t gsm_get_octet_len(const uint8_t sept_len){
144 int octet_len = (sept_len * 7) / 8;
145 if ((sept_len * 7) % 8 != 0)
146 octet_len++;
147
148 return octet_len;
149}
150
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200151/*! TS 03.38 7-bit Character unpacking (6.2.1)
Harald Welte96e2a002017-06-12 21:44:18 +0200152 * \param[out] text Caller-provided output text buffer
153 * \param[in] n Length of \a text
154 * \param[in] user_data Input Data (septets)
155 * \param[in] septet_l Number of septets in \a user_data
156 * \param[in] ud_hdr_ind User Data Header present in data
157 * \returns number of bytes written to \a text */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200158int 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 +0100159{
Maxcf37c4c2016-01-21 16:52:40 +0100160 unsigned shift = 0;
161 uint8_t c7, c8, next_is_ext = 0, lu, ru;
162 const uint8_t maxlen = gsm_get_octet_len(septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200163 const char *text_buf_begin = text;
164 const char *text_buf_end = text + n;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200165
166 OSMO_ASSERT (n > 0);
Harald Welteec8b4502010-02-20 20:34:29 +0100167
Dennis Wehrle291e6132011-07-24 20:14:13 +0200168 /* skip the user data header */
169 if (ud_hdr_ind) {
170 /* get user data header length + 1 (for the 'user data header length'-field) */
171 shift = ((user_data[0] + 1) * 8) / 7;
172 if ((((user_data[0] + 1) * 8) % 7) != 0)
173 shift++;
174 septet_l = septet_l - shift;
175 }
176
Maxcf37c4c2016-01-21 16:52:40 +0100177 unsigned i, l, r;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200178 for (i = 0; i < septet_l && text != text_buf_end - 1; i++) {
Maxcf37c4c2016-01-21 16:52:40 +0100179
180 l = ((i + shift) * 7 + 7) >> 3;
181 r = ((i + shift) * 7) >> 3;
182
183 /* the left side index is always >= right side index
184 sometimes it even gets beyond array boundary
185 check for that explicitly and force 0 instead
186 */
187 if (l >= maxlen)
188 lu = 0;
189 else
190 lu = user_data[l] << (7 - (((i + shift) * 7 + 7) & 7));
191
192 ru = user_data[r] >> (((i + shift) * 7) & 7);
193
194 c7 = (lu | ru) & 0x7f;
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200195
Harald Weltebe55a8b2012-09-20 10:00:25 +0200196 if (next_is_ext) {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200197 /* this is an extension character */
Nico Goldec56a56d2012-09-18 14:29:40 +0200198 next_is_ext = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200199 c8 = gsm_7bit_alphabet[0x7f + c7];
200 } else if (c7 == 0x1b && i + 1 < septet_l) {
201 next_is_ext = 1;
Nico Golde5b67a042012-09-20 16:56:23 +0200202 continue;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200203 } else {
204 c8 = gsm_septet_lookup(c7);
Nico Golde5b67a042012-09-20 16:56:23 +0200205 }
206
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200207 *(text++) = c8;
Harald Welteec8b4502010-02-20 20:34:29 +0100208 }
209
Nico Golde28de0532010-07-09 17:19:12 +0200210 *text = '\0';
Nico Golde28de0532010-07-09 17:19:12 +0200211
Maxcf37c4c2016-01-21 16:52:40 +0100212 return text - text_buf_begin;
Nico Golde28de0532010-07-09 17:19:12 +0200213}
214
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200215/*! Decode 7bit GSM Alphabet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200216int 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 +0200217{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200218 return gsm_7bit_decode_n_hdr(text, n, user_data, septet_l, 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200219}
220
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200221/*! Decode 7bit GSM Alphabet (USSD) */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200222int 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 +0200223{
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200224 int nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200225
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200226 nchars = gsm_7bit_decode_n_hdr(text, n, user_data, length, 0);
Andreas Eversberg95975552013-08-08 12:38:53 +0200227 /* remove last <CR>, if it fits up to the end of last octet */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200228 if (nchars && (user_data[gsm_get_octet_len(length) - 1] >> 1) == '\r')
229 text[--nchars] = '\0';
Andreas Eversberg95975552013-08-08 12:38:53 +0200230
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200231 return nchars;
Andreas Eversberg95975552013-08-08 12:38:53 +0200232}
233
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200234/*! Encode a ASCII characterrs as 7-bit GSM alphabet (TS 03.38)
Harald Welte96e2a002017-06-12 21:44:18 +0200235 *
236 * This function converts a zero-terminated input string \a data from
237 * ASCII into octet-aligned 7-bit GSM characters. No packing is
238 * performed.
239 *
240 * \param[out] result caller-allocated output buffer
241 * \param[in] data input data, ASCII
242 * \returns number of octets used in \a result */
Dennis Wehrle291e6132011-07-24 20:14:13 +0200243int gsm_septet_encode(uint8_t *result, const char *data)
Nico Golde28de0532010-07-09 17:19:12 +0200244{
245 int i, y = 0;
246 uint8_t ch;
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200247 for (i = 0; i < strlen(data); i++) {
Nico Golde28de0532010-07-09 17:19:12 +0200248 ch = data[i];
249 switch(ch){
250 /* fall-through for extension characters */
251 case 0x0c:
252 case 0x5e:
253 case 0x7b:
254 case 0x7d:
255 case 0x5c:
256 case 0x5b:
257 case 0x7e:
258 case 0x5d:
259 case 0x7c:
260 result[y++] = 0x1b;
261 default:
262 result[y] = gsm_7bit_alphabet[ch];
263 break;
264 }
265 y++;
266 }
267
268 return y;
269}
270
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200271/*! GSM Default Alphabet 7bit to octet packing
Harald Welte96e2a002017-06-12 21:44:18 +0200272 * \param[out] result Caller-provided output buffer
273 * \param[in] rdata Input data septets
274 * \param[in] septet_len Length of \a rdata
275 * \param[in] padding padding bits at start
276 * \returns number of bytes used in \a result */
Harald Welteca693882013-03-13 15:10:55 +0100277int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len, uint8_t padding)
278{
Dennis Wehrle291e6132011-07-24 20:14:13 +0200279 int i = 0, z = 0;
Nico Golde28de0532010-07-09 17:19:12 +0200280 uint8_t cb, nb;
281 int shift = 0;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200282 uint8_t *data = calloc(septet_len + 1, sizeof(uint8_t));
Nico Golde28de0532010-07-09 17:19:12 +0200283
Dennis Wehrle291e6132011-07-24 20:14:13 +0200284 if (padding) {
285 shift = 7 - padding;
286 /* the first zero is needed for padding */
287 memcpy(data + 1, rdata, septet_len);
288 septet_len++;
289 } else
290 memcpy(data, rdata, septet_len);
Nico Golde28de0532010-07-09 17:19:12 +0200291
Holger Hans Peter Freyther7e1a6222011-07-24 20:17:00 +0200292 for (i = 0; i < septet_len; i++) {
Dennis Wehrle291e6132011-07-24 20:14:13 +0200293 if (shift == 7) {
294 /*
295 * special end case with the. This is necessary if the
296 * last septet fits into the previous octet. E.g. 48
297 * non-extension characters:
298 * ....ag ( a = 1100001, g = 1100111)
299 * result[40] = 100001 XX, result[41] = 1100111 1 */
300 if (i + 1 < septet_len) {
301 shift = 0;
302 continue;
303 } else if (i + 1 == septet_len)
304 break;
Nico Golde28de0532010-07-09 17:19:12 +0200305 }
306
Dennis Wehrle291e6132011-07-24 20:14:13 +0200307 cb = (data[i] & 0x7f) >> shift;
308 if (i + 1 < septet_len) {
309 nb = (data[i + 1] & 0x7f) << (7 - shift);
Nico Golde28de0532010-07-09 17:19:12 +0200310 cb = cb | nb;
311 }
312
313 result[z++] = cb;
Nico Golde28de0532010-07-09 17:19:12 +0200314 shift++;
315 }
316
Dennis Wehrle291e6132011-07-24 20:14:13 +0200317 free(data);
318
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200319 return z;
Harald Welteec8b4502010-02-20 20:34:29 +0100320}
321
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200322/*! GSM 7-bit alphabet TS 03.38 6.2.1 Character packing
Harald Welte96e2a002017-06-12 21:44:18 +0200323 * \param[out] result Caller-provided output buffer
324 * \param[in] n Maximum length of \a result in bytes
325 * \param[in] data octet-aligned string
326 * \param[out] octets Number of octets encoded
327 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200328int gsm_7bit_encode_n(uint8_t *result, size_t n, const char *data, int *octets)
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200329{
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200330 int y = 0;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200331 int o;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100332 size_t max_septets = n * 8 / 7;
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200333
Dennis Wehrle291e6132011-07-24 20:14:13 +0200334 /* prepare for the worst case, every character expanding to two bytes */
335 uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t));
336 y = gsm_septet_encode(rdata, data);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200337
338 if (y > max_septets) {
339 /*
340 * Limit the number of septets to avoid the generation
341 * of more than n octets.
342 */
343 y = max_septets;
344 }
345
346 o = gsm_septets2octets(result, rdata, y, 0);
347
348 if (octets)
349 *octets = o;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200350
351 free(rdata);
352
353 /*
Holger Hans Peter Freythercc7d9ec2012-09-11 10:38:43 +0200354 * We don't care about the number of octets, because they are not
Dennis Wehrle291e6132011-07-24 20:14:13 +0200355 * unique. E.g.:
356 * 1.) 46 non-extension characters + 1 extension character
357 * => (46 * 7 bit + (1 * (2 * 7 bit))) / 8 bit = 42 octets
358 * 2.) 47 non-extension characters
359 * => (47 * 7 bit) / 8 bit = 41,125 = 42 octets
360 * 3.) 48 non-extension characters
361 * => (48 * 7 bit) / 8 bit = 42 octects
362 */
363 return y;
364}
365
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200366/*! Encode according to GSM 7-bit alphabet (TS 03.38 6.2.1) for USSD
Harald Welte96e2a002017-06-12 21:44:18 +0200367 * \param[out] result Caller-provided output buffer
368 * \param[in] n Maximum length of \a result in bytes
369 * \param[in] data octet-aligned string
370 * \param[out] octets Number of octets encoded
371 * \returns number of septets encoded */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200372int gsm_7bit_encode_n_ussd(uint8_t *result, size_t n, const char *data, int *octets)
373{
374 int y;
375
376 y = gsm_7bit_encode_n(result, n, data, octets);
377 /* if last octet contains only one bit, add <CR> */
378 if (((y * 7) & 7) == 1)
379 result[(*octets) - 1] |= ('\r' << 1);
380 /* if last character is <CR> and completely fills last octet, add
381 * another <CR>. */
382 if (y && ((y * 7) & 7) == 0 && (result[(*octets) - 1] >> 1) == '\r' && *octets < n - 1) {
383 result[(*octets)++] = '\r';
384 y++;
385 }
386
387 return y;
388}
389
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200390/*! Build the RSL uplink measurement IE (3GPP TS 08.58 § 9.3.25)
Max764b0222016-05-11 17:33:17 +0200391 * \param[in] mru Unidirectional measurement report structure
392 * \param[in] dtxd_used Indicates if DTXd was used during measurement report
393 * period
394 * \param[out] buf Pre-allocated bufer for storing IE
395 * \returns Number of bytes filled in buf
396 */
397size_t gsm0858_rsl_ul_meas_enc(struct gsm_meas_rep_unidir *mru, bool dtxd_used,
398 uint8_t *buf)
399{
400 buf[0] = dtxd_used ? (1 << 6) : 0;
401 buf[0] |= (mru->full.rx_lev & 0x3f);
402 buf[1] = (mru->sub.rx_lev & 0x3f);
403 buf[2] = ((mru->full.rx_qual & 7) << 3) | (mru->sub.rx_qual & 7);
404
405 return 3;
406}
407
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200408/*! Convert power class to dBm according to GSM TS 05.05
Harald Welte96e2a002017-06-12 21:44:18 +0200409 * \param[in] band GSM frequency band
410 * \param[in] class GSM power class
411 * \returns maximum transmit power of power class in dBm */
Andreas Eversberg2a68c7c2011-06-26 11:41:48 +0200412unsigned int ms_class_gmsk_dbm(enum gsm_band band, int class)
413{
414 switch (band) {
415 case GSM_BAND_450:
416 case GSM_BAND_480:
417 case GSM_BAND_750:
418 case GSM_BAND_900:
419 case GSM_BAND_810:
420 case GSM_BAND_850:
421 if (class == 1)
422 return 43; /* 20W */
423 if (class == 2)
424 return 39; /* 8W */
425 if (class == 3)
426 return 37; /* 5W */
427 if (class == 4)
428 return 33; /* 2W */
429 if (class == 5)
430 return 29; /* 0.8W */
431 break;
432 case GSM_BAND_1800:
433 if (class == 1)
434 return 30; /* 1W */
435 if (class == 2)
436 return 24; /* 0.25W */
437 if (class == 3)
438 return 36; /* 4W */
439 break;
440 case GSM_BAND_1900:
441 if (class == 1)
442 return 30; /* 1W */
443 if (class == 2)
444 return 24; /* 0.25W */
445 if (class == 3)
446 return 33; /* 2W */
447 break;
448 }
449 return -EINVAL;
450}
451
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200452/*! determine power control level for given dBm value, as indicated
Harald Welte96e2a002017-06-12 21:44:18 +0200453 * by the tables in chapter 4.1.1 of GSM TS 05.05
454 * \param[in] GSM frequency band
455 * \param[in] dbm RF power value in dBm
456 * \returns TS 05.05 power control level */
Harald Welteec8b4502010-02-20 20:34:29 +0100457int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
458{
459 switch (band) {
460 case GSM_BAND_450:
461 case GSM_BAND_480:
462 case GSM_BAND_750:
463 case GSM_BAND_900:
464 case GSM_BAND_810:
465 case GSM_BAND_850:
466 if (dbm >= 39)
467 return 0;
468 else if (dbm < 5)
469 return 19;
470 else {
471 /* we are guaranteed to have (5 <= dbm < 39) */
472 return 2 + ((39 - dbm) / 2);
473 }
474 break;
475 case GSM_BAND_1800:
476 if (dbm >= 36)
477 return 29;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200478 else if (dbm >= 34)
Harald Welteec8b4502010-02-20 20:34:29 +0100479 return 30;
480 else if (dbm >= 32)
481 return 31;
482 else if (dbm == 31)
483 return 0;
484 else {
485 /* we are guaranteed to have (0 <= dbm < 31) */
486 return (30 - dbm) / 2;
487 }
488 break;
489 case GSM_BAND_1900:
490 if (dbm >= 33)
491 return 30;
492 else if (dbm >= 32)
493 return 31;
494 else if (dbm == 31)
495 return 0;
496 else {
497 /* we are guaranteed to have (0 <= dbm < 31) */
498 return (30 - dbm) / 2;
499 }
500 break;
501 }
502 return -EINVAL;
503}
504
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200505/*! Convert TS 05.05 power level to absolute dBm value
Harald Welte96e2a002017-06-12 21:44:18 +0200506 * \param[in] band GSM frequency band
507 * \param[in] lvl TS 05.05 power control level
508 * \returns RF power level in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100509int ms_pwr_dbm(enum gsm_band band, uint8_t lvl)
510{
511 lvl &= 0x1f;
512
513 switch (band) {
514 case GSM_BAND_450:
515 case GSM_BAND_480:
516 case GSM_BAND_750:
517 case GSM_BAND_900:
518 case GSM_BAND_810:
519 case GSM_BAND_850:
520 if (lvl < 2)
521 return 39;
522 else if (lvl < 20)
523 return 39 - ((lvl - 2) * 2) ;
524 else
525 return 5;
526 break;
527 case GSM_BAND_1800:
528 if (lvl < 16)
529 return 30 - (lvl * 2);
530 else if (lvl < 29)
531 return 0;
532 else
533 return 36 - ((lvl - 29) * 2);
534 break;
535 case GSM_BAND_1900:
536 if (lvl < 16)
537 return 30 - (lvl * 2);
538 else if (lvl < 30)
539 return -EINVAL;
540 else
541 return 33 - (lvl - 30);
542 break;
543 }
544 return -EINVAL;
545}
546
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200547/*! Convert TS 05.08 RxLev to dBm (TS 05.08 Chapter 8.1.4)
Harald Welte96e2a002017-06-12 21:44:18 +0200548 * \param[in] rxlev TS 05.08 RxLev value
549 * \returns Received RF power in dBm */
Harald Welteec8b4502010-02-20 20:34:29 +0100550int rxlev2dbm(uint8_t rxlev)
551{
552 if (rxlev > 63)
553 rxlev = 63;
554
555 return -110 + rxlev;
556}
557
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200558/*! 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 +0200559 * \param[in] dbm RF signal level in dBm
560 * \returns TS 05.08 RxLev value */
Harald Welteec8b4502010-02-20 20:34:29 +0100561uint8_t dbm2rxlev(int dbm)
562{
563 int rxlev = dbm + 110;
564
565 if (rxlev > 63)
566 rxlev = 63;
567 else if (rxlev < 0)
568 rxlev = 0;
569
570 return rxlev;
571}
572
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200573/*! Return string name of a given GSM Band */
Harald Weltecbc80622010-03-22 08:28:44 +0800574const char *gsm_band_name(enum gsm_band band)
Harald Welteaebe08c2010-03-04 10:39:17 +0100575{
576 switch (band) {
577 case GSM_BAND_450:
578 return "GSM450";
579 case GSM_BAND_480:
Sylvain Munaute10ae5b2010-07-04 11:41:36 +0200580 return "GSM480";
Harald Welteaebe08c2010-03-04 10:39:17 +0100581 case GSM_BAND_750:
582 return "GSM750";
583 case GSM_BAND_810:
584 return "GSM810";
585 case GSM_BAND_850:
586 return "GSM850";
587 case GSM_BAND_900:
588 return "GSM900";
589 case GSM_BAND_1800:
590 return "DCS1800";
591 case GSM_BAND_1900:
592 return "PCS1900";
593 }
594 return "invalid";
595}
596
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200597/*! Parse string name of a GSM band */
Harald Welteaebe08c2010-03-04 10:39:17 +0100598enum gsm_band gsm_band_parse(const char* mhz)
599{
Pau Espin Pedrol399a6f02017-06-18 14:07:37 +0200600 while (*mhz && !isdigit((unsigned char)*mhz))
Harald Welteaebe08c2010-03-04 10:39:17 +0100601 mhz++;
602
603 if (*mhz == '\0')
604 return -EINVAL;
605
Harald Welted3ff15f2010-03-07 18:23:47 +0100606 switch (strtol(mhz, NULL, 10)) {
Harald Welteaebe08c2010-03-04 10:39:17 +0100607 case 450:
608 return GSM_BAND_450;
609 case 480:
610 return GSM_BAND_480;
611 case 750:
612 return GSM_BAND_750;
613 case 810:
614 return GSM_BAND_810;
615 case 850:
616 return GSM_BAND_850;
617 case 900:
618 return GSM_BAND_900;
619 case 1800:
620 return GSM_BAND_1800;
621 case 1900:
622 return GSM_BAND_1900;
623 default:
624 return -EINVAL;
625 }
626}
627
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200628/*! Resolve GSM band from ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200629 * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS
630 * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode
631 * \returns GSM Band */
Harald Welte622b7182010-03-07 17:50:21 +0100632enum gsm_band gsm_arfcn2band(uint16_t arfcn)
633{
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100634 int is_pcs = arfcn & ARFCN_PCS;
635
636 arfcn &= ~ARFCN_FLAG_MASK;
637
638 if (is_pcs)
Harald Welte622b7182010-03-07 17:50:21 +0100639 return GSM_BAND_1900;
640 else if (arfcn <= 124)
641 return GSM_BAND_900;
642 else if (arfcn >= 955 && arfcn <= 1023)
643 return GSM_BAND_900;
644 else if (arfcn >= 128 && arfcn <= 251)
645 return GSM_BAND_850;
646 else if (arfcn >= 512 && arfcn <= 885)
647 return GSM_BAND_1800;
648 else if (arfcn >= 259 && arfcn <= 293)
649 return GSM_BAND_450;
650 else if (arfcn >= 306 && arfcn <= 340)
651 return GSM_BAND_480;
652 else if (arfcn >= 350 && arfcn <= 425)
653 return GSM_BAND_810;
654 else if (arfcn >= 438 && arfcn <= 511)
655 return GSM_BAND_750;
656 else
657 return GSM_BAND_1800;
658}
659
Sylvain Munaut55720312012-12-11 23:44:41 +0100660struct gsm_freq_range {
661 uint16_t arfcn_first;
662 uint16_t arfcn_last;
663 uint16_t freq_ul_first;
664 uint16_t freq_dl_offset;
665 uint16_t flags;
666};
667
668static struct gsm_freq_range gsm_ranges[] = {
669 { 512, 810, 18502, 800, ARFCN_PCS }, /* PCS 1900 */
670 { 0, 124, 8900, 450, 0 }, /* P-GSM + E-GSM ARFCN 0 */
671 { 955, 1023, 8762, 450, 0 }, /* E-GSM + R-GSM */
672 { 128, 251, 8242, 450, 0 }, /* GSM 850 */
673 { 512, 885, 17102, 950, 0 }, /* DCS 1800 */
674 { 259, 293, 4506, 100, 0 }, /* GSM 450 */
675 { 306, 340, 4790, 100, 0 }, /* GSM 480 */
676 { 350, 425, 8060, 450, 0 }, /* GSM 810 */
677 { 438, 511, 7472, 300, 0 }, /* GSM 750 */
678 { /* Guard */ }
679};
680
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200681/*! Convert an ARFCN to the frequency in MHz * 10
Harald Welte96e2a002017-06-12 21:44:18 +0200682 * \param[in] arfcn GSM ARFCN to convert
683 * \param[in] uplink Uplink (1) or Downlink (0) frequency
684 * \returns Frequency in units of 1/10ths of MHz (100kHz) */
Harald Welte622b7182010-03-07 17:50:21 +0100685uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
686{
Sylvain Munaut55720312012-12-11 23:44:41 +0100687 struct gsm_freq_range *r;
688 uint16_t flags = arfcn & ARFCN_FLAG_MASK;
689 uint16_t freq10_ul = 0xffff;
690 uint16_t freq10_dl = 0xffff;
Harald Welte622b7182010-03-07 17:50:21 +0100691
Sylvain Munaut2a471ee2010-11-13 17:51:37 +0100692 arfcn &= ~ARFCN_FLAG_MASK;
693
Sylvain Munaut55720312012-12-11 23:44:41 +0100694 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
695 if ((flags == r->flags) &&
696 (arfcn >= r->arfcn_first) &&
697 (arfcn <= r->arfcn_last))
698 {
699 freq10_ul = r->freq_ul_first + 2 * (arfcn - r->arfcn_first);
700 freq10_dl = freq10_ul + r->freq_dl_offset;
701 break;
702 }
703 }
704
705 return uplink ? freq10_ul : freq10_dl;
706}
707
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200708/*! Convert a Frequency in MHz * 10 to ARFCN
Harald Welte96e2a002017-06-12 21:44:18 +0200709 * \param[in] freq10 Frequency in units of 1/10ths of MHz (100kHz)
710 * \param[in] uplink Frequency is Uplink (1) or Downlink (0)
711 * \returns ARFCN in case of success; 0xffff on error */
Sylvain Munaut55720312012-12-11 23:44:41 +0100712uint16_t gsm_freq102arfcn(uint16_t freq10, int uplink)
713{
714 struct gsm_freq_range *r;
715 uint16_t freq10_lo, freq10_hi;
716 uint16_t arfcn = 0xffff;
717
718 for (r=gsm_ranges; r->freq_ul_first>0; r++) {
719 /* Generate frequency limits */
720 freq10_lo = r->freq_ul_first;
721 freq10_hi = freq10_lo + 2 * (r->arfcn_last - r->arfcn_first);
722 if (!uplink) {
723 freq10_lo += r->freq_dl_offset;
724 freq10_hi += r->freq_dl_offset;
725 }
726
727 /* Check if this fits */
728 if (freq10 >= freq10_lo && freq10 <= freq10_hi) {
729 arfcn = r->arfcn_first + ((freq10 - freq10_lo) >> 1);
730 arfcn |= r->flags;
731 break;
732 }
733 }
Harald Welte622b7182010-03-07 17:50:21 +0100734
735 if (uplink)
Sylvain Munaut55720312012-12-11 23:44:41 +0100736 arfcn |= ARFCN_UPLINK;
737
738 return arfcn;
Harald Welte622b7182010-03-07 17:50:21 +0100739}
740
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200741/*! Parse GSM Frame Number into struct \ref gsm_time
Harald Welte96e2a002017-06-12 21:44:18 +0200742 * \param[out] time Caller-provided memory for \ref gsm_time
743 * \param[in] fn GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100744void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
745{
746 time->fn = fn;
747 time->t1 = time->fn / (26*51);
748 time->t2 = time->fn % 26;
749 time->t3 = time->fn % 51;
750 time->tc = (time->fn / 51) % 8;
751}
752
Philipp Maierb808da42017-06-26 10:50:28 +0200753/*! Parse GSM Frame Number into printable string
754 * \param[in] fn GSM Frame Number
755 * \returns pointer to printable string */
756char *gsm_fn_as_gsmtime_str(uint32_t fn)
757{
758 struct gsm_time time;
759
760 gsm_fn2gsmtime(&time, fn);
761 return osmo_dump_gsmtime(&time);
762}
763
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200764/*! Encode decoded \ref gsm_time to Frame Number
Harald Welte96e2a002017-06-12 21:44:18 +0200765 * \param[in] time GSM Time in decoded structure
766 * \returns GSM Frame Number */
Harald Welte622b7182010-03-07 17:50:21 +0100767uint32_t gsm_gsmtime2fn(struct gsm_time *time)
768{
769 /* TS 05.02 Chapter 4.3.3 TDMA frame number */
770 return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
771}
Harald Weltea1c4f762010-05-01 11:59:42 +0200772
Pau Espin Pedrol363130f2017-07-03 10:42:42 +0200773char *osmo_dump_gsmtime(const struct gsm_time *tm)
774{
775 static char buf[64];
776
777 snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,
778 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);
779 buf[sizeof(buf)-1] = '\0';
780 return buf;
781}
782
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200783/*! append range1024 encoded data to bit vector
Harald Welte96e2a002017-06-12 21:44:18 +0200784 * \param[out] bv Caller-provided output bit-vector
785 * \param[in] r Input Range1024 sructure */
Max8a5346b2016-04-22 19:28:09 +0200786void bitvec_add_range1024(struct bitvec *bv, const struct gsm48_range_1024 *r)
787{
788 bitvec_set_uint(bv, r->w1_hi, 2);
789 bitvec_set_uint(bv, r->w1_lo, 8);
790 bitvec_set_uint(bv, r->w2_hi, 8);
791 bitvec_set_uint(bv, r->w2_lo, 1);
792 bitvec_set_uint(bv, r->w3_hi, 7);
793 bitvec_set_uint(bv, r->w3_lo, 2);
794 bitvec_set_uint(bv, r->w4_hi, 6);
795 bitvec_set_uint(bv, r->w4_lo, 2);
796 bitvec_set_uint(bv, r->w5_hi, 6);
797 bitvec_set_uint(bv, r->w5_lo, 2);
798 bitvec_set_uint(bv, r->w6_hi, 6);
799 bitvec_set_uint(bv, r->w6_lo, 2);
800 bitvec_set_uint(bv, r->w7_hi, 6);
801 bitvec_set_uint(bv, r->w7_lo, 2);
802 bitvec_set_uint(bv, r->w8_hi, 6);
803 bitvec_set_uint(bv, r->w8_lo, 1);
804 bitvec_set_uint(bv, r->w9, 7);
805 bitvec_set_uint(bv, r->w10, 7);
806 bitvec_set_uint(bv, r->w11_hi, 1);
807 bitvec_set_uint(bv, r->w11_lo, 6);
808 bitvec_set_uint(bv, r->w12_hi, 2);
809 bitvec_set_uint(bv, r->w12_lo, 5);
810 bitvec_set_uint(bv, r->w13_hi, 3);
811 bitvec_set_uint(bv, r->w13_lo, 4);
812 bitvec_set_uint(bv, r->w14_hi, 4);
813 bitvec_set_uint(bv, r->w14_lo, 3);
814 bitvec_set_uint(bv, r->w15_hi, 5);
815 bitvec_set_uint(bv, r->w15_lo, 2);
816 bitvec_set_uint(bv, r->w16, 6);
817}
818
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200819/*! Determine GPRS TLLI Type (TS 23.003 Chapter 2.6) */
Harald Weltea1c4f762010-05-01 11:59:42 +0200820int gprs_tlli_type(uint32_t tlli)
821{
822 if ((tlli & 0xc0000000) == 0xc0000000)
823 return TLLI_LOCAL;
824 else if ((tlli & 0xc0000000) == 0x80000000)
825 return TLLI_FOREIGN;
826 else if ((tlli & 0xf8000000) == 0x78000000)
827 return TLLI_RANDOM;
828 else if ((tlli & 0xf8000000) == 0x70000000)
829 return TLLI_AUXILIARY;
Harald Welte1f6aad12015-08-15 19:51:45 +0200830 else if ((tlli & 0xf0000000) == 0x00000000)
831 return TLLI_G_RNTI;
832 else if ((tlli & 0xf0000000) == 0x10000000)
833 return TLLI_RAND_G_RNTI;
Harald Weltea1c4f762010-05-01 11:59:42 +0200834
835 return TLLI_RESERVED;
836}
Harald Weltec2263172010-06-01 10:47:07 +0200837
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200838/*! Determine TLLI from P-TMSI
Harald Welte96e2a002017-06-12 21:44:18 +0200839 * \param[in] p_tmsi P-TMSI
840 * \param[in] type TLLI Type we want to derive from \a p_tmsi
841 * \returns TLLI of given type */
Harald Weltec2263172010-06-01 10:47:07 +0200842uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type)
843{
844 uint32_t tlli;
845 switch (type) {
846 case TLLI_LOCAL:
847 tlli = p_tmsi | 0xc0000000;
848 break;
849 case TLLI_FOREIGN:
850 tlli = (p_tmsi & 0x3fffffff) | 0x80000000;
851 break;
852 default:
853 tlli = 0;
854 break;
855 }
856 return tlli;
857}
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200858
859/* Wrappers for deprecated functions: */
860
861int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t septet_l)
862{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100863 gsm_7bit_decode_n(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
864 user_data, septet_l);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200865
866 /* Mimic the original behaviour. */
867 return septet_l;
868}
869
870int gsm_7bit_decode_ussd(char *text, const uint8_t *user_data, uint8_t length)
871{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100872 return gsm_7bit_decode_n_ussd(text, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
873 user_data, length);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200874}
875
876int gsm_7bit_encode(uint8_t *result, const char *data)
877{
878 int out;
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100879 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
880 data, &out);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200881}
882
883int gsm_7bit_encode_ussd(uint8_t *result, const char *data, int *octets)
884{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100885 return gsm_7bit_encode_n_ussd(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
886 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200887}
888
889int gsm_7bit_encode_oct(uint8_t *result, const char *data, int *octets)
890{
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100891 return gsm_7bit_encode_n(result, GSM_7BIT_LEGACY_MAX_BUFFER_SIZE,
892 data, octets);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200893}