blob: 2d2507ede28e17bbf762c36c912e7675f4c42df2 [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>
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010023#include <openbsc/osmo_msc_data.h>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010024#include <openbsc/debug.h>
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +010025#include <openbsc/gsm_subscriber.h>
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010026#include <openbsc/mgcp.h>
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +010027#include <openbsc/paging.h>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010028
Harald Welted36ff762011-03-23 18:26:56 +010029#include <osmocom/gsm/protocol/gsm_08_08.h>
30#include <osmocom/gsm/gsm0808.h>
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +010031
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +010032/*
33 * helpers for the assignment command
34 */
35enum gsm0808_permitted_speech audio_support_to_gsm88(struct gsm_audio_support *audio)
36{
37 if (audio->hr) {
38 switch (audio->ver) {
39 case 1:
40 return GSM0808_PERM_HR1;
41 break;
42 case 2:
43 return GSM0808_PERM_HR2;
44 break;
45 case 3:
46 return GSM0808_PERM_HR3;
47 break;
48 default:
49 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
50 return GSM0808_PERM_FR1;
51 }
52 } else {
53 switch (audio->ver) {
54 case 1:
55 return GSM0808_PERM_FR1;
56 break;
57 case 2:
58 return GSM0808_PERM_FR2;
59 break;
60 case 3:
61 return GSM0808_PERM_FR3;
62 break;
63 default:
64 LOGP(DMSC, LOGL_ERROR, "Wrong speech mode: %d\n", audio->ver);
65 return GSM0808_PERM_HR1;
66 }
67 }
68}
69
70enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
71{
72 switch (speech) {
73 case GSM0808_PERM_HR1:
74 case GSM0808_PERM_FR1:
75 return GSM48_CMODE_SPEECH_V1;
76 break;
77 case GSM0808_PERM_HR2:
78 case GSM0808_PERM_FR2:
79 return GSM48_CMODE_SPEECH_EFR;
80 break;
81 case GSM0808_PERM_HR3:
82 case GSM0808_PERM_FR3:
83 return GSM48_CMODE_SPEECH_AMR;
84 break;
85 }
86
87 LOGP(DMSC, LOGL_FATAL, "Should not be reached.\n");
88 return GSM48_CMODE_SPEECH_AMR;
89}
90
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +020091static int bssmap_handle_reset_ack(struct osmo_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +010092 struct msgb *msg, unsigned int length)
93{
94 LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
95 return 0;
96}
97
98/* GSM 08.08 ยง 3.2.1.19 */
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +020099static int bssmap_handle_paging(struct osmo_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100100 struct msgb *msg, unsigned int payload_length)
101{
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100102 struct gsm_subscriber *subscr;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100103 struct tlv_parsed tp;
104 char mi_string[GSM48_MI_SIZE];
105 uint32_t tmsi = GSM_RESERVED_TMSI;
106 unsigned int lac = GSM_LAC_RESERVED_ALL_BTS;
107 uint8_t data_length;
108 const uint8_t *data;
109 uint8_t chan_needed = RSL_CHANNEED_ANY;
110
111 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
112
113 if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200114 LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100115 return -1;
116 } else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) {
117 LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n");
118 return -1;
119 }
120
121 if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200122 LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n");
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100123 return -1;
124 }
125
Harald Welted55cef92012-01-20 17:20:51 +0100126 if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) &&
127 TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) {
Daniel Willmann8a485f02014-06-27 17:05:47 +0200128 tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100129 }
130
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100131 /*
132 * parse the IMSI
133 */
134 gsm48_mi_to_string(mi_string, sizeof(mi_string),
135 TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI));
136
137 /*
138 * parse the cell identifier list
139 */
140 data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
141 data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
142
143 /*
144 * Support paging to all network or one BTS at one LAC
145 */
146 if (data_length == 3 && data[0] == CELL_IDENT_LAC) {
Max4c6e6672014-10-22 16:21:20 +0200147 lac = osmo_load16be(&data[1]);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100148 } else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) {
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200149 LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100150 return -1;
151 }
152
153 if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1)
154 chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03;
155
156 if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) {
157 LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
158 }
159
Jacob Erlbeck1e30a282014-12-03 09:28:24 +0100160 subscr = subscr_get_or_create(msc->network->subscr_group, mi_string);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100161 if (!subscr) {
162 LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
163 return -1;
164 }
165
166 subscr->lac = lac;
167 subscr->tmsi = tmsi;
168
Harald Weltecccd3012011-07-11 18:18:35 +0200169 LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac);
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +0100170 bsc_grace_paging_request(subscr, chan_needed, msc);
Holger Hans Peter Freyther9c838ae2010-11-15 09:16:09 +0100171 return 0;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100172}
173
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100174/*
175 * GSM 08.08 ยง 3.1.9.1 and 3.2.1.21...
176 * release our gsm_subscriber_connection and send message
177 */
178static int bssmap_handle_clear_command(struct osmo_bsc_sccp_con *conn,
179 struct msgb *msg, unsigned int payload_length)
180{
181 struct msgb *resp;
182
183 /* TODO: handle the cause of this package */
184
185 if (conn->conn) {
Harald Weltecccd3012011-07-11 18:18:35 +0200186 LOGP(DMSC, LOGL_INFO, "Releasing all transactions on %p\n", conn);
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100187 gsm0808_clear(conn->conn);
188 subscr_con_free(conn->conn);
189 conn->conn = NULL;
190 }
191
192 /* send the clear complete message */
193 resp = gsm0808_create_clear_complete();
194 if (!resp) {
195 LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
196 return -1;
197 }
198
199 bsc_queue_for_msc(conn, resp);
200 return 0;
201}
202
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100203/*
204 * GSM 08.08 ยง 3.4.7 cipher mode handling. We will have to pick
205 * the cipher to be used for this. In case we are already using
206 * a cipher we will have to send cipher mode reject to the MSC,
207 * otherwise we will have to pick something that we and the MS
208 * is supporting. Currently we are doing it in a rather static
209 * way by picking one ecnryption or no encrytpion.
210 */
211static int bssmap_handle_cipher_mode(struct osmo_bsc_sccp_con *conn,
212 struct msgb *msg, unsigned int payload_length)
213{
214 uint16_t len;
215 struct gsm_network *network = NULL;
216 const uint8_t *data;
217 struct tlv_parsed tp;
218 struct msgb *resp;
219 int reject_cause = -1;
220 int include_imeisv = 1;
221
222 if (!conn->conn) {
223 LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
224 goto reject;
225 }
226
227 if (conn->ciphering_handled) {
228 LOGP(DMSC, LOGL_ERROR, "Already seen ciphering command. Protocol Error.\n");
229 goto reject;
230 }
231
232 conn->ciphering_handled = 1;
233
234 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
235 if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
236 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
237 goto reject;
238 }
239
240 /*
241 * check if our global setting is allowed
242 * - Currently we check for A5/0 and A5/1
243 * - Copy the key if that is necessary
244 * - Otherwise reject
245 */
246 len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
247 if (len < 1) {
248 LOGP(DMSC, LOGL_ERROR, "IE Encryption Information is too short.\n");
249 goto reject;
250 }
251
252 network = conn->conn->bts->network;
253 data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION);
254
255 if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
256 include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
257
258 if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) {
259 gsm0808_cipher_mode(conn->conn, 0, NULL, 0, include_imeisv);
260 } else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) {
261 gsm0808_cipher_mode(conn->conn, 1, &data[1], len - 1, include_imeisv);
262 } else {
263 LOGP(DMSC, LOGL_ERROR, "Can not select encryption...\n");
264 goto reject;
265 }
266
Harald Welte75413c42011-07-12 00:03:43 +0200267 return 0;
268
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100269reject:
270 resp = gsm0808_create_cipher_reject(reject_cause);
271 if (!resp) {
272 LOGP(DMSC, LOGL_ERROR, "Sending the cipher reject failed.\n");
273 return -1;
274 }
275
276 bsc_queue_for_msc(conn, resp);
277 return -1;
278}
279
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100280/*
281 * Handle the assignment request message.
282 *
283 * See ยง3.2.1.1 for the message type
284 */
285static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn,
286 struct msgb *msg, unsigned int length)
287{
288 struct msgb *resp;
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200289 struct osmo_msc_data *msc;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100290 struct tlv_parsed tp;
291 uint8_t *data;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100292 uint8_t timeslot;
293 uint8_t multiplex;
294 enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN;
295 int i, supported, port, full_rate = -1;
296
297 if (!conn->conn) {
298 LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
299 return -1;
300 }
301
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100302 tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
303
304 if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
Holger Hans Peter Freyther59043d82012-08-03 11:05:29 +0200305 LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n");
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100306 goto reject;
307 }
308
309 if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) {
310 LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n");
311 goto reject;
312 }
313
Max4c6e6672014-10-22 16:21:20 +0200314 conn->cic = osmo_load16be(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE));
Holger Hans Peter Freyther93dfa242014-08-08 21:06:30 +0200315 timeslot = conn->cic & 0x1f;
316 multiplex = (conn->cic & ~0x1f) >> 5;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100317
318 /*
319 * Currently we only support a limited subset of all
320 * possible channel types. The limitation ends by not using
321 * multi-slot, limiting the channel coding, speech...
322 */
323 if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) {
324 LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n",
325 TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE));
326 goto reject;
327 }
328
329 /*
330 * Try to figure out if we support the proposed speech codecs. For
331 * now we will always pick the full rate codecs.
332 */
333
334 data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE);
335 if ((data[0] & 0xf) != 0x1) {
336 LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]);
337 goto reject;
338 }
339
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100340 /*
341 * go through the list of preferred codecs of our gsm network
342 * and try to find it among the permitted codecs. If we found
343 * it we will send chan_mode to the right mode and break the
344 * inner loop. The outer loop will exit due chan_mode having
345 * the correct value.
346 */
347 full_rate = 0;
Holger Hans Peter Freytherf936fb42011-06-04 15:12:57 +0200348 msc = conn->msc;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100349 for (supported = 0;
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200350 chan_mode == GSM48_CMODE_SIGN && supported < msc->audio_length;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100351 ++supported) {
352
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200353 int perm_val = audio_support_to_gsm88(msc->audio_support[supported]);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100354 for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) {
355 if ((data[i] & 0x7f) == perm_val) {
356 chan_mode = gsm88_to_chan_mode(perm_val);
357 full_rate = (data[i] & 0x4) == 0;
358 break;
359 } else if ((data[i] & 0x80) == 0x00) {
360 break;
361 }
362 }
363 }
364
365 if (chan_mode == GSM48_CMODE_SIGN) {
366 LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n");
367 goto reject;
368 }
369
370 /* map it to a MGCP Endpoint and a RTP port */
371 port = mgcp_timeslot_to_endpoint(multiplex, timeslot);
Holger Hans Peter Freyther8ec49522011-08-15 15:53:00 +0200372 conn->rtp_port = rtp_calculate_port(port, msc->rtp_base);
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100373
374 return gsm0808_assign_req(conn->conn, chan_mode, full_rate);
375
376reject:
377 resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
378 if (!resp) {
379 LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n");
380 return -1;
381 }
382
383 bsc_queue_for_msc(conn, resp);
384 return -1;
385}
386
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200387static int bssmap_rcvmsg_udt(struct osmo_msc_data *msc,
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100388 struct msgb *msg, unsigned int length)
389{
390 int ret = 0;
391
392 if (length < 1) {
393 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
394 return -1;
395 }
396
Harald Weltecccd3012011-07-11 18:18:35 +0200397 LOGP(DMSC, LOGL_INFO, "Rx MSC UDT BSSMAP %s\n",
398 gsm0808_bssmap_name(msg->l4h[0]));
399
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100400 switch (msg->l4h[0]) {
401 case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200402 ret = bssmap_handle_reset_ack(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100403 break;
404 case BSS_MAP_MSG_PAGING:
Holger Hans Peter Freytherdc030962013-01-07 17:30:13 +0100405 ret = bssmap_handle_paging(msc, msg, length);
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100406 break;
407 }
408
409 return ret;
410}
411
412static int bssmap_rcvmsg_dt1(struct osmo_bsc_sccp_con *conn,
413 struct msgb *msg, unsigned int length)
414{
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100415 int ret = 0;
416
417 if (length < 1) {
418 LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length);
419 return -1;
420 }
421
Harald Weltecccd3012011-07-11 18:18:35 +0200422 LOGP(DMSC, LOGL_INFO, "Rx MSC DT1 BSSMAP %s\n",
423 gsm0808_bssmap_name(msg->l4h[0]));
424
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100425 switch (msg->l4h[0]) {
426 case BSS_MAP_MSG_CLEAR_CMD:
427 ret = bssmap_handle_clear_command(conn, msg, length);
428 break;
Holger Hans Peter Freytherfae3c652010-11-10 09:44:34 +0100429 case BSS_MAP_MSG_CIPHER_MODE_CMD:
430 ret = bssmap_handle_cipher_mode(conn, msg, length);
431 break;
Holger Hans Peter Freyther50c579b2010-11-10 10:07:30 +0100432 case BSS_MAP_MSG_ASSIGMENT_RQST:
433 ret = bssmap_handle_assignm_req(conn, msg, length);
434 break;
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100435 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200436 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
437 gsm0808_bssmap_name(msg->l4h[0]));
Holger Hans Peter Freytherf1f57a82010-11-10 09:34:47 +0100438 break;
439 }
440
441 return ret;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100442}
443
444static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
445 struct msgb *msg, unsigned int length)
446{
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100447 struct dtap_header *header;
448 struct msgb *gsm48;
449 uint8_t *data;
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100450 int rc, dtap_rc;
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100451
Harald Weltecccd3012011-07-11 18:18:35 +0200452 LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n",
453 osmo_hexdump(msg->l3h, length));
454
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100455 if (!conn->conn) {
456 LOGP(DMSC, LOGL_ERROR, "No subscriber connection available\n");
457 return -1;
458 }
459
460 header = (struct dtap_header *) msg->l3h;
461 if (sizeof(*header) >= length) {
Holger Hans Peter Freyther2f2be572012-03-16 12:18:39 +0100462 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 +0200463 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100464 return -1;
465 }
466
467 if (header->length > length - sizeof(*header)) {
468 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 +0200469 LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length));
Holger Hans Peter Freytherdbc698a2010-11-10 10:17:05 +0100470 return -1;
471 }
472
Harald Weltecccd3012011-07-11 18:18:35 +0200473 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 +0100474
475 /* forward the data */
476 gsm48 = gsm48_msgb_alloc();
477 if (!gsm48) {
478 LOGP(DMSC, LOGL_ERROR, "Allocation of the message failed.\n");
479 return -1;
480 }
481
482 gsm48->l3h = gsm48->data;
483 data = msgb_put(gsm48, length - sizeof(*header));
484 memcpy(data, msg->l3h + sizeof(*header), length - sizeof(*header));
485
486 /* pass it to the filter for extra actions */
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100487 rc = bsc_scan_msc_msg(conn->conn, gsm48);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100488 dtap_rc = gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
Holger Hans Peter Freytherd2361d92012-12-03 15:32:54 +0100489 if (rc == BSS_SEND_USSD)
490 bsc_send_welcome_ussd(conn->conn);
Holger Hans Peter Freyther3d4d79d2012-12-03 15:32:54 +0100491 return dtap_rc;
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100492}
493
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200494int bsc_handle_udt(struct osmo_msc_data *msc,
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100495 struct msgb *msgb, unsigned int length)
496{
497 struct bssmap_header *bs;
498
Harald Weltecccd3012011-07-11 18:18:35 +0200499 LOGP(DMSC, LOGL_DEBUG, "Rx MSC UDT: %s\n",
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200500 osmo_hexdump(msgb->l3h, length));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100501
502 if (length < sizeof(*bs)) {
503 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
504 return -1;
505 }
506
507 bs = (struct bssmap_header *) msgb->l3h;
508 if (bs->length < length - sizeof(*bs))
509 return -1;
510
511 switch (bs->type) {
512 case BSSAP_MSG_BSS_MANAGEMENT:
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100513 msgb->l4h = &msgb->l3h[sizeof(*bs)];
Holger Hans Peter Freyther644b0bf2011-06-08 15:52:07 +0200514 bssmap_rcvmsg_udt(msc, msgb, length - sizeof(*bs));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100515 break;
516 default:
Harald Welte9f32a8a2011-07-11 17:56:34 +0200517 LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
518 gsm0808_bssmap_name(bs->type));
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100519 }
520
521 return 0;
522}
523
524int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn,
525 struct msgb *msg, unsigned int len)
526{
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100527 if (len < sizeof(struct bssmap_header)) {
528 LOGP(DMSC, LOGL_ERROR, "The header is too short.\n");
529 }
530
531 switch (msg->l3h[0]) {
532 case BSSAP_MSG_BSS_MANAGEMENT:
533 msg->l4h = &msg->l3h[sizeof(struct bssmap_header)];
534 bssmap_rcvmsg_dt1(conn, msg, len - sizeof(struct bssmap_header));
535 break;
536 case BSSAP_MSG_DTAP:
537 dtap_rcvmsg(conn, msg, len);
538 break;
539 default:
Harald Weltecccd3012011-07-11 18:18:35 +0200540 LOGP(DMSC, LOGL_NOTICE, "Unimplemented BSSAP msg type: %s\n",
541 gsm0808_bssap_name(msg->l3h[0]));
Holger Hans Peter Freyther890dfc52010-11-10 09:24:37 +0100542 }
543
Holger Hans Peter Freyther3485feb2010-11-09 23:28:33 +0100544 return -1;
545}