blob: 379674a91c667d7334e0b06ed69db6b9c6cec736 [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
Alexander Couzens6c0586a2019-04-14 05:36:00 +0200386 case GSM48_MT_GSM_DEACT_PDP_REQ:
387 parse_ctx->llc_msg_name = "DEACT_PDP_REQ";
388 break;
389
390 case GSM48_MT_GSM_DEACT_PDP_ACK:
391 parse_ctx->llc_msg_name = "DEACT_PDP_ACK";
392 break;
393
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200394 default:
Neels Hofmeyr531734a2016-03-14 16:13:24 +0100395 LOGP(DLLC, LOGL_NOTICE,
Max7b5dbc22017-05-05 13:24:03 +0200396 "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n",
397 get_value_string(gprs_msgt_gmm_names, msg_type), get_value_string(gsm48_pdisc_names, pdisc));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200398 break;
399 };
400
401 return 1;
402}
403
404int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
405 struct gprs_gb_parse_context *parse_ctx)
406{
407 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
408 int rc;
409 int fcs;
410
411 /* parse LLC */
412 rc = gprs_llc_hdr_parse(ghp, llc, llc_len);
Max549ebc72016-11-18 14:07:04 +0100413 gprs_llc_hdr_dump(ghp, NULL);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200414 if (rc != 0) {
415 LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n");
416 return 0;
417 }
418
419 fcs = gprs_llc_fcs(llc, ghp->crc_length);
420 LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n",
421 ghp->fcs, fcs);
422
423 if (!ghp->data)
424 return 0;
425
426 if (ghp->sapi != GPRS_SAPI_GMM)
427 return 1;
428
429 if (ghp->cmd != GPRS_LLC_UI)
430 return 1;
431
432 if (ghp->is_encrypted) {
433 parse_ctx->need_decryption = 1;
434 return 0;
435 }
436
437 return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx);
438}
439
440int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
441 struct gprs_gb_parse_context *parse_ctx)
442{
443 struct bssgp_normal_hdr *bgph;
444 struct bssgp_ud_hdr *budh = NULL;
445 struct tlv_parsed *tp = &parse_ctx->bssgp_tp;
446 uint8_t pdu_type;
447 uint8_t *data;
448 size_t data_len;
449 int rc;
450
451 if (bssgp_len < sizeof(struct bssgp_normal_hdr))
452 return 0;
453
454 bgph = (struct bssgp_normal_hdr *)bssgp;
455 pdu_type = bgph->pdu_type;
456
457 if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
458 pdu_type == BSSGP_PDUT_DL_UNITDATA) {
459 if (bssgp_len < sizeof(struct bssgp_ud_hdr))
460 return 0;
461 budh = (struct bssgp_ud_hdr *)bssgp;
462 bgph = NULL;
463 data = budh->data;
464 data_len = bssgp_len - sizeof(*budh);
465 } else {
466 data = bgph->data;
467 data_len = bssgp_len - sizeof(*bgph);
468 }
469
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200470 parse_ctx->pdu_type = pdu_type;
471 parse_ctx->bud_hdr = budh;
472 parse_ctx->bgp_hdr = bgph;
473 parse_ctx->bssgp_data = data;
474 parse_ctx->bssgp_data_len = data_len;
475
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200476 if (bssgp_tlv_parse(tp, data, data_len) < 0)
477 return 0;
478
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200479 if (budh)
480 parse_ctx->tlli_enc = (uint8_t *)&budh->tlli;
481
482 if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA))
483 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
484
485 if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID))
486 parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID);
487
488 if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) {
489 parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI);
490 parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI);
491 }
492
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200493 if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) {
494 if (parse_ctx->tlli_enc)
495 /* This is TLLI old, don't confuse it with TLLI current */
496 parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
497 else
498 parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI);
499 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200500
501 if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS)
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200502 parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200503
504 if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) {
505 uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
506 size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
507
508 rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx);
509 if (!rc)
510 return 0;
511
512 parse_ctx->llc = llc;
513 parse_ctx->llc_len = llc_len;
514 }
515
516 if (parse_ctx->tlli_enc) {
517 uint32_t tmp_tlli;
518 memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli));
519 parse_ctx->tlli = ntohl(tmp_tlli);
520 }
521
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200522 if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc &&
523 memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0)
524 parse_ctx->old_raid_is_foreign = 1;
525
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200526 return 1;
527}
528
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200529void gprs_gb_log_parse_context(int log_level,
530 struct gprs_gb_parse_context *parse_ctx,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200531 const char *default_msg_name)
532{
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200533 const char *msg_name;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200534 const char *sep = "";
535
536 if (!parse_ctx->tlli_enc &&
537 !parse_ctx->ptmsi_enc &&
538 !parse_ctx->new_ptmsi_enc &&
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200539 !parse_ctx->bssgp_ptmsi_enc &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200540 !parse_ctx->imsi)
541 return;
542
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200543 msg_name = gprs_gb_message_name(parse_ctx, default_msg_name);
544
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200545 if (parse_ctx->llc_msg_name)
546 msg_name = parse_ctx->llc_msg_name;
547
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200548 LOGP(DGPRS, log_level, "%s: Got", msg_name);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200549
550 if (parse_ctx->tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200551 LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200552 sep = ",";
553 }
554
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200555 if (parse_ctx->old_tlli_enc) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200556 LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep,
Jacob Erlbeck4b663ac2014-08-21 15:07:11 +0200557 parse_ctx->old_tlli_enc[0],
558 parse_ctx->old_tlli_enc[1],
559 parse_ctx->old_tlli_enc[2],
560 parse_ctx->old_tlli_enc[3]);
561 sep = ",";
562 }
563
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200564 if (parse_ctx->bssgp_raid_enc) {
565 struct gprs_ra_id raid;
566 gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100567 LOGPC(DGPRS, log_level, "%s BSSGP RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200568 sep = ",";
569 }
570
571 if (parse_ctx->raid_enc) {
572 struct gprs_ra_id raid;
573 gsm48_parse_ra(&raid, parse_ctx->raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100574 LOGPC(DGPRS, log_level, "%s RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200575 sep = ",";
576 }
577
578 if (parse_ctx->old_raid_enc) {
579 struct gprs_ra_id raid;
580 gsm48_parse_ra(&raid, parse_ctx->old_raid_enc);
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100581 LOGPC(DGPRS, log_level, "%s old RAID %s", sep, osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200582 sep = ",";
583 }
584
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200585 if (parse_ctx->bssgp_ptmsi_enc) {
586 uint32_t ptmsi = GSM_RESERVED_TMSI;
587 gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi);
588 LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi);
589 sep = ",";
590 }
591
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200592 if (parse_ctx->ptmsi_enc) {
593 uint32_t ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200594 gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200595 LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200596 sep = ",";
597 }
598
599 if (parse_ctx->new_ptmsi_enc) {
600 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200601 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200602 LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200603 sep = ",";
604 }
605
606 if (parse_ctx->imsi) {
607 char mi_buf[200];
608 mi_buf[0] = '\0';
609 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
610 parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200611 LOGPC(DGPRS, log_level, "%s IMSI %s",
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200612 sep, mi_buf);
613 sep = ",";
614 }
615 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200616 LOGPC(DGPRS, log_level, "%s invalidate", sep);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200617 sep = ",";
618 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200619 if (parse_ctx->await_reattach) {
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200620 LOGPC(DGPRS, log_level, "%s re-attach", sep);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200621 sep = ",";
622 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200623
Jacob Erlbeck1c407aa2014-10-09 12:16:17 +0200624 LOGPC(DGPRS, log_level, "\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200625}
626
Jacob Erlbeck9b071352014-10-09 12:04:56 +0200627const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
628 const char *default_msg_name)
629{
630 if (parse_ctx->llc_msg_name)
631 return parse_ctx->llc_msg_name;
632
633 if (parse_ctx->g48_hdr)
634 return "GMM";
635
636 if (parse_ctx->llc)
637 return "LLC";
638
639 if (parse_ctx->bud_hdr)
640 return "BSSGP-UNITDATA";
641
642 if (parse_ctx->bgp_hdr)
643 return "BSSGP";
644
645 return "unknown";
646}