/src/wireshark/epan/dissectors/packet-netanalyzer.c
Line | Count | Source |
1 | | /* packet-netanalyzer.c |
2 | | * Dissector for Hilscher netANALYZER frames. |
3 | | * Copyright 2008-2016, Hilscher GmbH, Holger Pfrommer hpfrommer[AT]hilscher.com |
4 | | * |
5 | | * Packet structure: |
6 | | * +---------------------------+ |
7 | | * | Header | |
8 | | * | (4 Octets) | |
9 | | * +---------------------------+ |
10 | | * | Payload | |
11 | | * . . |
12 | | * . . |
13 | | * . . |
14 | | * |
15 | | * Description: |
16 | | * The header field contains a 32-bit value in little-endian byte order. |
17 | | * The low-order 8 bits are a set of error flags for the packet: |
18 | | * 0x00000001 - MII RX_ER |
19 | | * 0x00000002 - alignment error |
20 | | * 0x00000004 - FCS error |
21 | | * 0x00000008 - frame too long |
22 | | * 0x00000010 - SFD error |
23 | | * 0x00000020 - frame shorter than 64 bytes |
24 | | * 0x00000040 - preamble shorter than 7 bytes |
25 | | * 0x00000080 - preamble longer than 7 bytes/li> |
26 | | * The next bit, 0x00000100, is set if the packet arrived on the GPIO port rather tha the Ethernet port. |
27 | | * The next bit, 0x00000200, is set if the packet was received in transparent capture mode. |
28 | | * That should never be set for LINKTYPE_NETANALYZER and should always be set for LINKTYPE_NETANALYZER_TRANSPARENT. |
29 | | * The next 4 bits, 0x00003C00, are a bitfield giving the version of the header field; version can be 1 or 2. |
30 | | * The next 2 bits, 0x0000C000, are the capture port/GPIO number, from 0 to 3. |
31 | | * The next 12 bits, 0x0FFF0000, are the frame length, in bytes. |
32 | | * The topmost 4 bits, 0xF0000000, for version 2 header, these bits are the type of the following packet |
33 | | * (0: Ethernet, 1: PROFIBUS, 2: buffer state entry, 3: timetick, 4..15: reserved). |
34 | | * The payload is an Ethernet frame, beginning with the MAC header and ending with the FCS, for LINKTYPE_NETANALYZER, |
35 | | * and an Ethernet frame, beginning with the preamble and ending with the FCS, for LINKTYPE_NETANALYZER_TRANSPARENT. |
36 | | * |
37 | | * |
38 | | * Wireshark - Network traffic analyzer |
39 | | * By Gerald Combs <gerald[AT]wireshark.org> |
40 | | * Copyright 1999 Gerald Combs |
41 | | * |
42 | | * SPDX-License-Identifier: GPL-2.0-or-later |
43 | | */ |
44 | | |
45 | | |
46 | | #include "config.h" |
47 | | |
48 | | #include <epan/packet.h> |
49 | | #include <epan/expert.h> |
50 | | #include <wiretap/wtap.h> |
51 | | |
52 | | void proto_register_netanalyzer(void); |
53 | | void proto_reg_handoff_netanalyzer(void); |
54 | | |
55 | | static dissector_handle_t netana_handle; |
56 | | static dissector_handle_t netana_handle_transparent; |
57 | | |
58 | 5 | #define HEADER_SIZE 4 |
59 | 0 | #define INFO_TYPE_OFFSET 18 |
60 | | |
61 | 15 | #define MSK_RX_ERR 0x01 |
62 | 15 | #define MSK_ALIGN_ERR 0x02 |
63 | 15 | #define MSK_FCS_ERROR 0x04 |
64 | 15 | #define MSK_TOO_LONG 0x08 |
65 | 15 | #define MSK_SFD_ERROR 0x10 |
66 | 15 | #define MSK_SHORT_FRAME 0x20 |
67 | 15 | #define MSK_SHORT_PREAMBLE 0x40 |
68 | 15 | #define MSK_LONG_PREAMBLE 0x80 |
69 | | |
70 | | static const char *msk_strings[] = { |
71 | | "MII RX_ER error", /* 0x01 */ |
72 | | "Alignment error", /* 0x02 */ |
73 | | "FCS error", /* 0x04 */ |
74 | | "Frame too long", /* 0x08 */ |
75 | | "No valid SFD found", /* 0x10 */ |
76 | | "Frame smaller 64 bytes", /* 0x20 */ |
77 | | "Preamble shorter than 7 bytes", /* 0x40 */ |
78 | | "Preamble longer than 7 bytes" /* 0x80 */ |
79 | | }; |
80 | | |
81 | 3 | #define SRT_TYPE 28 |
82 | 1 | #define SRT_PORT_NUM 6 |
83 | 3 | #define SRT_VERSION 2 |
84 | 5 | #define SRT_GPIO_FLAG 0 |
85 | 15 | #define MSK_PACKET_STATUS 0xff |
86 | 1 | #define MSK_LENGTH 0x0fff |
87 | 1 | #define MSK_TRANSPARENT_MODE 0x02 |
88 | | |
89 | 0 | #define MSK_BUF_STATE 0x1 |
90 | 0 | #define SRT_BUF_ID 4 |
91 | 0 | #define MSK_BUF_ID 0xf0 |
92 | | |
93 | 1 | #define VAL_TYPE_ETH 0 |
94 | 1 | #define VAL_TYPE_PB 1 |
95 | 1 | #define VAL_TYPE_BUF 2 |
96 | 1 | #define VAL_TYPE_TICK 3 |
97 | | |
98 | | |
99 | | static const value_string gpio_number[] = { |
100 | | { 0x0, "GPIO 0" }, |
101 | | { 0x1, "GPIO 1" }, |
102 | | { 0x2, "GPIO 2" }, |
103 | | { 0x3, "GPIO 3" }, |
104 | | { 0, NULL } |
105 | | }; |
106 | | |
107 | | static const value_string gpio_edge_vals[] = { |
108 | | { 0x0, "Rising edge" }, |
109 | | { 0x1, "Falling edge" }, |
110 | | { 0, NULL } |
111 | | }; |
112 | | |
113 | | static const value_string buf_state_vals[] = { |
114 | | { 0x0, "Buffer overflow, frames will be dropped until next buffer recovery" }, |
115 | | { 0x1, "Buffer recovery, frame reception has recovered" }, |
116 | | { 0, NULL } |
117 | | }; |
118 | | |
119 | | static const value_string buf_source_vals[] = { |
120 | | { 0x0, "Backend RX FIFO" }, |
121 | | { 0x1, "netX URX FIFO" }, |
122 | | { 0x2, "netX INTRAM buffer" }, |
123 | | { 0x3, "Host buffer" }, |
124 | | { 0x4, "Capture driver (WinPcap)" }, |
125 | | { 0, NULL } |
126 | | }; |
127 | | |
128 | | |
129 | | static dissector_handle_t eth_dissector_handle; |
130 | | |
131 | | static int proto_netanalyzer; |
132 | | |
133 | | static int hf_netanalyzer_gpio; |
134 | | static int hf_netanalyzer_gpio_number; |
135 | | static int hf_netanalyzer_gpio_edge; |
136 | | static int hf_netanalyzer_eth; |
137 | | static int hf_netanalyzer_port; |
138 | | static int hf_netanalyzer_length; |
139 | | static int hf_netanalyzer_status; |
140 | | static int hf_netanalyzer_status_rx_err; |
141 | | static int hf_netanalyzer_status_align_err; |
142 | | static int hf_netanalyzer_status_fcs; |
143 | | static int hf_netanalyzer_status_too_long; |
144 | | static int hf_netanalyzer_status_sfd_error; |
145 | | static int hf_netanalyzer_status_short_frame; |
146 | | static int hf_netanalyzer_status_short_preamble; |
147 | | static int hf_netanalyzer_status_long_preamble; |
148 | | static int hf_netanalyzer_buf; |
149 | | static int hf_netanalyzer_buf_state; |
150 | | static int hf_netanalyzer_buf_source; |
151 | | static int hf_netanalyzer_timetick; |
152 | | |
153 | | static int * const hfx_netanalyzer_status[] = { |
154 | | &hf_netanalyzer_status_rx_err, |
155 | | &hf_netanalyzer_status_align_err, |
156 | | &hf_netanalyzer_status_fcs, |
157 | | &hf_netanalyzer_status_too_long, |
158 | | &hf_netanalyzer_status_sfd_error, |
159 | | &hf_netanalyzer_status_short_frame, |
160 | | &hf_netanalyzer_status_short_preamble, |
161 | | &hf_netanalyzer_status_long_preamble, |
162 | | NULL |
163 | | }; |
164 | | |
165 | | static int ett_netanalyzer; |
166 | | static int ett_netanalyzer_gpio; |
167 | | static int ett_netanalyzer_status; |
168 | | static int ett_netanalyzer_transparent; |
169 | | static int ett_netanalyzer_buf; |
170 | | |
171 | | static expert_field ei_netanalyzer_header_wrong; |
172 | | static expert_field ei_netanalyzer_gpio_def_none; |
173 | | static expert_field ei_netanalyzer_header_none; |
174 | | static expert_field ei_netanalyzer_transparent_frame; |
175 | | static expert_field ei_netanalyzer_alignment_error; |
176 | | static expert_field ei_netanalyzer_not_implemented; |
177 | | |
178 | | /* common routine for Ethernet and transparent mode */ |
179 | | static int |
180 | | dissect_netanalyzer_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
181 | 5 | { |
182 | 5 | proto_item *ti = NULL; |
183 | 5 | proto_tree *netanalyzer_header_tree = NULL; |
184 | 5 | uint32_t packet_status; |
185 | 5 | uint32_t port_num; |
186 | 5 | uint32_t frame_length; |
187 | 5 | unsigned is_gpio; |
188 | 5 | uint32_t offset; |
189 | 5 | unsigned gpio_num; |
190 | 5 | unsigned gpio_edge; |
191 | 5 | unsigned version; |
192 | 5 | unsigned type; |
193 | 5 | unsigned idx; |
194 | 5 | unsigned buf_state; |
195 | 5 | unsigned buf_source; |
196 | | |
197 | 5 | if (tree) |
198 | 5 | { |
199 | | /* generate netANALYZER tree */ |
200 | 5 | ti = proto_tree_add_item(tree, proto_netanalyzer, tvb, 0, HEADER_SIZE, ENC_NA); |
201 | 5 | netanalyzer_header_tree = proto_item_add_subtree(ti, ett_netanalyzer); |
202 | | |
203 | 5 | is_gpio = (tvb_get_uint8(tvb, 1) >> SRT_GPIO_FLAG) & 0x1; |
204 | | |
205 | 5 | if (!is_gpio) |
206 | 3 | { |
207 | | /* normal packet, no GPIO */ |
208 | | |
209 | | /* decode version */ |
210 | 3 | version = (tvb_get_uint8(tvb, 1) >> SRT_VERSION) & 0xf; |
211 | 3 | type = (tvb_get_uint32(tvb, 0, ENC_LITTLE_ENDIAN) >> SRT_TYPE) & 0xf; |
212 | | |
213 | 3 | if ((version == 1) || ((version == 2) && (type == VAL_TYPE_ETH))) |
214 | 1 | { |
215 | 1 | proto_tree_add_none_format(netanalyzer_header_tree, hf_netanalyzer_eth, tvb, 0, 0, "Ethernet frame"); |
216 | | |
217 | | /* decode port */ |
218 | 1 | port_num = (tvb_get_uint8(tvb, 1) >> SRT_PORT_NUM) & 0x3; |
219 | 1 | proto_tree_add_uint(netanalyzer_header_tree, hf_netanalyzer_port, tvb, 0, 4, port_num); |
220 | 1 | proto_item_append_text(ti, " (Port: %u, ", port_num); |
221 | | |
222 | | /* decode length */ |
223 | 1 | frame_length = tvb_get_letohs(tvb, 2) & MSK_LENGTH; |
224 | 1 | proto_tree_add_uint(netanalyzer_header_tree, hf_netanalyzer_length, tvb, 0, 4, frame_length); |
225 | 1 | proto_item_append_text(ti, "Length: %u byte%s, ", frame_length, (frame_length == 1) ? "" : "s"); |
226 | | |
227 | | /* decode status */ |
228 | 1 | proto_item_append_text(ti, "Status: "); |
229 | 1 | packet_status = tvb_get_uint8(tvb, 0); |
230 | 1 | if (packet_status == 0) |
231 | 1 | { |
232 | 1 | proto_tree_add_uint_format_value(netanalyzer_header_tree, hf_netanalyzer_status, tvb, 0, 1, |
233 | 1 | packet_status, "No Error"); |
234 | 1 | proto_item_append_text(ti, "No Error)"); |
235 | 1 | } |
236 | 0 | else |
237 | 0 | { |
238 | 0 | wmem_strbuf_t *strbuf; |
239 | 0 | bool first = true; |
240 | |
|
241 | 0 | proto_tree_add_bitmask(netanalyzer_header_tree, tvb, 0, hf_netanalyzer_status, ett_netanalyzer_status, hfx_netanalyzer_status, ENC_LITTLE_ENDIAN); |
242 | |
|
243 | 0 | strbuf = wmem_strbuf_create(pinfo->pool); |
244 | 0 | for (idx = 0; idx < 8; idx++) |
245 | 0 | { |
246 | 0 | if (packet_status & (1 << idx)) |
247 | 0 | { |
248 | 0 | if (first) |
249 | 0 | { |
250 | 0 | first = false; |
251 | 0 | } |
252 | 0 | else |
253 | 0 | { |
254 | 0 | wmem_strbuf_append(strbuf, ", "); |
255 | 0 | } |
256 | 0 | wmem_strbuf_append(strbuf, msk_strings[idx]); |
257 | 0 | } |
258 | 0 | } |
259 | 0 | proto_item_append_text(ti, "%s)", wmem_strbuf_get_str(strbuf)); |
260 | 0 | } |
261 | | |
262 | | /* decode transparent mode */ |
263 | 1 | if (tvb_get_uint8(tvb, 1) & MSK_TRANSPARENT_MODE) |
264 | 0 | { |
265 | 0 | proto_tree_add_expert(netanalyzer_header_tree, pinfo, &ei_netanalyzer_transparent_frame, tvb, 0, 4); |
266 | 0 | proto_item_append_text(ti, ", Transparent Mode"); |
267 | |
|
268 | 0 | if (packet_status & MSK_ALIGN_ERR) |
269 | 0 | { |
270 | 0 | proto_tree_add_expert(netanalyzer_header_tree, pinfo, &ei_netanalyzer_alignment_error, tvb, tvb_captured_length(tvb) - 1, 1); |
271 | 0 | } |
272 | 0 | } |
273 | 1 | } |
274 | 2 | else if ((version == 2) && (type == VAL_TYPE_PB)) |
275 | 0 | { |
276 | | /* currently not implemented */ |
277 | 0 | expert_add_info(pinfo, ti, &ei_netanalyzer_not_implemented); |
278 | 0 | return false; |
279 | 0 | } |
280 | 2 | else if ((version == 2) && (type == VAL_TYPE_BUF)) |
281 | 0 | { |
282 | 0 | proto_tree_add_none_format(netanalyzer_header_tree, hf_netanalyzer_buf, tvb, 0, 0, "Buffer state entry"); |
283 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "netANALYZER"); |
284 | |
|
285 | 0 | buf_state = tvb_get_uint8(tvb, 0) & MSK_BUF_STATE; |
286 | 0 | if (buf_state == 0) |
287 | 0 | { |
288 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Buffer overflow"); |
289 | 0 | } |
290 | 0 | else |
291 | 0 | { |
292 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Buffer recovery"); |
293 | 0 | } |
294 | 0 | proto_item_append_text(ti, " (%s)", buf_state_vals[buf_state].strptr); |
295 | | |
296 | | /* decode buffer state */ |
297 | 0 | proto_tree_add_uint(ti, hf_netanalyzer_buf_state, tvb, 0, 1, buf_state); |
298 | 0 | port_num = (tvb_get_uint8(tvb, 1) >> SRT_PORT_NUM) & 0x3; |
299 | 0 | proto_tree_add_uint(ti, hf_netanalyzer_port, tvb, 0, 4, port_num); |
300 | 0 | buf_source = (tvb_get_uint8(tvb, 0) & MSK_BUF_ID) >> SRT_BUF_ID; |
301 | 0 | proto_tree_add_uint(ti, hf_netanalyzer_buf_source, tvb, 0, 1, buf_source); |
302 | |
|
303 | 0 | return false; |
304 | 0 | } |
305 | 2 | else if ((version == 2) && (type == VAL_TYPE_TICK)) |
306 | 0 | { |
307 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "netANALYZER"); |
308 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Time tick"); |
309 | 0 | proto_item_append_text(ti, " (Time tick)"); |
310 | 0 | proto_tree_add_none_format(netanalyzer_header_tree, hf_netanalyzer_timetick, tvb, 0, 0, "Time tick"); |
311 | 0 | return false; |
312 | 0 | } |
313 | 2 | else |
314 | 2 | { |
315 | | /* something is wrong */ |
316 | 2 | expert_add_info(pinfo, ti, &ei_netanalyzer_header_wrong); |
317 | 2 | return false; |
318 | 2 | } |
319 | 3 | } |
320 | 2 | else |
321 | 2 | { |
322 | | /* check consistency */ |
323 | 2 | if ( (tvb_get_uint8(tvb, 10) == 0x00) && |
324 | 1 | (tvb_get_uint8(tvb, 11) == 0x02) && |
325 | 0 | (tvb_get_uint8(tvb, 12) == 0xa2) && |
326 | 0 | (tvb_get_uint8(tvb, 13) == 0xff) && |
327 | 0 | (tvb_get_uint8(tvb, 14) == 0xff) && |
328 | 0 | (tvb_get_uint8(tvb, 15) == 0xff) && |
329 | 0 | (tvb_get_uint8(tvb, 16) == 0x88) && |
330 | 0 | (tvb_get_uint8(tvb, 17) == 0xff) && |
331 | 0 | (tvb_get_uint8(tvb, INFO_TYPE_OFFSET) == 0x00) ) |
332 | 0 | { |
333 | 0 | char *szTemp; |
334 | | |
335 | | /* everything ok */ |
336 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "netANALYZER"); |
337 | 0 | offset = INFO_TYPE_OFFSET; |
338 | 0 | proto_tree_add_none_format(netanalyzer_header_tree, hf_netanalyzer_gpio, tvb, 0, 0, "GPIO event"); |
339 | 0 | proto_item_append_text(ti, " (GPIO event)"); |
340 | | |
341 | | /* GPIO number */ |
342 | 0 | offset++; |
343 | 0 | proto_tree_add_item (netanalyzer_header_tree, hf_netanalyzer_gpio_number, tvb, offset, 1, ENC_LITTLE_ENDIAN); |
344 | 0 | gpio_num = (tvb_get_uint8(tvb, offset) & 0x03); |
345 | | |
346 | | /* GPIO edge */ |
347 | 0 | offset++; |
348 | 0 | ti = proto_tree_add_item (netanalyzer_header_tree, hf_netanalyzer_gpio_edge, tvb, offset, 1, ENC_LITTLE_ENDIAN); |
349 | 0 | gpio_edge = (tvb_get_uint8(tvb, offset) & 0x01); |
350 | |
|
351 | 0 | szTemp = wmem_strdup_printf(pinfo->pool, "GPIO event on GPIO %d (%sing edge)", gpio_num, (gpio_edge == 0x00) ? "ris" : "fall"); |
352 | |
|
353 | 0 | col_add_str(pinfo->cinfo, COL_INFO, szTemp); |
354 | 0 | proto_item_append_text(ti, " %s", szTemp); |
355 | 0 | } |
356 | 2 | else |
357 | 2 | { |
358 | | /* something is wrong */ |
359 | 2 | expert_add_info(pinfo, ti, &ei_netanalyzer_gpio_def_none); |
360 | 2 | } |
361 | 2 | return false; |
362 | 2 | } |
363 | 5 | } |
364 | 1 | return true; |
365 | 5 | } |
366 | | |
367 | | |
368 | | /* Ethernet capture mode */ |
369 | | static int |
370 | | dissect_netanalyzer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
371 | 1 | { |
372 | 1 | tvbuff_t *next_tvb; |
373 | | |
374 | 1 | if (tvb_reported_length(tvb) >= 4) |
375 | 1 | { |
376 | | /* generate tvb subset for Ethernet frame */ |
377 | 1 | if (dissect_netanalyzer_common(tvb, pinfo, tree)) |
378 | 0 | { |
379 | | /* hand off to eth dissector with the new tvb subset */ |
380 | 0 | next_tvb = tvb_new_subset_remaining(tvb, 4); |
381 | 0 | call_dissector(eth_dissector_handle, next_tvb, pinfo, tree); |
382 | 0 | } |
383 | 1 | } |
384 | 0 | else |
385 | 0 | { |
386 | | /* something is wrong */ |
387 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_netanalyzer_header_none, tvb, 4, |
388 | 0 | "netANALYZER - No netANALYZER header found"); |
389 | 0 | } |
390 | 1 | return tvb_captured_length(tvb); |
391 | 1 | } |
392 | | |
393 | | |
394 | | /* Transparent capture mode */ |
395 | | static int |
396 | | dissect_netanalyzer_transparent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
397 | 4 | { |
398 | 4 | proto_tree *transparent_payload_tree = NULL; |
399 | 4 | tvbuff_t *next_tvb; |
400 | | |
401 | 4 | if (tvb_reported_length(tvb) >= 4) |
402 | 4 | { |
403 | | /* generate tvb subset for Ethernet frame */ |
404 | 4 | if (dissect_netanalyzer_common(tvb, pinfo, tree)) |
405 | 1 | { |
406 | | /* do not hand off transparent packet for further Ethernet dissectors |
407 | | * as normally the transparent mode is used for low level analysis |
408 | | * where dissecting the frame's content wouldn't make much sense |
409 | | * use data dissector instead */ |
410 | 1 | transparent_payload_tree = proto_tree_add_subtree(tree, tvb, 4, tvb_captured_length(tvb)-4, |
411 | 1 | ett_netanalyzer_transparent, NULL, "Raw packet data"); |
412 | 1 | next_tvb = tvb_new_subset_remaining(tvb, 4); |
413 | 1 | call_data_dissector(next_tvb, pinfo, transparent_payload_tree); |
414 | | |
415 | 1 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "netANALYZER"); |
416 | 1 | col_set_str(pinfo->cinfo, COL_INFO, "Frame captured in transparent mode"); |
417 | 1 | } |
418 | 4 | } |
419 | 0 | else |
420 | 0 | { |
421 | | /* something is wrong */ |
422 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_netanalyzer_header_none, tvb, 4, |
423 | 0 | "netANALYZER transparent mode - No netANALYZER header found"); |
424 | 0 | } |
425 | 4 | return tvb_captured_length(tvb); |
426 | 4 | } |
427 | | |
428 | | |
429 | | void proto_register_netanalyzer(void) |
430 | 15 | { |
431 | 15 | static hf_register_info hf[] = { |
432 | 15 | { &hf_netanalyzer_gpio, |
433 | 15 | { "GPIO event", "netanalyzer.gpio_event", |
434 | 15 | FT_NONE, BASE_NONE, NULL, 0x0, |
435 | 15 | "Shows the occurrence of an digital switching event", HFILL } |
436 | 15 | }, |
437 | 15 | { &hf_netanalyzer_gpio_number, |
438 | 15 | { "GPIO event on", "netanalyzer.gpio_event.gpio_number", |
439 | 15 | FT_UINT8, BASE_HEX, VALS(gpio_number), 0x0, |
440 | 15 | "GPIO event on GPIO number", HFILL } |
441 | 15 | }, |
442 | 15 | { &hf_netanalyzer_gpio_edge, |
443 | 15 | { "GPIO event type", "netanalyzer.gpio_event.gpio_edge", |
444 | 15 | FT_UINT8, BASE_HEX, VALS(gpio_edge_vals), 0x0, |
445 | 15 | "GPIO edge of GPIO event", HFILL } |
446 | 15 | }, |
447 | 15 | { &hf_netanalyzer_eth, |
448 | 15 | { "Ethernet frame", "netanalyzer.eth", |
449 | 15 | FT_NONE, BASE_NONE, NULL, 0x0, |
450 | 15 | "This is an Ethernet frame", HFILL } |
451 | 15 | }, |
452 | 15 | { &hf_netanalyzer_port, |
453 | 15 | { "Reception Port", "netanalyzer.port", |
454 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
455 | 15 | "netANALYZER reception port", HFILL } |
456 | 15 | }, |
457 | 15 | { &hf_netanalyzer_length, |
458 | 15 | { "Ethernet frame length", "netanalyzer.framelen", |
459 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
460 | 15 | "Actual Ethernet frame length", HFILL } |
461 | 15 | }, |
462 | 15 | { &hf_netanalyzer_status, |
463 | 15 | { "Status", "netanalyzer.packetstatus", |
464 | 15 | FT_UINT8, BASE_HEX, NULL, MSK_PACKET_STATUS, |
465 | 15 | "Status of Ethernet frame", HFILL } |
466 | 15 | }, |
467 | 15 | { &hf_netanalyzer_status_rx_err, |
468 | 15 | { "MII RX_ER error", "netanalyzer.packetstatus.rx_er", |
469 | 15 | FT_BOOLEAN, 8, NULL, MSK_RX_ERR, |
470 | 15 | "RX_ER detected in frame", HFILL } |
471 | 15 | }, |
472 | 15 | { &hf_netanalyzer_status_align_err, |
473 | 15 | { "Alignment error", "netanalyzer.packetstatus.alignment_error", |
474 | 15 | FT_BOOLEAN, 8, NULL, MSK_ALIGN_ERR, |
475 | 15 | NULL, HFILL } |
476 | 15 | }, |
477 | 15 | { &hf_netanalyzer_status_fcs, |
478 | 15 | { "FCS error", "netanalyzer.packetstatus.fcs_error", |
479 | 15 | FT_BOOLEAN, 8, NULL, MSK_FCS_ERROR, |
480 | 15 | NULL, HFILL } |
481 | 15 | }, |
482 | 15 | { &hf_netanalyzer_status_too_long, |
483 | 15 | { "Frame too long", "netanalyzer.packetstatus.too_long", |
484 | 15 | FT_BOOLEAN, 8, NULL, MSK_TOO_LONG, |
485 | 15 | "Frame too long (capture truncated)", HFILL } |
486 | 15 | }, |
487 | 15 | { &hf_netanalyzer_status_sfd_error, |
488 | 15 | { "No valid SFD found", "netanalyzer.packetstatus.sfd_error", |
489 | 15 | FT_BOOLEAN, 8, NULL, MSK_SFD_ERROR, |
490 | 15 | "SDF error detected in frame", HFILL } |
491 | 15 | }, |
492 | 15 | { &hf_netanalyzer_status_short_frame, |
493 | 15 | { "Frame smaller 64 bytes", "netanalyzer.packetstatus.short_frame", |
494 | 15 | FT_BOOLEAN, 8, NULL, MSK_SHORT_FRAME, |
495 | 15 | NULL, HFILL } |
496 | 15 | }, |
497 | 15 | { &hf_netanalyzer_status_short_preamble, |
498 | 15 | { "Preamble shorter than 7 bytes", "netanalyzer.packetstatus.short_preamble", |
499 | 15 | FT_BOOLEAN, 8, NULL, MSK_SHORT_PREAMBLE, |
500 | 15 | NULL, HFILL } |
501 | 15 | }, |
502 | 15 | { &hf_netanalyzer_status_long_preamble, |
503 | 15 | { "Preamble longer than 7 bytes", "netanalyzer.packetstatus.long_preamble", |
504 | 15 | FT_BOOLEAN, 8, NULL, MSK_LONG_PREAMBLE, |
505 | 15 | NULL, HFILL } |
506 | 15 | }, |
507 | 15 | { &hf_netanalyzer_buf, |
508 | 15 | { "Buffer state entry", "netanalyzer.buffer", |
509 | 15 | FT_NONE, BASE_NONE, NULL, 0x0, |
510 | 15 | "Info about reception buffer conditions", HFILL } |
511 | 15 | }, |
512 | 15 | { &hf_netanalyzer_buf_state, |
513 | 15 | { "Buffer state", "netanalyzer.buffer.state", |
514 | 15 | FT_UINT8, BASE_DEC, VALS(buf_state_vals), 0x0, |
515 | 15 | "State of receive buffers", HFILL } |
516 | 15 | }, |
517 | 15 | { &hf_netanalyzer_buf_source, |
518 | 15 | { "Buffer source", "netanalyzer.buffer.source", |
519 | 15 | FT_UINT8, BASE_DEC, VALS(buf_source_vals), 0x0, |
520 | 15 | "Source of buffer error", HFILL } |
521 | 15 | }, |
522 | 15 | { &hf_netanalyzer_timetick, |
523 | 15 | { "Time tick", "netanalyzer.timetick", |
524 | 15 | FT_NONE, BASE_NONE, NULL, 0x0, |
525 | 15 | "Cyclic time tick of netANALYZER device", HFILL } |
526 | 15 | }, |
527 | 15 | }; |
528 | | |
529 | 15 | static int *ett[] = { |
530 | 15 | &ett_netanalyzer, |
531 | 15 | &ett_netanalyzer_gpio, |
532 | 15 | &ett_netanalyzer_status, |
533 | 15 | &ett_netanalyzer_transparent, |
534 | 15 | &ett_netanalyzer_buf, |
535 | 15 | }; |
536 | | |
537 | 15 | static ei_register_info ei[] = { |
538 | 15 | { &ei_netanalyzer_header_wrong, { "netanalyzer.header.wrong", PI_PROTOCOL, PI_ERROR, "Wrong netANALYZER header", EXPFILL }}, |
539 | 15 | { &ei_netanalyzer_gpio_def_none, { "netanalyzer.gpio_def_none", PI_MALFORMED, PI_ERROR, "No valid netANALYZER GPIO definition found", EXPFILL }}, |
540 | 15 | { &ei_netanalyzer_header_none, { "netanalyzer.header.none", PI_MALFORMED, PI_ERROR, "No netANALYZER header found", EXPFILL }}, |
541 | 15 | { &ei_netanalyzer_transparent_frame, { "netanalyzer.transparent_frame", PI_PROTOCOL, PI_NOTE, "This frame was captured in transparent mode", EXPFILL }}, |
542 | 15 | { &ei_netanalyzer_alignment_error, { "netanalyzer.alignment_error", PI_PROTOCOL, PI_WARN, "Displayed frame data contains additional nibble due to alignment error (upper nibble is not valid)", EXPFILL }}, |
543 | 15 | { &ei_netanalyzer_not_implemented,{ "netanalyzer.not_implemented", PI_PROTOCOL, PI_ERROR, "This feature is currently not implemented in Wireshark", EXPFILL } }, |
544 | 15 | }; |
545 | | |
546 | 15 | expert_module_t* expert_netanalyzer; |
547 | | |
548 | 15 | proto_netanalyzer = proto_register_protocol ("netANALYZER", "netANALYZER", "netanalyzer"); |
549 | | |
550 | 15 | proto_register_field_array(proto_netanalyzer, hf, array_length(hf)); |
551 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
552 | 15 | expert_netanalyzer = expert_register_protocol(proto_netanalyzer); |
553 | 15 | expert_register_field_array(expert_netanalyzer, ei, array_length(ei)); |
554 | | |
555 | 15 | netana_handle = register_dissector("netanalyzer", dissect_netanalyzer, proto_netanalyzer); |
556 | 15 | netana_handle_transparent = register_dissector("netanalyzer_transparent", dissect_netanalyzer_transparent, proto_netanalyzer); |
557 | 15 | } |
558 | | |
559 | | |
560 | | void proto_reg_handoff_netanalyzer(void) |
561 | 15 | { |
562 | 15 | eth_dissector_handle = find_dissector_add_dependency("eth_withfcs", proto_netanalyzer); |
563 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_NETANALYZER, netana_handle); |
564 | 15 | dissector_add_uint("wtap_encap", WTAP_ENCAP_NETANALYZER_TRANSPARENT, netana_handle_transparent); |
565 | 15 | } |
566 | | |
567 | | /* |
568 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
569 | | * |
570 | | * Local Variables: |
571 | | * c-basic-offset: 2 |
572 | | * tab-width: 8 |
573 | | * indent-tabs-mode: nil |
574 | | * End: |
575 | | * |
576 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
577 | | * :indentSize=2:tabSize=8:noTabs=true: |
578 | | */ |