blob: 100f664416b133f7f81c97f675275628d6231c4b [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>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010032
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010033/*
34 * helpers for the assignment command
35 */
36enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support *audio)
37{
38 if (audio->hr) {
39 switch (audio->ver) {
40 case 1:
41 return GSM0808_PERM_HR1;
42 break;
43 case 2:
44 return GSM0808_PERM_HR2;
45 break;
46 case 3:
47 return GSM0808_PERM_HR3;
48 break;
49 default:
50 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
51 return GSM0808_PERM_FR1;
52 }
53 } else {
54 switch (audio->ver) {
55 case 1:
56 return GSM0808_PERM_FR1;
57 break;
58 case 2:
59 return GSM0808_PERM_FR2;
60 break;
61 case 3:
62 return GSM0808_PERM_FR3;
63 break;
64 default:
65 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
66 return GSM0808_PERM_HR1;
67 }
68 }
69}
70
71enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
72{
73 switch (speech) {
74 case GSM0808_PERM_HR1:
75 case GSM0808_PERM_FR1:
76 return GSM48_CMODE_SPEECH_V1;
77 break;
78 case GSM0808_PERM_HR2:
79 case GSM0808_PERM_FR2:
80 return GSM48_CMODE_SPEECH_EFR;
81 break;
82 case GSM0808_PERM_HR3:
83 case GSM0808_PERM_FR3:
84 return GSM48_CMODE_SPEECH_AMR;
85 break;
86 }
87
88 LOGP(DMSC, LOGL_FATAL, "Should not be reached.\n");
89 return GSM48_CMODE_SPEECH_AMR;
90}
91
Neels Hofmeyra369e242017-02-23 21:57:23 +010092static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +010093 struct msgb *msg, unsigned int length)
94{
95 LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
96 return 0;
97}
98
99/* GSM 08.08 ยง 3.2.1.19 */
Neels Hofmeyra369e242017-02-23 21:57:23 +0100100static int bssmap_handle_paging(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100101 struct msgb *msg, unsigned int payload_length)
102{
Neels Hofmeyr6d804b12017-02-18 22:20:46 +0100103 struct bsc_subscr *subscr;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100104 struct tlv_parsed tp;
105 char mi_string[GSM48_MI_SIZE];
106 uint32_t tmsi = GSM_RESERVED_TMSI;
107 unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
108 uint8_t data_length;
109 const uint8_t *data;
110 uint8_t chan_needed = RSL_CHANNEED_ANY;
111
112 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
113
114 if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200115 LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100116 return -1;
117 } else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
118 LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
119 return -1;
120 }
121
122 if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200123 LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100124 return -1;
125 }
126
Harald Welted55cef92012-01-20 17:20:51 +0100127 if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) &&
128 TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) {
Daniel Willmann8a485f02014-06-27 17:05:47 +0200129 tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100130 }
131
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100132 /*
133 * parse the IMSI
134 */
135 gsm48_mi_to_string(mi_string, sizeof(mi_string),
136 TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
137
138 /*
139 * parse the cell identifier list
140 */
141 data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
142 data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
143
144 /*
145 * Support paging to all network or one BTS at one LAC
146 */
147 if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
Max4c6e6672014-10-22 16:21:20 +0200148 lac = osmo_load16be(&data[1]);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100149 } else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200150 LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100151 return -1;
152 }
153
154 if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
155 chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
156
157 if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
158 LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
159 }
160
Neels Hofmeyr6d804b12017-02-18 22:20:46 +0100161 subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers,
162 mi_string);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100163 if (!subscr) {
164 LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
165 return -1;
166 }
167
168 subscr->lac = lac;
169 subscr->tmsi = tmsi;
170
Harald Weltecccd3012011-07-11 18:18:35 +0200171 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 +0100172 bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy,
173 subscr, chan_needed, msc);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100174 return 0;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100175}
176
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100177/*
178 * GSM 08.08 ยง 3.1.9.1 and 3.2.1.21...
179 * release our gsm_subscriber_connection and send message
180 */
181static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
182 struct msgb *msg, unsigned int payload_length)
183{
184 struct msgb *resp;
185
186 /* TODO: handle the cause of this package */
187
188 if (conn->conn) {
Harald Weltecccd3012011-07-11 18:18:35 +0200189 LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100190 gsm0808_clear(conn->conn);
Neels Hofmeyr42eb0142016-05-20 17:15:44 +0200191 bsc_subscr_con_free(conn->conn);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100192 conn->conn = NULL;
193 }
194
195 /* send the clear complete message */
196 resp = gsm0808_create_clear_complete();
197 if (!resp) {
198 LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
199 return -1;
200 }
201
202 bsc_queue_for_msc(conn, resp);
203 return 0;
204}
205
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100206/*
207 * GSM 08.08 ยง 3.4.7 cipher mode handling. We will have to pick
208 * the cipher to be used for this. In case we are already using
209 * a cipher we will have to send cipher mode reject to the MSC,
210 * otherwise we will have to pick something that we and the MS
211 * is supporting. Currently we are doing it in a rather static
212 * way by picking one ecnryption or no encrytpion.
213 */
214static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
215 struct msgb *msg, unsigned int payload_length)
216{
217 uint16_t len;
218 struct gsm_network *network = NULL;
219 const uint8_t *data;
220 struct tlv_parsed tp;
221 struct msgb *resp;
222 int reject_cause = -1;
223 int include_imeisv = 1;
224
225 if (!conn->conn) {
226 LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
227 goto reject;
228 }
229
230 if (conn->ciphering_handled) {
231 LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
232 goto reject;
233 }
234
235 conn->ciphering_handled = 1;
236
237 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
238 if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
239 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
240 goto reject;
241 }
242
243 /*
244 * check if our global setting is allowed
245 * - Currently we check for A5/0 and A5/1
246 * - Copy the key if that is necessary
247 * - Otherwise reject
248 */
249 len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
250 if (len < 1) {
251 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
252 goto reject;
253 }
254
255 network = conn->conn->bts->network;
256 data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
257
258 if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
259 include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
260
261 if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
262 gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
263 } else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
264 gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
265 } else {
266 LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
267 goto reject;
268 }
269
Harald Welte75413c42011-07-12 00:03:43 +0200270 return 0;
271
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100272reject:
273 resp = gsm0808_create_cipher_reject(reject_cause);
274 if (!resp) {
275 LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
276 return -1;
277 }
278
279 bsc_queue_for_msc(conn, resp);
280 return -1;
281}
282
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100283/*
284 * Handle the assignment request message.
285 *
286 * See ยง3.2.1.1 for the message type
287 */
288static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
289 struct msgb *msg, unsigned int length)
290{
291 struct msgb *resp;
Neels Hofmeyra369e242017-02-23 21:57:23 +0100292 struct bsc_msc_data *msc;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100293 struct tlv_parsed tp;
294 uint8_t *data;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100295 uint8_t timeslot;
296 uint8_t multiplex;
297 enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
298 int i, supported, port, full_rate = -1;
299
300 if (!conn->conn) {
301 LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
302 return -1;
303 }
304
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100305 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
306
307 if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200308 LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n");
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100309 goto reject;
310 }
311
312 if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
313 LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n");
314 goto reject;
315 }
316
Max4c6e6672014-10-22 16:21:20 +0200317 conn->cic = osmo_load16be(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
Holger Hans Peter Freyther93dfa242014-08-08 21:06:30 +0200318 timeslot = conn->cic & 0x1f;
319 multiplex = (conn->cic & ~0x1f) >> 5;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100320
321 /*
322 * Currently we only support a limited subset of all
323 * possible channel types. The limitation ends by not using
324 * multi-slot, limiting the channel coding, speech...
325 */
326 if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) {
327 LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n",
328 TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE));
329 goto reject;
330 }
331
332 /*
333 * Try to figure out if we support the proposed speech codecs. For
334 * now we will always pick the full rate codecs.
335 */
336
337 data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
338 if ((data[0] & 0xf) != 0x1) {
339 LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]);
340 goto reject;
341 }
342
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100343 /*
344 * go through the list of preferred codecs of our gsm network
345 * and try to find it among the permitted codecs. If we found
346 * it we will send chan_mode to the right mode and break the
347 * inner loop. The outer loop will exit due chan_mode having
348 * the correct value.
349 */
350 full_rate = 0;
Holger Hans Peter Freytherf936fb42011-06-04 15:12:57 +0200351 msc = conn->msc;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100352 for (supported = 0;
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200353 chan_mode == GSM48_CMODE_SIGN && supported < msc->audio_length;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100354 ++supported) {
355
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200356 int perm_val = audio_support_to_gsm88(msc->audio_support[supported]);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100357 for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) {
358 if ((data[i] & 0x7f) == perm_val) {
359 chan_mode = gsm88_to_chan_mode(perm_val);
360 full_rate = (data[i] & 0x4) == 0;
361 break;
362 } else if ((data[i] & 0x80) == 0x00) {
363 break;
364 }
365 }
366 }
367
368 if (chan_mode == GSM48_CMODE_SIGN) {
369 LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
370 goto reject;
371 }
372
373 /* map it to a MGCP Endpoint and a RTP port */
374 port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200375 conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100376
377 return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
378
379reject:
380 resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
381 if (!resp) {
382 LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
383 return -1;
384 }
385
386 bsc_queue_for_msc(conn, resp);
387 return -1;
388}
389
Neels Hofmeyra369e242017-02-23 21:57:23 +0100390static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100391 struct msgb *msg, unsigned int length)
392{
393 int ret = 0;
394
395 if (length < 1) {
396 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
397 return -1;
398 }
399
Harald Weltecccd3012011-07-11 18:18:35 +0200400 LOGP(DMSC, LOGL_INFO, "Rx MSC UDT BSSMAP %s\n",
401 gsm0808_bssmap_name(msg->l4h[0]));
402
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100403 switch (msg->l4h[0]) {
404 case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200405 ret = bssmap_handle_reset_ack(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100406 break;
407 case BSS_MAP_MSG_PAGING:
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +0100408 ret = bssmap_handle_paging(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100409 break;
410 }
411
412 return ret;
413}
414
415static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
416 struct msgb *msg, unsigned int length)
417{
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100418 int ret = 0;
419
420 if (length < 1) {
421 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
422 return -1;
423 }
424
Harald Weltecccd3012011-07-11 18:18:35 +0200425 LOGP(DMSC, LOGL_INFO, "Rx MSC DT1 BSSMAP %s\n",
426 gsm0808_bssmap_name(msg->l4h[0]));
427
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100428 switch (msg->l4h[0]) {
429 case BSS_MAP_MSG_CLEAR_CMD:
430 ret = bssmap_handle_clear_command(conn, msg, length);
431 break;
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100432 case BSS_MAP_MSG_CIPHER_MODE_CMD:
433 ret = bssmap_handle_cipher_mode(conn, msg, length);
434 break;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100435 case BSS_MAP_MSG_ASSIGMENT_RQST:
436 ret = bssmap_handle_assignm_req(conn, msg, length);
437 break;
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100438 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200439 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
440 gsm0808_bssmap_name(msg->l4h[0]));
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100441 break;
442 }
443
444 return ret;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100445}
446
447static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
448 struct msgb *msg, unsigned int length)
449{
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100450 struct dtap_header *header;
451 struct msgb *gsm48;
452 uint8_t *data;
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100453 int rc, dtap_rc;
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100454
Harald Weltecccd3012011-07-11 18:18:35 +0200455 LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n",
456 osmo_hexdump(msg->l3h, length));
457
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100458 if (!conn->conn) {
459 LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
460 return -1;
461 }
462
463 header = (struct dtap_header *) msg->l3h;
464 if (sizeof(*header) >= length) {
Holger Hans Peter Freyther2f2be572012-03-16 12:18:39 +0100465 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 +0200466 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100467 return -1;
468 }
469
470 if (header->length > length - sizeof(*header)) {
471 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 +0200472 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100473 return -1;
474 }
475
Harald Weltecccd3012011-07-11 18:18:35 +0200476 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 +0100477
478 /* forward the data */
Holger Hans Peter Freyther8239e062016-01-25 22:03:25 +0100479 gsm48 = gsm48_msgb_alloc_name("GSM 04.08 DTAP RCV");
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100480 if (!gsm48) {
481 LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
482 return -1;
483 }
484
485 gsm48->l3h = gsm48->data;
486 data = msgb_put(gsm48, length - sizeof(*header));
487 memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
488
489 /* pass it to the filter for extra actions */
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100490 rc = bsc_scan_msc_msg(conn->conn, gsm48);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100491 dtap_rc = gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100492 if (rc == BSS_SEND_USSD)
493 bsc_send_welcome_ussd(conn->conn);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100494 return dtap_rc;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100495}
496
Neels Hofmeyra369e242017-02-23 21:57:23 +0100497int bsc_handle_udt(struct bsc_msc_data *msc,
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100498 struct msgb *msgb, unsigned int length)
499{
500 struct bssmap_header *bs;
501
Harald Weltecccd3012011-07-11 18:18:35 +0200502 LOGP(DMSC, LOGL_DEBUG, "Rx MSC UDT: %s\n",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200503 osmo_hexdump(msgb->l3h, length));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100504
505 if (length < sizeof(*bs)) {
506 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
507 return -1;
508 }
509
510 bs = (struct bssmap_header *) msgb->l3h;
511 if (bs->length < length - sizeof(*bs))
512 return -1;
513
514 switch (bs->type) {
515 case BSSAP_MSG_BSS_MANAGEMENT:
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100516 msgb->l4h = &msgb->l3h[sizeof(*bs)];
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200517 bssmap_rcvmsg_udt(msc, msgb, length - sizeof(*bs));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100518 break;
519 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200520 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
521 gsm0808_bssmap_name(bs->type));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100522 }
523
524 return 0;
525}
526
527int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn,
528 struct msgb *msg, unsigned int len)
529{
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100530 if (len < sizeof(struct bssmap_header)) {
531 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
532 }
533
534 switch (msg->l3h[0]) {
535 case BSSAP_MSG_BSS_MANAGEMENT:
536 msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
537 bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
538 break;
539 case BSSAP_MSG_DTAP:
540 dtap_rcvmsg(conn, msg, len);
541 break;
542 default:
Harald Weltecccd3012011-07-11 18:18:35 +0200543 LOGP(DMSC, LOGL_NOTICE, "Unimplemented BSSAP msg type: %s\n",
544 gsm0808_bssap_name(msg->l3h[0]));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100545 }
546
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100547 return -1;
548}