blob: 4353b9ad06c2235b27097f9fd21144ee40b291bc [file] [log] [blame]
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +01001/* GSM 08.08 BSSMAP handling */
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +01002/* (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * (C) 2009-2012 by On-Waves
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +01004 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +01009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010015 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010018 *
19 */
20
21#include <openbsc/osmo_bsc.h>
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +010022#include <openbsc/osmo_bsc_grace.h>
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010023#include <openbsc/osmo_bsc_rf.h>
Neels Hofmeyra42855f2017-02-23 21:49:55 +010024#include <openbsc/bsc_msc_data.h>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010025#include <openbsc/debug.h>
Neels Hofmeyr6d804b12017-02-18 22:20:46 +010026#include <openbsc/bsc_subscriber.h>
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010027#include <openbsc/mgcp.h>
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +010028#include <openbsc/paging.h>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010029
Harald Welted36ff762011-03-23 18:26:56 +010030#include <osmocom/gsm/protocol/gsm_08_08.h>
31#include <osmocom/gsm/gsm0808.h>
Philipp Maierfbf66102017-04-09 12:32:51 +020032#include <osmocom/gsm/gsm0808_utils.h>
33#include <openbsc/osmo_bsc_sigtran.h>
34#include <openbsc/a_reset.h>
35#include <osmocom/core/byteswap.h>
36
37#define IP_V4_ADDR_LEN 4
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010038
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010039/*
40 * helpers for the assignment command
41 */
Philipp Maierfbf66102017-04-09 12:32:51 +020042
43/* Helper function for match_codec_pref(), looks up a matching permitted speech
44 * value for a given msc audio codec pref */
45enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support
46 *audio)
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010047{
48 if (audio->hr) {
49 switch (audio->ver) {
50 case 1:
51 return GSM0808_PERM_HR1;
52 break;
53 case 2:
54 return GSM0808_PERM_HR2;
55 break;
56 case 3:
57 return GSM0808_PERM_HR3;
58 break;
59 default:
Philipp Maierfbf66102017-04-09 12:32:51 +020060 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n",
61 audio->ver);
62 return GSM0808_PERM_FR1;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010063 }
64 } else {
65 switch (audio->ver) {
66 case 1:
67 return GSM0808_PERM_FR1;
68 break;
69 case 2:
70 return GSM0808_PERM_FR2;
71 break;
72 case 3:
73 return GSM0808_PERM_FR3;
74 break;
75 default:
Philipp Maierfbf66102017-04-09 12:32:51 +020076 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n",
77 audio->ver);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010078 return GSM0808_PERM_HR1;
79 }
80 }
81}
82
Philipp Maierfbf66102017-04-09 12:32:51 +020083/* Helper function for match_codec_pref(), looks up a matching chan mode for
84 * a given permitted speech value */
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010085enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
86{
87 switch (speech) {
88 case GSM0808_PERM_HR1:
89 case GSM0808_PERM_FR1:
90 return GSM48_CMODE_SPEECH_V1;
91 break;
92 case GSM0808_PERM_HR2:
93 case GSM0808_PERM_FR2:
94 return GSM48_CMODE_SPEECH_EFR;
95 break;
96 case GSM0808_PERM_HR3:
97 case GSM0808_PERM_FR3:
98 return GSM48_CMODE_SPEECH_AMR;
99 break;
Philipp Maierfbf66102017-04-09 12:32:51 +0200100 default:
101 LOGP(DMSC, LOGL_FATAL,
102 "Unsupported permitted speech selected, assuming AMR as channel mode...\n");
103 return GSM48_CMODE_SPEECH_AMR;
104 }
105}
106
107/* Helper function for match_codec_pref(), tests if a given audio support
108 * matches one of the permitted speech settings of the channel type element.
109 * The matched permitted speech value is then also compared against the
110 * speech codec list. (optional, only relevant for AoIP) */
111static bool test_codec_pref(const struct gsm0808_channel_type *ct,
112 const struct gsm0808_speech_codec_list *scl,
113 uint8_t perm_spch)
114{
115 unsigned int i;
116 bool match = false;
117 struct gsm0808_speech_codec sc;
118 int rc;
119
120 /* Try to finde the given permitted speech value in the
121 * codec list of the channel type element */
122 for (i = 0; i < ct->perm_spch_len; i++) {
123 if (ct->perm_spch[i] == perm_spch) {
124 match = true;
125 break;
126 }
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100127 }
128
Philipp Maierfbf66102017-04-09 12:32:51 +0200129 /* If we do not have a speech codec list to test against,
130 * we just exit early (will be always the case in non-AoIP networks) */
131 if (!scl)
132 return match;
133
134 /* If we failed to match until here, there is no
135 * point in testing further */
136 if (match == false)
137 return false;
138
139 /* Extrapolate speech codec data */
140 rc = gsm0808_speech_codec_from_chan_type(&sc, perm_spch);
141 if (rc < 0)
142 return false;
143
144 /* Try to find extrapolated speech codec data in
145 * the speech codec list */
146 for (i = 0; i < scl->len; i++) {
147 if (memcmp(&sc, &scl->codec[i], sizeof(sc)) == 0)
148 return true;
149 }
150
151 return false;
152}
153
154/* Helper function for bssmap_handle_assignm_req(), matches the codec
155 * preferences from the MSC with the codec preferences */
156static int match_codec_pref(int *full_rate, enum gsm48_chan_mode *chan_mode,
157 const struct gsm0808_channel_type *ct,
158 const struct gsm0808_speech_codec_list *scl,
159 const struct bsc_msc_data *msc)
160{
161 unsigned int i;
162 uint8_t perm_spch;
163 bool match = false;
164
165 for (i = 0; i < msc->audio_length; i++) {
166 perm_spch = audio_support_to_gsm88(msc->audio_support[i]);
167 if (test_codec_pref(ct, scl, perm_spch)) {
168 match = true;
169 break;
170 }
171 }
172
173 /* Exit without result, in case no match can be deteched */
174 if (!match) {
175 *full_rate = -1;
176 *chan_mode = GSM48_CMODE_SIGN;
177 return -1;
178 }
179
180 /* Check if the result is a half or full rate codec */
181 if (perm_spch == GSM0808_PERM_HR1 || perm_spch == GSM0808_PERM_HR2
182 || perm_spch == GSM0808_PERM_HR3 || perm_spch == GSM0808_PERM_HR4
183 || perm_spch == GSM0808_PERM_HR6)
184 *full_rate = 0;
185 else
186 *full_rate = 1;
187
188 /* Lookup a channel mode for the selected codec */
189 *chan_mode = gsm88_to_chan_mode(perm_spch);
190
191 return 0;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100192}
193
Neels Hofmeyra369e242017-02-23 21:57:23 +0100194static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100195 struct msgb *msg, unsigned int length)
196{
Philipp Maierfbf66102017-04-09 12:32:51 +0200197 LOGP(DMSC, LOGL_NOTICE, "RESET ACK from MSC: %s\n",
198 osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance),
199 &msc->a.msc_addr));
200
201 /* Inform the FSM that controls the RESET/RESET-ACK procedure
202 * that we have successfully received the reset-ack message */
203 a_reset_ack_confirm(msc->a.reset);
204
205 return 0;
206}
207
208/* Handle MSC sided reset */
209static int bssmap_handle_reset(struct bsc_msc_data *msc,
210 struct msgb *msg, unsigned int length)
211{
212 LOGP(DMSC, LOGL_NOTICE, "RESET from MSC: %s\n",
213 osmo_sccp_addr_name(osmo_ss7_instance_find(msc->a.cs7_instance),
214 &msc->a.msc_addr));
215
216 /* Instruct the bsc to close all open sigtran connections and to
217 * close all active channels on the BTS side as well */
218 osmo_bsc_sigtran_reset(msc);
219
220 /* Inform the MSC that we have received the reset request and
221 * that we acted accordingly */
222 osmo_bsc_sigtran_tx_reset_ack(msc);
223
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100224 return 0;
225}
226
227/* GSM 08.08 § 3.2.1.19 */
Neels Hofmeyra369e242017-02-23 21:57:23 +0100228static int bssmap_handle_paging(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100229 struct msgb *msg, unsigned int payload_length)
230{
Neels Hofmeyr6d804b12017-02-18 22:20:46 +0100231 struct bsc_subscr *subscr;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100232 struct tlv_parsed tp;
233 char mi_string[GSM48_MI_SIZE];
234 uint32_t tmsi = GSM_RESERVED_TMSI;
235 unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
236 uint8_t data_length;
237 const uint8_t *data;
238 uint8_t chan_needed = RSL_CHANNEED_ANY;
239
240 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
241
242 if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200243 LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100244 return -1;
245 } else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
246 LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
247 return -1;
248 }
249
250 if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200251 LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100252 return -1;
253 }
254
Harald Welted55cef92012-01-20 17:20:51 +0100255 if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) &&
256 TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) {
Daniel Willmann8a485f02014-06-27 17:05:47 +0200257 tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100258 }
259
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100260 /*
261 * parse the IMSI
262 */
263 gsm48_mi_to_string(mi_string, sizeof(mi_string),
264 TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
265
266 /*
267 * parse the cell identifier list
268 */
269 data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
270 data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
271
272 /*
273 * Support paging to all network or one BTS at one LAC
274 */
275 if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
Max4c6e6672014-10-22 16:21:20 +0200276 lac = osmo_load16be(&data[1]);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100277 } else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200278 LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100279 return -1;
280 }
281
282 if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
283 chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
284
285 if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
286 LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
287 }
288
Neels Hofmeyr6d804b12017-02-18 22:20:46 +0100289 subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers,
290 mi_string);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100291 if (!subscr) {
292 LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
293 return -1;
294 }
295
296 subscr->lac = lac;
297 subscr->tmsi = tmsi;
298
Harald Weltecccd3012011-07-11 18:18:35 +0200299 LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
Neels Hofmeyr6d804b12017-02-18 22:20:46 +0100300 bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy,
301 subscr, chan_needed, msc);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100302 return 0;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100303}
304
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100305/*
306 * GSM 08.08 § 3.1.9.1 and 3.2.1.21...
307 * release our gsm_subscriber_connection and send message
308 */
309static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
310 struct msgb *msg, unsigned int payload_length)
311{
312 struct msgb *resp;
313
314 /* TODO: handle the cause of this package */
315
316 if (conn->conn) {
Harald Weltecccd3012011-07-11 18:18:35 +0200317 LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100318 gsm0808_clear(conn->conn);
Neels Hofmeyr42eb0142016-05-20 17:15:44 +0200319 bsc_subscr_con_free(conn->conn);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100320 conn->conn = NULL;
321 }
322
323 /* send the clear complete message */
324 resp = gsm0808_create_clear_complete();
325 if (!resp) {
326 LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
327 return -1;
328 }
329
Philipp Maierfbf66102017-04-09 12:32:51 +0200330 osmo_bsc_sigtran_send(conn, resp);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100331 return 0;
332}
333
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100334/*
335 * GSM 08.08 § 3.4.7 cipher mode handling. We will have to pick
336 * the cipher to be used for this. In case we are already using
337 * a cipher we will have to send cipher mode reject to the MSC,
338 * otherwise we will have to pick something that we and the MS
339 * is supporting. Currently we are doing it in a rather static
340 * way by picking one ecnryption or no encrytpion.
341 */
342static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
343 struct msgb *msg, unsigned int payload_length)
344{
345 uint16_t len;
346 struct gsm_network *network = NULL;
347 const uint8_t *data;
348 struct tlv_parsed tp;
349 struct msgb *resp;
350 int reject_cause = -1;
351 int include_imeisv = 1;
352
353 if (!conn->conn) {
354 LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
355 goto reject;
356 }
357
358 if (conn->ciphering_handled) {
359 LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
360 goto reject;
361 }
362
363 conn->ciphering_handled = 1;
364
365 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
366 if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
367 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
368 goto reject;
369 }
370
371 /*
372 * check if our global setting is allowed
373 * - Currently we check for A5/0 and A5/1
374 * - Copy the key if that is necessary
375 * - Otherwise reject
376 */
377 len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
378 if (len < 1) {
379 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
380 goto reject;
381 }
382
383 network = conn->conn->bts->network;
384 data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
385
386 if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
387 include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
388
389 if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
390 gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
391 } else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
392 gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
393 } else {
394 LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
395 goto reject;
396 }
397
Harald Welte75413c42011-07-12 00:03:43 +0200398 return 0;
399
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100400reject:
401 resp = gsm0808_create_cipher_reject(reject_cause);
402 if (!resp) {
403 LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
404 return -1;
405 }
406
Philipp Maierfbf66102017-04-09 12:32:51 +0200407 osmo_bsc_sigtran_send(conn, resp);
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100408 return -1;
409}
410
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100411/*
412 * Handle the assignment request message.
413 *
414 * See §3.2.1.1 for the message type
415 */
416static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
417 struct msgb *msg, unsigned int length)
418{
419 struct msgb *resp;
Neels Hofmeyra369e242017-02-23 21:57:23 +0100420 struct bsc_msc_data *msc;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100421 struct tlv_parsed tp;
Philipp Maierfbf66102017-04-09 12:32:51 +0200422 uint8_t timeslot = 0;
423 uint8_t multiplex = 0;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100424 enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
Philipp Maierfbf66102017-04-09 12:32:51 +0200425 int port, full_rate = -1;
426 bool aoip = false;
427 struct sockaddr_storage rtp_addr;
428 struct sockaddr_in *rtp_addr_in;
429 struct gsm0808_channel_type ct;
430 struct gsm0808_speech_codec_list scl;
431 struct gsm0808_speech_codec_list *scl_ptr = NULL;
432 int rc;
433 const uint8_t *data;
434 char len;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100435
436 if (!conn->conn) {
Philipp Maierfbf66102017-04-09 12:32:51 +0200437 LOGP(DMSC, LOGL_ERROR,
438 "No lchan/msc_data in cipher mode command.\n");
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100439 return -1;
440 }
441
Philipp Maierfbf66102017-04-09 12:32:51 +0200442 msc = conn->msc;
443
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100444 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
445
Philipp Maierfbf66102017-04-09 12:32:51 +0200446 /* Check for channel type element, if its missing, immediately reject */
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100447 if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200448 LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n");
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100449 goto reject;
450 }
451
Philipp Maierfbf66102017-04-09 12:32:51 +0200452 /* Detect if a CIC code is present, if so, we use the classic ip.access
453 * method to calculate the RTP port */
454 if (TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
455 conn->cic =
456 osmo_load16be(TLVP_VAL
457 (&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
458 timeslot = conn->cic & 0x1f;
459 multiplex = (conn->cic & ~0x1f) >> 5;
460 } else if (TLVP_PRESENT(&tp, GSM0808_IE_AOIP_TRASP_ADDR)) {
461 /* Decode AoIP transport address element */
462 data = TLVP_VAL(&tp, GSM0808_IE_AOIP_TRASP_ADDR);
463 len = TLVP_LEN(&tp, GSM0808_IE_AOIP_TRASP_ADDR);
464 rc = gsm0808_dec_aoip_trasp_addr(&rtp_addr, data, len);
465 if (rc < 0) {
466 LOGP(DMSC, LOGL_ERROR,
467 "Unable to decode aoip transport address.\n");
468 goto reject;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100469 }
Philipp Maierfbf66102017-04-09 12:32:51 +0200470 aoip = true;
471 } else {
472 LOGP(DMSC, LOGL_ERROR,
473 "transport address missing. Audio routing will not work.\n");
474 goto reject;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100475 }
476
Philipp Maierfbf66102017-04-09 12:32:51 +0200477 /* Decode speech codec list (AoIP) */
478 if (aoip) {
479 /* Check for speech codec list element */
480 if (!TLVP_PRESENT(&tp, GSM0808_IE_SPEECH_CODEC_LIST)) {
481 LOGP(DMSC, LOGL_ERROR,
482 "Mandatory speech codec list not present.\n");
483 goto reject;
484 }
485
486 /* Decode Speech Codec list */
487 data = TLVP_VAL(&tp, GSM0808_IE_SPEECH_CODEC_LIST);
488 len = TLVP_LEN(&tp, GSM0808_IE_SPEECH_CODEC_LIST);
489 rc = gsm0808_dec_speech_codec_list(&scl, data, len);
490 if (rc < 0) {
491 LOGP(DMSC, LOGL_ERROR,
492 "Unable to decode speech codec list\n");
493 goto reject;
494 }
495 scl_ptr = &scl;
496 }
497
498 /* Decode Channel Type element */
499 data = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
500 len = TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE);
501 rc = gsm0808_dec_channel_type(&ct, data, len);
502 if (rc < 0) {
503 LOGP(DMSC, LOGL_ERROR, "unable to decode channel type.\n");
504 goto reject;
505 }
506
507 /* Currently we only support a limited subset of all
508 * possible channel types. The limitation ends by not using
509 * multi-slot, limiting the channel coding to speech */
510 if (ct.ch_indctr != GSM0808_CHAN_SPEECH) {
511 LOGP(DMSC, LOGL_ERROR,
512 "Unsupported channel type, currently only speech is supported!\n");
513 goto reject;
514 }
515
516 /* Match codec information from the assignment command against the
517 * local preferences of the BSC */
518 rc = match_codec_pref(&full_rate, &chan_mode, &ct, scl_ptr, msc);
519 if (rc < 0) {
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100520 LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
521 goto reject;
522 }
523
Philipp Maierfbf66102017-04-09 12:32:51 +0200524 if (aoip == false) {
525 /* map it to a MGCP Endpoint and a RTP port */
526 port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
527 conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
528 conn->rtp_ip = 0;
529 } else {
530 /* use address / port supplied with the AoIP
531 * transport address element */
532 if (rtp_addr.ss_family == AF_INET) {
533 rtp_addr_in = (struct sockaddr_in *)&rtp_addr;
534 conn->rtp_port = osmo_ntohs(rtp_addr_in->sin_port);
535 memcpy(&conn->rtp_ip, &rtp_addr_in->sin_addr.s_addr,
536 IP_V4_ADDR_LEN);
537 conn->rtp_ip = osmo_ntohl(conn->rtp_ip);
538 } else {
539 LOGP(DMSC, LOGL_ERROR,
540 "Unsopported addressing scheme. (supports only IPV4)\n");
541 goto reject;
542 }
543 }
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100544
545 return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
546
547reject:
Philipp Maierfbf66102017-04-09 12:32:51 +0200548 resp =
549 gsm0808_create_assignment_failure
550 (GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100551 if (!resp) {
552 LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
553 return -1;
554 }
555
Philipp Maierfbf66102017-04-09 12:32:51 +0200556 osmo_bsc_sigtran_send(conn, resp);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100557 return -1;
558}
559
Neels Hofmeyra369e242017-02-23 21:57:23 +0100560static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100561 struct msgb *msg, unsigned int length)
562{
563 int ret = 0;
564
565 if (length < 1) {
566 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
567 return -1;
568 }
569
Harald Weltecccd3012011-07-11 18:18:35 +0200570 LOGP(DMSC, LOGL_INFO, "Rx MSC UDT BSSMAP %s\n",
571 gsm0808_bssmap_name(msg->l4h[0]));
572
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100573 switch (msg->l4h[0]) {
574 case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200575 ret = bssmap_handle_reset_ack(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100576 break;
Philipp Maierfbf66102017-04-09 12:32:51 +0200577 case BSS_MAP_MSG_RESET:
578 ret = bssmap_handle_reset(msc, msg, length);
579 break;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100580 case BSS_MAP_MSG_PAGING:
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +0100581 ret = bssmap_handle_paging(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100582 break;
583 }
584
585 return ret;
586}
587
588static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
589 struct msgb *msg, unsigned int length)
590{
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100591 int ret = 0;
592
593 if (length < 1) {
594 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
595 return -1;
596 }
597
Harald Weltecccd3012011-07-11 18:18:35 +0200598 LOGP(DMSC, LOGL_INFO, "Rx MSC DT1 BSSMAP %s\n",
599 gsm0808_bssmap_name(msg->l4h[0]));
600
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100601 switch (msg->l4h[0]) {
602 case BSS_MAP_MSG_CLEAR_CMD:
603 ret = bssmap_handle_clear_command(conn, msg, length);
604 break;
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100605 case BSS_MAP_MSG_CIPHER_MODE_CMD:
606 ret = bssmap_handle_cipher_mode(conn, msg, length);
607 break;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100608 case BSS_MAP_MSG_ASSIGMENT_RQST:
609 ret = bssmap_handle_assignm_req(conn, msg, length);
610 break;
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100611 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200612 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
613 gsm0808_bssmap_name(msg->l4h[0]));
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100614 break;
615 }
616
617 return ret;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100618}
619
620static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
621 struct msgb *msg, unsigned int length)
622{
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100623 struct dtap_header *header;
624 struct msgb *gsm48;
625 uint8_t *data;
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100626 int rc, dtap_rc;
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100627
Harald Weltecccd3012011-07-11 18:18:35 +0200628 LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n",
629 osmo_hexdump(msg->l3h, length));
630
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100631 if (!conn->conn) {
632 LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
633 return -1;
634 }
635
636 header = (struct dtap_header *) msg->l3h;
637 if (sizeof(*header) >= length) {
Holger Hans Peter Freyther2f2be572012-03-16 12:18:39 +0100638 LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %zu got: %u\n", sizeof(*header), length);
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200639 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100640 return -1;
641 }
642
643 if (header->length > length - sizeof(*header)) {
644 LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit: header: %u length: %u\n", header->length, length);
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200645 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100646 return -1;
647 }
648
Harald Weltecccd3012011-07-11 18:18:35 +0200649 LOGP(DMSC, LOGL_INFO, "Rx MSC DTAP, SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0);
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100650
651 /* forward the data */
Holger Hans Peter Freyther8239e062016-01-25 22:03:25 +0100652 gsm48 = gsm48_msgb_alloc_name("GSM 04.08 DTAP RCV");
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100653 if (!gsm48) {
654 LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
655 return -1;
656 }
657
658 gsm48->l3h = gsm48->data;
659 data = msgb_put(gsm48, length - sizeof(*header));
660 memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
661
662 /* pass it to the filter for extra actions */
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100663 rc = bsc_scan_msc_msg(conn->conn, gsm48);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100664 dtap_rc = gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100665 if (rc == BSS_SEND_USSD)
666 bsc_send_welcome_ussd(conn->conn);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100667 return dtap_rc;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100668}
669
Neels Hofmeyra369e242017-02-23 21:57:23 +0100670int bsc_handle_udt(struct bsc_msc_data *msc,
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100671 struct msgb *msgb, unsigned int length)
672{
673 struct bssmap_header *bs;
674
Harald Weltecccd3012011-07-11 18:18:35 +0200675 LOGP(DMSC, LOGL_DEBUG, "Rx MSC UDT: %s\n",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200676 osmo_hexdump(msgb->l3h, length));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100677
678 if (length < sizeof(*bs)) {
679 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
680 return -1;
681 }
682
683 bs = (struct bssmap_header *) msgb->l3h;
684 if (bs->length < length - sizeof(*bs))
685 return -1;
686
687 switch (bs->type) {
688 case BSSAP_MSG_BSS_MANAGEMENT:
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100689 msgb->l4h = &msgb->l3h[sizeof(*bs)];
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200690 bssmap_rcvmsg_udt(msc, msgb, length - sizeof(*bs));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100691 break;
692 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200693 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
694 gsm0808_bssmap_name(bs->type));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100695 }
696
697 return 0;
698}
699
Philipp Maierfbf66102017-04-09 12:32:51 +0200700int bsc_handle_dt(struct osmo_bsc_sccp_con *conn,
701 struct msgb *msg, unsigned int len)
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100702{
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100703 if (len < sizeof(struct bssmap_header)) {
704 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
705 }
706
707 switch (msg->l3h[0]) {
708 case BSSAP_MSG_BSS_MANAGEMENT:
709 msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
710 bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
711 break;
712 case BSSAP_MSG_DTAP:
713 dtap_rcvmsg(conn, msg, len);
714 break;
715 default:
Harald Weltecccd3012011-07-11 18:18:35 +0200716 LOGP(DMSC, LOGL_NOTICE, "Unimplemented BSSAP msg type: %s\n",
717 gsm0808_bssap_name(msg->l3h[0]));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100718 }
719
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100720 return -1;
721}