blob: 6c6371ca00a89de7d08ea7a4c29550e262e660a6 [file] [log] [blame]
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001/* GPRS Gb message parser */
2
3/* (C) 2014 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * 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
9 * (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
14 * GNU Affero General Public License for more details.
15 *
16 * 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/>.
18 *
19 */
20
Harald Welte6e688082014-08-24 17:38:18 +020021#include <osmocom/gsm/gsm48.h>
22
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020023#include <openbsc/gprs_gb_parse.h>
24
25#include <openbsc/gprs_utils.h>
26
27#include <openbsc/gsm_04_08_gprs.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020028#include <openbsc/debug.h>
29
30#include <osmocom/gprs/gprs_bssgp.h>
31
32/* TODO: Move shift functions to libosmocore */
33
34int v_fixed_shift(uint8_t **data, size_t *data_len,
35 size_t len, uint8_t **value)
36{
37 if (len > *data_len)
38 goto fail;
39
40 if (value)
41 *value = *data;
42
43 *data += len;
44 *data_len -= len;
45
46 return len;
47
48fail:
49 *data += *data_len;
50 *data_len = 0;
51 return -1;
52}
53
54int tv_fixed_match(uint8_t **data, size_t *data_len,
55 uint8_t tag, size_t len,
56 uint8_t **value)
57{
58 size_t ie_len;
59
60 if (*data_len == 0)
61 goto fail;
62
63 if ((*data)[0] != tag)
64 return 0;
65
66 if (len > *data_len - 1)
67 goto fail;
68
69 if (value)
70 *value = *data + 1;
71
72 ie_len = len + 1;
73 *data += ie_len;
74 *data_len -= ie_len;
75
76 return ie_len;
77
78fail:
79 *data += *data_len;
80 *data_len = 0;
81 return -1;
82}
83
84int tlv_match(uint8_t **data, size_t *data_len,
85 uint8_t tag, uint8_t **value, size_t *value_len)
86{
87 size_t len;
88 size_t ie_len;
89
90 if (*data_len < 2)
91 goto fail;
92
93 if ((*data)[0] != tag)
94 return 0;
95
96 len = (*data)[1];
97 if (len > *data_len - 2)
98 goto fail;
99
100 if (value)
101 *value = *data + 2;
102 if (value_len)
103 *value_len = len;
104
105 ie_len = len + 2;
106
107 *data += ie_len;
108 *data_len -= ie_len;
109
110 return ie_len;
111
112fail:
113 *data += *data_len;
114 *data_len = 0;
115 return -1;
116}
117
118int lv_shift(uint8_t **data, size_t *data_len,
119 uint8_t **value, size_t *value_len)
120{
121 size_t len;
122 size_t ie_len;
123
124 if (*data_len < 1)
125 goto fail;
126
127 len = (*data)[0];
128 if (len > *data_len - 1)
129 goto fail;
130
131 if (value)
132 *value = *data + 1;
133 if (value_len)
134 *value_len = len;
135
136 ie_len = len + 1;
137 *data += ie_len;
138 *data_len -= ie_len;
139
140 return ie_len;
141
142fail:
143 *data += *data_len;
144 *data_len = 0;
145 return -1;
146}
147
148static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
149 struct gprs_gb_parse_context *parse_ctx)
150{
151 uint8_t *value;
152 size_t value_len;
153
154 parse_ctx->llc_msg_name = "ATTACH_REQ";
155
156 /* Skip MS network capability */
157 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeckc9cd15f2014-09-29 12:36:45 +0200158 value_len < 1 || value_len > 8)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200159 /* invalid */
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200160 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200161
162 /* Skip Attach type */
163 /* Skip Ciphering key sequence number */
164 /* Skip DRX parameter */
165 v_fixed_shift(&data, &data_len, 3, NULL);
166
167 /* Get Mobile identity */
168 if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
169 value_len < 5 || value_len > 8)
170 /* invalid */
171 return 0;
172
173 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +0200174 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200175 } else if (gprs_is_mi_imsi(value, value_len)) {
176 parse_ctx->imsi = value;
177 parse_ctx->imsi_len = value_len;
178 }
179
180 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
181 return 0;
182
183 parse_ctx->old_raid_enc = value;
184
185 return 1;
186}
187
188static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
189 struct gprs_gb_parse_context *parse_ctx)
190{
191 uint8_t *value;
192 size_t value_len;
193
194 parse_ctx->llc_msg_name = "ATTACH_ACK";
195
196 /* Skip Attach result */
197 /* Skip Force to standby */
198 /* Skip Periodic RA update timer */
199 /* Skip Radio priority for SMS */
200 /* Skip Spare half octet */
201 v_fixed_shift(&data, &data_len, 3, NULL);
202
203 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
204 return 0;
205
206 parse_ctx->raid_enc = value;
207
208 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
209 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
210
211 /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
212 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
213
214 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
215 if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
216 &value, &value_len) > 0 &&
217 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200218 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200219 return 1;
220}
221
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200222static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len,
223 struct gprs_gb_parse_context *parse_ctx)
224{
225 uint8_t *value;
226
227 parse_ctx->llc_msg_name = "ATTACH_REJ";
228
229 /* GMM cause */
230 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
231 return 0;
232
233 parse_ctx->invalidate_tlli = 1;
234
235 return 1;
236}
237
238
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200239static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
240 struct gprs_gb_parse_context *parse_ctx)
241{
242 uint8_t *value;
243 size_t value_len;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200244 int detach_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200245 int power_off;
246
247 parse_ctx->llc_msg_name = "DETACH_REQ";
248
249 /* Skip spare half octet */
250 /* Get Detach type */
251 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
252 /* invalid */
253 return 0;
254
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200255 detach_type = *value & 0x07;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200256 power_off = *value & 0x08 ? 1 : 0;
257
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200258 if (parse_ctx->to_bss) {
259 /* Network originated */
260 if (detach_type == GPRS_DET_T_MT_REATT_REQ)
261 parse_ctx->await_reattach = 1;
262 } else {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200263 /* Mobile originated */
264
265 if (power_off)
266 parse_ctx->invalidate_tlli = 1;
267
268 /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
269 if (tlv_match(&data, &data_len,
270 GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
271 {
272 if (gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200273 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200274 }
275 }
276
277 return 1;
278}
279
280static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
281 struct gprs_gb_parse_context *parse_ctx)
282{
283 uint8_t *value;
284
285 parse_ctx->llc_msg_name = "RA_UPD_REQ";
286
287 /* Skip Update type */
288 /* Skip GPRS ciphering key sequence number */
289 v_fixed_shift(&data, &data_len, 1, NULL);
290
291 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
292 return 0;
293
294 parse_ctx->old_raid_enc = value;
295
296 return 1;
297}
298
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200299static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len,
300 struct gprs_gb_parse_context *parse_ctx)
301{
302 uint8_t *value;
303 uint8_t cause;
304 int force_standby;
305
306 parse_ctx->llc_msg_name = "RA_UPD_REJ";
307
308 /* GMM cause */
309 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
310 return 0;
311
312 cause = value[0];
313
314 /* Force to standby, 1/2 */
315 /* spare bits, 1/2 */
316 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
317 return 0;
318
319 force_standby = (value[0] & 0x07) == 0x01;
320
321 if (cause == GMM_CAUSE_IMPL_DETACHED && !force_standby)
322 parse_ctx->await_reattach = 1;
323
324 parse_ctx->invalidate_tlli = 1;
325
326 return 1;
327}
328
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200329static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
330 struct gprs_gb_parse_context *parse_ctx)
331{
332 uint8_t *value;
333 size_t value_len;
334
335 parse_ctx->llc_msg_name = "RA_UPD_ACK";
336
337 /* Skip Force to standby */
338 /* Skip Update result */
339 /* Skip Periodic RA update timer */
340 v_fixed_shift(&data, &data_len, 2, NULL);
341
342 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
343 return 0;
344
345 parse_ctx->raid_enc = value;
346
347 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
348 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
349
350 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
351 if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
352 &value, &value_len) > 0 &&
353 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200354 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200355
356 return 1;
357}
358
359static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
360 struct gprs_gb_parse_context *parse_ctx)
361{
362 uint8_t *value;
363 size_t value_len;
364
365 parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
366
367 LOGP(DLLC, LOGL_NOTICE,
368 "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
369
370 /* Allocated P-TMSI */
371 if (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
372 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200373 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200374
375 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
376 return 0;
377
378 parse_ctx->raid_enc = value;
379
380 return 1;
381}
382
383static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
384 struct gprs_gb_parse_context *parse_ctx)
385{
386 uint8_t *value;
387 size_t value_len;
388
389 parse_ctx->llc_msg_name = "ID_RESP";
390
391 /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
392 if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
393 value_len < 1 || value_len > 9)
394 /* invalid */
395 return 0;
396
397 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +0200398 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200399 } else if (gprs_is_mi_imsi(value, value_len)) {
400 parse_ctx->imsi = value;
401 parse_ctx->imsi_len = value_len;
402 }
403
404 return 1;
405}
406
407static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
408 struct gprs_gb_parse_context *parse_ctx)
409{
410 ssize_t old_len;
411 uint8_t *value;
412 size_t value_len;
413
414 parse_ctx->llc_msg_name = "ACT_PDP_REQ";
415
416 /* Skip Requested NSAPI */
417 /* Skip Requested LLC SAPI */
418 v_fixed_shift(&data, &data_len, 2, NULL);
419
420 /* Skip Requested QoS (support 04.08 and 24.008) */
421 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
422 value_len < 4 || value_len > 14)
423 /* invalid */
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200424 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200425
426 /* Skip Requested PDP address */
427 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
428 value_len < 2 || value_len > 18)
429 /* invalid */
430 return 0;
431
432 /* Access point name */
433 old_len = tlv_match(&data, &data_len,
434 GSM48_IE_GSM_APN, &value, &value_len);
435
436 if (old_len > 0 && value_len >=1 && value_len <= 100) {
437 parse_ctx->apn_ie = data - old_len;
438 parse_ctx->apn_ie_len = old_len;
439 }
440
441 return 1;
442}
443
444int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
445 struct gprs_gb_parse_context *parse_ctx)
446{
447 struct gsm48_hdr *g48h;
448
449 if (v_fixed_shift(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
450 return 0;
451
452 parse_ctx->g48_hdr = g48h;
453
454 if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS &&
455 (g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS)
456 return 1;
457
458 switch (g48h->msg_type) {
459 case GSM48_MT_GMM_ATTACH_REQ:
460 return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
461
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200462 case GSM48_MT_GMM_ATTACH_REJ:
463 return gprs_gb_parse_gmm_attach_rej(data, data_len, parse_ctx);
464
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200465 case GSM48_MT_GMM_ATTACH_ACK:
466 return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
467
468 case GSM48_MT_GMM_RA_UPD_REQ:
469 return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
470
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200471 case GSM48_MT_GMM_RA_UPD_REJ:
472 return gprs_gb_parse_gmm_ra_upd_rej(data, data_len, parse_ctx);
473
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200474 case GSM48_MT_GMM_RA_UPD_ACK:
475 return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
476
477 case GSM48_MT_GMM_PTMSI_REALL_CMD:
478 return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
479
480 case GSM48_MT_GSM_ACT_PDP_REQ:
481 return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
482
483 case GSM48_MT_GMM_ID_RESP:
484 return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
485
486 case GSM48_MT_GMM_DETACH_REQ:
487 return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
488
489 case GSM48_MT_GMM_DETACH_ACK:
490 parse_ctx->llc_msg_name = "DETACH_ACK";
491 parse_ctx->invalidate_tlli = 1;
492 break;
493
494 default:
495 break;
496 };
497
498 return 1;
499}
500
501int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
502 struct gprs_gb_parse_context *parse_ctx)
503{
504 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
505 int rc;
506 int fcs;
507
508 /* parse LLC */
509 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
510 gprs_llc_hdr_dump(ghp);
511 if (rc != 0) {
512 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
513 return 0;
514 }
515
516 fcs = gprs_llc_fcs(llc, ghp->crc_length);
517 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
518 ghp->fcs, fcs);
519
520 if (!ghp->data)
521 return 0;
522
523 if (ghp->sapi != GPRS_SAPI_GMM)
524 return 1;
525
526 if (ghp->cmd != GPRS_LLC_UI)
527 return 1;
528
529 if (ghp->is_encrypted) {
530 parse_ctx->need_decryption = 1;
531 return 0;
532 }
533
534 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
535}
536
537int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
538 struct gprs_gb_parse_context *parse_ctx)
539{
540 struct bssgp_normal_hdr *bgph;
541 struct bssgp_ud_hdr *budh = NULL;
542 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
543 uint8_t pdu_type;
544 uint8_t *data;
545 size_t data_len;
546 int rc;
547
548 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
549 return 0;
550
551 bgph = (struct bssgp_normal_hdr *)bssgp;
552 pdu_type = bgph->pdu_type;
553
554 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
555 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
556 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
557 return 0;
558 budh = (struct bssgp_ud_hdr *)bssgp;
559 bgph = NULL;
560 data = budh->data;
561 data_len = bssgp_len - sizeof(*budh);
562 } else {
563 data = bgph->data;
564 data_len = bssgp_len - sizeof(*bgph);
565 }
566
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200567 parse_ctx->pdu_type = pdu_type;
568 parse_ctx->bud_hdr = budh;
569 parse_ctx->bgp_hdr = bgph;
570 parse_ctx->bssgp_data = data;
571 parse_ctx->bssgp_data_len = data_len;
572
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200573 if (bssgp_tlv_parse(tp, data, data_len) < 0)
574 return 0;
575
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200576 if (budh)
577 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
578
579 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
580 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
581
582 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
583 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
584
585 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
586 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
587 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
588 }
589
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200590 if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
591 if (parse_ctx->tlli_enc)
592 /* This is TLLI old, don't confuse it with TLLI current */
593 parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
594 else
595 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
596 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200597
598 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200599 parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200600
601 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
602 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
603 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
604
605 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
606 if (!rc)
607 return 0;
608
609 parse_ctx->llc = llc;
610 parse_ctx->llc_len = llc_len;
611 }
612
613 if (parse_ctx->tlli_enc) {
614 uint32_t tmp_tlli;
615 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
616 parse_ctx->tlli = ntohl(tmp_tlli);
617 }
618
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200619 if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
620 memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
621 parse_ctx->old_raid_is_foreign = 1;
622
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200623 return 1;
624}
625
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200626void gprs_gb_log_parse_context(int log_level,
627 struct gprs_gb_parse_context *parse_ctx,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200628 const char *default_msg_name)
629{
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200630 const char *msg_name;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200631 const char *sep = "";
632
633 if (!parse_ctx->tlli_enc &&
634 !parse_ctx->ptmsi_enc &&
635 !parse_ctx->new_ptmsi_enc &&
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200636 !parse_ctx->bssgp_ptmsi_enc &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200637 !parse_ctx->imsi)
638 return;
639
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200640 msg_name = gprs_gb_message_name(parse_ctx, default_msg_name);
641
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200642 if (parse_ctx->llc_msg_name)
643 msg_name = parse_ctx->llc_msg_name;
644
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200645 LOGP(DGPRS, log_level, "%s: Got", msg_name);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200646
647 if (parse_ctx->tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200648 LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200649 sep = ",";
650 }
651
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200652 if (parse_ctx->old_tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200653 LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep,
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200654 parse_ctx->old_tlli_enc[0],
655 parse_ctx->old_tlli_enc[1],
656 parse_ctx->old_tlli_enc[2],
657 parse_ctx->old_tlli_enc[3]);
658 sep = ",";
659 }
660
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200661 if (parse_ctx->bssgp_raid_enc) {
662 struct gprs_ra_id raid;
663 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200664 LOGPC(DGPRS, log_level, "%s BSSGP RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200665 raid.mcc, raid.mnc, raid.lac, raid.rac);
666 sep = ",";
667 }
668
669 if (parse_ctx->raid_enc) {
670 struct gprs_ra_id raid;
671 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200672 LOGPC(DGPRS, log_level, "%s RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200673 raid.mcc, raid.mnc, raid.lac, raid.rac);
674 sep = ",";
675 }
676
677 if (parse_ctx->old_raid_enc) {
678 struct gprs_ra_id raid;
679 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200680 LOGPC(DGPRS, log_level, "%s old RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200681 raid.mcc, raid.mnc, raid.lac, raid.rac);
682 sep = ",";
683 }
684
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200685 if (parse_ctx->bssgp_ptmsi_enc) {
686 uint32_t ptmsi = GSM_RESERVED_TMSI;
687 gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
688 LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
689 sep = ",";
690 }
691
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200692 if (parse_ctx->ptmsi_enc) {
693 uint32_t ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200694 gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200695 LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200696 sep = ",";
697 }
698
699 if (parse_ctx->new_ptmsi_enc) {
700 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200701 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200702 LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200703 sep = ",";
704 }
705
706 if (parse_ctx->imsi) {
707 char mi_buf[200];
708 mi_buf[0] = '\0';
709 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
710 parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200711 LOGPC(DGPRS, log_level, "%s IMSI %s",
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200712 sep, mi_buf);
713 sep = ",";
714 }
715 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200716 LOGPC(DGPRS, log_level, "%s invalidate", sep);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200717 sep = ",";
718 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200719 if (parse_ctx->await_reattach) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200720 LOGPC(DGPRS, log_level, "%s re-attach", sep);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200721 sep = ",";
722 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200723
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200724 LOGPC(DGPRS, log_level, "\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200725}
726
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200727const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
728 const char *default_msg_name)
729{
730 if (parse_ctx->llc_msg_name)
731 return parse_ctx->llc_msg_name;
732
733 if (parse_ctx->g48_hdr)
734 return "GMM";
735
736 if (parse_ctx->llc)
737 return "LLC";
738
739 if (parse_ctx->bud_hdr)
740 return "BSSGP-UNITDATA";
741
742 if (parse_ctx->bgp_hdr)
743 return "BSSGP";
744
745 return "unknown";
746}