3 * Routines for GMR-1 RACH dissection in wireshark.
4 * Copyright (c) 2012 Sylvain Munaut <tnt@246tNt.com>
7 * [1] ETSI TS 101 376-4-8 V1.3.1 - GMR-1 04.008
8 * [2] ETSI TS 101 376-4-8 V2.2.1 - GMPRS-1 04.008
9 * [3] ETSI TS 101 376-4-8 V3.1.1 - GMR-1 3G 44.008
11 * Especially [1] 10.1.8
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * SPDX-License-Identifier: GPL-2.0-or-later
24 #include <epan/packet.h>
27 void proto_register_gmr1_rach(void);
29 /* GMR-1 RACH proto */
30 static int proto_gmr1_rach
;
32 /* GMR-1 RACH subtrees */
33 static int ett_rach_msg
;
34 static int ett_rach_kls1
;
35 static int ett_rach_kls2
;
36 static int ett_rach_gmprs_type1_kls2
;
37 static int ett_rach_gmprs_type2_kls2
;
38 static int ett_rach_est_cause
;
39 static int ett_rach_dialed_num
;
40 static int ett_rach_gps_pos
;
41 static int ett_rach_gmprs_req_type
;
44 static int hf_rach_prio
;
45 static int hf_rach_est_cause
;
46 static int hf_rach_est_cause_moc
;
47 static int hf_rach_est_cause_pag_resp
;
48 static int hf_rach_num_plan
;
49 static int hf_rach_chan_needed
;
50 static int hf_rach_retry_cnt
;
51 static int hf_rach_precorr
;
52 static int hf_rach_rand_ref
;
54 static int hf_rach_gps_pos_cpi
;
55 static int hf_rach_gps_pos_lat
;
56 static int hf_rach_gps_pos_long
;
58 static int hf_rach_mes_pwr_class
;
59 static int hf_rach_sp_hplmn_id
;
60 static int hf_rach_pd
;
61 static int hf_rach_number
;
62 static int hf_rach_number_grp1
;
63 static int hf_rach_number_grp2
;
64 static int hf_rach_number_grp3
;
65 static int hf_rach_number_grp4
;
66 static int hf_rach_number_grp5
;
67 static int hf_rach_msc_id
;
68 static int hf_rach_gps_timestamp
;
69 static int hf_rach_software_version
;
70 static int hf_rach_spare
;
71 static int hf_rach_gci
;
74 static int hf_rach_number_type
;
76 static int hf_rach_gmprs_term_type
;
77 static int hf_rach_gmprs_radio_prio
;
78 static int hf_rach_gmprs_tlli
;
79 static int hf_rach_gmprs_num_rlc_blks
;
80 static int hf_rach_gmprs_peak_tput
;
81 static int hf_rach_gmprs_dl_peak_tput
;
82 static int hf_rach_gmprs_ul_peak_tput
;
83 static int hf_rach_gmprs_rlc_mode
;
84 static int hf_rach_gmprs_llc_mode
;
85 static int hf_rach_gmprs_spare1
;
86 static int hf_rach_gmprs_spare2
;
87 static int hf_rach_gmprs_spare3
;
88 static int hf_rach_gmprs_reserved1
;
89 static int hf_rach_gmprs_req_type
;
90 static int hf_rach_gmprs_req_type_pag_resp
;
91 static int hf_rach_gmprs_chan_needed
;
94 static const true_false_string rach_prio_tfs
= {
99 static const value_string rach_est_cause_vals
[] = {
100 { 4, "In response to alerting" },
101 { 7, "(GmPRS) Channel Request Type 2" },
102 { 8, "Location update" },
103 { 9, "IMSI Detach" },
104 { 10, "Supplementary Services" },
105 { 11, "Short Message Services" },
106 { 12, "Position Verification" },
107 { 13, "(GmPRS) Attach/RA Update" },
108 { 14, "(GmPRS) Packet Data Transfer" },
109 { 15, "Emergency Call" },
113 static const value_string rach_est_cause_moc_vals
[] = {
114 { 1, "Mobile Originated Call" },
118 static const value_string rach_est_cause_pag_resp_vals
[] = {
119 { 0, "In response to paging" },
123 static const value_string rach_num_plan_vals
[] = {
125 { 1, "ISDN E.164/E.163" },
129 { 8, "National Numbering Plan" },
130 { 9, "Private Numbering Plan" },
131 { 15, "Reserved for Extension" },
135 static const value_string rach_chan_needed_vals
[] = {
143 static const value_string rach_precorr_vals
[] = {
145 { 1, "-47 symbols correction" },
146 { 2, "-94 symbols correction" },
147 { 3, "-141 symbols correction" },
148 { 4, "+141 symbols correction" },
149 { 5, "+94 symbols correction" },
150 { 6, "+47 symbols correction" },
151 { 7, "No precorrection" },
156 dissect_gmr1_rach_kls1(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*root_tree
,
157 int *is_moc
, int *is_pdt
)
159 proto_tree
*tree
= NULL
;
160 proto_item
*ec_item
= NULL
;
161 proto_tree
*ec_tree
= NULL
;
165 tree
= proto_tree_add_subtree(
166 root_tree
, tvb
, 0, 2,
167 ett_rach_kls1
, NULL
, "Class-1 informations");
170 proto_tree_add_item(tree
, hf_rach_prio
,
171 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
173 /* Establishment Cause */
174 ec
= (tvb_get_uint8(tvb
, offset
) >> 1) & 0x1f;
176 *is_moc
= !!(ec
& 0x10);
177 *is_pdt
= (ec
== 14);
182 ec_item
= proto_tree_add_item(tree
, hf_rach_est_cause_moc
,
183 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
185 ec_tree
= proto_item_add_subtree(ec_item
, ett_rach_est_cause
);
187 col_append_str(pinfo
->cinfo
, COL_INFO
, "Mobile Originated Call ");
190 proto_tree_add_item(ec_tree
, hf_rach_num_plan
,
191 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
193 else if ((ec
& 0x1c) == 0x00)
195 /* Paging response */
196 ec_item
= proto_tree_add_item(tree
, hf_rach_est_cause_pag_resp
,
197 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
199 ec_tree
= proto_item_add_subtree(ec_item
, ett_rach_est_cause
);
201 col_append_str(pinfo
->cinfo
, COL_INFO
, "Paging response ");
204 proto_tree_add_item(ec_tree
, hf_rach_chan_needed
,
205 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
209 /* Channel Request Type 2 */
210 proto_tree_add_item(tree
, hf_rach_est_cause
,
211 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
216 proto_tree_add_item(tree
, hf_rach_est_cause
,
217 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
219 col_append_str(pinfo
->cinfo
, COL_INFO
,
220 val_to_str(ec
, rach_est_cause_vals
, "Unknown (%u)"));
224 proto_tree_add_item(tree
, hf_rach_retry_cnt
,
225 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
227 /* Precorrection Indication */
228 proto_tree_add_item(tree
, hf_rach_precorr
,
229 tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
231 /* Random Reference */
232 proto_tree_add_item(tree
, hf_rach_rand_ref
,
233 tvb
, offset
+ 1, 1, ENC_BIG_ENDIAN
);
237 static const true_false_string rach_gps_pos_cpi_tfs
= {
238 "GPS position is current position",
239 "GPS position is old position"
243 rach_gps_pos_lat_fmt(char *s
, uint32_t v
)
247 snprintf(s
, ITEM_LABEL_LENGTH
, "%.5f %s (%d)",
248 abs(sv
) / 2912.7f
, sv
< 0 ? "S" : "N", sv
);
252 rach_gps_pos_long_fmt(char *s
, uint32_t v
)
256 snprintf(s
, ITEM_LABEL_LENGTH
, "%.5f %s (%d)",
257 abs(sv
) / 2912.70555f
, sv
< 0 ? "W" : "E", sv
);
259 /* FIXME: The specs says >0 is West ... but it doesn't seem to
260 * match real world captures !
265 dissect_gmr1_rach_gps_pos(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo _U_
, proto_tree
*tree
)
270 /* Spec says that NULL is latitude == 0x40000 and longitude
271 * is random. But from real capture it seems that
272 * longitude == 0x80000 and latitude random is also NULL pos */
274 lat
= (tvb_get_ntohl(tvb
, offset
) >> 12) & 0x7ffff;
275 lng
= tvb_get_ntohl(tvb
, offset
+ 1) & 0xfffff;
277 if (lat
== 0x40000) {
278 proto_tree_add_int_format(tree
, hf_rach_gps_pos_lat
, tvb
, offset
, 5, lat
,
279 "NULL GPS Position (latitude == 0x40000)");
281 } else if (lng
== 0x80000) {
282 proto_tree_add_int_format(tree
, hf_rach_gps_pos_long
, tvb
, offset
, 5, lng
,
283 "NULL GPS Position (longitude == 0x80000)");
288 proto_tree_add_item(tree
, hf_rach_gps_pos_cpi
,
289 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
292 proto_tree_add_item(tree
, hf_rach_gps_pos_lat
,
293 tvb
, offset
, 3, ENC_BIG_ENDIAN
);
296 proto_tree_add_item(tree
, hf_rach_gps_pos_long
,
297 tvb
, offset
+ 2, 3, ENC_BIG_ENDIAN
);
302 rach_sp_hplmn_id_fmt(char *s
, uint32_t v
)
305 snprintf(s
, ITEM_LABEL_LENGTH
, "%05x (Null)", v
);
306 } else if ((v
& 0xf8000) == 0xf8000) {
307 snprintf(s
, ITEM_LABEL_LENGTH
, "%05x (SP ID %4d)", v
, v
& 0x7fff);
309 snprintf(s
, ITEM_LABEL_LENGTH
, "%05x (HPLMN ID)", v
);
313 static const value_string rach_pd_vals
[] = {
314 { 0, "Fixed to 00 for this version of the protocol" },
322 rach_dialed_num_grp1234_fmt(char *s
, uint32_t v
)
325 snprintf(s
, ITEM_LABEL_LENGTH
, "%03d", v
);
326 } else if (v
== 1023) {
327 snprintf(s
, ITEM_LABEL_LENGTH
,
328 "All digits in the preceding group are valid (%d)", v
);
329 } else if (v
== 1022) {
330 snprintf(s
, ITEM_LABEL_LENGTH
,
331 "First two digits in the preceding group are valid, "
332 "and the third digit (i.e. 0) is padding (%d)", v
);
333 } else if (v
== 1021) {
334 snprintf(s
, ITEM_LABEL_LENGTH
,
335 "First digit in the preceding group is valid, and "
336 "the second and third 0s are padding (%d)", v
);
338 snprintf(s
, ITEM_LABEL_LENGTH
, "Invalid (%d)", v
);
343 rach_dialed_num_grp5_fmt(char *s
, uint32_t v
)
345 if (v
>= 1100 && v
<= 1199) {
346 snprintf(s
, ITEM_LABEL_LENGTH
, "%02d (%d)", v
- 1100, v
);
347 } else if (v
>= 1200 && v
<= 1209) {
348 snprintf(s
, ITEM_LABEL_LENGTH
, "%01d (%d)", v
- 1200, v
);
350 rach_dialed_num_grp1234_fmt(s
, v
);
355 rach_gps_timestamp_fmt(char *s
, uint32_t v
)
358 snprintf(s
, ITEM_LABEL_LENGTH
, ">= 65535 minutes or N/A (%04x)", v
);
360 snprintf(s
, ITEM_LABEL_LENGTH
, "%d minutes (%04x)", v
, v
);
364 static const true_false_string rach_gci_tfs
= {
365 "MES is GPS capable",
366 "MES is not GPS capable"
369 static const true_false_string rach_r_tfs
= {
371 "Retry (see specs for details)"
374 static const true_false_string rach_o_tfs
= {
375 "Retry after failed optimal routing attempt",
379 static const value_string rach_number_type_vals
[] = {
381 { 1, "International Number" },
382 { 2, "National Number" },
383 { 3, "Network-specific Number (operator access)" },
384 { 4, "Dedicated Access short code" },
387 { 7, "(N/A - Not MO Call)" },
391 static const value_string rach_gmprs_term_type_vals
[] = {
392 { 0x09, "Multislot class 2, Power class 1 (type C), Half Duplex, Handheld, Internal antenna, A/Gb interface, L-band" },
393 { 0x0a, "Multislot class 3, Power class 1 (type C), Half Duplex, Handheld, Internal antenna, A/Gb interface, L-band" },
394 { 0x0b, "Multislot class 4, Power class 1 (type C), Half Duplex, Handheld, Internal antenna, A/Gb interface, L-band" },
395 { 0x0c, "Multislot class 1, Power class 1 (type C), Full Duplex, Handheld, Internal antenna, A/Gb interface, L-band" },
396 { 0x0d, "Multislot class 1, Power class 9 (type D), Full Duplex, Fixed, Internal antenna, Gb interface, L-band" },
397 { 0x0e, "Multislot class 1, Power class 9 (type D), Full Duplex, Fixed, Passive external antenna, Gb interface, L-band" },
398 { 0x0f, "Multislot class 1, Power class 9 (type D), Full Duplex, Fixed, Active external antenna, Gb interface, L-band" },
399 { 0x10, "Multislot class 4, Power class 1 (type E), Half Duplex, Handheld, Internal antenna, Iu-PS interface, S-band" },
400 { 0x11, "Multislot class 5, Power class 1 (type E), Half Duplex, Handheld, Internal antenna, Iu-PS interface, S-band" },
401 { 0x12, "Multislot class 5, Power class 1 (type E), Half Duplex, Handheld, Internal antenna, Iu-PS interface, S-band" },
402 { 0x15, "Multislot class 3, Power class 1 (type F), Half Duplex, Handheld, Internal antenna, Iu-PS interface, S-band" },
403 { 0x1a, "Multislot class 3, Power class 1 (type G), Half Duplex, Handheld, Internal antenna, Iu-PS interface, S-band" },
404 { 0x1f, "Multislot class 1, Power class 2 (type H), Full Duplex, Vehicular, Internal antenna, Iu-PS interface, S-band" },
405 { 0x20, "Multislot class 5, Power class 2 (type H), Full Duplex, Vehicular, Internal antenna, Iu-PS interface, S-band" },
406 { 0x24, "Multislot class 1, Power class 9 (type I), Full Duplex, Fixed, Internal antenna, Iu-PS interface, S-band" },
407 { 0x25, "Multislot class 1, Power class 9 (type I), Full Duplex, Fixed, Internal antenna, Iu-PS interface, S-band" },
408 { 0x29, "Multislot class 3, (type J), Half Duplex, Handheld, Internal antenna, Iu-PS interface, L-band" },
409 { 0x2e, "Multislot class 3, (type K), Half Duplex, Handheld, Internal antenna, Iu-PS interface, L-band" },
410 { 0x33, "Multislot class 1, (type L), Full Duplex, Handheld, Internal antenna, Iu-PS interface, L-band" },
411 { 0x38, "Multislot class 1, (type M), Full Duplex, Fixed, External antenna, Iu-PS interface, L-band" },
412 { 0x40, "Reserved" },
413 { 0x48, "Multislot class 1, Power class 8 (type A), Full Duplex, Fixed, Internal antenna, Gb interface, L-band" },
416 static value_string_ext rach_gmprs_term_type_ext_vals
= VALUE_STRING_EXT_INIT(rach_gmprs_term_type_vals
);
418 static const value_string rach_gmprs_radio_prio_vals
[] = {
419 { 0, "Radio Priority 1 (1=highest, 4=lowest)" },
420 { 1, "Radio Priority 2 (1=highest, 4=lowest)" },
421 { 2, "Radio Priority 3 (1=highest, 4=lowest)" },
422 { 3, "Radio Priority 4 (1=highest, 4=lowest)" },
426 static const true_false_string rach_gmprs_rlc_mode_tfs
= {
431 static const true_false_string rach_gmprs_llc_mode_tfs
= {
436 static const value_string rach_gmprs_req_type_vals
[] = {
437 { 0x04, "Suspend - In Response to Alerting for circuit switched services" },
438 { 0x06, "Suspend - MO Call" },
440 { 0x08, "Suspend - Location Update" },
441 { 0x09, "Suspend - IMSI Detach" },
442 { 0x0a, "Suspend - Supplementary Services" },
443 { 0x0b, "Suspend - Short Message Services" },
444 { 0x0f, "Suspend - Emergency Call" },
448 static const value_string rach_gmprs_req_type_pag_resp_vals
[] = {
449 { 0x00, "Suspend - Answer to Paging" },
454 _parse_dialed_number(char *s
, int slen
, tvbuff_t
*tvb
, int offset
)
459 grp
[0] = ((tvb_get_uint8(tvb
, offset
+0) & 0x3f) << 4) |
460 ((tvb_get_uint8(tvb
, offset
+1) & 0xf0) >> 4);
461 grp
[1] = ((tvb_get_uint8(tvb
, offset
+1) & 0x0f) << 6) |
462 ((tvb_get_uint8(tvb
, offset
+2) & 0xfc) >> 2);
463 grp
[2] = ((tvb_get_uint8(tvb
, offset
+2) & 0x03) << 8) |
464 tvb_get_uint8(tvb
, offset
+3);
465 grp
[3] = ((tvb_get_uint8(tvb
, offset
+4) & 0xff) << 2) |
466 ((tvb_get_uint8(tvb
, offset
+5) & 0xc0) >> 6);
467 grp
[4] = ((tvb_get_uint8(tvb
, offset
+5) & 0x3f) << 5) |
468 ((tvb_get_uint8(tvb
, offset
+6) & 0xf8) >> 3);
477 /* All digits of group are valid */
478 rv
+= snprintf(s
+ rv
, slen
- rv
, "%03d", grp
[i
]);
480 else if (grp
[i
+1] == 1023)
482 /* Last group and all digits are valid */
483 rv
+= snprintf(s
+ rv
, slen
- rv
, "%03d", grp
[i
]);
487 else if (grp
[i
+1] == 1022)
489 /* Last group and first two digits are valid */
490 rv
+= snprintf(s
+ rv
, slen
- rv
, "%02d", grp
[i
] / 10);
494 else if (grp
[i
+1] == 1021)
496 /* Last group and first digit is valid */
497 rv
+= snprintf(s
+ rv
, slen
- rv
, "%01d", grp
[i
] / 100);
501 else if ((i
==3) && (grp
[i
+1] >= 1100) && (grp
[i
+1] <= 1209))
503 /* All digits of group are valid */
504 rv
+= snprintf(s
+ rv
, slen
- rv
, "%03d", grp
[i
]);
509 return snprintf(s
, slen
, "(Invalid)");
516 /* All digits are valid */
517 rv
+= snprintf(s
+ rv
, slen
- rv
, "%03d", grp
[4]);
519 else if (grp
[4] >= 1100 && grp
[4] <= 1199)
521 /* Only two digits are valid */
522 rv
+= snprintf(s
+ rv
, slen
- rv
, "%02d", grp
[4] - 1100);
524 else if (grp
[4] >= 1200 && grp
[4] <= 1209)
526 /* Only one digit is valid */
527 rv
+= snprintf(s
+ rv
, slen
- rv
, "%01d", grp
[4] - 1200);
532 return snprintf(s
, slen
, "(Invalid)");
540 dissect_gmr1_rach_kls2(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*root_tree
,
543 proto_tree
*tree
= NULL
;
544 proto_item
*dialed_num_item
= NULL
;
545 proto_tree
*dialed_num_tree
= NULL
, *gps_pos_tree
= NULL
;
548 tree
= proto_tree_add_subtree(
549 root_tree
, tvb
, 2, 16,
550 ett_rach_kls2
, NULL
, "Class-2 informations");
552 /* MES Power Class */
553 proto_tree_add_item(tree
, hf_rach_mes_pwr_class
,
554 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
557 proto_tree_add_item(tree
, hf_rach_sp_hplmn_id
,
558 tvb
, offset
, 3, ENC_BIG_ENDIAN
);
561 proto_tree_add_item(tree
, hf_rach_pd
,
562 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
565 /* Is it a MO call ? */
571 _parse_dialed_number(s
, sizeof(s
), tvb
, offset
+ 3);
573 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", s
);
576 dialed_num_item
= proto_tree_add_string(
577 tree
, hf_rach_number
, tvb
, offset
+ 3, 7, s
);
579 dialed_num_tree
= proto_item_add_subtree(
580 dialed_num_item
, ett_rach_dialed_num
);
583 proto_tree_add_item(dialed_num_tree
, hf_rach_number_grp1
,
584 tvb
, offset
+ 3, 2, ENC_BIG_ENDIAN
);
587 proto_tree_add_item(dialed_num_tree
, hf_rach_number_grp2
,
588 tvb
, offset
+ 4, 2, ENC_BIG_ENDIAN
);
591 proto_tree_add_item(dialed_num_tree
, hf_rach_number_grp3
,
592 tvb
, offset
+ 5, 2, ENC_BIG_ENDIAN
);
595 proto_tree_add_item(dialed_num_tree
, hf_rach_number_grp4
,
596 tvb
, offset
+ 7, 2, ENC_BIG_ENDIAN
);
599 proto_tree_add_item(dialed_num_tree
, hf_rach_number_grp5
,
600 tvb
, offset
+ 8, 2, ENC_BIG_ENDIAN
);
603 proto_tree_add_item(tree
, hf_rach_msc_id
,
604 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
607 proto_tree_add_item(tree
, hf_rach_gps_timestamp
,
608 tvb
, offset
+ 4, 2, ENC_BIG_ENDIAN
);
610 /* Software version number */
611 proto_tree_add_item(tree
, hf_rach_software_version
,
612 tvb
, offset
+ 6, 1, ENC_BIG_ENDIAN
);
615 proto_tree_add_item(tree
, hf_rach_spare
,
616 tvb
, offset
+ 6, 1, ENC_BIG_ENDIAN
);
620 proto_tree_add_item(tree
, hf_rach_gci
,
621 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
624 proto_tree_add_item(tree
, hf_rach_r
,
625 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
628 proto_tree_add_item(tree
, hf_rach_o
,
629 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
632 gps_pos_tree
= proto_tree_add_subtree(
633 tree
, tvb
, offset
+ 10, 5,
634 ett_rach_gps_pos
, NULL
, "GPS Position");
636 dissect_gmr1_rach_gps_pos(tvb
, offset
+ 10, pinfo
, gps_pos_tree
);
639 proto_tree_add_item(tree
, hf_rach_number_type
,
640 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
643 static const crumb_spec_t rach_gmprs_type1_term_type_crumbs
[] = {
649 static const crumb_spec_t rach_gmprs_num_rlc_blks_crumbs
[] = {
656 dissect_gmprs_rach_type1_kls2(tvbuff_t
*tvb
, int offset
,
657 packet_info
*pinfo
, proto_tree
*root_tree
, int is_pdt
)
659 proto_tree
*tree
= NULL
;
660 proto_tree
*gps_pos_tree
= NULL
;
665 tree
= proto_tree_add_subtree(
666 root_tree
, tvb
, 2, 16,
667 ett_rach_gmprs_type1_kls2
, NULL
, "GmPRS Type-1 Class-2 informations");
669 /* GmPRS Terminal Type */
670 proto_tree_add_split_bits_item_ret_val(
671 tree
, hf_rach_gmprs_term_type
,
673 rach_gmprs_type1_term_type_crumbs
,
676 term_type
= ((tvb_get_uint8(tvb
, offset
) >> 1) & 0x78 ) |
677 ( tvb_get_uint8(tvb
, offset
+ 3) & 0x07);
679 is_class_d
= (term_type
== 0x0d) ||
680 (term_type
== 0x0e) ||
683 /* Class D terminal ? */
685 /* DL Peak Throughput */
686 proto_tree_add_item(tree
, hf_rach_gmprs_dl_peak_tput
,
687 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
690 proto_tree_add_item(tree
, hf_rach_gmprs_reserved1
,
691 tvb
, offset
, 2, ENC_BIG_ENDIAN
);
694 proto_tree_add_item(tree
, hf_rach_sp_hplmn_id
,
695 tvb
, offset
, 3, ENC_BIG_ENDIAN
);
699 proto_tree_add_item(tree
, hf_rach_gmprs_radio_prio
,
700 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
703 proto_tree_add_item(tree
, hf_rach_gmprs_spare1
,
704 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
707 proto_tree_add_item(tree
, hf_rach_pd
,
708 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
711 proto_tree_add_item(tree
, hf_rach_gmprs_tlli
,
712 tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
714 /* Is it for Packet Data Transfer ? */
716 /* Number of RLC blocks */
717 proto_tree_add_split_bits_item_ret_val(
718 tree
, hf_rach_gmprs_num_rlc_blks
,
719 tvb
, (offset
+ 8) << 3,
720 rach_gmprs_num_rlc_blks_crumbs
,
723 /* (UL) Peak Throughput */
724 proto_tree_add_item(tree
, is_class_d
?
725 hf_rach_gmprs_ul_peak_tput
:
726 hf_rach_gmprs_peak_tput
,
727 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
730 proto_tree_add_item(tree
, hf_rach_gmprs_spare2
,
731 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
734 proto_tree_add_item(tree
, hf_rach_gps_timestamp
,
735 tvb
, offset
+ 8, 2, ENC_BIG_ENDIAN
);
739 gps_pos_tree
= proto_tree_add_subtree(
740 tree
, tvb
, offset
+ 10, 5,
741 ett_rach_gps_pos
, NULL
, "GPS Position");
743 dissect_gmr1_rach_gps_pos(tvb
, offset
+ 10, pinfo
, gps_pos_tree
);
746 /* Off-the-air data shows bit is sometimes set even
747 * when not a PDT ... */
748 proto_tree_add_item(tree
, hf_rach_gmprs_rlc_mode
,
749 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
752 /* Off-the-air data shows bit is sometimes set even
753 * when not a PDT ... */
754 proto_tree_add_item(tree
, hf_rach_gmprs_llc_mode
,
755 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
758 proto_tree_add_item(tree
, hf_rach_gmprs_spare3
,
759 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
762 static const crumb_spec_t rach_gmprs_type2_term_type_crumbs
[] = {
769 dissect_gmprs_rach_type2_kls2(tvbuff_t
*tvb
, int offset
,
770 packet_info
*pinfo
, proto_tree
*root_tree
)
772 proto_tree
*tree
= NULL
;
773 proto_tree
*gps_pos_tree
= NULL
;
777 tree
= proto_tree_add_subtree(
778 root_tree
, tvb
, 2, 16,
779 ett_rach_gmprs_type2_kls2
, NULL
, "GmPRS Type-2 Class-2 informations");
781 /* GmPRS Terminal type */
782 proto_tree_add_split_bits_item_ret_val(
783 tree
, hf_rach_gmprs_term_type
,
785 rach_gmprs_type2_term_type_crumbs
,
789 proto_tree_add_item(tree
, hf_rach_sp_hplmn_id
,
790 tvb
, offset
, 3, ENC_BIG_ENDIAN
);
793 proto_tree_add_item(tree
, hf_rach_pd
,
794 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
797 proto_tree_add_item(tree
, hf_rach_msc_id
,
798 tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
801 proto_tree_add_item(tree
, hf_rach_gmprs_tlli
,
802 tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
805 req_type
= tvb_get_uint8(tvb
, offset
+ 8) & 0x1f;
807 if ((req_type
& 0x1c) == 0) {
808 /* Paging response */
809 proto_item
*rt_item
= proto_tree_add_item(
810 tree
, hf_rach_gmprs_req_type_pag_resp
,
811 tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
813 proto_tree
*rt_tree
= proto_item_add_subtree(rt_item
, ett_rach_gmprs_req_type
);
815 col_append_str(pinfo
->cinfo
, COL_INFO
, "Paging response ");
818 proto_tree_add_item(rt_tree
, hf_rach_gmprs_chan_needed
,
819 tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
822 proto_tree_add_item(tree
, hf_rach_gmprs_req_type
,
823 tvb
, offset
+ 8, 1, ENC_BIG_ENDIAN
);
825 col_append_str(pinfo
->cinfo
, COL_INFO
,
826 val_to_str(req_type
, rach_gmprs_req_type_vals
, "Unknown (%u)"));
829 /* Software version number */
830 proto_tree_add_item(tree
, hf_rach_software_version
,
831 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
834 proto_tree_add_item(tree
, hf_rach_spare
,
835 tvb
, offset
+ 9, 1, ENC_BIG_ENDIAN
);
838 gps_pos_tree
= proto_tree_add_subtree(
839 tree
, tvb
, offset
+ 10, 5,
840 ett_rach_gps_pos
, NULL
, "GPS Position");
842 dissect_gmr1_rach_gps_pos(tvb
, offset
+ 10, pinfo
, gps_pos_tree
);
845 proto_tree_add_item(tree
, hf_rach_gci
,
846 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
849 proto_tree_add_item(tree
, hf_rach_r
,
850 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
853 proto_tree_add_item(tree
, hf_rach_o
,
854 tvb
, offset
+ 15, 1, ENC_BIG_ENDIAN
);
858 dissect_gmr1_rach(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
860 const int RACH_IE_CLASS1
= (1 << 0);
861 const int RACH_IE_CLASS2_GMR1
= (1 << 1);
862 const int RACH_IE_CLASS2_GMPRS_TYPE1
= (1 << 2);
863 const int RACH_IE_CLASS2_GMPRS_TYPE2
= (1 << 3);
865 proto_item
*rach_item
;
866 proto_tree
*rach_tree
;
868 int len
, is_moc
, is_pdt
, ies
;
872 len
= tvb_reported_length(tvb
);
874 desc
= "GMR-1 Channel Request (RACH)";
878 uint8_t ec
= (tvb_get_uint8(tvb
, 0) >> 1) & 0x1f;
880 ies
|= RACH_IE_CLASS1
;
882 if ((ec
== 13) || (ec
== 14)) {
883 desc
= "GMR-1 GmPRS Channel Request Type 1 (RACH)";
884 ies
|= RACH_IE_CLASS2_GMPRS_TYPE1
;
885 } else if (ec
== 7) {
886 desc
= "GMR-1 GmPRS Channel Request Type 2 (RACH)";
887 ies
|= RACH_IE_CLASS2_GMPRS_TYPE2
;
888 #if 0 /* Fix -Wduplicated-branches */
889 } else if (ec
== 12) {
890 /* Position verification exists in both GMR-1 and GmPRS-1
891 * I have no idea how to differentiate them ... but from
892 * off-the-air data, it seems it used the GMR-1 format */
893 ies
|= RACH_IE_CLASS2_GMR1
;
896 ies
|= RACH_IE_CLASS2_GMR1
;
900 rach_item
= proto_tree_add_protocol_format(
901 tree
, proto_gmr1_rach
, tvb
, 0, len
, "%s", desc
);
902 rach_tree
= proto_item_add_subtree(rach_item
, ett_rach_msg
);
905 col_append_str(pinfo
->cinfo
, COL_INFO
, "(Invalid)");
906 call_data_dissector(tvb
, pinfo
, tree
);
907 return tvb_captured_length(tvb
);
910 col_append_str(pinfo
->cinfo
, COL_INFO
, "(RACH) ");
912 if (ies
& RACH_IE_CLASS1
)
913 dissect_gmr1_rach_kls1(tvb
, 0, pinfo
, rach_tree
, &is_moc
, &is_pdt
);
915 if (ies
& RACH_IE_CLASS2_GMR1
)
916 dissect_gmr1_rach_kls2(tvb
, 2, pinfo
, rach_tree
, is_moc
);
918 if (ies
& RACH_IE_CLASS2_GMPRS_TYPE1
)
919 dissect_gmprs_rach_type1_kls2(tvb
, 2, pinfo
, rach_tree
, is_pdt
);
921 if (ies
& RACH_IE_CLASS2_GMPRS_TYPE2
)
922 dissect_gmprs_rach_type2_kls2(tvb
, 2, pinfo
, rach_tree
);
924 return tvb_captured_length(tvb
);
928 proto_register_gmr1_rach(void)
930 static hf_register_info hf
[] = {
932 { "Priority", "gmr1.rach.priority",
933 FT_BOOLEAN
, 8, TFS(&rach_prio_tfs
), 0x01,
936 { &hf_rach_est_cause
,
937 { "Establishment Cause", "gmr1.rach.est_cause",
938 FT_UINT8
, BASE_HEX
, VALS(rach_est_cause_vals
), 0x3e,
941 { &hf_rach_est_cause_moc
,
942 { "Establishment Cause", "gmr1.rach.est_cause.moc",
943 FT_UINT8
, BASE_HEX
, VALS(rach_est_cause_moc_vals
), 0x20,
946 { &hf_rach_est_cause_pag_resp
,
947 { "Establishment Cause", "gmr1.rach.est_cause.pag_resp",
948 FT_UINT8
, BASE_HEX
, VALS(rach_est_cause_pag_resp_vals
), 0x38,
952 { "Numbering Plan Identification", "gmr1.rach.numbering_plan",
953 FT_UINT8
, BASE_DEC
, VALS(rach_num_plan_vals
), 0x1e,
956 { &hf_rach_chan_needed
,
957 { "Channel Needed", "gmr1.rach.chan_needed",
958 FT_UINT8
, BASE_DEC
, VALS(rach_chan_needed_vals
), 0x06,
959 "Echoed from Paging Request", HFILL
}
961 { &hf_rach_retry_cnt
,
962 { "Retry Counter", "gmr1.rach.retry_counter",
963 FT_UINT8
, BASE_DEC
, NULL
, 0xc0,
964 "Retransmission count for current access attempt", HFILL
}
967 { "Precorrection Indication", "gmr1.rach.precorr_ind",
968 FT_UINT8
, BASE_DEC
, VALS(rach_precorr_vals
), 0xe0,
969 "This is the timing correction applied to RACH while "
970 "sending this message. See GMR 05.010.", HFILL
}
973 { "Random Reference", "gmr1.rach.random_reference",
974 FT_UINT8
, BASE_HEX
, NULL
, 0x1f,
975 "A random number of 5 bits", HFILL
}
977 { &hf_rach_gps_pos_cpi
,
978 { "CPI", "gmr1.rach.gps_pos.cpi",
979 FT_BOOLEAN
, 8, TFS(&rach_gps_pos_cpi_tfs
), 0x80,
980 "Current Position Indicator", HFILL
}
982 { &hf_rach_gps_pos_lat
,
983 { "Latitude", "gmr1.rach.gps_pos.latitude",
984 FT_INT24
, BASE_CUSTOM
, CF_FUNC(rach_gps_pos_lat_fmt
), 0x7ffff0,
987 { &hf_rach_gps_pos_long
,
988 { "Longitude", "gmr1.rach.gps_pos.longitude",
989 FT_INT24
, BASE_CUSTOM
, CF_FUNC(rach_gps_pos_long_fmt
), 0x0fffff,
992 { &hf_rach_mes_pwr_class
,
993 { "MES Power Class", "gmr1.rach.mes_power_class",
994 FT_UINT8
, BASE_DEC
, NULL
, 0xf0,
995 "See GMR 05.005 for infos", HFILL
}
997 { &hf_rach_sp_hplmn_id
,
998 { "SP/HPLMN ID", "gmr1.rach.sp_hplmn_id",
999 FT_UINT24
, BASE_CUSTOM
, CF_FUNC(rach_sp_hplmn_id_fmt
), 0x0fffff,
1003 { "PD", "gmr1.rach.pd",
1004 FT_UINT8
, BASE_DEC
, VALS(rach_pd_vals
), 0xc0,
1005 "Protocol Discriminator", HFILL
}
1008 { "Dialed Number", "gmr1.rach.number",
1009 FT_STRING
, BASE_NONE
, NULL
, 0x00,
1012 { &hf_rach_number_grp1
,
1013 { "Group 1", "gmr1.rach.number.grp1",
1014 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_dialed_num_grp1234_fmt
), 0x3ff0,
1017 { &hf_rach_number_grp2
,
1018 { "Group 2", "gmr1.rach.number.grp2",
1019 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_dialed_num_grp1234_fmt
), 0x0ffc,
1022 { &hf_rach_number_grp3
,
1023 { "Group 3", "gmr1.rach.number.grp3",
1024 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_dialed_num_grp1234_fmt
), 0x03ff,
1027 { &hf_rach_number_grp4
,
1028 { "Group 4", "gmr1.rach.number.grp4",
1029 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_dialed_num_grp1234_fmt
), 0xffc0,
1032 { &hf_rach_number_grp5
,
1033 { "Group 5", "gmr1.rach.number.grp5",
1034 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_dialed_num_grp5_fmt
), 0x3ff8,
1038 { "MSC ID", "gmr1.rach.msc_id",
1039 FT_UINT8
, BASE_DEC
, NULL
, 0x3f,
1042 { &hf_rach_gps_timestamp
,
1043 { "GPS Timestamp", "gmr1.rach.gps_timestamp",
1044 FT_UINT16
, BASE_CUSTOM
, CF_FUNC(rach_gps_timestamp_fmt
), 0xffff,
1047 { &hf_rach_software_version
,
1048 { "Software Version", "gmr1.rach.software_version",
1049 FT_UINT8
, BASE_DEC
, NULL
, 0xfe,
1053 { "Spare", "gmr1.rach.spare",
1054 FT_UINT32
, BASE_DEC
, NULL
, 0x01fffff8,
1058 { "GCI", "gmr1.rach.gci",
1059 FT_BOOLEAN
, 8, TFS(&rach_gci_tfs
), 0x01,
1060 "GPS Capability Indicator", HFILL
}
1063 { "R", "gmr1.rach.r",
1064 FT_BOOLEAN
, 8, TFS(&rach_r_tfs
), 0x02,
1065 "See GMR 04.008 10.1.8 for full description" , HFILL
}
1068 { "O", "gmr1.rach.o",
1069 FT_BOOLEAN
, 8, TFS(&rach_o_tfs
), 0x04,
1070 "See GMR 04.008 10.1.8 for full description", HFILL
}
1072 { &hf_rach_number_type
,
1073 { "Number Type", "gmr1.rach.number_type",
1074 FT_UINT8
, BASE_DEC
, VALS(rach_number_type_vals
), 0x07,
1075 "For MO Call only", HFILL
}
1077 { &hf_rach_gmprs_term_type
,
1078 { "GmPRS Terminal Type", "gmr1.rach.gmprs_term_type",
1079 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &rach_gmprs_term_type_ext_vals
, 0x00,
1080 "See GMR-1 3G 45.002 Annex C for infos", HFILL
}
1082 { &hf_rach_gmprs_radio_prio
,
1083 { "Radio Priority", "gmr1.rach.gmprs_radio_prio",
1084 FT_UINT8
, BASE_DEC
, VALS(rach_gmprs_radio_prio_vals
), 0x18,
1085 "See GMPRS-1 04.060 for infos", HFILL
}
1087 { &hf_rach_gmprs_tlli
,
1088 { "TLLI", "gmr1.rach.gmprs_tlli",
1089 FT_UINT32
, BASE_HEX
, NULL
, 0x00,
1090 "See GMPRS-1 04.060 for infos", HFILL
}
1092 { &hf_rach_gmprs_num_rlc_blks
,
1093 { "Number of RLC blocks", "gmr1.rach.gmprs_num_rlc_blks",
1094 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
1095 "See GMPRS-1 04.060 12.31 for infos", HFILL
}
1097 { &hf_rach_gmprs_peak_tput
,
1098 { "Peak Throughput", "gmr1.rach.gmprs_peak_tput",
1099 FT_UINT8
, BASE_DEC
, NULL
, 0x3c,
1100 "See GMPRS-1 04.060 for infos", HFILL
}
1102 { &hf_rach_gmprs_dl_peak_tput
,
1103 { "DL Peak Throughput", "gmr1.rach.gmprs_dl_peak_tput",
1104 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
1105 "See 3GPP TS 23.060 for infos", HFILL
}
1107 { &hf_rach_gmprs_ul_peak_tput
,
1108 { "UL Peak Throughput", "gmr1.rach.gmprs_ul_peak_tput",
1109 FT_UINT8
, BASE_DEC
, NULL
, 0x3c,
1110 "See 3GPP TS 23.060 for infos", HFILL
}
1112 { &hf_rach_gmprs_rlc_mode
,
1113 { "RLC mode", "gmr1.rach.gmprs_rlc_mode",
1114 FT_BOOLEAN
, 8, TFS(&rach_gmprs_rlc_mode_tfs
), 0x01,
1117 { &hf_rach_gmprs_llc_mode
,
1118 { "LLC mode", "gmr1.rach.gmprs_llc_mode",
1119 FT_BOOLEAN
, 8, TFS(&rach_gmprs_llc_mode_tfs
), 0x02,
1122 { &hf_rach_gmprs_spare1
,
1123 { "Spare", "gmr1.rach.gmprs_spare1",
1124 FT_UINT8
, BASE_DEC
, NULL
, 0x20,
1127 { &hf_rach_gmprs_spare2
,
1128 { "Spare", "gmr1.rach.gmprs_spare2",
1129 FT_UINT8
, BASE_DEC
, NULL
, 0xc0,
1132 { &hf_rach_gmprs_spare3
,
1133 { "Spare", "gmr1.rach.gmprs_spare3",
1134 FT_UINT8
, BASE_DEC
, NULL
, 0x04,
1137 { &hf_rach_gmprs_reserved1
,
1138 { "Reserved", "gmr1.rach.gmprs_reserved1",
1139 FT_UINT16
, BASE_HEX
, NULL
, 0xffff,
1142 { &hf_rach_gmprs_req_type
,
1143 { "Request Type", "gmr1.rach.gmprs_req_type",
1144 FT_UINT8
, BASE_DEC
, VALS(rach_gmprs_req_type_vals
), 0x1f,
1147 { &hf_rach_gmprs_req_type_pag_resp
,
1148 { "Request Type", "gmr1.rach.gmprs_req_type.pag_resp",
1149 FT_UINT8
, BASE_DEC
, VALS(rach_gmprs_req_type_pag_resp_vals
), 0x1c,
1152 { &hf_rach_gmprs_chan_needed
,
1153 { "Channel Needed", "gmr1.rach.gmprs_chan_needed",
1154 FT_UINT8
, BASE_DEC
, VALS(rach_chan_needed_vals
), 0x03,
1155 "Echoed from Paging Request", HFILL
}
1159 static int *ett
[] = {
1163 &ett_rach_gmprs_type1_kls2
,
1164 &ett_rach_gmprs_type2_kls2
,
1165 &ett_rach_est_cause
,
1166 &ett_rach_dialed_num
,
1168 &ett_rach_gmprs_req_type
,
1171 proto_gmr1_rach
= proto_register_protocol("GEO-Mobile Radio (1) RACH", "GMR-1 RACH", "gmr1.rach");
1173 proto_register_field_array(proto_gmr1_rach
, hf
, array_length(hf
));
1174 proto_register_subtree_array(ett
, array_length(ett
));
1176 register_dissector("gmr1_rach", dissect_gmr1_rach
, proto_gmr1_rach
);
1180 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1185 * indent-tabs-mode: t
1188 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1189 * :indentSize=8:tabSize=8:noTabs=false: