/src/wireshark/epan/dissectors/packet-gmr1_rach.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-gmr1_rach.c |
2 | | * |
3 | | * Routines for GMR-1 RACH dissection in wireshark. |
4 | | * Copyright (c) 2012 Sylvain Munaut <tnt@246tNt.com> |
5 | | * |
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 |
10 | | * |
11 | | * Especially [1] 10.1.8 |
12 | | * |
13 | | * Wireshark - Network traffic analyzer |
14 | | * By Gerald Combs <gerald@wireshark.org> |
15 | | * Copyright 1998 Gerald Combs |
16 | | * |
17 | | * SPDX-License-Identifier: GPL-2.0-or-later |
18 | | */ |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | | #include <stdlib.h> |
23 | | |
24 | | #include <epan/packet.h> |
25 | | |
26 | | |
27 | | void proto_register_gmr1_rach(void); |
28 | | |
29 | | /* GMR-1 RACH proto */ |
30 | | static int proto_gmr1_rach = -1; |
31 | | |
32 | | /* GMR-1 RACH subtrees */ |
33 | | static gint ett_rach_msg = -1; |
34 | | static gint ett_rach_kls1 = -1; |
35 | | static gint ett_rach_kls2 = -1; |
36 | | static gint ett_rach_gmprs_type1_kls2 = -1; |
37 | | static gint ett_rach_gmprs_type2_kls2 = -1; |
38 | | static gint ett_rach_est_cause = -1; |
39 | | static gint ett_rach_dialed_num = -1; |
40 | | static gint ett_rach_gps_pos = -1; |
41 | | static gint ett_rach_gmprs_req_type = -1; |
42 | | |
43 | | /* Fields */ |
44 | | static int hf_rach_prio = -1; |
45 | | static int hf_rach_est_cause = -1; |
46 | | static int hf_rach_est_cause_moc = -1; |
47 | | static int hf_rach_est_cause_pag_resp = -1; |
48 | | static int hf_rach_num_plan = -1; |
49 | | static int hf_rach_chan_needed = -1; |
50 | | static int hf_rach_retry_cnt = -1; |
51 | | static int hf_rach_precorr = -1; |
52 | | static int hf_rach_rand_ref = -1; |
53 | | |
54 | | static int hf_rach_gps_pos_cpi = -1; |
55 | | static int hf_rach_gps_pos_lat = -1; |
56 | | static int hf_rach_gps_pos_long = -1; |
57 | | |
58 | | static int hf_rach_mes_pwr_class = -1; |
59 | | static int hf_rach_sp_hplmn_id = -1; |
60 | | static int hf_rach_pd = -1; |
61 | | static int hf_rach_number = -1; |
62 | | static int hf_rach_number_grp1 = -1; |
63 | | static int hf_rach_number_grp2 = -1; |
64 | | static int hf_rach_number_grp3 = -1; |
65 | | static int hf_rach_number_grp4 = -1; |
66 | | static int hf_rach_number_grp5 = -1; |
67 | | static int hf_rach_msc_id = -1; |
68 | | static int hf_rach_gps_timestamp = -1; |
69 | | static int hf_rach_software_version = -1; |
70 | | static int hf_rach_spare = -1; |
71 | | static int hf_rach_gci = -1; |
72 | | static int hf_rach_r = -1; |
73 | | static int hf_rach_o = -1; |
74 | | static int hf_rach_number_type = -1; |
75 | | |
76 | | static int hf_rach_gmprs_term_type = -1; |
77 | | static int hf_rach_gmprs_radio_prio = -1; |
78 | | static int hf_rach_gmprs_tlli = -1; |
79 | | static int hf_rach_gmprs_num_rlc_blks = -1; |
80 | | static int hf_rach_gmprs_peak_tput = -1; |
81 | | static int hf_rach_gmprs_dl_peak_tput = -1; |
82 | | static int hf_rach_gmprs_ul_peak_tput = -1; |
83 | | static int hf_rach_gmprs_rlc_mode = -1; |
84 | | static int hf_rach_gmprs_llc_mode = -1; |
85 | | static int hf_rach_gmprs_spare1 = -1; |
86 | | static int hf_rach_gmprs_spare2 = -1; |
87 | | static int hf_rach_gmprs_spare3 = -1; |
88 | | static int hf_rach_gmprs_reserved1 = -1; |
89 | | static int hf_rach_gmprs_req_type = -1; |
90 | | static int hf_rach_gmprs_req_type_pag_resp = -1; |
91 | | static int hf_rach_gmprs_chan_needed = -1; |
92 | | |
93 | | |
94 | | static const true_false_string rach_prio_tfs = { |
95 | | "Priority Call", |
96 | | "Normal Call" |
97 | | }; |
98 | | |
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 } |
111 | | }; |
112 | | |
113 | | static const value_string rach_est_cause_moc_vals[] = { |
114 | | { 1, "Mobile Originated Call" }, |
115 | | { 0, NULL } |
116 | | }; |
117 | | |
118 | | static const value_string rach_est_cause_pag_resp_vals[] = { |
119 | | { 0, "In response to paging" }, |
120 | | { 0, NULL } |
121 | | }; |
122 | | |
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 } |
133 | | }; |
134 | | |
135 | | static const value_string rach_chan_needed_vals[] = { |
136 | | { 0, "any" }, |
137 | | { 1, "SDCCH" }, |
138 | | { 2, "TCH3" }, |
139 | | { 3, "spare" }, |
140 | | { 0, NULL } |
141 | | }; |
142 | | |
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 } |
153 | | }; |
154 | | |
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) |
158 | 0 | { |
159 | 0 | proto_tree *tree = NULL; |
160 | 0 | proto_item *ec_item = NULL; |
161 | 0 | proto_tree *ec_tree = NULL; |
162 | 0 | guint8 ec; |
163 | | |
164 | | /* Tree */ |
165 | 0 | tree = proto_tree_add_subtree( |
166 | 0 | root_tree, tvb, 0, 2, |
167 | 0 | ett_rach_kls1, NULL, "Class-1 informations"); |
168 | | |
169 | | /* Priority */ |
170 | 0 | proto_tree_add_item(tree, hf_rach_prio, |
171 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
172 | | |
173 | | /* Establishment Cause */ |
174 | 0 | ec = (tvb_get_guint8(tvb, offset) >> 1) & 0x1f; |
175 | |
|
176 | 0 | *is_moc = !!(ec & 0x10); |
177 | 0 | *is_pdt = (ec == 14); |
178 | |
|
179 | 0 | if (ec & 0x10) |
180 | 0 | { |
181 | | /* MOC */ |
182 | 0 | ec_item = proto_tree_add_item(tree, hf_rach_est_cause_moc, |
183 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
184 | |
|
185 | 0 | ec_tree = proto_item_add_subtree(ec_item, ett_rach_est_cause); |
186 | |
|
187 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Mobile Originated Call "); |
188 | | |
189 | | /* Numbering plan */ |
190 | 0 | proto_tree_add_item(ec_tree, hf_rach_num_plan, |
191 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
192 | 0 | } |
193 | 0 | else if ((ec & 0x1c) == 0x00) |
194 | 0 | { |
195 | | /* Paging response */ |
196 | 0 | ec_item = proto_tree_add_item(tree, hf_rach_est_cause_pag_resp, |
197 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
198 | |
|
199 | 0 | ec_tree = proto_item_add_subtree(ec_item, ett_rach_est_cause); |
200 | |
|
201 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Paging response "); |
202 | | |
203 | | /* Channel Needed */ |
204 | 0 | proto_tree_add_item(ec_tree, hf_rach_chan_needed, |
205 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
206 | 0 | } |
207 | 0 | else if (ec == 7) |
208 | 0 | { |
209 | | /* Channel Request Type 2 */ |
210 | 0 | proto_tree_add_item(tree, hf_rach_est_cause, |
211 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
212 | 0 | } |
213 | 0 | else |
214 | 0 | { |
215 | | /* Other */ |
216 | 0 | proto_tree_add_item(tree, hf_rach_est_cause, |
217 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
218 | |
|
219 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
220 | 0 | val_to_str(ec, rach_est_cause_vals, "Unknown (%u)")); |
221 | 0 | } |
222 | | |
223 | | /* Retry counter */ |
224 | 0 | proto_tree_add_item(tree, hf_rach_retry_cnt, |
225 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
226 | | |
227 | | /* Precorrection Indication */ |
228 | 0 | proto_tree_add_item(tree, hf_rach_precorr, |
229 | 0 | tvb, offset + 1, 1, ENC_BIG_ENDIAN); |
230 | | |
231 | | /* Random Reference */ |
232 | 0 | proto_tree_add_item(tree, hf_rach_rand_ref, |
233 | 0 | tvb, offset + 1, 1, ENC_BIG_ENDIAN); |
234 | 0 | } |
235 | | |
236 | | |
237 | | static const true_false_string rach_gps_pos_cpi_tfs = { |
238 | | "GPS position is current position", |
239 | | "GPS position is old position" |
240 | | }; |
241 | | |
242 | | static void |
243 | | rach_gps_pos_lat_fmt(gchar *s, guint32 v) |
244 | 0 | { |
245 | 0 | gint32 sv = v; |
246 | |
|
247 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%.5f %s (%d)", |
248 | 0 | abs(sv) / 2912.7f, sv < 0 ? "S" : "N", sv); |
249 | 0 | } |
250 | | |
251 | | static void |
252 | | rach_gps_pos_long_fmt(gchar *s, guint32 v) |
253 | 0 | { |
254 | 0 | gint32 sv = v; |
255 | |
|
256 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%.5f %s (%d)", |
257 | 0 | abs(sv) / 2912.70555f, sv < 0 ? "W" : "E", sv); |
258 | | |
259 | | /* FIXME: The specs says >0 is West ... but it doesn't seem to |
260 | | * match real world captures ! |
261 | | */ |
262 | 0 | } |
263 | | |
264 | | static void |
265 | | dissect_gmr1_rach_gps_pos(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) |
266 | 0 | { |
267 | 0 | guint32 lat, lng; |
268 | | |
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 */ |
273 | |
|
274 | 0 | lat = (tvb_get_ntohl(tvb, offset) >> 12) & 0x7ffff; |
275 | 0 | lng = tvb_get_ntohl(tvb, offset + 1) & 0xfffff; |
276 | |
|
277 | 0 | if (lat == 0x40000) { |
278 | 0 | proto_tree_add_int_format(tree, hf_rach_gps_pos_lat, tvb, offset, 5, lat, |
279 | 0 | "NULL GPS Position (latitude == 0x40000)"); |
280 | 0 | return; |
281 | 0 | } else if (lng == 0x80000) { |
282 | 0 | proto_tree_add_int_format(tree, hf_rach_gps_pos_long, tvb, offset, 5, lng, |
283 | 0 | "NULL GPS Position (longitude == 0x80000)"); |
284 | 0 | return; |
285 | 0 | } |
286 | | |
287 | | /* CPI */ |
288 | 0 | proto_tree_add_item(tree, hf_rach_gps_pos_cpi, |
289 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
290 | | |
291 | | /* Latitude */ |
292 | 0 | proto_tree_add_item(tree, hf_rach_gps_pos_lat, |
293 | 0 | tvb, offset, 3, ENC_BIG_ENDIAN); |
294 | | |
295 | | /* Longitude */ |
296 | 0 | proto_tree_add_item(tree, hf_rach_gps_pos_long, |
297 | 0 | tvb, offset + 2, 3, ENC_BIG_ENDIAN); |
298 | 0 | } |
299 | | |
300 | | |
301 | | static void |
302 | | rach_sp_hplmn_id_fmt(gchar *s, guint32 v) |
303 | 0 | { |
304 | 0 | if (v == 0xfffff) { |
305 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%05x (Null)", v); |
306 | 0 | } else if ((v & 0xf8000) == 0xf8000) { |
307 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%05x (SP ID %4d)", v, v & 0x7fff); |
308 | 0 | } else { |
309 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%05x (HPLMN ID)", v); |
310 | 0 | } |
311 | 0 | } |
312 | | |
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 } |
319 | | }; |
320 | | |
321 | | static void |
322 | | rach_dialed_num_grp1234_fmt(gchar *s, guint32 v) |
323 | 0 | { |
324 | 0 | if (v <= 999) { |
325 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%03d", v); |
326 | 0 | } else if (v == 1023) { |
327 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, |
328 | 0 | "All digits in the preceding group are valid (%d)", v); |
329 | 0 | } else if (v == 1022) { |
330 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, |
331 | 0 | "First two digits in the preceding group are valid, " |
332 | 0 | "and the third digit (i.e. 0) is padding (%d)", v); |
333 | 0 | } else if (v == 1021) { |
334 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, |
335 | 0 | "First digit in the preceding group is valid, and " |
336 | 0 | "the second and third 0s are padding (%d)", v); |
337 | 0 | } else { |
338 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "Invalid (%d)", v); |
339 | 0 | } |
340 | 0 | } |
341 | | |
342 | | static void |
343 | | rach_dialed_num_grp5_fmt(gchar *s, guint32 v) |
344 | 0 | { |
345 | 0 | if (v >= 1100 && v <= 1199) { |
346 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%02d (%d)", v - 1100, v); |
347 | 0 | } else if (v >= 1200 && v <= 1209) { |
348 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%01d (%d)", v - 1200, v); |
349 | 0 | } else { |
350 | 0 | rach_dialed_num_grp1234_fmt(s, v); |
351 | 0 | } |
352 | 0 | } |
353 | | |
354 | | static void |
355 | | rach_gps_timestamp_fmt(gchar *s, guint32 v) |
356 | 0 | { |
357 | 0 | if (v == 0xffff) { |
358 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, ">= 65535 minutes or N/A (%04x)", v); |
359 | 0 | } else { |
360 | 0 | g_snprintf(s, ITEM_LABEL_LENGTH, "%d minutes (%04x)", v, v); |
361 | 0 | } |
362 | 0 | } |
363 | | |
364 | | static const true_false_string rach_gci_tfs = { |
365 | | "MES is GPS capable", |
366 | | "MES is not GPS capable" |
367 | | }; |
368 | | |
369 | | static const true_false_string rach_r_tfs = { |
370 | | "Normal case", |
371 | | "Retry (see specs for details)" |
372 | | }; |
373 | | |
374 | | static const true_false_string rach_o_tfs = { |
375 | | "Retry after failed optimal routing attempt", |
376 | | "Normal case" |
377 | | }; |
378 | | |
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 } |
389 | | }; |
390 | | |
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 } |
415 | | }; |
416 | | static value_string_ext rach_gmprs_term_type_ext_vals = VALUE_STRING_EXT_INIT(rach_gmprs_term_type_vals); |
417 | | |
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 } |
424 | | }; |
425 | | |
426 | | static const true_false_string rach_gmprs_rlc_mode_tfs = { |
427 | | "Unacknowledged", |
428 | | "Acknowledged" |
429 | | }; |
430 | | |
431 | | static const true_false_string rach_gmprs_llc_mode_tfs = { |
432 | | "Data packets", |
433 | | "SACK/ACK packets" |
434 | | }; |
435 | | |
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 } |
446 | | }; |
447 | | |
448 | | static const value_string rach_gmprs_req_type_pag_resp_vals[] = { |
449 | | { 0x00, "Suspend - Answer to Paging" }, |
450 | | { 0, NULL } |
451 | | }; |
452 | | |
453 | | static int |
454 | | _parse_dialed_number(gchar *s, int slen, tvbuff_t *tvb, int offset) |
455 | 0 | { |
456 | 0 | guint16 grp[5]; |
457 | 0 | int rv, i, done; |
458 | |
|
459 | 0 | grp[0] = ((tvb_get_guint8(tvb, offset+0) & 0x3f) << 4) | |
460 | 0 | ((tvb_get_guint8(tvb, offset+1) & 0xf0) >> 4); |
461 | 0 | grp[1] = ((tvb_get_guint8(tvb, offset+1) & 0x0f) << 6) | |
462 | 0 | ((tvb_get_guint8(tvb, offset+2) & 0xfc) >> 2); |
463 | 0 | grp[2] = ((tvb_get_guint8(tvb, offset+2) & 0x03) << 8) | |
464 | 0 | tvb_get_guint8(tvb, offset+3); |
465 | 0 | grp[3] = ((tvb_get_guint8(tvb, offset+4) & 0xff) << 2) | |
466 | 0 | ((tvb_get_guint8(tvb, offset+5) & 0xc0) >> 6); |
467 | 0 | grp[4] = ((tvb_get_guint8(tvb, offset+5) & 0x3f) << 5) | |
468 | 0 | ((tvb_get_guint8(tvb, offset+6) & 0xf8) >> 3); |
469 | |
|
470 | 0 | rv = 0; |
471 | 0 | done = 0; |
472 | |
|
473 | 0 | for (i=0; i<4; i++) |
474 | 0 | { |
475 | 0 | if (grp[i+1] <= 999) |
476 | 0 | { |
477 | | /* All digits of group are valid */ |
478 | 0 | rv += g_snprintf(s + rv, slen - rv, "%03d", grp[i]); |
479 | 0 | } |
480 | 0 | else if (grp[i+1] == 1023) |
481 | 0 | { |
482 | | /* Last group and all digits are valid */ |
483 | 0 | rv += g_snprintf(s + rv, slen - rv, "%03d", grp[i]); |
484 | 0 | done = 1; |
485 | 0 | break; |
486 | 0 | } |
487 | 0 | else if (grp[i+1] == 1022) |
488 | 0 | { |
489 | | /* Last group and first two digits are valid */ |
490 | 0 | rv += g_snprintf(s + rv, slen - rv, "%02d", grp[i] / 10); |
491 | 0 | done = 1; |
492 | 0 | break; |
493 | 0 | } |
494 | 0 | else if (grp[i+1] == 1021) |
495 | 0 | { |
496 | | /* Last group and first digit is valid */ |
497 | 0 | rv += g_snprintf(s + rv, slen - rv, "%01d", grp[i] / 100); |
498 | 0 | done = 1; |
499 | 0 | break; |
500 | 0 | } |
501 | 0 | else if ((i==3) && (grp[i+1] >= 1100) && (grp[i+1] <= 1209)) |
502 | 0 | { |
503 | | /* All digits of group are valid */ |
504 | 0 | rv += g_snprintf(s + rv, slen - rv, "%03d", grp[i]); |
505 | 0 | } |
506 | 0 | else |
507 | 0 | { |
508 | | /* Invalid */ |
509 | 0 | return g_snprintf(s, slen, "(Invalid)"); |
510 | 0 | } |
511 | 0 | } |
512 | |
|
513 | 0 | if (!done) { |
514 | 0 | if (grp[4] <= 999) |
515 | 0 | { |
516 | | /* All digits are valid */ |
517 | 0 | rv += g_snprintf(s + rv, slen - rv, "%03d", grp[4]); |
518 | 0 | } |
519 | 0 | else if (grp[4] >= 1100 && grp[4] <= 1199) |
520 | 0 | { |
521 | | /* Only two digits are valid */ |
522 | 0 | rv += g_snprintf(s + rv, slen - rv, "%02d", grp[4] - 1100); |
523 | 0 | } |
524 | 0 | else if (grp[4] >= 1200 && grp[4] <= 1209) |
525 | 0 | { |
526 | | /* Only one digit is valid */ |
527 | 0 | rv += g_snprintf(s + rv, slen - rv, "%01d", grp[4] - 1200); |
528 | 0 | } |
529 | 0 | else |
530 | 0 | { |
531 | | /* Invalid */ |
532 | 0 | return g_snprintf(s, slen, "(Invalid)"); |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | 0 | return rv; |
537 | 0 | } |
538 | | |
539 | | static void |
540 | | dissect_gmr1_rach_kls2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *root_tree, |
541 | | int is_moc) |
542 | 0 | { |
543 | 0 | proto_tree *tree = NULL; |
544 | 0 | proto_item *dialed_num_item = NULL; |
545 | 0 | proto_tree *dialed_num_tree = NULL, *gps_pos_tree = NULL; |
546 | | |
547 | | /* Tree */ |
548 | 0 | tree = proto_tree_add_subtree( |
549 | 0 | root_tree, tvb, 2, 16, |
550 | 0 | ett_rach_kls2, NULL, "Class-2 informations"); |
551 | | |
552 | | /* MES Power Class */ |
553 | 0 | proto_tree_add_item(tree, hf_rach_mes_pwr_class, |
554 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
555 | | |
556 | | /* SP/HPLMN ID */ |
557 | 0 | proto_tree_add_item(tree, hf_rach_sp_hplmn_id, |
558 | 0 | tvb, offset, 3, ENC_BIG_ENDIAN); |
559 | | |
560 | | /* PD */ |
561 | 0 | proto_tree_add_item(tree, hf_rach_pd, |
562 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
563 | | |
564 | | |
565 | | /* Is it a MO call ? */ |
566 | 0 | if (is_moc) { |
567 | 0 | gchar s[32]; |
568 | | |
569 | | /* Dialed number */ |
570 | | /* Parse number */ |
571 | 0 | _parse_dialed_number(s, sizeof(s), tvb, offset + 3); |
572 | |
|
573 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", s); |
574 | | |
575 | | /* Base item */ |
576 | 0 | dialed_num_item = proto_tree_add_string( |
577 | 0 | tree, hf_rach_number, tvb, offset + 3, 7, s); |
578 | |
|
579 | 0 | dialed_num_tree = proto_item_add_subtree( |
580 | 0 | dialed_num_item, ett_rach_dialed_num); |
581 | | |
582 | | /* Group 1 */ |
583 | 0 | proto_tree_add_item(dialed_num_tree, hf_rach_number_grp1, |
584 | 0 | tvb, offset + 3, 2, ENC_BIG_ENDIAN); |
585 | | |
586 | | /* Group 2 */ |
587 | 0 | proto_tree_add_item(dialed_num_tree, hf_rach_number_grp2, |
588 | 0 | tvb, offset + 4, 2, ENC_BIG_ENDIAN); |
589 | | |
590 | | /* Group 3 */ |
591 | 0 | proto_tree_add_item(dialed_num_tree, hf_rach_number_grp3, |
592 | 0 | tvb, offset + 5, 2, ENC_BIG_ENDIAN); |
593 | | |
594 | | /* Group 4 */ |
595 | 0 | proto_tree_add_item(dialed_num_tree, hf_rach_number_grp4, |
596 | 0 | tvb, offset + 7, 2, ENC_BIG_ENDIAN); |
597 | | |
598 | | /* Group 5 */ |
599 | 0 | proto_tree_add_item(dialed_num_tree, hf_rach_number_grp5, |
600 | 0 | tvb, offset + 8, 2, ENC_BIG_ENDIAN); |
601 | 0 | } else { |
602 | | /* MSC ID */ |
603 | 0 | proto_tree_add_item(tree, hf_rach_msc_id, |
604 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
605 | | |
606 | | /* GPS timestamp */ |
607 | 0 | proto_tree_add_item(tree, hf_rach_gps_timestamp, |
608 | 0 | tvb, offset + 4, 2, ENC_BIG_ENDIAN); |
609 | | |
610 | | /* Software version number */ |
611 | 0 | proto_tree_add_item(tree, hf_rach_software_version, |
612 | 0 | tvb, offset + 6, 1, ENC_BIG_ENDIAN); |
613 | | |
614 | | /* Spare */ |
615 | 0 | proto_tree_add_item(tree, hf_rach_spare, |
616 | 0 | tvb, offset + 6, 1, ENC_BIG_ENDIAN); |
617 | 0 | } |
618 | | |
619 | | /* GCI */ |
620 | 0 | proto_tree_add_item(tree, hf_rach_gci, |
621 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
622 | | |
623 | | /* R */ |
624 | 0 | proto_tree_add_item(tree, hf_rach_r, |
625 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
626 | | |
627 | | /* O */ |
628 | 0 | proto_tree_add_item(tree, hf_rach_o, |
629 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
630 | | |
631 | | /* GPS Position */ |
632 | 0 | gps_pos_tree = proto_tree_add_subtree( |
633 | 0 | tree, tvb, offset + 10, 5, |
634 | 0 | ett_rach_gps_pos, NULL, "GPS Position"); |
635 | |
|
636 | 0 | dissect_gmr1_rach_gps_pos(tvb, offset + 10, pinfo, gps_pos_tree); |
637 | | |
638 | | /* Number type */ |
639 | 0 | proto_tree_add_item(tree, hf_rach_number_type, |
640 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
641 | 0 | } |
642 | | |
643 | | static const crumb_spec_t rach_gmprs_type1_term_type_crumbs[] = { |
644 | | { 0, 4 }, |
645 | | { 29, 3 }, |
646 | | { 0, 0 } |
647 | | }; |
648 | | |
649 | | static const crumb_spec_t rach_gmprs_num_rlc_blks_crumbs[] = { |
650 | | { 0, 8 }, |
651 | | { 14, 2 }, |
652 | | { 0, 0 } |
653 | | }; |
654 | | |
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) |
658 | 0 | { |
659 | 0 | proto_tree *tree = NULL; |
660 | 0 | proto_tree *gps_pos_tree = NULL; |
661 | 0 | guint8 term_type; |
662 | 0 | int is_class_d; |
663 | | |
664 | | /* Tree */ |
665 | 0 | tree = proto_tree_add_subtree( |
666 | 0 | root_tree, tvb, 2, 16, |
667 | 0 | ett_rach_gmprs_type1_kls2, NULL, "GmPRS Type-1 Class-2 informations"); |
668 | | |
669 | | /* GmPRS Terminal Type */ |
670 | 0 | proto_tree_add_split_bits_item_ret_val( |
671 | 0 | tree, hf_rach_gmprs_term_type, |
672 | 0 | tvb, offset << 3, |
673 | 0 | rach_gmprs_type1_term_type_crumbs, |
674 | 0 | NULL); |
675 | |
|
676 | 0 | term_type = ((tvb_get_guint8(tvb, offset) >> 1) & 0x78 ) | |
677 | 0 | ( tvb_get_guint8(tvb, offset + 3) & 0x07); |
678 | |
|
679 | 0 | is_class_d = (term_type == 0x0d) || |
680 | 0 | (term_type == 0x0e) || |
681 | 0 | (term_type == 0x0f); |
682 | | |
683 | | /* Class D terminal ? */ |
684 | 0 | if (is_class_d) { |
685 | | /* DL Peak Throughput */ |
686 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_dl_peak_tput, |
687 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
688 | | |
689 | | /* Reserved */ |
690 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_reserved1, |
691 | 0 | tvb, offset, 2, ENC_BIG_ENDIAN); |
692 | 0 | } else { |
693 | | /* SP/HPLMN ID */ |
694 | 0 | proto_tree_add_item(tree, hf_rach_sp_hplmn_id, |
695 | 0 | tvb, offset, 3, ENC_BIG_ENDIAN); |
696 | 0 | } |
697 | | |
698 | | /* Radio Priority */ |
699 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_radio_prio, |
700 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
701 | | |
702 | | /* Spare */ |
703 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_spare1, |
704 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
705 | | |
706 | | /* PD */ |
707 | 0 | proto_tree_add_item(tree, hf_rach_pd, |
708 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
709 | | |
710 | | /* TLLI */ |
711 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_tlli, |
712 | 0 | tvb, offset + 4, 4, ENC_BIG_ENDIAN); |
713 | | |
714 | | /* Is it for Packet Data Transfer ? */ |
715 | 0 | if (is_pdt) { |
716 | | /* Number of RLC blocks */ |
717 | 0 | proto_tree_add_split_bits_item_ret_val( |
718 | 0 | tree, hf_rach_gmprs_num_rlc_blks, |
719 | 0 | tvb, (offset + 8) << 3, |
720 | 0 | rach_gmprs_num_rlc_blks_crumbs, |
721 | 0 | NULL); |
722 | | |
723 | | /* (UL) Peak Throughput */ |
724 | 0 | proto_tree_add_item(tree, is_class_d ? |
725 | 0 | hf_rach_gmprs_ul_peak_tput : |
726 | 0 | hf_rach_gmprs_peak_tput, |
727 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
728 | | |
729 | | /* Spare */ |
730 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_spare2, |
731 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
732 | 0 | } else { |
733 | | /* GPS timestamp */ |
734 | 0 | proto_tree_add_item(tree, hf_rach_gps_timestamp, |
735 | 0 | tvb, offset + 8, 2, ENC_BIG_ENDIAN); |
736 | 0 | } |
737 | | |
738 | | /* GPS Position */ |
739 | 0 | gps_pos_tree = proto_tree_add_subtree( |
740 | 0 | tree, tvb, offset + 10, 5, |
741 | 0 | ett_rach_gps_pos, NULL, "GPS Position"); |
742 | |
|
743 | 0 | dissect_gmr1_rach_gps_pos(tvb, offset + 10, pinfo, gps_pos_tree); |
744 | | |
745 | | /* RLC mode */ |
746 | | /* Off-the-air data shows bit is sometimes set even |
747 | | * when not a PDT ... */ |
748 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_rlc_mode, |
749 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
750 | | |
751 | | /* LLC mode */ |
752 | | /* Off-the-air data shows bit is sometimes set even |
753 | | * when not a PDT ... */ |
754 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_llc_mode, |
755 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
756 | | |
757 | | /* Spare */ |
758 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_spare3, |
759 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
760 | 0 | } |
761 | | |
762 | | static const crumb_spec_t rach_gmprs_type2_term_type_crumbs[] = { |
763 | | { 0, 4 }, |
764 | | { 64, 3 }, |
765 | | { 0, 0 } |
766 | | }; |
767 | | |
768 | | static void |
769 | | dissect_gmprs_rach_type2_kls2(tvbuff_t *tvb, int offset, |
770 | | packet_info *pinfo, proto_tree *root_tree) |
771 | 0 | { |
772 | 0 | proto_tree *tree = NULL; |
773 | 0 | proto_tree *gps_pos_tree = NULL; |
774 | 0 | guint8 req_type; |
775 | | |
776 | | /* Tree */ |
777 | 0 | tree = proto_tree_add_subtree( |
778 | 0 | root_tree, tvb, 2, 16, |
779 | 0 | ett_rach_gmprs_type2_kls2, NULL, "GmPRS Type-2 Class-2 informations"); |
780 | | |
781 | | /* GmPRS Terminal type */ |
782 | 0 | proto_tree_add_split_bits_item_ret_val( |
783 | 0 | tree, hf_rach_gmprs_term_type, |
784 | 0 | tvb, offset << 3, |
785 | 0 | rach_gmprs_type2_term_type_crumbs, |
786 | 0 | NULL); |
787 | | |
788 | | /* SP/HPLMN ID */ |
789 | 0 | proto_tree_add_item(tree, hf_rach_sp_hplmn_id, |
790 | 0 | tvb, offset, 3, ENC_BIG_ENDIAN); |
791 | | |
792 | | /* PD */ |
793 | 0 | proto_tree_add_item(tree, hf_rach_pd, |
794 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
795 | | |
796 | | /* MSC ID */ |
797 | 0 | proto_tree_add_item(tree, hf_rach_msc_id, |
798 | 0 | tvb, offset + 3, 1, ENC_BIG_ENDIAN); |
799 | | |
800 | | /* TLLI */ |
801 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_tlli, |
802 | 0 | tvb, offset + 4, 4, ENC_BIG_ENDIAN); |
803 | | |
804 | | /* Request type */ |
805 | 0 | req_type = tvb_get_guint8(tvb, offset + 8) & 0x1f; |
806 | |
|
807 | 0 | if ((req_type & 0x1c) == 0) { |
808 | | /* Paging response */ |
809 | 0 | proto_item *rt_item = proto_tree_add_item( |
810 | 0 | tree, hf_rach_gmprs_req_type_pag_resp, |
811 | 0 | tvb, offset + 8, 1, ENC_BIG_ENDIAN); |
812 | |
|
813 | 0 | proto_tree *rt_tree = proto_item_add_subtree(rt_item, ett_rach_gmprs_req_type); |
814 | |
|
815 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Paging response "); |
816 | | |
817 | | /* Channel Needed */ |
818 | 0 | proto_tree_add_item(rt_tree, hf_rach_gmprs_chan_needed, |
819 | 0 | tvb, offset + 8, 1, ENC_BIG_ENDIAN); |
820 | 0 | } else { |
821 | | /* Other */ |
822 | 0 | proto_tree_add_item(tree, hf_rach_gmprs_req_type, |
823 | 0 | tvb, offset + 8, 1, ENC_BIG_ENDIAN); |
824 | |
|
825 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
826 | 0 | val_to_str(req_type, rach_gmprs_req_type_vals, "Unknown (%u)")); |
827 | 0 | } |
828 | | |
829 | | /* Software version number */ |
830 | 0 | proto_tree_add_item(tree, hf_rach_software_version, |
831 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
832 | | |
833 | | /* Spare */ |
834 | 0 | proto_tree_add_item(tree, hf_rach_spare, |
835 | 0 | tvb, offset + 9, 1, ENC_BIG_ENDIAN); |
836 | | |
837 | | /* GPS Position */ |
838 | 0 | gps_pos_tree = proto_tree_add_subtree( |
839 | 0 | tree, tvb, offset + 10, 5, |
840 | 0 | ett_rach_gps_pos, NULL, "GPS Position"); |
841 | |
|
842 | 0 | dissect_gmr1_rach_gps_pos(tvb, offset + 10, pinfo, gps_pos_tree); |
843 | | |
844 | | /* GCI */ |
845 | 0 | proto_tree_add_item(tree, hf_rach_gci, |
846 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
847 | | |
848 | | /* R */ |
849 | 0 | proto_tree_add_item(tree, hf_rach_r, |
850 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
851 | | |
852 | | /* O */ |
853 | 0 | proto_tree_add_item(tree, hf_rach_o, |
854 | 0 | tvb, offset + 15, 1, ENC_BIG_ENDIAN); |
855 | 0 | } |
856 | | |
857 | | static int |
858 | | dissect_gmr1_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
859 | 0 | { |
860 | 0 | const int RACH_IE_CLASS1 = (1 << 0); |
861 | 0 | const int RACH_IE_CLASS2_GMR1 = (1 << 1); |
862 | 0 | const int RACH_IE_CLASS2_GMPRS_TYPE1 = (1 << 2); |
863 | 0 | const int RACH_IE_CLASS2_GMPRS_TYPE2 = (1 << 3); |
864 | |
|
865 | 0 | proto_item *rach_item; |
866 | 0 | proto_tree *rach_tree; |
867 | 0 | const char *desc; |
868 | 0 | int len, is_moc, is_pdt, ies; |
869 | |
|
870 | 0 | len = tvb_reported_length(tvb); |
871 | |
|
872 | 0 | desc = "GMR-1 Channel Request (RACH)"; |
873 | 0 | ies = 0; |
874 | |
|
875 | 0 | if (len == 18) { |
876 | 0 | guint8 ec = (tvb_get_guint8(tvb, 0) >> 1) & 0x1f; |
877 | |
|
878 | 0 | ies |= RACH_IE_CLASS1; |
879 | |
|
880 | 0 | if ((ec == 13) || (ec == 14)) { |
881 | 0 | desc = "GMR-1 GmPRS Channel Request Type 1 (RACH)"; |
882 | 0 | ies |= RACH_IE_CLASS2_GMPRS_TYPE1; |
883 | 0 | } else if (ec == 7) { |
884 | 0 | desc = "GMR-1 GmPRS Channel Request Type 2 (RACH)"; |
885 | 0 | ies |= RACH_IE_CLASS2_GMPRS_TYPE2; |
886 | | #if 0 /* Fix -Wduplicated-branches */ |
887 | | } else if (ec == 12) { |
888 | | /* Position verification exists in both GMR-1 and GmPRS-1 |
889 | | * I have no idea how to differentiate them ... but from |
890 | | * off-the-air data, it seems it used the GMR-1 format */ |
891 | | ies |= RACH_IE_CLASS2_GMR1; |
892 | | #endif |
893 | 0 | } else { |
894 | 0 | ies |= RACH_IE_CLASS2_GMR1; |
895 | 0 | } |
896 | 0 | } |
897 | |
|
898 | 0 | rach_item = proto_tree_add_protocol_format( |
899 | 0 | tree, proto_gmr1_rach, tvb, 0, len, "%s", desc); |
900 | 0 | rach_tree = proto_item_add_subtree(rach_item, ett_rach_msg); |
901 | |
|
902 | 0 | if (!ies) { |
903 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "(Invalid)"); |
904 | 0 | call_data_dissector(tvb, pinfo, tree); |
905 | 0 | return tvb_captured_length(tvb); |
906 | 0 | } |
907 | | |
908 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "(RACH) "); |
909 | |
|
910 | 0 | if (ies & RACH_IE_CLASS1) |
911 | 0 | dissect_gmr1_rach_kls1(tvb, 0, pinfo, rach_tree, &is_moc, &is_pdt); |
912 | |
|
913 | 0 | if (ies & RACH_IE_CLASS2_GMR1) |
914 | 0 | dissect_gmr1_rach_kls2(tvb, 2, pinfo, rach_tree, is_moc); |
915 | |
|
916 | 0 | if (ies & RACH_IE_CLASS2_GMPRS_TYPE1) |
917 | 0 | dissect_gmprs_rach_type1_kls2(tvb, 2, pinfo, rach_tree, is_pdt); |
918 | |
|
919 | 0 | if (ies & RACH_IE_CLASS2_GMPRS_TYPE2) |
920 | 0 | dissect_gmprs_rach_type2_kls2(tvb, 2, pinfo, rach_tree); |
921 | |
|
922 | 0 | return tvb_captured_length(tvb); |
923 | 0 | } |
924 | | |
925 | | void |
926 | | proto_register_gmr1_rach(void) |
927 | 5.41k | { |
928 | 5.41k | static hf_register_info hf[] = { |
929 | 5.41k | { &hf_rach_prio, |
930 | 5.41k | { "Priority", "gmr1.rach.priority", |
931 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_prio_tfs), 0x01, |
932 | 5.41k | NULL, HFILL } |
933 | 5.41k | }, |
934 | 5.41k | { &hf_rach_est_cause, |
935 | 5.41k | { "Establishment Cause", "gmr1.rach.est_cause", |
936 | 5.41k | FT_UINT8, BASE_HEX, VALS(rach_est_cause_vals), 0x3e, |
937 | 5.41k | NULL, HFILL } |
938 | 5.41k | }, |
939 | 5.41k | { &hf_rach_est_cause_moc, |
940 | 5.41k | { "Establishment Cause", "gmr1.rach.est_cause.moc", |
941 | 5.41k | FT_UINT8, BASE_HEX, VALS(rach_est_cause_moc_vals), 0x20, |
942 | 5.41k | NULL, HFILL } |
943 | 5.41k | }, |
944 | 5.41k | { &hf_rach_est_cause_pag_resp, |
945 | 5.41k | { "Establishment Cause", "gmr1.rach.est_cause.pag_resp", |
946 | 5.41k | FT_UINT8, BASE_HEX, VALS(rach_est_cause_pag_resp_vals), 0x38, |
947 | 5.41k | NULL, HFILL } |
948 | 5.41k | }, |
949 | 5.41k | { &hf_rach_num_plan, |
950 | 5.41k | { "Numbering Plan Identification", "gmr1.rach.numbering_plan", |
951 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_num_plan_vals), 0x1e, |
952 | 5.41k | NULL, HFILL } |
953 | 5.41k | }, |
954 | 5.41k | { &hf_rach_chan_needed, |
955 | 5.41k | { "Channel Needed", "gmr1.rach.chan_needed", |
956 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_chan_needed_vals), 0x06, |
957 | 5.41k | "Echoed from Paging Request", HFILL } |
958 | 5.41k | }, |
959 | 5.41k | { &hf_rach_retry_cnt, |
960 | 5.41k | { "Retry Counter", "gmr1.rach.retry_counter", |
961 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0xc0, |
962 | 5.41k | "Retransmission count for current access attempt", HFILL } |
963 | 5.41k | }, |
964 | 5.41k | { &hf_rach_precorr, |
965 | 5.41k | { "Precorrection Indication", "gmr1.rach.precorr_ind", |
966 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_precorr_vals), 0xe0, |
967 | 5.41k | "This is the timing correction applied to RACH while " |
968 | 5.41k | "sending this message. See GMR 05.010.", HFILL } |
969 | 5.41k | }, |
970 | 5.41k | { &hf_rach_rand_ref, |
971 | 5.41k | { "Random Reference", "gmr1.rach.random_reference", |
972 | 5.41k | FT_UINT8, BASE_HEX, NULL, 0x1f, |
973 | 5.41k | "A random number of 5 bits", HFILL } |
974 | 5.41k | }, |
975 | 5.41k | { &hf_rach_gps_pos_cpi, |
976 | 5.41k | { "CPI", "gmr1.rach.gps_pos.cpi", |
977 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_gps_pos_cpi_tfs), 0x80, |
978 | 5.41k | "Current Position Indicator", HFILL } |
979 | 5.41k | }, |
980 | 5.41k | { &hf_rach_gps_pos_lat, |
981 | 5.41k | { "Latitude", "gmr1.rach.gps_pos.latitude", |
982 | 5.41k | FT_INT24, BASE_CUSTOM, CF_FUNC(rach_gps_pos_lat_fmt), 0x7ffff0, |
983 | 5.41k | NULL, HFILL } |
984 | 5.41k | }, |
985 | 5.41k | { &hf_rach_gps_pos_long, |
986 | 5.41k | { "Longitude", "gmr1.rach.gps_pos.longitude", |
987 | 5.41k | FT_INT24, BASE_CUSTOM, CF_FUNC(rach_gps_pos_long_fmt), 0x0fffff, |
988 | 5.41k | NULL, HFILL } |
989 | 5.41k | }, |
990 | 5.41k | { &hf_rach_mes_pwr_class, |
991 | 5.41k | { "MES Power Class", "gmr1.rach.mes_power_class", |
992 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0xf0, |
993 | 5.41k | "See GMR 05.005 for infos", HFILL } |
994 | 5.41k | }, |
995 | 5.41k | { &hf_rach_sp_hplmn_id, |
996 | 5.41k | { "SP/HPLMN ID", "gmr1.rach.sp_hplmn_id", |
997 | 5.41k | FT_UINT24, BASE_CUSTOM, CF_FUNC(rach_sp_hplmn_id_fmt), 0x0fffff, |
998 | 5.41k | NULL, HFILL } |
999 | 5.41k | }, |
1000 | 5.41k | { &hf_rach_pd, |
1001 | 5.41k | { "PD", "gmr1.rach.pd", |
1002 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_pd_vals), 0xc0, |
1003 | 5.41k | "Protocol Discriminator", HFILL } |
1004 | 5.41k | }, |
1005 | 5.41k | { &hf_rach_number, |
1006 | 5.41k | { "Dialed Number", "gmr1.rach.number", |
1007 | 5.41k | FT_STRING, BASE_NONE, NULL, 0x00, |
1008 | 5.41k | NULL, HFILL } |
1009 | 5.41k | }, |
1010 | 5.41k | { &hf_rach_number_grp1, |
1011 | 5.41k | { "Group 1", "gmr1.rach.number.grp1", |
1012 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_dialed_num_grp1234_fmt), 0x3ff0, |
1013 | 5.41k | NULL, HFILL } |
1014 | 5.41k | }, |
1015 | 5.41k | { &hf_rach_number_grp2, |
1016 | 5.41k | { "Group 2", "gmr1.rach.number.grp2", |
1017 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_dialed_num_grp1234_fmt), 0x0ffc, |
1018 | 5.41k | NULL, HFILL } |
1019 | 5.41k | }, |
1020 | 5.41k | { &hf_rach_number_grp3, |
1021 | 5.41k | { "Group 3", "gmr1.rach.number.grp3", |
1022 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_dialed_num_grp1234_fmt), 0x03ff, |
1023 | 5.41k | NULL, HFILL } |
1024 | 5.41k | }, |
1025 | 5.41k | { &hf_rach_number_grp4, |
1026 | 5.41k | { "Group 4", "gmr1.rach.number.grp4", |
1027 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_dialed_num_grp1234_fmt), 0xffc0, |
1028 | 5.41k | NULL, HFILL } |
1029 | 5.41k | }, |
1030 | 5.41k | { &hf_rach_number_grp5, |
1031 | 5.41k | { "Group 5", "gmr1.rach.number.grp5", |
1032 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_dialed_num_grp5_fmt), 0x3ff8, |
1033 | 5.41k | NULL, HFILL } |
1034 | 5.41k | }, |
1035 | 5.41k | { &hf_rach_msc_id, |
1036 | 5.41k | { "MSC ID", "gmr1.rach.msc_id", |
1037 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x3f, |
1038 | 5.41k | NULL, HFILL } |
1039 | 5.41k | }, |
1040 | 5.41k | { &hf_rach_gps_timestamp, |
1041 | 5.41k | { "GPS Timestamp", "gmr1.rach.gps_timestamp", |
1042 | 5.41k | FT_UINT16, BASE_CUSTOM, CF_FUNC(rach_gps_timestamp_fmt), 0xffff, |
1043 | 5.41k | NULL, HFILL } |
1044 | 5.41k | }, |
1045 | 5.41k | { &hf_rach_software_version, |
1046 | 5.41k | { "Software Version", "gmr1.rach.software_version", |
1047 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0xfe, |
1048 | 5.41k | NULL, HFILL } |
1049 | 5.41k | }, |
1050 | 5.41k | { &hf_rach_spare, |
1051 | 5.41k | { "Spare", "gmr1.rach.spare", |
1052 | 5.41k | FT_UINT32, BASE_DEC, NULL, 0x01fffff8, |
1053 | 5.41k | NULL, HFILL } |
1054 | 5.41k | }, |
1055 | 5.41k | { &hf_rach_gci, |
1056 | 5.41k | { "GCI", "gmr1.rach.gci", |
1057 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_gci_tfs), 0x01, |
1058 | 5.41k | "GPS Capability Indicator", HFILL } |
1059 | 5.41k | }, |
1060 | 5.41k | { &hf_rach_r, |
1061 | 5.41k | { "R", "gmr1.rach.r", |
1062 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_r_tfs), 0x02, |
1063 | 5.41k | "See GMR 04.008 10.1.8 for full description" , HFILL } |
1064 | 5.41k | }, |
1065 | 5.41k | { &hf_rach_o, |
1066 | 5.41k | { "O", "gmr1.rach.o", |
1067 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_o_tfs), 0x04, |
1068 | 5.41k | "See GMR 04.008 10.1.8 for full description", HFILL } |
1069 | 5.41k | }, |
1070 | 5.41k | { &hf_rach_number_type, |
1071 | 5.41k | { "Number Type", "gmr1.rach.number_type", |
1072 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_number_type_vals), 0x07, |
1073 | 5.41k | "For MO Call only", HFILL } |
1074 | 5.41k | }, |
1075 | 5.41k | { &hf_rach_gmprs_term_type, |
1076 | 5.41k | { "GmPRS Terminal Type", "gmr1.rach.gmprs_term_type", |
1077 | 5.41k | FT_UINT8, BASE_DEC | BASE_EXT_STRING, &rach_gmprs_term_type_ext_vals, 0x00, |
1078 | 5.41k | "See GMR-1 3G 45.002 Annex C for infos", HFILL } |
1079 | 5.41k | }, |
1080 | 5.41k | { &hf_rach_gmprs_radio_prio, |
1081 | 5.41k | { "Radio Priority", "gmr1.rach.gmprs_radio_prio", |
1082 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_gmprs_radio_prio_vals), 0x18, |
1083 | 5.41k | "See GMPRS-1 04.060 for infos", HFILL } |
1084 | 5.41k | }, |
1085 | 5.41k | { &hf_rach_gmprs_tlli, |
1086 | 5.41k | { "TLLI", "gmr1.rach.gmprs_tlli", |
1087 | 5.41k | FT_UINT32, BASE_HEX, NULL, 0x00, |
1088 | 5.41k | "See GMPRS-1 04.060 for infos", HFILL } |
1089 | 5.41k | }, |
1090 | 5.41k | { &hf_rach_gmprs_num_rlc_blks, |
1091 | 5.41k | { "Number of RLC blocks", "gmr1.rach.gmprs_num_rlc_blks", |
1092 | 5.41k | FT_UINT16, BASE_DEC, NULL, 0x00, |
1093 | 5.41k | "See GMPRS-1 04.060 12.31 for infos", HFILL } |
1094 | 5.41k | }, |
1095 | 5.41k | { &hf_rach_gmprs_peak_tput, |
1096 | 5.41k | { "Peak Throughput", "gmr1.rach.gmprs_peak_tput", |
1097 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x3c, |
1098 | 5.41k | "See GMPRS-1 04.060 for infos", HFILL } |
1099 | 5.41k | }, |
1100 | 5.41k | { &hf_rach_gmprs_dl_peak_tput, |
1101 | 5.41k | { "DL Peak Throughput", "gmr1.rach.gmprs_dl_peak_tput", |
1102 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x0f, |
1103 | 5.41k | "See 3GPP TS 23.060 for infos", HFILL } |
1104 | 5.41k | }, |
1105 | 5.41k | { &hf_rach_gmprs_ul_peak_tput, |
1106 | 5.41k | { "UL Peak Throughput", "gmr1.rach.gmprs_ul_peak_tput", |
1107 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x3c, |
1108 | 5.41k | "See 3GPP TS 23.060 for infos", HFILL } |
1109 | 5.41k | }, |
1110 | 5.41k | { &hf_rach_gmprs_rlc_mode, |
1111 | 5.41k | { "RLC mode", "gmr1.rach.gmprs_rlc_mode", |
1112 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_gmprs_rlc_mode_tfs), 0x01, |
1113 | 5.41k | NULL, HFILL } |
1114 | 5.41k | }, |
1115 | 5.41k | { &hf_rach_gmprs_llc_mode, |
1116 | 5.41k | { "LLC mode", "gmr1.rach.gmprs_llc_mode", |
1117 | 5.41k | FT_BOOLEAN, 8, TFS(&rach_gmprs_llc_mode_tfs), 0x02, |
1118 | 5.41k | NULL, HFILL } |
1119 | 5.41k | }, |
1120 | 5.41k | { &hf_rach_gmprs_spare1, |
1121 | 5.41k | { "Spare", "gmr1.rach.gmprs_spare1", |
1122 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x20, |
1123 | 5.41k | NULL, HFILL } |
1124 | 5.41k | }, |
1125 | 5.41k | { &hf_rach_gmprs_spare2, |
1126 | 5.41k | { "Spare", "gmr1.rach.gmprs_spare2", |
1127 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0xc0, |
1128 | 5.41k | NULL, HFILL } |
1129 | 5.41k | }, |
1130 | 5.41k | { &hf_rach_gmprs_spare3, |
1131 | 5.41k | { "Spare", "gmr1.rach.gmprs_spare3", |
1132 | 5.41k | FT_UINT8, BASE_DEC, NULL, 0x04, |
1133 | 5.41k | NULL, HFILL } |
1134 | 5.41k | }, |
1135 | 5.41k | { &hf_rach_gmprs_reserved1, |
1136 | 5.41k | { "Reserved", "gmr1.rach.gmprs_reserved1", |
1137 | 5.41k | FT_UINT16, BASE_HEX, NULL, 0xffff, |
1138 | 5.41k | NULL, HFILL } |
1139 | 5.41k | }, |
1140 | 5.41k | { &hf_rach_gmprs_req_type, |
1141 | 5.41k | { "Request Type", "gmr1.rach.gmprs_req_type", |
1142 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_gmprs_req_type_vals), 0x1f, |
1143 | 5.41k | NULL, HFILL } |
1144 | 5.41k | }, |
1145 | 5.41k | { &hf_rach_gmprs_req_type_pag_resp, |
1146 | 5.41k | { "Request Type", "gmr1.rach.gmprs_req_type.pag_resp", |
1147 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_gmprs_req_type_pag_resp_vals), 0x1c, |
1148 | 5.41k | NULL, HFILL } |
1149 | 5.41k | }, |
1150 | 5.41k | { &hf_rach_gmprs_chan_needed, |
1151 | 5.41k | { "Channel Needed", "gmr1.rach.gmprs_chan_needed", |
1152 | 5.41k | FT_UINT8, BASE_DEC, VALS(rach_chan_needed_vals), 0x03, |
1153 | 5.41k | "Echoed from Paging Request", HFILL } |
1154 | 5.41k | }, |
1155 | 5.41k | }; |
1156 | | |
1157 | 5.41k | static gint *ett[] = { |
1158 | 5.41k | &ett_rach_msg, |
1159 | 5.41k | &ett_rach_kls1, |
1160 | 5.41k | &ett_rach_kls2, |
1161 | 5.41k | &ett_rach_gmprs_type1_kls2, |
1162 | 5.41k | &ett_rach_gmprs_type2_kls2, |
1163 | 5.41k | &ett_rach_est_cause, |
1164 | 5.41k | &ett_rach_dialed_num, |
1165 | 5.41k | &ett_rach_gps_pos, |
1166 | 5.41k | &ett_rach_gmprs_req_type, |
1167 | 5.41k | }; |
1168 | | |
1169 | 5.41k | proto_gmr1_rach = proto_register_protocol("GEO-Mobile Radio (1) RACH", "GMR-1 RACH", "gmr1.rach"); |
1170 | | |
1171 | 5.41k | proto_register_field_array(proto_gmr1_rach, hf, array_length(hf)); |
1172 | 5.41k | proto_register_subtree_array(ett, array_length(ett)); |
1173 | | |
1174 | 5.41k | register_dissector("gmr1_rach", dissect_gmr1_rach, proto_gmr1_rach); |
1175 | 5.41k | } |
1176 | | |
1177 | | /* |
1178 | | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
1179 | | * |
1180 | | * Local variables: |
1181 | | * c-basic-offset: 8 |
1182 | | * tab-width: 8 |
1183 | | * indent-tabs-mode: t |
1184 | | * End: |
1185 | | * |
1186 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1187 | | * :indentSize=8:tabSize=8:noTabs=false: |
1188 | | */ |