blob: 7ae792a628be4c36c1ff772f2d662b9c719d2dd7 [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 ||
158 value_len < 1 || value_len > 2)
159 /* invalid */
160 return 0;;
161
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)) {
174 parse_ctx->ptmsi_enc = value;
175 } 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))
218 parse_ctx->new_ptmsi_enc = value;
219 return 1;
220}
221
222static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
223 struct gprs_gb_parse_context *parse_ctx)
224{
225 uint8_t *value;
226 size_t value_len;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200227 int detach_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200228 int power_off;
229
230 parse_ctx->llc_msg_name = "DETACH_REQ";
231
232 /* Skip spare half octet */
233 /* Get Detach type */
234 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
235 /* invalid */
236 return 0;
237
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200238 detach_type = *value & 0x07;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200239 power_off = *value & 0x08 ? 1 : 0;
240
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200241 if (parse_ctx->to_bss) {
242 /* Network originated */
243 if (detach_type == GPRS_DET_T_MT_REATT_REQ)
244 parse_ctx->await_reattach = 1;
245 } else {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200246 /* Mobile originated */
247
248 if (power_off)
249 parse_ctx->invalidate_tlli = 1;
250
251 /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
252 if (tlv_match(&data, &data_len,
253 GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
254 {
255 if (gprs_is_mi_tmsi(value, value_len))
256 parse_ctx->ptmsi_enc = value;
257 }
258 }
259
260 return 1;
261}
262
263static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
264 struct gprs_gb_parse_context *parse_ctx)
265{
266 uint8_t *value;
267
268 parse_ctx->llc_msg_name = "RA_UPD_REQ";
269
270 /* Skip Update type */
271 /* Skip GPRS ciphering key sequence number */
272 v_fixed_shift(&data, &data_len, 1, NULL);
273
274 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
275 return 0;
276
277 parse_ctx->old_raid_enc = value;
278
279 return 1;
280}
281
282static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
283 struct gprs_gb_parse_context *parse_ctx)
284{
285 uint8_t *value;
286 size_t value_len;
287
288 parse_ctx->llc_msg_name = "RA_UPD_ACK";
289
290 /* Skip Force to standby */
291 /* Skip Update result */
292 /* Skip Periodic RA update timer */
293 v_fixed_shift(&data, &data_len, 2, NULL);
294
295 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
296 return 0;
297
298 parse_ctx->raid_enc = value;
299
300 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
301 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
302
303 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
304 if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
305 &value, &value_len) > 0 &&
306 gprs_is_mi_tmsi(value, value_len))
307 parse_ctx->new_ptmsi_enc = value;
308
309 return 1;
310}
311
312static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
313 struct gprs_gb_parse_context *parse_ctx)
314{
315 uint8_t *value;
316 size_t value_len;
317
318 parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
319
320 LOGP(DLLC, LOGL_NOTICE,
321 "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
322
323 /* Allocated P-TMSI */
324 if (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
325 gprs_is_mi_tmsi(value, value_len))
326 parse_ctx->new_ptmsi_enc = value;
327
328 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
329 return 0;
330
331 parse_ctx->raid_enc = value;
332
333 return 1;
334}
335
336static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
337 struct gprs_gb_parse_context *parse_ctx)
338{
339 uint8_t *value;
340 size_t value_len;
341
342 parse_ctx->llc_msg_name = "ID_RESP";
343
344 /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
345 if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
346 value_len < 1 || value_len > 9)
347 /* invalid */
348 return 0;
349
350 if (gprs_is_mi_tmsi(value, value_len)) {
351 parse_ctx->ptmsi_enc = value;
352 } else if (gprs_is_mi_imsi(value, value_len)) {
353 parse_ctx->imsi = value;
354 parse_ctx->imsi_len = value_len;
355 }
356
357 return 1;
358}
359
360static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
361 struct gprs_gb_parse_context *parse_ctx)
362{
363 ssize_t old_len;
364 uint8_t *value;
365 size_t value_len;
366
367 parse_ctx->llc_msg_name = "ACT_PDP_REQ";
368
369 /* Skip Requested NSAPI */
370 /* Skip Requested LLC SAPI */
371 v_fixed_shift(&data, &data_len, 2, NULL);
372
373 /* Skip Requested QoS (support 04.08 and 24.008) */
374 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
375 value_len < 4 || value_len > 14)
376 /* invalid */
377 return 0;;
378
379 /* Skip Requested PDP address */
380 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
381 value_len < 2 || value_len > 18)
382 /* invalid */
383 return 0;
384
385 /* Access point name */
386 old_len = tlv_match(&data, &data_len,
387 GSM48_IE_GSM_APN, &value, &value_len);
388
389 if (old_len > 0 && value_len >=1 && value_len <= 100) {
390 parse_ctx->apn_ie = data - old_len;
391 parse_ctx->apn_ie_len = old_len;
392 }
393
394 return 1;
395}
396
397int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
398 struct gprs_gb_parse_context *parse_ctx)
399{
400 struct gsm48_hdr *g48h;
401
402 if (v_fixed_shift(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
403 return 0;
404
405 parse_ctx->g48_hdr = g48h;
406
407 if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS &&
408 (g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS)
409 return 1;
410
411 switch (g48h->msg_type) {
412 case GSM48_MT_GMM_ATTACH_REQ:
413 return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
414
415 case GSM48_MT_GMM_ATTACH_ACK:
416 return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
417
418 case GSM48_MT_GMM_RA_UPD_REQ:
419 return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
420
421 case GSM48_MT_GMM_RA_UPD_ACK:
422 return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
423
424 case GSM48_MT_GMM_PTMSI_REALL_CMD:
425 return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
426
427 case GSM48_MT_GSM_ACT_PDP_REQ:
428 return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
429
430 case GSM48_MT_GMM_ID_RESP:
431 return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
432
433 case GSM48_MT_GMM_DETACH_REQ:
434 return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
435
436 case GSM48_MT_GMM_DETACH_ACK:
437 parse_ctx->llc_msg_name = "DETACH_ACK";
438 parse_ctx->invalidate_tlli = 1;
439 break;
440
441 default:
442 break;
443 };
444
445 return 1;
446}
447
448int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
449 struct gprs_gb_parse_context *parse_ctx)
450{
451 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
452 int rc;
453 int fcs;
454
455 /* parse LLC */
456 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
457 gprs_llc_hdr_dump(ghp);
458 if (rc != 0) {
459 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
460 return 0;
461 }
462
463 fcs = gprs_llc_fcs(llc, ghp->crc_length);
464 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
465 ghp->fcs, fcs);
466
467 if (!ghp->data)
468 return 0;
469
470 if (ghp->sapi != GPRS_SAPI_GMM)
471 return 1;
472
473 if (ghp->cmd != GPRS_LLC_UI)
474 return 1;
475
476 if (ghp->is_encrypted) {
477 parse_ctx->need_decryption = 1;
478 return 0;
479 }
480
481 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
482}
483
484int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
485 struct gprs_gb_parse_context *parse_ctx)
486{
487 struct bssgp_normal_hdr *bgph;
488 struct bssgp_ud_hdr *budh = NULL;
489 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
490 uint8_t pdu_type;
491 uint8_t *data;
492 size_t data_len;
493 int rc;
494
495 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
496 return 0;
497
498 bgph = (struct bssgp_normal_hdr *)bssgp;
499 pdu_type = bgph->pdu_type;
500
501 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
502 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
503 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
504 return 0;
505 budh = (struct bssgp_ud_hdr *)bssgp;
506 bgph = NULL;
507 data = budh->data;
508 data_len = bssgp_len - sizeof(*budh);
509 } else {
510 data = bgph->data;
511 data_len = bssgp_len - sizeof(*bgph);
512 }
513
514 if (bssgp_tlv_parse(tp, data, data_len) < 0)
515 return 0;
516
517 parse_ctx->pdu_type = pdu_type;
518 parse_ctx->bud_hdr = budh;
519 parse_ctx->bgp_hdr = bgph;
520 parse_ctx->bssgp_data = data;
521 parse_ctx->bssgp_data_len = data_len;
522
523 if (budh)
524 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
525
526 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
527 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
528
529 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
530 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
531
532 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
533 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
534 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
535 }
536
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200537 if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
538 if (parse_ctx->tlli_enc)
539 /* This is TLLI old, don't confuse it with TLLI current */
540 parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
541 else
542 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
543 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200544
545 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
546 parse_ctx->ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
547
548 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
549 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
550 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
551
552 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
553 if (!rc)
554 return 0;
555
556 parse_ctx->llc = llc;
557 parse_ctx->llc_len = llc_len;
558 }
559
560 if (parse_ctx->tlli_enc) {
561 uint32_t tmp_tlli;
562 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
563 parse_ctx->tlli = ntohl(tmp_tlli);
564 }
565
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200566 if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
567 memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
568 parse_ctx->old_raid_is_foreign = 1;
569
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200570 return 1;
571}
572
573void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx,
574 const char *default_msg_name)
575{
576 const char *msg_name = default_msg_name;
577 const char *sep = "";
578
579 if (!parse_ctx->tlli_enc &&
580 !parse_ctx->ptmsi_enc &&
581 !parse_ctx->new_ptmsi_enc &&
582 !parse_ctx->imsi)
583 return;
584
585 if (parse_ctx->llc_msg_name)
586 msg_name = parse_ctx->llc_msg_name;
587
588 LOGP(DGPRS, LOGL_DEBUG, "%s: Got", msg_name);
589
590 if (parse_ctx->tlli_enc) {
591 LOGP(DGPRS, LOGL_DEBUG, "%s TLLI %08x", sep, parse_ctx->tlli);
592 sep = ",";
593 }
594
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200595 if (parse_ctx->old_tlli_enc) {
596 LOGP(DGPRS, LOGL_DEBUG, "%s old TLLI %02x%02x%02x%02x", sep,
597 parse_ctx->old_tlli_enc[0],
598 parse_ctx->old_tlli_enc[1],
599 parse_ctx->old_tlli_enc[2],
600 parse_ctx->old_tlli_enc[3]);
601 sep = ",";
602 }
603
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200604 if (parse_ctx->bssgp_raid_enc) {
605 struct gprs_ra_id raid;
606 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
607 LOGP(DGPRS, LOGL_DEBUG, "%s BSSGP RAID %u-%u-%u-%u", sep,
608 raid.mcc, raid.mnc, raid.lac, raid.rac);
609 sep = ",";
610 }
611
612 if (parse_ctx->raid_enc) {
613 struct gprs_ra_id raid;
614 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
615 LOGP(DGPRS, LOGL_DEBUG, "%s RAID %u-%u-%u-%u", sep,
616 raid.mcc, raid.mnc, raid.lac, raid.rac);
617 sep = ",";
618 }
619
620 if (parse_ctx->old_raid_enc) {
621 struct gprs_ra_id raid;
622 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
623 LOGP(DGPRS, LOGL_DEBUG, "%s old RAID %u-%u-%u-%u", sep,
624 raid.mcc, raid.mnc, raid.lac, raid.rac);
625 sep = ",";
626 }
627
628 if (parse_ctx->ptmsi_enc) {
629 uint32_t ptmsi = GSM_RESERVED_TMSI;
630 int ok;
631 ok = gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN, &ptmsi);
632 LOGP(DGPRS, LOGL_DEBUG, "%s PTMSI %08x%s",
633 sep, ptmsi, ok ? "" : " (parse error)");
634 sep = ",";
635 }
636
637 if (parse_ctx->new_ptmsi_enc) {
638 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
639 int ok;
640 ok = gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
641 &new_ptmsi);
642 LOGP(DGPRS, LOGL_DEBUG, "%s new PTMSI %08x%s",
643 sep, new_ptmsi, ok ? "" : " (parse error)");
644 sep = ",";
645 }
646
647 if (parse_ctx->imsi) {
648 char mi_buf[200];
649 mi_buf[0] = '\0';
650 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
651 parse_ctx->imsi, parse_ctx->imsi_len);
652 LOGP(DGPRS, LOGL_DEBUG, "%s IMSI %s",
653 sep, mi_buf);
654 sep = ",";
655 }
656 if (parse_ctx->invalidate_tlli) {
657 LOGP(DGPRS, LOGL_DEBUG, "%s invalidate", sep);
658 sep = ",";
659 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200660 if (parse_ctx->await_reattach) {
661 LOGP(DGPRS, LOGL_DEBUG, "%s re-attach", sep);
662 sep = ",";
663 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200664
665 LOGP(DGPRS, LOGL_DEBUG, "\n");
666}
667