blob: d5a122bdae273e8a01f203a644b1b0bf8098bd5d [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>
Harald Welte53373bc2016-04-20 17:11:43 +020022#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Welte6e688082014-08-24 17:38:18 +020023
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020024#include <openbsc/gprs_gb_parse.h>
25
26#include <openbsc/gprs_utils.h>
27
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020028#include <openbsc/debug.h>
29
30#include <osmocom/gprs/gprs_bssgp.h>
31
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020032static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
33 struct gprs_gb_parse_context *parse_ctx)
34{
35 uint8_t *value;
36 size_t value_len;
37
38 parse_ctx->llc_msg_name = "ATTACH_REQ";
39
40 /* Skip MS network capability */
Harald Welte842674b2016-04-25 15:14:01 +020041 if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeckc9cd15f2014-09-29 12:36:45 +020042 value_len < 1 || value_len > 8)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020043 /* invalid */
Jacob Erlbeckf349bae2014-09-29 12:45:36 +020044 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020045
46 /* Skip Attach type */
47 /* Skip Ciphering key sequence number */
48 /* Skip DRX parameter */
Harald Welte842674b2016-04-25 15:14:01 +020049 osmo_shift_v_fixed(&data, &data_len, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020050
51 /* Get Mobile identity */
Harald Welte842674b2016-04-25 15:14:01 +020052 if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020053 value_len < 5 || value_len > 8)
54 /* invalid */
55 return 0;
56
57 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +020058 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020059 } else if (gprs_is_mi_imsi(value, value_len)) {
60 parse_ctx->imsi = value;
61 parse_ctx->imsi_len = value_len;
62 }
63
Harald Welte842674b2016-04-25 15:14:01 +020064 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020065 return 0;
66
67 parse_ctx->old_raid_enc = value;
68
69 return 1;
70}
71
72static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
73 struct gprs_gb_parse_context *parse_ctx)
74{
75 uint8_t *value;
76 size_t value_len;
77
78 parse_ctx->llc_msg_name = "ATTACH_ACK";
79
80 /* Skip Attach result */
81 /* Skip Force to standby */
82 /* Skip Periodic RA update timer */
83 /* Skip Radio priority for SMS */
84 /* Skip Spare half octet */
Harald Welte842674b2016-04-25 15:14:01 +020085 osmo_shift_v_fixed(&data, &data_len, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020086
Harald Welte842674b2016-04-25 15:14:01 +020087 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020088 return 0;
89
90 parse_ctx->raid_enc = value;
91
92 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
Harald Welte842674b2016-04-25 15:14:01 +020093 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020094
95 /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
Harald Welte842674b2016-04-25 15:14:01 +020096 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020097
98 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
Harald Welte842674b2016-04-25 15:14:01 +020099 if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200100 &value, &value_len) > 0 &&
101 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200102 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200103 return 1;
104}
105
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200106static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len,
107 struct gprs_gb_parse_context *parse_ctx)
108{
109 uint8_t *value;
110
111 parse_ctx->llc_msg_name = "ATTACH_REJ";
112
113 /* GMM cause */
Harald Welte842674b2016-04-25 15:14:01 +0200114 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200115 return 0;
116
117 parse_ctx->invalidate_tlli = 1;
118
119 return 1;
120}
121
122
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200123static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
124 struct gprs_gb_parse_context *parse_ctx)
125{
126 uint8_t *value;
127 size_t value_len;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200128 int detach_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200129 int power_off;
130
131 parse_ctx->llc_msg_name = "DETACH_REQ";
132
133 /* Skip spare half octet */
134 /* Get Detach type */
Harald Welte842674b2016-04-25 15:14:01 +0200135 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200136 /* invalid */
137 return 0;
138
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200139 detach_type = *value & 0x07;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200140 power_off = *value & 0x08 ? 1 : 0;
141
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200142 if (parse_ctx->to_bss) {
143 /* Network originated */
144 if (detach_type == GPRS_DET_T_MT_REATT_REQ)
145 parse_ctx->await_reattach = 1;
146 } else {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200147 /* Mobile originated */
148
149 if (power_off)
150 parse_ctx->invalidate_tlli = 1;
151
152 /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
Harald Welte842674b2016-04-25 15:14:01 +0200153 if (osmo_match_shift_tlv(&data, &data_len,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200154 GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
155 {
156 if (gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200157 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200158 }
159 }
160
161 return 1;
162}
163
164static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
165 struct gprs_gb_parse_context *parse_ctx)
166{
167 uint8_t *value;
168
169 parse_ctx->llc_msg_name = "RA_UPD_REQ";
170
171 /* Skip Update type */
172 /* Skip GPRS ciphering key sequence number */
Harald Welte842674b2016-04-25 15:14:01 +0200173 osmo_shift_v_fixed(&data, &data_len, 1, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200174
Harald Welte842674b2016-04-25 15:14:01 +0200175 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200176 return 0;
177
178 parse_ctx->old_raid_enc = value;
179
180 return 1;
181}
182
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200183static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len,
184 struct gprs_gb_parse_context *parse_ctx)
185{
186 uint8_t *value;
187 uint8_t cause;
188 int force_standby;
189
190 parse_ctx->llc_msg_name = "RA_UPD_REJ";
191
192 /* GMM cause */
Harald Welte842674b2016-04-25 15:14:01 +0200193 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200194 return 0;
195
196 cause = value[0];
197
198 /* Force to standby, 1/2 */
199 /* spare bits, 1/2 */
Harald Welte842674b2016-04-25 15:14:01 +0200200 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200201 return 0;
202
203 force_standby = (value[0] & 0x07) == 0x01;
204
205 if (cause == GMM_CAUSE_IMPL_DETACHED && !force_standby)
206 parse_ctx->await_reattach = 1;
207
208 parse_ctx->invalidate_tlli = 1;
209
210 return 1;
211}
212
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200213static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
214 struct gprs_gb_parse_context *parse_ctx)
215{
216 uint8_t *value;
217 size_t value_len;
218
219 parse_ctx->llc_msg_name = "RA_UPD_ACK";
220
221 /* Skip Force to standby */
222 /* Skip Update result */
223 /* Skip Periodic RA update timer */
Harald Welte842674b2016-04-25 15:14:01 +0200224 osmo_shift_v_fixed(&data, &data_len, 2, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200225
Harald Welte842674b2016-04-25 15:14:01 +0200226 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200227 return 0;
228
229 parse_ctx->raid_enc = value;
230
231 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
Harald Welte842674b2016-04-25 15:14:01 +0200232 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200233
234 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
Harald Welte842674b2016-04-25 15:14:01 +0200235 if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200236 &value, &value_len) > 0 &&
237 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200238 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200239
240 return 1;
241}
242
243static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
244 struct gprs_gb_parse_context *parse_ctx)
245{
246 uint8_t *value;
247 size_t value_len;
248
249 parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
250
251 LOGP(DLLC, LOGL_NOTICE,
252 "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
253
254 /* Allocated P-TMSI */
Harald Welte842674b2016-04-25 15:14:01 +0200255 if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200256 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200257 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200258
Harald Welte842674b2016-04-25 15:14:01 +0200259 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200260 return 0;
261
262 parse_ctx->raid_enc = value;
263
264 return 1;
265}
266
267static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
268 struct gprs_gb_parse_context *parse_ctx)
269{
270 uint8_t *value;
271 size_t value_len;
272
273 parse_ctx->llc_msg_name = "ID_RESP";
274
275 /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
Harald Welte842674b2016-04-25 15:14:01 +0200276 if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200277 value_len < 1 || value_len > 9)
278 /* invalid */
279 return 0;
280
281 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +0200282 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200283 } else if (gprs_is_mi_imsi(value, value_len)) {
284 parse_ctx->imsi = value;
285 parse_ctx->imsi_len = value_len;
286 }
287
288 return 1;
289}
290
291static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
292 struct gprs_gb_parse_context *parse_ctx)
293{
294 ssize_t old_len;
295 uint8_t *value;
296 size_t value_len;
297
298 parse_ctx->llc_msg_name = "ACT_PDP_REQ";
299
300 /* Skip Requested NSAPI */
301 /* Skip Requested LLC SAPI */
Harald Welte842674b2016-04-25 15:14:01 +0200302 osmo_shift_v_fixed(&data, &data_len, 2, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200303
304 /* Skip Requested QoS (support 04.08 and 24.008) */
Harald Welte842674b2016-04-25 15:14:01 +0200305 if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200306 value_len < 4 || value_len > 14)
307 /* invalid */
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200308 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200309
310 /* Skip Requested PDP address */
Harald Welte842674b2016-04-25 15:14:01 +0200311 if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200312 value_len < 2 || value_len > 18)
313 /* invalid */
314 return 0;
315
316 /* Access point name */
Harald Welte842674b2016-04-25 15:14:01 +0200317 old_len = osmo_match_shift_tlv(&data, &data_len,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200318 GSM48_IE_GSM_APN, &value, &value_len);
319
320 if (old_len > 0 && value_len >=1 && value_len <= 100) {
321 parse_ctx->apn_ie = data - old_len;
322 parse_ctx->apn_ie_len = old_len;
323 }
324
325 return 1;
326}
327
328int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
329 struct gprs_gb_parse_context *parse_ctx)
330{
331 struct gsm48_hdr *g48h;
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100332 uint8_t pdisc;
333 uint8_t msg_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200334
Harald Welte842674b2016-04-25 15:14:01 +0200335 if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200336 return 0;
337
338 parse_ctx->g48_hdr = g48h;
339
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100340 pdisc = gsm48_hdr_pdisc(g48h);
341 if (pdisc != GSM48_PDISC_MM_GPRS && pdisc != GSM48_PDISC_SM_GPRS)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200342 return 1;
343
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100344 msg_type = gsm48_hdr_msg_type(g48h);
345 switch (msg_type) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200346 case GSM48_MT_GMM_ATTACH_REQ:
347 return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
348
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200349 case GSM48_MT_GMM_ATTACH_REJ:
350 return gprs_gb_parse_gmm_attach_rej(data, data_len, parse_ctx);
351
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200352 case GSM48_MT_GMM_ATTACH_ACK:
353 return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
354
355 case GSM48_MT_GMM_RA_UPD_REQ:
356 return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
357
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200358 case GSM48_MT_GMM_RA_UPD_REJ:
359 return gprs_gb_parse_gmm_ra_upd_rej(data, data_len, parse_ctx);
360
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200361 case GSM48_MT_GMM_RA_UPD_ACK:
362 return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
363
364 case GSM48_MT_GMM_PTMSI_REALL_CMD:
365 return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
366
367 case GSM48_MT_GSM_ACT_PDP_REQ:
368 return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
369
370 case GSM48_MT_GMM_ID_RESP:
371 return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
372
373 case GSM48_MT_GMM_DETACH_REQ:
374 return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
375
376 case GSM48_MT_GMM_DETACH_ACK:
377 parse_ctx->llc_msg_name = "DETACH_ACK";
378 parse_ctx->invalidate_tlli = 1;
379 break;
380
381 default:
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100382 LOGP(DLLC, LOGL_NOTICE,
Max7b5dbc22017-05-05 13:24:03 +0200383 "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n",
384 get_value_string(gprs_msgt_gmm_names, msg_type), get_value_string(gsm48_pdisc_names, pdisc));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200385 break;
386 };
387
388 return 1;
389}
390
391int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
392 struct gprs_gb_parse_context *parse_ctx)
393{
394 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
395 int rc;
396 int fcs;
397
398 /* parse LLC */
399 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
Max549ebc72016-11-18 14:07:04 +0100400 gprs_llc_hdr_dump(ghp, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200401 if (rc != 0) {
402 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
403 return 0;
404 }
405
406 fcs = gprs_llc_fcs(llc, ghp->crc_length);
407 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
408 ghp->fcs, fcs);
409
410 if (!ghp->data)
411 return 0;
412
413 if (ghp->sapi != GPRS_SAPI_GMM)
414 return 1;
415
416 if (ghp->cmd != GPRS_LLC_UI)
417 return 1;
418
419 if (ghp->is_encrypted) {
420 parse_ctx->need_decryption = 1;
421 return 0;
422 }
423
424 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
425}
426
427int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
428 struct gprs_gb_parse_context *parse_ctx)
429{
430 struct bssgp_normal_hdr *bgph;
431 struct bssgp_ud_hdr *budh = NULL;
432 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
433 uint8_t pdu_type;
434 uint8_t *data;
435 size_t data_len;
436 int rc;
437
438 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
439 return 0;
440
441 bgph = (struct bssgp_normal_hdr *)bssgp;
442 pdu_type = bgph->pdu_type;
443
444 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
445 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
446 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
447 return 0;
448 budh = (struct bssgp_ud_hdr *)bssgp;
449 bgph = NULL;
450 data = budh->data;
451 data_len = bssgp_len - sizeof(*budh);
452 } else {
453 data = bgph->data;
454 data_len = bssgp_len - sizeof(*bgph);
455 }
456
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200457 parse_ctx->pdu_type = pdu_type;
458 parse_ctx->bud_hdr = budh;
459 parse_ctx->bgp_hdr = bgph;
460 parse_ctx->bssgp_data = data;
461 parse_ctx->bssgp_data_len = data_len;
462
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200463 if (bssgp_tlv_parse(tp, data, data_len) < 0)
464 return 0;
465
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200466 if (budh)
467 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
468
469 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
470 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
471
472 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
473 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
474
475 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
476 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
477 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
478 }
479
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200480 if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
481 if (parse_ctx->tlli_enc)
482 /* This is TLLI old, don't confuse it with TLLI current */
483 parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
484 else
485 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
486 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200487
488 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200489 parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200490
491 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
492 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
493 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
494
495 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
496 if (!rc)
497 return 0;
498
499 parse_ctx->llc = llc;
500 parse_ctx->llc_len = llc_len;
501 }
502
503 if (parse_ctx->tlli_enc) {
504 uint32_t tmp_tlli;
505 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
506 parse_ctx->tlli = ntohl(tmp_tlli);
507 }
508
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200509 if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
510 memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
511 parse_ctx->old_raid_is_foreign = 1;
512
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200513 return 1;
514}
515
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200516void gprs_gb_log_parse_context(int log_level,
517 struct gprs_gb_parse_context *parse_ctx,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200518 const char *default_msg_name)
519{
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200520 const char *msg_name;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200521 const char *sep = "";
522
523 if (!parse_ctx->tlli_enc &&
524 !parse_ctx->ptmsi_enc &&
525 !parse_ctx->new_ptmsi_enc &&
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200526 !parse_ctx->bssgp_ptmsi_enc &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200527 !parse_ctx->imsi)
528 return;
529
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200530 msg_name = gprs_gb_message_name(parse_ctx, default_msg_name);
531
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200532 if (parse_ctx->llc_msg_name)
533 msg_name = parse_ctx->llc_msg_name;
534
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200535 LOGP(DGPRS, log_level, "%s: Got", msg_name);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200536
537 if (parse_ctx->tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200538 LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200539 sep = ",";
540 }
541
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200542 if (parse_ctx->old_tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200543 LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep,
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200544 parse_ctx->old_tlli_enc[0],
545 parse_ctx->old_tlli_enc[1],
546 parse_ctx->old_tlli_enc[2],
547 parse_ctx->old_tlli_enc[3]);
548 sep = ",";
549 }
550
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200551 if (parse_ctx->bssgp_raid_enc) {
552 struct gprs_ra_id raid;
553 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200554 LOGPC(DGPRS, log_level, "%s BSSGP RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200555 raid.mcc, raid.mnc, raid.lac, raid.rac);
556 sep = ",";
557 }
558
559 if (parse_ctx->raid_enc) {
560 struct gprs_ra_id raid;
561 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200562 LOGPC(DGPRS, log_level, "%s RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200563 raid.mcc, raid.mnc, raid.lac, raid.rac);
564 sep = ",";
565 }
566
567 if (parse_ctx->old_raid_enc) {
568 struct gprs_ra_id raid;
569 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200570 LOGPC(DGPRS, log_level, "%s old RAID %u-%u-%u-%u", sep,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200571 raid.mcc, raid.mnc, raid.lac, raid.rac);
572 sep = ",";
573 }
574
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200575 if (parse_ctx->bssgp_ptmsi_enc) {
576 uint32_t ptmsi = GSM_RESERVED_TMSI;
577 gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
578 LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
579 sep = ",";
580 }
581
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200582 if (parse_ctx->ptmsi_enc) {
583 uint32_t ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200584 gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200585 LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200586 sep = ",";
587 }
588
589 if (parse_ctx->new_ptmsi_enc) {
590 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200591 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200592 LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200593 sep = ",";
594 }
595
596 if (parse_ctx->imsi) {
597 char mi_buf[200];
598 mi_buf[0] = '\0';
599 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
600 parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200601 LOGPC(DGPRS, log_level, "%s IMSI %s",
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200602 sep, mi_buf);
603 sep = ",";
604 }
605 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200606 LOGPC(DGPRS, log_level, "%s invalidate", sep);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200607 sep = ",";
608 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200609 if (parse_ctx->await_reattach) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200610 LOGPC(DGPRS, log_level, "%s re-attach", sep);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200611 sep = ",";
612 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200613
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200614 LOGPC(DGPRS, log_level, "\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200615}
616
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200617const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
618 const char *default_msg_name)
619{
620 if (parse_ctx->llc_msg_name)
621 return parse_ctx->llc_msg_name;
622
623 if (parse_ctx->g48_hdr)
624 return "GMM";
625
626 if (parse_ctx->llc)
627 return "LLC";
628
629 if (parse_ctx->bud_hdr)
630 return "BSSGP-UNITDATA";
631
632 if (parse_ctx->bgp_hdr)
633 return "BSSGP";
634
635 return "unknown";
636}