1 /* packet-enip.c
2 * Routines for EtherNet/IP (Industrial Protocol) dissection
3 * EtherNet/IP Home: www.odva.org
4 *
5 * This dissector includes items from:
6 * CIP Volume 1: Common Industrial Protocol, Edition 3.24
7 * CIP Volume 2: EtherNet/IP Adaptation of CIP, Edition 1.27
8 * CIP Volume 8: CIP Security, Edition 1.11
9 *
10 * Copyright 2003-2004
11 * Magnus Hansson <mah@hms.se>
12 * Joakim Wiberg <jow@hms.se>
13 *
14 * Conversation data support for CIP
15 * Jan Bartels, Siempelkamp Maschinen- und Anlagenbau GmbH & Co. KG
16 * Copyright 2007
17 *
18 * Ethernet/IP object support
19 * Michael Mann
20 * Copyright 2011
21 *
22 * Wireshark - Network traffic analyzer
23 * By Gerald Combs <gerald@wireshark.org>
24 * Copyright 1998 Gerald Combs
25 *
26 * SPDX-License-Identifier: GPL-2.0-or-later
27 */
28
29 #include "config.h"
30
31 #include <epan/packet.h>
32 #include <epan/conversation_filter.h>
33 #include <epan/prefs.h>
34 #include <epan/etypes.h>
35 #include <epan/expert.h>
36 #include <epan/decode_as.h>
37 #include <epan/proto_data.h>
38 #include <ipproto.h>
39
40 #include "packet-tcp.h"
41 #include "packet-cip.h"
42 #include "packet-enip.h"
43 #include "packet-cipsafety.h"
44 #include "packet-dtls.h"
45 #include "packet-tls.h"
46 #include "packet-tls-utils.h"
47
48 void proto_register_enip(void);
49 void proto_reg_handoff_enip(void);
50
51 /* Communication Ports */
52 #define ENIP_ENCAP_PORT 44818 /* EtherNet/IP located on port 44818 */
53 #define ENIP_SECURE_PORT 2221 /* EtherNet/IP TLS/DTLS port */
54 #define ENIP_IO_PORT 2222 /* EtherNet/IP IO located on port 2222 */
55
56 /* EtherNet/IP function codes */
57 #define NOP 0x0000
58 #define LIST_SERVICES 0x0004
59 #define LIST_IDENTITY 0x0063
60 #define LIST_INTERFACES 0x0064
61 #define REGISTER_SESSION 0x0065
62 #define UNREGISTER_SESSION 0x0066
63 #define SEND_RR_DATA 0x006F
64 #define SEND_UNIT_DATA 0x0070
65 #define START_DTLS 0x00C8
66
67 /* EtherNet/IP status codes */
68 #define SUCCESS 0x0000
69 #define INVALID_CMD 0x0001
70 #define NO_RESOURCES 0x0002
71 #define INCORRECT_DATA 0x0003
72 #define INVALID_SESSION 0x0064
73 #define INVALID_LENGTH 0x0065
74 #define UNSUPPORTED_PROT_REV 0x0069
75 #define ENCAP_HEADER_ERROR 0x006A
76
77 /* EtherNet/IP Common Packet Format Type IDs */
78 #define CPF_ITEM_NULL 0x0000
79 #define CPF_ITEM_CIP_IDENTITY 0x000C
80 #define CPF_ITEM_CIP_SECURITY 0x0086
81 #define CPF_ITEM_ENIP_CAPABILITY 0x0087
82 #define CPF_ITEM_ENIP_USAGE 0x0088
83 #define CPF_ITEM_CONNECTED_ADDRESS 0x00A1
84 #define CPF_ITEM_CONNECTED_DATA 0x00B1
85 #define CPF_ITEM_UNCONNECTED_DATA 0x00B2
86 #define CPF_ITEM_LIST_SERVICES_RESP 0x0100
87 #define CPF_ITEM_SOCK_ADR_INFO_OT 0x8000
88 #define CPF_ITEM_SOCK_ADR_INFO_TO 0x8001
89 #define CPF_ITEM_SEQUENCED_ADDRESS 0x8002
90 #define CPF_ITEM_UNCONNECTED_MSG_DTLS 0x8003
91
92 /* Initialize the protocol and registered fields */
93 static int proto_enip = -1;
94 static int proto_cipio = -1;
95 static int proto_cip_class1 = -1;
96
97 static int hf_enip_command = -1;
98 static int hf_enip_length = -1;
99 static int hf_enip_options = -1;
100 static int hf_enip_sendercontex = -1;
101 static int hf_enip_listid_delay = -1;
102 static int hf_enip_status = -1;
103 static int hf_enip_session = -1;
104 static int hf_enip_encapver = -1;
105 static int hf_enip_sinfamily = -1;
106 static int hf_enip_sinport = -1;
107 static int hf_enip_sinaddr = -1;
108 static int hf_enip_sinzero = -1;
109 static int hf_enip_timeout = -1;
110 static int hf_enip_encap_data = -1;
111
112 static int hf_enip_lir_vendor = -1;
113 static int hf_enip_lir_devtype = -1;
114 static int hf_enip_lir_prodcode = -1;
115 static int hf_enip_lir_revision = -1;
116 static int hf_enip_lir_status = -1;
117 static int hf_enip_lir_serial = -1;
118 static int hf_enip_lir_namelen = -1;
119 static int hf_enip_lir_name = -1;
120 static int hf_enip_lir_state = -1;
121
122 static int hf_enip_lsr_capaflags = -1;
123 static int hf_enip_lsr_tcp = -1;
124 static int hf_enip_lsr_udp = -1;
125 static int hf_enip_lsr_servicename = -1;
126
127 static int hf_enip_rs_version = -1;
128 static int hf_enip_rs_optionflags = -1;
129
130 static int hf_enip_security_profiles = -1;
131 static int hf_enip_security_profiles_eip_integrity = -1;
132 static int hf_enip_security_profiles_eip_confidentiality = -1;
133 static int hf_enip_security_profiles_cip_authorization = -1;
134 static int hf_enip_security_profiles_cip_user_authentication = -1;
135 static int hf_enip_security_profiles_resource_constrained = -1;
136 static int hf_enip_security_profiles_reserved = -1;
137 static int hf_enip_cip_security_state = -1;
138 static int hf_enip_eip_security_state = -1;
139 static int hf_enip_iana_port_state_flags = -1;
140 static int hf_enip_iana_port_state_flags_tcp_44818 = -1;
141 static int hf_enip_iana_port_state_flags_udp_44818 = -1;
142 static int hf_enip_iana_port_state_flags_udp_2222 = -1;
143 static int hf_enip_iana_port_state_flags_tcp_2221 = -1;
144 static int hf_enip_iana_port_state_flags_udp_2221 = -1;
145 static int hf_enip_iana_port_state_flags_reserved = -1;
146
147 static int hf_enip_srrd_ifacehnd = -1;
148
149 static int hf_enip_sud_ifacehnd = -1;
150
151 static int hf_enip_cpf_itemcount = -1;
152 static int hf_enip_cpf_typeid = -1;
153 static int hf_enip_cpf_length = -1;
154 static int hf_cip_sequence_count = -1;
155 static int hf_cip_cm_ot_api = -1;
156 static int hf_cip_cm_to_api = -1;
157 static int hf_enip_cpf_cai_connid = -1;
158 static int hf_enip_cpf_sai_connid = -1;
159 static int hf_cip_connid = -1;
160 static int hf_enip_cpf_sai_seqnum = -1;
161 static int hf_enip_cpf_ucmm_request = -1;
162 static int hf_enip_cpf_ucmm_msg_type = -1;
163 static int hf_enip_cpf_ucmm_trans_id = -1;
164 static int hf_enip_cpf_ucmm_status = -1;
165
166 static int hf_enip_cpf_data = -1;
167
168 static int hf_enip_response_in = -1;
169 static int hf_enip_response_to = -1;
170 static int hf_enip_time = -1;
171 static int hf_enip_fwd_open_in = -1;
172 static int hf_cip_connection = -1;
173 static int hf_cip_io_data = -1;
174
175 /* Parsed Attributes */
176 static int hf_tcpip_status = -1;
177 static int hf_tcpip_status_interface_config = -1;
178 static int hf_tcpip_status_mcast_pending = -1;
179 static int hf_tcpip_status_interface_config_pending = -1;
180 static int hf_tcpip_status_acd = -1;
181 static int hf_tcpip_acd_fault = -1;
182 static int hf_tcpip_status_iana_port_admin_change = -1;
183 static int hf_tcpip_status_iana_protocol_admin_change = -1;
184 static int hf_tcpip_status_reserved = -1;
185 static int hf_tcpip_config_cap = -1;
186 static int hf_tcpip_config_cap_bootp = -1;
187 static int hf_tcpip_config_cap_dns = -1;
188 static int hf_tcpip_config_cap_dhcp = -1;
189 static int hf_tcpip_config_cap_dhcp_dns_update = -1;
190 static int hf_tcpip_config_cap_config_settable = -1;
191 static int hf_tcpip_config_cap_hardware_config = -1;
192 static int hf_tcpip_config_cap_interface_reset = -1;
193 static int hf_tcpip_config_cap_acd = -1;
194 static int hf_tcpip_config_cap_reserved = -1;
195 static int hf_tcpip_config_control = -1;
196 static int hf_tcpip_config_control_config = -1;
197 static int hf_tcpip_config_control_dns = -1;
198 static int hf_tcpip_config_control_reserved = -1;
199 static int hf_tcpip_ic_ip_addr = -1;
200 static int hf_tcpip_ic_subnet_mask = -1;
201 static int hf_tcpip_ic_gateway = -1;
202 static int hf_tcpip_ic_name_server = -1;
203 static int hf_tcpip_ic_name_server2 = -1;
204 static int hf_tcpip_ic_domain_name = -1;
205 static int hf_tcpip_hostname = -1;
206 static int hf_tcpip_snn_timestamp = -1;
207 static int hf_tcpip_snn_date = -1;
208 static int hf_tcpip_snn_time = -1;
209 static int hf_tcpip_ttl_value = -1;
210 static int hf_tcpip_mcast_alloc = -1;
211 static int hf_tcpip_mcast_reserved = -1;
212 static int hf_tcpip_mcast_num_mcast = -1;
213 static int hf_tcpip_mcast_addr_start = -1;
214 static int hf_tcpip_lcd_acd_activity = -1;
215 static int hf_tcpip_lcd_remote_mac = -1;
216 static int hf_tcpip_lcd_arp_pdu = -1;
217 static int hf_tcpip_select_acd = -1;
218 static int hf_tcpip_quick_connect = -1;
219 static int hf_tcpip_encap_inactivity = -1;
220
221 static int hf_tcpip_port_count = -1;
222 static int hf_tcpip_port_name = -1;
223 static int hf_tcpip_port_number = -1;
224 static int hf_tcpip_port_protocol = -1;
225 static int hf_tcpip_port_admin_state = -1;
226 static int hf_tcpip_port_admin_capability = -1;
227 static int hf_tcpip_admin_capability_configurable = -1;
228 static int hf_tcpip_admin_capability_reset_required = -1;
229 static int hf_tcpip_admin_capability_reserved = -1;
230
231 static int hf_elink_interface_flags = -1;
232 static int hf_elink_iflags_link_status = -1;
233 static int hf_elink_iflags_duplex = -1;
234 static int hf_elink_iflags_neg_status = -1;
235 static int hf_elink_iflags_manual_reset = -1;
236 static int hf_elink_iflags_local_hw_fault = -1;
237 static int hf_elink_iflags_reserved = -1;
238 static int hf_elink_interface_speed = -1;
239 static int hf_elink_physical_address = -1;
240 static int hf_elink_icount_in_octets = -1;
241 static int hf_elink_icount_in_ucast = -1;
242 static int hf_elink_icount_in_nucast = -1;
243 static int hf_elink_icount_in_discards = -1;
244 static int hf_elink_icount_in_errors = -1;
245 static int hf_elink_icount_in_unknown_protos = -1;
246 static int hf_elink_icount_out_octets = -1;
247 static int hf_elink_icount_out_ucast = -1;
248 static int hf_elink_icount_out_nucast = -1;
249 static int hf_elink_icount_out_discards = -1;
250 static int hf_elink_icount_out_errors = -1;
251 static int hf_elink_mcount_alignment_errors = -1;
252 static int hf_elink_mcount_fcs_errors = -1;
253 static int hf_elink_mcount_single_collisions = -1;
254 static int hf_elink_mcount_multiple_collisions = -1;
255 static int hf_elink_mcount_sqe_test_errors = -1;
256 static int hf_elink_mcount_deferred_transmission = -1;
257 static int hf_elink_mcount_late_collisions = -1;
258 static int hf_elink_mcount_excessive_collisions = -1;
259 static int hf_elink_mcount_mac_transmit_errors = -1;
260 static int hf_elink_mcount_carrier_sense_errors = -1;
261 static int hf_elink_mcount_frame_too_long = -1;
262 static int hf_elink_mcount_mac_receive_errors = -1;
263 static int hf_elink_icontrol_control_bits = -1;
264 static int hf_elink_icontrol_control_bits_auto_neg = -1;
265 static int hf_elink_icontrol_control_bits_forced_duplex = -1;
266 static int hf_elink_icontrol_control_bits_reserved = -1;
267 static int hf_elink_icontrol_forced_speed = -1;
268 static int hf_elink_icapability_capability_bits = -1;
269 static int hf_elink_icapability_capability_bits_manual = -1;
270 static int hf_elink_icapability_capability_bits_auto_neg = -1;
271 static int hf_elink_icapability_capability_bits_auto_mdix = -1;
272 static int hf_elink_icapability_capability_bits_manual_speed = -1;
273 static int hf_elink_icapability_capability_speed_duplex_array_count = -1;
274 static int hf_elink_icapability_capability_speed = -1;
275 static int hf_elink_icapability_capability_duplex = -1;
276 static int hf_elink_interface_type = -1;
277 static int hf_elink_interface_state = -1;
278 static int hf_elink_admin_state = -1;
279 static int hf_elink_interface_label = -1;
280 static int hf_elink_hc_icount_in_octets = -1;
281 static int hf_elink_hc_icount_in_ucast = -1;
282 static int hf_elink_hc_icount_in_mcast = -1;
283 static int hf_elink_hc_icount_in_broadcast = -1;
284 static int hf_elink_hc_icount_out_octets = -1;
285 static int hf_elink_hc_icount_out_ucast = -1;
286 static int hf_elink_hc_icount_out_mcast = -1;
287 static int hf_elink_hc_icount_out_broadcast = -1;
288
289 static int hf_elink_hc_mcount_stats_align_errors = -1;
290 static int hf_elink_hc_mcount_stats_fcs_errors = -1;
291 static int hf_elink_hc_mcount_stats_internal_mac_transmit_errors = -1;
292 static int hf_elink_hc_mcount_stats_frame_too_long = -1;
293 static int hf_elink_hc_mcount_stats_internal_mac_receive_errors = -1;
294 static int hf_elink_hc_mcount_stats_symbol_errors = -1;
295
296 static int hf_qos_8021q_enable = -1;
297 static int hf_qos_dscp_ptp_event = -1;
298 static int hf_qos_dscp_ptp_general = -1;
299 static int hf_qos_dscp_urgent = -1;
300 static int hf_qos_dscp_scheduled = -1;
301 static int hf_qos_dscp_high = -1;
302 static int hf_qos_dscp_low = -1;
303 static int hf_qos_dscp_explicit = -1;
304
305 static int hf_dlr_network_topology = -1;
306 static int hf_dlr_network_status = -1;
307 static int hf_dlr_ring_supervisor_status = -1;
308 static int hf_dlr_rsc_ring_supervisor_enable = -1;
309 static int hf_dlr_rsc_ring_supervisor_precedence = -1;
310 static int hf_dlr_rsc_beacon_interval = -1;
311 static int hf_dlr_rsc_beacon_timeout = -1;
312 static int hf_dlr_rsc_dlr_vlan_id = -1;
313 static int hf_dlr_ring_faults_count = -1;
314 static int hf_dlr_lanp1_dev_ip_addr = -1;
315 static int hf_dlr_lanp1_dev_physical_address = -1;
316 static int hf_dlr_lanp2_dev_ip_addr = -1;
317 static int hf_dlr_lanp2_dev_physical_address = -1;
318 static int hf_dlr_ring_protocol_participants_count = -1;
319 static int hf_dlr_rppl_dev_ip_addr = -1;
320 static int hf_dlr_rppl_dev_physical_address = -1;
321 static int hf_dlr_asa_supervisor_ip_addr = -1;
322 static int hf_dlr_asa_supervisor_physical_address = -1;
323 static int hf_dlr_active_supervisor_precedence = -1;
324 static int hf_dlr_capability_flags = -1;
325 static int hf_dlr_capflags_announce_base_node = -1;
326 static int hf_dlr_capflags_beacon_base_node = -1;
327 static int hf_dlr_capflags_reserved1 = -1;
328 static int hf_dlr_capflags_supervisor_capable = -1;
329 static int hf_dlr_capflags_reserved2 = -1;
330 static int hf_dlr_capflags_redundant_gateway_capable = -1;
331 static int hf_dlr_capflags_flush_frame_capable = -1;
332 static int hf_dlr_rgc_red_gateway_enable = -1;
333 static int hf_dlr_rgc_gateway_precedence = -1;
334 static int hf_dlr_rgc_advertise_interval = -1;
335 static int hf_dlr_rgc_advertise_timeout = -1;
336 static int hf_dlr_rgc_learning_update_enable = -1;
337 static int hf_dlr_redundant_gateway_status = -1;
338 static int hf_dlr_aga_ip_addr = -1;
339 static int hf_dlr_aga_physical_address = -1;
340 static int hf_dlr_active_gateway_precedence = -1;
341
342 static int hf_cip_security_state = -1;
343 static int hf_eip_security_state = -1;
344 static int hf_eip_security_verify_client_cert = -1;
345 static int hf_eip_security_send_cert_chain = -1;
346 static int hf_eip_security_check_expiration = -1;
347 static int hf_eip_security_capability_flags = -1;
348 static int hf_eip_security_capflags_secure_renegotiation = -1;
349 static int hf_eip_security_capflags_reserved = -1;
350 static int hf_eip_security_num_avail_cipher_suites = -1;
351 static int hf_eip_security_avail_cipher_suite = -1;
352 static int hf_eip_security_num_allow_cipher_suites = -1;
353 static int hf_eip_security_allow_cipher_suite = -1;
354 static int hf_eip_security_num_psk = -1;
355 static int hf_eip_security_psk_identity_size = -1;
356 static int hf_eip_security_psk_identity = -1;
357 static int hf_eip_security_psk_size = -1;
358 static int hf_eip_security_psk = -1;
359 static int hf_eip_security_num_active_certs = -1;
360 static int hf_eip_security_num_trusted_auths = -1;
361 static int hf_eip_cert_name = -1;
362 static int hf_eip_cert_state = -1;
363 static int hf_eip_cert_encoding = -1;
364 static int hf_eip_cert_device_cert_status = -1;
365 static int hf_eip_cert_ca_cert_status = -1;
366 static int hf_eip_cert_capflags_push = -1;
367 static int hf_eip_cert_capflags_reserved = -1;
368 static int hf_eip_cert_capability_flags = -1;
369 static int hf_eip_cert_num_certs = -1;
370 static int hf_eip_cert_cert_name = -1;
371
372 /* Initialize the subtree pointers */
373 static gint ett_enip = -1;
374 static gint ett_cip_io_generic = -1;
375 static gint ett_path = -1;
376 static gint ett_count_tree = -1;
377 static gint ett_type_tree = -1;
378 static gint ett_command_tree = -1;
379 static gint ett_sockadd = -1;
380 static gint ett_lsrcf = -1;
381 static gint ett_tcpip_status = -1;
382 static gint ett_tcpip_admin_capability = -1;
383 static gint ett_tcpip_config_cap = -1;
384 static gint ett_tcpip_config_control = -1;
385 static gint ett_elink_interface_flags = -1;
386 static gint ett_elink_icontrol_bits = -1;
387 static gint ett_elink_icapability_bits = -1;
388 static gint ett_dlr_capability_flags = -1;
389 static gint ett_dlr_lnknbrstatus_flags = -1;
390 static gint ett_eip_security_capability_flags = -1;
391 static gint ett_eip_security_psk = -1;
392 static gint ett_eip_security_active_certs = -1;
393 static gint ett_eip_security_trusted_auths = -1;
394 static gint ett_eip_cert_capability_flags = -1;
395 static gint ett_eip_cert_num_certs = -1;
396 static gint ett_security_profiles = -1;
397 static gint ett_iana_port_state_flags = -1;
398 static gint ett_connection_info = -1;
399 static gint ett_connection_path_info = -1;
400 static gint ett_cmd_data = -1;
401
402 static expert_field ei_mal_tcpip_status = EI_INIT;
403 static expert_field ei_mal_tcpip_config_cap = EI_INIT;
404 static expert_field ei_mal_tcpip_config_control = EI_INIT;
405 static expert_field ei_mal_tcpip_interface_config = EI_INIT;
406 static expert_field ei_mal_tcpip_mcast_config = EI_INIT;
407 static expert_field ei_mal_tcpip_last_conflict = EI_INIT;
408 static expert_field ei_mal_tcpip_snn = EI_INIT;
409 static expert_field ei_mal_elink_interface_flags = EI_INIT;
410 static expert_field ei_mal_elink_physical_address = EI_INIT;
411 static expert_field ei_mal_elink_interface_counters = EI_INIT;
412 static expert_field ei_mal_elink_media_counters = EI_INIT;
413 static expert_field ei_mal_elink_interface_control = EI_INIT;
414 static expert_field ei_mal_dlr_ring_supervisor_config = EI_INIT;
415 static expert_field ei_mal_dlr_last_active_node_on_port_1 = EI_INIT;
416 static expert_field ei_mal_dlr_last_active_node_on_port_2 = EI_INIT;
417 static expert_field ei_mal_dlr_ring_protocol_participants_list = EI_INIT;
418 static expert_field ei_mal_dlr_active_supervisor_address = EI_INIT;
419 static expert_field ei_mal_dlr_capability_flags = EI_INIT;
420 static expert_field ei_mal_dlr_redundant_gateway_config = EI_INIT;
421 static expert_field ei_mal_dlr_active_gateway_address = EI_INIT;
422 static expert_field ei_mal_eip_security_capability_flags = EI_INIT;
423 static expert_field ei_mal_eip_security_avail_cipher_suites = EI_INIT;
424 static expert_field ei_mal_eip_security_allow_cipher_suites = EI_INIT;
425 static expert_field ei_mal_eip_security_preshared_keys = EI_INIT;
426 static expert_field ei_mal_eip_security_active_certs = EI_INIT;
427 static expert_field ei_mal_eip_security_trusted_auths = EI_INIT;
428 static expert_field ei_mal_eip_cert_capability_flags = EI_INIT;
429 static expert_field ei_mal_cpf_item_length_mismatch = EI_INIT;
430 static expert_field ei_mal_cpf_item_minimum_size = EI_INIT;
431
432 static dissector_table_t subdissector_srrd_table;
433 static dissector_table_t subdissector_io_table;
434 static dissector_table_t subdissector_decode_as_io_table;
435 static dissector_table_t subdissector_class_table;
436 static dissector_table_t subdissector_cip_connection_table;
437
438 static dissector_handle_t arp_handle;
439 static dissector_handle_t cipsafety_handle;
440 static dissector_handle_t cip_io_generic_handle;
441 static dissector_handle_t cip_implicit_handle;
442 static dissector_handle_t cip_handle;
443 static dissector_handle_t enip_tcp_handle;
444 static dissector_handle_t cipio_handle;
445 static dissector_handle_t cip_class1_handle;
446
447 static gboolean enip_desegment = TRUE;
448 static gboolean enip_OTrun_idle = TRUE;
449 static gboolean enip_TOrun_idle = FALSE;
450
451 static int proto_dlr = -1;
452
453 static int hf_dlr_ringsubtype = -1;
454 static int hf_dlr_ringprotoversion = -1;
455 static int hf_dlr_frametype = -1;
456 static int hf_dlr_sourceport = -1;
457 static int hf_dlr_sourceip = -1;
458 static int hf_dlr_sequenceid = -1;
459
460 static int hf_dlr_ringstate = -1;
461 static int hf_dlr_supervisorprecedence = -1;
462 static int hf_dlr_beaconinterval = -1;
463 static int hf_dlr_beacontimeout = -1;
464 static int hf_dlr_beaconreserved = -1;
465
466 static int hf_dlr_nreqreserved = -1;
467
468 static int hf_dlr_nressourceport = -1;
469 static int hf_dlr_nresreserved = -1;
470
471 static int hf_dlr_lnknbrstatus = -1;
472 static int hf_dlr_lnknbrstatus_port1 = -1;
473 static int hf_dlr_lnknbrstatus_port2 = -1;
474 static int hf_dlr_lnknbrstatus_reserved = -1;
475 static int hf_dlr_lnknbrstatus_frame_type = -1;
476 static int hf_dlr_lnknbrreserved = -1;
477
478 static int hf_dlr_lfreserved = -1;
479
480 static int hf_dlr_anreserved = -1;
481
482 static int hf_dlr_sonumnodes = -1;
483 static int hf_dlr_somac = -1;
484 static int hf_dlr_soip = -1;
485 static int hf_dlr_soreserved = -1;
486
487 static int hf_dlr_advgatewaystate = -1;
488 static int hf_dlr_advgatewayprecedence = -1;
489 static int hf_dlr_advadvertiseinterval = -1;
490 static int hf_dlr_advadvertisetimeout = -1;
491 static int hf_dlr_advlearningupdateenable = -1;
492 static int hf_dlr_advreserved = -1;
493
494 static int hf_dlr_flushlearningupdateenable = -1;
495 static int hf_dlr_flushreserved = -1;
496
497 static int hf_dlr_learnreserved = -1;
498
499 static gint ett_dlr = -1;
500
501 /* Translate function to string - Encapsulation commands */
502 static const value_string encap_cmd_vals[] = {
503 { NOP, "NOP" },
504 { LIST_SERVICES, "List Services" },
505 { LIST_IDENTITY, "List Identity" },
506 { LIST_INTERFACES, "List Interfaces" },
507 { REGISTER_SESSION, "Register Session" },
508 { UNREGISTER_SESSION,"Unregister Session" },
509 { SEND_RR_DATA, "Send RR Data" },
510 { SEND_UNIT_DATA, "Send Unit Data" },
511 { START_DTLS, "StartDTLS" },
512
513 { 0, NULL }
514 };
515
516 /* Translate function to string - Encapsulation status */
517 static const value_string encap_status_vals[] = {
518 { SUCCESS, "Success" },
519 { INVALID_CMD, "Invalid Command" },
520 { NO_RESOURCES, "No Memory Resources" },
521 { INCORRECT_DATA, "Incorrect Data" },
522 { INVALID_SESSION, "Invalid Session Handle" },
523 { INVALID_LENGTH, "Invalid Length" },
524 { UNSUPPORTED_PROT_REV, "Unsupported Protocol Revision" },
525 { ENCAP_HEADER_ERROR, "Encapsulated CIP service not allowed on this port" },
526
527 { 0, NULL }
528 };
529
530 /* Translate function to Common packet format values */
531 static const value_string cpf_type_vals[] = {
532 { CPF_ITEM_NULL, "Null Address Item" },
533 { CPF_ITEM_CIP_IDENTITY, "CIP Identity" },
534 { CPF_ITEM_CIP_SECURITY, "CIP Security Information" },
535 { CPF_ITEM_ENIP_CAPABILITY, "EtherNet/IP Capability" },
536 { CPF_ITEM_ENIP_USAGE, "EtherNet/IP Usage" },
537 { CPF_ITEM_CONNECTED_ADDRESS, "Connected Address Item" },
538 { CPF_ITEM_CONNECTED_DATA, "Connected Data Item" },
539 { CPF_ITEM_UNCONNECTED_DATA, "Unconnected Data Item" },
540 { CPF_ITEM_LIST_SERVICES_RESP, "List Services Response" },
541 { CPF_ITEM_SOCK_ADR_INFO_OT, "Socket Address Info O->T" },
542 { CPF_ITEM_SOCK_ADR_INFO_TO, "Socket Address Info T->O" },
543 { CPF_ITEM_SEQUENCED_ADDRESS, "Sequenced Address Item" },
544 { CPF_ITEM_UNCONNECTED_MSG_DTLS, "Unconnected Message over UDP" },
545
546 { 0, NULL }
547 };
548
549 static const value_string unconn_msg_type_vals[] = {
550 { 0, "Reserved" },
551 { 1, "UCMM_NOACK" },
552
553 { 0, NULL }
554 };
555
556 static const value_string enip_tcpip_status_interface_config_vals[] = {
557 { 0, "Not configured" },
558 { 1, "BOOTP/DHCP/NVS" },
559 { 2, "Hardware settings" },
560
561 { 0, NULL }
562 };
563
564 static const value_string enip_tcpip_status_acd_vals[] = {
565 { 0, "No Address Conflict Detected" },
566 { 1, "Address Conflict Detected" },
567
568 { 0, NULL }
569 };
570
571 static const value_string enip_tcpip_config_control_config_vals[] = {
572 { 0, "Static IP" },
573 { 1, "BOOTP" },
574 { 2, "DHCP" },
575
576 { 0, NULL }
577 };
578
579 static const value_string enip_tcpip_mcast_alloc_vals[] = {
580 { 0, "Use default multicast algorithm" },
581 { 1, "Use Num Mcast and Mcast Start Addr" },
582
583 { 0, NULL }
584 };
585
586 static const value_string enip_tcpip_acd_activity_vals[] = {
587 { 0, "No Conflict Detected" },
588 { 1, "Probe IPv4 Address" },
589 { 2, "Ongoing Detection" },
590 { 3, "Semi Active Probe" },
591
592 { 0, NULL }
593 };
594
595 static const value_string enip_elink_duplex_vals[] = {
596 { 0, "Half Duplex" },
597 { 1, "Full Duplex" },
598
599 { 0, NULL }
600 };
601
602 static const value_string enip_elink_iflags_neg_status_vals[] = {
603 { 0, "Auto-negotiation in progress" },
604 { 1, "Auto-negotiation and speed detection failed" },
605 { 2, "Auto-negotiation failed but detected speed" },
606 { 3, "Successfully negotiated speed and duplex" },
607 { 4, "Auto-negotiation not attempted. Forced speed and duplex" },
608
609 { 0, NULL }
610 };
611
612 static const value_string enip_elink_iflags_reset_vals[] = {
613 { 0, "Activate change automatically" },
614 { 1, "Device requires Reset service for change" },
615
616 { 0, NULL }
617 };
618
619 static const value_string enip_elink_iflags_hw_fault_vals[] = {
620 { 0, "No local hardware fault" },
621 { 1, "Local hardware fault detected" },
622
623 { 0, NULL }
624 };
625
626 static const value_string enip_elink_interface_type_vals[] = {
627 { 0, "Unknown type" },
628 { 1, "Internal" },
629 { 2, "Twisted-pair" },
630 { 3, "Optical fiber" },
631
632 { 0, NULL }
633 };
634
635 static const value_string enip_elink_interface_state_vals[] = {
636 { 0, "Unknown state" },
637 { 1, "Enabled" },
638 { 2, "Disabled" },
639 { 3, "Testing" },
640
641 { 0, NULL }
642 };
643
644 static const value_string enip_elink_admin_state_vals[] = {
645 { 1, "Enabled" },
646 { 2, "Disabled" },
647
648 { 0, NULL }
649 };
650
651 static const value_string enip_dlr_network_topology_vals[] = {
652 { 0, "Linear" },
653 { 1, "Ring" },
654
655 { 0, NULL }
656 };
657
658 static const value_string enip_dlr_network_status_vals[] = {
659 { 0, "Normal" },
660 { 1, "Ring Fault" },
661 { 2, "Unexpected Loop Detected" },
662 { 3, "Partial Network Failure" },
663 { 4, "Rapid Fault/Restore Cycle" },
664
665 { 0, NULL }
666 };
667
668 static const value_string enip_dlr_ring_supervisor_status_vals[] = {
669 { 0, "Backup Ring Supervisor" },
670 { 1, "Active Ring Supervisor" },
671 { 2, "Ring Node" },
672 { 3, "Non-DLR Topology" },
673 { 4, "Cannot Support Parameters" },
674
675 { 0, NULL }
676 };
677
678 static const value_string enip_dlr_redundant_gateway_status_vals[] = {
679 { 0, "Non-Gateway DLR node" },
680 { 1, "Backup Gateway" },
681 { 2, "Active Gateway" },
682 { 3, "Gateway Fault" },
683 { 4, "Cannot Support Parameters" },
684 { 5, "Partial Network Fault" },
685
686 { 0, NULL }
687 };
688
689 static const value_string cip_security_state_vals[] = {
690 { 0, "Factory Default Configuration" },
691 { 1, "Initial Commissioning In Progress" },
692 { 2, "Configured" },
693 { 3, "Incomplete Configuration" },
694
695 { 0, NULL }
696 };
697
698 static const value_string eip_security_state_vals[] = {
699 { 0, "Factory Default Configuration" },
700 { 1, "Configuration In Progress" },
701 { 2, "Configured" },
702
703 { 0, NULL }
704 };
705
706 static const value_string eip_cert_state_vals[] = {
707 { 0, "Created" },
708
709 { 0, NULL }
710 };
711
712 static const value_string eip_cert_status_vals[] = {
713 { 0, "Not Verified" },
714 { 1, "Verified" },
715 { 2, "Invalid" },
716
717 { 0, NULL }
718 };
719
720 /* Translate interface handle to string */
721 static const value_string enip_interface_handle_vals[] = {
722 { 0, "CIP" },
723
724 { 0, NULL }
725 };
726
727 /* Translate function to DLR Frame Type values */
728 static const value_string dlr_frame_type_vals[] = {
729 { DLR_FT_BEACON, "Beacon" },
730 { DLR_FT_NEIGHBOR_REQ, "Neighbor_Check_Request" },
731 { DLR_FT_NEIGHBOR_RES, "Neighbor_Check_Response" },
732 { DLR_FT_LINK_STAT, "Link_Status / Neighbor_Status" },
733 { DLR_FT_LOCATE_FLT, "Locate_Fault" },
734 { DLR_FT_ANNOUNCE, "Announce" },
735 { DLR_FT_SIGN_ON, "Sign_On" },
736 { DLR_FT_ADVERTISE, "Advertise" },
737 { DLR_FT_FLUSH_TABLES, "Flush_Tables" },
738 { DLR_FT_LEARNING_UPDATE, "Learning_Update" },
739
740 { 0, NULL }
741 };
742
743 /* Translate function to DLR Source Port values */
744 static const value_string dlr_source_port_vals[] = {
745 { 0, "Port 1 or Port 2" },
746 { 1, "Port 1" },
747 { 2, "Port 2" },
748
749 { 0, NULL }
750 };
751
752 /* Translate function to DLR Ring State values */
753 static const value_string dlr_ring_state_vals[] = {
754 { 1, "RING_NORMAL_STATE" },
755 { 2, "RING_FAULT_STATE" },
756
757 { 0, NULL }
758 };
759
760 /* Translate function to DLR Advertise State values */
761 static const value_string dlr_adv_state_vals[] = {
762 { 0x01, "ACTIVE_LISTEN_STATE" },
763 { 0x02, "ACTIVE_NORMAL_STATE" },
764 { 0x03, "FAULT_STATE" },
765
766 { 0, NULL }
767 };
768
769 /* Translate function to DLR Learning Update values */
770 static const value_string dlr_adv_learning_update_vals[] = {
771 { 0, "Disabled" },
772 { 1, "Enabled" },
773
774 { 0, NULL }
775 };
776
777 /* Translate function to DLR Flush Learning Update values */
778 static const value_string dlr_flush_learning_update_vals[] = {
779 { 0, "Disabled" },
780 { 1, "Enabled" },
781
782 { 0, NULL }
783 };
784
785 static const true_false_string dlr_lnknbrstatus_frame_type_vals = {
786 "Neighbor_Status Frame",
787 "Link_Status Frame"
788 };
789
enip_prompt(packet_info * pinfo _U_,gchar * result)790 static void enip_prompt(packet_info *pinfo _U_, gchar* result)
791 {
792 g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Dissect unidentified I/O traffic as");
793 }
794
795 static wmem_map_t *enip_request_hashtable = NULL;
796
797 /* Return codes of function classifying packets as query/response */
798 enum enip_packet_type {ENIP_REQUEST_PACKET, ENIP_RESPONSE_PACKET, ENIP_CANNOT_CLASSIFY};
799 enum enip_packet_data_type { EPDT_UNKNOWN, EPDT_CONNECTED_TRANSPORT, EPDT_UNCONNECTED };
800
801 typedef struct enip_request_key {
802 guint32 session_handle;
803 enum enip_packet_type requesttype;
804 enum enip_packet_data_type type;
805 guint64 sender_context;
806 guint32 conversation;
807 union {
808 struct {
809 guint32 connid;
810 guint16 sequence;
811 } connected_transport;
812 } data;
813 } enip_request_key_t;
814
815 typedef struct enip_request_val {
816 wmem_tree_t *frames;
817 } enip_request_val_t;
818
819 /*
820 * Hash Functions
821 */
822 static gboolean
enip_request_equal(gconstpointer v,gconstpointer w)823 enip_request_equal(gconstpointer v, gconstpointer w)
824 {
825 const enip_request_key_t *v1 = (const enip_request_key_t *)v;
826 const enip_request_key_t *v2 = (const enip_request_key_t *)w;
827
828 if ( v1->conversation == v2->conversation
829 && v1->session_handle == v2->session_handle
830 && v1->type == v2->type
831 && ( ( v1->sender_context == v2->sender_context /* heuristic approach */
832 && v1->type == EPDT_UNCONNECTED
833 )
834 ||
835 ( v1->data.connected_transport.connid == v2->data.connected_transport.connid
836 && v1->data.connected_transport.sequence == v2->data.connected_transport.sequence
837 && v1->type == EPDT_CONNECTED_TRANSPORT
838 )
839 )
840 )
841 return TRUE;
842
843 return FALSE;
844 }
845
846 static void
enip_fmt_lir_revision(gchar * result,guint32 revision)847 enip_fmt_lir_revision( gchar *result, guint32 revision )
848 {
849 g_snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (guint8)(( revision & 0xFF00 ) >> 8), (guint8)(revision & 0xFF) );
850 }
851
852 static guint
enip_request_hash(gconstpointer v)853 enip_request_hash (gconstpointer v)
854 {
855 const enip_request_key_t *key = (const enip_request_key_t *)v;
856 guint val;
857
858 val = (guint)(key->conversation * 37 + key->session_handle * 93 + key->type * 765);
859
860 if (key->type == EPDT_UNCONNECTED)
861 {
862 val += ((guint)(key->sender_context * 23));
863 }
864 else if (key->type == EPDT_CONNECTED_TRANSPORT)
865 {
866 val += ((guint)(key->data.connected_transport.connid * 87 + key->data.connected_transport.sequence * 834));
867 }
868
869 return val;
870 }
871
872 static enip_request_info_t *
enip_match_request(packet_info * pinfo,proto_tree * tree,enip_request_key_t * prequest_key)873 enip_match_request( packet_info *pinfo, proto_tree *tree, enip_request_key_t *prequest_key )
874 {
875 enip_request_key_t *new_request_key;
876 enip_request_val_t *request_val;
877 enip_request_info_t *request_info;
878
879 request_info = NULL;
880 request_val = (enip_request_val_t *)wmem_map_lookup( enip_request_hashtable, prequest_key );
881 if (!pinfo->fd->visited)
882 {
883 if ( prequest_key && prequest_key->requesttype == ENIP_REQUEST_PACKET )
884 {
885 if ( request_val == NULL )
886 {
887 new_request_key = (enip_request_key_t *)wmem_memdup(wmem_file_scope(), prequest_key, sizeof(enip_request_key_t));
888
889 request_val = wmem_new(wmem_file_scope(), enip_request_val_t);
890 request_val->frames = wmem_tree_new(wmem_file_scope());
891
892 wmem_map_insert(enip_request_hashtable, new_request_key, request_val );
893 }
894
895 request_info = wmem_new(wmem_file_scope(), enip_request_info_t);
896 request_info->req_num = pinfo->num;
897 request_info->rep_num = 0;
898 request_info->req_time = pinfo->abs_ts;
899 request_info->cip_info = NULL;
900 wmem_tree_insert32(request_val->frames, pinfo->num, (void *)request_info);
901 }
902 if ( request_val && prequest_key && prequest_key->requesttype == ENIP_RESPONSE_PACKET )
903 {
904 request_info = (enip_request_info_t*)wmem_tree_lookup32_le( request_val->frames, pinfo->num );
905 if ( request_info )
906 {
907 request_info->rep_num = pinfo->num;
908 }
909 }
910 }
911 else
912 {
913 if ( request_val )
914 request_info = (enip_request_info_t *)wmem_tree_lookup32_le( request_val->frames, pinfo->num );
915 }
916
917 if ( tree && request_info )
918 {
919 /* print state tracking in the tree */
920 if ( prequest_key && prequest_key->requesttype == ENIP_REQUEST_PACKET )
921 {
922 /* This is a request */
923 if (request_info->rep_num)
924 {
925 proto_item *it;
926
927 it = proto_tree_add_uint(tree, hf_enip_response_in,
928 NULL, 0, 0, request_info->rep_num);
929 proto_item_set_generated(it);
930 }
931 }
932 else
933 {
934 if ( prequest_key && prequest_key->requesttype == ENIP_RESPONSE_PACKET )
935 {
936 /* This is a reply */
937 if (request_info->req_num)
938 {
939 proto_item *it;
940 nstime_t ns;
941
942 it = proto_tree_add_uint(tree, hf_enip_response_to,
943 NULL, 0, 0, request_info->req_num);
944 proto_item_set_generated(it);
945
946 nstime_delta(&ns, &pinfo->abs_ts, &request_info->req_time);
947 it = proto_tree_add_time(tree, hf_enip_time, NULL, 0, 0, &ns);
948 proto_item_set_generated(it);
949 }
950 }
951 }
952 }
953 return request_info;
954 }
955
956 typedef struct enip_conn_key {
957 cip_connection_triad_t triad;
958 guint32 O2TConnID;
959 guint32 T2OConnID;
960 } enip_conn_key_t;
961
962 typedef struct _enip_conv_info_t {
963 wmem_tree_t *O2TConnIDs;
964 wmem_tree_t *T2OConnIDs;
965 } enip_conv_info_t;
966
967 /*
968 * Conversation filter
969 */
970 static gboolean
enip_io_conv_valid(packet_info * pinfo)971 enip_io_conv_valid(packet_info *pinfo)
972 {
973 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
974
975 if (conn == NULL)
976 return FALSE;
977
978 return (((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 0) ||
979 ((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1));
980 }
981
982 static gchar *
enip_io_conv_filter(packet_info * pinfo)983 enip_io_conv_filter(packet_info *pinfo)
984 {
985 char *buf;
986 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
987
988 if (conn == NULL)
989 return NULL;
990
991 if (conn->close_frame > 0)
992 {
993 buf = g_strdup_printf(
994 "((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
995 "((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
996 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
997 conn->open_req_frame, conn->open_reply_frame, conn->close_frame,
998 conn->O2T.connID, conn->T2O.connID,
999 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1000 }
1001 else
1002 {
1003 /* If Forward Close isn't found, don't limit the (end) frame range */
1004 buf = g_strdup_printf(
1005 "((frame.number == %u) || (frame.number >= %u)) && " /* Frames starting with ForwardOpen */
1006 "((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1007 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1008 conn->open_req_frame, conn->open_reply_frame,
1009 conn->O2T.connID, conn->T2O.connID,
1010 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1011 }
1012
1013 return buf;
1014 }
1015
1016 static gboolean
enip_exp_conv_valid(packet_info * pinfo)1017 enip_exp_conv_valid(packet_info *pinfo)
1018 {
1019 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1020
1021 if (conn == NULL)
1022 return FALSE;
1023
1024 return (((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 2) ||
1025 ((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 3));
1026 }
1027
1028 static gchar *
enip_exp_conv_filter(packet_info * pinfo)1029 enip_exp_conv_filter(packet_info *pinfo)
1030 {
1031 char *buf;
1032 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1033
1034 if (conn == NULL)
1035 return NULL;
1036
1037 if (conn->close_frame > 0)
1038 {
1039 buf = g_strdup_printf(
1040 "((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
1041 "((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1042 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1043 conn->open_req_frame, conn->open_reply_frame, conn->close_frame,
1044 conn->O2T.connID, conn->T2O.connID,
1045 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1046 }
1047 else
1048 {
1049 /* If Forward Close isn't found, don't limit the (end) frame range */
1050 buf = g_strdup_printf(
1051 "((frame.number == %u) || (frame.number >= %u)) && " /* Frames between ForwardOpen and ForwardClose */
1052 "((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1053 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1054 conn->open_req_frame, conn->open_reply_frame,
1055 conn->O2T.connID, conn->T2O.connID,
1056 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1057 }
1058 return buf;
1059 }
1060
cip_connection_conv_valid(packet_info * pinfo)1061 static gboolean cip_connection_conv_valid(packet_info *pinfo)
1062 {
1063 return enip_io_conv_valid(pinfo) || enip_exp_conv_valid(pinfo);
1064 }
1065
cip_connection_conv_filter(packet_info * pinfo)1066 static gchar* cip_connection_conv_filter(packet_info *pinfo)
1067 {
1068 char* buf = NULL;
1069
1070 if (enip_io_conv_valid(pinfo))
1071 {
1072 buf = enip_io_conv_filter(pinfo);
1073 }
1074 else if (enip_exp_conv_valid(pinfo))
1075 {
1076 buf = enip_exp_conv_filter(pinfo);
1077 }
1078
1079 return buf;
1080 }
1081
1082 /*
1083 * Connection management
1084 */
1085
1086 // Key: (triad, connection IDs), Value: cip_conn_info_t
1087 static wmem_map_t *enip_conn_hashtable = NULL;
1088 static guint32 enip_unique_connid;
1089
1090 static gboolean
enip_conn_equal(gconstpointer v,gconstpointer w)1091 enip_conn_equal(gconstpointer v, gconstpointer w)
1092 {
1093 const enip_conn_key_t *v1 = (const enip_conn_key_t *)v;
1094 const enip_conn_key_t *v2 = (const enip_conn_key_t *)w;
1095
1096 if ((v1->triad.ConnSerialNumber == v2->triad.ConnSerialNumber) &&
1097 (v1->triad.VendorID == v2->triad.VendorID) &&
1098 (v1->triad.DeviceSerialNumber == v2->triad.DeviceSerialNumber) &&
1099 ((v1->O2TConnID == 0) || (v2->O2TConnID == 0) || (v1->O2TConnID == v2->O2TConnID)) &&
1100 ((v1->T2OConnID == 0) || (v2->T2OConnID == 0) || (v1->T2OConnID == v2->T2OConnID)))
1101 return TRUE;
1102
1103 return FALSE;
1104 }
1105
1106 static guint
enip_conn_hash(gconstpointer v)1107 enip_conn_hash (gconstpointer v)
1108 {
1109 const enip_conn_key_t *key = (const enip_conn_key_t *)v;
1110 guint val;
1111
1112 val = (guint)( key->triad.ConnSerialNumber + key->triad.VendorID + key->triad.DeviceSerialNumber );
1113
1114 return val;
1115 }
1116
1117 // Create a list of connection IDs and attach it to the conversation.
create_connection_id_list(conversation_t * conversation)1118 static enip_conv_info_t* create_connection_id_list(conversation_t* conversation)
1119 {
1120 enip_conv_info_t* enip_info = wmem_new(wmem_file_scope(), enip_conv_info_t);
1121 enip_info->O2TConnIDs = wmem_tree_new(wmem_file_scope());
1122 enip_info->T2OConnIDs = wmem_tree_new(wmem_file_scope());
1123
1124 conversation_add_proto_data(conversation, proto_enip, enip_info);
1125
1126 return enip_info;
1127 }
1128
1129 static
get_conversation_info_one_direction(packet_info * pinfo,address * src_address,address * dst_address,cip_connID_info_t * connid_info)1130 enip_conv_info_t* get_conversation_info_one_direction(packet_info* pinfo, address* src_address, address* dst_address, cip_connID_info_t* connid_info)
1131 {
1132 /* default some information if not included */
1133 if ((connid_info->port == 0) || (connid_info->type == CONN_TYPE_MULTICAST))
1134 {
1135 connid_info->port = ENIP_IO_PORT;
1136 }
1137
1138 ws_in6_addr ipv6_zero = {0};
1139 if ((connid_info->ipaddress.type == AT_NONE) ||
1140 ((connid_info->ipaddress.type == AT_IPv4) && ((*(const guint32*)connid_info->ipaddress.data)) == 0) ||
1141 ((connid_info->ipaddress.type == AT_IPv6) && (memcmp(connid_info->ipaddress.data, &ipv6_zero, sizeof(ipv6_zero)) == 0)) ||
1142 (connid_info->type != CONN_TYPE_MULTICAST))
1143 {
1144 copy_address_wmem(wmem_file_scope(), &connid_info->ipaddress, dst_address);
1145 }
1146
1147 address dest_address;
1148 if (connid_info->ipaddress.type == AT_IPv6)
1149 {
1150 dest_address.type = AT_IPv6;
1151 dest_address.len = 16;
1152 }
1153 else
1154 {
1155 dest_address.type = AT_IPv4;
1156 dest_address.len = 4;
1157 }
1158 dest_address.data = connid_info->ipaddress.data;
1159
1160 // Similar logic to find_or_create_conversation(), but since I/O traffic
1161 // is on UDP, the pinfo parameter doesn't have the correct information.
1162 conversation_t* conversation = find_conversation(pinfo->num, src_address, &dest_address,
1163 ENDPOINT_UDP, connid_info->port, 0, NO_PORT_B);
1164 if (conversation == NULL)
1165 {
1166 conversation = conversation_new(pinfo->num, src_address, &dest_address,
1167 ENDPOINT_UDP, connid_info->port, 0, NO_PORT2);
1168 }
1169
1170 enip_conv_info_t* enip_info = (enip_conv_info_t*)conversation_get_proto_data(conversation, proto_enip);
1171 if (enip_info == NULL)
1172 {
1173 enip_info = create_connection_id_list(conversation);
1174 }
1175
1176 return enip_info;
1177 }
1178
1179 // connInfo - Connection Information that is known so far (from the Forward Open Request).
enip_open_cip_connection(packet_info * pinfo,cip_conn_info_t * connInfo)1180 static void enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo)
1181 {
1182 if (pinfo->fd->visited)
1183 return;
1184
1185 // Don't create connections for Null Forward Opens.
1186 if (connInfo->T2O.type == CONN_TYPE_NULL && connInfo->O2T.type == CONN_TYPE_NULL)
1187 {
1188 return;
1189 }
1190
1191 enip_conn_key_t* conn_key = wmem_new(wmem_file_scope(), enip_conn_key_t);
1192 conn_key->triad = connInfo->triad;
1193 conn_key->O2TConnID = connInfo->O2T.connID;
1194 conn_key->T2OConnID = connInfo->T2O.connID;
1195
1196 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, conn_key );
1197 if ( conn_val == NULL )
1198 {
1199 conn_val = wmem_new0(wmem_file_scope(), cip_conn_info_t);
1200
1201 // Copy initial connection data from the Forward Open Request.
1202 *conn_val = *connInfo;
1203
1204 // These values are not copies from the Forward Open Request. Initialize these separately.
1205 conn_val->open_reply_frame = pinfo->num;
1206 conn_val->connid = enip_unique_connid++;
1207
1208 wmem_map_insert(enip_conn_hashtable, conn_key, conn_val );
1209
1210 /* I/O connection */
1211 if (((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 0) ||
1212 ((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1))
1213 {
1214 /* check for O->T conversation */
1215 enip_conv_info_t* enip_info = get_conversation_info_one_direction(pinfo, &pinfo->dst, &pinfo->src, &(connInfo->O2T));
1216 wmem_tree_insert32(enip_info->O2TConnIDs, connInfo->O2T.connID, (void*)conn_val);
1217
1218 /* Check if separate T->O conversation is necessary. If either side is multicast
1219 or ports aren't equal, a separate conversation must be generated */
1220 enip_info = get_conversation_info_one_direction(pinfo, &pinfo->src, &pinfo->dst, &(connInfo->T2O));
1221 wmem_tree_insert32(enip_info->T2OConnIDs, connInfo->T2O.connID, (void *)conn_val);
1222 }
1223 else
1224 {
1225 /* explicit message connection */
1226 conversation_t* conversation = find_or_create_conversation(pinfo);
1227
1228 enip_conv_info_t* enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip);
1229 if (!enip_info)
1230 {
1231 enip_info = create_connection_id_list(conversation);
1232 }
1233 wmem_tree_insert32(enip_info->O2TConnIDs, connInfo->O2T.connID, (void *)conn_val);
1234 wmem_tree_insert32(enip_info->T2OConnIDs, connInfo->T2O.connID, (void *)conn_val);
1235 }
1236 }
1237
1238 /* Save the connection info for the conversation filter */
1239 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1240 }
1241
1242 void
enip_close_cip_connection(packet_info * pinfo,const cip_connection_triad_t * triad)1243 enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* triad)
1244 {
1245 if (pinfo->fd->visited)
1246 return;
1247
1248 enip_conn_key_t conn_key;
1249 conn_key.triad = *triad;
1250 conn_key.O2TConnID = 0;
1251 conn_key.T2OConnID = 0;
1252
1253 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, &conn_key );
1254 if ( conn_val )
1255 {
1256 conn_val->close_frame = pinfo->num;
1257
1258 /* Save the connection info for the conversation filter */
1259 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1260 }
1261 }
1262
1263 /* Save the connection info for the conversation filter */
enip_mark_connection_triad(packet_info * pinfo,const cip_connection_triad_t * triad)1264 void enip_mark_connection_triad(packet_info *pinfo, const cip_connection_triad_t* triad)
1265 {
1266 enip_conn_key_t conn_key;
1267 conn_key.triad = *triad;
1268 conn_key.O2TConnID = 0;
1269 conn_key.T2OConnID = 0;
1270
1271 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, &conn_key );
1272 if ( conn_val )
1273 {
1274 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1275 }
1276 }
1277
1278 static cip_conn_info_t*
enip_get_explicit_connid(packet_info * pinfo,enip_request_key_t * prequest_key,guint32 connid)1279 enip_get_explicit_connid(packet_info *pinfo, enip_request_key_t *prequest_key, guint32 connid)
1280 {
1281 conversation_t *conversation;
1282 enip_conv_info_t *enip_info;
1283 enum enip_packet_type requesttype = ENIP_REQUEST_PACKET;
1284
1285 if (prequest_key != NULL)
1286 {
1287 /* Sanity check */
1288 if ((prequest_key->requesttype != ENIP_REQUEST_PACKET) && (prequest_key->requesttype != ENIP_RESPONSE_PACKET ))
1289 return NULL;
1290
1291 requesttype = prequest_key->requesttype;
1292 }
1293
1294 /*
1295 * Do we have a conversation for this connection?
1296 */
1297 conversation = find_conversation_pinfo(pinfo, 0);
1298 if (conversation == NULL)
1299 return NULL;
1300
1301 /*
1302 * Do we already have a state structure for this conv
1303 */
1304 enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip);
1305 if (!enip_info)
1306 return NULL;
1307
1308 cip_conn_info_t* conn_val = NULL;
1309 switch (requesttype )
1310 {
1311 case ENIP_REQUEST_PACKET:
1312 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->O2TConnIDs, connid );
1313 if ( conn_val == NULL )
1314 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid );
1315 break;
1316
1317 case ENIP_RESPONSE_PACKET:
1318 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid );
1319 if ( conn_val == NULL )
1320 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->O2TConnIDs, connid );
1321 break;
1322 case ENIP_CANNOT_CLASSIFY:
1323 /* ignore */
1324 break;
1325 }
1326
1327 if ((conn_val == NULL ) || (conn_val->open_reply_frame > pinfo->num))
1328 return NULL;
1329
1330 return conn_val;
1331 }
1332
1333 static cip_conn_info_t*
enip_get_io_connid(packet_info * pinfo,guint32 connid,enum enip_connid_type * pconnid_type)1334 enip_get_io_connid(packet_info *pinfo, guint32 connid, enum enip_connid_type* pconnid_type)
1335 {
1336 conversation_t *conversation;
1337 enip_conv_info_t *enip_info;
1338 cip_conn_info_t *conn_val = NULL;
1339
1340 *pconnid_type = ECIDT_UNKNOWN;
1341
1342 /*
1343 * Do we have a conversation for this connection?
1344 */
1345 conversation = find_conversation(pinfo->num,
1346 &pinfo->src, &pinfo->dst,
1347 conversation_pt_to_endpoint_type(pinfo->ptype),
1348 pinfo->destport, 0, NO_PORT_B);
1349
1350 if (conversation == NULL)
1351 return NULL;
1352
1353 /*
1354 * Do we already have a state structure for this conv
1355 */
1356 if ((enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip)) == NULL)
1357 return NULL;
1358
1359 if (enip_info->O2TConnIDs != NULL)
1360 {
1361 conn_val = (cip_conn_info_t*)wmem_tree_lookup32(enip_info->O2TConnIDs, connid);
1362 if (conn_val)
1363 {
1364 *pconnid_type = ECIDT_O2T;
1365 }
1366 }
1367
1368 if ( conn_val == NULL )
1369 {
1370 if (enip_info->T2OConnIDs != NULL)
1371 {
1372 if ((conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid)) != NULL)
1373 *pconnid_type = ECIDT_T2O;
1374 }
1375 }
1376
1377 if ((conn_val == NULL) || ( conn_val->open_reply_frame > pinfo->num ))
1378 return NULL;
1379
1380 return conn_val;
1381 }
1382
1383 static int
dissect_tcpip_status(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1384 dissect_tcpip_status(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1385 int offset, int total_len)
1386
1387 {
1388 static int * const status[] = {
1389 &hf_tcpip_status_interface_config,
1390 &hf_tcpip_status_mcast_pending,
1391 &hf_tcpip_status_interface_config_pending,
1392 &hf_tcpip_status_acd,
1393 &hf_tcpip_acd_fault,
1394 &hf_tcpip_status_iana_port_admin_change,
1395 &hf_tcpip_status_iana_protocol_admin_change,
1396 &hf_tcpip_status_reserved,
1397 NULL
1398 };
1399
1400 if (total_len < 4)
1401 {
1402 expert_add_info(pinfo, item, &ei_mal_tcpip_status);
1403 return total_len;
1404 }
1405
1406 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_status, ett_tcpip_status, status, ENC_LITTLE_ENDIAN);
1407 return 4;
1408 }
1409
1410 static int
dissect_tcpip_config_cap(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1411 dissect_tcpip_config_cap(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1412 int offset, int total_len)
1413
1414 {
1415 static int * const capabilities[] = {
1416 &hf_tcpip_config_cap_bootp,
1417 &hf_tcpip_config_cap_dns,
1418 &hf_tcpip_config_cap_dhcp,
1419 &hf_tcpip_config_cap_dhcp_dns_update,
1420 &hf_tcpip_config_cap_config_settable,
1421 &hf_tcpip_config_cap_hardware_config,
1422 &hf_tcpip_config_cap_interface_reset,
1423 &hf_tcpip_config_cap_acd,
1424 &hf_tcpip_config_cap_reserved,
1425 NULL
1426 };
1427
1428 if (total_len < 4)
1429 {
1430 expert_add_info(pinfo, item, &ei_mal_tcpip_config_cap);
1431 return total_len;
1432 }
1433
1434 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_config_cap, ett_tcpip_config_cap, capabilities, ENC_LITTLE_ENDIAN);
1435 return 4;
1436 }
1437
1438 static int
dissect_tcpip_config_control(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1439 dissect_tcpip_config_control(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1440 int offset, int total_len)
1441
1442 {
1443 static int * const control_bits[] = {
1444 &hf_tcpip_config_control_config,
1445 &hf_tcpip_config_control_dns,
1446 &hf_tcpip_config_control_reserved,
1447 NULL
1448 };
1449
1450 if (total_len < 4)
1451 {
1452 expert_add_info(pinfo, item, &ei_mal_tcpip_config_control);
1453 return total_len;
1454 }
1455
1456 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_config_control, ett_tcpip_config_control, control_bits, ENC_LITTLE_ENDIAN);
1457 return 4;
1458 }
1459
1460 static int
dissect_tcpip_physical_link(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1461 dissect_tcpip_physical_link(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1462 int offset, int total_len)
1463
1464 {
1465 return dissect_padded_epath_len_uint(pinfo, tree, item, tvb, offset, total_len);
1466 }
1467
1468 static int
dissect_tcpip_interface_config(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1469 dissect_tcpip_interface_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1470 int offset, int total_len)
1471
1472 {
1473 guint16 domain_length;
1474
1475 if (total_len < 22)
1476 {
1477 expert_add_info(pinfo, item, &ei_mal_tcpip_interface_config);
1478 return total_len;
1479 }
1480
1481 proto_tree_add_item(tree, hf_tcpip_ic_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1482 proto_tree_add_item(tree, hf_tcpip_ic_subnet_mask, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1483 proto_tree_add_item(tree, hf_tcpip_ic_gateway, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1484 proto_tree_add_item(tree, hf_tcpip_ic_name_server, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1485 proto_tree_add_item(tree, hf_tcpip_ic_name_server2, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1486
1487 domain_length = tvb_get_letohs( tvb, offset+20);
1488 proto_tree_add_item(tree, hf_tcpip_ic_domain_name, tvb, offset+22, domain_length, ENC_ASCII|ENC_NA);
1489
1490 /* Add padding. */
1491 domain_length += domain_length % 2;
1492
1493 return (22+domain_length);
1494 }
1495
dissect_tcpip_hostname(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len _U_)1496 static int dissect_tcpip_hostname(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1497 int offset, int total_len _U_)
1498 {
1499 int parsed_len;
1500 parsed_len = dissect_cip_string_type(pinfo, tree, item, tvb, offset, hf_tcpip_hostname, CIP_STRING_TYPE);
1501
1502 /* Add padding. */
1503 parsed_len += parsed_len % 2;
1504
1505 return parsed_len;
1506 }
1507
dissect_tcpip_snn(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1508 static int dissect_tcpip_snn(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1509 int offset, int total_len)
1510 {
1511 if (total_len < 6)
1512 {
1513 expert_add_info(pinfo, item, &ei_mal_tcpip_snn);
1514 return total_len;
1515 }
1516
1517 dissect_cipsafety_snn(tree, tvb, pinfo, offset, hf_tcpip_snn_timestamp, hf_tcpip_snn_date, hf_tcpip_snn_time);
1518 return 6;
1519 }
1520
1521 static int
dissect_tcpip_mcast_config(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1522 dissect_tcpip_mcast_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1523 int offset, int total_len)
1524
1525 {
1526 if (total_len < 8)
1527 {
1528 expert_add_info(pinfo, item, &ei_mal_tcpip_mcast_config);
1529 return total_len;
1530 }
1531
1532 proto_tree_add_item(tree, hf_tcpip_mcast_alloc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1533 proto_tree_add_item(tree, hf_tcpip_mcast_reserved, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1534 proto_tree_add_item(tree, hf_tcpip_mcast_num_mcast, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1535 proto_tree_add_item(tree, hf_tcpip_mcast_addr_start, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1536 return 8;
1537 }
1538
1539 static int
dissect_tcpip_last_conflict(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1540 dissect_tcpip_last_conflict(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1541 int offset, int total_len)
1542
1543 {
1544 tvbuff_t *next_tvb;
1545 gboolean save_info;
1546
1547 if (total_len < 35)
1548 {
1549 expert_add_info(pinfo, item, &ei_mal_tcpip_last_conflict);
1550 return total_len;
1551 }
1552
1553 proto_tree_add_item(tree, hf_tcpip_lcd_acd_activity, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1554 proto_tree_add_item(tree, hf_tcpip_lcd_remote_mac, tvb, offset+1, 6, ENC_NA);
1555
1556 if ( tvb_get_guint8(tvb, offset) == 0 )
1557 proto_tree_add_item(tree, hf_tcpip_lcd_arp_pdu, tvb, offset+7, 28, ENC_NA);
1558 else
1559 {
1560 /* Dissect ARP PDU, but don't have it change column info */
1561 save_info = col_get_writable(pinfo->cinfo, -1);
1562 col_set_writable(pinfo->cinfo, -1, FALSE);
1563
1564 next_tvb = tvb_new_subset_length(tvb, offset+7, 28);
1565 call_dissector(arp_handle, next_tvb, pinfo, tree);
1566
1567 col_set_writable(pinfo->cinfo, -1, save_info);
1568 }
1569
1570 return 35;
1571 }
1572
1573 static int
dissect_elink_interface_flags(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1574 dissect_elink_interface_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1575 int offset, int total_len)
1576
1577 {
1578 static int * const flags[] = {
1579 &hf_elink_iflags_link_status,
1580 &hf_elink_iflags_duplex,
1581 &hf_elink_iflags_neg_status,
1582 &hf_elink_iflags_manual_reset,
1583 &hf_elink_iflags_local_hw_fault,
1584 &hf_elink_iflags_reserved,
1585 NULL
1586 };
1587
1588 if (total_len < 4)
1589 {
1590 expert_add_info(pinfo, item, &ei_mal_elink_interface_flags);
1591 return total_len;
1592 }
1593
1594 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_interface_flags, ett_elink_interface_flags, flags, ENC_LITTLE_ENDIAN);
1595 return 4;
1596 }
1597
1598 static int
dissect_elink_physical_address(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1599 dissect_elink_physical_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1600 int offset, int total_len)
1601
1602 {
1603 if (total_len < 6)
1604 {
1605 expert_add_info(pinfo, item, &ei_mal_elink_physical_address);
1606 return total_len;
1607 }
1608
1609 proto_tree_add_item(tree, hf_elink_physical_address, tvb, offset, 6, ENC_NA);
1610 return 6;
1611 }
1612
1613
1614 static int
dissect_elink_interface_counters(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1615 dissect_elink_interface_counters(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1616 int offset, int total_len)
1617
1618 {
1619 if (total_len < 44)
1620 {
1621 expert_add_info(pinfo, item, &ei_mal_elink_interface_counters);
1622 return total_len;
1623 }
1624
1625 proto_tree_add_item(tree, hf_elink_icount_in_octets, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1626 proto_tree_add_item(tree, hf_elink_icount_in_ucast, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1627 proto_tree_add_item(tree, hf_elink_icount_in_nucast, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1628 proto_tree_add_item(tree, hf_elink_icount_in_discards, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1629 proto_tree_add_item(tree, hf_elink_icount_in_errors, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1630 proto_tree_add_item(tree, hf_elink_icount_in_unknown_protos, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
1631 proto_tree_add_item(tree, hf_elink_icount_out_octets, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
1632 proto_tree_add_item(tree, hf_elink_icount_out_ucast, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
1633 proto_tree_add_item(tree, hf_elink_icount_out_nucast, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
1634 proto_tree_add_item(tree, hf_elink_icount_out_discards, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
1635 proto_tree_add_item(tree, hf_elink_icount_out_errors, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
1636 return 44;
1637 }
1638
1639 static int
dissect_elink_media_counters(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1640 dissect_elink_media_counters(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1641 int offset, int total_len)
1642
1643 {
1644 if (total_len < 48)
1645 {
1646 expert_add_info(pinfo, item, &ei_mal_elink_media_counters);
1647 return total_len;
1648 }
1649
1650 proto_tree_add_item(tree, hf_elink_mcount_alignment_errors, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1651 proto_tree_add_item(tree, hf_elink_mcount_fcs_errors, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1652 proto_tree_add_item(tree, hf_elink_mcount_single_collisions, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1653 proto_tree_add_item(tree, hf_elink_mcount_multiple_collisions, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1654 proto_tree_add_item(tree, hf_elink_mcount_sqe_test_errors, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1655 proto_tree_add_item(tree, hf_elink_mcount_deferred_transmission, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
1656 proto_tree_add_item(tree, hf_elink_mcount_late_collisions, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
1657 proto_tree_add_item(tree, hf_elink_mcount_excessive_collisions, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
1658 proto_tree_add_item(tree, hf_elink_mcount_mac_transmit_errors, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
1659 proto_tree_add_item(tree, hf_elink_mcount_carrier_sense_errors, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
1660 proto_tree_add_item(tree, hf_elink_mcount_frame_too_long, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
1661 proto_tree_add_item(tree, hf_elink_mcount_mac_receive_errors, tvb, offset+44, 4, ENC_LITTLE_ENDIAN);
1662 return 48;
1663 }
1664
1665 static int
dissect_elink_interface_capability(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)1666 dissect_elink_interface_capability(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1667 int offset, int total_len _U_)
1668 {
1669 static int * const bits[] = {
1670 &hf_elink_icapability_capability_bits_manual,
1671 &hf_elink_icapability_capability_bits_auto_neg,
1672 &hf_elink_icapability_capability_bits_auto_mdix,
1673 &hf_elink_icapability_capability_bits_manual_speed,
1674 NULL
1675 };
1676
1677 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_icapability_capability_bits, ett_elink_icapability_bits, bits, ENC_LITTLE_ENDIAN);
1678 offset += 4;
1679
1680 guint32 array_count;
1681 proto_tree_add_item_ret_uint(tree, hf_elink_icapability_capability_speed_duplex_array_count, tvb, offset, 1, ENC_NA, &array_count);
1682 offset++;
1683
1684 for (guint32 i = 0; i < array_count; i++)
1685 {
1686 proto_tree_add_item(tree, hf_elink_icapability_capability_speed, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1687 offset += 2;
1688
1689 proto_tree_add_item(tree, hf_elink_icapability_capability_duplex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1690 offset++;
1691 }
1692
1693 return 4 + 1 + array_count * 3;
1694 }
1695
1696 static int
dissect_elink_hc_interface_counters(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)1697 dissect_elink_hc_interface_counters(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1698 int offset, int total_len _U_)
1699 {
1700 proto_tree_add_item(tree, hf_elink_hc_icount_in_octets, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1701 proto_tree_add_item(tree, hf_elink_hc_icount_in_ucast, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
1702 proto_tree_add_item(tree, hf_elink_hc_icount_in_mcast, tvb, offset + 16, 8, ENC_LITTLE_ENDIAN);
1703 proto_tree_add_item(tree, hf_elink_hc_icount_in_broadcast, tvb, offset + 24, 8, ENC_LITTLE_ENDIAN);
1704 proto_tree_add_item(tree, hf_elink_hc_icount_out_octets, tvb, offset + 32, 8, ENC_LITTLE_ENDIAN);
1705 proto_tree_add_item(tree, hf_elink_hc_icount_out_ucast, tvb, offset + 40, 8, ENC_LITTLE_ENDIAN);
1706 proto_tree_add_item(tree, hf_elink_hc_icount_out_mcast, tvb, offset + 48, 8, ENC_LITTLE_ENDIAN);
1707 proto_tree_add_item(tree, hf_elink_hc_icount_out_broadcast, tvb, offset + 56, 8, ENC_LITTLE_ENDIAN);
1708
1709 return 8 * 8;
1710 }
1711
1712 static int
dissect_elink_hc_media_counters(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)1713 dissect_elink_hc_media_counters(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1714 int offset, int total_len _U_)
1715 {
1716 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_align_errors, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1717 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_fcs_errors, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
1718 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_internal_mac_transmit_errors, tvb, offset + 16, 8, ENC_LITTLE_ENDIAN);
1719 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_frame_too_long, tvb, offset + 24, 8, ENC_LITTLE_ENDIAN);
1720 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_internal_mac_receive_errors, tvb, offset + 32, 8, ENC_LITTLE_ENDIAN);
1721 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_symbol_errors, tvb, offset + 40, 8, ENC_LITTLE_ENDIAN);
1722
1723 return 8 * 6;
1724 }
1725
1726 static int
dissect_elink_interface_control(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1727 dissect_elink_interface_control(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1728 int offset, int total_len)
1729
1730 {
1731 static int * const control_bits[] = {
1732 &hf_elink_icontrol_control_bits_auto_neg,
1733 &hf_elink_icontrol_control_bits_forced_duplex,
1734 &hf_elink_icontrol_control_bits_reserved,
1735 NULL
1736 };
1737
1738 if (total_len < 4)
1739 {
1740 expert_add_info(pinfo, item, &ei_mal_elink_interface_control);
1741 return total_len;
1742 }
1743
1744 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_icontrol_control_bits, ett_elink_icontrol_bits, control_bits, ENC_LITTLE_ENDIAN);
1745 proto_tree_add_item(tree, hf_elink_icontrol_forced_speed, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1746 return 4;
1747 }
1748
1749 static int
dissect_dlr_ring_supervisor_config(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1750 dissect_dlr_ring_supervisor_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1751 int offset, int total_len)
1752
1753 {
1754 if (total_len < 12)
1755 {
1756 expert_add_info(pinfo, item, &ei_mal_dlr_ring_supervisor_config);
1757 return total_len;
1758 }
1759
1760 proto_tree_add_item(tree, hf_dlr_rsc_ring_supervisor_enable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1761 proto_tree_add_item(tree, hf_dlr_rsc_ring_supervisor_precedence, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1762 proto_tree_add_item(tree, hf_dlr_rsc_beacon_interval, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
1763 proto_tree_add_item(tree, hf_dlr_rsc_beacon_timeout, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
1764 proto_tree_add_item(tree, hf_dlr_rsc_dlr_vlan_id, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
1765 return 12;
1766 }
1767
1768 static int
dissect_dlr_last_active_node_on_port_1(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1769 dissect_dlr_last_active_node_on_port_1(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1770 int offset, int total_len)
1771
1772 {
1773 if (total_len < 10)
1774 {
1775 expert_add_info(pinfo, item, &ei_mal_dlr_last_active_node_on_port_1);
1776 return total_len;
1777 }
1778
1779 proto_tree_add_item(tree, hf_dlr_lanp1_dev_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1780 proto_tree_add_item(tree, hf_dlr_lanp1_dev_physical_address, tvb, offset+4, 6, ENC_NA);
1781 return 10;
1782 }
1783
1784 static int
dissect_dlr_last_active_node_on_port_2(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1785 dissect_dlr_last_active_node_on_port_2(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1786 int offset, int total_len)
1787
1788 {
1789 if (total_len < 10)
1790 {
1791 expert_add_info(pinfo, item, &ei_mal_dlr_last_active_node_on_port_2);
1792 return total_len;
1793 }
1794
1795 proto_tree_add_item(tree, hf_dlr_lanp2_dev_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1796 proto_tree_add_item(tree, hf_dlr_lanp2_dev_physical_address, tvb, offset+4, 6, ENC_NA);
1797 return 10;
1798 }
1799
1800 static int
dissect_dlr_ring_protocol_participants_list(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1801 dissect_dlr_ring_protocol_participants_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1802 int offset, int total_len)
1803
1804 {
1805 int pos;
1806
1807 if (total_len % 10)
1808 {
1809 expert_add_info(pinfo, item, &ei_mal_dlr_ring_protocol_participants_list);
1810 return total_len;
1811 }
1812
1813 pos = 0;
1814 while ( pos < total_len)
1815 {
1816 proto_tree_add_item(tree, hf_dlr_rppl_dev_ip_addr, tvb, offset+pos, 4, ENC_LITTLE_ENDIAN);
1817 proto_tree_add_item(tree, hf_dlr_rppl_dev_physical_address, tvb, offset+pos+4, 6, ENC_NA);
1818 pos+=10;
1819 }
1820 return total_len;
1821 }
1822
1823 static int
dissect_dlr_active_supervisor_address(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1824 dissect_dlr_active_supervisor_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1825 int offset, int total_len)
1826
1827 {
1828 if (total_len < 10)
1829 {
1830 expert_add_info(pinfo, item, &ei_mal_dlr_active_supervisor_address);
1831 return total_len;
1832 }
1833
1834 proto_tree_add_item(tree, hf_dlr_asa_supervisor_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1835 proto_tree_add_item(tree, hf_dlr_asa_supervisor_physical_address, tvb, offset+4, 6, ENC_NA);
1836 return 10;
1837 }
1838
1839 static int
dissect_dlr_capability_flags(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1840 dissect_dlr_capability_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1841 int offset, int total_len)
1842
1843 {
1844 static int * const capabilities[] = {
1845 &hf_dlr_capflags_announce_base_node,
1846 &hf_dlr_capflags_beacon_base_node,
1847 &hf_dlr_capflags_reserved1,
1848 &hf_dlr_capflags_supervisor_capable,
1849 &hf_dlr_capflags_redundant_gateway_capable,
1850 &hf_dlr_capflags_flush_frame_capable,
1851 &hf_dlr_capflags_reserved2,
1852 NULL
1853 };
1854
1855 if (total_len < 4)
1856 {
1857 expert_add_info(pinfo, item, &ei_mal_dlr_capability_flags);
1858 return total_len;
1859 }
1860
1861 proto_tree_add_bitmask(tree, tvb, offset, hf_dlr_capability_flags, ett_dlr_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
1862 return 4;
1863 }
1864
1865 static int
dissect_dlr_redundant_gateway_config(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1866 dissect_dlr_redundant_gateway_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1867 int offset, int total_len)
1868
1869 {
1870 if (total_len < 11)
1871 {
1872 expert_add_info(pinfo, item, &ei_mal_dlr_redundant_gateway_config);
1873 return total_len;
1874 }
1875
1876 proto_tree_add_item(tree, hf_dlr_rgc_red_gateway_enable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1877 proto_tree_add_item(tree, hf_dlr_rgc_gateway_precedence, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1878 proto_tree_add_item(tree, hf_dlr_rgc_advertise_interval, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
1879 proto_tree_add_item(tree, hf_dlr_rgc_advertise_timeout, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
1880 proto_tree_add_item(tree, hf_dlr_rgc_learning_update_enable, tvb, offset+10, 1, ENC_LITTLE_ENDIAN);
1881 return 11;
1882 }
1883
1884 static int
dissect_dlr_active_gateway_address(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1885 dissect_dlr_active_gateway_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1886 int offset, int total_len)
1887
1888 {
1889 if (total_len < 10)
1890 {
1891 expert_add_info(pinfo, item, &ei_mal_dlr_active_gateway_address);
1892 return total_len;
1893 }
1894
1895 proto_tree_add_item(tree, hf_dlr_aga_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1896 proto_tree_add_item(tree, hf_dlr_aga_physical_address, tvb, offset+4, 6, ENC_NA);
1897 return 10;
1898 }
1899
dissect_cip_security_profiles(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)1900 static int dissect_cip_security_profiles(packet_info* pinfo _U_, proto_tree* tree, proto_item* item _U_, tvbuff_t* tvb,
1901 int offset, int total_len _U_)
1902 {
1903 static int* const security_profiles[] = {
1904 &hf_enip_security_profiles_eip_integrity,
1905 &hf_enip_security_profiles_eip_confidentiality,
1906 &hf_enip_security_profiles_cip_authorization,
1907 &hf_enip_security_profiles_cip_user_authentication,
1908 &hf_enip_security_profiles_resource_constrained,
1909 &hf_enip_security_profiles_reserved,
1910 NULL
1911 };
1912
1913 proto_tree_add_bitmask(tree, tvb, offset, hf_enip_security_profiles, ett_security_profiles, security_profiles, ENC_LITTLE_ENDIAN);
1914
1915 return 2;
1916 }
1917
1918 static int
dissect_eip_security_cap(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1919 dissect_eip_security_cap(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1920 int offset, int total_len)
1921
1922 {
1923 static int * const capabilities[] = {
1924 &hf_eip_security_capflags_secure_renegotiation,
1925 &hf_eip_security_capflags_reserved,
1926 NULL
1927 };
1928
1929 if (total_len < 4)
1930 {
1931 expert_add_info(pinfo, item, &ei_mal_eip_security_capability_flags);
1932 return total_len;
1933 }
1934
1935 proto_tree_add_bitmask(tree, tvb, offset, hf_eip_security_capability_flags, ett_eip_security_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
1936 return 4;
1937 }
1938
1939 static int
dissect_eip_security_avail_cipher_suites(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1940 dissect_eip_security_avail_cipher_suites(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1941 int offset, int total_len)
1942
1943 {
1944 guint32 i, num_suites;
1945
1946 if (total_len < 1)
1947 {
1948 expert_add_info(pinfo, item, &ei_mal_eip_security_avail_cipher_suites);
1949 return total_len;
1950 }
1951
1952 proto_tree_add_item_ret_uint(tree, hf_eip_security_num_avail_cipher_suites, tvb, offset, 1, ENC_NA, &num_suites);
1953 offset++;
1954
1955 for (i = 0; i < num_suites; i++)
1956 {
1957 proto_tree_add_item(tree, hf_eip_security_avail_cipher_suite, tvb, offset, 2, ENC_BIG_ENDIAN);
1958 offset += 2;
1959 }
1960
1961 return ((num_suites*2)+1);
1962 }
1963
1964 static int
dissect_eip_security_allow_cipher_suites(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1965 dissect_eip_security_allow_cipher_suites(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1966 int offset, int total_len)
1967
1968 {
1969 guint32 i, num_suites;
1970
1971 if (total_len < 1)
1972 {
1973 expert_add_info(pinfo, item, &ei_mal_eip_security_allow_cipher_suites);
1974 return total_len;
1975 }
1976
1977 proto_tree_add_item_ret_uint(tree, hf_eip_security_num_allow_cipher_suites, tvb, offset, 1, ENC_NA, &num_suites);
1978 offset++;
1979
1980 for (i = 0; i < num_suites; i++)
1981 {
1982 proto_tree_add_item(tree, hf_eip_security_allow_cipher_suite, tvb, offset, 2, ENC_BIG_ENDIAN);
1983 offset += 2;
1984 }
1985
1986 return ((num_suites*2)+1);
1987 }
1988
1989 static int
dissect_eip_security_preshared_keys(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)1990 dissect_eip_security_preshared_keys(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1991 int offset, int total_len)
1992
1993 {
1994 guint32 i, num, id_size, psk_size;
1995 proto_item* ti;
1996 proto_tree* psk_tree;
1997 int start_offset = offset;
1998
1999 if (total_len < 1)
2000 {
2001 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2002 return total_len;
2003 }
2004
2005 ti = proto_tree_add_item_ret_uint(tree, hf_eip_security_num_psk, tvb, offset, 1, ENC_NA, &num);
2006 psk_tree = proto_item_add_subtree(ti, ett_eip_security_psk);
2007 offset++;
2008
2009 for (i = 0; i < num; i++)
2010 {
2011 proto_tree_add_item_ret_uint(psk_tree, hf_eip_security_psk_identity_size, tvb, offset, 1, ENC_NA, &id_size);
2012 if (total_len < (int)(id_size+2))
2013 {
2014 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2015 return total_len;
2016 }
2017 offset++;
2018 proto_tree_add_item(psk_tree, hf_eip_security_psk_identity, tvb, offset, id_size, ENC_NA);
2019 offset += id_size;
2020
2021 proto_tree_add_item_ret_uint(psk_tree, hf_eip_security_psk_size, tvb, offset, 1, ENC_NA, &psk_size);
2022 offset++;
2023 if (total_len < (int)(id_size+psk_size+2))
2024 {
2025 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2026 return total_len;
2027 }
2028 proto_tree_add_item(psk_tree, hf_eip_security_psk, tvb, offset, psk_size, ENC_NA);
2029 offset += psk_size;
2030 }
2031 proto_item_set_len(ti, offset-start_offset);
2032 return offset-start_offset;
2033 }
2034
2035 static int
dissect_eip_security_active_certs(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2036 dissect_eip_security_active_certs(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2037 int offset, int total_len)
2038
2039 {
2040 guint32 i, num, path_size;
2041 proto_item *ti;
2042 proto_tree* cert_tree;
2043 int start_offset = offset;
2044
2045 if (total_len < 1)
2046 {
2047 expert_add_info(pinfo, item, &ei_mal_eip_security_active_certs);
2048 return total_len;
2049 }
2050
2051 ti = proto_tree_add_item_ret_uint(tree, hf_eip_security_num_active_certs, tvb, offset, 1, ENC_NA, &num);
2052 cert_tree = proto_item_add_subtree(ti, ett_eip_security_active_certs);
2053 offset++;
2054
2055 for (i = 0; i < num; i++)
2056 {
2057 path_size = dissect_padded_epath_len_usint(pinfo, cert_tree, ti, tvb, offset, total_len);
2058 offset += path_size;
2059 }
2060 proto_item_set_len(ti, offset-start_offset);
2061 return offset-start_offset;
2062 }
2063
2064 static int
dissect_eip_security_trusted_auths(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2065 dissect_eip_security_trusted_auths(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2066 int offset, int total_len)
2067
2068 {
2069 guint32 i, num, path_size;
2070 proto_item *ti;
2071 proto_tree* cert_tree;
2072 int start_offset = offset;
2073
2074 if (total_len < 1)
2075 {
2076 expert_add_info(pinfo, item, &ei_mal_eip_security_trusted_auths);
2077 return total_len;
2078 }
2079
2080 ti = proto_tree_add_item_ret_uint(tree, hf_eip_security_num_trusted_auths, tvb, offset, 1, ENC_NA, &num);
2081 cert_tree = proto_item_add_subtree(ti, ett_eip_security_trusted_auths);
2082 offset++;
2083
2084 for (i = 0; i < num; i++)
2085 {
2086 path_size = dissect_padded_epath_len_usint(pinfo, cert_tree, ti, tvb, offset, total_len);
2087 offset += path_size;
2088 }
2089 proto_item_set_len(ti, offset-start_offset);
2090 return offset-start_offset;
2091 }
2092
2093 static int
dissect_eip_security_cert_revocation_list(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2094 dissect_eip_security_cert_revocation_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2095 int offset, int total_len)
2096 {
2097 return dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset, total_len);
2098 }
2099
2100 static int
dissect_eip_cert_cap_flags(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2101 dissect_eip_cert_cap_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2102 int offset, int total_len)
2103 {
2104 static int * const capabilities[] = {
2105 &hf_eip_cert_capflags_push,
2106 &hf_eip_cert_capflags_reserved,
2107 NULL
2108 };
2109
2110 if (total_len < 4)
2111 {
2112 expert_add_info(pinfo, item, &ei_mal_eip_cert_capability_flags);
2113 return total_len;
2114 }
2115
2116 proto_tree_add_bitmask(tree, tvb, offset, hf_eip_cert_capability_flags, ett_eip_cert_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
2117 return 4;
2118 }
2119
2120 static int
dissect_eip_cert_cert_list(packet_info * pinfo,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len)2121 dissect_eip_cert_cert_list(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
2122 int offset, int total_len)
2123 {
2124 guint32 i, num, path_size;
2125 proto_item *ti;
2126 proto_tree* cert_tree;
2127 int start_offset = offset;
2128
2129 ti = proto_tree_add_item_ret_uint(tree, hf_eip_cert_num_certs, tvb, offset, 1, ENC_NA, &num);
2130 cert_tree = proto_item_add_subtree(ti, ett_eip_cert_num_certs);
2131 offset++;
2132
2133 for (i = 0; i < num; i++)
2134 {
2135 path_size = tvb_get_guint8( tvb, offset );
2136 proto_tree_add_item(tree, hf_eip_cert_cert_name, tvb, offset+1, path_size, ENC_ASCII|ENC_NA);
2137 offset += (1+path_size);
2138
2139 path_size = dissect_padded_epath_len_usint(pinfo, cert_tree, ti, tvb, offset, total_len);
2140 offset += path_size;
2141 }
2142 proto_item_set_len(ti, offset-start_offset);
2143 return offset-start_offset;
2144 }
2145
2146 static int
dissect_eip_cert_device_cert(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2147 dissect_eip_cert_device_cert(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2148 int offset, int total_len)
2149 {
2150 guint32 path_size;
2151
2152 proto_tree_add_item(tree, hf_eip_cert_device_cert_status, tvb, offset, 1, ENC_NA);
2153 offset++;
2154
2155 path_size = dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset, total_len);
2156
2157 return path_size + 1;
2158 }
2159
2160 static int
dissect_eip_cert_ca_cert(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)2161 dissect_eip_cert_ca_cert(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2162 int offset, int total_len)
2163 {
2164 guint32 path_size;
2165
2166 proto_tree_add_item(tree, hf_eip_cert_ca_cert_status, tvb, offset, 1, ENC_NA);
2167 offset++;
2168
2169 path_size = dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset, total_len);
2170
2171 return path_size + 1;
2172 }
2173
dissect_tcpip_port_information(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset)2174 static int dissect_tcpip_port_information(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2175 int offset)
2176 {
2177 int start_offset = offset;
2178
2179 guint32 port_count;
2180 proto_tree_add_item_ret_uint(tree, hf_tcpip_port_count, tvb, offset, 1, ENC_LITTLE_ENDIAN, &port_count);
2181 offset++;
2182
2183 for (guint32 i = 0; i < port_count; ++i)
2184 {
2185 proto_item *port_item;
2186 proto_tree *port_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cmd_data, &port_item, "Port: ");
2187
2188 offset += dissect_cip_string_type(pinfo, port_tree, item, tvb, offset, hf_tcpip_port_name, CIP_SHORT_STRING_TYPE);
2189
2190 guint32 port_number;
2191 proto_tree_add_item_ret_uint(port_tree, hf_tcpip_port_number, tvb, offset, 2, ENC_LITTLE_ENDIAN, &port_number);
2192 offset += 2;
2193 proto_item_append_text(port_item, "Number: %d", port_number);
2194
2195 proto_tree_add_item(port_tree, hf_tcpip_port_protocol, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2196 offset++;
2197
2198 proto_tree_add_item(port_tree, hf_tcpip_port_admin_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2199 offset++;
2200
2201 static int* const capability[] = {
2202 &hf_tcpip_admin_capability_configurable,
2203 &hf_tcpip_admin_capability_reset_required,
2204 &hf_tcpip_admin_capability_reserved,
2205 NULL
2206 };
2207
2208 proto_tree_add_bitmask(port_tree, tvb, offset, hf_tcpip_port_admin_capability, ett_tcpip_admin_capability, capability, ENC_LITTLE_ENDIAN);
2209 offset++;
2210 }
2211
2212 return offset - start_offset;
2213 }
2214
dissect_tcpip_port_admin(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len _U_)2215 static int dissect_tcpip_port_admin(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2216 int offset, int total_len _U_)
2217 {
2218 return dissect_tcpip_port_information(pinfo, tree, item, tvb, offset);
2219 }
2220
2221 attribute_info_t enip_attribute_vals[] = {
2222
2223 /* TCP/IP Object (class attributes) */
2224 {0xF5, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2225 {0xF5, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2226 {0xF5, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2227 {0xF5, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2228 {0xF5, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2229 {0xF5, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2230 {0xF5, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2231
2232 /* TCP/IP object (instance attributes) */
2233 {0xF5, FALSE, 1, 0, "Status", cip_dissector_func, NULL, dissect_tcpip_status},
2234 {0xF5, FALSE, 2, 1, "Configuration Capability", cip_dissector_func, NULL, dissect_tcpip_config_cap},
2235 {0xF5, FALSE, 3, 2, "Configuration Control", cip_dissector_func, NULL, dissect_tcpip_config_control},
2236 {0xF5, FALSE, 4, 3, "Physical Link Object", cip_dissector_func, NULL, dissect_tcpip_physical_link},
2237 {0xF5, FALSE, 5, 4, "Interface Configuration", cip_dissector_func, NULL, dissect_tcpip_interface_config},
2238 {0xF5, FALSE, 6, 5, "Host Name", cip_dissector_func, NULL, dissect_tcpip_hostname},
2239 {0xF5, FALSE, 7, 6, "Safety Network Number", cip_dissector_func, NULL, dissect_tcpip_snn},
2240 {0xF5, FALSE, 8, 7, "TTL Value", cip_usint, &hf_tcpip_ttl_value, NULL},
2241 {0xF5, FALSE, 9, 8, "Multicast Configuration", cip_dissector_func, NULL, dissect_tcpip_mcast_config},
2242 {0xF5, FALSE, 10, 9, "Select ACD", cip_bool, &hf_tcpip_select_acd, NULL},
2243 {0xF5, FALSE, 11, 10, "Last Conflict Detected", cip_dissector_func, NULL, dissect_tcpip_last_conflict},
2244 {0xF5, FALSE, 12, 11, "EtherNet/IP Quick Connect", cip_bool, &hf_tcpip_quick_connect, NULL},
2245 {0xF5, FALSE, 13, 12, "Encapsulation Inactivity Timeout", cip_uint, &hf_tcpip_encap_inactivity, NULL},
2246 {0xF5, FALSE, 14, -1, "IANA Port Admin", cip_dissector_func, NULL, dissect_tcpip_port_admin },
2247
2248 /* Ethernet Link Object (class attributes) */
2249 {0xF6, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2250 {0xF6, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2251 {0xF6, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2252 {0xF6, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2253 {0xF6, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2254 {0xF6, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2255 {0xF6, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2256
2257 /* Ethernet Link object (instance attributes) */
2258 {0xF6, FALSE, 1, 0, "Interface Speed", cip_dword, &hf_elink_interface_speed, NULL},
2259 {0xF6, FALSE, 2, 1, "Interface Flags", cip_dissector_func, NULL, dissect_elink_interface_flags},
2260 {0xF6, FALSE, 3, 2, "Physical Address", cip_dissector_func, NULL, dissect_elink_physical_address },
2261 {0xF6, FALSE, 4, 3, "Interface Counters", cip_dissector_func, NULL, dissect_elink_interface_counters},
2262 {0xF6, FALSE, 5, 4, "Media Counters", cip_dissector_func, NULL, dissect_elink_media_counters},
2263 {0xF6, FALSE, 6, 5, "Interface Control", cip_dissector_func, NULL, dissect_elink_interface_control},
2264 {0xF6, FALSE, 7, 6, "Interface Type", cip_usint, &hf_elink_interface_type, NULL},
2265 {0xF6, FALSE, 8, 7, "Interface State", cip_usint, &hf_elink_interface_state, NULL},
2266 {0xF6, FALSE, 9, 8, "Admin State", cip_usint, &hf_elink_admin_state, NULL},
2267 {0xF6, FALSE, 10, 9, "Interface Label", cip_short_string, &hf_elink_interface_label, NULL},
2268 {0xF6, FALSE, 11, 10, "Interface Capability", cip_dissector_func, NULL, dissect_elink_interface_capability},
2269 {0xF6, FALSE, 12, 11, "HC Interface Counters", cip_dissector_func, NULL, dissect_elink_hc_interface_counters},
2270 {0xF6, FALSE, 13, 12, "HC Media Counters", cip_dissector_func, NULL, dissect_elink_hc_media_counters},
2271
2272 /* QoS Object (class attributes) */
2273 {0x48, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2274 {0x48, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2275 {0x48, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2276 {0x48, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2277 {0x48, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2278 {0x48, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2279 {0x48, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2280
2281 /* QoS object (instance attributes) */
2282 {0x48, FALSE, 1, -1, "802.1Q Tag Enable", cip_bool, &hf_qos_8021q_enable, NULL},
2283 {0x48, FALSE, 2, -1, "DSCP PTP Event", cip_usint, &hf_qos_dscp_ptp_event, NULL},
2284 {0x48, FALSE, 3, -1, "DSCP PTP General", cip_usint, &hf_qos_dscp_ptp_general, NULL},
2285 {0x48, FALSE, 4, -1, "DSCP Urgent", cip_usint, &hf_qos_dscp_urgent, NULL},
2286 {0x48, FALSE, 5, -1, "DSCP Scheduled", cip_usint, &hf_qos_dscp_scheduled, NULL},
2287 {0x48, FALSE, 6, -1, "DSCP High", cip_usint, &hf_qos_dscp_high, NULL},
2288 {0x48, FALSE, 7, -1, "DSCP Low", cip_usint, &hf_qos_dscp_low, NULL},
2289 {0x48, FALSE, 8, -1, "DSCP Explicit", cip_usint, &hf_qos_dscp_explicit, NULL},
2290
2291 /* DLR Object (class attributes) */
2292 {0x47, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2293 {0x47, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2294 {0x47, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2295 {0x47, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2296 {0x47, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2297 {0x47, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2298 {0x47, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2299
2300 /* DLR object (instance attributes) */
2301 /* Get Attributes All is not fully parsed here because there are multiple formats. */
2302 {0x47, FALSE, 1, 0, "Network Topology", cip_usint, &hf_dlr_network_topology, NULL},
2303 {0x47, FALSE, 2, 1, "Network Status", cip_usint, &hf_dlr_network_status, NULL},
2304 {0x47, FALSE, 3, -1, "Ring Supervisor Status", cip_usint, &hf_dlr_ring_supervisor_status, NULL},
2305 {0x47, FALSE, 4, -1, "Ring Supervisor Config", cip_dissector_func, NULL, dissect_dlr_ring_supervisor_config},
2306 {0x47, FALSE, 5, -1, "Ring Faults Count", cip_uint, &hf_dlr_ring_faults_count, NULL},
2307 {0x47, FALSE, 6, -1, "Last Active Node on Port 1", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_1},
2308 {0x47, FALSE, 7, -1, "Last Active Node on Port 2", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_2},
2309 {0x47, FALSE, 8, -1, "Ring Protocol Participants Count", cip_uint, &hf_dlr_ring_protocol_participants_count, NULL},
2310 {0x47, FALSE, 9, -1, "Ring Protocol Participants List", cip_dissector_func, NULL, dissect_dlr_ring_protocol_participants_list},
2311 {0x47, FALSE, 10, -1, "Active Supervisor Address", cip_dissector_func, NULL, dissect_dlr_active_supervisor_address},
2312 {0x47, FALSE, 11, -1, "Active Supervisor Precedence", cip_usint, &hf_dlr_active_supervisor_precedence, NULL},
2313 {0x47, FALSE, 12, -1, "Capability Flags", cip_dissector_func, NULL, dissect_dlr_capability_flags},
2314 {0x47, FALSE, 13, -1, "Redundant Gateway Config", cip_dissector_func, NULL, dissect_dlr_redundant_gateway_config},
2315 {0x47, FALSE, 14, -1, "Redundant Gateway Status", cip_usint, &hf_dlr_redundant_gateway_status, NULL},
2316 {0x47, FALSE, 15, -1, "Active Gateway Address", cip_dissector_func, NULL, dissect_dlr_active_gateway_address},
2317 {0x47, FALSE, 16, -1, "Active Gateway Precedence", cip_usint, &hf_dlr_active_gateway_precedence, NULL},
2318
2319 /* CIP Security Object (instance attributes) */
2320 {0x5D, CIP_ATTR_INSTANCE, 1, 0, "State", cip_usint, &hf_cip_security_state, NULL},
2321 {0x5D, CIP_ATTR_INSTANCE, 2, 1, "Security Profiles", cip_dissector_func, NULL, dissect_cip_security_profiles },
2322
2323 /* EtherNet/IP Security object (instance attributes) */
2324 {0x5E, FALSE, 1, 0, "State", cip_usint, &hf_eip_security_state, NULL},
2325 {0x5E, FALSE, 2, 1, "Capability Flags", cip_dissector_func, NULL, dissect_eip_security_cap},
2326 {0x5E, FALSE, 3, 2, "Available Cipher Suites", cip_dissector_func, NULL, dissect_eip_security_avail_cipher_suites},
2327 {0x5E, FALSE, 4, 3, "Allowed Cipher Suites", cip_dissector_func, NULL, dissect_eip_security_allow_cipher_suites},
2328 {0x5E, FALSE, 5, 4, "Pre-Shared Keys", cip_dissector_func, NULL, dissect_eip_security_preshared_keys},
2329 {0x5E, FALSE, 6, 5, "Active Device Certificates", cip_dissector_func, NULL, dissect_eip_security_active_certs},
2330 {0x5E, FALSE, 7, 6, "Trusted Authorities", cip_dissector_func, NULL, dissect_eip_security_trusted_auths},
2331 {0x5E, FALSE, 8, 7, "Certificate Revocation List", cip_dissector_func, NULL, dissect_eip_security_cert_revocation_list},
2332 {0x5E, FALSE, 9, 8, "Verify Client Certificate", cip_bool, &hf_eip_security_verify_client_cert, NULL},
2333 {0x5E, FALSE, 10, 9, "Send Certificate Chain", cip_bool, &hf_eip_security_send_cert_chain, NULL},
2334 {0x5E, FALSE, 11, 10, "Check Expiration", cip_bool, &hf_eip_security_check_expiration, NULL},
2335
2336 /* Certificate Management Object (class attributes) */
2337 {0x5F, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2338 {0x5F, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2339 {0x5F, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2340 {0x5F, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2341 {0x5F, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2342 {0x5F, TRUE, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2343 {0x5F, TRUE, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2344 {0x5F, TRUE, 8, 4, "Capability Flags", cip_dissector_func, NULL, dissect_eip_cert_cap_flags },
2345 {0x5F, TRUE, 9, 5, "Certificate List", cip_dissector_func, NULL, dissect_eip_cert_cert_list },
2346
2347 /* Certificate Management Object (instance attributes) */
2348 {0x5F, FALSE, 1, 0, "Name", cip_short_string, &hf_eip_cert_name, NULL},
2349 {0x5F, FALSE, 2, 1, "State", cip_usint, &hf_eip_cert_state, NULL},
2350 {0x5F, FALSE, 3, 2, "Device Certificate", cip_dissector_func, NULL, dissect_eip_cert_device_cert},
2351 {0x5F, FALSE, 4, 3, "CA Certificate", cip_dissector_func, NULL, dissect_eip_cert_ca_cert},
2352 {0x5F, FALSE, 5, 4, "Certificate Encoding", cip_usint, &hf_eip_cert_encoding, NULL },
2353 };
2354
enip_init_protocol(void)2355 static void enip_init_protocol(void)
2356 {
2357 enip_unique_connid = 0;
2358 }
2359
2360 // offset - Starts at the "Encapsulation Protocol Version" field.
dissect_item_list_identity(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * item_tree)2361 static void dissect_item_list_identity(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree)
2362 {
2363 /* Encapsulation version */
2364 proto_tree_add_item(item_tree, hf_enip_encapver, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2365
2366 /* Socket Address */
2367 proto_tree* sockaddr_tree = proto_tree_add_subtree(item_tree, tvb, offset + 2, 16, ett_sockadd, NULL, "Socket Address");
2368
2369 /* Socket address struct - sin_family */
2370 proto_tree_add_item(sockaddr_tree, hf_enip_sinfamily, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2371
2372 /* Socket address struct - sin_port */
2373 proto_tree_add_item(sockaddr_tree, hf_enip_sinport, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2374
2375 /* Socket address struct - sin_address */
2376 proto_tree_add_item(sockaddr_tree, hf_enip_sinaddr, tvb, offset + 6, 4, ENC_BIG_ENDIAN);
2377
2378 /* Socket address struct - sin_zero */
2379 proto_tree_add_item(sockaddr_tree, hf_enip_sinzero, tvb, offset + 10, 8, ENC_NA);
2380
2381 /* Vendor ID */
2382 proto_tree_add_item(item_tree, hf_enip_lir_vendor, tvb, offset + 18, 2, ENC_LITTLE_ENDIAN);
2383
2384 /* Device Type */
2385 proto_tree_add_item(item_tree, hf_enip_lir_devtype, tvb, offset + 20, 2, ENC_LITTLE_ENDIAN);
2386
2387 /* Product Code */
2388 proto_tree_add_item(item_tree, hf_enip_lir_prodcode, tvb, offset + 22, 2, ENC_LITTLE_ENDIAN);
2389
2390 /* Revision */
2391 proto_tree_add_item(item_tree, hf_enip_lir_revision, tvb, offset + 24, 2, ENC_BIG_ENDIAN);
2392
2393 /* Status */
2394 proto_tree_add_item(item_tree, hf_enip_lir_status, tvb, offset + 26, 2, ENC_LITTLE_ENDIAN);
2395
2396 /* Serial Number */
2397 proto_tree_add_item(item_tree, hf_enip_lir_serial, tvb, offset + 28, 4, ENC_LITTLE_ENDIAN);
2398
2399 /* Product Name Length */
2400 guint32 name_length;
2401 proto_tree_add_item_ret_uint(item_tree, hf_enip_lir_namelen, tvb, offset + 32, 1, ENC_LITTLE_ENDIAN, &name_length);
2402
2403 /* Product Name */
2404 proto_tree_add_item(item_tree, hf_enip_lir_name, tvb, offset + 33, name_length, ENC_ASCII | ENC_NA);
2405
2406 /* Append product name to info column */
2407 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", tvb_format_text(pinfo->pool, tvb, offset + 33, name_length));
2408
2409 /* State */
2410 proto_tree_add_item(item_tree, hf_enip_lir_state, tvb, offset + name_length + 33, 1, ENC_LITTLE_ENDIAN);
2411 }
2412
2413 // offset - Starts at the "Security Profiles" field.
dissect_item_cip_security_information(tvbuff_t * tvb,int offset,proto_tree * item_tree)2414 static void dissect_item_cip_security_information(tvbuff_t* tvb, int offset, proto_tree* item_tree)
2415 {
2416 static int * const iana_flags[] = {
2417 &hf_enip_iana_port_state_flags_tcp_44818,
2418 &hf_enip_iana_port_state_flags_udp_44818,
2419 &hf_enip_iana_port_state_flags_udp_2222,
2420 &hf_enip_iana_port_state_flags_tcp_2221,
2421 &hf_enip_iana_port_state_flags_udp_2221,
2422 &hf_enip_iana_port_state_flags_reserved,
2423 NULL
2424 };
2425
2426 dissect_cip_security_profiles(NULL, item_tree, NULL, tvb, offset, tvb_reported_length_remaining(tvb, offset));
2427
2428 /* CIP Security object state */
2429 proto_tree_add_item(item_tree, hf_enip_cip_security_state, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
2430
2431 /* ENIP Security object state */
2432 proto_tree_add_item(item_tree, hf_enip_eip_security_state, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
2433
2434 /* IANA Port State flags */
2435 proto_tree_add_bitmask(item_tree, tvb, offset + 4, hf_enip_iana_port_state_flags, ett_iana_port_state_flags, iana_flags, ENC_LITTLE_ENDIAN);
2436 }
2437
2438 // offset - Starts at the "Encapsulation Protocol Version" field.
dissect_item_list_services_response(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * item_tree)2439 static void dissect_item_list_services_response(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree)
2440 {
2441 /* Encapsulation version */
2442 proto_tree_add_item(item_tree, hf_enip_encapver, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2443
2444 /* Capability flags */
2445 static int* const capability_bits[] = {
2446 &hf_enip_lsr_tcp,
2447 &hf_enip_lsr_udp,
2448 NULL
2449 };
2450 proto_tree_add_bitmask(item_tree, tvb, offset + 2, hf_enip_lsr_capaflags, ett_lsrcf, capability_bits, ENC_LITTLE_ENDIAN);
2451
2452 /* Name of service */
2453 proto_tree_add_item(item_tree, hf_enip_lsr_servicename, tvb, offset + 4, 16, ENC_ASCII | ENC_NA);
2454
2455 /* Append service name to info column */
2456 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2457 tvb_format_stringzpad(pinfo->pool, tvb, offset + 4, 16));
2458 }
2459
display_fwd_open_connection_path(cip_conn_info_t * conn_info,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo)2460 static void display_fwd_open_connection_path(cip_conn_info_t* conn_info, proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo)
2461 {
2462 if (!conn_info->pFwdOpenPathData)
2463 {
2464 return;
2465 }
2466
2467 tvbuff_t* tvbIOI = tvb_new_real_data((const guint8*)conn_info->pFwdOpenPathData, conn_info->FwdOpenPathLenBytes, conn_info->FwdOpenPathLenBytes);
2468 if (tvbIOI)
2469 {
2470 proto_item* pi = NULL;
2471 proto_tree* epath_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_path_info, &pi, "Forward Open Connection Path: ");
2472 proto_item_set_generated(pi);
2473
2474 dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, conn_info->FwdOpenPathLenBytes, TRUE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
2475 tvb_free(tvbIOI);
2476 }
2477 }
2478
display_connection_information(packet_info * pinfo,tvbuff_t * tvb,proto_tree * tree,cip_conn_info_t * conn_info,enum enip_connid_type connid_type)2479 static void display_connection_information(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, cip_conn_info_t* conn_info, enum enip_connid_type connid_type)
2480 {
2481 proto_item* conn_info_item = NULL;
2482 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
2483 proto_item_set_generated(conn_info_item);
2484
2485 if (connid_type == ECIDT_O2T)
2486 {
2487 proto_item_append_text(conn_info_item, ": O->T");
2488 }
2489 else if (connid_type == ECIDT_T2O)
2490 {
2491 proto_item_append_text(conn_info_item, ": T->O");
2492 }
2493
2494 display_fwd_open_connection_path(conn_info, conn_info_tree, tvb, pinfo);
2495
2496 proto_item* pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_ot_api, tvb, 0, 0, conn_info->O2T.api);
2497 proto_item_set_generated(pi);
2498
2499 pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_to_api, tvb, 0, 0, conn_info->T2O.api);
2500 proto_item_set_generated(pi);
2501
2502 pi = proto_tree_add_uint(conn_info_tree, hf_cip_connection, tvb, 0, 0, conn_info->connid);
2503 proto_item_set_generated(pi);
2504
2505 pi = proto_tree_add_uint(conn_info_tree, hf_enip_fwd_open_in, tvb, 0, 0, conn_info->open_req_frame);
2506 proto_item_set_generated(pi);
2507 }
2508
2509 // This dissects Class 0 or Class 1 I/O.
2510 // offset - Starts at the field after the Item Length field.
dissect_cip_io_generic(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,void * data)2511 static int dissect_cip_io_generic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data)
2512 {
2513 cip_io_data_input* io_data_input = (cip_io_data_input*)data;
2514
2515 int offset = 0;
2516
2517 proto_item* ti = proto_tree_add_item(tree, proto_cipio, tvb, 0, -1, ENC_NA);
2518 proto_tree* io_tree = proto_item_add_subtree(ti, ett_cip_io_generic);
2519
2520 if (io_data_input != NULL)
2521 {
2522 if ((io_data_input->conn_info->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1)
2523 {
2524 proto_tree_add_item(io_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2525 offset += 2;
2526 }
2527
2528 if ((tvb_reported_length_remaining(tvb, offset) >= 4) &&
2529 (((io_data_input->connid_type == ECIDT_O2T) && enip_OTrun_idle) ||
2530 ((io_data_input->connid_type == ECIDT_T2O) && enip_TOrun_idle)))
2531 {
2532 dissect_cip_run_idle(tvb, offset, io_tree);
2533 offset += 4;
2534 }
2535 }
2536
2537 proto_tree_add_item(io_tree, hf_cip_io_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
2538
2539 return tvb_captured_length(tvb);
2540 }
2541
2542 // Dissect the various kinds of CIP Class 0/1 I/O formats. This will determine the appropriate format and
2543 // call the appropriate related dissector.
2544 // offset - Starts at the field after the Item Length field.
dissect_cip_class01_io(packet_info * pinfo,tvbuff_t * tvb,int offset,int item_length,cip_conn_info_t * conn_info,enum enip_connid_type connid_type,proto_tree * dissector_tree)2545 static void dissect_cip_class01_io(packet_info* pinfo, tvbuff_t* tvb, int offset,
2546 int item_length, cip_conn_info_t* conn_info, enum enip_connid_type connid_type,
2547 proto_tree* dissector_tree)
2548 {
2549 if (tvb_reported_length_remaining(tvb, offset) <= 0)
2550 {
2551 return;
2552 }
2553
2554 /* Display data */
2555 tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset, item_length);
2556 if (conn_info != NULL)
2557 {
2558 cip_io_data_input io_data_input;
2559 io_data_input.conn_info = conn_info;
2560 io_data_input.connid_type = connid_type;
2561
2562 if (conn_info->safety.safety_seg == TRUE)
2563 {
2564 /* Add any possible safety related data */
2565 cip_safety_info_t cip_safety;
2566 cip_safety.conn_type = connid_type;
2567 cip_safety.eip_conn_info = conn_info;
2568 cip_safety.compute_crc = TRUE;
2569
2570 call_dissector_with_data(cipsafety_handle, next_tvb, pinfo, dissector_tree, &cip_safety);
2571 }
2572 else
2573 {
2574 dissector_handle_t dissector = dissector_get_uint_handle(subdissector_io_table, conn_info->ClassID);
2575 if (dissector)
2576 {
2577 call_dissector_with_data(dissector, next_tvb, pinfo, dissector_tree, &io_data_input);
2578 }
2579 else
2580 {
2581 call_dissector_with_data(cip_io_generic_handle, next_tvb, pinfo, dissector_tree, &io_data_input);
2582 }
2583 }
2584 }
2585 else
2586 {
2587 // This handles the Decode As options
2588 if (!dissector_try_payload(subdissector_decode_as_io_table, next_tvb, pinfo, dissector_tree))
2589 {
2590 call_dissector_with_data(cip_io_generic_handle, next_tvb, pinfo, dissector_tree, NULL);
2591 }
2592 }
2593 }
2594
2595 // Dissect CIP Class 2/3 data. This will determine the appropriate format and call the appropriate related dissector.
2596 // offset - Starts at the field after the Item Length field.
dissect_cip_class23_data(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * tree,proto_tree * item_tree,guint32 item_length,enip_request_key_t * request_key,cip_conn_info_t * conn_info,proto_tree * dissector_tree)2597 static void dissect_cip_class23_data(packet_info* pinfo, tvbuff_t* tvb, int offset,
2598 proto_tree* tree, proto_tree* item_tree, guint32 item_length,
2599 enip_request_key_t* request_key, cip_conn_info_t* conn_info, proto_tree* dissector_tree)
2600 {
2601 enip_request_info_t* request_info = NULL;
2602
2603 if (request_key)
2604 {
2605 request_key->type = EPDT_CONNECTED_TRANSPORT;
2606 request_key->data.connected_transport.sequence = tvb_get_letohs(tvb, offset);
2607 request_info = enip_match_request(pinfo, tree, request_key);
2608 }
2609
2610 /* Add sequence count ( Transport Class 2,3 ) */
2611 proto_tree_add_item(item_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2612
2613 /* Call dissector for interface */
2614 tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset + 2, item_length - 2);
2615
2616 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO, request_info);
2617
2618 if (conn_info != NULL)
2619 {
2620 dissector_handle_t dissector = dissector_get_uint_handle(subdissector_cip_connection_table, conn_info->ClassID);
2621 if (dissector)
2622 {
2623 call_dissector_with_data(dissector, next_tvb, pinfo, dissector_tree, GUINT_TO_POINTER(conn_info->ClassID));
2624 }
2625 else
2626 {
2627 call_dissector_with_data(cip_implicit_handle, next_tvb, pinfo, dissector_tree, GUINT_TO_POINTER(conn_info->ClassID));
2628 }
2629 }
2630 else
2631 {
2632 // Default to Message Router format, since this is the most common. Since we don't have the connection
2633 // info, at least ensure that the data can at least meet the minimum explicit message size.
2634 if (tvb_reported_length(next_tvb) >= 2)
2635 {
2636 call_dissector(cip_handle, next_tvb, pinfo, dissector_tree);
2637 }
2638 }
2639
2640 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2641 }
2642
2643 // offset - Starts at the sin_family field.
dissect_item_sockaddr_info(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * item_tree,guint32 item_type_id,gboolean is_fwd_open)2644 static void dissect_item_sockaddr_info(packet_info *pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree,
2645 guint32 item_type_id, gboolean is_fwd_open)
2646 {
2647 /* Socket address struct - sin_family */
2648 proto_tree_add_item(item_tree, hf_enip_sinfamily, tvb, offset, 2, ENC_BIG_ENDIAN);
2649
2650 /* Socket address struct - sin_port */
2651 proto_tree_add_item(item_tree, hf_enip_sinport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2652
2653 /* Socket address struct - sin_address */
2654 proto_tree_add_item(item_tree, hf_enip_sinaddr, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
2655
2656 /* Socket address struct - sin_zero */
2657 proto_tree_add_item(item_tree, hf_enip_sinzero, tvb, offset + 8, 8, ENC_NA);
2658
2659 if (is_fwd_open)
2660 {
2661 enip_request_info_t* request_info = (enip_request_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2662 if (request_info != NULL)
2663 {
2664 if (item_type_id == CPF_ITEM_SOCK_ADR_INFO_OT)
2665 {
2666 request_info->cip_info->connInfo->O2T.port = tvb_get_ntohs(tvb, offset + 2);
2667 alloc_address_tvb(wmem_file_scope(), &request_info->cip_info->connInfo->O2T.ipaddress,
2668 AT_IPv4, sizeof(guint32), tvb, offset + 4);
2669 }
2670 else
2671 {
2672 request_info->cip_info->connInfo->T2O.port = tvb_get_ntohs(tvb, offset + 2);
2673 alloc_address_tvb(wmem_file_scope(), &request_info->cip_info->connInfo->T2O.ipaddress,
2674 AT_IPv4, sizeof(guint32), tvb, offset + 4);
2675 }
2676 }
2677 }
2678 }
2679
2680 // offset - Starts at the Connection ID
2681 // Returns: connid_type, conn_info
dissect_item_sequenced_address(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * tree,enum enip_connid_type * connid_type,cip_conn_info_t ** conn_info)2682 static void dissect_item_sequenced_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
2683 proto_tree* tree, enum enip_connid_type* connid_type, cip_conn_info_t** conn_info)
2684 {
2685 guint32 connection_id;
2686 proto_tree_add_item_ret_uint(tree, hf_enip_cpf_sai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &connection_id);
2687 proto_item* pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2688 proto_item_set_hidden(pi);
2689
2690 guint32 sequence_num;
2691 proto_tree_add_item_ret_uint(tree, hf_enip_cpf_sai_seqnum, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &sequence_num);
2692
2693 *conn_info = enip_get_io_connid(pinfo, connection_id, connid_type);
2694
2695 col_add_fstr(pinfo->cinfo, COL_INFO, "Connection: ID=0x%08X, SEQ=%010u", connection_id, sequence_num);
2696 if (*connid_type == ECIDT_O2T)
2697 {
2698 col_append_str(pinfo->cinfo, COL_INFO, ", O->T");
2699 }
2700 else if (*connid_type == ECIDT_T2O)
2701 {
2702 col_append_str(pinfo->cinfo, COL_INFO, ", T->O");
2703 }
2704 }
2705
2706 // offset - Starts at the Connection ID
2707 // Returns: conn_info
dissect_item_connected_address(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * item_tree,proto_item * enip_item,enip_request_key_t * request_key,cip_conn_info_t ** conn_info)2708 static void dissect_item_connected_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
2709 proto_tree* item_tree, proto_item* enip_item,
2710 enip_request_key_t* request_key, cip_conn_info_t** conn_info)
2711 {
2712 guint32 connection_id;
2713 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_cai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &connection_id);
2714 proto_item* pi = proto_tree_add_item(item_tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2715 proto_item_set_hidden(pi);
2716
2717 *conn_info = enip_get_explicit_connid(pinfo, request_key, connection_id);
2718 if (request_key)
2719 {
2720 request_key->type = EPDT_CONNECTED_TRANSPORT;
2721 request_key->data.connected_transport.connid = (*conn_info != NULL) ? (*conn_info)->connid : 0;
2722 }
2723
2724 /* Add Connection ID to Info col and tree */
2725 col_append_fstr(pinfo->cinfo, COL_INFO, ", Connection: ID=0x%08X", connection_id);
2726
2727 if (enip_item)
2728 {
2729 proto_item_append_text(enip_item, ", Connection ID: 0x%08X", connection_id);
2730 }
2731 }
2732
2733 // offset - Starts at Unconn Msg Type
2734 // returns - input_request_key
2735 // Dissects the following parts of the Unconnected Message over UDP item: Unconn Msg Type, Transaction Number, Status.
2736 // The Unconnected Messge field is handled outside of this function.
dissect_item_unconnected_message_over_udp(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * item_tree,enip_request_key_t ** input_request_key)2737 static void dissect_item_unconnected_message_over_udp(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree, enip_request_key_t** input_request_key)
2738 {
2739 guint32 ucmm_request;
2740 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_ucmm_request, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ucmm_request);
2741 proto_tree_add_item(item_tree, hf_enip_cpf_ucmm_msg_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2742
2743 guint32 trans_id;
2744 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_ucmm_trans_id, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN, &trans_id);
2745 proto_tree_add_item(item_tree, hf_enip_cpf_ucmm_status, tvb, offset + 6, 4, ENC_LITTLE_ENDIAN);
2746
2747 if (*input_request_key == NULL)
2748 {
2749 /*
2750 * Under normal circumstances request_key should always be NULL here
2751 * Duplicating setting up a request (like is done with explicit messaging)
2752 */
2753 conversation_t* conversation = find_or_create_conversation(pinfo);
2754
2755 /*
2756 * Attach that information to the conversation, and add
2757 * it to the list of information structures later before dissection.
2758 */
2759 enip_request_key_t* request_key = wmem_new0(pinfo->pool, enip_request_key_t);
2760 request_key->requesttype = ucmm_request ? ENIP_RESPONSE_PACKET : ENIP_REQUEST_PACKET;
2761 request_key->type = EPDT_UNKNOWN;
2762
2763 /* UCMM over UDP doesn't have a session handle, so use conversation
2764 * pointer as "unique-ish ID"
2765 */
2766 request_key->session_handle = GPOINTER_TO_UINT(conversation);
2767 request_key->sender_context = trans_id;
2768 request_key->conversation = conversation->conv_index;
2769
2770 // Return the new request key.
2771 *input_request_key = request_key;
2772 }
2773 }
2774
is_forward_open(guint8 cip_service)2775 static gboolean is_forward_open(guint8 cip_service)
2776 {
2777 return (cip_service == SC_CM_FWD_OPEN
2778 || cip_service == SC_CM_LARGE_FWD_OPEN);
2779 }
2780
2781 /* Dissect Common Packet Format */
2782 static void
dissect_cpf(enip_request_key_t * request_key,int command,tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * dissector_tree,proto_tree * enip_layer_tree,proto_item * enip_item,int offset,guint32 ifacehndl)2783 dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
2784 packet_info *pinfo, proto_tree *tree, proto_tree *dissector_tree, proto_tree *enip_layer_tree,
2785 proto_item *enip_item, int offset, guint32 ifacehndl)
2786 {
2787 proto_item *count_item;
2788 proto_tree *count_tree;
2789 int item_count;
2790
2791 // The following variables are set in one pass of the loop, and read in a second pass.
2792 cip_conn_info_t* conn_info = NULL;
2793 gboolean FwdOpenRequest = FALSE;
2794 gboolean FwdOpenReply = FALSE;
2795 enum enip_connid_type connid_type = ECIDT_UNKNOWN;
2796
2797 // Normal "Common Packet Format" configurations. See CIP Volume 2, Section 2-6.4.
2798 // SendRRData (Unconnected):
2799 // Item 1: CPF_ITEM_NULL
2800 // Item 2: CPF_ITEM_UNCONNECTED_DATA
2801 // SendUnitData (Connected, Class 3):
2802 // Item 1: CPF_ITEM_CONNECTED_ADDRESS
2803 // Item 2: CPF_ITEM_CONNECTED_DATA
2804 // Item 3 (Optional): CPF_ITEM_SOCK_ADR_INFO_OT/CPF_ITEM_SOCK_ADR_INFO_TO
2805 // Class 0/1 packet:
2806 // Item 1: CPF_ITEM_SEQUENCED_ADDRESS
2807 // Item 2: CPF_ITEM_CONNECTED_DATA
2808 // Unconnected Message over UDP:
2809 // Item 1: CPF_ITEM_UNCONNECTED_MSG_DTLS
2810
2811 /* Create item count tree */
2812 item_count = tvb_get_letohs( tvb, offset );
2813 count_item = proto_tree_add_item( tree, hf_enip_cpf_itemcount, tvb, offset, 2, ENC_LITTLE_ENDIAN );
2814 count_tree = proto_item_add_subtree( count_item, ett_count_tree );
2815 offset += 2;
2816
2817 while ( item_count-- )
2818 {
2819 // Verify that we have the minimum CPF Item size.
2820 if (tvb_reported_length_remaining(tvb, offset) < 4)
2821 {
2822 expert_add_info_format(pinfo, count_item, &ei_mal_cpf_item_minimum_size,
2823 "%s, but Remaining Data Length is %d",
2824 expert_get_summary(&ei_mal_cpf_item_minimum_size), tvb_reported_length_remaining(tvb, offset));
2825
2826 break;
2827 }
2828
2829 /* Add item type tree to item count tree*/
2830 guint32 item_type_id;
2831 proto_item* type_item = proto_tree_add_item_ret_uint( count_tree, hf_enip_cpf_typeid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_type_id );
2832 proto_tree* item_tree = proto_item_add_subtree( type_item, ett_type_tree );
2833 offset += 2;
2834
2835 /* Add length field to item type tree */
2836 guint32 item_length;
2837 proto_tree_add_item_ret_uint( item_tree, hf_enip_cpf_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_length);
2838 offset += 2;
2839
2840 // Check if the declared item length is more bytes than we have available. But, don't exit early
2841 // so maybe it will be more obvious where the problem is.
2842 if ((int)item_length > tvb_reported_length_remaining(tvb, offset))
2843 {
2844 expert_add_info_format(pinfo, type_item, &ei_mal_cpf_item_length_mismatch,
2845 "%s: Item Length %d, Remaining Data Length: %d",
2846 expert_get_summary(&ei_mal_cpf_item_length_mismatch), item_length, tvb_reported_length_remaining(tvb, offset));
2847 }
2848
2849 // offset now starts at the data field after the Item Length field. The name of this
2850 // field varies depending on the item type.
2851 if ( item_length )
2852 {
2853 /* Add item data field */
2854
2855 switch ( item_type_id )
2856 {
2857 case CPF_ITEM_CONNECTED_ADDRESS: // 1st Item for: Class 3 Connected Messages
2858 conn_info = NULL;
2859 dissect_item_connected_address(pinfo, tvb, offset, item_tree, enip_item, request_key, &conn_info);
2860 break;
2861
2862 case CPF_ITEM_UNCONNECTED_MSG_DTLS: // Only item for: Unconnected messages over DTLS
2863 {
2864 ifacehndl = ENIP_CIP_INTERFACE;
2865
2866 dissect_item_unconnected_message_over_udp(pinfo, tvb, offset, item_tree, &request_key);
2867
2868 // Skip over the fields already parsed before falling through.
2869 offset += 10;
2870 item_length -= 10;
2871 }
2872
2873 /* Intentionally fall through */
2874
2875 case CPF_ITEM_UNCONNECTED_DATA: // 2nd Item for: Unconnected Messages
2876 {
2877 enip_request_info_t* request_info = NULL;
2878 if ( request_key )
2879 {
2880 request_key->type = EPDT_UNCONNECTED;
2881 request_info = enip_match_request( pinfo, tree, request_key );
2882 }
2883
2884 /* Call dissector for interface */
2885 tvbuff_t* next_tvb = tvb_new_subset_length( tvb, offset, item_length);
2886 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO, request_info);
2887 if ( tvb_reported_length_remaining(next_tvb, 0) <= 0 || !dissector_try_uint(subdissector_srrd_table, ifacehndl, next_tvb, pinfo, dissector_tree) )
2888 {
2889 /* Show the undissected payload */
2890 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
2891 call_data_dissector(next_tvb, pinfo, dissector_tree);
2892 }
2893
2894 /* Check if this is a ForwardOpen packet, because special handling is needed
2895 to handle connection conversations */
2896 if ((request_info != NULL) && (request_info->cip_info != NULL) &&
2897 (request_info->cip_info->connInfo != NULL) &&
2898 (request_key != NULL) &&
2899 is_forward_open(request_info->cip_info->bService & CIP_SC_MASK) &&
2900 (request_info->cip_info->dissector == dissector_get_uint_handle(subdissector_class_table, CI_CLS_CM)))
2901 {
2902 if (request_key->requesttype == ENIP_REQUEST_PACKET)
2903 {
2904 FwdOpenRequest = TRUE;
2905 }
2906 else
2907 {
2908 FwdOpenReply = TRUE;
2909 }
2910 }
2911 else
2912 {
2913 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2914 }
2915 break;
2916 }
2917
2918 case CPF_ITEM_CONNECTED_DATA: // 2nd item for: Connected messages (both Class 0/1 and Class 3)
2919 // Save the connection info for the conversation filter
2920 if (!pinfo->fd->visited && conn_info)
2921 {
2922 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_info);
2923 }
2924
2925 if (command == SEND_UNIT_DATA) // Class 2/3 over TCP.
2926 {
2927 dissect_cip_class23_data(pinfo, tvb, offset, tree, item_tree, item_length, request_key, conn_info, dissector_tree);
2928 }
2929 else // No command. Send as CPF items only over UDP.
2930 {
2931 dissect_cip_class01_io(pinfo, tvb, offset, item_length, conn_info, connid_type, dissector_tree);
2932 }
2933
2934 if (conn_info)
2935 {
2936 display_connection_information(pinfo, tvb, enip_layer_tree, conn_info, connid_type);
2937 }
2938
2939 break;
2940
2941 case CPF_ITEM_CIP_IDENTITY:
2942 dissect_item_list_identity(pinfo, tvb, offset, item_tree);
2943 break;
2944
2945 case CPF_ITEM_CIP_SECURITY:
2946 dissect_item_cip_security_information(tvb, offset, item_tree);
2947 break;
2948
2949 case CPF_ITEM_SOCK_ADR_INFO_OT: // Optional 3rd item for: Unconnected Messages
2950 case CPF_ITEM_SOCK_ADR_INFO_TO:
2951 {
2952 gboolean is_fwd_open = (FwdOpenRequest == TRUE) || (FwdOpenReply == TRUE);
2953 dissect_item_sockaddr_info(pinfo, tvb, offset, item_tree, item_type_id, is_fwd_open);
2954 break;
2955 }
2956
2957 case CPF_ITEM_SEQUENCED_ADDRESS: // 1st item for: Class 0/1 connected data
2958 conn_info = NULL;
2959 dissect_item_sequenced_address(pinfo, tvb, offset, item_tree, &connid_type, &conn_info);
2960 break;
2961
2962 case CPF_ITEM_LIST_SERVICES_RESP:
2963 dissect_item_list_services_response(pinfo, tvb, offset, item_tree);
2964 break;
2965
2966 default:
2967 proto_tree_add_item(item_tree, hf_enip_cpf_data, tvb, offset, item_length, ENC_NA);
2968 break;
2969
2970 } /* end of switch ( item type ) */
2971
2972 } /* end of if ( item length ) */
2973
2974 offset += item_length;
2975 } /* end of while ( item count ) */
2976
2977 /* See if there is a CIP connection to establish */
2978 if (FwdOpenReply == TRUE)
2979 {
2980 enip_request_info_t* request_info = (enip_request_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2981 if (request_info != NULL)
2982 {
2983 enip_open_cip_connection(pinfo, request_info->cip_info->connInfo);
2984 }
2985 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2986 }
2987 else if (FwdOpenRequest == TRUE)
2988 {
2989 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2990 }
2991
2992 } /* end of dissect_cpf() */
2993
2994
2995
2996 static enum enip_packet_type
classify_packet(packet_info * pinfo)2997 classify_packet(packet_info *pinfo)
2998 {
2999 /* see if nature of packets can be derived from src/dst ports */
3000 /* if so, return as found */
3001 if (((ENIP_ENCAP_PORT == pinfo->srcport && ENIP_ENCAP_PORT != pinfo->destport)) ||
3002 ((ENIP_SECURE_PORT == pinfo->srcport && ENIP_SECURE_PORT != pinfo->destport)))
3003 {
3004 return ENIP_RESPONSE_PACKET;
3005 }
3006 else if (((ENIP_ENCAP_PORT != pinfo->srcport && ENIP_ENCAP_PORT == pinfo->destport)) ||
3007 ((ENIP_SECURE_PORT != pinfo->srcport && ENIP_SECURE_PORT == pinfo->destport)))
3008 {
3009 return ENIP_REQUEST_PACKET;
3010 }
3011 else
3012 {
3013 return ENIP_CANNOT_CLASSIFY;
3014 }
3015 }
3016
3017 static guint
get_enip_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)3018 get_enip_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
3019 {
3020 guint16 plen;
3021
3022 /*
3023 * Get the length of the data from the encapsulation header.
3024 */
3025 plen = tvb_get_letohs(tvb, offset + 2);
3026
3027 /*
3028 * That length doesn't include the encapsulation header itself;
3029 * add that in.
3030 */
3031 return plen + 24;
3032 }
3033
3034 /* Code to actually dissect the packets */
3035 static int
dissect_enip_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3036 dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3037 {
3038 enum enip_packet_type packet_type;
3039 guint16 encap_cmd, encap_data_length;
3040 const char *pkt_type_str = "";
3041 guint32 ifacehndl;
3042 conversation_t *conversation;
3043
3044 /* Set up structures needed to add the protocol subtree and manage it */
3045 proto_item *ti = NULL;
3046 proto_tree *enip_tree, *header_tree = NULL, *csftree;
3047
3048 /* Make entries in Protocol column and Info column on summary display */
3049 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENIP");
3050 col_clear(pinfo->cinfo, COL_INFO);
3051
3052 encap_cmd = tvb_get_letohs( tvb, 0 );
3053
3054 packet_type = classify_packet(pinfo);
3055
3056 switch ( packet_type )
3057 {
3058 case ENIP_REQUEST_PACKET:
3059 pkt_type_str = "Req";
3060 break;
3061
3062 case ENIP_RESPONSE_PACKET:
3063 pkt_type_str = "Rsp";
3064 break;
3065
3066 case ENIP_CANNOT_CLASSIFY:
3067 default:
3068 pkt_type_str = "?";
3069 }
3070
3071 /* Add encapsulation command to info column */
3072 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ", "%s (%s)",
3073 val_to_str(encap_cmd, encap_cmd_vals, "Unknown Command (0x%04x)"),
3074 pkt_type_str );
3075
3076 /*
3077 * We need to track some state for this protocol on a per conversation
3078 * basis so we can do neat things like request/response tracking
3079 */
3080 conversation = find_or_create_conversation(pinfo);
3081
3082 /*
3083 * Attach that information to the conversation, and add
3084 * it to the list of information structures later before dissection.
3085 */
3086 enip_request_key_t request_key = {0};
3087 request_key.requesttype = packet_type;
3088 request_key.type = EPDT_UNKNOWN;
3089 request_key.session_handle = tvb_get_letohl( tvb, 4 );
3090 request_key.sender_context = tvb_get_letoh64( tvb, 12 );
3091 request_key.conversation = conversation->conv_index;
3092
3093 /* create display subtree for the protocol */
3094 ti = proto_tree_add_item(tree, proto_enip, tvb, 0, -1, ENC_NA );
3095
3096 enip_tree = proto_item_add_subtree(ti, ett_enip);
3097
3098 /* Add encapsulation header tree */
3099 header_tree = proto_tree_add_subtree( enip_tree, tvb, 0, 24, ett_enip, NULL, "Encapsulation Header");
3100
3101 /* Add EtherNet/IP encapsulation header */
3102 proto_tree_add_item( header_tree, hf_enip_command, tvb, 0, 2, ENC_LITTLE_ENDIAN );
3103
3104 encap_data_length = tvb_get_letohs( tvb, 2 );
3105 proto_tree_add_item( header_tree, hf_enip_length, tvb, 2, 2, ENC_LITTLE_ENDIAN );
3106 proto_tree_add_item( header_tree, hf_enip_session, tvb, 4, 4, ENC_LITTLE_ENDIAN );
3107 proto_tree_add_item( header_tree, hf_enip_status, tvb, 8, 4, ENC_LITTLE_ENDIAN );
3108 if ((encap_cmd == LIST_IDENTITY) &&
3109 /* Length of 0 probably indicates a request */
3110 ((encap_data_length == 0) || (packet_type == ENIP_REQUEST_PACKET)))
3111 {
3112 proto_tree_add_item( header_tree, hf_enip_listid_delay, tvb, 12, 2, ENC_LITTLE_ENDIAN );
3113 proto_tree_add_item( header_tree, hf_enip_sendercontex, tvb, 14, 6, ENC_NA );
3114 }
3115 else
3116 {
3117 proto_tree_add_item( header_tree, hf_enip_sendercontex, tvb, 12, 8, ENC_NA );
3118 }
3119 proto_tree_add_item( header_tree, hf_enip_options, tvb, 20, 4, ENC_LITTLE_ENDIAN );
3120
3121 /* Append session and command to the protocol tree */
3122 proto_item_append_text( ti, ", Session: 0x%08X, %s", tvb_get_letohl( tvb, 4 ),
3123 val_to_str( encap_cmd, encap_cmd_vals, "Unknown Command (0x%04x)" ) );
3124
3125 /*
3126 ** For some commands we want to add some info to the info column
3127 */
3128 switch ( encap_cmd )
3129 {
3130 case REGISTER_SESSION:
3131 case UNREGISTER_SESSION:
3132 col_append_fstr( pinfo->cinfo, COL_INFO, ", Session: 0x%08X",
3133 tvb_get_letohl( tvb, 4 ) );
3134 break;
3135 }
3136
3137 /* Command specific data - create tree */
3138 if ( encap_data_length )
3139 {
3140 /* The packet have some command specific data, build a sub tree for it */
3141
3142 csftree = proto_tree_add_subtree( enip_tree, tvb, 24, encap_data_length,
3143 ett_command_tree, NULL, "Command Specific Data");
3144
3145 switch ( encap_cmd )
3146 {
3147 case NOP:
3148 break;
3149
3150 case LIST_SERVICES:
3151 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
3152 break;
3153
3154 case LIST_IDENTITY:
3155 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
3156 break;
3157
3158 case LIST_INTERFACES:
3159 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
3160 break;
3161
3162 case REGISTER_SESSION:
3163 proto_tree_add_item( csftree, hf_enip_rs_version, tvb, 24, 2, ENC_LITTLE_ENDIAN );
3164 proto_tree_add_item( csftree, hf_enip_rs_optionflags, tvb, 26, 2, ENC_LITTLE_ENDIAN );
3165 break;
3166
3167 case UNREGISTER_SESSION:
3168 break;
3169
3170 case SEND_RR_DATA:
3171 proto_tree_add_item( csftree, hf_enip_srrd_ifacehnd, tvb, 24, 4, ENC_LITTLE_ENDIAN );
3172 proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
3173
3174 ifacehndl = tvb_get_letohl( tvb, 24 );
3175 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 30, ifacehndl );
3176 break;
3177
3178 case SEND_UNIT_DATA:
3179 proto_tree_add_item(csftree, hf_enip_sud_ifacehnd, tvb, 24, 4, ENC_LITTLE_ENDIAN);
3180 proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
3181
3182 ifacehndl = tvb_get_letohl( tvb, 24 );
3183 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, ti, 30, ifacehndl );
3184
3185 break;
3186
3187 default:
3188
3189 /* Can not decode - Just show the data */
3190 proto_tree_add_item(header_tree, hf_enip_encap_data, tvb, 24, encap_data_length, ENC_NA);
3191 break;
3192
3193 } /* end of switch () */
3194
3195 } /* end of if ( encapsulated data ) */
3196
3197 col_set_fence(pinfo->cinfo, COL_INFO);
3198
3199 return tvb_captured_length(tvb);
3200 } /* end of dissect_enip_pdu() */
3201
3202 static int
dissect_enip_udp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3203 dissect_enip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3204 {
3205 /* An ENIP packet is at least 4 bytes long. */
3206 if (tvb_captured_length(tvb) < 4)
3207 return 0;
3208
3209 return dissect_enip_pdu(tvb, pinfo, tree, data);
3210 }
3211
3212 static int
dissect_enip_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3213 dissect_enip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3214 {
3215 // TCP connections for EtherNet/IP are typically open for extended periods of time.
3216 // This means that mostly likely, for real world traffic, a capture initiated for
3217 // EtherNet/IP traffic will start in the middle of a TCP connection. This check
3218 // ignores one byte TCP payloads because it is far more likely that a one byte TCP
3219 // payload is a TCP keep alive message, than a client actually sending real EtherNet/IP
3220 // messages in one byte chunks.
3221 if (tvb_captured_length(tvb) < 2)
3222 return 0;
3223
3224 tcp_dissect_pdus(tvb, pinfo, tree, enip_desegment, 4, get_enip_pdu_len, dissect_enip_pdu, data);
3225 return tvb_captured_length(tvb);
3226 }
3227
3228 /* Code to actually dissect the io packets*/
3229 static int
dissect_cipio(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3230 dissect_cipio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3231 {
3232 /* Set up structures needed to add the protocol subtree and manage it */
3233 proto_item *ti;
3234 proto_tree *enip_tree;
3235
3236 /* Make entries in Protocol column and Info column on summary display */
3237 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP I/O");
3238
3239 /* create display subtree for the protocol */
3240 ti = proto_tree_add_item(tree, proto_enip, tvb, 0, -1, ENC_NA );
3241
3242 enip_tree = proto_item_add_subtree(ti, ett_enip);
3243
3244 dissect_cpf( NULL, 0xFFFF, tvb, pinfo, enip_tree, tree, enip_tree, NULL, 0, 0 );
3245
3246 return tvb_captured_length(tvb);
3247 }
3248
3249
3250 static gboolean
dissect_dlr(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3251 dissect_dlr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3252 {
3253 proto_item *ti;
3254 proto_tree *dlr_tree;
3255 guint8 dlr_subtype;
3256 guint8 dlr_protover;
3257 guint8 dlr_frametype;
3258
3259 /* Make entries in Protocol column and Info column on summary display */
3260 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLR");
3261
3262 col_clear(pinfo->cinfo, COL_INFO);
3263
3264 /* Create display subtree for the protocol */
3265 ti = proto_tree_add_item(tree, proto_dlr, tvb, 0, -1, ENC_NA );
3266 dlr_tree = proto_item_add_subtree( ti, ett_dlr );
3267
3268 /* Get values for the Common Frame Header Format */
3269 dlr_subtype = tvb_get_guint8(tvb, DLR_CFH_SUB_TYPE);
3270 dlr_protover = tvb_get_guint8(tvb, DLR_CFH_PROTO_VERSION);
3271
3272 /* Dissect the Common Frame Header Format */
3273 proto_tree_add_uint( dlr_tree, hf_dlr_ringsubtype, tvb, DLR_CFH_SUB_TYPE, 1, dlr_subtype );
3274 proto_tree_add_uint( dlr_tree, hf_dlr_ringprotoversion, tvb, DLR_CFH_PROTO_VERSION, 1, dlr_protover );
3275
3276 /* Get values for the DLR Message Payload Fields */
3277 dlr_frametype = tvb_get_guint8(tvb, DLR_MPF_FRAME_TYPE);
3278
3279 /* Dissect the DLR Message Payload Fields */
3280 proto_tree_add_item( dlr_tree, hf_dlr_frametype, tvb, DLR_MPF_FRAME_TYPE, 1, ENC_BIG_ENDIAN );
3281 proto_tree_add_item( dlr_tree, hf_dlr_sourceport, tvb, DLR_MPF_SOURCE_PORT, 1, ENC_BIG_ENDIAN );
3282 proto_tree_add_item( dlr_tree, hf_dlr_sourceip, tvb, DLR_MPF_SOURCE_IP, 4, ENC_BIG_ENDIAN );
3283 proto_tree_add_item( dlr_tree, hf_dlr_sequenceid, tvb, DLR_MPF_SEQUENCE_ID, 4, ENC_BIG_ENDIAN );
3284
3285 /* Add frame type to col info */
3286 col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
3287 val_to_str(dlr_frametype, dlr_frame_type_vals, "Unknown (0x%04x)") );
3288
3289 if ( dlr_frametype == DLR_FT_BEACON )
3290 {
3291 /* Beacon */
3292 proto_tree_add_item( dlr_tree, hf_dlr_ringstate, tvb, DLR_BE_RING_STATE, 1, ENC_BIG_ENDIAN );
3293 proto_tree_add_item( dlr_tree, hf_dlr_supervisorprecedence, tvb, DLR_BE_SUPERVISOR_PRECEDENCE, 1, ENC_BIG_ENDIAN );
3294 proto_tree_add_item( dlr_tree, hf_dlr_beaconinterval, tvb, DLR_BE_BEACON_INTERVAL, 4, ENC_BIG_ENDIAN );
3295 proto_tree_add_item( dlr_tree, hf_dlr_beacontimeout, tvb, DLR_BE_BEACON_TIMEOUT, 4, ENC_BIG_ENDIAN );
3296 proto_tree_add_item( dlr_tree, hf_dlr_beaconreserved, tvb, DLR_BE_RESERVED, 20, ENC_NA );
3297 }
3298 else if ( dlr_frametype == DLR_FT_NEIGHBOR_REQ )
3299 {
3300 /* Neighbor_Check_Request */
3301 proto_tree_add_item( dlr_tree, hf_dlr_nreqreserved, tvb, DLR_NREQ_RESERVED, 30, ENC_NA );
3302 }
3303 else if ( dlr_frametype == DLR_FT_NEIGHBOR_RES )
3304 {
3305 /* Neighbor_Check_Response */
3306 proto_tree_add_item( dlr_tree, hf_dlr_nressourceport, tvb, DLR_NRES_SOURCE_PORT, 1, ENC_BIG_ENDIAN );
3307 proto_tree_add_item( dlr_tree, hf_dlr_nresreserved, tvb, DLR_NRES_RESERVED, 29, ENC_NA );
3308 }
3309 else if ( dlr_frametype == DLR_FT_LINK_STAT )
3310 {
3311 /* Link_Status/Neighbor_Status */
3312 static int* const bits[] = {
3313 &hf_dlr_lnknbrstatus_port1,
3314 &hf_dlr_lnknbrstatus_port2,
3315 &hf_dlr_lnknbrstatus_reserved,
3316 &hf_dlr_lnknbrstatus_frame_type,
3317 NULL
3318 };
3319
3320 proto_tree_add_bitmask(dlr_tree, tvb, DLR_LNS_SOURCE_PORT, hf_dlr_lnknbrstatus, ett_dlr_lnknbrstatus_flags, bits, ENC_LITTLE_ENDIAN);
3321
3322 proto_tree_add_item( dlr_tree, hf_dlr_lnknbrreserved, tvb, DLR_LNS_RESERVED, 29, ENC_NA );
3323 }
3324 else if ( dlr_frametype == DLR_FT_LOCATE_FLT )
3325 {
3326 /* Locate_Fault */
3327 proto_tree_add_item( dlr_tree, hf_dlr_lfreserved, tvb, DLR_LF_RESERVED, 30, ENC_NA );
3328 }
3329 else if ( dlr_frametype == DLR_FT_ANNOUNCE )
3330 {
3331 /* Announce */
3332 proto_tree_add_item( dlr_tree, hf_dlr_ringstate, tvb, DLR_AN_RING_STATE, 1, ENC_BIG_ENDIAN );
3333 proto_tree_add_item( dlr_tree, hf_dlr_anreserved, tvb, DLR_AN_RESERVED, 29, ENC_NA );
3334 }
3335 else if ( dlr_frametype == DLR_FT_SIGN_ON )
3336 {
3337 guint16 nCnt;
3338 guint16 nNumNodes;
3339 guint16 nOffset;
3340
3341
3342 /* Sign_On */
3343 nNumNodes = tvb_get_ntohs(tvb, DLR_SO_NUM_NODES);
3344
3345 proto_tree_add_uint( dlr_tree, hf_dlr_sonumnodes, tvb, DLR_SO_NUM_NODES, 2, nNumNodes );
3346
3347 /* Add each node in the list */
3348 for( nCnt = 0, nOffset = DLR_SO_NODE_1_MAC; nCnt < nNumNodes; nCnt++ )
3349 {
3350 proto_tree_add_item( dlr_tree, hf_dlr_somac, tvb, nOffset, 6, ENC_NA );
3351 nOffset += 6;
3352 proto_tree_add_item( dlr_tree, hf_dlr_soip, tvb, nOffset, 4, ENC_BIG_ENDIAN );
3353 nOffset += 4;
3354 }
3355
3356 if ( nOffset < 42 )
3357 {
3358 proto_tree_add_item( dlr_tree, hf_dlr_soreserved, tvb, nOffset, 42 - nOffset, ENC_NA );
3359 /* nOffset += (42 - nOffset); */
3360 }
3361 }
3362 else if ( dlr_frametype == DLR_FT_ADVERTISE )
3363 {
3364 /* Advertise */
3365 proto_tree_add_item( dlr_tree, hf_dlr_advgatewaystate, tvb, DLR_ADV_GATEWAY_STATE, 1, ENC_BIG_ENDIAN );
3366 proto_tree_add_item( dlr_tree, hf_dlr_advgatewayprecedence, tvb, DLR_ADV_GATEWAY_PRECEDENCE, 1, ENC_BIG_ENDIAN );
3367 proto_tree_add_item( dlr_tree, hf_dlr_advadvertiseinterval, tvb, DLR_ADV_ADVERTISE_INTERVAL, 4, ENC_BIG_ENDIAN );
3368 proto_tree_add_item( dlr_tree, hf_dlr_advadvertisetimeout, tvb, DLR_ADV_ADVERTISE_TIMEOUT, 4, ENC_BIG_ENDIAN );
3369 proto_tree_add_item( dlr_tree, hf_dlr_advlearningupdateenable, tvb, DLR_ADV_LEARNING_UPDATE_ENABLE, 1, ENC_BIG_ENDIAN );
3370 proto_tree_add_item( dlr_tree, hf_dlr_advreserved, tvb, DLR_ADV_RESERVED, 19, ENC_NA );
3371 }
3372 else if ( dlr_frametype == DLR_FT_FLUSH_TABLES )
3373 {
3374 proto_tree_add_item( dlr_tree, hf_dlr_flushlearningupdateenable, tvb, DLR_FLUSH_LEARNING_UPDATE_ENABLE, 1, ENC_BIG_ENDIAN );
3375 proto_tree_add_item( dlr_tree, hf_dlr_flushreserved, tvb, DLR_FLUSH_RESERVED, 29, ENC_NA );
3376 }
3377 else if ( dlr_frametype == DLR_FT_LEARNING_UPDATE )
3378 {
3379 proto_tree_add_item( dlr_tree, hf_dlr_learnreserved, tvb, DLR_LEARN_RESERVED, 34, ENC_NA );
3380 }
3381 else
3382 {
3383 /* Unknown Frame type */
3384 }
3385
3386 return tvb_captured_length(tvb);
3387
3388 } /* end of dissect_dlr() */
3389
dissect_cip_class1(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3390 static int dissect_cip_class1(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
3391 {
3392 cip_conn_info_t conn_info;
3393 memset(&conn_info, 0, sizeof(conn_info));
3394 conn_info.TransportClass_trigger = 1;
3395
3396 cip_io_data_input io_data_input;
3397 io_data_input.conn_info = &conn_info;
3398 io_data_input.connid_type = ECIDT_UNKNOWN;
3399
3400 return dissect_cip_io_generic(tvb, pinfo, tree, &io_data_input);
3401 }
3402
3403 /* Register the protocol with Wireshark */
3404
3405 /* this format is require because a script is used to build the C function
3406 that calls all the protocol registration.
3407 */
3408
3409 void
proto_register_enip(void)3410 proto_register_enip(void)
3411 {
3412 /* Setup list of header fields */
3413 static hf_register_info hf[] = {
3414 { &hf_enip_command,
3415 { "Command", "enip.command",
3416 FT_UINT16, BASE_HEX, VALS(encap_cmd_vals), 0,
3417 "Encapsulation command", HFILL }},
3418
3419 { &hf_enip_length,
3420 { "Length", "enip.length",
3421 FT_UINT16, BASE_DEC, NULL, 0,
3422 "Encapsulation length", HFILL }},
3423
3424 { &hf_enip_session,
3425 { "Session Handle", "enip.session",
3426 FT_UINT32, BASE_HEX, NULL, 0,
3427 "Session identification", HFILL }},
3428
3429 { &hf_enip_status,
3430 { "Status", "enip.status",
3431 FT_UINT32, BASE_HEX, VALS(encap_status_vals), 0,
3432 "Status code", HFILL }},
3433
3434 { &hf_enip_sendercontex,
3435 { "Sender Context", "enip.context",
3436 FT_BYTES, BASE_NONE, NULL, 0,
3437 "Information pertinent to the sender", HFILL }},
3438
3439 { &hf_enip_listid_delay,
3440 { "Max Response Delay", "enip.listid_delay",
3441 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0,
3442 "Maximum random delay allowed by target", HFILL }},
3443
3444 { &hf_enip_options,
3445 { "Options", "enip.options",
3446 FT_UINT32, BASE_HEX, NULL, 0,
3447 "Options flags", HFILL }},
3448
3449 { &hf_enip_encapver,
3450 { "Encapsulation Protocol Version", "enip.encapver",
3451 FT_UINT16, BASE_DEC, NULL, 0,
3452 NULL, HFILL }},
3453
3454 { &hf_enip_sinfamily,
3455 { "sin_family", "enip.sinfamily",
3456 FT_UINT16, BASE_DEC, NULL, 0,
3457 "Socket Address.Sin Family", HFILL }},
3458
3459 { &hf_enip_sinport,
3460 { "sin_port", "enip.sinport",
3461 FT_UINT16, BASE_DEC, NULL, 0,
3462 "Socket Address.Sin Port", HFILL }},
3463
3464 { &hf_enip_sinaddr,
3465 { "sin_addr", "enip.sinaddr",
3466 FT_IPv4, BASE_NONE, NULL, 0,
3467 "Socket Address.Sin Addr", HFILL }},
3468
3469 { &hf_enip_sinzero,
3470 { "sin_zero", "enip.sinzero",
3471 FT_BYTES, BASE_NONE, NULL, 0,
3472 "Socket Address.Sin Zero", HFILL }},
3473
3474 { &hf_enip_timeout,
3475 { "Timeout", "enip.timeout",
3476 FT_UINT16, BASE_DEC, NULL, 0,
3477 "Encapsulation Timeout", HFILL }},
3478
3479 { &hf_enip_encap_data,
3480 { "Encap Data", "enip.encap_data",
3481 FT_BYTES, BASE_NONE, NULL, 0,
3482 "Encapsulation Data", HFILL }},
3483
3484 /* List Services Reply */
3485 { &hf_enip_lsr_capaflags,
3486 { "Capability Flags", "enip.lsr.capaflags",
3487 FT_UINT16, BASE_HEX, NULL, 0,
3488 "ListServices Reply: Capability Flags", HFILL }},
3489
3490 { &hf_enip_lsr_tcp,
3491 { "Supports CIP Encapsulation via TCP", "enip.lsr.capaflags.tcp",
3492 FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0020,
3493 "ListServices Reply: Supports CIP Encapsulation via TCP", HFILL }},
3494
3495 { &hf_enip_lsr_udp,
3496 { "Supports CIP Class 0 or 1 via UDP", "enip.lsr.capaflags.udp",
3497 FT_BOOLEAN, 16, TFS(&tfs_true_false), 0x0100,
3498 "ListServices Reply: Supports CIP Class 0 or 1 via UDP", HFILL }},
3499
3500 { &hf_enip_lsr_servicename,
3501 { "Name of Service", "enip.lsr.servicename",
3502 FT_STRING, BASE_NONE, NULL, 0,
3503 "ListServices Reply: Name of Service", HFILL }},
3504
3505 /* Register Session */
3506 { &hf_enip_rs_version,
3507 { "Protocol Version", "enip.rs.version",
3508 FT_UINT16, BASE_DEC, NULL, 0,
3509 "Register Session: Protocol Version", HFILL }},
3510
3511 { &hf_enip_rs_optionflags,
3512 { "Option Flags", "enip.rs.flags",
3513 FT_UINT16, BASE_HEX, NULL, 0,
3514 "Register Session: Option Flags", HFILL }},
3515
3516 /* Send Request/Reply Data */
3517 { &hf_enip_srrd_ifacehnd,
3518 { "Interface Handle", "enip.srrd.iface",
3519 FT_UINT32, BASE_HEX, VALS(enip_interface_handle_vals), 0,
3520 "SendRRData: Interface handle", HFILL }},
3521
3522 /* Send Unit Data */
3523 { &hf_enip_sud_ifacehnd,
3524 { "Interface Handle", "enip.sud.iface",
3525 FT_UINT32, BASE_HEX, VALS(enip_interface_handle_vals), 0,
3526 "SendUnitData: Interface handle", HFILL }},
3527
3528 /* List identity reply */
3529 { &hf_enip_lir_vendor,
3530 { "Vendor ID", "enip.lir.vendor",
3531 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0,
3532 "ListIdentity Reply: Vendor ID", HFILL }},
3533
3534 { &hf_enip_lir_devtype,
3535 { "Device Type", "enip.lir.devtype",
3536 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &cip_devtype_vals_ext, 0,
3537 "ListIdentity Reply: Device Type", HFILL }},
3538
3539 { &hf_enip_lir_prodcode,
3540 { "Product Code", "enip.lir.prodcode",
3541 FT_UINT16, BASE_DEC, NULL, 0,
3542 "ListIdentity Reply: Product Code", HFILL }},
3543
3544 { &hf_enip_lir_revision,
3545 { "Revision", "enip.lir.revision",
3546 FT_UINT16, BASE_CUSTOM, CF_FUNC(enip_fmt_lir_revision), 0,
3547 "ListIdentity Reply: Revision", HFILL }},
3548
3549 { &hf_enip_lir_status,
3550 { "Status", "enip.lir.status",
3551 FT_UINT16, BASE_HEX, NULL, 0,
3552 "ListIdentity Reply: Status", HFILL }},
3553
3554 { &hf_enip_lir_serial,
3555 { "Serial Number", "enip.lir.serial",
3556 FT_UINT32, BASE_HEX, NULL, 0,
3557 "ListIdentity Reply: Serial Number", HFILL }},
3558
3559 { &hf_enip_lir_namelen,
3560 { "Product Name Length", "enip.lir.namelen",
3561 FT_UINT8, BASE_DEC, NULL, 0,
3562 "ListIdentity Reply: Product Name Length", HFILL }},
3563
3564 { &hf_enip_lir_name,
3565 { "Product Name", "enip.lir.name",
3566 FT_STRING, BASE_NONE, NULL, 0,
3567 "ListIdentity Reply: Product Name", HFILL }},
3568
3569 { &hf_enip_lir_state,
3570 { "State", "enip.lir.state",
3571 FT_UINT8, BASE_HEX, NULL, 0,
3572 "ListIdentity Reply: State", HFILL }},
3573
3574 { &hf_enip_security_profiles,
3575 { "Security Profiles", "enip.security_profiles",
3576 FT_UINT16, BASE_HEX, NULL, 0,
3577 NULL, HFILL }},
3578
3579 { &hf_enip_security_profiles_eip_integrity,
3580 { "EtherNet/IP Integrity Profile", "enip.security_profiles.eip_integrity",
3581 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0001,
3582 NULL, HFILL }},
3583
3584 { &hf_enip_security_profiles_eip_confidentiality,
3585 { "EtherNet/IP Confidentiality Profile", "enip.security_profiles.eip_confidentiality",
3586 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0002,
3587 NULL, HFILL }},
3588
3589 { &hf_enip_security_profiles_cip_authorization,
3590 { "CIP Authorization Profile", "enip.security_profiles.cip_authorization",
3591 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0004,
3592 NULL, HFILL }},
3593
3594 { &hf_enip_security_profiles_cip_user_authentication,
3595 { "CIP User Authentication Profile", "enip.security_profiles.cip_user_authentication",
3596 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0008,
3597 NULL, HFILL }},
3598
3599 { &hf_enip_security_profiles_resource_constrained,
3600 { "Resource-Constrained CIP Security Profile", "enip.security_profiles.resource_constrained",
3601 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0010,
3602 NULL, HFILL } },
3603
3604 { &hf_enip_security_profiles_reserved,
3605 { "Reserved", "enip.security_profiles.reserved",
3606 FT_UINT16, BASE_HEX, NULL, 0xFFE0,
3607 NULL, HFILL }},
3608
3609 { &hf_enip_cip_security_state,
3610 { "CIP Security State", "enip.cip_security_state",
3611 FT_UINT8, BASE_DEC, VALS(cip_security_state_vals), 0,
3612 NULL, HFILL }},
3613
3614 { &hf_enip_eip_security_state,
3615 { "EIP Security State", "enip.eip_security_state",
3616 FT_UINT8, BASE_DEC, VALS(eip_security_state_vals), 0,
3617 NULL, HFILL }},
3618
3619 { &hf_enip_iana_port_state_flags,
3620 { "IANA Port State", "enip.iana_port_state_flags",
3621 FT_UINT8, BASE_HEX, NULL, 0,
3622 NULL, HFILL }},
3623
3624 { &hf_enip_iana_port_state_flags_tcp_44818,
3625 { "44818/tcp", "enip.security_profiles.iana_port_state_flags.tcp_44818",
3626 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x01,
3627 NULL, HFILL }},
3628
3629 { &hf_enip_iana_port_state_flags_udp_44818,
3630 { "44818/udp", "enip.security_profiles.iana_port_state_flags.udp_44818",
3631 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x02,
3632 NULL, HFILL }},
3633
3634 { &hf_enip_iana_port_state_flags_udp_2222,
3635 { "2222/udp", "enip.security_profiles.iana_port_state_flags.udp_2222",
3636 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x04,
3637 NULL, HFILL }},
3638
3639 { &hf_enip_iana_port_state_flags_tcp_2221,
3640 { "2221/tcp", "enip.security_profiles.iana_port_state_flags.tcp_2221",
3641 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x08,
3642 NULL, HFILL }},
3643
3644 { &hf_enip_iana_port_state_flags_udp_2221,
3645 { "2221/udp", "enip.security_profiles.iana_port_state_flags.udp_2221",
3646 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x10,
3647 NULL, HFILL }},
3648
3649 { &hf_enip_iana_port_state_flags_reserved,
3650 { "Reserved", "enip.iana_port_state_flags.reserved",
3651 FT_UINT8, BASE_HEX, NULL, 0xE0,
3652 NULL, HFILL }},
3653
3654 /* Common Packet Format */
3655 { &hf_enip_cpf_itemcount,
3656 { "Item Count", "enip.cpf.itemcount",
3657 FT_UINT16, BASE_DEC, NULL, 0,
3658 "Common Packet Format: Item Count", HFILL }},
3659
3660 { &hf_enip_cpf_typeid,
3661 { "Type ID", "enip.cpf.typeid",
3662 FT_UINT16, BASE_HEX, VALS(cpf_type_vals), 0,
3663 "Common Packet Format: Type of encapsulated item", HFILL }},
3664
3665 { &hf_enip_cpf_length,
3666 { "Length", "enip.cpf.length",
3667 FT_UINT16, BASE_DEC, NULL, 0,
3668 "Common Packet Format: Length", HFILL }},
3669
3670 /* Connected Data Item */
3671 { &hf_cip_sequence_count,
3672 { "CIP Sequence Count", "cip.seq",
3673 FT_UINT16, BASE_DEC, NULL, 0,
3674 NULL, HFILL }},
3675
3676 /* Connection Address Item */
3677 { &hf_enip_cpf_cai_connid,
3678 { "Connection ID", "enip.cpf.cai.connid",
3679 FT_UINT32, BASE_HEX, NULL, 0,
3680 "Common Packet Format: Connection Address Item, Connection Identifier", HFILL }},
3681
3682 { &hf_enip_cpf_ucmm_request,
3683 { "Request/Response", "enip.cpf.ucmm.request",
3684 FT_UINT16, BASE_DEC, VALS(cip_sc_rr), 0x8000,
3685 "Common Packet Format: UCMM Request/Response", HFILL }},
3686
3687 { &hf_enip_cpf_ucmm_msg_type,
3688 { "Unconn Msg Type", "enip.cpf.ucmm.msg_type",
3689 FT_UINT16, BASE_DEC, VALS(unconn_msg_type_vals), 0x7FFF,
3690 "Common Packet Format: UCMM Transaction ID", HFILL }},
3691
3692 { &hf_enip_cpf_ucmm_trans_id,
3693 { "Transaction ID", "enip.cpf.ucmm.trans_id",
3694 FT_UINT32, BASE_HEX, NULL, 0,
3695 "Common Packet Format: UCMM Transaction ID", HFILL }},
3696
3697 { &hf_enip_cpf_ucmm_status,
3698 { "UCMM Status", "enip.cpf.ucmm.status",
3699 FT_UINT32, BASE_HEX, VALS(encap_status_vals), 0,
3700 "Common Packet Format: UCMM Status", HFILL }},
3701
3702 /* Sequenced Address Type */
3703 { &hf_enip_cpf_sai_connid,
3704 { "Connection ID", "enip.cpf.sai.connid",
3705 FT_UINT32, BASE_HEX, NULL, 0,
3706 "Common Packet Format: Sequenced Address Item, Connection Identifier", HFILL }},
3707 { &hf_cip_connid, { "Connection ID", "cip.connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
3708
3709 { &hf_enip_cpf_sai_seqnum,
3710 { "Encapsulation Sequence Number", "enip.cpf.sai.seq",
3711 FT_UINT32, BASE_DEC, NULL, 0,
3712 "Common Packet Format: Sequenced Address Item, Sequence Number", HFILL }},
3713
3714 { &hf_enip_cpf_data,
3715 { "Data", "enip.cpf.data",
3716 FT_BYTES, BASE_NONE, NULL, 0,
3717 "Common Packet Format: Unknown Data", HFILL }},
3718
3719 /* Request/Response Matching */
3720 { &hf_enip_response_in,
3721 { "Response In", "enip.response_in",
3722 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
3723 "The response to this ENIP request is in this frame", HFILL }},
3724
3725 { &hf_enip_response_to,
3726 { "Request In", "enip.response_to",
3727 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
3728 "This is a response to the ENIP request in this frame", HFILL }},
3729
3730 { &hf_enip_time,
3731 { "Time", "enip.time",
3732 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
3733 "The time between the Call and the Reply", HFILL }},
3734
3735 { &hf_enip_fwd_open_in,
3736 { "Forward Open Request In", "enip.fwd_open_in",
3737 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
3738
3739 // Generated API data.
3740 { &hf_cip_cm_ot_api, { "O->T API", "cip.cm.otapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL } },
3741 { &hf_cip_cm_to_api, { "T->O API", "cip.cm.toapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL } },
3742
3743 { &hf_cip_connection,
3744 { "CIP Connection Index", "cip.connection",
3745 FT_UINT32, BASE_DEC, NULL, 0x0,
3746 NULL, HFILL } },
3747
3748 { &hf_cip_io_data,
3749 { "Data", "cipio.data",
3750 FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x0,
3751 NULL, HFILL }},
3752
3753 { &hf_tcpip_status,
3754 { "Status", "cip.tcpip.status",
3755 FT_UINT32, BASE_HEX, NULL, 0,
3756 NULL, HFILL }},
3757
3758 { &hf_tcpip_status_interface_config,
3759 { "Interface Configuration Status", "cip.tcpip.status.interface_config",
3760 FT_UINT32, BASE_DEC, VALS(enip_tcpip_status_interface_config_vals), 0x0000000F,
3761 NULL, HFILL }},
3762
3763 { &hf_tcpip_status_mcast_pending,
3764 { "MCast Pending", "cip.tcpip.status.mcast_pending",
3765 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000010,
3766 NULL, HFILL }},
3767
3768 { &hf_tcpip_status_interface_config_pending,
3769 { "Interface Configuration Pending", "cip.tcpip.status.interface_config_pending",
3770 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000020,
3771 NULL, HFILL }},
3772
3773 { &hf_tcpip_status_acd,
3774 { "ACD Status", "cip.tcpip.status.acd",
3775 FT_UINT32, BASE_DEC, VALS(enip_tcpip_status_acd_vals), 0x00000040,
3776 NULL, HFILL }},
3777
3778 { &hf_tcpip_acd_fault,
3779 { "ACD Fault", "cip.tcpip.status.acd_fault",
3780 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000080,
3781 NULL, HFILL }},
3782
3783 { &hf_tcpip_status_iana_port_admin_change,
3784 { "IANA Port Admin Change Pending", "cip.tcpip.status.iana_port_admin",
3785 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000100,
3786 NULL, HFILL }},
3787
3788 { &hf_tcpip_status_iana_protocol_admin_change,
3789 { "IANA Protocol Admin Change Pending", "cip.tcpip.status.iana_protocol_admin",
3790 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000200,
3791 NULL, HFILL }},
3792
3793 { &hf_tcpip_status_reserved,
3794 { "Reserved", "cip.tcpip.status.reserved",
3795 FT_UINT32, BASE_HEX, NULL, 0xFFFFFC00,
3796 NULL, HFILL }},
3797
3798 { &hf_tcpip_config_cap,
3799 { "Configuration Capability", "cip.tcpip.config_cap",
3800 FT_UINT32, BASE_HEX, NULL, 0,
3801 NULL, HFILL }},
3802
3803 { &hf_tcpip_config_cap_bootp,
3804 { "BOOTP Client", "cip.tcpip.config_cap.bootp",
3805 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000001,
3806 NULL, HFILL }},
3807
3808 { &hf_tcpip_config_cap_dns,
3809 { "DNS Client", "cip.tcpip.config_cap.dns",
3810 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000002,
3811 NULL, HFILL }},
3812
3813 { &hf_tcpip_config_cap_dhcp,
3814 { "DHCP Client", "cip.tcpip.config_cap.dhcp",
3815 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000004,
3816 NULL, HFILL }},
3817
3818 { &hf_tcpip_config_cap_dhcp_dns_update,
3819 { "DHCP-DNS Update", "cip.tcpip.config_cap.dhcp_dns_update",
3820 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000008,
3821 NULL, HFILL }},
3822
3823 { &hf_tcpip_config_cap_config_settable,
3824 { "Configuration Settable", "cip.tcpip.config_cap.config_settable",
3825 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000010,
3826 NULL, HFILL }},
3827
3828 { &hf_tcpip_config_cap_hardware_config,
3829 { "Hardware Configurable", "cip.tcpip.config_cap.hardware_config",
3830 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000020,
3831 NULL, HFILL }},
3832
3833 { &hf_tcpip_config_cap_interface_reset,
3834 { "Interface Configuration Change Requires Reset", "cip.tcpip.config_cap.interface_reset",
3835 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000040,
3836 NULL, HFILL }},
3837
3838 { &hf_tcpip_config_cap_acd,
3839 { "ACD Capable", "cip.tcpip.config_cap.acd",
3840 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000080,
3841 NULL, HFILL }},
3842
3843 { &hf_tcpip_config_cap_reserved,
3844 { "Reserved", "cip.tcpip.config_cap.reserved",
3845 FT_UINT32, BASE_HEX, NULL, 0xFFFFFF00,
3846 NULL, HFILL }},
3847
3848 { &hf_tcpip_config_control,
3849 { "Configuration Control", "cip.tcpip.config_control",
3850 FT_UINT32, BASE_HEX, NULL, 0,
3851 NULL, HFILL }},
3852
3853 { &hf_tcpip_config_control_config,
3854 { "Configuration Method", "cip.tcpip.config_control.config",
3855 FT_UINT32, BASE_DEC, VALS(enip_tcpip_config_control_config_vals), 0x0000000F,
3856 NULL, HFILL }},
3857
3858 { &hf_tcpip_config_control_dns,
3859 { "DNS Enable", "cip.tcpip.config_control.dns",
3860 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000010,
3861 NULL, HFILL }},
3862
3863 { &hf_tcpip_config_control_reserved,
3864 { "Reserved", "cip.tcpip.config_control.reserved",
3865 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFE0,
3866 NULL, HFILL }},
3867
3868 { &hf_tcpip_ic_ip_addr,
3869 { "IP Address", "cip.tcpip.ip_addr",
3870 FT_IPv4, BASE_NONE, NULL, 0,
3871 NULL, HFILL }},
3872
3873 { &hf_tcpip_ic_subnet_mask,
3874 { "Subnet Mask", "cip.tcpip.subnet_mask",
3875 FT_IPv4, BASE_NETMASK, NULL, 0,
3876 NULL, HFILL }},
3877
3878 { &hf_tcpip_ic_gateway,
3879 { "Gateway", "cip.tcpip.gateway",
3880 FT_IPv4, BASE_NONE, NULL, 0,
3881 NULL, HFILL }},
3882
3883 { &hf_tcpip_ic_name_server,
3884 { "Name Server", "cip.tcpip.name_server",
3885 FT_IPv4, BASE_NONE, NULL, 0,
3886 NULL, HFILL }},
3887
3888 { &hf_tcpip_ic_name_server2,
3889 { "Name Server2", "cip.tcpip.name_server2",
3890 FT_IPv4, BASE_NONE, NULL, 0,
3891 NULL, HFILL }},
3892
3893 { &hf_tcpip_ic_domain_name,
3894 { "Domain Name", "cip.tcpip.domain_name",
3895 FT_STRING, BASE_NONE, NULL, 0,
3896 NULL, HFILL }},
3897
3898 { &hf_tcpip_hostname,
3899 { "Hostname", "cip.tcpip.hostname",
3900 FT_STRING, BASE_NONE, NULL, 0,
3901 NULL, HFILL }},
3902
3903 { &hf_tcpip_snn_timestamp,
3904 { "Safety Network Number (Timestamp)", "cip.tcpip.snn.timestamp",
3905 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
3906 NULL, HFILL }
3907 },
3908
3909 { &hf_tcpip_snn_date,
3910 { "Safety Network Number (Manual) Date", "cip.tcpip.snn.date",
3911 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0,
3912 NULL, HFILL }
3913 },
3914
3915 { &hf_tcpip_snn_time,
3916 { "Safety Network Number (Manual) Time", "cip.tcpip.snn.time",
3917 FT_UINT32, BASE_HEX, NULL, 0,
3918 NULL, HFILL }
3919 },
3920
3921 { &hf_tcpip_ttl_value,
3922 { "TTL Value", "cip.tcpip.ttl_value",
3923 FT_UINT8, BASE_DEC, NULL, 0,
3924 NULL, HFILL }},
3925
3926 { &hf_tcpip_mcast_alloc,
3927 { "Alloc Control", "cip.tcpip.mcast.alloc",
3928 FT_UINT8, BASE_DEC, VALS(enip_tcpip_mcast_alloc_vals), 0,
3929 NULL, HFILL }},
3930
3931 { &hf_tcpip_mcast_reserved,
3932 { "Reserved", "cip.tcpip.mcast.reserved",
3933 FT_UINT8, BASE_HEX, NULL, 0,
3934 NULL, HFILL }},
3935
3936 { &hf_tcpip_mcast_num_mcast,
3937 { "Num MCast", "cip.tcpip.mcast.num_mcast",
3938 FT_UINT16, BASE_DEC, NULL, 0,
3939 NULL, HFILL }},
3940
3941 { &hf_tcpip_mcast_addr_start,
3942 { "MCast Start Addr", "cip.tcpip.mcast.addr_start",
3943 FT_IPv4, BASE_NONE, NULL, 0,
3944 NULL, HFILL }},
3945
3946 { &hf_tcpip_select_acd,
3947 { "Select ACD", "cip.tcpip.select_acd",
3948 FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0,
3949 NULL, HFILL }},
3950
3951 { &hf_tcpip_lcd_acd_activity,
3952 { "ACD Activity", "cip.tcpip.last_conflict.acd_activity",
3953 FT_UINT8, BASE_DEC, VALS(enip_tcpip_acd_activity_vals), 0,
3954 NULL, HFILL }},
3955
3956 { &hf_tcpip_lcd_remote_mac,
3957 { "RemoteMAC", "cip.tcpip.last_conflict.remote_mac",
3958 FT_ETHER, BASE_NONE, NULL, 0,
3959 NULL, HFILL }},
3960
3961 { &hf_tcpip_lcd_arp_pdu,
3962 { "Arp PDU", "cip.tcpip.last_conflict.arp_pdu",
3963 FT_BYTES, BASE_NONE, NULL, 0,
3964 NULL, HFILL }},
3965
3966 { &hf_tcpip_quick_connect,
3967 { "Ethernet/IP Quick Connection", "cip.tcpip.quick_connect",
3968 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x1,
3969 NULL, HFILL }},
3970
3971 { &hf_tcpip_encap_inactivity,
3972 { "Encapsulation Inactivity Timeout", "cip.tcpip.encap_inactivity",
3973 FT_UINT16, BASE_DEC, NULL, 0x0,
3974 NULL, HFILL }},
3975
3976 { &hf_tcpip_port_count, { "Port Count", "cip.tcpip.port_count", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
3977 { &hf_tcpip_port_name, { "Port Name", "cip.tcpip.port_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
3978 { &hf_tcpip_port_number, { "Port Number", "cip.tcpip.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
3979 { &hf_tcpip_port_protocol, { "Protocol", "cip.tcpip.protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0, NULL, HFILL } },
3980 { &hf_tcpip_port_admin_state, { "Admin State", "cip.tcpip.admin_state", FT_BOOLEAN, BASE_NONE, TFS(&tfs_open_closed), 0, NULL, HFILL } },
3981
3982 { &hf_tcpip_port_admin_capability, { "Admin Capability", "cip.tcpip.admin_capability", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
3983 { &hf_tcpip_admin_capability_configurable, { "Configurable", "cip.tcpip.admin_capability.configurable", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL } },
3984 { &hf_tcpip_admin_capability_reset_required, { "Reset Required", "cip.tcpip.admin_capability.reset_required", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x02, NULL, HFILL } },
3985 { &hf_tcpip_admin_capability_reserved, { "Reserved", "cip.tcpip.admin_capability", FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL } },
3986
3987 { &hf_elink_interface_speed,
3988 { "Interface Speed", "cip.elink.interface_speed",
3989 FT_UINT32, BASE_DEC, NULL, 0,
3990 NULL, HFILL }},
3991
3992 { &hf_elink_interface_flags,
3993 { "Interface Flags", "cip.elink.iflags",
3994 FT_UINT32, BASE_HEX, NULL, 0,
3995 NULL, HFILL }},
3996
3997 { &hf_elink_iflags_link_status,
3998 { "Link Status", "cip.elink.iflags.link_status",
3999 FT_BOOLEAN, 32, TFS(&tfs_active_inactive), 0x00000001,
4000 NULL, HFILL }},
4001
4002 { &hf_elink_iflags_duplex,
4003 { "Duplex", "cip.elink.iflags.duplex",
4004 FT_UINT32, BASE_DEC, VALS(enip_elink_duplex_vals), 0x00000002,
4005 NULL, HFILL }},
4006
4007 { &hf_elink_iflags_neg_status,
4008 { "Negotiation Status", "cip.elink.iflags.neg_status",
4009 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_neg_status_vals), 0x0000001C,
4010 NULL, HFILL }},
4011
4012 { &hf_elink_iflags_manual_reset,
4013 { "Manual Reset Required", "cip.elink.iflags.manual_reset",
4014 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_reset_vals), 0x00000020,
4015 NULL, HFILL }},
4016
4017 { &hf_elink_iflags_local_hw_fault,
4018 { "Local Hardware Fault", "cip.elink.iflags.local_hw_fault",
4019 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_hw_fault_vals), 0x00000040,
4020 NULL, HFILL }},
4021
4022 { &hf_elink_iflags_reserved,
4023 { "Reserved", "cip.elink.iflags.reserved",
4024 FT_UINT32, BASE_HEX, NULL, 0xFFFFFF80,
4025 NULL, HFILL }},
4026
4027 { &hf_elink_physical_address,
4028 { "Physical Address", "cip.elink.physical_address",
4029 FT_ETHER, BASE_NONE, NULL, 0,
4030 NULL, HFILL }},
4031
4032 { &hf_elink_icount_in_octets,
4033 { "In Octets", "cip.elink.icount.in_octets",
4034 FT_UINT32, BASE_DEC, NULL, 0,
4035 NULL, HFILL }},
4036
4037 { &hf_elink_icount_in_ucast,
4038 { "In Ucast Packets", "cip.elink.icount.in_ucast",
4039 FT_UINT32, BASE_DEC, NULL, 0,
4040 NULL, HFILL }},
4041
4042 { &hf_elink_icount_in_nucast,
4043 { "In NUcast Packets", "cip.elink.icount.in_nucast",
4044 FT_UINT32, BASE_DEC, NULL, 0,
4045 NULL, HFILL }},
4046
4047 { &hf_elink_icount_in_discards,
4048 { "In Discards", "cip.elink.icount.in_discards",
4049 FT_UINT32, BASE_DEC, NULL, 0,
4050 NULL, HFILL }},
4051
4052 { &hf_elink_icount_in_errors,
4053 { "In Errors", "cip.elink.icount.in_errors",
4054 FT_UINT32, BASE_DEC, NULL, 0,
4055 NULL, HFILL }},
4056
4057 { &hf_elink_icount_in_unknown_protos,
4058 { "In Unknown Protos", "cip.elink.icount.in_unknown_protos",
4059 FT_UINT32, BASE_DEC, NULL, 0,
4060 NULL, HFILL }},
4061
4062 { &hf_elink_icount_out_octets,
4063 { "Out Octets", "cip.elink.icount.out_octets",
4064 FT_UINT32, BASE_DEC, NULL, 0,
4065 NULL, HFILL }},
4066
4067 { &hf_elink_icount_out_ucast,
4068 { "Out Ucast Packets", "cip.elink.icount.out_ucast",
4069 FT_UINT32, BASE_DEC, NULL, 0,
4070 NULL, HFILL }},
4071
4072 { &hf_elink_icount_out_nucast,
4073 { "Out NUcast Packets", "cip.elink.icount.out_nucast",
4074 FT_UINT32, BASE_DEC, NULL, 0,
4075 NULL, HFILL }},
4076
4077 { &hf_elink_icount_out_discards,
4078 { "Out Discards", "cip.elink.icount.out_discards",
4079 FT_UINT32, BASE_DEC, NULL, 0,
4080 NULL, HFILL }},
4081
4082 { &hf_elink_icount_out_errors,
4083 { "Out Errors", "cip.elink.icount.out_errors",
4084 FT_UINT32, BASE_DEC, NULL, 0,
4085 NULL, HFILL }},
4086
4087 { &hf_elink_mcount_alignment_errors,
4088 { "Alignment Errors", "cip.elink.mcount.alignment_errors",
4089 FT_UINT32, BASE_DEC, NULL, 0,
4090 NULL, HFILL }},
4091
4092 { &hf_elink_mcount_fcs_errors,
4093 { "FCS Errors", "cip.elink.mcount.fcs_errors",
4094 FT_UINT32, BASE_DEC, NULL, 0,
4095 NULL, HFILL }},
4096
4097 { &hf_elink_mcount_single_collisions,
4098 { "Single Collisions", "cip.elink.mcount.single_collisions",
4099 FT_UINT32, BASE_DEC, NULL, 0,
4100 NULL, HFILL }},
4101
4102 { &hf_elink_mcount_multiple_collisions,
4103 { "Multiple Collisions", "cip.elink.mcount.multiple_collisions",
4104 FT_UINT32, BASE_DEC, NULL, 0,
4105 NULL, HFILL }},
4106
4107 { &hf_elink_mcount_sqe_test_errors,
4108 { "SQE Test Errors", "cip.elink.mcount.sqe_test_errors",
4109 FT_UINT32, BASE_DEC, NULL, 0,
4110 NULL, HFILL }},
4111
4112 { &hf_elink_mcount_deferred_transmission,
4113 { "Deferred Transmission", "cip.elink.mcount.deferred_transmission",
4114 FT_UINT32, BASE_DEC, NULL, 0,
4115 NULL, HFILL }},
4116
4117 { &hf_elink_mcount_late_collisions,
4118 { "Late Collisions", "cip.elink.mcount.late_collisions",
4119 FT_UINT32, BASE_DEC, NULL, 0,
4120 NULL, HFILL }},
4121
4122 { &hf_elink_mcount_excessive_collisions,
4123 { "Excessive Collisions", "cip.elink.mcount.excessive_collisions",
4124 FT_UINT32, BASE_DEC, NULL, 0,
4125 NULL, HFILL }},
4126
4127 { &hf_elink_mcount_mac_transmit_errors,
4128 { "MAC Transmit Errors", "cip.elink.mcount.mac_transmit_errors",
4129 FT_UINT32, BASE_DEC, NULL, 0,
4130 NULL, HFILL }},
4131
4132 { &hf_elink_mcount_carrier_sense_errors,
4133 { "Carrier Sense Errors", "cip.elink.mcount.carrier_sense_errors",
4134 FT_UINT32, BASE_DEC, NULL, 0,
4135 NULL, HFILL }},
4136
4137 { &hf_elink_mcount_frame_too_long,
4138 { "Frame Too Long", "cip.elink.mcount.frame_too_long",
4139 FT_UINT32, BASE_DEC, NULL, 0,
4140 NULL, HFILL }},
4141
4142 { &hf_elink_mcount_mac_receive_errors,
4143 { "MAC Receive Errors", "cip.elink.mcount.mac_receive_errors",
4144 FT_UINT32, BASE_DEC, NULL, 0,
4145 NULL, HFILL }},
4146
4147 { &hf_elink_icontrol_control_bits,
4148 { "Control Bits", "cip.elink.icontrol.control_bits",
4149 FT_UINT16, BASE_HEX, NULL, 0,
4150 NULL, HFILL }},
4151
4152 { &hf_elink_icontrol_control_bits_auto_neg,
4153 { "Auto-negotiate", "cip.elink.icontrol.control_bits.auto_neg",
4154 FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), 0x0001,
4155 NULL, HFILL }},
4156
4157 { &hf_elink_icontrol_control_bits_forced_duplex,
4158 { "Forced Duplex Mode", "cip.elink.icontrol.control_bits.forced_duplex",
4159 FT_UINT16, BASE_DEC, VALS(enip_elink_duplex_vals), 0x0002,
4160 NULL, HFILL }},
4161
4162 { &hf_elink_icontrol_control_bits_reserved,
4163 { "Reserved", "cip.elink.icontrol.control_bits.reserved",
4164 FT_UINT16, BASE_HEX, NULL, 0xFFFC,
4165 NULL, HFILL }},
4166
4167 { &hf_elink_icontrol_forced_speed,
4168 { "Forced Interface Speed", "cip.elink.icontrol.forced_speed",
4169 FT_UINT16, BASE_DEC, NULL, 0,
4170 NULL, HFILL }},
4171
4172 { &hf_elink_icapability_capability_bits,
4173 { "Capability Bits", "cip.elink.icapability.capability_bits",
4174 FT_UINT32, BASE_HEX, NULL, 0,
4175 NULL, HFILL }},
4176
4177 { &hf_elink_icapability_capability_bits_manual,
4178 { "Manual Setting Requires Reset", "cip.elink.icapability.capability_bits.manual",
4179 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x0001,
4180 NULL, HFILL }},
4181
4182 { &hf_elink_icapability_capability_bits_auto_neg,
4183 { "Auto-negotiate", "cip.elink.icapability.capability_bits.auto_neg",
4184 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x0002,
4185 NULL, HFILL }},
4186
4187 { &hf_elink_icapability_capability_bits_auto_mdix,
4188 { "Auto-MDIX", "cip.elink.icapability.capability_bits.auto_mdix",
4189 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x0004,
4190 NULL, HFILL } },
4191
4192 { &hf_elink_icapability_capability_bits_manual_speed,
4193 { "Manual Speed/Duplex", "cip.elink.icapability.capability_bits.manual_speed",
4194 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x0008,
4195 NULL, HFILL } },
4196
4197 { &hf_elink_icapability_capability_speed_duplex_array_count,
4198 { "Speed/Duplex Array Count", "cip.elink.icapability.array_count",
4199 FT_UINT8, BASE_DEC, NULL, 0,
4200 NULL, HFILL } },
4201
4202 { &hf_elink_icapability_capability_speed,
4203 { "Interface Speed", "cip.elink.icapability.speed",
4204 FT_UINT16, BASE_DEC, NULL, 0,
4205 NULL, HFILL } },
4206
4207 { &hf_elink_icapability_capability_duplex,
4208 { "Interface Duplex Mode", "cip.elink.icapability.duplex",
4209 FT_UINT8, BASE_DEC, VALS(enip_elink_duplex_vals), 0,
4210 NULL, HFILL } },
4211
4212 { &hf_elink_interface_type,
4213 { "Interface Type", "cip.elink.interface_type",
4214 FT_UINT8, BASE_DEC, VALS(enip_elink_interface_type_vals), 0,
4215 NULL, HFILL }},
4216
4217 { &hf_elink_interface_state,
4218 { "Interface State", "cip.elink.interface_state",
4219 FT_UINT8, BASE_DEC, VALS(enip_elink_interface_state_vals), 0,
4220 NULL, HFILL }},
4221
4222 { &hf_elink_admin_state,
4223 { "Admin State", "cip.elink.admin_state",
4224 FT_UINT8, BASE_DEC, VALS(enip_elink_admin_state_vals), 0,
4225 NULL, HFILL }},
4226
4227 { &hf_elink_interface_label,
4228 { "Interface Label", "cip.elink.interface_label",
4229 FT_STRING, BASE_NONE, NULL, 0,
4230 NULL, HFILL }},
4231
4232 { &hf_elink_hc_icount_in_octets,
4233 { "In Octets", "cip.elink.hc_icount.in_octets",
4234 FT_UINT64, BASE_DEC, NULL, 0,
4235 NULL, HFILL } },
4236
4237 { &hf_elink_hc_icount_in_ucast,
4238 { "In Ucast Packets", "cip.elink.hc_icount.in_ucast",
4239 FT_UINT64, BASE_DEC, NULL, 0,
4240 NULL, HFILL } },
4241
4242 { &hf_elink_hc_icount_in_mcast,
4243 { "In Multicast Packets", "cip.elink.hc_icount.in_mcast",
4244 FT_UINT64, BASE_DEC, NULL, 0,
4245 NULL, HFILL } },
4246
4247 { &hf_elink_hc_icount_in_broadcast,
4248 { "In Broadcast", "cip.elink.hc_icount.in_broadcast",
4249 FT_UINT64, BASE_DEC, NULL, 0,
4250 NULL, HFILL } },
4251
4252 { &hf_elink_hc_icount_out_octets,
4253 { "Out Octets", "cip.elink.hc_icount.out_octets",
4254 FT_UINT64, BASE_DEC, NULL, 0,
4255 NULL, HFILL } },
4256
4257 { &hf_elink_hc_icount_out_ucast,
4258 { "Out Ucast Packets", "cip.elink.hc_icount.out_ucast",
4259 FT_UINT64, BASE_DEC, NULL, 0,
4260 NULL, HFILL } },
4261
4262 { &hf_elink_hc_icount_out_mcast,
4263 { "Out Multicast Packets", "cip.elink.hc_icount.out_mcast",
4264 FT_UINT64, BASE_DEC, NULL, 0,
4265 NULL, HFILL } },
4266
4267 { &hf_elink_hc_icount_out_broadcast,
4268 { "Out Broadcast Packets", "cip.elink.hc_icount.out_broadcast",
4269 FT_UINT64, BASE_DEC, NULL, 0,
4270 NULL, HFILL } },
4271
4272 { &hf_elink_hc_mcount_stats_align_errors,
4273 { "Stats Alignment Errors", "cip.elink.hc_mcount.stats_align_errors",
4274 FT_UINT64, BASE_DEC, NULL, 0,
4275 NULL, HFILL } },
4276
4277 { &hf_elink_hc_mcount_stats_fcs_errors,
4278 { "Stats FCS Errors", "cip.elink.hc_mcount.stats_fcs_errors",
4279 FT_UINT64, BASE_DEC, NULL, 0,
4280 NULL, HFILL } },
4281
4282 { &hf_elink_hc_mcount_stats_internal_mac_transmit_errors,
4283 { "Stats Internal MAC Transmit Errors", "cip.elink.hc_mcount.internal_mac_transmit_errors",
4284 FT_UINT64, BASE_DEC, NULL, 0,
4285 NULL, HFILL } },
4286
4287 { &hf_elink_hc_mcount_stats_frame_too_long,
4288 { "Stats Frame Too Long", "cip.elink.hc_mcount.stats_frame_too_long",
4289 FT_UINT64, BASE_DEC, NULL, 0,
4290 NULL, HFILL } },
4291
4292 { &hf_elink_hc_mcount_stats_internal_mac_receive_errors,
4293 { "Stats Internal MAC Receive Errors", "cip.elink.hc_mcount.internal_mac_receive_errors",
4294 FT_UINT64, BASE_DEC, NULL, 0,
4295 NULL, HFILL } },
4296
4297 { &hf_elink_hc_mcount_stats_symbol_errors,
4298 { "Stats Symbol Errors", "cip.elink.hc_mcount.stats_symbol_errors",
4299 FT_UINT64, BASE_DEC, NULL, 0,
4300 NULL, HFILL } },
4301
4302 { &hf_qos_8021q_enable,
4303 { "802.1Q Tag Enable", "cip.qos.8021q_enable",
4304 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x1,
4305 NULL, HFILL }},
4306
4307 { &hf_qos_dscp_ptp_event,
4308 { "DSCP PTP Event", "cip.qos.ptp_event",
4309 FT_UINT8, BASE_DEC, NULL, 0,
4310 NULL, HFILL }},
4311
4312 { &hf_qos_dscp_ptp_general,
4313 { "DSCP PTP General", "cip.qos.ptp_general",
4314 FT_UINT8, BASE_DEC, NULL, 0,
4315 NULL, HFILL }},
4316
4317 { &hf_qos_dscp_urgent,
4318 { "DSCP Urgent", "cip.qos.urgent",
4319 FT_UINT8, BASE_DEC, NULL, 0,
4320 NULL, HFILL }},
4321
4322 { &hf_qos_dscp_scheduled,
4323 { "DSCP Scheduled", "cip.qos.scheduled",
4324 FT_UINT8, BASE_DEC, NULL, 0,
4325 NULL, HFILL }},
4326
4327 { &hf_qos_dscp_high,
4328 { "DSCP High", "cip.qos.high",
4329 FT_UINT8, BASE_DEC, NULL, 0,
4330 NULL, HFILL }},
4331
4332 { &hf_qos_dscp_low,
4333 { "DSCP Low", "cip.qos.low",
4334 FT_UINT8, BASE_DEC, NULL, 0,
4335 NULL, HFILL }},
4336
4337 { &hf_qos_dscp_explicit,
4338 { "DSCP Explicit", "cip.qos.explicit",
4339 FT_UINT8, BASE_DEC, NULL, 0,
4340 NULL, HFILL }},
4341
4342 { &hf_dlr_network_topology,
4343 { "Network Topology", "cip.dlr.network_topology",
4344 FT_UINT8, BASE_DEC, VALS(enip_dlr_network_topology_vals), 0,
4345 NULL, HFILL }},
4346
4347 { &hf_dlr_network_status,
4348 { "Network Status", "cip.dlr.network_status",
4349 FT_UINT8, BASE_DEC, VALS(enip_dlr_network_status_vals), 0,
4350 NULL, HFILL }},
4351
4352 { &hf_dlr_ring_supervisor_status,
4353 { "Ring Supervisor Status", "cip.dlr.ring_supervisor_status",
4354 FT_UINT8, BASE_DEC, VALS(enip_dlr_ring_supervisor_status_vals), 0,
4355 NULL, HFILL }},
4356
4357 { &hf_dlr_rsc_ring_supervisor_enable,
4358 { "Ring Supervisor Enable", "cip.dlr.rscconfig.supervisor_enable",
4359 FT_BOOLEAN, 8, TFS(&tfs_true_false), 0,
4360 NULL, HFILL }},
4361
4362 { &hf_dlr_rsc_ring_supervisor_precedence,
4363 { "Ring Supervisor Precedence", "cip.dlr.rscconfig.supervisor_precedence",
4364 FT_UINT8, BASE_DEC, NULL, 0,
4365 NULL, HFILL }},
4366
4367 { &hf_dlr_rsc_beacon_interval,
4368 { "Beacon Interval", "cip.dlr.rscconfig.beacon_interval",
4369 FT_UINT32, BASE_DEC, NULL, 0,
4370 NULL, HFILL }},
4371
4372 { &hf_dlr_rsc_beacon_timeout,
4373 { "Beacon Timeout", "cip.dlr.rscconfig.beacon_timeout",
4374 FT_UINT32, BASE_DEC, NULL, 0,
4375 NULL, HFILL }},
4376
4377 { &hf_dlr_rsc_dlr_vlan_id,
4378 { "DLR VLAN ID", "cip.dlr.rscconfig.dlr_vlan_id",
4379 FT_UINT16, BASE_DEC, NULL, 0,
4380 NULL, HFILL }},
4381
4382 { &hf_dlr_ring_faults_count,
4383 { "Ring Faults Count", "cip.dlr.ring_faults_count",
4384 FT_UINT16, BASE_DEC, NULL, 0,
4385 NULL, HFILL }},
4386
4387 { &hf_dlr_lanp1_dev_ip_addr,
4388 { "Device IP Address", "cip.dlr.lanp1.ip_addr",
4389 FT_IPv4, BASE_NONE, NULL, 0,
4390 NULL, HFILL }},
4391
4392 { &hf_dlr_lanp1_dev_physical_address,
4393 { "Device Physical Address", "cip.dlr.lanp1.physical_address",
4394 FT_ETHER, BASE_NONE, NULL, 0,
4395 NULL, HFILL }},
4396
4397 { &hf_dlr_lanp2_dev_ip_addr,
4398 { "Device IP Address", "cip.dlr.lanp2.ip_addr",
4399 FT_IPv4, BASE_NONE, NULL, 0,
4400 NULL, HFILL }},
4401
4402 { &hf_dlr_lanp2_dev_physical_address,
4403 { "Device Physical Address", "cip.dlr.lanp2.physical_address",
4404 FT_ETHER, BASE_NONE, NULL, 0,
4405 NULL, HFILL }},
4406
4407 { &hf_dlr_ring_protocol_participants_count,
4408 { "Participants Count", "cip.dlr.participants_count",
4409 FT_UINT16, BASE_DEC, NULL, 0,
4410 NULL, HFILL }},
4411
4412 { &hf_dlr_rppl_dev_ip_addr,
4413 { "Device IP Address", "cip.dlr.rppl.ip_addr",
4414 FT_IPv4, BASE_NONE, NULL, 0,
4415 NULL, HFILL }},
4416
4417 { &hf_dlr_rppl_dev_physical_address,
4418 { "Device Physical Address", "cip.dlr.rppl.physical_address",
4419 FT_ETHER, BASE_NONE, NULL, 0,
4420 NULL, HFILL }},
4421
4422 { &hf_dlr_asa_supervisor_ip_addr,
4423 { "Supervisor IP Address", "cip.dlr.asa.ip_addr",
4424 FT_IPv4, BASE_NONE, NULL, 0,
4425 NULL, HFILL }},
4426
4427 { &hf_dlr_asa_supervisor_physical_address,
4428 { "Supervisor Physical Address", "cip.dlr.asa.physical_address",
4429 FT_ETHER, BASE_NONE, NULL, 0,
4430 NULL, HFILL }},
4431
4432 { &hf_dlr_active_supervisor_precedence,
4433 { "Active Supervisor Precedence", "cip.dlr.supervisor_precedence",
4434 FT_UINT8, BASE_DEC, NULL, 0,
4435 NULL, HFILL }},
4436
4437 { &hf_dlr_capability_flags,
4438 { "Capability Flags", "cip.dlr.capflags",
4439 FT_UINT32, BASE_HEX, NULL, 0,
4440 NULL, HFILL }},
4441
4442 { &hf_dlr_capflags_announce_base_node,
4443 { "Announce-based Ring Node", "cip.dlr.capflags.announce_based",
4444 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000001,
4445 NULL, HFILL }},
4446
4447 { &hf_dlr_capflags_beacon_base_node,
4448 { "Beacon-based Ring Node", "cip.dlr.capflags.beacon_based",
4449 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000002,
4450 NULL, HFILL }},
4451
4452 { &hf_dlr_capflags_reserved1,
4453 { "Reserved", "cip.dlr.capflags.reserved1",
4454 FT_BOOLEAN, 32, NULL, 0x0000001C,
4455 NULL, HFILL }},
4456
4457 { &hf_dlr_capflags_supervisor_capable,
4458 { "Supervisor Capable", "cip.dlr.capflags.supervisor_capable",
4459 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000020,
4460 NULL, HFILL }},
4461
4462 { &hf_dlr_capflags_redundant_gateway_capable,
4463 { "Redundant Gateway Capable", "cip.dlr.capflags.redundant_gateway_capable",
4464 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000040,
4465 NULL, HFILL }},
4466
4467 { &hf_dlr_capflags_flush_frame_capable,
4468 { "Flush_Table Frame Capable", "cip.dlr.capflags.flush_frame_capable",
4469 FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x00000080,
4470 NULL, HFILL }},
4471
4472 { &hf_dlr_capflags_reserved2,
4473 { "Reserved", "cip.dlr.capflags.reserved2",
4474 FT_BOOLEAN, 32, NULL, 0xFFFFFF00,
4475 NULL, HFILL }},
4476
4477 { &hf_dlr_rgc_red_gateway_enable,
4478 { "Redundant Gateway Enable", "cip.dlr.rgc.gateway_enable",
4479 FT_BOOLEAN, 8, TFS(&tfs_true_false), 0,
4480 NULL, HFILL }},
4481
4482 { &hf_dlr_rgc_gateway_precedence,
4483 { "Gateway Precedence", "cip.dlr.rgc.gateway_precedence",
4484 FT_UINT8, BASE_DEC, NULL, 0,
4485 NULL, HFILL }},
4486
4487 { &hf_dlr_rgc_advertise_interval,
4488 { "Advertise Interval", "cip.dlr.rgc.advertise_interval",
4489 FT_UINT32, BASE_DEC, NULL, 0,
4490 NULL, HFILL }},
4491
4492 { &hf_dlr_rgc_advertise_timeout,
4493 { "Advertise Timeout", "cip.dlr.rgc.advertise_timeout",
4494 FT_UINT32, BASE_DEC, NULL, 0,
4495 NULL, HFILL }},
4496
4497 { &hf_dlr_rgc_learning_update_enable,
4498 { "Learning Update Enable", "cip.dlr.rgc.learning_update_enable",
4499 FT_BOOLEAN, 8, TFS(&tfs_true_false), 0,
4500 NULL, HFILL }},
4501
4502 { &hf_dlr_redundant_gateway_status,
4503 { "Redundant Gateway Status", "cip.dlr.redundant_gateway_status",
4504 FT_UINT8, BASE_DEC, VALS(enip_dlr_redundant_gateway_status_vals), 0,
4505 NULL, HFILL }},
4506
4507 { &hf_dlr_aga_ip_addr,
4508 { "Active Gateway IP Address", "cip.dlr.aga.ip_addr",
4509 FT_IPv4, BASE_NONE, NULL, 0,
4510 NULL, HFILL }},
4511
4512 { &hf_dlr_aga_physical_address,
4513 { "Active Gateway Physical Address", "cip.dlr.aga.physical_address",
4514 FT_ETHER, BASE_NONE, NULL, 0,
4515 NULL, HFILL }},
4516
4517 { &hf_dlr_active_gateway_precedence,
4518 { "Active Gateway Precedence", "cip.dlr.active_gateway_precedence",
4519 FT_UINT8, BASE_DEC, NULL, 0,
4520 NULL, HFILL }},
4521
4522 { &hf_cip_security_state, { "State", "cip.security.state", FT_UINT8, BASE_DEC, VALS(cip_security_state_vals), 0, NULL, HFILL } },
4523
4524 { &hf_eip_security_state,
4525 { "State", "cip.eip_security.state",
4526 FT_UINT8, BASE_DEC, VALS(eip_security_state_vals), 0,
4527 NULL, HFILL }},
4528
4529 { &hf_eip_security_verify_client_cert,
4530 { "Verify Client Certificate", "cip.eip_security.verify_client_cert",
4531 FT_BOOLEAN, 8, NULL, 0,
4532 NULL, HFILL }},
4533
4534 { &hf_eip_security_send_cert_chain,
4535 { "Send Certificate Chain", "cip.eip_security.send_cert_chain",
4536 FT_BOOLEAN, 8, NULL, 0,
4537 NULL, HFILL }},
4538
4539 { &hf_eip_security_check_expiration,
4540 { "Check Expiration", "cip.eip_security.check_expiration",
4541 FT_BOOLEAN, 8, NULL, 0,
4542 NULL, HFILL }},
4543
4544 { &hf_eip_security_capability_flags,
4545 { "Capability Flags", "cip.eip_security.capability_flags",
4546 FT_UINT32, BASE_HEX, NULL, 0,
4547 NULL, HFILL }},
4548
4549 { &hf_eip_security_capflags_secure_renegotiation,
4550 { "Secure Renegotiation", "cip.eip_security.capability_flags.secure_renegotiation",
4551 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000001,
4552 NULL, HFILL }},
4553
4554 { &hf_eip_security_capflags_reserved,
4555 { "Reserved", "cip.eip_security.capability_flags.reserved",
4556 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFE,
4557 NULL, HFILL }},
4558
4559 { &hf_eip_security_num_avail_cipher_suites,
4560 { "Number of Available Cipher Suites", "cip.eip_security.num_avail_cipher_suites",
4561 FT_UINT8, BASE_DEC, NULL, 0,
4562 NULL, HFILL }},
4563
4564 { &hf_eip_security_avail_cipher_suite,
4565 { "Available Cipher Suite", "cip.eip_security.avail_cipher_suite",
4566 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0,
4567 NULL, HFILL }},
4568
4569 { &hf_eip_security_num_allow_cipher_suites,
4570 { "Number of Allowed Cipher Suites", "cip.eip_security.num_allow_cipher_suites",
4571 FT_UINT8, BASE_DEC, NULL, 0,
4572 NULL, HFILL }},
4573
4574 { &hf_eip_security_allow_cipher_suite,
4575 { "Allowed Cipher Suite", "cip.eip_security.allow_cipher_suite",
4576 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0,
4577 NULL, HFILL }},
4578
4579 { &hf_eip_security_num_psk,
4580 { "Number of PSKs", "cip.eip_security.num_psk",
4581 FT_UINT8, BASE_DEC, NULL, 0,
4582 NULL, HFILL }},
4583
4584 { &hf_eip_security_psk_identity_size,
4585 { "PSK Identity Size", "cip.eip_security.psk_identity_size",
4586 FT_UINT8, BASE_DEC, NULL, 0,
4587 NULL, HFILL }},
4588
4589 { &hf_eip_security_psk_identity,
4590 { "PSK Identity", "cip.eip_security.psk_identity",
4591 FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0,
4592 NULL, HFILL }},
4593
4594 { &hf_eip_security_psk_size,
4595 { "PSK Size", "cip.eip_security.psk_size",
4596 FT_UINT8, BASE_DEC, NULL, 0,
4597 NULL, HFILL }},
4598
4599 { &hf_eip_security_psk,
4600 { "PSK", "cip.eip_security.psk",
4601 FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0,
4602 NULL, HFILL }},
4603
4604 { &hf_eip_security_num_active_certs,
4605 { "Number of Active Certificates", "cip.eip_security.num_active_certs",
4606 FT_UINT8, BASE_DEC, NULL, 0,
4607 NULL, HFILL }},
4608
4609 { &hf_eip_security_num_trusted_auths,
4610 { "Number of Trusted Authorities", "cip.eip_security.num_trusted_auths",
4611 FT_UINT8, BASE_DEC, NULL, 0,
4612 NULL, HFILL }},
4613
4614 { &hf_eip_cert_name,
4615 { "Name", "cip.eip_cert.name",
4616 FT_STRING, BASE_NONE, NULL, 0,
4617 NULL, HFILL }},
4618
4619 { &hf_eip_cert_state,
4620 { "State", "cip.eip_cert.state",
4621 FT_UINT8, BASE_DEC, VALS(eip_cert_state_vals), 0,
4622 NULL, HFILL }},
4623
4624 { &hf_eip_cert_encoding,
4625 { "Certificate Encoding", "cip.eip_cert.encoding",
4626 FT_UINT8, BASE_DEC, NULL, 0,
4627 NULL, HFILL } },
4628
4629 { &hf_eip_cert_device_cert_status,
4630 { "Certificate Status", "cip.eip_cert.device_cert.status",
4631 FT_UINT8, BASE_DEC, VALS(eip_cert_status_vals), 0,
4632 NULL, HFILL }},
4633
4634 { &hf_eip_cert_ca_cert_status,
4635 { "Certificate Status", "cip.eip_cert.ca_cert.status",
4636 FT_UINT8, BASE_DEC, VALS(eip_cert_status_vals), 0,
4637 NULL, HFILL }},
4638
4639 { &hf_eip_cert_capflags_push,
4640 { "Push", "cip.eip_cert.capflags.push",
4641 FT_BOOLEAN, 32, NULL, 0x00000001,
4642 NULL, HFILL }},
4643
4644 { &hf_eip_cert_capflags_reserved,
4645 { "Reserved", "cip.eip_cert.capflags.reserved",
4646 FT_BOOLEAN, 32, NULL, 0xFFFFFFFE,
4647 NULL, HFILL }},
4648
4649 { &hf_eip_cert_capability_flags,
4650 { "Capability flags", "cip.eip_cert.capflags",
4651 FT_UINT32, BASE_HEX, NULL, 0,
4652 NULL, HFILL }},
4653
4654 { &hf_eip_cert_num_certs,
4655 { "Number of Certificates", "cip.eip_cert.num_certs",
4656 FT_UINT8, BASE_DEC, NULL, 0,
4657 NULL, HFILL }},
4658
4659 { &hf_eip_cert_cert_name,
4660 { "Certificate name", "cip.eip_cert.cert_name",
4661 FT_STRING, BASE_NONE, NULL, 0,
4662 NULL, HFILL }},
4663 };
4664
4665 /* Setup protocol subtree array */
4666 static gint *ett[] = {
4667 &ett_enip,
4668 &ett_cip_io_generic,
4669 &ett_path,
4670 &ett_count_tree,
4671 &ett_type_tree,
4672 &ett_command_tree,
4673 &ett_sockadd,
4674 &ett_lsrcf,
4675 &ett_tcpip_status,
4676 &ett_tcpip_admin_capability,
4677 &ett_tcpip_config_cap,
4678 &ett_tcpip_config_control,
4679 &ett_elink_interface_flags,
4680 &ett_elink_icontrol_bits,
4681 &ett_elink_icapability_bits,
4682 &ett_dlr_capability_flags,
4683 &ett_dlr_lnknbrstatus_flags,
4684 &ett_eip_security_capability_flags,
4685 &ett_eip_security_psk,
4686 &ett_eip_security_active_certs,
4687 &ett_eip_security_trusted_auths,
4688 &ett_eip_cert_capability_flags,
4689 &ett_eip_cert_num_certs,
4690 &ett_security_profiles,
4691 &ett_iana_port_state_flags,
4692 &ett_connection_info,
4693 &ett_connection_path_info,
4694 &ett_cmd_data
4695 };
4696
4697 static ei_register_info ei[] = {
4698 { &ei_mal_tcpip_status, { "cip.malformed.tcpip.status", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Status", EXPFILL }},
4699 { &ei_mal_tcpip_config_cap, { "cip.malformed.tcpip.config_cap", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Configuration Capability", EXPFILL }},
4700 { &ei_mal_tcpip_config_control, { "cip.malformed.tcpip.config_control", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Configuration Control", EXPFILL }},
4701 { &ei_mal_tcpip_interface_config, { "cip.malformed.tcpip.interface_config", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Interface Configuration", EXPFILL }},
4702 { &ei_mal_tcpip_snn, { "cip.malformed.tcpip.snn", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Object Safety Network Number", EXPFILL }},
4703 { &ei_mal_tcpip_mcast_config, { "cip.malformed.tcpip.mcast_config", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Multicast Config", EXPFILL }},
4704 { &ei_mal_tcpip_last_conflict, { "cip.malformed.tcpip.last_conflict", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Last Conflict Detected", EXPFILL }},
4705 { &ei_mal_elink_interface_flags, { "cip.malformed.elink.interface_flags", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Flags", EXPFILL }},
4706 { &ei_mal_elink_physical_address, { "cip.malformed.elink.physical_address", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Physical Address", EXPFILL } },
4707 { &ei_mal_elink_interface_counters, { "cip.malformed.elink.interface_counters", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Counters", EXPFILL }},
4708 { &ei_mal_elink_media_counters, { "cip.malformed.elink.media_counters", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Media Counters", EXPFILL }},
4709 { &ei_mal_elink_interface_control, { "cip.malformed.elink.interface_control", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Control", EXPFILL }},
4710 { &ei_mal_dlr_ring_supervisor_config, { "cip.malformed.dlr.ring_supervisor_config", PI_MALFORMED, PI_ERROR, "Malformed DLR Ring Supervisor Config", EXPFILL }},
4711 { &ei_mal_dlr_last_active_node_on_port_1, { "cip.malformed.dlr.last_active_node_on_port_1", PI_MALFORMED, PI_ERROR, "Malformed DLR Last Active Node on Port 1", EXPFILL }},
4712 { &ei_mal_dlr_last_active_node_on_port_2, { "cip.malformed.dlr.last_active_node_on_port_2", PI_MALFORMED, PI_ERROR, "Malformed DLR Last Active Node on Port 2", EXPFILL }},
4713 { &ei_mal_dlr_ring_protocol_participants_list, { "cip.malformed.dlr.ring_protocol_participants_list", PI_MALFORMED, PI_ERROR, "Malformed DLR Ring Protocol Participants List", EXPFILL }},
4714 { &ei_mal_dlr_active_supervisor_address, { "cip.malformed.dlr.active_supervisor_address", PI_MALFORMED, PI_ERROR, "Malformed DLR Active Supervisor Address", EXPFILL }},
4715 { &ei_mal_dlr_capability_flags, { "cip.malformed.dlr.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed DLR Capability Flag", EXPFILL }},
4716 { &ei_mal_dlr_redundant_gateway_config, { "cip.malformed.dlr.redundant_gateway_config", PI_MALFORMED, PI_ERROR, "Malformed DLR Redundant Gateway Config", EXPFILL }},
4717 { &ei_mal_dlr_active_gateway_address, { "cip.malformed.dlr.active_gateway_address", PI_MALFORMED, PI_ERROR, "Malformed DLR Active Gateway Address", EXPFILL }},
4718 { &ei_mal_eip_security_capability_flags, { "cip.malformed.eip_security.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Capability Flags", EXPFILL }},
4719 { &ei_mal_eip_security_avail_cipher_suites, { "cip.malformed.eip_security.avail_cipher_suites", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Available Cipher Suites", EXPFILL }},
4720 { &ei_mal_eip_security_allow_cipher_suites, { "cip.malformed.eip_security.allow_cipher_suites", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Allowed Cipher Suites", EXPFILL }},
4721 { &ei_mal_eip_security_preshared_keys, { "cip.malformed.eip_security.preshared_keys", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Pre-Shared Keys", EXPFILL }},
4722 { &ei_mal_eip_security_active_certs, { "cip.malformed.eip_security.active_certs", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Active Device Certificates", EXPFILL }},
4723 { &ei_mal_eip_security_trusted_auths, { "cip.malformed.eip_security.trusted_auths", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Trusted Authorities", EXPFILL }},
4724 { &ei_mal_eip_cert_capability_flags, { "cip.malformed.eip_cert.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed EIP Certificate Management Capability Flags", EXPFILL }},
4725 { &ei_mal_cpf_item_length_mismatch, { "enip.malformed.cpf_item_length_mismatch", PI_MALFORMED, PI_ERROR, "CPF Item Length Mismatch", EXPFILL } },
4726 { &ei_mal_cpf_item_minimum_size, { "enip.malformed.cpf_item_minimum_size", PI_MALFORMED, PI_ERROR, "CPF Item Minimum Size is 4", EXPFILL } },
4727 };
4728
4729 /* Setup list of header fields for DLR See Section 1.6.1 for details*/
4730 static hf_register_info hfdlr[] = {
4731 /* Ring Sub-type */
4732 { &hf_dlr_ringsubtype,
4733 { "Ring Sub-Type", "enip.dlr.ringsubtype",
4734 FT_UINT8, BASE_HEX, NULL, 0,
4735 NULL, HFILL }
4736 },
4737 /* Ring Protocol Version */
4738 { &hf_dlr_ringprotoversion,
4739 { "Ring Protocol Version", "enip.dlr.protversion",
4740 FT_UINT8, BASE_DEC, NULL, 0,
4741 NULL, HFILL }
4742 },
4743 /* Frame Type */
4744 { &hf_dlr_frametype,
4745 { "Frame Type", "enip.dlr.frametype",
4746 FT_UINT8, BASE_HEX, VALS(dlr_frame_type_vals), 0,
4747 NULL, HFILL }
4748 },
4749 /* Source Port */
4750 { &hf_dlr_sourceport,
4751 { "Source Port", "enip.dlr.sourceport",
4752 FT_UINT8, BASE_HEX, VALS(dlr_source_port_vals), 0,
4753 NULL, HFILL }
4754 },
4755 /* Source IP Address */
4756 { &hf_dlr_sourceip,
4757 { "Source IP", "enip.dlr.sourceip",
4758 FT_IPv4, BASE_NONE, NULL, 0,
4759 "Source IP Address", HFILL }
4760 },
4761 /* Sequence ID*/
4762 { &hf_dlr_sequenceid,
4763 { "Sequence Id", "enip.dlr.seqid",
4764 FT_UINT32, BASE_HEX, NULL, 0,
4765 NULL, HFILL }
4766 },
4767 /* Ring State */
4768 { &hf_dlr_ringstate,
4769 { "Ring State", "enip.dlr.state",
4770 FT_UINT8, BASE_HEX, VALS(dlr_ring_state_vals), 0,
4771 NULL, HFILL }
4772 },
4773 /* Supervisor Precedence */
4774 { &hf_dlr_supervisorprecedence,
4775 { "Supervisor Precedence", "enip.dlr.supervisorprecedence",
4776 FT_UINT8, BASE_DEC, NULL, 0,
4777 NULL, HFILL }
4778 },
4779 /* Beacon Interval */
4780 { &hf_dlr_beaconinterval,
4781 { "Beacon Interval", "enip.dlr.beaconinterval",
4782 FT_UINT32, BASE_DEC, NULL, 0,
4783 NULL, HFILL }
4784 },
4785 /* Beacon Timeout */
4786 { &hf_dlr_beacontimeout,
4787 { "Beacon Timeout", "enip.dlr.beacontimeout",
4788 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_microseconds, 0,
4789 NULL, HFILL }
4790 },
4791 /* Beacon Reserved */
4792 { &hf_dlr_beaconreserved,
4793 { "Reserved", "enip.dlr.beaconreserved",
4794 FT_BYTES, BASE_NONE, NULL, 0,
4795 "Beacon Reserved", HFILL }
4796 },
4797 /* Neighbor_Check_Request Reserved */
4798 { &hf_dlr_nreqreserved,
4799 { "Reserved", "enip.dlr.nreqreserved",
4800 FT_BYTES, BASE_NONE, NULL, 0,
4801 "Neighbor_Check_Request Reserved", HFILL }
4802 },
4803 /* Neighbor_Check_Response Source Port */
4804 { &hf_dlr_nressourceport,
4805 { "Request Source Port", "enip.dlr.nressourceport",
4806 FT_UINT8, BASE_HEX, VALS(dlr_source_port_vals), 0,
4807 "Neighbor_Check_Response Source Port", HFILL }
4808 },
4809 /* Neighbor_Check_Response Reserved */
4810 { &hf_dlr_nresreserved,
4811 { "Reserved", "enip.dlr.nresreserved",
4812 FT_BYTES, BASE_NONE, NULL, 0,
4813 "Neighbor_Check_Response Reserved", HFILL }
4814 },
4815 /* Link_Status/Neighbor_Status Status */
4816 { &hf_dlr_lnknbrstatus,
4817 { "Link/Neighbor Status", "enip.dlr.lnknbrstatus.status",
4818 FT_UINT8, BASE_HEX, NULL, 0,
4819 "Link_Status/Neighbor_Status Status", HFILL }
4820 },
4821 { &hf_dlr_lnknbrstatus_port1,
4822 { "Port 1 Active", "enip.dlr.lnknbrstatus.port1",
4823 FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01,
4824 NULL, HFILL }
4825 },
4826 { &hf_dlr_lnknbrstatus_port2,
4827 { "Port 2 Active", "enip.dlr.lnknbrstatus.port2",
4828 FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x02,
4829 NULL, HFILL }
4830 },
4831 { &hf_dlr_lnknbrstatus_reserved,
4832 { "Reserved", "enip.dlr.lnknbrstatus.reserved",
4833 FT_BOOLEAN, 8, NULL, 0x7C,
4834 NULL, HFILL }
4835 },
4836 { &hf_dlr_lnknbrstatus_frame_type,
4837 { "Link/Neighbor Status Frame Type", "enip.dlr.lnknbrstatus.frame_type",
4838 FT_BOOLEAN, 8, TFS(&dlr_lnknbrstatus_frame_type_vals), 0x80,
4839 NULL, HFILL }
4840 },
4841 /* Link_Status/Neighbor_Status Reserved */
4842 { &hf_dlr_lnknbrreserved,
4843 { "Reserved", "enip.dlr.lnknbrreserved",
4844 FT_BYTES, BASE_NONE, NULL, 0,
4845 "Link_Status/Neighbor_Status Reserved", HFILL }
4846 },
4847 /* Locate_Fault Reserved */
4848 { &hf_dlr_lfreserved,
4849 { "Reserved", "enip.dlr.lfreserved",
4850 FT_BYTES, BASE_NONE, NULL, 0,
4851 "Locate_Fault Reserved", HFILL }
4852 },
4853 /* Announce Reserved */
4854 { &hf_dlr_anreserved,
4855 { "Reserved", "enip.dlr.anreserved",
4856 FT_BYTES, BASE_NONE, NULL, 0,
4857 "Announce Reserved", HFILL }
4858 },
4859 /* Number of Nodes in List */
4860 { &hf_dlr_sonumnodes,
4861 { "Num nodes", "enip.dlr.sonumnodes",
4862 FT_UINT16, BASE_DEC, NULL, 0,
4863 "Number of Nodes in List", HFILL }
4864 },
4865 /* Sign_On Node # MAC Address */
4866 { &hf_dlr_somac,
4867 { "MAC Address", "enip.dlr.somac",
4868 FT_ETHER, BASE_NONE, NULL, 0,
4869 "Sign_On Node MAC Address", HFILL }
4870 },
4871 /* Node # IP Address */
4872 { &hf_dlr_soip,
4873 { "IP Address", "enip.dlr.soip",
4874 FT_IPv4, BASE_NONE, NULL, 0,
4875 "Sign_On Node IP Address", HFILL }
4876 },
4877 /* Sign_On Reserved */
4878 { &hf_dlr_soreserved,
4879 { "Reserved", "enip.dlr.soreserved",
4880 FT_BYTES, BASE_NONE, NULL, 0,
4881 "Sign_On Reserved", HFILL }
4882 },
4883 /* Gateway State */
4884 { &hf_dlr_advgatewaystate,
4885 { "Gateway Status", "enip.dlr.advgatewaystate",
4886 FT_UINT8, BASE_HEX, VALS(dlr_adv_state_vals), 0,
4887 "Gateway State", HFILL }
4888 },
4889 /* Gateway Precedence */
4890 { &hf_dlr_advgatewayprecedence,
4891 { "Gateway Precedence", "enip.dlr.advgatewayprecedence",
4892 FT_UINT8, BASE_DEC, NULL, 0,
4893 NULL, HFILL }
4894 },
4895 /* Advertise Interval */
4896 { &hf_dlr_advadvertiseinterval,
4897 { "Advertise Interval", "enip.dlr.advadvertiseinterval",
4898 FT_UINT32, BASE_DEC, NULL, 0,
4899 NULL, HFILL }
4900 },
4901 /* Advertise Timeout */
4902 { &hf_dlr_advadvertisetimeout,
4903 { "Advertise Interval", "enip.dlr.advadvertisetimeout",
4904 FT_UINT32, BASE_DEC, NULL, 0,
4905 NULL, HFILL }
4906 },
4907 /* Learning Update Enable */
4908 { &hf_dlr_advlearningupdateenable,
4909 { "Learning Update Enable", "enip.dlr.advlearningupdateenable",
4910 FT_UINT8, BASE_HEX, VALS(dlr_adv_learning_update_vals), 0,
4911 "Advertise Learning Update Enable", HFILL }
4912 },
4913 /* Advertise Reserved */
4914 { &hf_dlr_advreserved,
4915 { "Reserved", "enip.dlr.advreserved",
4916 FT_BYTES, BASE_NONE, NULL, 0,
4917 "Advertise Reserved", HFILL }
4918 },
4919 /* Flush_Tables Learning Update Enable */
4920 { &hf_dlr_flushlearningupdateenable,
4921 { "Learning Update Enable", "enip.dlr.flushlearningupdateenable",
4922 FT_UINT8, BASE_HEX, VALS(dlr_flush_learning_update_vals), 0,
4923 "Flush_Tables Learning Update Enable", HFILL }
4924 },
4925 /* Flush Reserved */
4926 { &hf_dlr_flushreserved,
4927 { "Reserved", "enip.dlr.flushreserved",
4928 FT_BYTES, BASE_NONE, NULL, 0,
4929 "Flush_Tables Reserved", HFILL }
4930 },
4931 /* Learning_Update Reserved */
4932 { &hf_dlr_learnreserved,
4933 { "Reserved", "enip.dlr.learnreserved",
4934 FT_BYTES, BASE_NONE, NULL, 0,
4935 "Learning_Update Reserved", HFILL }
4936 }
4937 };
4938
4939 /* Setup protocol subtree array for DLR */
4940 static gint *ettdlr[] = {
4941 &ett_dlr
4942 };
4943
4944 module_t *enip_module;
4945 expert_module_t* expert_enip;
4946
4947 /* Register the protocol name and description */
4948 proto_enip = proto_register_protocol("EtherNet/IP (Industrial Protocol)", "ENIP", "enip");
4949 proto_cipio = proto_register_protocol("Common Industrial Protocol, I/O", "CIP I/O", "cipio");
4950 proto_cip_class1 = proto_register_protocol_in_name_only(
4951 "Common Industrial Protocol, I/O Class 1",
4952 "CIP Class 1",
4953 "cipio1",
4954 proto_cipio,
4955 FT_PROTOCOL);
4956
4957 enip_tcp_handle = register_dissector("enip", dissect_enip_tcp, proto_enip);
4958 cipio_handle = register_dissector("cipio", dissect_cipio, proto_cipio);
4959 cip_class1_handle = register_dissector("cipio_class1", dissect_cip_class1, proto_cip_class1);
4960 cip_io_generic_handle = register_dissector("cipgenericio", dissect_cip_io_generic, proto_cipio);
4961
4962 /* Required function calls to register the header fields and subtrees used */
4963 proto_register_field_array(proto_enip, hf, array_length(hf));
4964 proto_register_subtree_array(ett, array_length(ett));
4965
4966 expert_enip = expert_register_protocol(proto_enip);
4967 expert_register_field_array(expert_enip, ei, array_length(ei));
4968
4969 enip_module = prefs_register_protocol(proto_enip, NULL);
4970 prefs_register_bool_preference(enip_module, "desegment",
4971 "Desegment all EtherNet/IP messages spanning multiple TCP segments",
4972 "Whether the EtherNet/IP dissector should desegment all messages spanning multiple TCP segments",
4973 &enip_desegment);
4974
4975 prefs_register_bool_preference(enip_module, "o2t_run_idle",
4976 "Dissect 32-bit header in the O->T direction",
4977 "Determines whether all I/O connections will assume a 32-bit header in the O->T direction",
4978 &enip_OTrun_idle);
4979
4980 prefs_register_bool_preference(enip_module, "t2o_run_idle",
4981 "Dissect 32-bit header in the T->O direction",
4982 "Determines whether all I/O connections will assume a 32-bit header in the T->O direction",
4983 &enip_TOrun_idle);
4984
4985 prefs_register_obsolete_preference(enip_module, "default_io_dissector");
4986
4987 subdissector_srrd_table = register_dissector_table("enip.srrd.iface",
4988 "ENIP SendRequestReplyData.Interface Handle", proto_enip, FT_UINT32, BASE_HEX);
4989
4990 subdissector_io_table = register_dissector_table("cip.io.iface",
4991 "CIP Class 0/1 Interface Handle", proto_cipio, FT_UINT32, BASE_HEX);
4992
4993 subdissector_cip_connection_table = register_dissector_table("cip.connection.class",
4994 "CIP Class 2/3 Interface Handle", proto_enip, FT_UINT32, BASE_HEX);
4995
4996 enip_request_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), enip_request_hash, enip_request_equal);
4997 enip_conn_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), enip_conn_hash, enip_conn_equal);
4998
4999 register_init_routine(&enip_init_protocol);
5000
5001 /* Register the protocol name and description */
5002 proto_dlr = proto_register_protocol("Device Level Ring", "DLR", "dlr");
5003
5004 /* Required function calls to register the header fields and subtrees used */
5005 proto_register_field_array(proto_dlr, hfdlr, array_length(hfdlr));
5006 proto_register_subtree_array(ettdlr, array_length(ettdlr));
5007
5008 register_conversation_filter("enip", "CIP Connection", cip_connection_conv_valid, cip_connection_conv_filter);
5009
5010 subdissector_decode_as_io_table = register_decode_as_next_proto(proto_enip, "cip.io", "CIP I/O Payload", enip_prompt);
5011 } /* end of proto_register_enip() */
5012
5013
5014 void
proto_reg_handoff_enip(void)5015 proto_reg_handoff_enip(void)
5016 {
5017 dissector_handle_t enip_udp_handle;
5018 dissector_handle_t dlr_handle;
5019
5020 /* Register for EtherNet/IP, using TCP */
5021 dissector_add_uint_with_preference("tcp.port", ENIP_ENCAP_PORT, enip_tcp_handle);
5022
5023 /* Register for EtherNet/IP, using UDP */
5024 enip_udp_handle = create_dissector_handle(dissect_enip_udp, proto_enip);
5025 dissector_add_uint_with_preference("udp.port", ENIP_ENCAP_PORT, enip_udp_handle);
5026
5027 /* Register for EtherNet/IP IO data (UDP) */
5028 dissector_add_uint_with_preference("udp.port", ENIP_IO_PORT, cipio_handle);
5029
5030 /* Register for EtherNet/IP TLS */
5031 ssl_dissector_add(ENIP_SECURE_PORT, enip_tcp_handle);
5032 dtls_dissector_add(ENIP_SECURE_PORT, cipio_handle);
5033
5034 /* Find ARP dissector for TCP/IP object */
5035 arp_handle = find_dissector_add_dependency("arp", proto_enip);
5036
5037 /* I/O data dissectors */
5038 cipsafety_handle = find_dissector("cipsafety");
5039
5040 /* Implicit data dissector */
5041 cip_implicit_handle = find_dissector_add_dependency("cip_implicit", proto_enip);
5042
5043 cip_handle = find_dissector_add_dependency("cip", proto_enip);
5044
5045 /* Register for EtherNet/IP Device Level Ring protocol */
5046 dlr_handle = create_dissector_handle(dissect_dlr, proto_dlr);
5047 dissector_add_uint("ethertype", ETHERTYPE_DLR, dlr_handle);
5048
5049 subdissector_class_table = find_dissector_table("cip.class.iface");
5050
5051 dissector_add_for_decode_as("cip.io", cip_class1_handle);
5052 } /* end of proto_reg_handoff_enip() */
5053
5054 /*
5055 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5056 *
5057 * Local variables:
5058 * c-basic-offset: 3
5059 * tab-width: 8
5060 * indent-tabs-mode: nil
5061 * End:
5062 *
5063 * ex: set shiftwidth=3 tabstop=8 expandtab:
5064 * :indentSize=3:tabSize=8:noTabs=true:
5065 */
5066