blob: 72c0d57e8a59efd285597cfa031a91bb7d767de7 [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
21#include <openbsc/gprs_gb_parse.h>
22
23#include <openbsc/gprs_utils.h>
24
25#include <openbsc/gsm_04_08_gprs.h>
26#include <openbsc/gsm_data_shared.h>
27#include <openbsc/debug.h>
28
29#include <osmocom/gprs/gprs_bssgp.h>
30
31/* TODO: Move shift functions to libosmocore */
32
33int v_fixed_shift(uint8_t **data, size_t *data_len,
34 size_t len, uint8_t **value)
35{
36 if (len > *data_len)
37 goto fail;
38
39 if (value)
40 *value = *data;
41
42 *data += len;
43 *data_len -= len;
44
45 return len;
46
47fail:
48 *data += *data_len;
49 *data_len = 0;
50 return -1;
51}
52
53int tv_fixed_match(uint8_t **data, size_t *data_len,
54 uint8_t tag, size_t len,
55 uint8_t **value)
56{
57 size_t ie_len;
58
59 if (*data_len == 0)
60 goto fail;
61
62 if ((*data)[0] != tag)
63 return 0;
64
65 if (len > *data_len - 1)
66 goto fail;
67
68 if (value)
69 *value = *data + 1;
70
71 ie_len = len + 1;
72 *data += ie_len;
73 *data_len -= ie_len;
74
75 return ie_len;
76
77fail:
78 *data += *data_len;
79 *data_len = 0;
80 return -1;
81}
82
83int tlv_match(uint8_t **data, size_t *data_len,
84 uint8_t tag, uint8_t **value, size_t *value_len)
85{
86 size_t len;
87 size_t ie_len;
88
89 if (*data_len < 2)
90 goto fail;
91
92 if ((*data)[0] != tag)
93 return 0;
94
95 len = (*data)[1];
96 if (len > *data_len - 2)
97 goto fail;
98
99 if (value)
100 *value = *data + 2;
101 if (value_len)
102 *value_len = len;
103
104 ie_len = len + 2;
105
106 *data += ie_len;
107 *data_len -= ie_len;
108
109 return ie_len;
110
111fail:
112 *data += *data_len;
113 *data_len = 0;
114 return -1;
115}
116
117int lv_shift(uint8_t **data, size_t *data_len,
118 uint8_t **value, size_t *value_len)
119{
120 size_t len;
121 size_t ie_len;
122
123 if (*data_len < 1)
124 goto fail;
125
126 len = (*data)[0];
127 if (len > *data_len - 1)
128 goto fail;
129
130 if (value)
131 *value = *data + 1;
132 if (value_len)
133 *value_len = len;
134
135 ie_len = len + 1;
136 *data += ie_len;
137 *data_len -= ie_len;
138
139 return ie_len;
140
141fail:
142 *data += *data_len;
143 *data_len = 0;
144 return -1;
145}
146
147static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
148 struct gprs_gb_parse_context *parse_ctx)
149{
150 uint8_t *value;
151 size_t value_len;
152
153 parse_ctx->llc_msg_name = "ATTACH_REQ";
154
155 /* Skip MS network capability */
156 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
157 value_len < 1 || value_len > 2)
158 /* invalid */
159 return 0;;
160
161 /* Skip Attach type */
162 /* Skip Ciphering key sequence number */
163 /* Skip DRX parameter */
164 v_fixed_shift(&data, &data_len, 3, NULL);
165
166 /* Get Mobile identity */
167 if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
168 value_len < 5 || value_len > 8)
169 /* invalid */
170 return 0;
171
172 if (gprs_is_mi_tmsi(value, value_len)) {
173 parse_ctx->ptmsi_enc = value;
174 } else if (gprs_is_mi_imsi(value, value_len)) {
175 parse_ctx->imsi = value;
176 parse_ctx->imsi_len = value_len;
177 }
178
179 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
180 return 0;
181
182 parse_ctx->old_raid_enc = value;
183
184 return 1;
185}
186
187static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
188 struct gprs_gb_parse_context *parse_ctx)
189{
190 uint8_t *value;
191 size_t value_len;
192
193 parse_ctx->llc_msg_name = "ATTACH_ACK";
194
195 /* Skip Attach result */
196 /* Skip Force to standby */
197 /* Skip Periodic RA update timer */
198 /* Skip Radio priority for SMS */
199 /* Skip Spare half octet */
200 v_fixed_shift(&data, &data_len, 3, NULL);
201
202 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
203 return 0;
204
205 parse_ctx->raid_enc = value;
206
207 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
208 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
209
210 /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
211 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
212
213 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
214 if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
215 &value, &value_len) > 0 &&
216 gprs_is_mi_tmsi(value, value_len))
217 parse_ctx->new_ptmsi_enc = value;
218 return 1;
219}
220
221static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
222 struct gprs_gb_parse_context *parse_ctx)
223{
224 uint8_t *value;
225 size_t value_len;
226 int detach_type;
227 int power_off;
228
229 parse_ctx->llc_msg_name = "DETACH_REQ";
230
231 /* Skip spare half octet */
232 /* Get Detach type */
233 if (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
234 /* invalid */
235 return 0;
236
237 detach_type = *value & 0x07;
238 power_off = *value & 0x08 ? 1 : 0;
239
240 if (!parse_ctx->to_bss) {
241 /* Mobile originated */
242
243 if (power_off)
244 parse_ctx->invalidate_tlli = 1;
245
246 /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
247 if (tlv_match(&data, &data_len,
248 GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
249 {
250 if (gprs_is_mi_tmsi(value, value_len))
251 parse_ctx->ptmsi_enc = value;
252 }
253 }
254
255 return 1;
256}
257
258static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
259 struct gprs_gb_parse_context *parse_ctx)
260{
261 uint8_t *value;
262
263 parse_ctx->llc_msg_name = "RA_UPD_REQ";
264
265 /* Skip Update type */
266 /* Skip GPRS ciphering key sequence number */
267 v_fixed_shift(&data, &data_len, 1, NULL);
268
269 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
270 return 0;
271
272 parse_ctx->old_raid_enc = value;
273
274 return 1;
275}
276
277static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
278 struct gprs_gb_parse_context *parse_ctx)
279{
280 uint8_t *value;
281 size_t value_len;
282
283 parse_ctx->llc_msg_name = "RA_UPD_ACK";
284
285 /* Skip Force to standby */
286 /* Skip Update result */
287 /* Skip Periodic RA update timer */
288 v_fixed_shift(&data, &data_len, 2, NULL);
289
290 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
291 return 0;
292
293 parse_ctx->raid_enc = value;
294
295 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
296 tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
297
298 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
299 if (tlv_match(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
300 &value, &value_len) > 0 &&
301 gprs_is_mi_tmsi(value, value_len))
302 parse_ctx->new_ptmsi_enc = value;
303
304 return 1;
305}
306
307static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
308 struct gprs_gb_parse_context *parse_ctx)
309{
310 uint8_t *value;
311 size_t value_len;
312
313 parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
314
315 LOGP(DLLC, LOGL_NOTICE,
316 "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
317
318 /* Allocated P-TMSI */
319 if (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
320 gprs_is_mi_tmsi(value, value_len))
321 parse_ctx->new_ptmsi_enc = value;
322
323 if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
324 return 0;
325
326 parse_ctx->raid_enc = value;
327
328 return 1;
329}
330
331static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
332 struct gprs_gb_parse_context *parse_ctx)
333{
334 uint8_t *value;
335 size_t value_len;
336
337 parse_ctx->llc_msg_name = "ID_RESP";
338
339 /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
340 if (lv_shift(&data, &data_len, &value, &value_len) <= 0 ||
341 value_len < 1 || value_len > 9)
342 /* invalid */
343 return 0;
344
345 if (gprs_is_mi_tmsi(value, value_len)) {
346 parse_ctx->ptmsi_enc = value;
347 } else if (gprs_is_mi_imsi(value, value_len)) {
348 parse_ctx->imsi = value;
349 parse_ctx->imsi_len = value_len;
350 }
351
352 return 1;
353}
354
355static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
356 struct gprs_gb_parse_context *parse_ctx)
357{
358 ssize_t old_len;
359 uint8_t *value;
360 size_t value_len;
361
362 parse_ctx->llc_msg_name = "ACT_PDP_REQ";
363
364 /* Skip Requested NSAPI */
365 /* Skip Requested LLC SAPI */
366 v_fixed_shift(&data, &data_len, 2, NULL);
367
368 /* Skip Requested QoS (support 04.08 and 24.008) */
369 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
370 value_len < 4 || value_len > 14)
371 /* invalid */
372 return 0;;
373
374 /* Skip Requested PDP address */
375 if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
376 value_len < 2 || value_len > 18)
377 /* invalid */
378 return 0;
379
380 /* Access point name */
381 old_len = tlv_match(&data, &data_len,
382 GSM48_IE_GSM_APN, &value, &value_len);
383
384 if (old_len > 0 && value_len >=1 && value_len <= 100) {
385 parse_ctx->apn_ie = data - old_len;
386 parse_ctx->apn_ie_len = old_len;
387 }
388
389 return 1;
390}
391
392int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
393 struct gprs_gb_parse_context *parse_ctx)
394{
395 struct gsm48_hdr *g48h;
396
397 if (v_fixed_shift(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
398 return 0;
399
400 parse_ctx->g48_hdr = g48h;
401
402 if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS &&
403 (g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS)
404 return 1;
405
406 switch (g48h->msg_type) {
407 case GSM48_MT_GMM_ATTACH_REQ:
408 return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
409
410 case GSM48_MT_GMM_ATTACH_ACK:
411 return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
412
413 case GSM48_MT_GMM_RA_UPD_REQ:
414 return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
415
416 case GSM48_MT_GMM_RA_UPD_ACK:
417 return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
418
419 case GSM48_MT_GMM_PTMSI_REALL_CMD:
420 return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
421
422 case GSM48_MT_GSM_ACT_PDP_REQ:
423 return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
424
425 case GSM48_MT_GMM_ID_RESP:
426 return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
427
428 case GSM48_MT_GMM_DETACH_REQ:
429 return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
430
431 case GSM48_MT_GMM_DETACH_ACK:
432 parse_ctx->llc_msg_name = "DETACH_ACK";
433 parse_ctx->invalidate_tlli = 1;
434 break;
435
436 default:
437 break;
438 };
439
440 return 1;
441}
442
443int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
444 struct gprs_gb_parse_context *parse_ctx)
445{
446 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
447 int rc;
448 int fcs;
449
450 /* parse LLC */
451 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
452 gprs_llc_hdr_dump(ghp);
453 if (rc != 0) {
454 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
455 return 0;
456 }
457
458 fcs = gprs_llc_fcs(llc, ghp->crc_length);
459 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
460 ghp->fcs, fcs);
461
462 if (!ghp->data)
463 return 0;
464
465 if (ghp->sapi != GPRS_SAPI_GMM)
466 return 1;
467
468 if (ghp->cmd != GPRS_LLC_UI)
469 return 1;
470
471 if (ghp->is_encrypted) {
472 parse_ctx->need_decryption = 1;
473 return 0;
474 }
475
476 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
477}
478
479int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
480 struct gprs_gb_parse_context *parse_ctx)
481{
482 struct bssgp_normal_hdr *bgph;
483 struct bssgp_ud_hdr *budh = NULL;
484 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
485 uint8_t pdu_type;
486 uint8_t *data;
487 size_t data_len;
488 int rc;
489
490 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
491 return 0;
492
493 bgph = (struct bssgp_normal_hdr *)bssgp;
494 pdu_type = bgph->pdu_type;
495
496 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
497 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
498 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
499 return 0;
500 budh = (struct bssgp_ud_hdr *)bssgp;
501 bgph = NULL;
502 data = budh->data;
503 data_len = bssgp_len - sizeof(*budh);
504 } else {
505 data = bgph->data;
506 data_len = bssgp_len - sizeof(*bgph);
507 }
508
509 if (bssgp_tlv_parse(tp, data, data_len) < 0)
510 return 0;
511
512 parse_ctx->pdu_type = pdu_type;
513 parse_ctx->bud_hdr = budh;
514 parse_ctx->bgp_hdr = bgph;
515 parse_ctx->bssgp_data = data;
516 parse_ctx->bssgp_data_len = data_len;
517
518 if (budh)
519 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
520
521 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
522 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
523
524 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
525 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
526
527 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
528 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
529 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
530 }
531
532 /* TODO: This is TLLI old, don't confuse with TLLI current, add
533 * and use tlli_old_enc instead */
534 if (0 && TLVP_PRESENT(tp, BSSGP_IE_TLLI))
535 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
536
537 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
538 parse_ctx->ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
539
540 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
541 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
542 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
543
544 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
545 if (!rc)
546 return 0;
547
548 parse_ctx->llc = llc;
549 parse_ctx->llc_len = llc_len;
550 }
551
552 if (parse_ctx->tlli_enc) {
553 uint32_t tmp_tlli;
554 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
555 parse_ctx->tlli = ntohl(tmp_tlli);
556 }
557
558 return 1;
559}
560
561void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx,
562 const char *default_msg_name)
563{
564 const char *msg_name = default_msg_name;
565 const char *sep = "";
566
567 if (!parse_ctx->tlli_enc &&
568 !parse_ctx->ptmsi_enc &&
569 !parse_ctx->new_ptmsi_enc &&
570 !parse_ctx->imsi)
571 return;
572
573 if (parse_ctx->llc_msg_name)
574 msg_name = parse_ctx->llc_msg_name;
575
576 LOGP(DGPRS, LOGL_DEBUG, "%s: Got", msg_name);
577
578 if (parse_ctx->tlli_enc) {
579 LOGP(DGPRS, LOGL_DEBUG, "%s TLLI %08x", sep, parse_ctx->tlli);
580 sep = ",";
581 }
582
583 if (parse_ctx->bssgp_raid_enc) {
584 struct gprs_ra_id raid;
585 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
586 LOGP(DGPRS, LOGL_DEBUG, "%s BSSGP RAID %u-%u-%u-%u", sep,
587 raid.mcc, raid.mnc, raid.lac, raid.rac);
588 sep = ",";
589 }
590
591 if (parse_ctx->raid_enc) {
592 struct gprs_ra_id raid;
593 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
594 LOGP(DGPRS, LOGL_DEBUG, "%s RAID %u-%u-%u-%u", sep,
595 raid.mcc, raid.mnc, raid.lac, raid.rac);
596 sep = ",";
597 }
598
599 if (parse_ctx->old_raid_enc) {
600 struct gprs_ra_id raid;
601 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
602 LOGP(DGPRS, LOGL_DEBUG, "%s old RAID %u-%u-%u-%u", sep,
603 raid.mcc, raid.mnc, raid.lac, raid.rac);
604 sep = ",";
605 }
606
607 if (parse_ctx->ptmsi_enc) {
608 uint32_t ptmsi = GSM_RESERVED_TMSI;
609 int ok;
610 ok = gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN, &ptmsi);
611 LOGP(DGPRS, LOGL_DEBUG, "%s PTMSI %08x%s",
612 sep, ptmsi, ok ? "" : " (parse error)");
613 sep = ",";
614 }
615
616 if (parse_ctx->new_ptmsi_enc) {
617 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
618 int ok;
619 ok = gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
620 &new_ptmsi);
621 LOGP(DGPRS, LOGL_DEBUG, "%s new PTMSI %08x%s",
622 sep, new_ptmsi, ok ? "" : " (parse error)");
623 sep = ",";
624 }
625
626 if (parse_ctx->imsi) {
627 char mi_buf[200];
628 mi_buf[0] = '\0';
629 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
630 parse_ctx->imsi, parse_ctx->imsi_len);
631 LOGP(DGPRS, LOGL_DEBUG, "%s IMSI %s",
632 sep, mi_buf);
633 sep = ",";
634 }
635 if (parse_ctx->invalidate_tlli) {
636 LOGP(DGPRS, LOGL_DEBUG, "%s invalidate", sep);
637 sep = ",";
638 }
639
640 LOGP(DGPRS, LOGL_DEBUG, "\n");
641}
642