Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gmr1_rach.c
blob9c8b4d9f70e944ff96e43d574d8da50b9503b2ab
1 /* packet-gmr1_rach.c
3 * Routines for GMR-1 RACH dissection in wireshark.
4 * Copyright (c) 2012 Sylvain Munaut <tnt@246tNt.com>
6 * References:
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
20 #include "config.h"
22 #include <stdlib.h>
24 #include <epan/packet.h>
25 #include <epan/tfs.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;
43 /* Fields */
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;
72 static int hf_rach_r;
73 static int hf_rach_o;
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 = {
95 "Priority Call",
96 "Normal Call"
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" },
110 { 0, NULL }
113 static const value_string rach_est_cause_moc_vals[] = {
114 { 1, "Mobile Originated Call" },
115 { 0, NULL }
118 static const value_string rach_est_cause_pag_resp_vals[] = {
119 { 0, "In response to paging" },
120 { 0, NULL }
123 static const value_string rach_num_plan_vals[] = {
124 { 0, "Unknown" },
125 { 1, "ISDN E.164/E.163" },
126 { 2, "Not Used" },
127 { 3, "X.121" },
128 { 4, "Telex F.69" },
129 { 8, "National Numbering Plan" },
130 { 9, "Private Numbering Plan" },
131 { 15, "Reserved for Extension" },
132 { 0, NULL }
135 static const value_string rach_chan_needed_vals[] = {
136 { 0, "any" },
137 { 1, "SDCCH" },
138 { 2, "TCH3" },
139 { 3, "spare" },
140 { 0, NULL }
143 static const value_string rach_precorr_vals[] = {
144 { 0, "Reserved" },
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" },
152 { 0, NULL }
155 static void
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;
162 uint8_t ec;
164 /* Tree */
165 tree = proto_tree_add_subtree(
166 root_tree, tvb, 0, 2,
167 ett_rach_kls1, NULL, "Class-1 informations");
169 /* Priority */
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);
179 if (ec & 0x10)
181 /* MOC */
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 ");
189 /* Numbering plan */
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 ");
203 /* Channel Needed */
204 proto_tree_add_item(ec_tree, hf_rach_chan_needed,
205 tvb, offset, 1, ENC_BIG_ENDIAN);
207 else if (ec == 7)
209 /* Channel Request Type 2 */
210 proto_tree_add_item(tree, hf_rach_est_cause,
211 tvb, offset, 1, ENC_BIG_ENDIAN);
213 else
215 /* Other */
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)"));
223 /* Retry counter */
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"
242 static void
243 rach_gps_pos_lat_fmt(char *s, uint32_t v)
245 int32_t sv = v;
247 snprintf(s, ITEM_LABEL_LENGTH, "%.5f %s (%d)",
248 abs(sv) / 2912.7f, sv < 0 ? "S" : "N", sv);
251 static void
252 rach_gps_pos_long_fmt(char *s, uint32_t v)
254 int32_t sv = 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 !
264 static void
265 dissect_gmr1_rach_gps_pos(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
267 uint32_t lat, lng;
269 /* Check for NULL */
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)");
280 return;
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)");
284 return;
287 /* CPI */
288 proto_tree_add_item(tree, hf_rach_gps_pos_cpi,
289 tvb, offset, 1, ENC_BIG_ENDIAN);
291 /* Latitude */
292 proto_tree_add_item(tree, hf_rach_gps_pos_lat,
293 tvb, offset, 3, ENC_BIG_ENDIAN);
295 /* Longitude */
296 proto_tree_add_item(tree, hf_rach_gps_pos_long,
297 tvb, offset + 2, 3, ENC_BIG_ENDIAN);
301 static void
302 rach_sp_hplmn_id_fmt(char *s, uint32_t v)
304 if (v == 0xfffff) {
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);
308 } else {
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" },
315 { 1, "Reserved" },
316 { 2, "Reserved" },
317 { 3, "Reserved" },
318 { 0, NULL }
321 static void
322 rach_dialed_num_grp1234_fmt(char *s, uint32_t v)
324 if (v <= 999) {
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);
337 } else {
338 snprintf(s, ITEM_LABEL_LENGTH, "Invalid (%d)", v);
342 static void
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);
349 } else {
350 rach_dialed_num_grp1234_fmt(s, v);
354 static void
355 rach_gps_timestamp_fmt(char *s, uint32_t v)
357 if (v == 0xffff) {
358 snprintf(s, ITEM_LABEL_LENGTH, ">= 65535 minutes or N/A (%04x)", v);
359 } else {
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 = {
370 "Normal case",
371 "Retry (see specs for details)"
374 static const true_false_string rach_o_tfs = {
375 "Retry after failed optimal routing attempt",
376 "Normal case"
379 static const value_string rach_number_type_vals[] = {
380 { 0, "Unknown" },
381 { 1, "International Number" },
382 { 2, "National Number" },
383 { 3, "Network-specific Number (operator access)" },
384 { 4, "Dedicated Access short code" },
385 { 5, "Reserved" },
386 { 6, "Reserved" },
387 { 7, "(N/A - Not MO Call)" },
388 { 0, NULL }
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" },
414 { 0, NULL }
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)" },
423 { 0, NULL }
426 static const true_false_string rach_gmprs_rlc_mode_tfs = {
427 "Unacknowledged",
428 "Acknowledged"
431 static const true_false_string rach_gmprs_llc_mode_tfs = {
432 "Data packets",
433 "SACK/ACK packets"
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" },
439 { 0x07, "Resume" },
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" },
445 { 0, NULL }
448 static const value_string rach_gmprs_req_type_pag_resp_vals[] = {
449 { 0x00, "Suspend - Answer to Paging" },
450 { 0, NULL }
453 static int
454 _parse_dialed_number(char *s, int slen, tvbuff_t *tvb, int offset)
456 uint16_t grp[5];
457 int rv, i, done;
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);
470 rv = 0;
471 done = 0;
473 for (i=0; i<4; i++)
475 if (grp[i+1] <= 999)
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]);
484 done = 1;
485 break;
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);
491 done = 1;
492 break;
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);
498 done = 1;
499 break;
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]);
506 else
508 /* Invalid */
509 return snprintf(s, slen, "(Invalid)");
513 if (!done) {
514 if (grp[4] <= 999)
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);
529 else
531 /* Invalid */
532 return snprintf(s, slen, "(Invalid)");
536 return rv;
539 static void
540 dissect_gmr1_rach_kls2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *root_tree,
541 int is_moc)
543 proto_tree *tree = NULL;
544 proto_item *dialed_num_item = NULL;
545 proto_tree *dialed_num_tree = NULL, *gps_pos_tree = NULL;
547 /* Tree */
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);
556 /* SP/HPLMN ID */
557 proto_tree_add_item(tree, hf_rach_sp_hplmn_id,
558 tvb, offset, 3, ENC_BIG_ENDIAN);
560 /* PD */
561 proto_tree_add_item(tree, hf_rach_pd,
562 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
565 /* Is it a MO call ? */
566 if (is_moc) {
567 char s[32];
569 /* Dialed number */
570 /* Parse number */
571 _parse_dialed_number(s, sizeof(s), tvb, offset + 3);
573 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", s);
575 /* Base item */
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);
582 /* Group 1 */
583 proto_tree_add_item(dialed_num_tree, hf_rach_number_grp1,
584 tvb, offset + 3, 2, ENC_BIG_ENDIAN);
586 /* Group 2 */
587 proto_tree_add_item(dialed_num_tree, hf_rach_number_grp2,
588 tvb, offset + 4, 2, ENC_BIG_ENDIAN);
590 /* Group 3 */
591 proto_tree_add_item(dialed_num_tree, hf_rach_number_grp3,
592 tvb, offset + 5, 2, ENC_BIG_ENDIAN);
594 /* Group 4 */
595 proto_tree_add_item(dialed_num_tree, hf_rach_number_grp4,
596 tvb, offset + 7, 2, ENC_BIG_ENDIAN);
598 /* Group 5 */
599 proto_tree_add_item(dialed_num_tree, hf_rach_number_grp5,
600 tvb, offset + 8, 2, ENC_BIG_ENDIAN);
601 } else {
602 /* MSC ID */
603 proto_tree_add_item(tree, hf_rach_msc_id,
604 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
606 /* GPS timestamp */
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);
614 /* Spare */
615 proto_tree_add_item(tree, hf_rach_spare,
616 tvb, offset + 6, 1, ENC_BIG_ENDIAN);
619 /* GCI */
620 proto_tree_add_item(tree, hf_rach_gci,
621 tvb, offset + 9, 1, ENC_BIG_ENDIAN);
623 /* R */
624 proto_tree_add_item(tree, hf_rach_r,
625 tvb, offset + 9, 1, ENC_BIG_ENDIAN);
627 /* O */
628 proto_tree_add_item(tree, hf_rach_o,
629 tvb, offset + 9, 1, ENC_BIG_ENDIAN);
631 /* GPS Position */
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);
638 /* Number type */
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[] = {
644 { 0, 4 },
645 { 29, 3 },
646 { 0, 0 }
649 static const crumb_spec_t rach_gmprs_num_rlc_blks_crumbs[] = {
650 { 0, 8 },
651 { 14, 2 },
652 { 0, 0 }
655 static void
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;
661 uint8_t term_type;
662 int is_class_d;
664 /* Tree */
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,
672 tvb, offset << 3,
673 rach_gmprs_type1_term_type_crumbs,
674 NULL);
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) ||
681 (term_type == 0x0f);
683 /* Class D terminal ? */
684 if (is_class_d) {
685 /* DL Peak Throughput */
686 proto_tree_add_item(tree, hf_rach_gmprs_dl_peak_tput,
687 tvb, offset, 1, ENC_BIG_ENDIAN);
689 /* Reserved */
690 proto_tree_add_item(tree, hf_rach_gmprs_reserved1,
691 tvb, offset, 2, ENC_BIG_ENDIAN);
692 } else {
693 /* SP/HPLMN ID */
694 proto_tree_add_item(tree, hf_rach_sp_hplmn_id,
695 tvb, offset, 3, ENC_BIG_ENDIAN);
698 /* Radio Priority */
699 proto_tree_add_item(tree, hf_rach_gmprs_radio_prio,
700 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
702 /* Spare */
703 proto_tree_add_item(tree, hf_rach_gmprs_spare1,
704 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
706 /* PD */
707 proto_tree_add_item(tree, hf_rach_pd,
708 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
710 /* TLLI */
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 ? */
715 if (is_pdt) {
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,
721 NULL);
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);
729 /* Spare */
730 proto_tree_add_item(tree, hf_rach_gmprs_spare2,
731 tvb, offset + 9, 1, ENC_BIG_ENDIAN);
732 } else {
733 /* GPS timestamp */
734 proto_tree_add_item(tree, hf_rach_gps_timestamp,
735 tvb, offset + 8, 2, ENC_BIG_ENDIAN);
738 /* GPS Position */
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);
745 /* RLC mode */
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);
751 /* LLC mode */
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);
757 /* Spare */
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[] = {
763 { 0, 4 },
764 { 64, 3 },
765 { 0, 0 }
768 static void
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;
774 uint8_t req_type;
776 /* Tree */
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,
784 tvb, offset << 3,
785 rach_gmprs_type2_term_type_crumbs,
786 NULL);
788 /* SP/HPLMN ID */
789 proto_tree_add_item(tree, hf_rach_sp_hplmn_id,
790 tvb, offset, 3, ENC_BIG_ENDIAN);
792 /* PD */
793 proto_tree_add_item(tree, hf_rach_pd,
794 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
796 /* MSC ID */
797 proto_tree_add_item(tree, hf_rach_msc_id,
798 tvb, offset + 3, 1, ENC_BIG_ENDIAN);
800 /* TLLI */
801 proto_tree_add_item(tree, hf_rach_gmprs_tlli,
802 tvb, offset + 4, 4, ENC_BIG_ENDIAN);
804 /* Request type */
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 ");
817 /* Channel Needed */
818 proto_tree_add_item(rt_tree, hf_rach_gmprs_chan_needed,
819 tvb, offset + 8, 1, ENC_BIG_ENDIAN);
820 } else {
821 /* Other */
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);
833 /* Spare */
834 proto_tree_add_item(tree, hf_rach_spare,
835 tvb, offset + 9, 1, ENC_BIG_ENDIAN);
837 /* GPS Position */
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);
844 /* GCI */
845 proto_tree_add_item(tree, hf_rach_gci,
846 tvb, offset + 15, 1, ENC_BIG_ENDIAN);
848 /* R */
849 proto_tree_add_item(tree, hf_rach_r,
850 tvb, offset + 15, 1, ENC_BIG_ENDIAN);
852 /* O */
853 proto_tree_add_item(tree, hf_rach_o,
854 tvb, offset + 15, 1, ENC_BIG_ENDIAN);
857 static int
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;
867 const char *desc;
868 int len, is_moc, is_pdt, ies;
869 is_moc = 0;
870 is_pdt = 0;
872 len = tvb_reported_length(tvb);
874 desc = "GMR-1 Channel Request (RACH)";
875 ies = 0;
877 if (len == 18) {
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;
894 #endif
895 } else {
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);
904 if (!ies) {
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);
927 void
928 proto_register_gmr1_rach(void)
930 static hf_register_info hf[] = {
931 { &hf_rach_prio,
932 { "Priority", "gmr1.rach.priority",
933 FT_BOOLEAN, 8, TFS(&rach_prio_tfs), 0x01,
934 NULL, HFILL }
936 { &hf_rach_est_cause,
937 { "Establishment Cause", "gmr1.rach.est_cause",
938 FT_UINT8, BASE_HEX, VALS(rach_est_cause_vals), 0x3e,
939 NULL, HFILL }
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,
944 NULL, HFILL }
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,
949 NULL, HFILL }
951 { &hf_rach_num_plan,
952 { "Numbering Plan Identification", "gmr1.rach.numbering_plan",
953 FT_UINT8, BASE_DEC, VALS(rach_num_plan_vals), 0x1e,
954 NULL, HFILL }
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 }
966 { &hf_rach_precorr,
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 }
972 { &hf_rach_rand_ref,
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,
985 NULL, HFILL }
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,
990 NULL, HFILL }
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,
1000 NULL, HFILL }
1002 { &hf_rach_pd,
1003 { "PD", "gmr1.rach.pd",
1004 FT_UINT8, BASE_DEC, VALS(rach_pd_vals), 0xc0,
1005 "Protocol Discriminator", HFILL }
1007 { &hf_rach_number,
1008 { "Dialed Number", "gmr1.rach.number",
1009 FT_STRING, BASE_NONE, NULL, 0x00,
1010 NULL, HFILL }
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,
1015 NULL, HFILL }
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,
1020 NULL, HFILL }
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,
1025 NULL, HFILL }
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,
1030 NULL, HFILL }
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,
1035 NULL, HFILL }
1037 { &hf_rach_msc_id,
1038 { "MSC ID", "gmr1.rach.msc_id",
1039 FT_UINT8, BASE_DEC, NULL, 0x3f,
1040 NULL, HFILL }
1042 { &hf_rach_gps_timestamp,
1043 { "GPS Timestamp", "gmr1.rach.gps_timestamp",
1044 FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_gps_timestamp_fmt), 0xffff,
1045 NULL, HFILL }
1047 { &hf_rach_software_version,
1048 { "Software Version", "gmr1.rach.software_version",
1049 FT_UINT8, BASE_DEC, NULL, 0xfe,
1050 NULL, HFILL }
1052 { &hf_rach_spare,
1053 { "Spare", "gmr1.rach.spare",
1054 FT_UINT32, BASE_DEC, NULL, 0x01fffff8,
1055 NULL, HFILL }
1057 { &hf_rach_gci,
1058 { "GCI", "gmr1.rach.gci",
1059 FT_BOOLEAN, 8, TFS(&rach_gci_tfs), 0x01,
1060 "GPS Capability Indicator", HFILL }
1062 { &hf_rach_r,
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 }
1067 { &hf_rach_o,
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,
1115 NULL, HFILL }
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,
1120 NULL, HFILL }
1122 { &hf_rach_gmprs_spare1,
1123 { "Spare", "gmr1.rach.gmprs_spare1",
1124 FT_UINT8, BASE_DEC, NULL, 0x20,
1125 NULL, HFILL }
1127 { &hf_rach_gmprs_spare2,
1128 { "Spare", "gmr1.rach.gmprs_spare2",
1129 FT_UINT8, BASE_DEC, NULL, 0xc0,
1130 NULL, HFILL }
1132 { &hf_rach_gmprs_spare3,
1133 { "Spare", "gmr1.rach.gmprs_spare3",
1134 FT_UINT8, BASE_DEC, NULL, 0x04,
1135 NULL, HFILL }
1137 { &hf_rach_gmprs_reserved1,
1138 { "Reserved", "gmr1.rach.gmprs_reserved1",
1139 FT_UINT16, BASE_HEX, NULL, 0xffff,
1140 NULL, HFILL }
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,
1145 NULL, HFILL }
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,
1150 NULL, HFILL }
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[] = {
1160 &ett_rach_msg,
1161 &ett_rach_kls1,
1162 &ett_rach_kls2,
1163 &ett_rach_gmprs_type1_kls2,
1164 &ett_rach_gmprs_type2_kls2,
1165 &ett_rach_est_cause,
1166 &ett_rach_dialed_num,
1167 &ett_rach_gps_pos,
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
1182 * Local variables:
1183 * c-basic-offset: 8
1184 * tab-width: 8
1185 * indent-tabs-mode: t
1186 * End:
1188 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1189 * :indentSize=8:tabSize=8:noTabs=false: