blob: e05783277826a2067a16c0513b34fe468589973a [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*
2 * (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +02003 * (C) 2009,2010 by On-Waves
4 * All Rights Reserved
5 *
Harald Weltee08da972017-11-13 01:00:26 +09006 * SPDX-License-Identifier: GPL-2.0+
7 *
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +02008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020018 */
19
Alexander Chemeris22630e62020-05-13 00:44:04 +030020#include <string.h>
21
Harald Welte95871da2017-05-15 12:11:36 +020022#include <osmocom/core/byteswap.h>
Philipp Maier2908dbf2020-06-05 14:16:11 +020023#include <osmocom/core/endian.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010024#include <osmocom/gsm/gsm0808.h>
Neels Hofmeyr5b214e22020-09-18 18:00:50 +020025#include <osmocom/gsm/gsm0808_lcs.h>
Philipp Maierfa896ab2017-03-27 16:55:32 +020026#include <osmocom/gsm/gsm0808_utils.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010027#include <osmocom/gsm/protocol/gsm_08_08.h>
28#include <osmocom/gsm/gsm48.h>
Neels Hofmeyr5b214e22020-09-18 18:00:50 +020029#include <osmocom/gsm/gad.h>
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020030
Harald Welte96e2a002017-06-12 21:44:18 +020031/*! \addtogroup gsm0808
32 * @{
Harald Welte37b61652017-10-16 18:46:03 +020033 * \file gsm0808.c
34 * Helper functions regarding the TS 08.08 / 48.008 A interface, primarily
35 * message generation/encoding.
Harald Welte96e2a002017-06-12 21:44:18 +020036 */
37
Alexander Chemeris22630e62020-05-13 00:44:04 +030038/*! Char buffer to return strings from functions */
39static __thread char str_buff[512];
40
Neels Hofmeyrc4fce142018-02-20 13:47:08 +010041/*! Create "Complete L3 Info" for AoIP, legacy implementation.
42 * Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros.
Harald Welte96e2a002017-06-12 21:44:18 +020043 * \param[in] msg_l3 msgb containing Layer 3 Message
44 * \param[in] nc Mobile Network Code
45 * \param[in] cc Mobile Country Code
46 * \param[in] lac Location Area Code
47 * \param[in] _ci Cell Identity
48 * \param[in] scl Speech Codec List
49 * \returns callee-allocated msgb with Complete L3 Info message */
Philipp Maierfa896ab2017-03-27 16:55:32 +020050struct msgb *gsm0808_create_layer3_aoip(const struct msgb *msg_l3, uint16_t nc,
51 uint16_t cc, int lac, uint16_t _ci,
52 const struct gsm0808_speech_codec_list
53 *scl)
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020054{
Neels Hofmeyrc4fce142018-02-20 13:47:08 +010055 struct osmo_cell_global_id cgi = {
56 .lai = {
57 .plmn = {
58 .mcc = cc,
59 .mnc = nc,
60 },
61 .lac = lac,
62 },
63 .cell_identity = _ci,
64 };
65 return gsm0808_create_layer3_2(msg_l3, &cgi, scl);
66}
67
68/*! Create "Complete L3 Info" for AoIP.
69 * \param[in] msg_l3 msgb containing Layer 3 Message -- not modified by this call.
70 * \param[in] cell MCC, MNC, LAC, CI to identify the cell.
71 * \param[in] scl Speech Codec List, optional.
72 * \returns newly allocated msgb with Complete L3 Info message */
73struct msgb *gsm0808_create_layer3_2(const struct msgb *msg_l3, const struct osmo_cell_global_id *cell,
74 const struct gsm0808_speech_codec_list *scl)
75{
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020076 struct msgb* msg;
Harald Welte65c2d362012-01-21 14:26:01 +010077 struct {
78 uint8_t ident;
79 struct gsm48_loc_area_id lai;
80 uint16_t ci;
81 } __attribute__ ((packed)) lai_ci;
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020082
83 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
84 "bssmap cmpl l3");
85 if (!msg)
86 return NULL;
87
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020088 /* create layer 3 header */
Harald Welte65c2d362012-01-21 14:26:01 +010089 msgb_v_put(msg, BSS_MAP_MSG_COMPLETE_LAYER_3);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020090
91 /* create the cell header */
Harald Welte65c2d362012-01-21 14:26:01 +010092 lai_ci.ident = CELL_IDENT_WHOLE_GLOBAL;
Neels Hofmeyrc4fce142018-02-20 13:47:08 +010093 gsm48_generate_lai2(&lai_ci.lai, &cell->lai);
94 lai_ci.ci = osmo_htons(cell->cell_identity);
Harald Welte65c2d362012-01-21 14:26:01 +010095 msgb_tlv_put(msg, GSM0808_IE_CELL_IDENTIFIER, sizeof(lai_ci),
96 (uint8_t *) &lai_ci);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +020097
98 /* copy the layer3 data */
Harald Welte65c2d362012-01-21 14:26:01 +010099 msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION,
100 msgb_l3len(msg_l3), msg_l3->l3h);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200101
Philipp Maierfa896ab2017-03-27 16:55:32 +0200102 /* AoIP: add Codec List (BSS Supported) 3.2.2.103 */
103 if (scl)
104 gsm0808_enc_speech_codec_list(msg, scl);
105
Harald Welte65c2d362012-01-21 14:26:01 +0100106 /* push the bssmap header */
107 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200108
109 return msg;
110}
111
Neels Hofmeyrc4fce142018-02-20 13:47:08 +0100112/*! Create "Complete L3 Info" for A, legacy implementation.
113 * Instead use gsm0808_create_layer3_2() with the scl parameter passed as NULL,
114 * which is capable of three-digit MNC with leading zeros.
Harald Welte96e2a002017-06-12 21:44:18 +0200115 * \param[in] msg_l3 msgb containing Layer 3 Message
116 * \param[in] nc Mobile Network Code
117 * \param[in] cc Mobile Country Code
118 * \param[in] lac Location Area Code
119 * \param[in] _ci Cell Identity
120 * \returns callee-allocated msgb with Complete L3 Info message */
Philipp Maierfa896ab2017-03-27 16:55:32 +0200121struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc,
122 uint16_t cc, int lac, uint16_t _ci)
123{
Neels Hofmeyr4eeb8082018-03-23 01:47:14 +0100124 struct osmo_cell_global_id cgi = {
125 .lai = {
126 .plmn = {
127 .mcc = cc,
128 .mnc = nc,
129 },
130 .lac = lac,
131 },
132 .cell_identity = _ci,
133 };
134 return gsm0808_create_layer3_2(msg_l3, &cgi, NULL);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200135}
136
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200137/*! Create BSSMAP RESET message
Harald Welte96e2a002017-06-12 21:44:18 +0200138 * \returns callee-allocated msgb with BSSMAP Reset message */
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200139struct msgb *gsm0808_create_reset(void)
140{
Harald Welte65c2d362012-01-21 14:26:01 +0100141 uint8_t cause = GSM0808_CAUSE_EQUIPMENT_FAILURE;
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200142 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
143 "bssmap: reset");
144 if (!msg)
145 return NULL;
146
Harald Welte65c2d362012-01-21 14:26:01 +0100147 msgb_v_put(msg, BSS_MAP_MSG_RESET);
Philipp Maier4f4905f2018-11-30 13:36:12 +0100148 gsm0808_enc_cause(msg, cause);
Harald Welte65c2d362012-01-21 14:26:01 +0100149 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
150
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200151 return msg;
152}
153
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200154/*! Create BSSMAP RESET ACK message
Harald Welte96e2a002017-06-12 21:44:18 +0200155 * \returns callee-allocated msgb with BSSMAP Reset ACK message */
Harald Weltea62fe312013-06-19 15:14:37 +0200156struct msgb *gsm0808_create_reset_ack(void)
157{
158 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
159 "bssmap: reset ack");
160 if (!msg)
161 return NULL;
162
163 msgb_v_put(msg, BSS_MAP_MSG_RESET_ACKNOWLEDGE);
164 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
165
166 return msg;
167}
168
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200169/*! Create BSSMAP Clear Complete message
Harald Welte96e2a002017-06-12 21:44:18 +0200170 * \returns callee-allocated msgb with BSSMAP Clear Complete message */
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200171struct msgb *gsm0808_create_clear_complete(void)
172{
173 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
174 "bssmap: clear complete");
Harald Welte65c2d362012-01-21 14:26:01 +0100175 uint8_t val = BSS_MAP_MSG_CLEAR_COMPLETE;
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200176 if (!msg)
177 return NULL;
178
Harald Welte65c2d362012-01-21 14:26:01 +0100179 msg->l3h = msg->data;
180 msgb_tlv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 1, &val);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200181
182 return msg;
183}
184
Harald Welted1365e12019-02-18 13:44:30 +0100185/*! Create BSSMAP Clear Command message with BSSAP header *before* l3h and BSSMAP in l3h.
186 * This is quite different from most (all?) other gsm0808_create_* which have l3h
187 * point to the BSSAP header. However, we have to keep this for backwards compatibility.
188 * Use gsm0808_create_clear_command2() for a 'modern' implementation.
Philipp Maier1a146c82018-10-30 09:36:49 +0100189 * \param[in] cause TS 08.08 cause value
Harald Welte96e2a002017-06-12 21:44:18 +0200190 * \returns callee-allocated msgb with BSSMAP Clear Command message */
Philipp Maier1a146c82018-10-30 09:36:49 +0100191struct msgb *gsm0808_create_clear_command(uint8_t cause)
Holger Hans Peter Freythera3f05d82010-10-27 11:49:24 +0200192{
193 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
194 "bssmap: clear command");
195 if (!msg)
196 return NULL;
197
Holger Hans Peter Freytheraeebe392010-10-27 12:36:05 +0200198 msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4);
199 msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD);
Philipp Maier4f4905f2018-11-30 13:36:12 +0100200 gsm0808_enc_cause(msg, cause);
Harald Welte65c2d362012-01-21 14:26:01 +0100201
Holger Hans Peter Freythera3f05d82010-10-27 11:49:24 +0200202 return msg;
203}
204
Philipp Maier74c4c4e2019-02-04 16:42:28 +0100205/*! Create BSSMAP Clear Command message.
206 * \param[in] cause TS 08.08 cause value.
207 * \param[in] csfb_ind indicate that the call was established in an CSFB context.
208 * \returns callee-allocated msgb with BSSMAP Clear Command message. */
209struct msgb *gsm0808_create_clear_command2(uint8_t cause, bool csfb_ind)
210{
Harald Welte10ba47d2019-02-18 12:36:54 +0100211 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
212 "bssmap: clear command");
Philipp Maier74c4c4e2019-02-04 16:42:28 +0100213 if (!msg)
214 return NULL;
215
Harald Welte10ba47d2019-02-18 12:36:54 +0100216 msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD);
217 gsm0808_enc_cause(msg, cause);
218
Philipp Maier74c4c4e2019-02-04 16:42:28 +0100219 if (csfb_ind)
220 msgb_v_put(msg, GSM0808_IE_CSFB_INDICATION);
221
Harald Welte10ba47d2019-02-18 12:36:54 +0100222 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
223
Philipp Maier74c4c4e2019-02-04 16:42:28 +0100224 return msg;
225}
226
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200227/*! Superseded by gsm0808_create_cipher2() to include Kc128.
228 * Create BSSMAP Cipher Mode Command message (without Kc128).
Harald Welte96e2a002017-06-12 21:44:18 +0200229 * \param[in] ei Mandatory Encryption Information
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200230 * \param[in] kc128 optional kc128 key for A5/4
Harald Welte96e2a002017-06-12 21:44:18 +0200231 * \param[in] cipher_response_mode optional 1-byte Cipher Response Mode
232 * \returns callee-allocated msgb with BSSMAP Cipher Mode Command message */
Philipp Maierb478dd32017-03-29 15:50:05 +0200233struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
234 const uint8_t *cipher_response_mode)
235{
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200236 struct gsm0808_cipher_mode_command cmc = {
237 .ei = *ei,
238 .cipher_response_mode_present = (cipher_response_mode != NULL),
239 .cipher_response_mode = (cipher_response_mode ? *cipher_response_mode : 0),
240 };
241 return gsm0808_create_cipher2(&cmc);
242}
243
244/*! Create BSSMAP Cipher Mode Command message.
245 * \param[in] cmc Information to encode.
246 * \returns callee-allocated msgb with BSSMAP Cipher Mode Command message */
247struct msgb *gsm0808_create_cipher2(const struct gsm0808_cipher_mode_command *cmc)
248{
Philipp Maierb478dd32017-03-29 15:50:05 +0200249 /* See also: 3GPP TS 48.008 3.2.1.30 CIPHER MODE COMMAND */
250 struct msgb *msg;
251
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200252 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "cipher-mode-command");
Philipp Maierb478dd32017-03-29 15:50:05 +0200253 if (!msg)
254 return NULL;
255
256 /* Message Type 3.2.2.1 */
257 msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_CMD);
258
259 /* Encryption Information 3.2.2.10 */
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200260 gsm0808_enc_encrypt_info(msg, &cmc->ei);
Philipp Maierb478dd32017-03-29 15:50:05 +0200261
262 /* Cipher Response Mode 3.2.2.34 */
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200263 if (cmc->cipher_response_mode_present)
Philipp Maierb478dd32017-03-29 15:50:05 +0200264 msgb_tv_put(msg, GSM0808_IE_CIPHER_RESPONSE_MODE,
Neels Hofmeyr4a9756c2021-06-10 00:48:15 +0200265 cmc->cipher_response_mode);
266
267 /* Kc128 3.2.2.109 */
268 if (cmc->kc128_present)
269 gsm0808_enc_kc128(msg, cmc->kc128);
Philipp Maierb478dd32017-03-29 15:50:05 +0200270
271 /* pre-pend the header */
272 msg->l3h =
273 msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
274
275 return msg;
276}
277
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200278/*! Create BSSMAP Cipher Mode Complete message
Harald Welte96e2a002017-06-12 21:44:18 +0200279 * \param[in] layer3 L3 Message to be included
280 * \param[in] alg_id Chosen Encrpytion Algorithm
281 * \returns callee-allocated msgb with BSSMAP Cipher Mode Complete message */
Holger Hans Peter Freyther81716d52010-04-17 06:16:35 +0200282struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id)
283{
284 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
285 "cipher-complete");
286 if (!msg)
287 return NULL;
288
289 /* send response with BSS override for A5/1... cheating */
Harald Welte65c2d362012-01-21 14:26:01 +0100290 msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_COMPLETE);
Holger Hans Peter Freyther81716d52010-04-17 06:16:35 +0200291
292 /* include layer3 in case we have at least two octets */
293 if (layer3 && msgb_l3len(layer3) > 2) {
Harald Welte65c2d362012-01-21 14:26:01 +0100294 msg->l4h = msgb_tlv_put(msg, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS,
295 msgb_l3len(layer3), layer3->l3h);
Holger Hans Peter Freyther81716d52010-04-17 06:16:35 +0200296 }
297
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +0700298 /* Optional Chosen Encryption Algorithm IE */
299 if (alg_id > 0)
300 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, alg_id);
Holger Hans Peter Freyther81716d52010-04-17 06:16:35 +0200301
Harald Welte65c2d362012-01-21 14:26:01 +0100302 /* pre-pend the header */
303 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
304
Holger Hans Peter Freyther81716d52010-04-17 06:16:35 +0200305 return msg;
306}
307
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200308/*! Create BSSMAP Cipher Mode Reject message
Maxaa934632018-11-07 13:16:54 +0100309 * \param[in] cause 3GPP TS 08.08 §3.2.2.5 cause value
Harald Welte96e2a002017-06-12 21:44:18 +0200310 * \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */
Maxaa934632018-11-07 13:16:54 +0100311struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause)
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200312{
313 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
Maxaa934632018-11-07 13:16:54 +0100314 "bssmap: cipher mode reject");
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200315 if (!msg)
316 return NULL;
317
Harald Welte62e40852017-12-17 20:50:34 +0100318 msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT);
Maxaa934632018-11-07 13:16:54 +0100319
Philipp Maier4f4905f2018-11-30 13:36:12 +0100320 gsm0808_enc_cause(msg, cause);
Harald Welte65c2d362012-01-21 14:26:01 +0100321
322 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200323
324 return msg;
325}
326
Maxed651d22018-11-07 15:25:05 +0100327/*! Create BSSMAP Cipher Mode Reject message
328 * \param[in] class 3GPP TS 08.08 §3.2.2.5 cause's class
329 * \param[in] ext 3GPP TS 08.08 §3.2.2.5 cause value (national application extension)
330 * \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */
331struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext)
332{
Philipp Maier4f4905f2018-11-30 13:36:12 +0100333 uint16_t cause;
Maxed651d22018-11-07 15:25:05 +0100334 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
335 "bssmap: cipher mode reject");
336 if (!msg)
337 return NULL;
338
Philipp Maier4f4905f2018-11-30 13:36:12 +0100339 /* Set cause code class in the upper byte */
340 cause = 0x80 | (class << 4);
341 cause = cause << 8;
342
343 /* Set cause code extension in the lower byte */
344 cause |= ext;
Maxed651d22018-11-07 15:25:05 +0100345
346 msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT);
347
Philipp Maier4f4905f2018-11-30 13:36:12 +0100348 gsm0808_enc_cause(msg, cause);
Maxed651d22018-11-07 15:25:05 +0100349
350 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
351
352 return msg;
353}
354
Harald Welte64e807c2018-05-29 21:00:56 +0200355/*! Create BSSMAP LCLS CONNECT CONTROL message (TS 48.008 3.2.1.91).
356 * \param[in] config LCLS Configuration
357 * \param[in] control LCLS Connection Status Control
358 * \returns callee-allocated msgb with BSSMAP LCLS NOTIFICATION */
Max45f89c92018-12-19 19:35:26 +0100359struct msgb *gsm0808_create_lcls_conn_ctrl(enum gsm0808_lcls_config config,
360 enum gsm0808_lcls_control control)
Harald Welte64e807c2018-05-29 21:00:56 +0200361{
Max45f89c92018-12-19 19:35:26 +0100362 struct msgb *msg;
363
364 /* According to NOTE 1 in §3.2.1.91 at least one of the parameters is required */
365 if (config == GSM0808_LCLS_CFG_NA && control == GSM0808_LCLS_CSC_NA)
366 return NULL;
367
368 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "bssmap: LCLS CONN CTRL");
Harald Welte64e807c2018-05-29 21:00:56 +0200369 if (!msg)
370 return NULL;
371
372 msgb_v_put(msg, BSS_MAP_MSG_LCLS_CONNECT_CTRL);
Max45f89c92018-12-19 19:35:26 +0100373 if (config != GSM0808_LCLS_CFG_NA)
374 msgb_tv_put(msg, GSM0808_IE_LCLS_CONFIG, config);
375 if (control != GSM0808_LCLS_CSC_NA)
Keith Whytee8525442022-10-06 01:01:47 +0100376 msgb_tv_put(msg, GSM0808_IE_LCLS_CONN_STATUS_CTRL, control);
Harald Welte64e807c2018-05-29 21:00:56 +0200377 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
378
379 return msg;
380}
381
382/*! Create BSSMAP LCLS CONNECT CONTROL ACK message (TS 48.008 3.2.1.92).
383 * \param[in] status LCLS BSS Status
384 * \returns callee-allocated msgb with BSSMAP LCLS NOTIFICATION */
385struct msgb *gsm0808_create_lcls_conn_ctrl_ack(enum gsm0808_lcls_status status)
386{
387 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
388 "bssmap: LCLS CONN CTRL ACK");
389 if (!msg)
390 return NULL;
391
392 msgb_v_put(msg, BSS_MAP_MSG_LCLS_CONNECT_CTRL_ACK);
393 msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, status);
394 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
395
396 return msg;
397}
398
399/*! Create BSSMAP LCLS NOTIFICATION message (TS 48.008 3.2.1.93).
400 * \param[in] status LCLS BSS Status
401 * \param[in] break_req Include the LCLS BREAK REQ IE (true) or not (false)
402 * \returns callee-allocated msgb with BSSMAP LCLS NOTIFICATION */
403struct msgb *gsm0808_create_lcls_notification(enum gsm0808_lcls_status status, bool break_req)
404{
405 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
406 "bssmap: LCLS NOTIFICATION");
407 if (!msg)
408 return NULL;
409
410 msgb_v_put(msg, BSS_MAP_MSG_LCLS_NOTIFICATION);
411 msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, status);
412 if (break_req)
413 msgb_v_put(msg, GSM0808_IE_LCLS_BREAK_REQ);
414 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
415
416 return msg;
417}
418
Neels Hofmeyr2c79d552018-09-13 05:36:32 +0200419/*! Create BSSMAP Classmark Request message
420 * \returns callee-allocated msgb with BSSMAP Classmark Request message */
421struct msgb *gsm0808_create_classmark_request()
422{
423 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
424 "classmark-request");
425 if (!msg)
426 return NULL;
427
428 msgb_v_put(msg, BSS_MAP_MSG_CLASSMARK_RQST);
429 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
430 return msg;
431}
Harald Welte64e807c2018-05-29 21:00:56 +0200432
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200433/*! Create BSSMAP Classmark Update message
Harald Welte96e2a002017-06-12 21:44:18 +0200434 * \param[in] cm2 Classmark 2
435 * \param[in] cm2_len length (in octets) of \a cm2
436 * \param[in] cm3 Classmark 3
437 * \param[in] cm3_len length (in octets) of \a cm3
438 * \returns callee-allocated msgb with BSSMAP Classmark Update message */
Harald Welte07b625d2012-01-23 10:02:58 +0100439struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
440 const uint8_t *cm3, uint8_t cm3_len)
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200441{
442 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
443 "classmark-update");
444 if (!msg)
445 return NULL;
446
Harald Welte65c2d362012-01-21 14:26:01 +0100447 msgb_v_put(msg, BSS_MAP_MSG_CLASSMARK_UPDATE);
Harald Welte07b625d2012-01-23 10:02:58 +0100448 msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T2, cm2_len, cm2);
449 if (cm3)
450 msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T3,
451 cm3_len, cm3);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200452
Harald Welte65c2d362012-01-21 14:26:01 +0100453 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
454
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200455 return msg;
456}
457
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200458/*! Create BSSMAP SAPI N Reject message
Harald Welte96e2a002017-06-12 21:44:18 +0200459 * \param[in] link_id Link Identifier
Vadim Yanitskiyfa6cd882020-08-26 18:03:59 +0700460 * \param[in] cause BSSAP Cause value (see 3GPP TS 48.008, section 3.2.2.5)
Harald Welte96e2a002017-06-12 21:44:18 +0200461 * \returns callee-allocated msgb with BSSMAP SAPI N Reject message */
Vadim Yanitskiyfa6cd882020-08-26 18:03:59 +0700462struct msgb *gsm0808_create_sapi_reject_cause(uint8_t link_id, uint16_t cause)
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200463{
464 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
465 "bssmap: sapi 'n' reject");
466 if (!msg)
467 return NULL;
468
Harald Welte65c2d362012-01-21 14:26:01 +0100469 msgb_v_put(msg, BSS_MAP_MSG_SAPI_N_REJECT);
Alexander Chemerisa5b1b862020-05-12 01:03:08 +0300470 msgb_tv_put(msg, GSM0808_IE_DLCI, link_id);
Vadim Yanitskiyfa6cd882020-08-26 18:03:59 +0700471 gsm0808_enc_cause(msg, cause);
Harald Welte65c2d362012-01-21 14:26:01 +0100472
473 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200474
475 return msg;
476}
477
Vadim Yanitskiyfa6cd882020-08-26 18:03:59 +0700478/*! Create BSSMAP SAPI N Reject message (with hard-coded cause "BSS not equipped").
479 * DEPRECATED: use gsm0808_create_sapi_reject_cause() instead.
480 * \param[in] link_id Link Identifier
481 * \param[in] cause BSSAP Cause value (see 3GPP TS 48.008, section 3.2.2.5)
482 * \returns callee-allocated msgb with BSSMAP SAPI N Reject message */
483struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
484{
485 return gsm0808_create_sapi_reject_cause(link_id, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
486}
487
Max52074322018-11-30 10:44:07 +0100488/*! Create BSSMAP Assignment Request message, 3GPP TS 48.008 §3.2.1.1.
489 * This is identical to gsm0808_create_ass(), but adds KC and LCLS IEs.
Harald Welte96e2a002017-06-12 21:44:18 +0200490 * \param[in] ct Channel Type
491 * \param[in] cic Circuit Identity Code (Classic A only)
492 * \param[in] ss Socket Address of MSC-side RTP socket (AoIP only)
493 * \param[in] scl Speech Codec List (AoIP only)
Max49c06682018-11-21 22:10:26 +0100494 * \param[in] ci Call Identifier (Optional), §3.2.2.105
Max52074322018-11-30 10:44:07 +0100495 * \param[in] kc Kc128 ciphering key (Optional, A5/4), §3.2.2.109
496 * \param[in] lcls Optional LCLS parameters
Harald Welte96e2a002017-06-12 21:44:18 +0200497 * \returns callee-allocated msgb with BSSMAP Assignment Request message */
Max52074322018-11-30 10:44:07 +0100498struct msgb *gsm0808_create_ass2(const struct gsm0808_channel_type *ct,
499 const uint16_t *cic,
500 const struct sockaddr_storage *ss,
501 const struct gsm0808_speech_codec_list *scl,
502 const uint32_t *ci,
503 const uint8_t *kc, const struct osmo_lcls *lcls)
Philipp Maierc6144a22017-03-29 17:53:43 +0200504{
505 /* See also: 3GPP TS 48.008 3.2.1.1 ASSIGNMENT REQUEST */
506 struct msgb *msg;
Philipp Maierc6144a22017-03-29 17:53:43 +0200507
508 /* Mandatory emelent! */
509 OSMO_ASSERT(ct);
510
511 msg =
512 msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
513 "bssmap: ass req");
514 if (!msg)
515 return NULL;
516
517 /* Message Type 3.2.2.1 */
518 msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_RQST);
519
520 /* Channel Type 3.2.2.11 */
521 gsm0808_enc_channel_type(msg, ct);
522
523 /* Circuit Identity Code 3.2.2.2 */
Vadim Yanitskiy1c4fc222021-02-05 03:58:24 +0100524 if (cic)
525 msgb_tv16_put(msg, GSM0808_IE_CIRCUIT_IDENTITY_CODE, *cic);
Philipp Maierc6144a22017-03-29 17:53:43 +0200526
527 /* AoIP: AoIP Transport Layer Address (MGW) 3.2.2.102 */
528 if (ss) {
529 gsm0808_enc_aoip_trasp_addr(msg, ss);
530 }
531
532 /* AoIP: Codec List (MSC Preferred) 3.2.2.103 */
533 if (scl)
534 gsm0808_enc_speech_codec_list(msg, scl);
535
536 /* AoIP: Call Identifier 3.2.2.105 */
537 if (ci) {
Philipp Maier2908dbf2020-06-05 14:16:11 +0200538 /* NOTE: 3GPP TS 48.008, section 3.2.2.105 specifies that
Vadim Yanitskiy1c4fc222021-02-05 03:58:24 +0100539 * the least significant byte shall be transmitted first. */
540 msgb_v_put(msg, GSM0808_IE_CALL_ID);
541 osmo_store32le(*ci, msgb_put(msg, sizeof(*ci)));
Philipp Maierc6144a22017-03-29 17:53:43 +0200542 }
543
Max52074322018-11-30 10:44:07 +0100544 if (kc)
545 msgb_tv_fixed_put(msg, GSM0808_IE_KC_128, 16, kc);
546
Max47022152018-12-19 18:51:00 +0100547 if (lcls)
548 gsm0808_enc_lcls(msg, lcls);
Max52074322018-11-30 10:44:07 +0100549
Philipp Maierc6144a22017-03-29 17:53:43 +0200550 /* push the bssmap header */
551 msg->l3h =
552 msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
553
554 return msg;
555}
556
Max52074322018-11-30 10:44:07 +0100557/*! Create BSSMAP Assignment Request message, 3GPP TS 48.008 §3.2.1.1.
558 * \param[in] ct Channel Type
559 * \param[in] cic Circuit Identity Code (Classic A only)
560 * \param[in] ss Socket Address of MSC-side RTP socket (AoIP only)
561 * \param[in] scl Speech Codec List (AoIP only)
562 * \param[in] ci Call Identifier (Optional), §3.2.2.105
563 * \returns callee-allocated msgb with BSSMAP Assignment Request message */
564struct msgb *gsm0808_create_ass(const struct gsm0808_channel_type *ct,
565 const uint16_t *cic,
566 const struct sockaddr_storage *ss,
567 const struct gsm0808_speech_codec_list *scl,
568 const uint32_t *ci)
569{
570 return gsm0808_create_ass2(ct, cic, ss, scl, ci, NULL, NULL);
571}
572
Max414c8f52019-01-08 14:44:24 +0100573/*! Create BSSMAP Assignment Completed message as per 3GPP TS 48.008 §3.2.1.2
Harald Welte96e2a002017-06-12 21:44:18 +0200574 * \param[in] rr_cause GSM 04.08 RR Cause value
575 * \param[in] chosen_channel Chosen Channel
576 * \param[in] encr_alg_id Encryption Algorithm ID
577 * \param[in] speech_mode Speech Mode
578 * \param[in] ss Socket Address of BSS-side RTP socket
579 * \param[in] sc Speech Codec (current)
580 * \param[in] scl Speech Codec List (permitted)
Max414c8f52019-01-08 14:44:24 +0100581 * \param[in] lcls_bss_status §3.2.2.119 LCLS-BSS-Status, optional
Harald Welte96e2a002017-06-12 21:44:18 +0200582 * \returns callee-allocated msgb with BSSMAP Assignment Complete message */
Max414c8f52019-01-08 14:44:24 +0100583struct msgb *gsm0808_create_ass_compl2(uint8_t rr_cause, uint8_t chosen_channel,
Philipp Maierfa896ab2017-03-27 16:55:32 +0200584 uint8_t encr_alg_id, uint8_t speech_mode,
585 const struct sockaddr_storage *ss,
586 const struct gsm0808_speech_codec *sc,
Max414c8f52019-01-08 14:44:24 +0100587 const struct gsm0808_speech_codec_list *scl,
588 enum gsm0808_lcls_status lcls_bss_status)
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200589{
Harald Welte65c2d362012-01-21 14:26:01 +0100590 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
591 "bssmap: ass compl");
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200592 if (!msg)
593 return NULL;
594
Harald Welte65c2d362012-01-21 14:26:01 +0100595 msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_COMPLETE);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200596
597 /* write 3.2.2.22 */
Harald Welte65c2d362012-01-21 14:26:01 +0100598 msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, rr_cause);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200599
600 /* write cirtcuit identity code 3.2.2.2 */
601 /* write cell identifier 3.2.2.17 */
602 /* write chosen channel 3.2.2.33 when BTS picked it */
Harald Welte65c2d362012-01-21 14:26:01 +0100603 msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, chosen_channel);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200604
605 /* write chosen encryption algorithm 3.2.2.44 */
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +0700606 if (encr_alg_id > 0)
607 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, encr_alg_id);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200608
609 /* write circuit pool 3.2.2.45 */
610 /* write speech version chosen: 3.2.2.51 when BTS picked it */
Harald Welte65c2d362012-01-21 14:26:01 +0100611 if (speech_mode != 0)
612 msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, speech_mode);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200613
Philipp Maierfa896ab2017-03-27 16:55:32 +0200614 /* AoIP: AoIP Transport Layer Address (BSS) 3.2.2.102 */
615 if (ss)
616 gsm0808_enc_aoip_trasp_addr(msg, ss);
617
618 /* AoIP: Speech Codec (Chosen) 3.2.2.104 */
619 if (sc)
620 gsm0808_enc_speech_codec(msg, sc);
621
622 /* AoIP: add Codec List (BSS Supported) 3.2.2.103 */
623 if (scl)
624 gsm0808_enc_speech_codec_list(msg, scl);
625
Max414c8f52019-01-08 14:44:24 +0100626 /* FIXME: write LSA identifier 3.2.2.15 - see 3GPP TS 43.073 */
627
628 /* LCLS-BSS-Status 3.2.2.119 */
629 if (lcls_bss_status != GSM0808_LCLS_STS_NA)
630 msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, lcls_bss_status);
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200631
Harald Welte65c2d362012-01-21 14:26:01 +0100632 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200633
Holger Hans Peter Freytherba6172a2010-04-17 06:21:49 +0200634 return msg;
635}
636
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200637/*! Create BSSMAP Assignment Completed message
Harald Welte96e2a002017-06-12 21:44:18 +0200638 * \param[in] rr_cause GSM 04.08 RR Cause value
639 * \param[in] chosen_channel Chosen Channel
640 * \param[in] encr_alg_id Encryption Algorithm ID
641 * \param[in] speech_mode Speech Mode
Max414c8f52019-01-08 14:44:24 +0100642 * \param[in] ss Socket Address of BSS-side RTP socket
643 * \param[in] sc Speech Codec (current)
644 * \param[in] scl Speech Codec List (permitted)
645 * \returns callee-allocated msgb with BSSMAP Assignment Complete message */
646struct msgb *gsm0808_create_ass_compl(uint8_t rr_cause, uint8_t chosen_channel,
647 uint8_t encr_alg_id, uint8_t speech_mode,
648 const struct sockaddr_storage *ss,
649 const struct gsm0808_speech_codec *sc,
650 const struct gsm0808_speech_codec_list *scl)
651{
652 return gsm0808_create_ass_compl2(rr_cause, chosen_channel, encr_alg_id, speech_mode,
653 ss, sc, scl, GSM0808_LCLS_STS_NA);
654}
655
656/*! Create BSSMAP Assignment Completed message
657 * \param[in] rr_cause GSM 04.08 RR Cause value
658 * \param[in] chosen_channel Chosen Channel
659 * \param[in] encr_alg_id Encryption Algorithm ID
660 * \param[in] speech_mode Speech Mode
Harald Welte96e2a002017-06-12 21:44:18 +0200661 * \returns callee-allocated msgb with BSSMAP Assignment Complete message */
Philipp Maierfa896ab2017-03-27 16:55:32 +0200662struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
663 uint8_t chosen_channel,
664 uint8_t encr_alg_id,
665 uint8_t speech_mode)
666{
Max414c8f52019-01-08 14:44:24 +0100667 return gsm0808_create_ass_compl2(rr_cause, chosen_channel, encr_alg_id,
668 speech_mode, NULL, NULL, NULL, GSM0808_LCLS_STS_NA);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200669}
670
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200671/*! Create BSSMAP Assignment Failure message
Harald Welte96e2a002017-06-12 21:44:18 +0200672 * \param[in] cause BSSMAP Cause value
673 * \param[in] rr_cause GSM 04.08 RR Cause value
674 * \param[in] scl Optional Speech Cdec List (AoIP)
675 * \returns callee-allocated msgb with BSSMAP Assignment Failure message */
Philipp Maierfa896ab2017-03-27 16:55:32 +0200676struct msgb *gsm0808_create_ass_fail(uint8_t cause, const uint8_t *rr_cause,
677 const struct gsm0808_speech_codec_list
678 *scl)
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200679{
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200680 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
681 "bssmap: ass fail");
682 if (!msg)
683 return NULL;
684
Harald Welte65c2d362012-01-21 14:26:01 +0100685 msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_FAILURE);
Philipp Maier4f4905f2018-11-30 13:36:12 +0100686 gsm0808_enc_cause(msg, cause);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200687
688 /* RR cause 3.2.2.22 */
Harald Welte65c2d362012-01-21 14:26:01 +0100689 if (rr_cause)
690 msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, *rr_cause);
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200691
692 /* Circuit pool 3.22.45 */
693 /* Circuit pool list 3.2.2.46 */
694
Philipp Maierfa896ab2017-03-27 16:55:32 +0200695 /* AoIP: add Codec List (BSS Supported) 3.2.2.103 */
696 if (scl)
697 gsm0808_enc_speech_codec_list(msg, scl);
698
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200699 /* update the size */
Harald Welte65c2d362012-01-21 14:26:01 +0100700 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
701
Holger Hans Peter Freyther280cd512010-04-15 10:10:39 +0200702 return msg;
703}
Holger Hans Peter Freyther7daa01c2010-04-17 05:14:36 +0200704
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200705/*! Create BSSMAP Assignment Failure message
Harald Welte96e2a002017-06-12 21:44:18 +0200706 * \param[in] cause BSSMAP Cause value
707 * \param[in] rr_cause GSM 04.08 RR Cause value
708 * \returns callee-allocated msgb with BSSMAP Assignment Failure message */
Philipp Maierfa896ab2017-03-27 16:55:32 +0200709struct msgb *gsm0808_create_assignment_failure(uint8_t cause,
710 uint8_t *rr_cause)
711{
712 return gsm0808_create_ass_fail(cause, rr_cause, NULL);
713}
714
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200715/*! Create BSSMAP Clear Request message
Harald Welte96e2a002017-06-12 21:44:18 +0200716 * \param[in] cause BSSMAP Cause value
717 * \returns callee-allocated msgb with BSSMAP Clear Request message */
Holger Hans Peter Freytheraf270a42010-11-04 12:42:50 +0100718struct msgb *gsm0808_create_clear_rqst(uint8_t cause)
719{
720 struct msgb *msg;
721
722 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
723 "bssmap: clear rqst");
724 if (!msg)
725 return NULL;
726
Harald Welte65c2d362012-01-21 14:26:01 +0100727 msgb_v_put(msg, BSS_MAP_MSG_CLEAR_RQST);
Philipp Maier4f4905f2018-11-30 13:36:12 +0100728 gsm0808_enc_cause(msg, cause);
Harald Welte65c2d362012-01-21 14:26:01 +0100729 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
Holger Hans Peter Freytheraf270a42010-11-04 12:42:50 +0100730
Holger Hans Peter Freytheraf270a42010-11-04 12:42:50 +0100731 return msg;
732}
733
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200734/*! Create BSSMAP PAGING message
Harald Welte96e2a002017-06-12 21:44:18 +0200735 * \param[in] imsi Mandatory paged IMSI in string representation
736 * \param[in] tmsi Optional paged TMSI
Stefan Sperling3953f412018-08-28 15:06:30 +0200737 * \param[in] cil Mandatory Cell Identity List (where to page)
Harald Welte96e2a002017-06-12 21:44:18 +0200738 * \param[in] chan_needed Channel Type needed
739 * \returns callee-allocated msgb with BSSMAP PAGING message */
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100740struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi,
741 const struct gsm0808_cell_id_list2 *cil,
742 const uint8_t *chan_needed)
Philipp Maier3d48ec02017-03-29 17:37:55 +0200743{
744 struct msgb *msg;
Harald Weltea13fb752020-06-16 08:44:42 +0200745 uint8_t mid_buf[GSM48_MI_SIZE + 2];
746 int mid_len;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200747 uint32_t tmsi_sw;
748
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100749 /* Mandatory elements! */
Philipp Maier3d48ec02017-03-29 17:37:55 +0200750 OSMO_ASSERT(imsi);
751 OSMO_ASSERT(cil);
752
753 /* Malformed IMSI */
754 OSMO_ASSERT(strlen(imsi) <= GSM48_MI_SIZE);
755
756 msg =
757 msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "paging");
758 if (!msg)
759 return NULL;
760
761 /* Message Type 3.2.2.1 */
762 msgb_v_put(msg, BSS_MAP_MSG_PAGING);
763
Stefan Sperling3953f412018-08-28 15:06:30 +0200764 /* mandatory IMSI 3.2.2.6 */
Harald Weltea13fb752020-06-16 08:44:42 +0200765 mid_len = gsm48_generate_mid_from_imsi(mid_buf, imsi);
766 msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200767
768 /* TMSI 3.2.2.7 */
769 if (tmsi) {
Harald Welte95871da2017-05-15 12:11:36 +0200770 tmsi_sw = osmo_htonl(*tmsi);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200771 msgb_tlv_put(msg, GSM0808_IE_TMSI, sizeof(*tmsi),
772 (uint8_t *) & tmsi_sw);
773 }
774
Stefan Sperling3953f412018-08-28 15:06:30 +0200775 /* mandatory Cell Identifier List 3.2.2.27 */
776 gsm0808_enc_cell_id_list2(msg, cil);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200777
778 /* Channel Needed 3.2.2.36 */
779 if (chan_needed) {
780 msgb_tv_put(msg, GSM0808_IE_CHANNEL_NEEDED,
781 (*chan_needed) & 0x03);
782 }
783
784 /* pre-pend the header */
785 msg->l3h =
786 msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
787
788 return msg;
789}
790
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100791/*! DEPRECATED: Use gsm0808_create_paging2 instead.
792 * Create BSSMAP PAGING message.
793 * \param[in] imsi Mandatory paged IMSI in string representation
794 * \param[in] tmsi Optional paged TMSI
795 * \param[in] cil Cell Identity List (where to page)
796 * \param[in] chan_needed Channel Type needed
797 * \returns callee-allocated msgb with BSSMAP PAGING message */
798struct msgb *gsm0808_create_paging(const char *imsi, const uint32_t *tmsi,
799 const struct gsm0808_cell_id_list *cil,
800 const uint8_t *chan_needed)
801{
802 struct gsm0808_cell_id_list2 cil2 = {};
803
Pau Espin Pedrol49766ab2021-04-19 12:14:36 +0200804 /* Mandatory elements! */
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100805 OSMO_ASSERT(cil);
806
807 if (cil->id_list_len > GSM0808_CELL_ID_LIST2_MAXLEN)
808 return NULL;
809
810 cil2.id_discr = cil->id_discr;
811 memcpy(cil2.id_list, cil->id_list_lac, cil->id_list_len * sizeof(cil2.id_list[0].lac));
812 cil2.id_list_len = cil->id_list_len;
813
814 return gsm0808_create_paging2(imsi, tmsi, &cil2, chan_needed);
815}
816
Neels Hofmeyr70aba3f2018-03-13 03:40:53 +0100817static uint8_t put_old_bss_to_new_bss_information(struct msgb *msg,
818 const struct gsm0808_old_bss_to_new_bss_info *i)
819{
820 uint8_t *old_tail;
821 uint8_t *tlv_len;
822
823 msgb_put_u8(msg, GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION);
824 tlv_len = msgb_put(msg, 1);
825 old_tail = msg->tail;
826
827 if (i->extra_information_present) {
828 uint8_t val = 0;
829 if (i->extra_information.prec)
830 val |= 1 << 0;
831 if (i->extra_information.lcs)
832 val |= 1 << 1;
833 if (i->extra_information.ue_prob)
834 val |= 1 << 2;
835 msgb_tlv_put(msg, GSM0808_FE_IE_EXTRA_INFORMATION, 1, &val);
836 }
837
838 if (i->current_channel_type_2_present) {
839 uint8_t val[2] = {
840 i->current_channel_type_2.mode,
841 i->current_channel_type_2.field,
842 };
843 msgb_tlv_put(msg, GSM0808_FE_IE_CURRENT_CHANNEL_TYPE_2, 2, val);
844 }
845
Pau Espin Pedrol1b625cb2021-04-14 21:27:31 +0200846 if (i->last_eutran_plmn_id_present) {
847 msgb_put_u8(msg, GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID);
848 osmo_plmn_to_bcd(msgb_put(msg, 3), &i->last_eutran_plmn_id);
849 }
850
Neels Hofmeyr70aba3f2018-03-13 03:40:53 +0100851 *tlv_len = (uint8_t) (msg->tail - old_tail);
852 return *tlv_len + 2;
853}
854
855/*! Create BSSMAP HANDOVER REQUIRED message.
856 * \param[in] params All information to be encoded.
Neels Hofmeyr302aafc2019-04-10 19:23:45 +0200857 * \returns newly allocated msgb with BSSMAP HANDOVER REQUIRED message. */
Neels Hofmeyr70aba3f2018-03-13 03:40:53 +0100858struct msgb *gsm0808_create_handover_required(const struct gsm0808_handover_required *params)
859{
860 struct msgb *msg;
861
862 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-REQUIRED");
863 if (!msg)
864 return NULL;
865
866 /* Message Type, 3.2.2.1 */
867 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_REQUIRED);
868
869 /* Cause, 3.2.2.5 */
Philipp Maier4f4905f2018-11-30 13:36:12 +0100870 gsm0808_enc_cause(msg, params->cause);
Neels Hofmeyr70aba3f2018-03-13 03:40:53 +0100871
872 /* Cell Identifier List, 3.2.2.27 */
873 gsm0808_enc_cell_id_list2(msg, &params->cil);
874
875 /* Current Channel Type 1, 3.2.2.49 */
876 if (params->current_channel_type_1_present)
877 msgb_tv_fixed_put(msg, GSM0808_IE_CURRENT_CHANNEL_TYPE_1, 1, &params->current_channel_type_1);
878
879 /* Speech Version (Used), 3.2.2.51 */
880 if (params->speech_version_used_present)
Neels Hofmeyr302aafc2019-04-10 19:23:45 +0200881 msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, params->speech_version_used);
Neels Hofmeyr70aba3f2018-03-13 03:40:53 +0100882
883 if (params->old_bss_to_new_bss_info_present)
884 put_old_bss_to_new_bss_information(msg, &params->old_bss_to_new_bss_info);
885
886 /* pre-pend the header */
887 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
888
889 return msg;
890}
891
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +0100892/*! Create BSSMAP HANDOVER REQUIRED REJECT message.
893 * \returns newly allocated msgb with BSSMAP HANDOVER REQUIRED REJECT message. */
894struct msgb *gsm0808_create_handover_required_reject(const struct gsm0808_handover_required_reject *params)
895{
896 struct msgb *msg;
897
898 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-REQUIRED-REJECT");
899 if (!msg)
900 return NULL;
901
902 /* Message Type, 3.2.2.1 */
903 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT);
904
905 /* Cause, 3.2.2.5 */
906 gsm0808_enc_cause(msg, params->cause);
907
908 /* prepend the header */
909 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
910
911 return msg;
912}
913
914/*! Create BSSMAP HANDOVER REQUEST message, 3GPP TS 48.008 3.2.1.8.
915 * Sent from the MSC to the potential new target cell during inter-BSC handover, or to the target MSC during inter-MSC
916 * handover.
917 */
918struct msgb *gsm0808_create_handover_request(const struct gsm0808_handover_request *params)
919{
920 struct msgb *msg;
921
922 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-REQUEST");
923 if (!msg)
924 return NULL;
925
926 /* Message Type, 3.2.2.1 */
927 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_RQST);
928
929 /* Channel Type 3.2.2.11 */
930 gsm0808_enc_channel_type(msg, &params->channel_type);
931
932 /* Encryption Information 3.2.2.10 */
933 gsm0808_enc_encrypt_info(msg, &params->encryption_information);
934
935 /* Classmark Information 1 3.2.2.30 or Classmark Information 2 3.2.2.19 (Classmark 2 wins) */
936 if (params->classmark_information.classmark2_len) {
937 msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T2,
938 params->classmark_information.classmark2_len,
939 (const uint8_t*)&params->classmark_information.classmark2);
940 } else if (params->classmark_information.classmark1_set) {
941 msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1,
942 sizeof(params->classmark_information.classmark1),
943 (const uint8_t*)&params->classmark_information.classmark1);
944 }
945 /* (Classmark 3 possibly follows below) */
946
947 /* Cell Identifier (Serving) , 3.2.2.17 */
948 gsm0808_enc_cell_id(msg, &params->cell_identifier_serving);
949
950 /* Cell Identifier (Target) , 3.2.2.17 */
951 gsm0808_enc_cell_id(msg, &params->cell_identifier_target);
952
953 /* Cause, 3.2.2.5 */
954 gsm0808_enc_cause(msg, params->cause);
955
956 /* Classmark Information 3 3.2.2.20 */
957 if (params->classmark_information.classmark3_len) {
958 msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T3,
959 params->classmark_information.classmark3_len,
960 (const uint8_t*)&params->classmark_information.classmark3);
961 }
962
963 /* Current Channel type 1 3.2.2.49 */
964 if (params->current_channel_type_1_present)
965 msgb_tv_fixed_put(msg, GSM0808_IE_CURRENT_CHANNEL_TYPE_1, 1, &params->current_channel_type_1);
966
967 /* Speech Version (Used), 3.2.2.51 */
968 if (params->speech_version_used) {
969 msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, params->speech_version_used);
970 }
971
972 /* Chosen Encryption Algorithm (Serving) 3.2.2.44 */
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +0700973 if (params->chosen_encryption_algorithm_serving > 0)
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +0100974 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, params->chosen_encryption_algorithm_serving);
975
976 /* Old BSS to New BSS Information 3.2.2.58 */
977 if (params->old_bss_to_new_bss_info_raw && params->old_bss_to_new_bss_info_raw_len) {
978 msgb_tlv_put(msg, GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION,
979 params->old_bss_to_new_bss_info_raw_len,
980 params->old_bss_to_new_bss_info_raw);
981 } else if (params->old_bss_to_new_bss_info_present) {
982 put_old_bss_to_new_bss_information(msg, &params->old_bss_to_new_bss_info);
983 }
984
985 /* IMSI 3.2.2.6 */
986 if (params->imsi) {
Harald Weltea13fb752020-06-16 08:44:42 +0200987 uint8_t mid_buf[GSM48_MI_SIZE + 2];
988 int mid_len = gsm48_generate_mid_from_imsi(mid_buf, params->imsi);
989 msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2);
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +0100990 }
991
992 if (params->aoip_transport_layer)
993 gsm0808_enc_aoip_trasp_addr(msg, params->aoip_transport_layer);
994
995 if (params->codec_list_msc_preferred)
996 gsm0808_enc_speech_codec_list(msg, params->codec_list_msc_preferred);
997
998 if (params->call_id_present) {
999 uint8_t val[4];
1000 osmo_store32le(params->call_id, val);
1001 msgb_tv_fixed_put(msg, GSM0808_IE_CALL_ID, 4, val);
1002 }
1003
Neels Hofmeyre4378b72021-06-10 00:54:35 +02001004 if (params->more_items && params->kc128_present)
1005 gsm0808_enc_kc128(msg, params->kc128);
1006
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +01001007 if (params->global_call_reference && params->global_call_reference_len) {
1008 msgb_tlv_put(msg, GSM0808_IE_GLOBAL_CALL_REF,
1009 params->global_call_reference_len, params->global_call_reference);
1010 }
1011
1012 /* prepend header with final length */
1013 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1014
1015 return msg;
1016}
1017
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001018/*! Create BSSMAP HANDOVER REQUEST ACKNOWLEDGE message, 3GPP TS 48.008 3.2.1.10.
1019 * Sent from the MT BSC back to the MSC when it has allocated an lchan to handover to.
1020 * l3_info is the RR Handover Command that the MO BSC sends to the MS to move over. */
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001021struct msgb *gsm0808_create_handover_request_ack2(const struct gsm0808_handover_request_ack *params)
Neels Hofmeyrb662b362018-04-16 22:31:15 +02001022{
1023 struct msgb *msg;
1024
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001025 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-REQUEST-ACK");
Neels Hofmeyrb662b362018-04-16 22:31:15 +02001026 if (!msg)
1027 return NULL;
1028
1029 /* Message Type, 3.2.2.1 */
1030 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE);
1031
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001032 /* Layer 3 Information, 3.2.2.24 -- it is actually mandatory, but rather compose a nonstandard message than
1033 * segfault or return NULL without a log message. */
1034 if (params->l3_info && params->l3_info_len)
1035 msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION, params->l3_info_len, params->l3_info);
Neels Hofmeyrb662b362018-04-16 22:31:15 +02001036
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001037 if (params->chosen_channel_present)
1038 msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, params->chosen_channel);
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +07001039 if (params->chosen_encr_alg > 0)
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001040 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, params->chosen_encr_alg);
1041
1042 if (params->chosen_speech_version != 0)
1043 msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, params->chosen_speech_version);
1044
1045 if (params->aoip_transport_layer)
1046 gsm0808_enc_aoip_trasp_addr(msg, params->aoip_transport_layer);
1047
Neels Hofmeyra25a6dc2022-02-23 14:25:22 +01001048 /* AoIP: add Codec List (BSS Supported) 3.2.2.103.
1049 * (codec_list_bss_supported was added to struct gsm0808_handover_request_ack later than speech_codec_chosen
1050 * below, but it needs to come before it in the message coding). */
1051 if (params->more_items && params->codec_list_bss_supported.len)
1052 gsm0808_enc_speech_codec_list(msg, &params->codec_list_bss_supported);
1053
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001054 /* AoIP: Speech Codec (Chosen) 3.2.2.104 */
1055 if (params->speech_codec_chosen_present)
1056 gsm0808_enc_speech_codec(msg, &params->speech_codec_chosen);
Neels Hofmeyrb662b362018-04-16 22:31:15 +02001057
Neels Hofmeyr43c266f2018-08-28 01:08:38 +02001058 /* prepend header with final length */
1059 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1060
Neels Hofmeyrb662b362018-04-16 22:31:15 +02001061 return msg;
1062}
1063
Neels Hofmeyr73b943e2019-03-14 04:10:25 +01001064/*! Same as gsm0808_create_handover_request_ack2() but with less parameters.
1065 * In particular, this lacks the AoIP Transport Layer address. */
1066struct msgb *gsm0808_create_handover_request_ack(const uint8_t *l3_info, uint8_t l3_info_len,
1067 uint8_t chosen_channel, uint8_t chosen_encr_alg,
1068 uint8_t chosen_speech_version)
1069{
1070 struct gsm0808_handover_request_ack params = {
1071 .l3_info = l3_info,
1072 .l3_info_len = l3_info_len,
1073 .chosen_channel = chosen_channel,
1074 .chosen_encr_alg = chosen_encr_alg,
1075 .chosen_speech_version = chosen_speech_version,
1076 };
1077
1078 return gsm0808_create_handover_request_ack2(&params);
1079}
1080
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +01001081/*! Create BSSMAP HANDOVER COMMAND message, 3GPP TS 48.008 3.2.1.11.
1082 * Sent from the MSC to the old BSS to transmit the RR Handover Command received from the new BSS. */
1083struct msgb *gsm0808_create_handover_command(const struct gsm0808_handover_command *params)
1084{
1085 struct msgb *msg;
1086
1087 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-COMMAND");
1088 if (!msg)
1089 return NULL;
1090
1091 /* Message Type, 3.2.2.1 */
1092 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_CMD);
1093
1094 msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION, params->l3_info_len, params->l3_info);
1095
1096 if (params->cell_identifier.id_discr != CELL_IDENT_NO_CELL)
1097 gsm0808_enc_cell_id(msg, &params->cell_identifier);
1098
1099 if (params->new_bss_to_old_bss_info_raw
1100 && params->new_bss_to_old_bss_info_raw_len)
1101 msgb_tlv_put(msg, GSM0808_IE_NEW_BSS_TO_OLD_BSS_INFO, params->new_bss_to_old_bss_info_raw_len,
1102 params->new_bss_to_old_bss_info_raw);
1103
1104 /* prepend header with final length */
1105 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1106
1107 return msg;
1108}
1109
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001110/*! Create BSSMAP HANDOVER DETECT message, 3GPP TS 48.008 3.2.1.40.
1111 * Sent from the MT BSC back to the MSC when the MS has sent a handover RACH request and the MT BSC has
1112 * received the Handover Detect message. */
1113struct msgb *gsm0808_create_handover_detect()
1114{
1115 struct msgb *msg;
1116
1117 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-DETECT");
1118 if (!msg)
1119 return NULL;
1120
1121 /* Message Type, 3.2.2.1 */
1122 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_DETECT);
1123
Neels Hofmeyr43c266f2018-08-28 01:08:38 +02001124 /* prepend header with final length */
1125 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1126
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001127 return msg;
1128}
1129
Neels Hofmeyrf7e9c512019-03-06 04:25:38 +01001130/*! Create BSSMAP HANDOVER SUCCEEDED message, 3GPP TS 48.008 3.2.1.13.
1131 * Sent from the MSC back to the old BSS to notify that the MS has successfully accessed the new BSS. */
1132struct msgb *gsm0808_create_handover_succeeded()
1133{
1134 struct msgb *msg;
1135
1136 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-DETECT");
1137 if (!msg)
1138 return NULL;
1139
1140 /* Message Type, 3.2.2.1 */
1141 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_SUCCEEDED);
1142
1143 /* prepend header with final length */
1144 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1145
1146 return msg;
1147}
1148
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001149/*! Create BSSMAP HANDOVER COMPLETE message, 3GPP TS 48.008 3.2.1.12.
1150 * Sent from the MT BSC back to the MSC when the MS has fully settled into the new lchan. */
1151struct msgb *gsm0808_create_handover_complete(const struct gsm0808_handover_complete *params)
1152{
1153 struct msgb *msg;
1154
1155 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-COMPLETE");
1156 if (!msg)
1157 return NULL;
1158
1159 /* Message Type, 3.2.2.1 */
1160 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_COMPLETE);
1161
1162 /* RR Cause, 3.2.2.22 */
1163 if (params->rr_cause_present)
1164 msgb_tlv_put(msg, GSM0808_IE_RR_CAUSE, 1, &params->rr_cause);
1165
1166 /* AoIP: Speech Codec (Chosen) 3.2.2.104 */
1167 if (params->speech_codec_chosen_present)
1168 gsm0808_enc_speech_codec(msg, &params->speech_codec_chosen);
1169
1170 /* AoIP: add Codec List (BSS Supported) 3.2.2.103 */
1171 if (params->codec_list_bss_supported.len)
1172 gsm0808_enc_speech_codec_list(msg, &params->codec_list_bss_supported);
1173
1174 /* Chosen Encryption Algorithm 3.2.2.44 */
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +07001175 if (params->chosen_encr_alg_present && params->chosen_encr_alg > 0)
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001176 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, params->chosen_encr_alg);
1177
1178 /* LCLS-BSS-Status 3.2.2.119 */
1179 if (params->lcls_bss_status_present)
1180 msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, params->lcls_bss_status);
1181
Neels Hofmeyr43c266f2018-08-28 01:08:38 +02001182 /* prepend header with final length */
1183 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1184
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001185 return msg;
1186}
1187
1188/*! Create BSSMAP HANDOVER FAILURE message, 3GPP TS 48.008 3.2.1.16.
1189 * Sent from the MT BSC back to the MSC when the handover has failed. */
1190struct msgb *gsm0808_create_handover_failure(const struct gsm0808_handover_failure *params)
1191{
1192 struct msgb *msg;
1193
1194 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-FAILURE");
1195 if (!msg)
1196 return NULL;
1197
1198 /* Message Type, 3.2.2.1 */
1199 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_FAILURE);
1200
1201 /* Cause, 3.2.2.5 */
Philipp Maier4f4905f2018-11-30 13:36:12 +01001202 gsm0808_enc_cause(msg, params->cause);
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001203
1204 /* RR Cause, 3.2.2.22 */
1205 if (params->rr_cause_present)
1206 msgb_tlv_put(msg, GSM0808_IE_RR_CAUSE, 1, &params->rr_cause);
1207
1208 /* AoIP: add Codec List (BSS Supported) 3.2.2.103 */
1209 if (params->codec_list_bss_supported.len)
1210 gsm0808_enc_speech_codec_list(msg, &params->codec_list_bss_supported);
1211
Neels Hofmeyr43c266f2018-08-28 01:08:38 +02001212 /* prepend header with final length */
1213 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1214
Neels Hofmeyr60f31532018-04-16 22:42:09 +02001215 return msg;
1216}
1217
Philipp Maier225bdf42018-10-30 14:56:59 +01001218/*! Create BSSMAP HANDOVER PERFORMED message, 3GPP TS 48.008 3.2.1.25.
1219 * \param[in] params All information to be encoded.
1220 * \returns callee-allocated msgb with BSSMAP HANDOVER PERFORMED message */
1221struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_performed *params)
1222{
1223 struct msgb *msg;
1224
1225 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-HANDOVER-PERFORMED");
1226 if (!msg)
1227 return NULL;
1228
1229 /* Message Type, 3.2.2.1 */
1230 msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_PERFORMED);
1231
1232 /* Cause, 3.2.2.5 */
Philipp Maier4f4905f2018-11-30 13:36:12 +01001233 gsm0808_enc_cause(msg, params->cause);
Philipp Maier225bdf42018-10-30 14:56:59 +01001234
1235 /* Cell Identifier, 3.2.2.17 */
1236 gsm0808_enc_cell_id(msg, &params->cell_id);
1237
1238 /* Chosen Channel 3.2.2.33 */
1239 if (params->chosen_channel_present)
1240 msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, params->chosen_channel);
1241
1242 /* Chosen Encryption Algorithm 3.2.2.44 */
Vadim Yanitskiyecaf5fa2020-08-31 19:10:39 +07001243 if (params->chosen_encr_alg_present && params->chosen_encr_alg > 0)
Philipp Maier225bdf42018-10-30 14:56:59 +01001244 msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, params->chosen_encr_alg);
1245
1246 /* Speech Version (chosen) 3.2.2.51 */
1247 if (params->speech_version_chosen_present)
1248 msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, params->speech_version_chosen);
1249
1250 /* AoIP: Speech Codec (chosen) 3.2.2.104 */
1251 if (params->speech_codec_chosen_present)
1252 gsm0808_enc_speech_codec(msg, &params->speech_codec_chosen);
1253
1254 /* LCLS-BSS-Status 3.2.2.119 */
1255 if (params->lcls_bss_status_present)
1256 msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, params->lcls_bss_status);
1257
1258 /* prepend header with final length */
1259 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1260
1261 return msg;
1262}
1263
Neels Hofmeyr9b35e562020-06-22 17:59:18 +02001264/*! Create BSSMAP COMMON ID message, 3GPP TS 48.008 3.2.1.68.
1265 * \param[in] imsi IMSI digits (decimal string).
1266 * \param[in] selected_plmn_id Selected PLMN ID to encode, or NULL to not encode this IE.
1267 * \param[in] last_used_eutran_plnm_id Last used E-UTRAN PLMN ID to encode, or NULL to not encode this IE.
1268 * \returns callee-allocated msgb with BSSMAP COMMON ID message, or NULL if encoding failed. */
Harald Welte1bd726a2020-06-21 22:04:52 +02001269struct msgb *gsm0808_create_common_id(const char *imsi,
1270 const struct osmo_plmn_id *selected_plmn_id,
1271 const struct osmo_plmn_id *last_used_eutran_plnm_id)
1272{
1273 struct msgb *msg;
Harald Welte1bd726a2020-06-21 22:04:52 +02001274 uint8_t *out;
Neels Hofmeyr9b35e562020-06-22 17:59:18 +02001275 struct osmo_mobile_identity mi;
1276 int rc;
Harald Welte1bd726a2020-06-21 22:04:52 +02001277
1278 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "COMMON-ID");
1279 if (!msg)
1280 return NULL;
1281
1282 /* Message Type, 3.2.2.1 */
1283 msgb_v_put(msg, BSS_MAP_MSG_COMMON_ID);
1284
1285 /* mandatory IMSI 3.2.2.6 */
Neels Hofmeyr9b35e562020-06-22 17:59:18 +02001286 mi = (struct osmo_mobile_identity){ .type = GSM_MI_TYPE_IMSI };
1287 OSMO_STRLCPY_ARRAY(mi.imsi, imsi);
1288 out = msgb_tl_put(msg, GSM0808_IE_IMSI);
1289 rc = osmo_mobile_identity_encode_msgb(msg, &mi, false);
1290 if (rc < 0) {
1291 msgb_free(msg);
1292 return NULL;
1293 }
1294 /* write the MI value length */
1295 *out = rc;
Harald Welte1bd726a2020-06-21 22:04:52 +02001296
1297 /* not implemented: SNA Access Information */
1298
1299 /* Selected PLMN ID */
1300 if (selected_plmn_id) {
1301 msgb_v_put(msg, GSM0808_IE_SELECTED_PLMN_ID);
1302 out = msgb_put(msg, 3);
1303 osmo_plmn_to_bcd(out, selected_plmn_id);
1304 }
1305
1306 /* Last used E-UTRAN PLMN ID */
1307 if (last_used_eutran_plnm_id) {
1308 msgb_v_put(msg, GSM0808_IE_LAST_USED_EUTRAN_PLMN_ID);
1309 out = msgb_put(msg, 3);
1310 osmo_plmn_to_bcd(out, last_used_eutran_plnm_id);
1311 }
1312
1313 /* prepend header with final length */
1314 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1315
1316 return msg;
1317}
1318
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001319/*! Prepend a DTAP header to given Message Buffer
Harald Welte96e2a002017-06-12 21:44:18 +02001320 * \param[in] msgb Message Buffer
1321 * \param[in] link_id Link Identifier */
Holger Hans Peter Freyther9a3dec02010-05-16 08:15:40 +08001322void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id)
1323{
1324 uint8_t *hh = msgb_push(msg, 3);
1325 hh[0] = BSSAP_MSG_DTAP;
1326 hh[1] = link_id;
1327 hh[2] = msg->len - 3;
1328}
1329
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001330/*! Create BSSMAP DTAP message
Harald Welte96e2a002017-06-12 21:44:18 +02001331 * \param[in] msg_l3 Messge Buffer containing Layer3 message
1332 * \param[in] link_id Link Identifier
1333 * \returns callee-allocated msgb with BSSMAP DTAP message */
Holger Hans Peter Freytherc25c6682010-11-04 12:26:06 +01001334struct msgb *gsm0808_create_dtap(struct msgb *msg_l3, uint8_t link_id)
1335{
1336 struct dtap_header *header;
1337 uint8_t *data;
1338 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
1339 "dtap");
1340 if (!msg)
1341 return NULL;
1342
1343 /* DTAP header */
1344 msg->l3h = msgb_put(msg, sizeof(*header));
1345 header = (struct dtap_header *) &msg->l3h[0];
1346 header->type = BSSAP_MSG_DTAP;
1347 header->link_id = link_id;
1348 header->length = msgb_l3len(msg_l3);
1349
1350 /* Payload */
1351 data = msgb_put(msg, header->length);
1352 memcpy(data, msg_l3->l3h, header->length);
1353
1354 return msg;
1355}
1356
Neels Hofmeyr5b214e22020-09-18 18:00:50 +02001357struct msgb *gsm0808_create_perform_location_request(const struct gsm0808_perform_location_request *params)
1358{
1359 struct msgb *msg;
1360 uint8_t *out;
1361 int rc;
1362
1363 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-REQUEST");
1364 if (!msg)
1365 return NULL;
1366
1367 /* Message Type, 3.2.2.1 */
1368 msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_RQST);
1369
1370 /* Location Type 3.2.2.63 */
1371 osmo_bssmap_le_ie_enc_location_type(msg, &params->location_type);
1372
1373 if (params->imsi.type == GSM_MI_TYPE_IMSI) {
1374 /* IMSI 3.2.2.6 */
1375 out = msgb_tl_put(msg, GSM0808_IE_IMSI);
1376 rc = osmo_mobile_identity_encode_msgb(msg, &params->imsi, false);
1377 if (rc < 0) {
1378 msgb_free(msg);
1379 return NULL;
1380 }
1381 /* write the MI value length */
1382 *out = rc;
1383 }
1384
1385 /* prepend header with final length */
1386 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1387
1388 return msg;
1389}
1390
1391struct msgb *gsm0808_create_perform_location_response(const struct gsm0808_perform_location_response *params)
1392{
1393 struct msgb *msg;
1394
1395 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-RESPONSE");
1396 if (!msg)
1397 return NULL;
1398
1399 /* Message Type, 3.2.2.1 */
1400 msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE);
1401
1402 if (params->location_estimate_present) {
1403 uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LOCATION_ESTIMATE);
1404 int rc = osmo_gad_raw_write(msg, &params->location_estimate);
1405 if (rc < 0) {
1406 msgb_free(msg);
1407 return NULL;
1408 }
1409 *l = rc;
1410 }
1411
1412 if (params->lcs_cause.present) {
1413 uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LCS_CAUSE);
1414 int rc = osmo_lcs_cause_enc(msg, &params->lcs_cause);
1415 if (rc < 0) {
1416 msgb_free(msg);
1417 return NULL;
1418 }
1419 *l = rc;
1420 }
1421
1422 /* prepend header with final length */
1423 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1424
1425 return msg;
1426}
1427
1428int gsm0808_enc_lcs_cause(struct msgb *msg, const struct lcs_cause_ie *lcs_cause)
1429{
1430 uint8_t *l = msgb_tl_put(msg, GSM0808_IE_LCS_CAUSE);
1431 int rc = osmo_lcs_cause_enc(msg, lcs_cause);
1432 if (rc <= 0)
1433 return rc;
1434 *l = rc;
1435 return rc + 2;
1436}
1437
1438struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lcs_cause)
1439{
1440 struct msgb *msg;
1441
1442 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-PERFORM-LOCATION-ABORT");
1443 if (!msg)
1444 return NULL;
1445
1446 /* Message Type, 3.2.2.1 */
1447 msgb_v_put(msg, BSS_MAP_MSG_PERFORM_LOCATION_ABORT);
1448
1449 gsm0808_enc_lcs_cause(msg, lcs_cause);
1450
1451 /* prepend header with final length */
1452 msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
1453
1454 return msg;
1455}
1456
Harald Welte92107df2014-06-21 23:16:20 +02001457/* As per 3GPP TS 48.008 version 11.7.0 Release 11 */
Holger Hans Peter Freyther7daa01c2010-04-17 05:14:36 +02001458static const struct tlv_definition bss_att_tlvdef = {
1459 .def = {
Harald Welte92107df2014-06-21 23:16:20 +02001460 [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_FIXED, 2 },
1461 [GSM0808_IE_CONNECTION_RELEASE_RQSTED] = { TLV_TYPE_TV },
1462 [GSM0808_IE_RESOURCE_AVAILABLE] = { TLV_TYPE_FIXED, 21 },
1463 [GSM0808_IE_CAUSE] = { TLV_TYPE_TLV },
Holger Hans Peter Freyther7daa01c2010-04-17 05:14:36 +02001464 [GSM0808_IE_IMSI] = { TLV_TYPE_TLV },
1465 [GSM0808_IE_TMSI] = { TLV_TYPE_TLV },
Harald Welte92107df2014-06-21 23:16:20 +02001466 [GSM0808_IE_NUMBER_OF_MSS] = { TLV_TYPE_TV },
Dmitri Soloviev29099422013-07-11 09:25:37 +02001467 [GSM0808_IE_LAYER_3_HEADER_INFORMATION] = { TLV_TYPE_TLV },
Harald Welte92107df2014-06-21 23:16:20 +02001468 [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
1469 [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV },
1470 [GSM0808_IE_PERIODICITY] = { TLV_TYPE_TV },
1471 [GSM0808_IE_EXTENDED_RESOURCE_INDICATOR]= { TLV_TYPE_TV },
1472 [GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE] = { TLV_TYPE_FIXED, 4 },
1473 [GSM0808_IE_LSA_IDENTIFIER] = { TLV_TYPE_TLV },
1474 [GSM0808_IE_LSA_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
Holger Hans Peter Freyther715e9452014-08-21 14:17:45 +02001475 [GSM0808_IE_LSA_INFORMATION] = { TLV_TYPE_TLV },
Harald Welte92107df2014-06-21 23:16:20 +02001476 [GSM0808_IE_CELL_IDENTIFIER] = { TLV_TYPE_TLV },
1477 [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV },
1478 [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
1479 [GSM0808_IE_CLASSMARK_INFORMATION_T3] = { TLV_TYPE_TLV },
1480 [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
1481 [GSM0808_IE_RR_CAUSE] = { TLV_TYPE_TV },
Harald Welte92107df2014-06-21 23:16:20 +02001482 [GSM0808_IE_LAYER_3_INFORMATION] = { TLV_TYPE_TLV },
1483 [GSM0808_IE_DLCI] = { TLV_TYPE_TV },
1484 [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV },
1485 [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
1486 [GSM0808_IE_CELL_ID_LIST_SEGMENT] = { TLV_TYPE_TLV },
1487 [GSM0808_IE_CELL_ID_LIST_SEG_EST_CELLS] = { TLV_TYPE_TLV },
1488 [GSM0808_IE_CELL_ID_LIST_SEG_CELLS_TBE] = { TLV_TYPE_TLV },
1489 [GSM0808_IE_CELL_ID_LIST_SEG_REL_CELLS] = { TLV_TYPE_TLV },
1490 [GSM0808_IE_CELL_ID_LIST_SEG_NE_CELLS] = { TLV_TYPE_TLV },
1491 [GSM0808_IE_RESPONSE_RQST] = { TLV_TYPE_T },
1492 [GSM0808_IE_RESOURCE_INDICATION_METHOD] = { TLV_TYPE_TV },
1493 [GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1] = { TLV_TYPE_TV },
1494 [GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST] = { TLV_TYPE_TLV },
1495 [GSM0808_IE_DIAGNOSTIC] = { TLV_TYPE_TLV },
1496 [GSM0808_IE_CHOSEN_CHANNEL] = { TLV_TYPE_TV },
1497 [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV },
1498 [GSM0808_IE_LAYER_3_MESSAGE_CONTENTS] = { TLV_TYPE_TLV },
1499 [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV },
1500 [GSM0808_IE_TRACE_TYPE] = { TLV_TYPE_TV },
1501 [GSM0808_IE_TRIGGERID] = { TLV_TYPE_TLV },
1502 [GSM0808_IE_TRACE_REFERENCE] = { TLV_TYPE_TV },
1503 [GSM0808_IE_TRANSACTIONID] = { TLV_TYPE_TLV },
1504 [GSM0808_IE_MOBILE_IDENTITY] = { TLV_TYPE_TLV },
1505 [GSM0808_IE_OMCID] = { TLV_TYPE_TLV },
1506 [GSM0808_IE_FORWARD_INDICATOR] = { TLV_TYPE_TV },
Holger Hans Peter Freytherc2b7f922010-08-04 18:50:43 +08001507 [GSM0808_IE_CHOSEN_ENCR_ALG] = { TLV_TYPE_TV },
Harald Welte92107df2014-06-21 23:16:20 +02001508 [GSM0808_IE_CIRCUIT_POOL] = { TLV_TYPE_TV },
1509 [GSM0808_IE_CIRCUIT_POOL_LIST] = { TLV_TYPE_TLV },
1510 [GSM0808_IE_TIME_INDICATION] = { TLV_TYPE_TV },
1511 [GSM0808_IE_RESOURCE_SITUATION] = { TLV_TYPE_TLV },
1512 [GSM0808_IE_CURRENT_CHANNEL_TYPE_1] = { TLV_TYPE_TV },
1513 [GSM0808_IE_QUEUEING_INDICATOR] = { TLV_TYPE_TV },
1514 [GSM0808_IE_SPEECH_VERSION] = { TLV_TYPE_TV },
1515 [GSM0808_IE_ASSIGNMENT_REQUIREMENT] = { TLV_TYPE_TV },
1516 [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T },
1517 [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV },
1518 [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV },
1519 [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV },
1520 [GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION] = { TLV_TYPE_TLV },
1521 [GSM0808_IE_LCS_QOS] = { TLV_TYPE_TLV },
1522 [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV },
1523 [GSM0808_IE_LCS_PRIORITY] = { TLV_TYPE_TLV },
1524 [GSM0808_IE_LOCATION_TYPE] = { TLV_TYPE_TLV },
1525 [GSM0808_IE_LOCATION_ESTIMATE] = { TLV_TYPE_TLV },
1526 [GSM0808_IE_POSITIONING_DATA] = { TLV_TYPE_TLV },
1527 [GSM0808_IE_LCS_CAUSE] = { TLV_TYPE_TLV },
Pau Espin Pedrolfffd7c32022-03-18 13:45:42 +01001528 [GSM0808_IE_LCS_CLIENT_TYPE] = { TLV_TYPE_TLV },
Harald Welte92107df2014-06-21 23:16:20 +02001529 [GSM0808_IE_APDU] = { TLV_TYPE_TLV },
1530 [GSM0808_IE_NETWORK_ELEMENT_IDENTITY] = { TLV_TYPE_TLV },
1531 [GSM0808_IE_GPS_ASSISTANCE_DATA] = { TLV_TYPE_TLV },
1532 [GSM0808_IE_DECIPHERING_KEYS] = { TLV_TYPE_TLV },
1533 [GSM0808_IE_RETURN_ERROR_RQST] = { TLV_TYPE_TLV },
1534 [GSM0808_IE_RETURN_ERROR_CAUSE] = { TLV_TYPE_TLV },
1535 [GSM0808_IE_SEGMENTATION] = { TLV_TYPE_TLV },
1536 [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TLV },
1537 [GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS] = { TLV_TYPE_TLV },
1538 [GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000] = { TLV_TYPE_TLV },
1539 [GSM0808_IE_GERAN_CLASSMARK] = { TLV_TYPE_TLV },
1540 [GSM0808_IE_GERAN_BSC_CONTAINER] = { TLV_TYPE_TLV },
1541 [GSM0808_IE_NEW_BSS_TO_OLD_BSS_INFO] = { TLV_TYPE_TLV },
1542 [GSM0800_IE_INTER_SYSTEM_INFO] = { TLV_TYPE_TLV },
1543 [GSM0808_IE_SNA_ACCESS_INFO] = { TLV_TYPE_TLV },
1544 [GSM0808_IE_VSTK_RAND_INFO] = { TLV_TYPE_TLV },
Pau Espin Pedrol3cf47592022-03-18 14:13:01 +01001545 [GSM0808_IE_VSTK_INFO] = { TLV_TYPE_TLV },
Harald Welte92107df2014-06-21 23:16:20 +02001546 [GSM0808_IE_PAGING_INFO] = { TLV_TYPE_TV },
1547 [GSM0808_IE_IMEI] = { TLV_TYPE_TLV },
1548 [GSM0808_IE_VELOCITY_ESTIMATE] = { TLV_TYPE_TLV },
1549 [GSM0808_IE_VGCS_FEATURE_FLAGS] = { TLV_TYPE_TLV },
1550 [GSM0808_IE_TALKER_PRIORITY] = { TLV_TYPE_TV },
1551 [GSM0808_IE_EMERGENCY_SET_INDICATION] = { TLV_TYPE_T },
1552 [GSM0808_IE_TALKER_IDENTITY] = { TLV_TYPE_TLV },
1553 [GSM0808_IE_SMS_TO_VGCS] = { TLV_TYPE_TLV },
1554 [GSM0808_IE_VGCS_TALKER_MODE] = { TLV_TYPE_TLV },
1555 [GSM0808_IE_VGCS_VBS_CELL_STATUS] = { TLV_TYPE_TLV },
1556 [GSM0808_IE_GANSS_ASSISTANCE_DATA] = { TLV_TYPE_TLV },
1557 [GSM0808_IE_GANSS_POSITIONING_DATA] = { TLV_TYPE_TLV },
1558 [GSM0808_IE_GANSS_LOCATION_TYPE] = { TLV_TYPE_TLV },
1559 [GSM0808_IE_APP_DATA] = { TLV_TYPE_TLV },
1560 [GSM0808_IE_DATA_IDENTITY] = { TLV_TYPE_TLV },
1561 [GSM0808_IE_APP_DATA_INFO] = { TLV_TYPE_TLV },
1562 [GSM0808_IE_MSISDN] = { TLV_TYPE_TLV },
1563 [GSM0808_IE_AOIP_TRASP_ADDR] = { TLV_TYPE_TLV },
1564 [GSM0808_IE_SPEECH_CODEC_LIST] = { TLV_TYPE_TLV },
1565 [GSM0808_IE_SPEECH_CODEC] = { TLV_TYPE_TLV },
1566 [GSM0808_IE_CALL_ID] = { TLV_TYPE_FIXED, 4 },
1567 [GSM0808_IE_CALL_ID_LIST] = { TLV_TYPE_TLV },
1568 [GSM0808_IE_A_IF_SEL_FOR_RESET] = { TLV_TYPE_TV },
1569 [GSM0808_IE_KC_128] = { TLV_TYPE_FIXED, 16 },
1570 [GSM0808_IE_CSG_IDENTIFIER] = { TLV_TYPE_TLV },
1571 [GSM0808_IE_REDIR_ATTEMPT_FLAG] = { TLV_TYPE_T },
1572 [GSM0808_IE_REROUTE_REJ_CAUSE] = { TLV_TYPE_TV },
1573 [GSM0808_IE_SEND_SEQ_NUM] = { TLV_TYPE_TV },
1574 [GSM0808_IE_REROUTE_COMPL_OUTCOME] = { TLV_TYPE_TV },
1575 [GSM0808_IE_GLOBAL_CALL_REF] = { TLV_TYPE_TLV },
1576 [GSM0808_IE_LCLS_CONFIG] = { TLV_TYPE_TV },
1577 [GSM0808_IE_LCLS_CONN_STATUS_CTRL] = { TLV_TYPE_TV },
1578 [GSM0808_IE_LCLS_CORR_NOT_NEEDED] = { TLV_TYPE_TV },
1579 [GSM0808_IE_LCLS_BSS_STATUS] = { TLV_TYPE_TV },
1580 [GSM0808_IE_LCLS_BREAK_REQ] = { TLV_TYPE_TV },
1581 [GSM0808_IE_CSFB_INDICATION] = { TLV_TYPE_T },
1582 [GSM0808_IE_CS_TO_PS_SRVCC] = { TLV_TYPE_T },
1583 [GSM0808_IE_SRC_ENB_TO_TGT_ENB_TRANSP] = { TLV_TYPE_TLV },
1584 [GSM0808_IE_CS_TO_PS_SRVCC_IND] = { TLV_TYPE_T },
1585 [GSM0808_IE_CN_TO_MS_TRANSP_INFO] = { TLV_TYPE_TLV },
1586 [GSM0808_IE_SELECTED_PLMN_ID] = { TLV_TYPE_FIXED, 3 },
1587 [GSM0808_IE_LAST_USED_EUTRAN_PLMN_ID] = { TLV_TYPE_FIXED, 3 },
Pau Espin Pedrol3cf47592022-03-18 14:13:01 +01001588 [GSM0808_IE_OLD_LAI] = { TLV_TYPE_FIXED, 5 },
1589 [GSM0808_IE_ATTACH_INDICATOR] = { TLV_TYPE_T },
1590 [GSM0808_IE_SELECTED_OPERATOR] = { TLV_TYPE_FIXED, 3 },
1591 [GSM0808_IE_PS_REGISTERED_OPERATOR] = { TLV_TYPE_FIXED, 3 },
1592 [GSM0808_IE_CS_REGISTERED_OPERATOR] = { TLV_TYPE_FIXED, 3 },
Pau Espin Pedrol18506c82019-04-16 15:47:59 +02001593
1594 /* Osmocom extensions */
1595 [GSM0808_IE_OSMO_OSMUX_SUPPORT] = { TLV_TYPE_T },
1596 [GSM0808_IE_OSMO_OSMUX_CID] = { TLV_TYPE_TV },
Holger Hans Peter Freyther7daa01c2010-04-17 05:14:36 +02001597 },
1598};
1599
Harald Weltef4d45ab2011-07-16 12:13:00 +02001600const struct tlv_definition *gsm0808_att_tlvdef(void)
Holger Hans Peter Freyther7daa01c2010-04-17 05:14:36 +02001601{
1602 return &bss_att_tlvdef;
1603}
Harald Welte9b837e62011-07-11 17:43:19 +02001604
Pau Espin Pedrolcde47792021-04-19 12:24:02 +02001605/* As per 3GPP TS 48.008 version 16.0.0 Release 16 § 3.2.2.58 Old BSS to New BSS Information */
1606const struct tlv_definition gsm0808_old_bss_to_new_bss_info_att_tlvdef = {
1607 .def = {
1608 [GSM0808_FE_IE_EXTRA_INFORMATION] = { TLV_TYPE_TLV },
1609 [GSM0808_FE_IE_CURRENT_CHANNEL_TYPE_2] = { TLV_TYPE_TLV },
1610 [GSM0808_FE_IE_TARGET_CELL_RADIO_INFORMATION] = { TLV_TYPE_TLV },
1611 [GSM0808_FE_IE_GPRS_SUSPEND_INFORMATION] = { TLV_TYPE_TLV },
1612 [GSM0808_FE_IE_MULTIRATE_CONFIGURATION_INFORMATION] = { TLV_TYPE_TLV },
1613 [GSM0808_FE_IE_DUAL_TRANSFER_MODE_INFORMATION] = { TLV_TYPE_TLV },
1614 [GSM0808_FE_IE_INTER_RAT_HANDOVER_INFO] = { TLV_TYPE_TLV },
1615 [GSM0808_FE_IE_CDMA2000_CAPABILITY_INFORMATION] = { TLV_TYPE_TLV },
1616 [GSM0808_FE_IE_DOWNLINK_CELL_LOAD_INFORMATION] = { TLV_TYPE_TLV },
1617 [GSM0808_FE_IE_UPLINK_CELL_LOAD_INFORMATION] = { TLV_TYPE_TLV },
1618 [GSM0808_FE_IE_CELL_LOAD_INFORMATION_GROUP] = { TLV_TYPE_TLV },
1619 [GSM0808_FE_IE_CELL_LOAD_INFORMATION] = { TLV_TYPE_TLV },
1620 [GSM0808_FE_IE_PS_INDICATION] = { TLV_TYPE_TLV },
1621 [GSM0808_FE_IE_DTM_HANDOVER_COMMAND_INDICATION] = { TLV_TYPE_TLV },
1622 [GSM0808_FE_IE_D_RNTI] = { TLV_TYPE_TLV },
1623 [GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION] = { TLV_TYPE_TLV },
1624 [GSM0808_FE_IE_SOURCE_CELL_ID] = { TLV_TYPE_TLV },
1625 [GSM0808_FE_IE_IRAT_MEASUREMENT_CONFIGURATION_EXTENDED_E_ARFCNS] = { TLV_TYPE_TLV },
1626 [GSM0808_FE_IE_VGCS_TALKER_MODE] = { TLV_TYPE_TLV },
1627 [GSM0808_FE_IE_LAST_USED_EUTRAN_PLMN_ID] = { TLV_TYPE_FIXED, 3 },
1628 },
1629};
1630
Pau Espin Pedrol392f6072019-11-27 12:07:04 +01001631const struct value_string gsm0406_dlci_sapi_names[] = {
1632 { DLCI_SAPI_RR_MM_CC, "RR/MM/CC" },
1633 { DLCI_SAPI_SMS, "SMS" },
1634 { 0, NULL }
1635};
1636
Harald Welte9b837e62011-07-11 17:43:19 +02001637static const struct value_string gsm0808_msgt_names[] = {
1638 { BSS_MAP_MSG_ASSIGMENT_RQST, "ASSIGNMENT REQ" },
1639 { BSS_MAP_MSG_ASSIGMENT_COMPLETE, "ASSIGNMENT COMPL" },
1640 { BSS_MAP_MSG_ASSIGMENT_FAILURE, "ASSIGNMENT FAIL" },
Harald Welte92107df2014-06-21 23:16:20 +02001641 { BSS_MAP_MSG_CHAN_MOD_RQST, "CHANNEL MODIFY REQUEST" },
Harald Welte9b837e62011-07-11 17:43:19 +02001642
1643 { BSS_MAP_MSG_HANDOVER_RQST, "HANDOVER REQ" },
1644 { BSS_MAP_MSG_HANDOVER_REQUIRED, "HANDOVER REQUIRED" },
1645 { BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE,"HANDOVER REQ ACK" },
1646 { BSS_MAP_MSG_HANDOVER_CMD, "HANDOVER CMD" },
1647 { BSS_MAP_MSG_HANDOVER_COMPLETE, "HANDOVER COMPLETE" },
1648 { BSS_MAP_MSG_HANDOVER_SUCCEEDED, "HANDOVER SUCCESS" },
1649 { BSS_MAP_MSG_HANDOVER_FAILURE, "HANDOVER FAILURE" },
1650 { BSS_MAP_MSG_HANDOVER_PERFORMED, "HANDOVER PERFORMED" },
1651 { BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE, "HANDOVER CAND ENQ" },
1652 { BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE, "HANDOVER CAND RESP" },
1653 { BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT, "HANDOVER REQ REJ" },
1654 { BSS_MAP_MSG_HANDOVER_DETECT, "HANDOVER DETECT" },
Harald Welte92107df2014-06-21 23:16:20 +02001655 { BSS_MAP_MSG_INT_HANDOVER_REQUIRED, "INT HANDOVER REQ" },
1656 { BSS_MAP_MSG_INT_HANDOVER_REQUIRED_REJ,"INT HANDOVER REQ REJ" },
1657 { BSS_MAP_MSG_INT_HANDOVER_CMD, "INT HANDOVER CMD" },
1658 { BSS_MAP_MSG_INT_HANDOVER_ENQUIRY, "INT HANDOVER ENQ" },
Harald Welte9b837e62011-07-11 17:43:19 +02001659
1660 { BSS_MAP_MSG_CLEAR_CMD, "CLEAR COMMAND" },
1661 { BSS_MAP_MSG_CLEAR_COMPLETE, "CLEAR COMPLETE" },
1662 { BSS_MAP_MSG_CLEAR_RQST, "CLEAR REQUEST" },
1663 { BSS_MAP_MSG_SAPI_N_REJECT, "SAPI N REJECT" },
1664 { BSS_MAP_MSG_CONFUSION, "CONFUSION" },
1665
1666 { BSS_MAP_MSG_SUSPEND, "SUSPEND" },
1667 { BSS_MAP_MSG_RESUME, "RESUME" },
1668 { BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION, "CONN ORIENT INFO" },
1669 { BSS_MAP_MSG_PERFORM_LOCATION_RQST, "PERFORM LOC REQ" },
1670 { BSS_MAP_MSG_LSA_INFORMATION, "LSA INFORMATION" },
1671 { BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE, "PERFORM LOC RESP" },
1672 { BSS_MAP_MSG_PERFORM_LOCATION_ABORT, "PERFORM LOC ABORT" },
1673 { BSS_MAP_MSG_COMMON_ID, "COMMON ID" },
Harald Welte92107df2014-06-21 23:16:20 +02001674 { BSS_MAP_MSG_REROUTE_CMD, "REROUTE COMMAND" },
1675 { BSS_MAP_MSG_REROUTE_COMPLETE, "REROUTE COMPLETE" },
Harald Welte9b837e62011-07-11 17:43:19 +02001676
1677 { BSS_MAP_MSG_RESET, "RESET" },
1678 { BSS_MAP_MSG_RESET_ACKNOWLEDGE, "RESET ACK" },
1679 { BSS_MAP_MSG_OVERLOAD, "OVERLOAD" },
1680 { BSS_MAP_MSG_RESET_CIRCUIT, "RESET CIRCUIT" },
1681 { BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE, "RESET CIRCUIT ACK" },
1682 { BSS_MAP_MSG_MSC_INVOKE_TRACE, "MSC INVOKE TRACE" },
1683 { BSS_MAP_MSG_BSS_INVOKE_TRACE, "BSS INVOKE TRACE" },
1684 { BSS_MAP_MSG_CONNECTIONLESS_INFORMATION, "CONNLESS INFO" },
Harald Welte92107df2014-06-21 23:16:20 +02001685 { BSS_MAP_MSG_RESET_IP_RSRC, "RESET IP RESOURCE" },
1686 { BSS_MAP_MSG_RESET_IP_RSRC_ACK, "RESET IP RESOURCE ACK" },
Harald Welte9b837e62011-07-11 17:43:19 +02001687
1688 { BSS_MAP_MSG_BLOCK, "BLOCK" },
1689 { BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE, "BLOCK ACK" },
1690 { BSS_MAP_MSG_UNBLOCK, "UNBLOCK" },
1691 { BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE, "UNBLOCK ACK" },
1692 { BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK, "CIRC GROUP BLOCK" },
1693 { BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE, "CIRC GORUP BLOCK ACK" },
1694 { BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK, "CIRC GROUP UNBLOCK" },
1695 { BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE, "CIRC GROUP UNBLOCK ACK" },
1696 { BSS_MAP_MSG_UNEQUIPPED_CIRCUIT, "UNEQUIPPED CIRCUIT" },
1697 { BSS_MAP_MSG_CHANGE_CIRCUIT, "CHANGE CIRCUIT" },
1698 { BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE, "CHANGE CIRCUIT ACK" },
1699
1700 { BSS_MAP_MSG_RESOURCE_RQST, "RESOURCE REQ" },
1701 { BSS_MAP_MSG_RESOURCE_INDICATION, "RESOURCE IND" },
1702 { BSS_MAP_MSG_PAGING, "PAGING" },
1703 { BSS_MAP_MSG_CIPHER_MODE_CMD, "CIPHER MODE CMD" },
1704 { BSS_MAP_MSG_CLASSMARK_UPDATE, "CLASSMARK UPDATE" },
1705 { BSS_MAP_MSG_CIPHER_MODE_COMPLETE, "CIPHER MODE COMPLETE" },
1706 { BSS_MAP_MSG_QUEUING_INDICATION, "QUEUING INDICATION" },
1707 { BSS_MAP_MSG_COMPLETE_LAYER_3, "COMPLETE LAYER 3" },
1708 { BSS_MAP_MSG_CLASSMARK_RQST, "CLASSMARK REQ" },
1709 { BSS_MAP_MSG_CIPHER_MODE_REJECT, "CIPHER MODE REJECT" },
1710 { BSS_MAP_MSG_LOAD_INDICATION, "LOAD IND" },
1711
Harald Welte92107df2014-06-21 23:16:20 +02001712 { BSS_MAP_MSG_VGCS_VBS_SETUP, "VGCS/VBS SETUP" },
1713 { BSS_MAP_MSG_VGCS_VBS_SETUP_ACK, "VGCS/VBS SETUP ACK" },
1714 { BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE, "VGCS/VBS SETUP REFUSE" },
1715 { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST, "VGCS/VBS ASSIGN REQ" },
1716 { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT, "VGCS/VBS ASSIGN RES" },
1717 { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE, "VGCS/VBS ASSIGN FAIL" },
1718 { BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION, "VGCS/VBS QUEUING IND" },
1719 { BSS_MAP_MSG_UPLINK_RQST, "UPLINK REQ" },
1720 { BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE, "UPLINK REQ ACK" },
1721 { BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION, "UPLINK REQ CONF" },
1722 { BSS_MAP_MSG_UPLINK_RELEASE_INDICATION,"UPLINK REL IND" },
1723 { BSS_MAP_MSG_UPLINK_REJECT_CMD, "UPLINK REJ CMD" },
1724 { BSS_MAP_MSG_UPLINK_RELEASE_CMD, "UPLINK REL CMD" },
1725 { BSS_MAP_MSG_UPLINK_SEIZED_CMD, "UPLINK SEIZED CMD" },
1726 { BSS_MAP_MSG_VGCS_ADDL_INFO, "VGCS ADDL INFO" },
1727 { BSS_MAP_MSG_NOTIFICATION_DATA, "NOTIF DATA" },
1728 { BSS_MAP_MSG_UPLINK_APP_DATA, "UPLINK APP DATA" },
1729
1730 { BSS_MAP_MSG_LCLS_CONNECT_CTRL, "LCLS-CONNECT-CONTROL" },
Keith Whyte486d9842022-10-06 03:16:15 +01001731 { BSS_MAP_MSG_LCLS_CONNECT_CTRL_ACK, "LCLS-CONNECT-CONTROL-ACK" },
Harald Welte92107df2014-06-21 23:16:20 +02001732 { BSS_MAP_MSG_LCLS_NOTIFICATION, "LCLS-NOTIFICATION" },
Harald Welte9b837e62011-07-11 17:43:19 +02001733
1734 { 0, NULL }
1735};
1736
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001737/*! Return string name of BSSMAP Message Type */
Harald Welte9b837e62011-07-11 17:43:19 +02001738const char *gsm0808_bssmap_name(uint8_t msg_type)
1739{
1740 return get_value_string(gsm0808_msgt_names, msg_type);
1741}
1742
1743static const struct value_string gsm0808_bssap_names[] = {
1744 { BSSAP_MSG_BSS_MANAGEMENT, "MANAGEMENT" },
1745 { BSSAP_MSG_DTAP, "DTAP" },
Neels Hofmeyr90fdb082017-03-01 14:59:44 +01001746 { 0, NULL }
Harald Welte9b837e62011-07-11 17:43:19 +02001747};
1748
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001749/*! Return string name of BSSAP Message Type */
Harald Welte9b837e62011-07-11 17:43:19 +02001750const char *gsm0808_bssap_name(uint8_t msg_type)
1751{
1752 return get_value_string(gsm0808_bssap_names, msg_type);
1753}
Harald Welte96e2a002017-06-12 21:44:18 +02001754
Neels Hofmeyrffad5742018-01-12 05:34:03 +01001755const struct value_string gsm0808_speech_codec_type_names[] = {
1756 { GSM0808_SCT_FR1, "FR1" },
1757 { GSM0808_SCT_FR2, "FR2" },
1758 { GSM0808_SCT_FR3, "FR3" },
1759 { GSM0808_SCT_FR4, "FR4" },
1760 { GSM0808_SCT_FR5, "FR5" },
1761 { GSM0808_SCT_HR1, "HR1" },
1762 { GSM0808_SCT_HR3, "HR3" },
1763 { GSM0808_SCT_HR4, "HR4" },
1764 { GSM0808_SCT_HR6, "HR6" },
1765 { GSM0808_SCT_CSD, "CSD" },
1766 { 0, NULL }
1767};
1768
Philipp Maiercdd05812018-07-12 18:21:07 +02001769const struct value_string gsm0808_permitted_speech_names[] = {
1770 { GSM0808_PERM_FR1, "FR1" },
1771 { GSM0808_PERM_FR2, "FR2" },
1772 { GSM0808_PERM_FR3, "FR3" },
1773 { GSM0808_PERM_FR4, "FR4" },
1774 { GSM0808_PERM_FR5, "FR5" },
1775 { GSM0808_PERM_HR1, "HR1" },
1776 { GSM0808_PERM_HR2, "HR2" },
1777 { GSM0808_PERM_HR3, "HR3" },
1778 { GSM0808_PERM_HR4, "HR4" },
1779 { GSM0808_PERM_HR6, "HR6" },
1780 { 0, NULL }
1781};
1782
Pau Espin Pedrolf2cda622018-07-06 17:16:41 +02001783const struct value_string gsm0808_chosen_enc_alg_names[] = {
1784 { GSM0808_ALG_ID_A5_0, "A5/0" },
1785 { GSM0808_ALG_ID_A5_1, "A5/1" },
1786 { GSM0808_ALG_ID_A5_2, "A5/2" },
1787 { GSM0808_ALG_ID_A5_3, "A5/3" },
1788 { GSM0808_ALG_ID_A5_4, "A5/4" },
1789 { GSM0808_ALG_ID_A5_5, "A5/5" },
1790 { GSM0808_ALG_ID_A5_6, "A5/6" },
1791 { GSM0808_ALG_ID_A5_7, "A5/7" },
1792 { 0, NULL }
1793};
1794
Philipp Maierdbb76592018-03-29 12:55:26 +02001795static const struct value_string gsm0808_cause_names[] = {
1796 { GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, "RADIO INTERFACE MESSAGE FAILURE" },
1797 { GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, "RADIO INTERFACE FAILURE" },
1798 { GSM0808_CAUSE_UPLINK_QUALITY, "UPLINK QUALITY" },
1799 { GSM0808_CAUSE_UPLINK_STRENGTH, "UPLINK STRENGTH" },
1800 { GSM0808_CAUSE_DOWNLINK_QUALITY, "DOWNLINK QUALITY" },
1801 { GSM0808_CAUSE_DOWNLINK_STRENGTH, "DOWNLINK STRENGTH" },
1802 { GSM0808_CAUSE_DISTANCE, "DISTANCE" },
1803 { GSM0808_CAUSE_O_AND_M_INTERVENTION, "O AND M INTERVENTION" },
1804 { GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION, "RESPONSE TO MSC INVOCATION" },
1805 { GSM0808_CAUSE_CALL_CONTROL, "CALL CONTROL" },
1806 { GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION, "RADIO INTERFACE FAILURE REVERSION" },
1807 { GSM0808_CAUSE_HANDOVER_SUCCESSFUL, "HANDOVER SUCCESSFUL" },
1808 { GSM0808_CAUSE_BETTER_CELL, "BETTER CELL" },
1809 { GSM0808_CAUSE_DIRECTED_RETRY, "DIRECTED RETRY" },
1810 { GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL, "JOINED GROUP CALL CHANNEL" },
1811 { GSM0808_CAUSE_TRAFFIC, "TRAFFIC" },
1812 { GSM0808_CAUSE_REDUCE_LOAD_IN_SERVING_CELL, "REDUCE LOAD IN SERVING CELL" },
1813 { GSM0808_CAUSE_TRAFFIC_LOAD_IN_TGT_HIGHER_THAN_IN_SRC_CELL, "TRAFFIC LOAD IN TGT HIGHER THAN IN SRC CELL" },
1814 { GSM0808_CAUSE_RELOCATION_TRIGGERED, "RELOCATION TRIGGERED" },
Thorsten Alteholz0062a5f2018-05-15 15:28:55 +02001815 { GSM0808_CAUSE_REQUESTED_OPT_NOT_AUTHORISED, "REQUESTED OPT NOT AUTHORISED" },
Philipp Maierdbb76592018-03-29 12:55:26 +02001816 { GSM0808_CAUSE_ALT_CHAN_CONFIG_REQUESTED, "ALT CHAN CONFIG REQUESTED" },
1817 { GSM0808_CAUSE_RESP_TO_INT_HO_ENQ_MSG, "RESP TO INT HO ENQ MSG" },
1818 { GSM0808_CAUSE_INT_HO_ENQUIRY_REJECT, "INT HO ENQUIRY REJECT" },
1819 { GSM0808_CAUSE_REDUNDANCY_LEVEL_NOT_ADEQUATE, "REDUNDANCY LEVEL NOT ADEQUATE" },
1820 { GSM0808_CAUSE_EQUIPMENT_FAILURE, "EQUIPMENT FAILURE" },
1821 { GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, "NO RADIO RESOURCE AVAILABLE" },
1822 { GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE, "RQSTED TERRESTRIAL RESOURCE UNAVAILABLE" },
1823 { GSM0808_CAUSE_CCCH_OVERLOAD, "CCCH OVERLOAD" },
1824 { GSM0808_CAUSE_PROCESSOR_OVERLOAD, "PROCESSOR OVERLOAD" },
1825 { GSM0808_CAUSE_BSS_NOT_EQUIPPED, "BSS NOT EQUIPPED" },
1826 { GSM0808_CAUSE_MS_NOT_EQUIPPED, "MS NOT EQUIPPED" },
1827 { GSM0808_CAUSE_INVALID_CELL, "INVALID CELL" },
1828 { GSM0808_CAUSE_TRAFFIC_LOAD, "TRAFFIC LOAD" },
1829 { GSM0808_CAUSE_PREEMPTION, "PREEMPTION" },
1830 { GSM0808_CAUSE_DTM_HO_SGSN_FAILURE, "DTM HO SGSN FAILURE" },
1831 { GSM0808_CAUSE_DTM_HO_PS_ALLOC_FAILURE, "DTM HO PS ALLOC FAILURE" },
1832 { GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE, "RQSTED TRANSCODING RATE ADAPTION UNAVAILABLE" },
1833 { GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH, "CIRCUIT POOL MISMATCH" },
1834 { GSM0808_CAUSE_SWITCH_CIRCUIT_POOL, "SWITCH CIRCUIT POOL" },
1835 { GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE, "RQSTED SPEECH VERSION UNAVAILABLE" },
1836 { GSM0808_CAUSE_LSA_NOT_ALLOWED, "LSA NOT ALLOWED" },
1837 { GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL, "REQ CODEC TYPE OR CONFIG UNAVAIL" },
1838 { GSM0808_CAUSE_REQ_A_IF_TYPE_UNAVAIL, "REQ A IF TYPE UNAVAIL" },
1839 { GSM0808_CAUSE_INVALID_CSG_CELL, "INVALID CSG CELL" },
1840 { GSM0808_CAUSE_REQ_REDUND_LEVEL_NOT_AVAIL, "REQ REDUND LEVEL NOT AVAIL" },
1841 { GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED, "CIPHERING ALGORITHM NOT SUPPORTED" },
1842 { GSM0808_CAUSE_GERAN_IU_MODE_FAILURE, "GERAN IU MODE FAILURE" },
1843 { GSM0808_CAUSE_INC_RELOC_NOT_SUPP_DT_PUESBINE_FEATURE, "INC RELOC NOT SUPP DT PUESBINE FEATURE" },
1844 { GSM0808_CAUSE_ACCESS_RESTRICTED_DUE_TO_SHARED_NETWORKS, "ACCESS RESTRICTED DUE TO SHARED NETWORKS" },
1845 { GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_NOT_SUPP, "REQ CODEC TYPE OR CONFIG NOT SUPP" },
1846 { GSM0808_CAUSE_REQ_A_IF_TYPE_NOT_SUPP, "REQ A IF TYPE NOT SUPP" },
1847 { GSM0808_CAUSE_REQ_REDUND_LVL_NOT_SUPP, "REQ REDUND LVL NOT SUPP" },
1848 { GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED, "TERRESTRIAL CIRCUIT ALREADY ALLOCATED" },
1849 { GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS, "INVALID MESSAGE CONTENTS" },
1850 { GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING, "INFORMATION ELEMENT OR FIELD MISSING" },
1851 { GSM0808_CAUSE_INCORRECT_VALUE, "INCORRECT VALUE" },
1852 { GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE, "UNKNOWN MESSAGE TYPE" },
1853 { GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT, "UNKNOWN INFORMATION ELEMENT" },
1854 { GSM0808_CAUSE_DTM_HO_INVALID_PS_IND, "DTM HO INVALID PS IND" },
1855 { GSM0808_CAUSE_CALL_ID_ALREADY_ALLOC, "CALL ID ALREADY ALLOC" },
1856 { GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, "PROTOCOL ERROR BETWEEN BSS AND MSC" },
Thorsten Alteholz0062a5f2018-05-15 15:28:55 +02001857 { GSM0808_CAUSE_VGCS_VBS_CALL_NON_EXISTENT, "VGCS VBS CALL NON EXISTENT" },
Philipp Maierdbb76592018-03-29 12:55:26 +02001858 { GSM0808_CAUSE_DTM_HO_TIMER_EXPIRY, "DTM HO TIMER EXPIRY" },
1859 { 0, NULL }
1860};
1861
Maxaa934632018-11-07 13:16:54 +01001862static const struct value_string gsm0808_cause_class_names[] = {
1863 { GSM0808_CAUSE_CLASS_NORM0, "Normal event" },
1864 { GSM0808_CAUSE_CLASS_NORM1, "Normal event" },
1865 { GSM0808_CAUSE_CLASS_RES_UNAVAIL, "Resource unavailable" },
1866 { GSM0808_CAUSE_CLASS_SRV_OPT_NA, "Service or option not available" },
1867 { GSM0808_CAUSE_CLASS_SRV_OPT_NIMPL, "Service or option not implemented" },
1868 { GSM0808_CAUSE_CLASS_INVAL, "Invalid message" },
1869 { GSM0808_CAUSE_CLASS_PERR, "Protocol error" },
1870 { GSM0808_CAUSE_CLASS_INTW, "Interworking" },
1871 { 0, NULL }
1872};
1873
1874/*! Return string name of BSSMAP Cause Class name */
1875const char *gsm0808_cause_class_name(enum gsm0808_cause_class class)
1876{
1877 return get_value_string(gsm0808_cause_class_names, class);
1878}
1879
Philipp Maierdbb76592018-03-29 12:55:26 +02001880/*! Return string name of BSSMAP Cause name */
Maxaa934632018-11-07 13:16:54 +01001881const char *gsm0808_cause_name(enum gsm0808_cause cause)
Philipp Maierdbb76592018-03-29 12:55:26 +02001882{
1883 return get_value_string(gsm0808_cause_names, cause);
1884}
1885
Alexander Chemerisfdfe25b2020-05-12 23:21:56 +03001886enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp)
1887{
1888 const uint8_t *buf = TLVP_VAL_MINLEN(tp, GSM0808_IE_CAUSE, 1);
1889
1890 if (!buf)
1891 return -EBADMSG;
1892
1893 if (TLVP_LEN(tp, GSM0808_IE_CAUSE) > 1) {
1894 if (!gsm0808_cause_ext(buf[0]))
1895 return -EINVAL;
1896 return buf[1];
1897 }
1898
1899 return buf[0];
1900}
1901
Alexander Chemeris22630e62020-05-13 00:44:04 +03001902const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer)
1903{
1904 switch (pointer) {
1905 case 0:
1906 return "Error location not determined";
1907 case 1:
1908 return "The first octet of the message received (i.e. the message type) was found erroneous (unknown)";
1909 case 0xfd:
1910 return "The first octet of the BSSAP header (Discrimination) was found erroneous";
1911 case 0xfe:
1912 return "(DTAP only) The DLCI (second) octet of the BSSAP header was found erroneous";
1913 case 0xff:
1914 return "The last octet of the BSSAP header (length indicator) was found erroneous";
1915 default:
1916 snprintf(str_buff, sizeof(str_buff), "The %d octet of the message received was found erroneous", pointer);
1917 return str_buff;
1918 }
1919}
1920
1921const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer)
1922{
1923 if (bit_pointer == 0) {
1924 return "No particular part of the octet is indicated";
1925 } else if (bit_pointer > 8) {
1926 return "Reserved value";
1927 }
1928
1929 snprintf(str_buff, sizeof(str_buff),
1930 "An error was provoked by the field whose most significant bit is in bit position %d",
1931 bit_pointer);
1932 return str_buff;
1933}
1934
Harald Welteebd362d2018-06-02 14:11:19 +02001935const struct value_string gsm0808_lcls_config_names[] = {
1936 { GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" },
1937 { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL,
1938 "Connect both-way, bi-cast UL to CN" },
1939 { GSM0808_LCLS_CFG_BOTH_WAY_AND_SEND_DL,
1940 "Connect both-way, send access DL from CN" },
1941 { GSM0808_LCLS_CFG_BOTH_WAY_AND_SEND_DL_BLOCK_LOCAL_DL,
1942 "Connect both-way, send access DL from CN, block local DL" },
1943 { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL_SEND_DL,
1944 "Connect both-way, bi-cast UL to CN, send access DL from CN" },
1945 { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL_SEND_DL_BLOCK_LOCAL_DL,
1946 "Connect both-way, bi-cast UL to CN, send access DL from CN, block local DL" },
Max961db7c2018-11-08 11:40:23 +01001947 { GSM0808_LCLS_CFG_NA, "Not available" },
Harald Welteebd362d2018-06-02 14:11:19 +02001948 { 0, NULL }
1949};
1950
1951const struct value_string gsm0808_lcls_control_names[] = {
1952 { GSM0808_LCLS_CSC_CONNECT, "Connect" },
1953 { GSM0808_LCLS_CSC_DO_NOT_CONNECT, "Do not connect" },
1954 { GSM0808_LCLS_CSC_RELEASE_LCLS, "Release LCLS" },
1955 { GSM0808_LCLS_CSC_BICAST_UL_AT_HANDOVER, "Bi-cast UL at Handover" },
1956 { GSM0808_LCLS_CSC_BICAST_UL_AND_RECV_DL_AT_HANDOVER, "Bi-cast UL and receive DL at Handover" },
Max961db7c2018-11-08 11:40:23 +01001957 { GSM0808_LCLS_CSC_NA, "Not available" },
Harald Welteebd362d2018-06-02 14:11:19 +02001958 { 0, NULL }
1959};
1960
1961const struct value_string gsm0808_lcls_status_names[] = {
1962 { GSM0808_LCLS_STS_NOT_YET_LS, "Call not yet locally switched" },
1963 { GSM0808_LCLS_STS_NOT_POSSIBLE_LS, "Call not possible to be locally switched" },
1964 { GSM0808_LCLS_STS_NO_LONGER_LS, "Call is no longer locally switched" },
1965 { GSM0808_LCLS_STS_REQ_LCLS_NOT_SUPP, "Requested LCLS configuration is not supported" },
1966 { GSM0808_LCLS_STS_LOCALLY_SWITCHED, "Call is locally switched with requested LCLS config" },
Max961db7c2018-11-08 11:40:23 +01001967 { GSM0808_LCLS_STS_NA, "Not available" },
Harald Welteebd362d2018-06-02 14:11:19 +02001968 { 0, NULL }
1969};
1970
Harald Welte96e2a002017-06-12 21:44:18 +02001971/*! @} */