/src/wireshark/epan/dissectors/packet-pathport.c
Line | Count | Source |
1 | | /* packet-pathport.c |
2 | | * Routines for Pathport Protocol dissection |
3 | | * Copyright 2014, Kevin Loewen <kloewen@pathwayconnect.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | #include <epan/packet.h> |
14 | | #include <epan/to_str.h> |
15 | | #include <wsutil/ws_roundup.h> |
16 | | |
17 | 16 | #define PATHPORT_UDP_PORT 3792 /* Not IANA registered */ |
18 | 1.29k | #define PATHPORT_MIN_LENGTH 24 /* HEADER + 1 PDU */ |
19 | 604 | #define PATHPORT_PROTO_MAGIC 0xed01 |
20 | | |
21 | 26 | #define PATHPORT_HEADER_OFFSET 0 |
22 | 13 | #define PATHPORT_HEADER_SRCID_OFFSET (PATHPORT_HEADER_OFFSET + 12) |
23 | | |
24 | 0 | #define PATHPORT_HEADER_DSTID_OFFSET (PATHPORT_HEADER_OFFSET + 16) |
25 | 26 | #define PATHPORT_HEADER_LENGTH 20 |
26 | | #define PATHPORT_HEADER_END (PATHPORT_HEADER_OFFSET + PATHPORT_HEADER_LENGTH) |
27 | | |
28 | | /** Rounds the specified integer up to the next multiple of four. */ |
29 | 51 | #define roof4(a) WS_ROUNDUP_4(a) |
30 | | |
31 | | void proto_reg_handoff_pathport(void); |
32 | | void proto_register_pathport(void); |
33 | | |
34 | | static dissector_handle_t pathport_handle; |
35 | | |
36 | | /* Initialize the protocol and registered fields */ |
37 | | static int proto_pathport; |
38 | | |
39 | | /* Initialize the subtree pointers */ |
40 | | static int ett_pathport; |
41 | | static int ett_pp_pdu; |
42 | | static int ett_pp_tlv; |
43 | | static int ett_pp_data; |
44 | | |
45 | | static int hf_pp_prot; |
46 | | static int hf_pp_reserved; |
47 | | static int hf_pp_version; |
48 | | static int hf_pp_seq; |
49 | | static int hf_pp_src; |
50 | | static int hf_pp_dst; |
51 | | static int hf_pp_data_encoding; |
52 | | static int hf_pp_data_len; |
53 | | static int hf_pp_data_start_code; |
54 | | static int hf_pp_data_dst; |
55 | | static int hf_pp_data_levels; |
56 | | static int hf_pp_arp_id; |
57 | | static int hf_pp_arp_manuf; |
58 | | static int hf_pp_arp_class; |
59 | | static int hf_pp_arp_type; |
60 | | static int hf_pp_arp_numdmx; |
61 | | static int hf_pp_arp_ip; |
62 | | static int hf_pp_get_type; |
63 | | static int hf_pp_pdu_type; |
64 | | static int hf_pp_pdu_len; |
65 | | static int hf_pp_pdu_payload; |
66 | | static int hf_pp_pid_type; |
67 | | static int hf_pp_pid_len; |
68 | | static int hf_pp_pid_value; |
69 | | static int hf_pp_pid_pad_bytes; |
70 | | |
71 | | /* Begin field and constant declarations */ |
72 | | #define PP_ID_BCAST 0xffffffff |
73 | | #define PP_ID_MCAST_ALL 0xefffedff |
74 | | #define PP_ID_MCAST_DATA 0xefffed01 |
75 | | #define PP_ID_MCAST_MANAGE 0xefffed02 |
76 | | |
77 | | /* Top Level PDU Types */ |
78 | 13 | #define PP_ARP_REQUEST 0x0301 |
79 | 13 | #define PP_ARP_REPLY 0x0302 |
80 | 1 | #define PP_ARP_INFO 0x0303 |
81 | 3 | #define PP_GET 0x0222 |
82 | 0 | #define PP_GET_REPLY 0x0223 |
83 | 15 | #define PP_DATA 0x0100 |
84 | 0 | #define PP_SET 0x0400 |
85 | | |
86 | | static const value_string pp_pdu_vals[] = { |
87 | | {PP_ARP_REQUEST, "ARP Request"}, |
88 | | {PP_ARP_REPLY, "ARP Reply"}, |
89 | | {PP_ARP_INFO, "ARP Extend Info"}, |
90 | | {PP_GET, "Get"}, |
91 | | {PP_GET_REPLY, "Get Reply"}, |
92 | | {PP_DATA, "XDMX Data"}, |
93 | | {PP_SET, "Set"}, |
94 | | {0, NULL} |
95 | | }; |
96 | | |
97 | | /* XDMX Data Transport Encodings */ |
98 | | #define PP_DATA_FLAT 0x0101 |
99 | | #define PP_DATA_RELEASE 0x0103 |
100 | | |
101 | | /** Data encoding strings. */ |
102 | | static const value_string pp_data_encoding_vals[] = { |
103 | | {PP_DATA_FLAT, "Flat"}, |
104 | | {PP_DATA_RELEASE, "Release"}, |
105 | | {0, NULL} |
106 | | }; |
107 | | |
108 | | /** ID strings. */ |
109 | | static const value_string ednet_id_vals[] = { |
110 | | {PP_ID_BCAST, "Broadcast"}, |
111 | | {PP_ID_MCAST_ALL, "All"}, |
112 | | {PP_ID_MCAST_DATA, "Data"}, |
113 | | {PP_ID_MCAST_MANAGE, "Manage"}, |
114 | | {0, NULL} |
115 | | }; |
116 | | |
117 | | /* Configuration Property IDs */ |
118 | | #define PP_PAD 0x0000 |
119 | | #define PP_NODE_NAME 0x0401 |
120 | | #define PP_PORT_NAME 0x0411 |
121 | | #define PP_PATCH_NAME 0x0412 |
122 | | #define PP_PORT_SPEED 0x0413 |
123 | | #define PP_IS_BIDIRECTIONAL 0x0414 |
124 | | #define PP_IS_PHYSICAL 0x0415 |
125 | | #define PP_IS_MALE 0x0416 |
126 | | #define PP_IS_SINK 0x0417 |
127 | | #define PP_XDMX_COUNT 0x0418 |
128 | | #define PP_ALT_START_CODE 0x041A |
129 | | #define PP_MAX_PATCHES 0x041B |
130 | | #define PP_NUM_PATCHES 0x041C |
131 | | #define PP_TERMINATED 0x041E |
132 | | #define PP_INPUT_PRIORITY 0x041F |
133 | | #define PP_INPUT_PRIORITY_CHANNEL 0x0420 |
134 | | #define PP_MAC 0x0421 |
135 | | #define PP_IP 0x0422 |
136 | | #define PP_NETMASK 0x0423 |
137 | | #define PP_ROUTER 0x0424 |
138 | | #define PP_PP_ID 0x0461 |
139 | | #define PP_PP_ID_MASK 0x0462 |
140 | | #define PP_PP_TX_DATA_DST 0x0463 |
141 | | #define PP_BACKLIGHT 0x0481 |
142 | | #define PP_SW_VERSION 0x0482 |
143 | | #define PP_HW_TYPE 0x0483 |
144 | | #define PP_LOADER_VERSION 0x0484 |
145 | | #define PP_IDENTIFY 0x0485 |
146 | | #define PP_IRENABLE 0x0486 |
147 | | #define PP_SERIAL 0x0487 |
148 | | #define PP_KEYPAD_LOCKOUT 0x0488 |
149 | | #define PP_ARTNET_RX_ENABLE 0x0489 |
150 | | #define PP_TX_PROTOCOL 0x048a |
151 | | #define PP_SHOWNET_RX_ENABLE 0x048b |
152 | | #define PP_LED_INTENSITY 0x048c |
153 | | #define PP_JUMPER_CONFIGURED 0x048d |
154 | | #define PP_SACN_RX_ENABLE 0x048e |
155 | | #define PP_NET2_RX_ENABLE 0x048f |
156 | | #define PP_PATHPORT_RX_ENABLE 0x0490 |
157 | | #define PP_SACN_IS_DRAFT 0x0491 |
158 | | #define PP_REBOOT 0x04a1 |
159 | | #define PP_BOOTORDER 0x04a2 |
160 | | #define PP_FACTORY_DEFAULT 0x04a4 |
161 | | #define PP_TEST_LCD 0x04c1 |
162 | | #define PP_IS_TERMINAL_BLOCK 0x04c2 |
163 | | #define PP_IS_RACK_MOUNTED 0x04c3 |
164 | | #define PP_IS_ENABLED 0x04c4 |
165 | | #define PP_IS_DMX_ACTIVE 0x04c5 |
166 | | #define PP_IS_XDMX_ACTIVE 0x04c6 |
167 | | #define PP_SIGNAL_LOSS_HOLD_TIME 0x04c7 |
168 | | #define PP_SIGNAL_LOSS_HOLD_FOREVER 0x04c8 |
169 | | #define PP_SIGNAL_LOSS_FADE_ENABLE 0x04c9 |
170 | | #define PP_SIGNAL_LOSS_FADE_TIME 0x04ca |
171 | | #define PP_SIGNAL_LOSS_PORT_SHUTDOWN 0x04cb |
172 | | #define PP_NET2_ADMIN_MCAST 0x04ce |
173 | | #define PP_NET2_DATA_MCAST 0x04cf |
174 | | #define PP_ROOMS_FEATURES 0x04d0 |
175 | | #define PP_UNIVERSE_TEMP 0x04d1 |
176 | | #define PP_CROSSFADE_TIME 0x04d2 |
177 | | #define PP_CROSSFADE_ENABLE 0x04d3 |
178 | | #define PP_IGNORE_INPUT_PRI 0x04d4 |
179 | | #define PP_ARTNET_ALT_MAP 0x04d5 |
180 | | #define PP_PATCH_CRC 0x04d6 |
181 | | #define PP_CONF_CHANGE 0x04d7 |
182 | | #define PP_PORT_ACTIVE_SUMMARY 0x04d8 |
183 | | #define PP_SUPPORTED_UNIV 0x04d9 |
184 | | #define PP_INPUT_HLL_TIME 0x04da |
185 | | #define PP_PCP_ENABLE 0x04db |
186 | | #define PP_INPUT_UNIVERSE 0x04dc |
187 | | #define PP_MODEL_NAME 0x04dd |
188 | | #define PP_MANUF_NAME 0x04de |
189 | | #define PP_VER_STR 0x04df |
190 | | #define PP_SERIAL_STR 0x04e0 |
191 | | #define PP_NODE_NOTES 0x04e1 |
192 | | #define PP_PORT_NOTES 0x04e2 |
193 | | #define PP_USER_NODE_ID 0x04e3 |
194 | | #define PP_MDG_GEN_STATE 0x0601 |
195 | | #define PP_EMBEDDED_ID 0x0602 |
196 | | #define PP_SLAVE_DMX_START 0x0603 |
197 | | #define PP_TB_MODE 0x0605 |
198 | | #define PP_LINK_MODE 0x0701 |
199 | | #define PP_LINK_STATUS 0x0702 |
200 | | #define PP_CONNECTED_COUNT 0x0703 |
201 | | #define PP_POE_STATUS 0x0704 |
202 | | #define PP_POE_EXTERN_WATT 0x0705 |
203 | | #define PP_POE_CURRENT_WATT 0x0706 |
204 | | #define PP_SFP_MODULE_TYPE 0x0707 |
205 | | #define PP_POE_EXTERN_PRESENT 0x0708 |
206 | | #define PP_POE_CAPABLE 0x0709 |
207 | | #define PP_SWITCH_PORT_TYPE 0x070a |
208 | | #define PP_POE_MAX_ALLOC_MW 0x070b |
209 | | #define PP_POE_CURRENT_ALLOC_MW 0x070c |
210 | | #define PP_VLAN_RANGE_START 0x070d |
211 | | #define PP_VLAN_RANGE_END 0x070e |
212 | | #define PP_VLAN_IS_TAGGED 0x070f |
213 | | #define PP_VLAN_PORT_VID 0x0710 |
214 | | #define PP_VLAN_MGMT_VID 0x0711 |
215 | | #define PP_VLAN_ENABLE 0x0712 |
216 | | #define PP_EAPS_MODE 0x0713 |
217 | | #define PP_EAPS_VLAN 0x0714 |
218 | | #define PP_EAPS_PRI_PORT 0x0715 |
219 | | #define PP_EAPS_SEC_PORT 0x0716 |
220 | | #define PP_LLDP_PARTNER_MAC 0x0717 |
221 | | #define PP_LLDP_PARTNER_PORT 0x0718 |
222 | | #define PP_ET_PARAM_1 0x1101 |
223 | | #define PP_END 0xffff |
224 | | |
225 | | /** Property strings. */ |
226 | | static const value_string pp_pid_vals[] = { |
227 | | {PP_PAD, "Pad"}, |
228 | | {PP_NODE_NAME, "Node Name"}, |
229 | | {PP_PORT_NAME, "Port Name"}, |
230 | | {PP_PATCH_NAME, "Patch Name"}, |
231 | | {PP_PORT_SPEED, "Port Speed"}, |
232 | | {PP_IS_BIDIRECTIONAL, "Bi Directional"}, |
233 | | {PP_IS_PHYSICAL, "Physical"}, |
234 | | {PP_IS_MALE, "Is Male"}, |
235 | | {PP_IS_SINK, "Is Sink"}, |
236 | | {PP_XDMX_COUNT, "XDMX Channel Count"}, |
237 | | {PP_ALT_START_CODE, "Alt Start Code List"}, |
238 | | {PP_MAX_PATCHES, "Max # Patches"}, |
239 | | {PP_NUM_PATCHES, "Current # Patches"}, |
240 | | {PP_TERMINATED, "Is Terminated"}, |
241 | | {PP_INPUT_PRIORITY, "Input Priority (Static)"}, |
242 | | {PP_INPUT_PRIORITY_CHANNEL, "Input Priority Channel"}, |
243 | | {PP_MAC, "Ethernet Address"}, |
244 | | {PP_IP, "IP Address"}, |
245 | | {PP_NETMASK, "IP Netmask"}, |
246 | | {PP_ROUTER, "Default Router"}, |
247 | | {PP_PP_ID, "Pathport ID"}, |
248 | | {PP_PP_ID_MASK, "Pathport ID Mask"}, |
249 | | {PP_PP_TX_DATA_DST, "Pathport Data Transmit Offset"}, |
250 | | {PP_BACKLIGHT, "Backlight"}, |
251 | | {PP_SW_VERSION, "Software Version"}, |
252 | | {PP_HW_TYPE, "Hardware Type"}, |
253 | | {PP_LOADER_VERSION, "Loader Version"}, |
254 | | {PP_IDENTIFY, "Identify"}, |
255 | | {PP_IRENABLE, "IR Enable"}, |
256 | | {PP_SERIAL, "Serial Number"}, |
257 | | {PP_KEYPAD_LOCKOUT, "Front Panel Lockout"}, |
258 | | {PP_ARTNET_RX_ENABLE, "ArtNet Rx Enable"}, |
259 | | {PP_TX_PROTOCOL, "Data Tx Proto"}, |
260 | | {PP_SHOWNET_RX_ENABLE, "Shownet Rx Enable"}, |
261 | | /* XXX: PP_LED_INTENSITY ?? */ |
262 | | {PP_JUMPER_CONFIGURED, "Universe Patched By Jumper"}, |
263 | | {PP_SACN_RX_ENABLE, "sACN (E1.31) Rx Enable"}, |
264 | | {PP_NET2_RX_ENABLE, "ETCNet2 Rx Enable"}, |
265 | | {PP_PATHPORT_RX_ENABLE, "xDMX Rx Enable"}, |
266 | | {PP_SACN_IS_DRAFT, "sACN TX is Draft"}, |
267 | | {PP_REBOOT, "Reboot"}, |
268 | | {PP_BOOTORDER, "Boot Order"}, |
269 | | {PP_FACTORY_DEFAULT, "Factory Default"}, |
270 | | {PP_TEST_LCD, "Test LCD"}, |
271 | | /* XXX: PP_IS_TERMINAL_BLOCK ?? */ |
272 | | /* XXX: PP_IS_RACK_MOUNTED ?? */ |
273 | | {PP_IS_ENABLED, "Port Enable"}, |
274 | | {PP_IS_DMX_ACTIVE , "DMX Active"}, |
275 | | {PP_IS_XDMX_ACTIVE , "xDMX Active"}, |
276 | | {PP_SIGNAL_LOSS_HOLD_TIME, "Signal Loss Hold Time (DMX OUT)"}, |
277 | | {PP_SIGNAL_LOSS_HOLD_FOREVER , "Signal Loss Infinite Hold"}, |
278 | | {PP_SIGNAL_LOSS_FADE_ENABLE, "Signal Loss Fade Enable"}, |
279 | | {PP_SIGNAL_LOSS_FADE_TIME, "Signal Loss Fade Time"}, |
280 | | {PP_SIGNAL_LOSS_PORT_SHUTDOWN, "Signal Loss Port Shutdown"}, |
281 | | /* XXX: PP_NET2_ADMIN_MCAST ?? */ |
282 | | /* XXX: PP_NET2_DATA_MCAST ?? */ |
283 | | /* XXX: PP_ROOMS_FEATURES ?? */ |
284 | | {PP_UNIVERSE_TEMP, "xDMX Universe"}, |
285 | | {PP_CROSSFADE_TIME, "Crossfade Time(ms)"}, |
286 | | {PP_CROSSFADE_ENABLE, "Crossfade Enable"}, |
287 | | {PP_IGNORE_INPUT_PRI, "Ignore Input Priority"}, |
288 | | {PP_ARTNET_ALT_MAP, "ArtNet Alternate Univ Mapping"}, |
289 | | {PP_PATCH_CRC, "Output Patch File CRC"}, |
290 | | {PP_CONF_CHANGE, "Config Change Notify"}, |
291 | | {PP_PORT_ACTIVE_SUMMARY, "Port Active Bitmap"}, |
292 | | {PP_SUPPORTED_UNIV, "Number Supported Univ"}, |
293 | | {PP_INPUT_HLL_TIME, "Signal Loss Hold Time (DMX IN)"}, |
294 | | {PP_PCP_ENABLE, "Per Channel Priority Enable"}, |
295 | | {PP_INPUT_UNIVERSE, "Input Universe"}, |
296 | | {PP_MODEL_NAME, "Model Name"}, |
297 | | {PP_MANUF_NAME, "Manufacturer Name"}, |
298 | | {PP_VER_STR, "Firmware Ver (String)"}, |
299 | | {PP_SERIAL_STR, "Serial Number (String)"}, |
300 | | {PP_NODE_NOTES, "Node User Notes"}, |
301 | | {PP_PORT_NOTES, "Port User Notes"}, |
302 | | {PP_USER_NODE_ID, "User Node ID"}, |
303 | | {PP_MDG_GEN_STATE, "MDG Generator Status"}, |
304 | | {PP_EMBEDDED_ID, "Embedded Device ID"}, |
305 | | {PP_SLAVE_DMX_START, "Embedded Device DMX Address"}, |
306 | | {PP_TB_MODE, "RDM Discovery Enable"}, |
307 | | {PP_LINK_MODE, "Ethernet Link Mode"}, |
308 | | {PP_LINK_STATUS, "Ethernet Link Status"}, |
309 | | {PP_CONNECTED_COUNT, "Connected PP Devices"}, |
310 | | {PP_POE_STATUS, "PoE Status"}, |
311 | | {PP_POE_EXTERN_WATT, "PoE External Supply Wattage"}, |
312 | | {PP_POE_CURRENT_WATT, "PoE Current Supply Wattage"}, |
313 | | {PP_SFP_MODULE_TYPE, "SFP Module Type"}, |
314 | | {PP_POE_EXTERN_PRESENT, "PoE External Supply Present"}, |
315 | | {PP_POE_CAPABLE, "PoE Capable Port"}, |
316 | | {PP_SWITCH_PORT_TYPE, "Ethernet Port Type"}, |
317 | | {PP_POE_MAX_ALLOC_MW, "PoE Max Alloc mW"}, |
318 | | {PP_POE_CURRENT_ALLOC_MW, "PoE Current Alloc mW"}, |
319 | | {PP_VLAN_RANGE_START, "VLAN Range Start"}, |
320 | | {PP_VLAN_RANGE_END, "VLAN Range End"}, |
321 | | {PP_VLAN_IS_TAGGED, "VLAN Port is Tagged"}, |
322 | | {PP_VLAN_PORT_VID, "VLAN Port VID"}, |
323 | | {PP_VLAN_MGMT_VID, "VLAN Management VID"}, |
324 | | {PP_VLAN_ENABLE, "VLAN Enable"}, |
325 | | {PP_EAPS_MODE, "EAPS Mode"}, |
326 | | {PP_EAPS_VLAN, "EAPS Control VLAN"}, |
327 | | {PP_EAPS_PRI_PORT, "EAPS Primary Port"}, |
328 | | {PP_EAPS_SEC_PORT, "EAPS Secondary Port"}, |
329 | | {PP_LLDP_PARTNER_MAC, "LLDP Partner MAC"}, |
330 | | {PP_LLDP_PARTNER_PORT, "LLDP Partner Port"}, |
331 | | /* XXX: ET_PARAM ?? */ |
332 | | {PP_END, "End"}, |
333 | | {0, NULL} |
334 | | }; |
335 | | |
336 | | static value_string_ext pp_pid_vals_ext = VALUE_STRING_EXT_INIT(pp_pid_vals); |
337 | | |
338 | | /** Unknown type format. */ |
339 | 73 | #define TYPE_UNKNOWN "Unknown (%04x)" |
340 | | |
341 | | /* End Field and enum declarations */ |
342 | | |
343 | | |
344 | | /* Code to actually dissect the packets */ |
345 | | static unsigned dissect_one_tlv(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, |
346 | | unsigned offset) |
347 | 0 | { |
348 | 0 | proto_item *ti; |
349 | 0 | proto_tree *tlv_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_pp_tlv, &ti, "Property"); |
350 | |
|
351 | 0 | unsigned len; |
352 | 0 | unsigned pad_len; |
353 | |
|
354 | 0 | unsigned type = tvb_get_ntohs(tvb, offset); |
355 | 0 | const char *name = val_to_str_ext(pinfo->pool, type, &pp_pid_vals_ext, TYPE_UNKNOWN); |
356 | 0 | proto_item_append_text(ti, " : %s", name); |
357 | |
|
358 | 0 | proto_tree_add_item(tlv_tree, hf_pp_pid_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
359 | 0 | offset += 2; |
360 | |
|
361 | 0 | len = tvb_get_ntohs(tvb, offset); |
362 | 0 | proto_item_set_len(ti, 4 + len); |
363 | |
|
364 | 0 | proto_tree_add_item(tlv_tree, hf_pp_pid_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
365 | 0 | offset += 2; |
366 | |
|
367 | 0 | proto_tree_add_item(tlv_tree, hf_pp_pid_value, tvb, offset, len, ENC_NA); |
368 | 0 | offset += len; |
369 | |
|
370 | 0 | pad_len = ~(offset-1) & 3; |
371 | 0 | if(pad_len) |
372 | 0 | { |
373 | 0 | proto_tree_add_item(tlv_tree, hf_pp_pid_pad_bytes, tvb, offset, pad_len, ENC_NA); |
374 | 0 | offset += pad_len; |
375 | 0 | } |
376 | 0 | return offset; |
377 | 0 | } |
378 | | |
379 | | |
380 | | static unsigned |
381 | | dissect_multiple_tlvs(tvbuff_t *tvb, packet_info* pinfo, proto_item *ti, |
382 | | unsigned offset, unsigned len) |
383 | 1 | { |
384 | 1 | unsigned end = offset + len; |
385 | 1 | while(offset < end) { |
386 | 0 | offset = dissect_one_tlv(tvb, pinfo, ti, offset); |
387 | 0 | } |
388 | 1 | return offset; |
389 | 1 | } |
390 | | |
391 | | static unsigned |
392 | | dissect_multiple_get_pids(tvbuff_t *tvb, proto_item *tree, unsigned offset, unsigned len) |
393 | 3 | { |
394 | 3 | unsigned end = offset + len; |
395 | | |
396 | 73 | while(offset < end) |
397 | 70 | { |
398 | 70 | proto_tree_add_item(tree, hf_pp_get_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
399 | 70 | offset += 2; |
400 | 70 | } |
401 | 3 | return len; |
402 | 3 | } |
403 | | |
404 | | static unsigned |
405 | | dissect_data_payload(tvbuff_t *tvb, proto_item *tree, unsigned offset, unsigned len) |
406 | 2 | { |
407 | 2 | unsigned end = offset + len; |
408 | 2 | unsigned blklen = 0; |
409 | 2 | unsigned xdmx, stc; |
410 | | |
411 | 3 | while(offset < end) |
412 | 1 | { |
413 | 1 | proto_item *ti; |
414 | 1 | proto_tree *data_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_pp_data, &ti, "xDMX Data: "); |
415 | 1 | proto_tree_add_item(data_tree, hf_pp_data_encoding, tvb, offset, 2, ENC_BIG_ENDIAN); |
416 | 1 | offset += 2; |
417 | 1 | blklen = tvb_get_ntohs(tvb, offset); |
418 | 1 | proto_tree_add_item(data_tree, hf_pp_data_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
419 | 1 | offset += 2; |
420 | 1 | proto_tree_add_item(data_tree, hf_pp_reserved, tvb, offset++, 1, ENC_NA); |
421 | 1 | stc = tvb_get_uint8(tvb, offset); |
422 | 1 | proto_tree_add_item(data_tree, hf_pp_data_start_code, tvb, offset++, 1, ENC_BIG_ENDIAN); |
423 | 1 | xdmx = tvb_get_ntohs(tvb, offset); |
424 | 1 | proto_tree_add_item(data_tree, hf_pp_data_dst, tvb, offset, 2, ENC_BIG_ENDIAN); |
425 | 1 | offset += 2; |
426 | 1 | proto_tree_add_item(data_tree, hf_pp_data_levels, tvb, offset, blklen, ENC_NA); |
427 | 1 | proto_item_append_text(ti, "%d Channels at xDMX %d (Univ %d.%d) StartCode: %d ", blklen, xdmx, xdmx / 512 + 1, xdmx % 512, stc); |
428 | 1 | offset += roof4(blklen); |
429 | 1 | } |
430 | 2 | return len; |
431 | 2 | } |
432 | | |
433 | | static unsigned |
434 | | dissect_arp_reply(tvbuff_t *tvb, proto_tree *tree, unsigned offset, unsigned len) |
435 | 0 | { |
436 | 0 | proto_tree_add_item(tree, hf_pp_arp_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
437 | 0 | offset += 4; |
438 | 0 | proto_tree_add_item(tree, hf_pp_arp_ip, tvb, offset, 4, ENC_BIG_ENDIAN); |
439 | 0 | offset += 4; |
440 | 0 | proto_tree_add_item(tree, hf_pp_arp_manuf, tvb, offset++, 1, ENC_BIG_ENDIAN); |
441 | 0 | proto_tree_add_item(tree, hf_pp_arp_class, tvb, offset++, 1, ENC_BIG_ENDIAN); |
442 | 0 | proto_tree_add_item(tree, hf_pp_arp_type, tvb, offset++, 1, ENC_BIG_ENDIAN); |
443 | 0 | proto_tree_add_item(tree, hf_pp_arp_numdmx, tvb, offset++, 1, ENC_BIG_ENDIAN); |
444 | 0 | return len; |
445 | 0 | } |
446 | | |
447 | | static unsigned |
448 | | dissect_one_pdu(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset) |
449 | 61 | { |
450 | 61 | proto_item *ti; |
451 | 61 | proto_tree *pdu_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_pp_pdu, &ti, "PDU"); |
452 | | |
453 | 61 | unsigned len; |
454 | | |
455 | 61 | unsigned type = tvb_get_ntohs(tvb, offset); |
456 | 61 | const char *name = val_to_str(pinfo->pool, type, pp_pdu_vals, TYPE_UNKNOWN); |
457 | | |
458 | 61 | proto_item_append_text(ti, " : %s", name); |
459 | | |
460 | 61 | proto_tree_add_item(pdu_tree, hf_pp_pdu_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
461 | 61 | offset += 2; |
462 | | |
463 | 61 | len = tvb_get_ntohs(tvb, offset); |
464 | 61 | proto_item_set_len(ti, 4 + len); |
465 | | |
466 | 61 | proto_tree_add_item(pdu_tree, hf_pp_pdu_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
467 | 61 | offset += 2; |
468 | | |
469 | 61 | switch(type) |
470 | 61 | { |
471 | 0 | case PP_ARP_REPLY : |
472 | 0 | dissect_arp_reply(tvb, pdu_tree, offset, len); |
473 | 0 | break; |
474 | 3 | case PP_GET : |
475 | 3 | dissect_multiple_get_pids(tvb, pdu_tree, offset, len); |
476 | 3 | break; |
477 | 0 | case PP_SET : |
478 | 0 | case PP_GET_REPLY : |
479 | 1 | case PP_ARP_INFO : |
480 | 1 | dissect_multiple_tlvs(tvb, pinfo, pdu_tree, offset, len); |
481 | 1 | break; |
482 | 2 | case PP_DATA : |
483 | 2 | dissect_data_payload(tvb, pdu_tree, offset, len); |
484 | 2 | break; |
485 | 55 | default: |
486 | 55 | proto_tree_add_item(pdu_tree, hf_pp_pdu_payload, tvb, offset, len, ENC_NA); |
487 | 55 | break; |
488 | 61 | } |
489 | 50 | offset += roof4(len); |
490 | 50 | return offset; |
491 | 61 | } |
492 | | |
493 | | static unsigned |
494 | | dissect_multiple_pdus(tvbuff_t *tvb, packet_info* pinfo, proto_item *ti, |
495 | | unsigned offset, unsigned len) |
496 | 13 | { |
497 | 13 | unsigned end = offset + len; |
498 | 74 | while(offset < end) { |
499 | 61 | offset = dissect_one_pdu(tvb, pinfo, ti, offset); |
500 | 61 | } |
501 | 13 | return offset; |
502 | 13 | } |
503 | | |
504 | | static int |
505 | | dissect_header(tvbuff_t *tvb, proto_tree *parent, unsigned offset) |
506 | 13 | { |
507 | 13 | proto_tree *tree = proto_tree_add_subtree(parent, tvb, offset, PATHPORT_HEADER_LENGTH, ett_pathport, NULL, "Header"); |
508 | | |
509 | 13 | proto_tree_add_item(tree, hf_pp_prot, tvb, offset, 2, ENC_BIG_ENDIAN); |
510 | 13 | offset += 2; |
511 | 13 | proto_tree_add_item(tree, hf_pp_version, tvb, offset, 2, ENC_BIG_ENDIAN); |
512 | 13 | offset += 2; |
513 | 13 | proto_tree_add_item(tree, hf_pp_seq, tvb, offset, 2, ENC_BIG_ENDIAN); |
514 | 13 | offset += 2; |
515 | 13 | proto_tree_add_item(tree, hf_pp_reserved, tvb, offset, 6, ENC_NA); |
516 | 13 | offset += 6; |
517 | 13 | proto_tree_add_item(tree, hf_pp_src, tvb, offset, 4, ENC_BIG_ENDIAN); |
518 | 13 | offset += 4; |
519 | 13 | proto_tree_add_item(tree, hf_pp_dst, tvb, offset, 4, ENC_BIG_ENDIAN); |
520 | 13 | offset += 4; |
521 | 13 | return offset; |
522 | 13 | } |
523 | | |
524 | | static bool |
525 | | packet_is_pathport(tvbuff_t *tvb) |
526 | 1.29k | { |
527 | 1.29k | if(tvb_captured_length(tvb) < PATHPORT_MIN_LENGTH) |
528 | 689 | return false; |
529 | | |
530 | 604 | if(tvb_get_ntohs(tvb, 0) != PATHPORT_PROTO_MAGIC) |
531 | 591 | return false; |
532 | | /* could also check that the first PDU is in our list of supported PDUs */ |
533 | | |
534 | 13 | return true; |
535 | 604 | } |
536 | | |
537 | | static int dissect_pathport_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
538 | 13 | { |
539 | | /* Set up structures needed to add the protocol subtree and manage it */ |
540 | 13 | proto_item *ti; |
541 | 13 | proto_tree *pathport_tree; |
542 | 13 | unsigned offset = 0; |
543 | 13 | unsigned remaining_len; |
544 | 13 | unsigned len; |
545 | 13 | uint16_t type; |
546 | 13 | uint32_t srcid; |
547 | 13 | uint32_t dstid; |
548 | | |
549 | 13 | len = tvb_reported_length(tvb); |
550 | | |
551 | | /* Set the Protocol column to the constant string of Pathport */ |
552 | 13 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Pathport"); |
553 | | |
554 | | /* Set the info column to reflect the first PDU in the packet */ |
555 | 13 | col_clear(pinfo->cinfo, COL_INFO); |
556 | 13 | srcid = tvb_get_ntohl(tvb, PATHPORT_HEADER_SRCID_OFFSET); |
557 | 13 | type = tvb_get_ntohs(tvb, PATHPORT_HEADER_LENGTH); |
558 | | |
559 | 13 | if(type == PP_ARP_REQUEST) |
560 | 0 | { |
561 | 0 | dstid = tvb_get_ntohl(tvb, PATHPORT_HEADER_DSTID_OFFSET); |
562 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", |
563 | 0 | val_to_str(pinfo->pool, dstid, ednet_id_vals, "%X"), val_to_str(pinfo->pool, srcid, ednet_id_vals, "%X")); |
564 | 0 | } |
565 | 13 | else |
566 | 13 | { |
567 | 13 | if((type == PP_ARP_REPLY) && (len >= 36)) |
568 | 0 | { |
569 | 0 | uint32_t id = tvb_get_ntohl(tvb, 24); |
570 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", val_to_str(pinfo->pool, id, ednet_id_vals, "%X"), tvb_ip_to_str(pinfo->pool, tvb, 28)); |
571 | 0 | } |
572 | 13 | else if((type == PP_DATA) && (len >= 32)) |
573 | 1 | { |
574 | 1 | uint16_t xdmx_start = tvb_get_ntohs(tvb, 30); |
575 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "xDMX Data - %d channels @ %d (Univ %d.%d)", |
576 | 1 | tvb_get_ntohs(tvb, 26), |
577 | 1 | xdmx_start, xdmx_start / 512 + 1, xdmx_start % 512); |
578 | 1 | } |
579 | 12 | else /* default */ |
580 | 12 | { |
581 | 12 | col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, type, pp_pdu_vals, TYPE_UNKNOWN)); |
582 | 12 | } |
583 | 13 | } |
584 | 13 | if(tree == NULL) |
585 | 0 | return tvb_reported_length(tvb); |
586 | | |
587 | | /* create display subtree for the protocol */ |
588 | 13 | ti = proto_tree_add_item(tree, proto_pathport, tvb, 0, -1, ENC_NA); |
589 | | |
590 | 13 | pathport_tree = proto_item_add_subtree(ti, ett_pathport); |
591 | 13 | offset = dissect_header(tvb, pathport_tree, PATHPORT_HEADER_OFFSET); |
592 | 13 | remaining_len = tvb_reported_length_remaining(tvb, offset); |
593 | 13 | offset = dissect_multiple_pdus(tvb, pinfo, tree, offset, remaining_len); |
594 | | |
595 | 13 | return offset; |
596 | 13 | } |
597 | | |
598 | | static int |
599 | | dissect_pathport(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
600 | | void *data _U_) |
601 | 0 | { |
602 | 0 | if(!packet_is_pathport(tvb)) |
603 | 0 | return 0; |
604 | 0 | return dissect_pathport_common(tvb, pinfo, tree); |
605 | 0 | } |
606 | | |
607 | | static bool |
608 | | dissect_pathport_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
609 | 1.29k | { |
610 | 1.29k | if(!packet_is_pathport(tvb)) |
611 | 1.28k | return false; |
612 | | |
613 | 13 | dissect_pathport_common(tvb, pinfo, tree); |
614 | 13 | return true; |
615 | 1.29k | } |
616 | | |
617 | | /* Register the protocol with Wireshark. |
618 | | */ |
619 | | void |
620 | | proto_register_pathport(void) |
621 | 16 | { |
622 | 16 | static hf_register_info hf[] = { |
623 | | /* Packet Header */ |
624 | 16 | {&hf_pp_prot, {"Protocol", "pathport.prot", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
625 | 16 | {&hf_pp_reserved, {"Reserved", "pathport.resv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
626 | 16 | {&hf_pp_version, {"Version", "pathport.version", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
627 | 16 | {&hf_pp_seq, {"Sequence", "pathport.seq", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
628 | 16 | {&hf_pp_src, {"Source ID", "pathport.src", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
629 | 16 | {&hf_pp_dst, {"Destination ID", "pathport.dst", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
630 | | |
631 | | /* PDU Header */ |
632 | 16 | {&hf_pp_pdu_type, {"PDU", "pathport.pdu", FT_UINT16, BASE_HEX, VALS(pp_pdu_vals), 0x0, NULL, HFILL }}, |
633 | 16 | {&hf_pp_pdu_len, {"Length", "pathport.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
634 | 16 | {&hf_pp_pdu_payload, {"Payload", "pathport.payload", FT_BYTES, 0, NULL, 0x0, NULL, HFILL }}, |
635 | | |
636 | | /* Property structures */ |
637 | 16 | {&hf_pp_get_type, {"Get", "pathport.get.pid", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &pp_pid_vals_ext, 0x0, NULL, HFILL }}, |
638 | 16 | {&hf_pp_pid_type, {"Property", "pathport.pid", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &pp_pid_vals_ext, 0x0, NULL, HFILL }}, |
639 | 16 | {&hf_pp_pid_len, {"Length", "pathport.pid.len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
640 | 16 | {&hf_pp_pid_value, {"Value", "pathport.pid.value", FT_BYTES, 0, NULL, 0x0, NULL, HFILL }}, |
641 | 16 | {&hf_pp_pid_pad_bytes, {"Pad bytes", "pathport.pid.pad_bytes", FT_BYTES, 0, NULL, 0x0, NULL, HFILL }}, |
642 | | |
643 | | /* Pathport XDMX Data */ |
644 | 16 | {&hf_pp_data_encoding, {"Data Encoding", "pathport.data.encoding", FT_UINT16, BASE_HEX, VALS(pp_data_encoding_vals), 0x0, NULL, HFILL }}, |
645 | 16 | {&hf_pp_data_start_code, {"DMX Start Code", "pathport.data.startcode", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
646 | 16 | {&hf_pp_data_len, {"Data Length", "pathport.data.len", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
647 | 16 | {&hf_pp_data_dst, {"xDMX Destination", "pathport.data.dst", FT_UINT16, BASE_HEX, NULL, 0x0,NULL, HFILL }}, |
648 | 16 | {&hf_pp_data_levels, {"Levels", "pathport.data.levels", FT_NONE, 0, NULL, 0x0, NULL, HFILL }}, |
649 | | |
650 | | /* PP_ARP Reply structures */ |
651 | 16 | {&hf_pp_arp_id, {"ID", "pathport.arp.id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
652 | 16 | {&hf_pp_arp_manuf, {"Manufacturer", "pathport.arp.manuf", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
653 | 16 | {&hf_pp_arp_class, {"Device Class", "pathport.arp.class", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
654 | 16 | {&hf_pp_arp_type, {"Device Type", "pathport.arp.type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
655 | 16 | {&hf_pp_arp_numdmx, {"Subcomponents", "pathport.arp.numdmx", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
656 | 16 | {&hf_pp_arp_ip, {"IP", "pathport.arp.ip", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
657 | 16 | }; |
658 | | |
659 | | /* Setup protocol subtree array */ |
660 | 16 | static int *ett[] = { |
661 | 16 | &ett_pathport, |
662 | 16 | &ett_pp_pdu, |
663 | 16 | &ett_pp_tlv, |
664 | 16 | &ett_pp_data |
665 | 16 | }; |
666 | | |
667 | | /* Register the protocol name and description */ |
668 | 16 | proto_pathport = proto_register_protocol("Pathport Protocol", "Pathport", "pathport"); |
669 | | |
670 | | /* Required function calls to register the header fields and subtrees */ |
671 | 16 | proto_register_field_array(proto_pathport, hf, array_length(hf)); |
672 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
673 | | |
674 | | /* Register the dissector handle */ |
675 | 16 | pathport_handle = register_dissector("pathport", dissect_pathport, proto_pathport); |
676 | 16 | } |
677 | | |
678 | | void |
679 | | proto_reg_handoff_pathport(void) |
680 | 16 | { |
681 | 16 | heur_dissector_add("udp", dissect_pathport_heur, "Pathport over UDP", "pathport_udp", proto_pathport, HEURISTIC_ENABLE); |
682 | 16 | dissector_add_uint_with_preference("udp.port", PATHPORT_UDP_PORT, pathport_handle); |
683 | 16 | } |
684 | | |
685 | | /* |
686 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
687 | | * |
688 | | * Local variables: |
689 | | * c-basic-offset: 4 |
690 | | * tab-width: 8 |
691 | | * indent-tabs-mode: nil |
692 | | * End: |
693 | | * |
694 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
695 | | * :indentSize=4:tabSize=8:noTabs=true: |
696 | | */ |