blob: 93b90a26dc8aa18f8d9ec8eb4b68db2dc2e54fdc [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
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020024#include <osmocom/sgsn/gprs_gb_parse.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020025
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020026#include <osmocom/sgsn/gprs_utils.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020027
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020028#include <osmocom/sgsn/debug.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020029
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 */
Stefan Sperling81c97ff2018-11-22 12:22:48 +010049 if (osmo_shift_v_fixed(&data, &data_len, 3, NULL) < 3)
50 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020051
52 /* Get Mobile identity */
Harald Welte842674b2016-04-25 15:14:01 +020053 if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020054 value_len < 5 || value_len > 8)
55 /* invalid */
56 return 0;
57
58 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +020059 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020060 } else if (gprs_is_mi_imsi(value, value_len)) {
61 parse_ctx->imsi = value;
62 parse_ctx->imsi_len = value_len;
63 }
64
Harald Welte842674b2016-04-25 15:14:01 +020065 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020066 return 0;
67
68 parse_ctx->old_raid_enc = value;
69
70 return 1;
71}
72
73static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
74 struct gprs_gb_parse_context *parse_ctx)
75{
76 uint8_t *value;
77 size_t value_len;
78
79 parse_ctx->llc_msg_name = "ATTACH_ACK";
80
81 /* Skip Attach result */
82 /* Skip Force to standby */
83 /* Skip Periodic RA update timer */
84 /* Skip Radio priority for SMS */
85 /* Skip Spare half octet */
Stefan Sperling81c97ff2018-11-22 12:22:48 +010086 if (osmo_shift_v_fixed(&data, &data_len, 3, NULL) < 3)
87 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020088
Harald Welte842674b2016-04-25 15:14:01 +020089 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020090 return 0;
91
92 parse_ctx->raid_enc = value;
93
94 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
Harald Welte842674b2016-04-25 15:14:01 +020095 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020096
97 /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
Harald Welte842674b2016-04-25 15:14:01 +020098 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020099
100 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
Harald Welte842674b2016-04-25 15:14:01 +0200101 if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200102 &value, &value_len) > 0 &&
103 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200104 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200105 return 1;
106}
107
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200108static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len,
109 struct gprs_gb_parse_context *parse_ctx)
110{
111 uint8_t *value;
112
113 parse_ctx->llc_msg_name = "ATTACH_REJ";
114
115 /* GMM cause */
Harald Welte842674b2016-04-25 15:14:01 +0200116 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200117 return 0;
118
119 parse_ctx->invalidate_tlli = 1;
120
121 return 1;
122}
123
124
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200125static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
126 struct gprs_gb_parse_context *parse_ctx)
127{
128 uint8_t *value;
129 size_t value_len;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200130 int detach_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200131 int power_off;
132
133 parse_ctx->llc_msg_name = "DETACH_REQ";
134
135 /* Skip spare half octet */
136 /* Get Detach type */
Harald Welte842674b2016-04-25 15:14:01 +0200137 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200138 /* invalid */
139 return 0;
140
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200141 detach_type = *value & 0x07;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200142 power_off = *value & 0x08 ? 1 : 0;
143
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200144 if (parse_ctx->to_bss) {
145 /* Network originated */
146 if (detach_type == GPRS_DET_T_MT_REATT_REQ)
147 parse_ctx->await_reattach = 1;
148 } else {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200149 /* Mobile originated */
150
151 if (power_off)
152 parse_ctx->invalidate_tlli = 1;
153
154 /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
Harald Welte842674b2016-04-25 15:14:01 +0200155 if (osmo_match_shift_tlv(&data, &data_len,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200156 GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
157 {
158 if (gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200159 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200160 }
161 }
162
163 return 1;
164}
165
166static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
167 struct gprs_gb_parse_context *parse_ctx)
168{
169 uint8_t *value;
170
171 parse_ctx->llc_msg_name = "RA_UPD_REQ";
172
173 /* Skip Update type */
174 /* Skip GPRS ciphering key sequence number */
Stefan Sperling81c97ff2018-11-22 12:22:48 +0100175 if (osmo_shift_v_fixed(&data, &data_len, 1, NULL) < 1)
176 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200177
Harald Welte842674b2016-04-25 15:14:01 +0200178 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200179 return 0;
180
181 parse_ctx->old_raid_enc = value;
182
183 return 1;
184}
185
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200186static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len,
187 struct gprs_gb_parse_context *parse_ctx)
188{
189 uint8_t *value;
190 uint8_t cause;
191 int force_standby;
192
193 parse_ctx->llc_msg_name = "RA_UPD_REJ";
194
195 /* GMM cause */
Harald Welte842674b2016-04-25 15:14:01 +0200196 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200197 return 0;
198
199 cause = value[0];
200
201 /* Force to standby, 1/2 */
202 /* spare bits, 1/2 */
Harald Welte842674b2016-04-25 15:14:01 +0200203 if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200204 return 0;
205
206 force_standby = (value[0] & 0x07) == 0x01;
207
208 if (cause == GMM_CAUSE_IMPL_DETACHED && !force_standby)
209 parse_ctx->await_reattach = 1;
210
211 parse_ctx->invalidate_tlli = 1;
212
213 return 1;
214}
215
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200216static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
217 struct gprs_gb_parse_context *parse_ctx)
218{
219 uint8_t *value;
220 size_t value_len;
221
222 parse_ctx->llc_msg_name = "RA_UPD_ACK";
223
224 /* Skip Force to standby */
225 /* Skip Update result */
226 /* Skip Periodic RA update timer */
Stefan Sperling81c97ff2018-11-22 12:22:48 +0100227 if (osmo_shift_v_fixed(&data, &data_len, 2, NULL) < 2)
228 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200229
Harald Welte842674b2016-04-25 15:14:01 +0200230 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200231 return 0;
232
233 parse_ctx->raid_enc = value;
234
235 /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
Harald Welte842674b2016-04-25 15:14:01 +0200236 osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200237
238 /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
Harald Welte842674b2016-04-25 15:14:01 +0200239 if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200240 &value, &value_len) > 0 &&
241 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200242 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200243
244 return 1;
245}
246
247static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
248 struct gprs_gb_parse_context *parse_ctx)
249{
250 uint8_t *value;
251 size_t value_len;
252
253 parse_ctx->llc_msg_name = "PTMSI_REALL_CMD";
254
255 LOGP(DLLC, LOGL_NOTICE,
256 "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
257
258 /* Allocated P-TMSI */
Harald Welte842674b2016-04-25 15:14:01 +0200259 if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200260 gprs_is_mi_tmsi(value, value_len))
Jacob Erlbeck49389172014-10-02 16:14:47 +0200261 parse_ctx->new_ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200262
Harald Welte842674b2016-04-25 15:14:01 +0200263 if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200264 return 0;
265
266 parse_ctx->raid_enc = value;
267
268 return 1;
269}
270
271static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
272 struct gprs_gb_parse_context *parse_ctx)
273{
274 uint8_t *value;
275 size_t value_len;
276
277 parse_ctx->llc_msg_name = "ID_RESP";
278
279 /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
Harald Welte842674b2016-04-25 15:14:01 +0200280 if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200281 value_len < 1 || value_len > 9)
282 /* invalid */
283 return 0;
284
285 if (gprs_is_mi_tmsi(value, value_len)) {
Jacob Erlbeck49389172014-10-02 16:14:47 +0200286 parse_ctx->ptmsi_enc = value + 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200287 } else if (gprs_is_mi_imsi(value, value_len)) {
288 parse_ctx->imsi = value;
289 parse_ctx->imsi_len = value_len;
290 }
291
292 return 1;
293}
294
295static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
296 struct gprs_gb_parse_context *parse_ctx)
297{
298 ssize_t old_len;
299 uint8_t *value;
300 size_t value_len;
301
302 parse_ctx->llc_msg_name = "ACT_PDP_REQ";
303
304 /* Skip Requested NSAPI */
305 /* Skip Requested LLC SAPI */
Stefan Sperling81c97ff2018-11-22 12:22:48 +0100306 if (osmo_shift_v_fixed(&data, &data_len, 2, NULL) < 2)
307 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200308
309 /* Skip Requested QoS (support 04.08 and 24.008) */
Harald Welte842674b2016-04-25 15:14:01 +0200310 if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200311 value_len < 4 || value_len > 14)
312 /* invalid */
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200313 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200314
315 /* Skip Requested PDP address */
Harald Welte842674b2016-04-25 15:14:01 +0200316 if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200317 value_len < 2 || value_len > 18)
318 /* invalid */
319 return 0;
320
321 /* Access point name */
Harald Welte842674b2016-04-25 15:14:01 +0200322 old_len = osmo_match_shift_tlv(&data, &data_len,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200323 GSM48_IE_GSM_APN, &value, &value_len);
324
325 if (old_len > 0 && value_len >=1 && value_len <= 100) {
326 parse_ctx->apn_ie = data - old_len;
327 parse_ctx->apn_ie_len = old_len;
328 }
329
330 return 1;
331}
332
333int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
334 struct gprs_gb_parse_context *parse_ctx)
335{
336 struct gsm48_hdr *g48h;
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100337 uint8_t pdisc;
338 uint8_t msg_type;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200339
Harald Welte842674b2016-04-25 15:14:01 +0200340 if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200341 return 0;
342
343 parse_ctx->g48_hdr = g48h;
344
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100345 pdisc = gsm48_hdr_pdisc(g48h);
346 if (pdisc != GSM48_PDISC_MM_GPRS && pdisc != GSM48_PDISC_SM_GPRS)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200347 return 1;
348
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100349 msg_type = gsm48_hdr_msg_type(g48h);
350 switch (msg_type) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200351 case GSM48_MT_GMM_ATTACH_REQ:
352 return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx);
353
Jacob Erlbeck9c65c812014-09-22 10:42:05 +0200354 case GSM48_MT_GMM_ATTACH_REJ:
355 return gprs_gb_parse_gmm_attach_rej(data, data_len, parse_ctx);
356
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200357 case GSM48_MT_GMM_ATTACH_ACK:
358 return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx);
359
360 case GSM48_MT_GMM_RA_UPD_REQ:
361 return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx);
362
Jacob Erlbeck85e5c8f2014-09-16 12:16:58 +0200363 case GSM48_MT_GMM_RA_UPD_REJ:
364 return gprs_gb_parse_gmm_ra_upd_rej(data, data_len, parse_ctx);
365
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200366 case GSM48_MT_GMM_RA_UPD_ACK:
367 return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx);
368
369 case GSM48_MT_GMM_PTMSI_REALL_CMD:
370 return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx);
371
372 case GSM48_MT_GSM_ACT_PDP_REQ:
373 return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx);
374
375 case GSM48_MT_GMM_ID_RESP:
376 return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx);
377
378 case GSM48_MT_GMM_DETACH_REQ:
379 return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx);
380
381 case GSM48_MT_GMM_DETACH_ACK:
382 parse_ctx->llc_msg_name = "DETACH_ACK";
383 parse_ctx->invalidate_tlli = 1;
384 break;
385
386 default:
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100387 LOGP(DLLC, LOGL_NOTICE,
Max7b5dbc22017-05-05 13:24:03 +0200388 "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n",
389 get_value_string(gprs_msgt_gmm_names, msg_type), get_value_string(gsm48_pdisc_names, pdisc));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200390 break;
391 };
392
393 return 1;
394}
395
396int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
397 struct gprs_gb_parse_context *parse_ctx)
398{
399 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
400 int rc;
401 int fcs;
402
403 /* parse LLC */
404 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
Max549ebc72016-11-18 14:07:04 +0100405 gprs_llc_hdr_dump(ghp, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200406 if (rc != 0) {
407 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
408 return 0;
409 }
410
411 fcs = gprs_llc_fcs(llc, ghp->crc_length);
412 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
413 ghp->fcs, fcs);
414
415 if (!ghp->data)
416 return 0;
417
418 if (ghp->sapi != GPRS_SAPI_GMM)
419 return 1;
420
421 if (ghp->cmd != GPRS_LLC_UI)
422 return 1;
423
424 if (ghp->is_encrypted) {
425 parse_ctx->need_decryption = 1;
426 return 0;
427 }
428
429 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
430}
431
432int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
433 struct gprs_gb_parse_context *parse_ctx)
434{
435 struct bssgp_normal_hdr *bgph;
436 struct bssgp_ud_hdr *budh = NULL;
437 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
438 uint8_t pdu_type;
439 uint8_t *data;
440 size_t data_len;
441 int rc;
442
443 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
444 return 0;
445
446 bgph = (struct bssgp_normal_hdr *)bssgp;
447 pdu_type = bgph->pdu_type;
448
449 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
450 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
451 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
452 return 0;
453 budh = (struct bssgp_ud_hdr *)bssgp;
454 bgph = NULL;
455 data = budh->data;
456 data_len = bssgp_len - sizeof(*budh);
457 } else {
458 data = bgph->data;
459 data_len = bssgp_len - sizeof(*bgph);
460 }
461
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200462 parse_ctx->pdu_type = pdu_type;
463 parse_ctx->bud_hdr = budh;
464 parse_ctx->bgp_hdr = bgph;
465 parse_ctx->bssgp_data = data;
466 parse_ctx->bssgp_data_len = data_len;
467
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200468 if (bssgp_tlv_parse(tp, data, data_len) < 0)
469 return 0;
470
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200471 if (budh)
472 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
473
474 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
475 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
476
477 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
478 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
479
480 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
481 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
482 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
483 }
484
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200485 if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
486 if (parse_ctx->tlli_enc)
487 /* This is TLLI old, don't confuse it with TLLI current */
488 parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
489 else
490 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
491 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200492
493 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200494 parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200495
496 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
497 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
498 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
499
500 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
501 if (!rc)
502 return 0;
503
504 parse_ctx->llc = llc;
505 parse_ctx->llc_len = llc_len;
506 }
507
508 if (parse_ctx->tlli_enc) {
509 uint32_t tmp_tlli;
510 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
511 parse_ctx->tlli = ntohl(tmp_tlli);
512 }
513
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200514 if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
515 memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
516 parse_ctx->old_raid_is_foreign = 1;
517
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200518 return 1;
519}
520
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200521void gprs_gb_log_parse_context(int log_level,
522 struct gprs_gb_parse_context *parse_ctx,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200523 const char *default_msg_name)
524{
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200525 const char *msg_name;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200526 const char *sep = "";
527
528 if (!parse_ctx->tlli_enc &&
529 !parse_ctx->ptmsi_enc &&
530 !parse_ctx->new_ptmsi_enc &&
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200531 !parse_ctx->bssgp_ptmsi_enc &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200532 !parse_ctx->imsi)
533 return;
534
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200535 msg_name = gprs_gb_message_name(parse_ctx, default_msg_name);
536
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200537 if (parse_ctx->llc_msg_name)
538 msg_name = parse_ctx->llc_msg_name;
539
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200540 LOGP(DGPRS, log_level, "%s: Got", msg_name);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200541
542 if (parse_ctx->tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200543 LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200544 sep = ",";
545 }
546
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200547 if (parse_ctx->old_tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200548 LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep,
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200549 parse_ctx->old_tlli_enc[0],
550 parse_ctx->old_tlli_enc[1],
551 parse_ctx->old_tlli_enc[2],
552 parse_ctx->old_tlli_enc[3]);
553 sep = ",";
554 }
555
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200556 if (parse_ctx->bssgp_raid_enc) {
557 struct gprs_ra_id raid;
558 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100559 LOGPC(DGPRS, log_level, "%s BSSGP RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200560 sep = ",";
561 }
562
563 if (parse_ctx->raid_enc) {
564 struct gprs_ra_id raid;
565 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100566 LOGPC(DGPRS, log_level, "%s RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200567 sep = ",";
568 }
569
570 if (parse_ctx->old_raid_enc) {
571 struct gprs_ra_id raid;
572 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100573 LOGPC(DGPRS, log_level, "%s old RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200574 sep = ",";
575 }
576
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200577 if (parse_ctx->bssgp_ptmsi_enc) {
578 uint32_t ptmsi = GSM_RESERVED_TMSI;
579 gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
580 LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
581 sep = ",";
582 }
583
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200584 if (parse_ctx->ptmsi_enc) {
585 uint32_t ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200586 gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200587 LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200588 sep = ",";
589 }
590
591 if (parse_ctx->new_ptmsi_enc) {
592 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200593 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200594 LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200595 sep = ",";
596 }
597
598 if (parse_ctx->imsi) {
599 char mi_buf[200];
600 mi_buf[0] = '\0';
601 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
602 parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200603 LOGPC(DGPRS, log_level, "%s IMSI %s",
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200604 sep, mi_buf);
605 sep = ",";
606 }
607 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200608 LOGPC(DGPRS, log_level, "%s invalidate", sep);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200609 sep = ",";
610 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200611 if (parse_ctx->await_reattach) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200612 LOGPC(DGPRS, log_level, "%s re-attach", sep);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200613 sep = ",";
614 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200615
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200616 LOGPC(DGPRS, log_level, "\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200617}
618
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200619const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
620 const char *default_msg_name)
621{
622 if (parse_ctx->llc_msg_name)
623 return parse_ctx->llc_msg_name;
624
625 if (parse_ctx->g48_hdr)
626 return "GMM";
627
628 if (parse_ctx->llc)
629 return "LLC";
630
631 if (parse_ctx->bud_hdr)
632 return "BSSGP-UNITDATA";
633
634 if (parse_ctx->bgp_hdr)
635 return "BSSGP";
636
637 return "unknown";
638}