/src/wireshark/epan/dissectors/packet-fp_hint.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Routines for UMTS FP Hint protocol disassembly |
2 | | * |
3 | | * Wireshark - Network traffic analyzer |
4 | | * By Gerald Combs <gerald@wireshark.org> |
5 | | * Copyright 1998 Gerald Combs |
6 | | * |
7 | | * SPDX-License-Identifier: GPL-2.0-or-later |
8 | | */ |
9 | | |
10 | | #include "config.h" |
11 | | |
12 | | |
13 | | #include <epan/packet.h> |
14 | | #include <wiretap/wtap.h> |
15 | | #include <epan/tfs.h> |
16 | | #include <epan/expert.h> |
17 | | #include <epan/proto_data.h> |
18 | | #include "packet-umts_fp.h" |
19 | | #include "packet-umts_mac.h" |
20 | | #include "packet-umts_rlc.h" |
21 | | |
22 | | void proto_register_fp_hint(void); |
23 | | void proto_reg_handoff_fp_hint(void); |
24 | | |
25 | | static int proto_fp_hint; |
26 | | extern int proto_fp; |
27 | | extern int proto_umts_mac; |
28 | | extern int proto_umts_rlc; |
29 | | |
30 | | static int ett_fph; |
31 | | static int ett_fph_rb; |
32 | | static int ett_fph_ddi_entry; |
33 | | static int ett_fph_tf; |
34 | | |
35 | | static int hf_fph_frametype; |
36 | | static int hf_fph_channeltype; |
37 | | static int hf_fph_chcnt; |
38 | | static int hf_fph_dchid; |
39 | | static int hf_fph_urnti; |
40 | | static int hf_fph_rlcmode; |
41 | | static int hf_fph_content; |
42 | | static int hf_fph_rbid; |
43 | | static int hf_fph_ctmux; |
44 | | static int hf_fph_ciphered; |
45 | | static int hf_fph_deciphered; |
46 | | static int hf_fph_macdflowid; |
47 | | static int hf_fph_macehs; |
48 | | static int hf_fph_rb; |
49 | | static int hf_fph_ddi_entry; |
50 | | static int hf_fph_ddi_size; |
51 | | static int hf_fph_ddi_logical; |
52 | | static int hf_fph_ddi_value; |
53 | | static int hf_fph_tf; |
54 | | static int hf_fph_tf_n; |
55 | | static int hf_fph_tf_size; |
56 | | |
57 | | static expert_field ei_fph_radio_bearers; |
58 | | static expert_field ei_fph_mac_frames; |
59 | | static expert_field ei_fph_fp_channels; |
60 | | |
61 | | static dissector_handle_t data_handle; |
62 | | static dissector_handle_t ethwithfcs_handle; |
63 | | static dissector_handle_t atm_untrunc_handle; |
64 | | |
65 | | enum fph_ctype { |
66 | | FPH_CHANNEL_PCH, |
67 | | FPH_CHANNEL_RACH, |
68 | | FPH_CHANNEL_FACH, |
69 | | FPH_CHANNEL_DCH, |
70 | | FPH_CHANNEL_HSDSCH, |
71 | | FPH_CHANNEL_EDCH |
72 | | }; |
73 | | |
74 | | enum fph_frame { |
75 | | FPH_FRAME_ATM_AAL2, |
76 | | FPH_FRAME_ETHERNET |
77 | | }; |
78 | | |
79 | | enum fph_pich { |
80 | | FPH_PICH18, |
81 | | FPH_PICH36, |
82 | | FPH_PICH72, |
83 | | FPH_PICH144 |
84 | | }; |
85 | | |
86 | | enum fph_content { |
87 | | FPH_CONTENT_UNKNOWN, |
88 | | FPH_CONTENT_DCCH, |
89 | | FPH_CONTENT_PS_DTCH, |
90 | | FPH_CONTENT_CS_DTCH |
91 | | }; |
92 | | |
93 | | static const value_string fph_frametype_vals[] = { |
94 | | { FPH_FRAME_ATM_AAL2, "ATM AAL2" }, |
95 | | { FPH_FRAME_ETHERNET, "Ethernet" }, |
96 | | { 0, NULL } |
97 | | }; |
98 | | |
99 | | static const value_string fph_channeltype_vals[] = { |
100 | | { FPH_CHANNEL_PCH, "PCH" }, |
101 | | { FPH_CHANNEL_RACH, "RACH" }, |
102 | | { FPH_CHANNEL_FACH, "FACH" }, |
103 | | { FPH_CHANNEL_DCH, "DCH" }, |
104 | | { FPH_CHANNEL_HSDSCH, "HSDSCH" }, |
105 | | { FPH_CHANNEL_EDCH, "E-DCH" }, |
106 | | { 0, NULL } |
107 | | }; |
108 | | |
109 | | static const value_string fph_rlcmode_vals[] = { |
110 | | { RLC_TM, "Transparent Mode" }, |
111 | | { RLC_UM, "Unacknowledged Mode" }, |
112 | | { RLC_AM, "Acknowledged Mode" }, |
113 | | { 0, NULL } |
114 | | }; |
115 | | |
116 | | static const value_string fph_content_vals[] = { |
117 | | { FPH_CONTENT_UNKNOWN, "Unknown" }, |
118 | | { FPH_CONTENT_DCCH, "DCCH" }, |
119 | | { FPH_CONTENT_PS_DTCH, "PS DTCH" }, |
120 | | { FPH_CONTENT_CS_DTCH, "PS DTCH" }, |
121 | | { 0, NULL } |
122 | | }; |
123 | | |
124 | | static const true_false_string fph_ctmux_vals = { |
125 | | "C/T Mux field present", "C/T Mux field not present" |
126 | | }; |
127 | | |
128 | | static const true_false_string fph_ciphered_vals = { |
129 | | "Ciphered", "Not ciphered" |
130 | | }; |
131 | | |
132 | | static const true_false_string fph_deciphered_vals = { |
133 | | "Deciphered", "Not deciphered" |
134 | | }; |
135 | | |
136 | | static uint16_t assign_rb_info(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, uint8_t rbcnt, proto_tree *tree) |
137 | 0 | { |
138 | 0 | uint8_t i = 0, next_byte; |
139 | 0 | uint8_t rlc_mode, content, rb_id, ctmux, ciphered, deciphered; |
140 | 0 | uint32_t urnti; |
141 | 0 | struct umts_mac_info *macinf; |
142 | 0 | struct rlc_info *rlcinf; |
143 | |
|
144 | 0 | macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0); |
145 | 0 | rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0); |
146 | 0 | if (!macinf) { |
147 | 0 | macinf = wmem_new0(wmem_file_scope(), struct umts_mac_info); |
148 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
149 | 0 | } |
150 | 0 | if (!rlcinf) { |
151 | 0 | rlcinf = wmem_new0(wmem_file_scope(), struct rlc_info); |
152 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
153 | 0 | } |
154 | |
|
155 | 0 | while (i < rbcnt) { |
156 | 0 | urnti = tvb_get_letohl(tvb, offset); |
157 | 0 | next_byte = tvb_get_uint8(tvb, offset + 4); |
158 | 0 | rlc_mode = next_byte & 0x3; |
159 | 0 | content = (next_byte >> 2) & 0x3; |
160 | 0 | rb_id = next_byte >> 4; |
161 | 0 | next_byte = tvb_get_uint8(tvb, offset + 5); |
162 | 0 | rb_id |= (next_byte & 0x01) << 4; |
163 | 0 | ctmux = (next_byte >> 1) & 0x1; |
164 | 0 | ciphered = (next_byte >> 2) & 0x1; |
165 | 0 | deciphered = (next_byte >> 3) & 0x1; |
166 | |
|
167 | 0 | if (i >= MAX_RLC_CHANS) { |
168 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_fph_radio_bearers, tvb, offset, -1, |
169 | 0 | "Frame contains more Radio Bearers than currently supported (%u present, %u supported)", |
170 | 0 | rbcnt, MAX_RLC_CHANS); |
171 | 0 | return -1; |
172 | 0 | } |
173 | 0 | if (i >= MAX_MAC_FRAMES) { |
174 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_fph_mac_frames, tvb, offset, -1, |
175 | 0 | "Frame contains more MAC Frames than currently supported (%u present, %u supported)", |
176 | 0 | rbcnt, MAX_MAC_FRAMES); |
177 | 0 | return -1; |
178 | 0 | } |
179 | | |
180 | 0 | rlcinf->mode[i] = rlc_mode; |
181 | 0 | rlcinf->rbid[i] = rb_id; |
182 | 0 | rlcinf->ueid[i] = urnti; |
183 | 0 | rlcinf->ciphered[i] = ciphered; |
184 | 0 | rlcinf->deciphered[i] = deciphered; |
185 | 0 | rlcinf->li_size[i] = RLC_LI_VARIABLE; |
186 | |
|
187 | 0 | macinf->ctmux[i] = ctmux ? true : false; |
188 | 0 | switch (content) { |
189 | 0 | case FPH_CONTENT_DCCH: |
190 | 0 | macinf->content[i] = MAC_CONTENT_DCCH; |
191 | 0 | break; |
192 | 0 | case FPH_CONTENT_PS_DTCH: |
193 | 0 | macinf->content[i] = MAC_CONTENT_PS_DTCH; |
194 | 0 | break; |
195 | 0 | case FPH_CONTENT_CS_DTCH: |
196 | 0 | macinf->content[i] = MAC_CONTENT_CS_DTCH; |
197 | 0 | break; |
198 | 0 | default: |
199 | 0 | macinf->content[i] = MAC_CONTENT_UNKNOWN; |
200 | 0 | } |
201 | | |
202 | 0 | if (tree) { |
203 | 0 | proto_tree *subtree; |
204 | 0 | proto_item *pi; |
205 | |
|
206 | 0 | pi = proto_tree_add_item(tree, hf_fph_rb, tvb, offset, 8, ENC_NA); |
207 | 0 | subtree = proto_item_add_subtree(pi, ett_fph_rb); |
208 | |
|
209 | 0 | if (urnti) |
210 | 0 | proto_tree_add_uint(subtree, hf_fph_urnti, tvb, offset, 4, urnti); |
211 | 0 | proto_tree_add_bits_item(subtree, hf_fph_content, tvb, (offset+4)*8+4, 2, ENC_LITTLE_ENDIAN); |
212 | 0 | proto_tree_add_bits_item(subtree, hf_fph_rlcmode, tvb, (offset+4)*8+6, 2, ENC_LITTLE_ENDIAN); |
213 | 0 | proto_tree_add_item(subtree, hf_fph_rbid, tvb, (offset+4), 2, ENC_LITTLE_ENDIAN); |
214 | 0 | proto_tree_add_boolean(subtree, hf_fph_ctmux, tvb, offset+5, 1, ctmux); |
215 | 0 | proto_tree_add_boolean(subtree, hf_fph_ciphered, tvb, offset+5, 1, ciphered); |
216 | 0 | proto_tree_add_boolean(subtree, hf_fph_deciphered, tvb, offset+5, 1, deciphered); |
217 | 0 | } |
218 | 0 | offset += 8; |
219 | 0 | i++; |
220 | 0 | } |
221 | 0 | return offset; |
222 | 0 | } |
223 | | |
224 | | static void assign_fph_pch(tvbuff_t *tvb, packet_info *pinfo _U_, uint16_t offset, fp_info *fpi, proto_tree *tree _U_) |
225 | 0 | { |
226 | 0 | uint8_t pich; |
227 | 0 | uint16_t blkcnt, blksz; |
228 | 0 | const uint8_t *hdr; |
229 | |
|
230 | 0 | fpi->channel = CHANNEL_PCH; |
231 | |
|
232 | 0 | hdr = tvb_get_ptr(tvb, offset, 4); |
233 | 0 | blkcnt = hdr[0] | ((hdr[1] & 0x01) << 8); |
234 | 0 | blksz = (hdr[1] >> 1) | ((hdr[2] & 0x3f) << 7); |
235 | 0 | pich = (hdr[2] >> 6) | ((hdr[3] & 0x01) << 2); |
236 | |
|
237 | 0 | switch (pich) { |
238 | 0 | case FPH_PICH18: |
239 | 0 | fpi->paging_indications = 18; |
240 | 0 | break; |
241 | 0 | case FPH_PICH36: |
242 | 0 | fpi->paging_indications = 36; |
243 | 0 | break; |
244 | 0 | case FPH_PICH72: |
245 | 0 | fpi->paging_indications = 72; |
246 | 0 | break; |
247 | 0 | case FPH_PICH144: |
248 | 0 | fpi->paging_indications = 144; |
249 | 0 | break; |
250 | 0 | default: |
251 | 0 | fpi->paging_indications = 0; |
252 | 0 | } |
253 | 0 | fpi->num_chans = 1; |
254 | 0 | fpi->chan_tf_size[0] = blksz; |
255 | 0 | fpi->chan_num_tbs[0] = blkcnt; |
256 | 0 | } |
257 | | |
258 | | static void assign_fph_rach(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, fp_info *fpi, proto_tree *tree) |
259 | 0 | { |
260 | 0 | const uint8_t *hdr; |
261 | 0 | uint8_t rbcnt; |
262 | 0 | uint16_t blkcnt, blksz; |
263 | |
|
264 | 0 | fpi->channel = CHANNEL_RACH_FDD; |
265 | |
|
266 | 0 | hdr = tvb_get_ptr(tvb, offset, 4); |
267 | 0 | blkcnt = hdr[0] | ((hdr[1] & 0x01) << 8); |
268 | 0 | blksz = (hdr[1] >> 1) | ((hdr[2] & 0x3f) << 7); |
269 | |
|
270 | 0 | fpi->num_chans = 1; |
271 | 0 | fpi->chan_tf_size[0] = blksz; |
272 | 0 | fpi->chan_num_tbs[0] = blkcnt; |
273 | |
|
274 | 0 | offset += 4; |
275 | 0 | rbcnt = tvb_get_uint8(tvb, offset); offset++; |
276 | 0 | if (rbcnt > 0) |
277 | 0 | /*offset =*/ assign_rb_info(tvb, pinfo, offset, rbcnt, tree); |
278 | 0 | } |
279 | | |
280 | | static void assign_fph_dch(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, fp_info *fpi, proto_tree *tree) |
281 | 0 | { |
282 | 0 | uint8_t dch_id, rbcnt; |
283 | 0 | uint16_t N, size; |
284 | 0 | uint32_t cnt, i = 0; |
285 | 0 | const uint8_t *hdr; |
286 | 0 | proto_tree *subtree; |
287 | 0 | proto_item *pi; |
288 | |
|
289 | 0 | fpi->channel = CHANNEL_DCH; |
290 | 0 | cnt = tvb_get_uint8(tvb, offset); offset++; |
291 | |
|
292 | 0 | if (tree) |
293 | 0 | proto_tree_add_uint(tree, hf_fph_chcnt, tvb, offset-1, 1, cnt); |
294 | |
|
295 | 0 | fpi->num_chans = cnt; |
296 | 0 | fpi->dch_crc_present = 1; |
297 | 0 | while (i < cnt) { |
298 | 0 | pi = proto_tree_add_item(tree, hf_fph_tf, tvb, offset, 4, ENC_NA); |
299 | 0 | subtree = proto_item_add_subtree(pi, ett_fph_rb); |
300 | 0 | hdr = tvb_get_ptr(tvb, offset, 4); |
301 | 0 | dch_id = (hdr[0] & 0x1f) + 1; |
302 | |
|
303 | 0 | N = ((hdr[1] & 0x3f)<<3) | (hdr[0] >> 5); |
304 | 0 | size = ((hdr[3] & 0x07)<<10) | (hdr[2] << 2) | ((hdr[1] & 0xc0)>>6); |
305 | 0 | size = size == 0x1fff ? 0 : size; |
306 | |
|
307 | 0 | fpi->chan_tf_size[i] = size; |
308 | 0 | fpi->chan_num_tbs[i] = N; |
309 | |
|
310 | 0 | if (subtree) { |
311 | 0 | proto_tree_add_uint(subtree, hf_fph_dchid, tvb, offset, 1, dch_id); |
312 | 0 | proto_tree_add_uint(subtree, hf_fph_tf_n, tvb, offset, 2, N); |
313 | 0 | if (size) |
314 | 0 | proto_tree_add_uint(subtree, hf_fph_tf_size, tvb, offset + 1, 3, size); |
315 | 0 | } |
316 | 0 | offset += 4; |
317 | 0 | if (i > MAX_FP_CHANS) { |
318 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_fph_fp_channels, tvb, offset, -1, |
319 | 0 | "Frame contains more FP channels than currently supported (%u supported)", |
320 | 0 | MAX_FP_CHANS); |
321 | 0 | return; |
322 | 0 | } |
323 | 0 | i++; |
324 | 0 | } |
325 | 0 | rbcnt = tvb_get_uint8(tvb, offset); offset++; |
326 | 0 | if (rbcnt > 0) |
327 | 0 | /*offset =*/ assign_rb_info(tvb, pinfo, offset, rbcnt, tree); |
328 | 0 | } |
329 | | |
330 | | static void assign_fph_fach(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, fp_info *fpi, proto_tree *tree) |
331 | 0 | { |
332 | 0 | const uint8_t *hdr; |
333 | 0 | uint8_t rbcnt; |
334 | 0 | uint16_t blkcnt, blksz; |
335 | |
|
336 | 0 | fpi->channel = CHANNEL_FACH_FDD; |
337 | |
|
338 | 0 | hdr = tvb_get_ptr(tvb, offset, 4); |
339 | 0 | blkcnt = hdr[0] | ((hdr[1] & 0x01) << 8); |
340 | 0 | blksz = (hdr[1] >> 1) | ((hdr[2] & 0x3f) << 7); |
341 | |
|
342 | 0 | fpi->num_chans = 1; |
343 | 0 | fpi->chan_tf_size[0] = blksz; |
344 | 0 | fpi->chan_num_tbs[0] = blkcnt; |
345 | |
|
346 | 0 | offset += 4; |
347 | 0 | rbcnt = tvb_get_uint8(tvb, offset); offset++; |
348 | 0 | if (rbcnt > 0) |
349 | 0 | /*offset =*/ assign_rb_info(tvb, pinfo, offset, rbcnt, tree); |
350 | 0 | } |
351 | | |
352 | | static void assign_fph_hsdsch(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, fp_info *fpi, proto_tree *tree) |
353 | 0 | { |
354 | 0 | uint8_t rbcnt, hsdsch_info; |
355 | |
|
356 | 0 | hsdsch_info = tvb_get_uint8(tvb, offset); |
357 | 0 | fpi->hsdsch_entity = hsdsch_info & 0x08 ? ehs : hs; |
358 | 0 | fpi->channel = CHANNEL_HSDSCH; |
359 | |
|
360 | 0 | if (tree) { |
361 | 0 | proto_tree_add_bits_item(tree, hf_fph_macehs, tvb, |
362 | 0 | offset*8+4, 1, ENC_LITTLE_ENDIAN); |
363 | 0 | proto_tree_add_bits_item(tree, hf_fph_macdflowid, tvb, |
364 | 0 | offset*8+5, 3, ENC_LITTLE_ENDIAN); |
365 | 0 | } |
366 | |
|
367 | 0 | offset++; |
368 | 0 | rbcnt = tvb_get_uint8(tvb, offset); offset++; |
369 | 0 | if (rbcnt > 0) |
370 | 0 | /*offset =*/ assign_rb_info(tvb, pinfo, offset, rbcnt, tree); |
371 | 0 | } |
372 | | |
373 | | static void assign_fph_edch(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, fp_info *fpi, proto_tree *tree) |
374 | 0 | { |
375 | 0 | uint8_t rbcnt, macdflow_id, maces_cnt, i = 0; |
376 | 0 | uint8_t logical, ddi; |
377 | 0 | uint16_t maces_size; |
378 | 0 | proto_item *pi; |
379 | 0 | proto_tree *subtree = NULL; |
380 | |
|
381 | 0 | fpi->channel = CHANNEL_EDCH; |
382 | 0 | macdflow_id = tvb_get_uint8(tvb, offset); |
383 | |
|
384 | 0 | if (tree) { |
385 | 0 | proto_tree_add_uint(tree, hf_fph_macdflowid, tvb, offset, 1, macdflow_id); |
386 | 0 | } |
387 | |
|
388 | 0 | offset++; |
389 | 0 | maces_cnt = tvb_get_uint8(tvb, offset); offset++; |
390 | |
|
391 | 0 | fpi->no_ddi_entries = maces_cnt; |
392 | 0 | while (i < maces_cnt) { |
393 | 0 | ddi = tvb_get_uint8(tvb, offset++); |
394 | 0 | logical = tvb_get_uint8(tvb, offset++); |
395 | 0 | maces_size = tvb_get_letohs(tvb, offset); |
396 | 0 | offset += 2; |
397 | 0 | fpi->edch_ddi[i] = ddi; |
398 | 0 | fpi->edch_macd_pdu_size[i] = maces_size; |
399 | 0 | if (tree) { |
400 | 0 | pi = proto_tree_add_item(tree, hf_fph_ddi_entry, tvb, offset - 4, 4, ENC_NA); |
401 | 0 | subtree = proto_item_add_subtree(pi, ett_fph_ddi_entry); |
402 | 0 | proto_tree_add_uint(subtree, hf_fph_ddi_value, tvb, offset - 4, 1, ddi); |
403 | 0 | proto_tree_add_uint(subtree, hf_fph_ddi_logical, tvb, offset - 3, 1, logical); |
404 | 0 | proto_tree_add_uint(subtree, hf_fph_ddi_size, tvb, offset - 2, 2, maces_size); |
405 | 0 | } |
406 | 0 | i++; |
407 | 0 | if (i >= MAX_EDCH_DDIS) { |
408 | 0 | proto_tree_add_expert_format(tree, pinfo, &ei_fph_fp_channels, tvb, offset, -1, |
409 | 0 | "Frame contains more FP channels than currently supported (%u supported)", |
410 | 0 | MAX_FP_CHANS); |
411 | 0 | return; |
412 | 0 | } |
413 | 0 | } |
414 | | |
415 | | |
416 | 0 | rbcnt = tvb_get_uint8(tvb, offset); offset++; |
417 | 0 | if (rbcnt > 0) |
418 | 0 | /*offset =*/ assign_rb_info(tvb, pinfo, offset, rbcnt, tree); |
419 | 0 | } |
420 | | |
421 | | static void attach_info(tvbuff_t *tvb, packet_info *pinfo, uint16_t offset, uint8_t channel_type, uint8_t frame_type, proto_tree *tree) |
422 | 0 | { |
423 | 0 | fp_info *fpi; |
424 | |
|
425 | 0 | fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
426 | 0 | if (!fpi) { |
427 | 0 | fpi = wmem_new0(wmem_file_scope(), fp_info); |
428 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, fpi); |
429 | 0 | } |
430 | |
|
431 | 0 | fpi->is_uplink = pinfo->p2p_dir == P2P_DIR_RECV; |
432 | | /* TODO make this configurable */ |
433 | 0 | fpi->release = 7; |
434 | 0 | fpi->release_year = 2008; |
435 | 0 | fpi->release_month = 9; |
436 | 0 | fpi->dch_crc_present = 1; |
437 | |
|
438 | 0 | switch (frame_type) { |
439 | 0 | case FPH_FRAME_ATM_AAL2: |
440 | 0 | fpi->link_type = FP_Link_ATM; |
441 | 0 | break; |
442 | 0 | case FPH_FRAME_ETHERNET: |
443 | 0 | fpi->link_type = FP_Link_Ethernet; |
444 | 0 | break; |
445 | 0 | default: |
446 | 0 | fpi->link_type = FP_Link_Unknown; |
447 | 0 | } |
448 | | |
449 | | /* at the moment, only IuB is supported */ |
450 | 0 | fpi->iface_type = IuB_Interface; |
451 | | /* at the moment, only FDD is supported */ |
452 | 0 | fpi->division = Division_FDD; |
453 | |
|
454 | 0 | switch (channel_type) { |
455 | 0 | case FPH_CHANNEL_PCH: |
456 | 0 | assign_fph_pch(tvb, pinfo, offset, fpi, tree); |
457 | 0 | break; |
458 | 0 | case FPH_CHANNEL_RACH: |
459 | 0 | assign_fph_rach(tvb, pinfo, offset, fpi, tree); |
460 | 0 | break; |
461 | 0 | case FPH_CHANNEL_FACH: |
462 | 0 | assign_fph_fach(tvb, pinfo, offset, fpi, tree); |
463 | 0 | break; |
464 | 0 | case FPH_CHANNEL_DCH: |
465 | 0 | assign_fph_dch(tvb, pinfo, offset, fpi, tree); |
466 | 0 | break; |
467 | 0 | case FPH_CHANNEL_HSDSCH: |
468 | 0 | assign_fph_hsdsch(tvb, pinfo, offset, fpi, tree); |
469 | 0 | break; |
470 | 0 | case FPH_CHANNEL_EDCH: |
471 | 0 | assign_fph_edch(tvb, pinfo, offset, fpi, tree); |
472 | 0 | break; |
473 | 0 | default: |
474 | 0 | fpi->channel = 0; |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | | static int dissect_fp_hint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
479 | 0 | { |
480 | 0 | uint8_t frame_type, channel_type; |
481 | 0 | uint16_t hdrlen; |
482 | 0 | uint32_t atm_hdr, aal2_ext; |
483 | 0 | tvbuff_t *next_tvb; |
484 | 0 | dissector_handle_t next_dissector; |
485 | 0 | void *next_dissector_data; |
486 | 0 | proto_item *ti; |
487 | 0 | proto_tree *fph_tree = NULL; |
488 | 0 | struct atm_phdr atm_info; |
489 | |
|
490 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "FP Hint"); |
491 | |
|
492 | 0 | hdrlen = tvb_get_letohs(tvb, 0); |
493 | 0 | frame_type = tvb_get_uint8(tvb, 2); |
494 | 0 | channel_type = tvb_get_uint8(tvb, 3); |
495 | |
|
496 | 0 | if (tree) { |
497 | 0 | ti = proto_tree_add_item(tree, proto_fp_hint, tvb, 0, hdrlen, ENC_NA); |
498 | 0 | fph_tree = proto_item_add_subtree(ti, ett_fph); |
499 | 0 | proto_tree_add_uint(fph_tree, hf_fph_frametype, tvb, 2, 1, frame_type); |
500 | 0 | proto_tree_add_uint(fph_tree, hf_fph_channeltype, tvb, 3, 1, channel_type); |
501 | 0 | } |
502 | | |
503 | | /* attach FP, MAC, RLC information */ |
504 | 0 | attach_info(tvb, pinfo, 4, channel_type, frame_type, fph_tree); |
505 | 0 | switch (frame_type) { |
506 | 0 | case FPH_FRAME_ATM_AAL2: |
507 | 0 | aal2_ext = tvb_get_ntohl(tvb, hdrlen); hdrlen += 4; |
508 | 0 | atm_hdr = tvb_get_ntohl(tvb, hdrlen); hdrlen += 4; |
509 | 0 | memset(&atm_info, 0, sizeof(atm_info)); |
510 | 0 | atm_info.aal = AAL_2; |
511 | | /* atm_info.flags = pinfo->p2p_dir; */ |
512 | 0 | atm_info.flags = ATM_AAL2_NOPHDR; |
513 | 0 | atm_info.vpi = ((atm_hdr & 0x0ff00000) >> 20); |
514 | 0 | atm_info.vci = ((atm_hdr & 0x000ffff0) >> 4); |
515 | 0 | atm_info.aal2_cid = aal2_ext & 0x000000ff; |
516 | 0 | atm_info.type = TRAF_UMTS_FP; |
517 | 0 | next_dissector = atm_untrunc_handle; |
518 | 0 | next_dissector_data = &atm_info; |
519 | 0 | break; |
520 | 0 | case FPH_FRAME_ETHERNET: |
521 | 0 | next_dissector = ethwithfcs_handle; |
522 | 0 | next_dissector_data = NULL; |
523 | 0 | break; |
524 | 0 | default: |
525 | 0 | next_dissector = data_handle; |
526 | 0 | next_dissector_data = NULL; |
527 | 0 | break; |
528 | 0 | } |
529 | | |
530 | 0 | next_tvb = tvb_new_subset_remaining(tvb, hdrlen); |
531 | 0 | call_dissector_with_data(next_dissector, next_tvb, pinfo, tree, |
532 | 0 | next_dissector_data); |
533 | 0 | return tvb_captured_length(tvb); |
534 | 0 | } |
535 | | |
536 | | void |
537 | | proto_register_fp_hint(void) |
538 | 14 | { |
539 | 14 | static hf_register_info hf[] = { |
540 | 14 | { &hf_fph_frametype, { "Frame Type", "fp_hint.frame_type", FT_UINT8, BASE_HEX, VALS(fph_frametype_vals), 0x0, NULL, HFILL } }, |
541 | 14 | { &hf_fph_channeltype, { "Channel Type", "fp_hint.channel_type", FT_UINT8, BASE_HEX, VALS(fph_channeltype_vals), 0x0, NULL, HFILL } }, |
542 | 14 | { &hf_fph_chcnt, { "Number of Channels", "fp_hint.num_chan", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, |
543 | 14 | { &hf_fph_dchid, { "DCH ID", "fp_hint.dchid", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, |
544 | 14 | { &hf_fph_macdflowid, { "MACd Flow ID", "fp_hint.macdflowid", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, |
545 | 14 | { &hf_fph_macehs, { "MAC-ehs indicator", "fp_hint.mac_ehs", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL } }, |
546 | | /* traffic format details */ |
547 | 14 | { &hf_fph_tf, { "Traffic Format", "fp_hint.tf", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, |
548 | 14 | { &hf_fph_tf_n, { "N", "fp_hint.tf.n", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, |
549 | 14 | { &hf_fph_tf_size, { "Size", "fp_hint.tf.size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, |
550 | | /* DDI information for E-DCH */ |
551 | 14 | { &hf_fph_ddi_entry, { "DDI Entry", "fp_hint.ddi", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, |
552 | 14 | { &hf_fph_ddi_value, { "DDI", "fp_hint.ddi.value", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, |
553 | 14 | { &hf_fph_ddi_logical, { "Logical Channel ID", "fp_hint.ddi.logical", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, |
554 | 14 | { &hf_fph_ddi_size, { "Size", "fp_hint.ddi.size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, |
555 | | /* radio bearer details */ |
556 | 14 | { &hf_fph_rb, { "Radio Bearer", "fp_hint.rb", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, |
557 | 14 | { &hf_fph_urnti, { "U-RNTI", "fp_hint.rb.urnti", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, |
558 | 14 | { &hf_fph_content, { "Content", "fp_hint.rb.content", FT_UINT8, BASE_DEC, VALS(fph_content_vals), 0, NULL, HFILL } }, |
559 | 14 | { &hf_fph_rlcmode, { "RLC Mode", "fp_hint.rb.rlc_mode", FT_UINT8, BASE_DEC, VALS(fph_rlcmode_vals), 0, NULL, HFILL } }, |
560 | 14 | { &hf_fph_rbid, { "Radio Bearer ID", "fp_hint.rb.rbid", FT_UINT16, BASE_DEC, NULL, 0x01f0, NULL, HFILL } }, |
561 | 14 | { &hf_fph_ctmux, { "C/T Mux", "fp_hint.rb.ctmux", FT_BOOLEAN, BASE_NONE, TFS(&fph_ctmux_vals), 0, "C/T Mux field", HFILL } }, |
562 | 14 | { &hf_fph_ciphered, { "Ciphered", "fp_hint.rb.ciphered", FT_BOOLEAN, BASE_NONE, TFS(&fph_ciphered_vals), 0, "Ciphered flag", HFILL } }, |
563 | 14 | { &hf_fph_deciphered, { "Deciphered", "fp_hint.rb.deciphered", FT_BOOLEAN, BASE_NONE, TFS(&fph_deciphered_vals), 0, "Deciphered flag", HFILL } } |
564 | 14 | }; |
565 | | |
566 | 14 | static int *ett[] = { |
567 | 14 | &ett_fph, |
568 | 14 | &ett_fph_rb, |
569 | 14 | &ett_fph_ddi_entry, |
570 | 14 | &ett_fph_tf |
571 | 14 | }; |
572 | | |
573 | 14 | static ei_register_info ei[] = { |
574 | 14 | { &ei_fph_radio_bearers, { "fp_hint.rb.invalid", PI_PROTOCOL, PI_WARN, "Frame contains more Radio Bearers than currently supported", EXPFILL }}, |
575 | 14 | { &ei_fph_mac_frames, { "fp_hint.mac_frames.invalid", PI_PROTOCOL, PI_WARN, "Frame contains more MAC Frames than currently supported", EXPFILL }}, |
576 | 14 | { &ei_fph_fp_channels, { "fp_hint.fp_channels.invalid", PI_PROTOCOL, PI_WARN, "Frame contains more FP channels than currently supported", EXPFILL }}, |
577 | 14 | }; |
578 | | |
579 | 14 | expert_module_t* expert_fp_hint; |
580 | | |
581 | 14 | proto_fp_hint = proto_register_protocol("FP Hint", "FP Hint", "fp_hint"); |
582 | 14 | register_dissector("fp_hint", dissect_fp_hint, proto_fp_hint); |
583 | | |
584 | 14 | proto_register_field_array(proto_fp_hint, hf, array_length(hf)); |
585 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
586 | 14 | expert_fp_hint = expert_register_protocol(proto_fp_hint); |
587 | 14 | expert_register_field_array(expert_fp_hint, ei, array_length(ei)); |
588 | 14 | } |
589 | | |
590 | | void |
591 | | proto_reg_handoff_fp_hint(void) |
592 | 14 | { |
593 | 14 | atm_untrunc_handle = find_dissector_add_dependency("atm_untruncated", proto_fp_hint); |
594 | 14 | data_handle = find_dissector("data"); |
595 | 14 | ethwithfcs_handle = find_dissector_add_dependency("eth_withfcs", proto_fp_hint); |
596 | 14 | } |
597 | | |
598 | | |
599 | | /* |
600 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
601 | | * |
602 | | * Local variables: |
603 | | * c-basic-offset: 4 |
604 | | * tab-width: 8 |
605 | | * indent-tabs-mode: nil |
606 | | * End: |
607 | | * |
608 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
609 | | * :indentSize=4:tabSize=8:noTabs=true: |
610 | | */ |