Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-enip.c
blobd4347f22b051e59fb7de8066e5a3b55885e603ab
1 /* packet-enip.c
2 * Routines for EtherNet/IP (Industrial Protocol) dissection
3 * EtherNet/IP Home: www.odva.org
5 * This dissector includes items from:
6 * CIP Volume 1: Common Industrial Protocol, Edition 3.34
7 * CIP Volume 2: EtherNet/IP Adaptation of CIP, Edition 1.30
8 * CIP Volume 8: CIP Security, Edition 1.17
10 * Copyright 2003-2004
11 * Magnus Hansson <mah@hms.se>
12 * Joakim Wiberg <jow@hms.se>
14 * Conversation data support for CIP
15 * Jan Bartels, Siempelkamp Maschinen- und Anlagenbau GmbH & Co. KG
16 * Copyright 2007
18 * Ethernet/IP object support
19 * Michael Mann
20 * Copyright 2011
22 * Wireshark - Network traffic analyzer
23 * By Gerald Combs <gerald@wireshark.org>
24 * Copyright 1998 Gerald Combs
26 * SPDX-License-Identifier: GPL-2.0-or-later
29 #include "config.h"
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 <epan/tfs.h>
39 #include <ipproto.h>
41 #include "packet-tcp.h"
42 #include "packet-cip.h"
43 #include "packet-enip.h"
44 #include "packet-cipsafety.h"
45 #include "packet-dtls.h"
46 #include "packet-tls.h"
47 #include "packet-tls-utils.h"
49 void proto_register_enip(void);
50 void proto_reg_handoff_enip(void);
52 /* Communication Ports */
53 #define ENIP_ENCAP_PORT 44818 /* EtherNet/IP located on port 44818 */
54 #define ENIP_SECURE_PORT 2221 /* EtherNet/IP TLS/DTLS port */
55 #define ENIP_IO_PORT 2222 /* EtherNet/IP IO located on port 2222 */
57 /* EtherNet/IP function codes */
58 #define NOP 0x0000
59 #define LIST_SERVICES 0x0004
60 #define LIST_IDENTITY 0x0063
61 #define LIST_INTERFACES 0x0064
62 #define REGISTER_SESSION 0x0065
63 #define UNREGISTER_SESSION 0x0066
64 #define SEND_RR_DATA 0x006F
65 #define SEND_UNIT_DATA 0x0070
66 #define START_DTLS 0x00C8
68 /* EtherNet/IP status codes */
69 #define SUCCESS 0x0000
70 #define INVALID_CMD 0x0001
71 #define NO_RESOURCES 0x0002
72 #define INCORRECT_DATA 0x0003
73 #define INVALID_SESSION 0x0064
74 #define INVALID_LENGTH 0x0065
75 #define UNSUPPORTED_PROT_REV 0x0069
76 #define ENCAP_HEADER_ERROR 0x006A
78 /* EtherNet/IP Common Packet Format Type IDs */
79 #define CPF_ITEM_NULL 0x0000
80 #define CPF_ITEM_CIP_IDENTITY 0x000C
81 #define CPF_ITEM_CIP_SECURITY 0x0086
82 #define CPF_ITEM_ENIP_CAPABILITY 0x0087
83 #define CPF_ITEM_ENIP_USAGE 0x0088
84 #define CPF_ITEM_CONNECTED_ADDRESS 0x00A1
85 #define CPF_ITEM_CONNECTED_DATA 0x00B1
86 #define CPF_ITEM_UNCONNECTED_DATA 0x00B2
87 #define CPF_ITEM_LIST_SERVICES_RESP 0x0100
88 #define CPF_ITEM_SOCK_ADR_INFO_OT 0x8000
89 #define CPF_ITEM_SOCK_ADR_INFO_TO 0x8001
90 #define CPF_ITEM_SEQUENCED_ADDRESS 0x8002
91 #define CPF_ITEM_UNCONNECTED_MSG_DTLS 0x8003
93 /* Initialize the protocol and registered fields */
94 static int proto_enip;
95 static int proto_cipio;
96 static int proto_cip_class1;
98 static int hf_enip_command;
99 static int hf_enip_length;
100 static int hf_enip_options;
101 static int hf_enip_sendercontex;
102 static int hf_enip_listid_delay;
103 static int hf_enip_status;
104 static int hf_enip_session;
105 static int hf_enip_encapver;
106 static int hf_enip_sinfamily;
107 static int hf_enip_sinport;
108 static int hf_enip_sinaddr;
109 static int hf_enip_sinzero;
110 static int hf_enip_timeout;
111 static int hf_enip_encap_data;
113 static int hf_enip_lir_vendor;
114 static int hf_enip_lir_devtype;
115 static int hf_enip_lir_prodcode;
116 static int hf_enip_lir_revision;
117 static int hf_enip_lir_status;
118 static int hf_enip_lir_serial;
119 static int hf_enip_lir_namelen;
120 static int hf_enip_lir_name;
121 static int hf_enip_lir_state;
123 static int hf_enip_lsr_capaflags;
124 static int hf_enip_lsr_tcp;
125 static int hf_enip_lsr_udp;
126 static int hf_enip_lsr_servicename;
128 static int hf_enip_rs_version;
129 static int hf_enip_rs_optionflags;
131 static int hf_enip_security_profiles;
132 static int hf_enip_security_profiles_eip_integrity;
133 static int hf_enip_security_profiles_eip_confidentiality;
134 static int hf_enip_security_profiles_cip_authorization;
135 static int hf_enip_security_profiles_cip_user_authentication;
136 static int hf_enip_security_profiles_resource_constrained;
137 static int hf_enip_security_profiles_reserved;
138 static int hf_enip_cip_security_state;
139 static int hf_enip_eip_security_state;
140 static int hf_enip_iana_port_state_flags;
141 static int hf_enip_iana_port_state_flags_tcp_44818;
142 static int hf_enip_iana_port_state_flags_udp_44818;
143 static int hf_enip_iana_port_state_flags_udp_2222;
144 static int hf_enip_iana_port_state_flags_tcp_2221;
145 static int hf_enip_iana_port_state_flags_udp_2221;
146 static int hf_enip_iana_port_state_flags_reserved;
148 static int hf_enip_srrd_ifacehnd;
150 static int hf_enip_sud_ifacehnd;
152 static int hf_enip_cpf_itemcount;
153 static int hf_enip_cpf_typeid;
154 static int hf_enip_cpf_length;
155 static int hf_cip_sequence_count;
156 static int hf_cip_cm_ot_api;
157 static int hf_cip_cm_to_api;
158 static int hf_enip_cpf_cai_connid;
159 static int hf_enip_cpf_sai_connid;
160 static int hf_cip_connid;
161 static int hf_enip_cpf_sai_seqnum;
162 static int hf_enip_cpf_ucmm_request;
163 static int hf_enip_cpf_ucmm_msg_type;
164 static int hf_enip_cpf_ucmm_trans_id;
165 static int hf_enip_cpf_ucmm_status;
167 static int hf_enip_cpf_data;
169 static int hf_enip_response_in;
170 static int hf_enip_response_to;
171 static int hf_enip_time;
172 static int hf_enip_fwd_open_in;
173 static int hf_cip_connection;
174 static int hf_cip_io_data;
176 /* Parsed Attributes */
177 static int hf_tcpip_status;
178 static int hf_tcpip_status_interface_config;
179 static int hf_tcpip_status_mcast_pending;
180 static int hf_tcpip_status_interface_config_pending;
181 static int hf_tcpip_status_acd;
182 static int hf_tcpip_acd_fault;
183 static int hf_tcpip_status_iana_port_admin_change;
184 static int hf_tcpip_status_iana_protocol_admin_change;
185 static int hf_tcpip_status_reserved;
186 static int hf_tcpip_config_cap;
187 static int hf_tcpip_config_cap_bootp;
188 static int hf_tcpip_config_cap_dns;
189 static int hf_tcpip_config_cap_dhcp;
190 static int hf_tcpip_config_cap_dhcp_dns_update;
191 static int hf_tcpip_config_cap_config_settable;
192 static int hf_tcpip_config_cap_hardware_config;
193 static int hf_tcpip_config_cap_interface_reset;
194 static int hf_tcpip_config_cap_acd;
195 static int hf_tcpip_config_cap_reserved;
196 static int hf_tcpip_config_control;
197 static int hf_tcpip_config_control_config;
198 static int hf_tcpip_config_control_dns;
199 static int hf_tcpip_config_control_reserved;
200 static int hf_tcpip_ic_ip_addr;
201 static int hf_tcpip_ic_subnet_mask;
202 static int hf_tcpip_ic_gateway;
203 static int hf_tcpip_ic_name_server;
204 static int hf_tcpip_ic_name_server2;
205 static int hf_tcpip_ic_domain_name;
206 static int hf_tcpip_hostname;
207 static int hf_tcpip_snn_timestamp;
208 static int hf_tcpip_snn_date;
209 static int hf_tcpip_snn_time;
210 static int hf_tcpip_ttl_value;
211 static int hf_tcpip_mcast_alloc;
212 static int hf_tcpip_mcast_reserved;
213 static int hf_tcpip_mcast_num_mcast;
214 static int hf_tcpip_mcast_addr_start;
215 static int hf_tcpip_lcd_acd_activity;
216 static int hf_tcpip_lcd_remote_mac;
217 static int hf_tcpip_lcd_arp_pdu;
218 static int hf_tcpip_select_acd;
219 static int hf_tcpip_quick_connect;
220 static int hf_tcpip_encap_inactivity;
222 static int hf_tcpip_port_count;
223 static int hf_tcpip_port_name;
224 static int hf_tcpip_port_number;
225 static int hf_tcpip_port_protocol;
226 static int hf_tcpip_port_admin_state;
227 static int hf_tcpip_port_admin_capability;
228 static int hf_tcpip_admin_capability_configurable;
229 static int hf_tcpip_admin_capability_reset_required;
230 static int hf_tcpip_admin_capability_reserved;
232 static int hf_elink_interface_flags;
233 static int hf_elink_iflags_link_status;
234 static int hf_elink_iflags_duplex;
235 static int hf_elink_iflags_neg_status;
236 static int hf_elink_iflags_manual_reset;
237 static int hf_elink_iflags_local_hw_fault;
238 static int hf_elink_iflags_reserved;
239 static int hf_elink_interface_speed;
240 static int hf_elink_physical_address;
241 static int hf_elink_icount_in_octets;
242 static int hf_elink_icount_in_ucast;
243 static int hf_elink_icount_in_nucast;
244 static int hf_elink_icount_in_discards;
245 static int hf_elink_icount_in_errors;
246 static int hf_elink_icount_in_unknown_protos;
247 static int hf_elink_icount_out_octets;
248 static int hf_elink_icount_out_ucast;
249 static int hf_elink_icount_out_nucast;
250 static int hf_elink_icount_out_discards;
251 static int hf_elink_icount_out_errors;
252 static int hf_elink_mcount_alignment_errors;
253 static int hf_elink_mcount_fcs_errors;
254 static int hf_elink_mcount_single_collisions;
255 static int hf_elink_mcount_multiple_collisions;
256 static int hf_elink_mcount_sqe_test_errors;
257 static int hf_elink_mcount_deferred_transmission;
258 static int hf_elink_mcount_late_collisions;
259 static int hf_elink_mcount_excessive_collisions;
260 static int hf_elink_mcount_mac_transmit_errors;
261 static int hf_elink_mcount_carrier_sense_errors;
262 static int hf_elink_mcount_frame_too_long;
263 static int hf_elink_mcount_mac_receive_errors;
264 static int hf_elink_icontrol_control_bits;
265 static int hf_elink_icontrol_control_bits_auto_neg;
266 static int hf_elink_icontrol_control_bits_forced_duplex;
267 static int hf_elink_icontrol_control_bits_reserved;
268 static int hf_elink_icontrol_forced_speed;
269 static int hf_elink_icapability_capability_bits;
270 static int hf_elink_icapability_capability_bits_manual;
271 static int hf_elink_icapability_capability_bits_auto_neg;
272 static int hf_elink_icapability_capability_bits_auto_mdix;
273 static int hf_elink_icapability_capability_bits_manual_speed;
274 static int hf_elink_icapability_capability_speed_duplex_array_count;
275 static int hf_elink_icapability_capability_speed;
276 static int hf_elink_icapability_capability_duplex;
277 static int hf_elink_interface_type;
278 static int hf_elink_interface_state;
279 static int hf_elink_admin_state;
280 static int hf_elink_interface_label;
281 static int hf_elink_hc_icount_in_octets;
282 static int hf_elink_hc_icount_in_ucast;
283 static int hf_elink_hc_icount_in_mcast;
284 static int hf_elink_hc_icount_in_broadcast;
285 static int hf_elink_hc_icount_out_octets;
286 static int hf_elink_hc_icount_out_ucast;
287 static int hf_elink_hc_icount_out_mcast;
288 static int hf_elink_hc_icount_out_broadcast;
290 static int hf_elink_hc_mcount_stats_align_errors;
291 static int hf_elink_hc_mcount_stats_fcs_errors;
292 static int hf_elink_hc_mcount_stats_internal_mac_transmit_errors;
293 static int hf_elink_hc_mcount_stats_frame_too_long;
294 static int hf_elink_hc_mcount_stats_internal_mac_receive_errors;
295 static int hf_elink_hc_mcount_stats_symbol_errors;
297 static int hf_qos_8021q_enable;
298 static int hf_qos_dscp_ptp_event;
299 static int hf_qos_dscp_ptp_general;
300 static int hf_qos_dscp_urgent;
301 static int hf_qos_dscp_scheduled;
302 static int hf_qos_dscp_high;
303 static int hf_qos_dscp_low;
304 static int hf_qos_dscp_explicit;
306 static int hf_dlr_network_topology;
307 static int hf_dlr_network_status;
308 static int hf_dlr_ring_supervisor_status;
309 static int hf_dlr_rsc_ring_supervisor_enable;
310 static int hf_dlr_rsc_ring_supervisor_precedence;
311 static int hf_dlr_rsc_beacon_interval;
312 static int hf_dlr_rsc_beacon_timeout;
313 static int hf_dlr_rsc_dlr_vlan_id;
314 static int hf_dlr_ring_faults_count;
315 static int hf_dlr_lanp1_dev_ip_addr;
316 static int hf_dlr_lanp1_dev_physical_address;
317 static int hf_dlr_lanp2_dev_ip_addr;
318 static int hf_dlr_lanp2_dev_physical_address;
319 static int hf_dlr_ring_protocol_participants_count;
320 static int hf_dlr_rppl_dev_ip_addr;
321 static int hf_dlr_rppl_dev_physical_address;
322 static int hf_dlr_asa_supervisor_ip_addr;
323 static int hf_dlr_asa_supervisor_physical_address;
324 static int hf_dlr_active_supervisor_precedence;
325 static int hf_dlr_capability_flags;
326 static int hf_dlr_capflags_announce_base_node;
327 static int hf_dlr_capflags_beacon_base_node;
328 static int hf_dlr_capflags_reserved1;
329 static int hf_dlr_capflags_supervisor_capable;
330 static int hf_dlr_capflags_reserved2;
331 static int hf_dlr_capflags_redundant_gateway_capable;
332 static int hf_dlr_capflags_flush_frame_capable;
333 static int hf_dlr_rgc_red_gateway_enable;
334 static int hf_dlr_rgc_gateway_precedence;
335 static int hf_dlr_rgc_advertise_interval;
336 static int hf_dlr_rgc_advertise_timeout;
337 static int hf_dlr_rgc_learning_update_enable;
338 static int hf_dlr_redundant_gateway_status;
339 static int hf_dlr_aga_ip_addr;
340 static int hf_dlr_aga_physical_address;
341 static int hf_dlr_active_gateway_precedence;
343 static int hf_cip_security_state;
344 static int hf_eip_security_state;
345 static int hf_eip_security_verify_client_cert;
346 static int hf_eip_security_send_cert_chain;
347 static int hf_eip_security_check_expiration;
348 static int hf_eip_security_capability_flags;
349 static int hf_eip_security_capflags_secure_renegotiation;
350 static int hf_eip_security_capflags_reserved;
351 static int hf_eip_security_num_avail_cipher_suites;
352 static int hf_eip_security_avail_cipher_suite;
353 static int hf_eip_security_num_allow_cipher_suites;
354 static int hf_eip_security_allow_cipher_suite;
355 static int hf_eip_security_num_psk;
356 static int hf_eip_security_psk_identity_size;
357 static int hf_eip_security_psk_identity;
358 static int hf_eip_security_psk_size;
359 static int hf_eip_security_psk;
360 static int hf_eip_security_psk_usage;
361 static int hf_eip_security_num_active_certs;
362 static int hf_eip_security_num_trusted_auths;
363 static int hf_eip_security_num_trusted_identities;
364 static int hf_eip_security_num_crl;
365 static int hf_eip_cert_name;
366 static int hf_eip_cert_state;
367 static int hf_eip_cert_encoding;
368 static int hf_eip_cert_device_cert_status;
369 static int hf_eip_cert_ca_cert_status;
370 static int hf_eip_cert_capflags_push;
371 static int hf_eip_cert_capflags_reserved;
372 static int hf_eip_cert_capability_flags;
373 static int hf_eip_cert_num_certs;
374 static int hf_eip_cert_cert_name;
375 static int hf_eip_cert_verify_certificate;
376 static int hf_lldp_subtype;
377 static int hf_lldp_mac_address;
378 static int hf_ingress_egress_num_ranges;
379 static int hf_ingress_egress_port_range_low;
380 static int hf_ingress_egress_port_range_high;
381 static int hf_ingress_egress_num_rules;
382 static int hf_ingress_egress_rule_string;
383 static int hf_ingress_egress_rules_change_count;
384 static int hf_ingress_egress_apply_behav_break_connections;
385 static int hf_ingress_egress_apply_behav_reserved;
386 static int hf_ingress_egress_apply_behavior;
387 static int hf_ingress_egress_ins_num;
388 static int hf_ingress_egress_ins;
390 /* Initialize the subtree pointers */
391 static int ett_enip;
392 static int ett_cip_io_generic;
393 static int ett_path;
394 static int ett_count_tree;
395 static int ett_type_tree;
396 static int ett_command_tree;
397 static int ett_sockadd;
398 static int ett_lsrcf;
399 static int ett_tcpip_status;
400 static int ett_tcpip_admin_capability;
401 static int ett_tcpip_config_cap;
402 static int ett_tcpip_config_control;
403 static int ett_elink_interface_flags;
404 static int ett_elink_icontrol_bits;
405 static int ett_elink_icapability_bits;
406 static int ett_dlr_capability_flags;
407 static int ett_dlr_lnknbrstatus_flags;
408 static int ett_eip_security_capability_flags;
409 static int ett_eip_security_psk;
410 static int ett_eip_security_active_certs;
411 static int ett_eip_security_trusted_auths;
412 static int ett_eip_security_trusted_identities;
413 static int ett_eip_security_crl;
414 static int ett_eip_cert_capability_flags;
415 static int ett_eip_cert_num_certs;
416 static int ett_security_profiles;
417 static int ett_ingress_egress_apply_behavior;
418 static int ett_iana_port_state_flags;
419 static int ett_connection_info;
420 static int ett_connection_path_info;
421 static int ett_cmd_data;
423 static expert_field ei_mal_tcpip_status;
424 static expert_field ei_mal_tcpip_config_cap;
425 static expert_field ei_mal_tcpip_config_control;
426 static expert_field ei_mal_tcpip_interface_config;
427 static expert_field ei_mal_tcpip_mcast_config;
428 static expert_field ei_mal_tcpip_last_conflict;
429 static expert_field ei_mal_tcpip_snn;
430 static expert_field ei_mal_elink_interface_flags;
431 static expert_field ei_mal_elink_physical_address;
432 static expert_field ei_mal_elink_interface_counters;
433 static expert_field ei_mal_elink_media_counters;
434 static expert_field ei_mal_elink_interface_control;
435 static expert_field ei_mal_dlr_ring_supervisor_config;
436 static expert_field ei_mal_dlr_last_active_node_on_port_1;
437 static expert_field ei_mal_dlr_last_active_node_on_port_2;
438 static expert_field ei_mal_dlr_ring_protocol_participants_list;
439 static expert_field ei_mal_dlr_active_supervisor_address;
440 static expert_field ei_mal_dlr_capability_flags;
441 static expert_field ei_mal_dlr_redundant_gateway_config;
442 static expert_field ei_mal_dlr_active_gateway_address;
443 static expert_field ei_mal_eip_security_capability_flags;
444 static expert_field ei_mal_eip_security_avail_cipher_suites;
445 static expert_field ei_mal_eip_security_allow_cipher_suites;
446 static expert_field ei_mal_eip_security_preshared_keys;
447 static expert_field ei_mal_eip_security_active_certs;
448 static expert_field ei_mal_eip_security_trusted_auths;
449 static expert_field ei_mal_eip_security_trusted_identities;
450 static expert_field ei_mal_eip_security_crl;
451 static expert_field ei_mal_eip_cert_capability_flags;
452 static expert_field ei_mal_cpf_item_length_mismatch;
453 static expert_field ei_mal_cpf_item_minimum_size;
455 static expert_field ei_cip_request_no_response;
456 static expert_field ei_cip_io_heartbeat;
459 static dissector_table_t subdissector_srrd_table;
460 static dissector_table_t subdissector_io_table;
461 static dissector_table_t subdissector_decode_as_io_table;
462 static dissector_table_t subdissector_class_table;
463 static dissector_table_t subdissector_cip_connection_table;
465 static dissector_handle_t arp_handle;
466 static dissector_handle_t cipsafety_handle;
467 static dissector_handle_t cip_io_generic_handle;
468 static dissector_handle_t cip_implicit_handle;
469 static dissector_handle_t cip_handle;
470 static dissector_handle_t enip_tcp_handle;
471 static dissector_handle_t enip_udp_handle;
472 static dissector_handle_t enip_cipio_handle;
473 static dissector_handle_t cip_class1_handle;
474 static dissector_handle_t dtls_handle;
475 static dissector_handle_t dlr_handle;
478 static bool enip_desegment = true;
479 static bool enip_OTrun_idle = true;
480 static bool enip_TOrun_idle;
482 static int proto_dlr;
484 static int hf_dlr_ringsubtype;
485 static int hf_dlr_ringprotoversion;
486 static int hf_dlr_frametype;
487 static int hf_dlr_sourceport;
488 static int hf_dlr_sourceip;
489 static int hf_dlr_sequenceid;
491 static int hf_dlr_ringstate;
492 static int hf_dlr_supervisorprecedence;
493 static int hf_dlr_beaconinterval;
494 static int hf_dlr_beacontimeout;
495 static int hf_dlr_beaconreserved;
497 static int hf_dlr_nreqreserved;
499 static int hf_dlr_nressourceport;
500 static int hf_dlr_nresreserved;
502 static int hf_dlr_lnknbrstatus;
503 static int hf_dlr_lnknbrstatus_port1;
504 static int hf_dlr_lnknbrstatus_port2;
505 static int hf_dlr_lnknbrstatus_reserved;
506 static int hf_dlr_lnknbrstatus_frame_type;
507 static int hf_dlr_lnknbrreserved;
509 static int hf_dlr_lfreserved;
511 static int hf_dlr_anreserved;
513 static int hf_dlr_sonumnodes;
514 static int hf_dlr_somac;
515 static int hf_dlr_soip;
516 static int hf_dlr_soreserved;
518 static int hf_dlr_advgatewaystate;
519 static int hf_dlr_advgatewayprecedence;
520 static int hf_dlr_advadvertiseinterval;
521 static int hf_dlr_advadvertisetimeout;
522 static int hf_dlr_advlearningupdateenable;
523 static int hf_dlr_advreserved;
525 static int hf_dlr_flushlearningupdateenable;
526 static int hf_dlr_flushreserved;
528 static int hf_dlr_learnreserved;
530 static int ett_dlr;
532 /* Translate function to string - Encapsulation commands */
533 static const value_string encap_cmd_vals[] = {
534 { NOP, "NOP" },
535 { LIST_SERVICES, "List Services" },
536 { LIST_IDENTITY, "List Identity" },
537 { LIST_INTERFACES, "List Interfaces" },
538 { REGISTER_SESSION, "Register Session" },
539 { UNREGISTER_SESSION,"Unregister Session" },
540 { SEND_RR_DATA, "Send RR Data" },
541 { SEND_UNIT_DATA, "Send Unit Data" },
542 { START_DTLS, "StartDTLS" },
544 { 0, NULL }
547 /* Translate function to string - Encapsulation status */
548 static const value_string encap_status_vals[] = {
549 { SUCCESS, "Success" },
550 { INVALID_CMD, "Invalid Command" },
551 { NO_RESOURCES, "No Memory Resources" },
552 { INCORRECT_DATA, "Incorrect Data" },
553 { INVALID_SESSION, "Invalid Session Handle" },
554 { INVALID_LENGTH, "Invalid Length" },
555 { UNSUPPORTED_PROT_REV, "Unsupported Protocol Revision" },
556 { ENCAP_HEADER_ERROR, "Encapsulated CIP service not allowed on this port" },
558 { 0, NULL }
561 /* Translate function to Common packet format values */
562 static const value_string cpf_type_vals[] = {
563 { CPF_ITEM_NULL, "Null Address Item" },
564 { CPF_ITEM_CIP_IDENTITY, "CIP Identity" },
565 { CPF_ITEM_CIP_SECURITY, "CIP Security Information" },
566 { CPF_ITEM_ENIP_CAPABILITY, "EtherNet/IP Capability" },
567 { CPF_ITEM_ENIP_USAGE, "EtherNet/IP Usage" },
568 { CPF_ITEM_CONNECTED_ADDRESS, "Connected Address Item" },
569 { CPF_ITEM_CONNECTED_DATA, "Connected Data Item" },
570 { CPF_ITEM_UNCONNECTED_DATA, "Unconnected Data Item" },
571 { CPF_ITEM_LIST_SERVICES_RESP, "List Services Response" },
572 { CPF_ITEM_SOCK_ADR_INFO_OT, "Socket Address Info O->T" },
573 { CPF_ITEM_SOCK_ADR_INFO_TO, "Socket Address Info T->O" },
574 { CPF_ITEM_SEQUENCED_ADDRESS, "Sequenced Address Item" },
575 { CPF_ITEM_UNCONNECTED_MSG_DTLS, "Unconnected Message over UDP" },
577 { 0, NULL }
580 static const value_string unconn_msg_type_vals[] = {
581 { 0, "Reserved" },
582 { 1, "UCMM_NOACK" },
584 { 0, NULL }
587 static const value_string enip_tcpip_status_interface_config_vals[] = {
588 { 0, "Not configured" },
589 { 1, "BOOTP/DHCP/NVS" },
590 { 2, "Hardware settings" },
592 { 0, NULL }
595 static const value_string enip_tcpip_status_acd_vals[] = {
596 { 0, "No Address Conflict Detected" },
597 { 1, "Address Conflict Detected" },
599 { 0, NULL }
602 static const value_string enip_tcpip_config_control_config_vals[] = {
603 { 0, "Static IP" },
604 { 1, "BOOTP" },
605 { 2, "DHCP" },
607 { 0, NULL }
610 static const value_string enip_tcpip_mcast_alloc_vals[] = {
611 { 0, "Use default multicast algorithm" },
612 { 1, "Use Num Mcast and Mcast Start Addr" },
614 { 0, NULL }
617 static const value_string enip_tcpip_acd_activity_vals[] = {
618 { 0, "No Conflict Detected" },
619 { 1, "Probe IPv4 Address" },
620 { 2, "Ongoing Detection" },
621 { 3, "Semi Active Probe" },
623 { 0, NULL }
626 static const value_string enip_elink_duplex_vals[] = {
627 { 0, "Half Duplex" },
628 { 1, "Full Duplex" },
630 { 0, NULL }
633 static const value_string enip_elink_iflags_neg_status_vals[] = {
634 { 0, "Auto-negotiation in progress" },
635 { 1, "Auto-negotiation and speed detection failed" },
636 { 2, "Auto-negotiation failed but detected speed" },
637 { 3, "Successfully negotiated speed and duplex" },
638 { 4, "Auto-negotiation not attempted. Forced speed and duplex" },
640 { 0, NULL }
643 static const value_string enip_elink_iflags_reset_vals[] = {
644 { 0, "Activate change automatically" },
645 { 1, "Device requires Reset service for change" },
647 { 0, NULL }
650 static const value_string enip_elink_iflags_hw_fault_vals[] = {
651 { 0, "No local hardware fault" },
652 { 1, "Local hardware fault detected" },
654 { 0, NULL }
657 static const value_string enip_elink_interface_type_vals[] = {
658 { 0, "Unknown type" },
659 { 1, "Internal" },
660 { 2, "Twisted-pair" },
661 { 3, "Optical fiber" },
663 { 0, NULL }
666 static const value_string enip_elink_interface_state_vals[] = {
667 { 0, "Unknown state" },
668 { 1, "Enabled" },
669 { 2, "Disabled" },
670 { 3, "Testing" },
672 { 0, NULL }
675 static const value_string enip_elink_admin_state_vals[] = {
676 { 1, "Enabled" },
677 { 2, "Disabled" },
679 { 0, NULL }
682 static const value_string enip_dlr_network_topology_vals[] = {
683 { 0, "Linear" },
684 { 1, "Ring" },
686 { 0, NULL }
689 static const value_string enip_dlr_network_status_vals[] = {
690 { 0, "Normal" },
691 { 1, "Ring Fault" },
692 { 2, "Unexpected Loop Detected" },
693 { 3, "Partial Network Failure" },
694 { 4, "Rapid Fault/Restore Cycle" },
696 { 0, NULL }
699 static const value_string enip_dlr_ring_supervisor_status_vals[] = {
700 { 0, "Backup Ring Supervisor" },
701 { 1, "Active Ring Supervisor" },
702 { 2, "Ring Node" },
703 { 3, "Non-DLR Topology" },
704 { 4, "Cannot Support Parameters" },
706 { 0, NULL }
709 static const value_string enip_dlr_redundant_gateway_status_vals[] = {
710 { 0, "Non-Gateway DLR node" },
711 { 1, "Backup Gateway" },
712 { 2, "Active Gateway" },
713 { 3, "Gateway Fault" },
714 { 4, "Cannot Support Parameters" },
715 { 5, "Partial Network Fault" },
717 { 0, NULL }
720 static const value_string cip_security_state_vals[] = {
721 { 0, "Factory Default Configuration" },
722 { 1, "Configuration In Progress" },
723 { 2, "Configured" },
724 { 3, "Incomplete Configuration" },
726 { 0, NULL }
729 static const value_string eip_security_state_vals[] = {
730 { 0, "Factory Default Configuration" },
731 { 1, "Configuration In Progress" },
732 { 2, "Configured" },
733 { 3, "Pull Model In Progress" },
734 { 4, "Pull Model Completed" },
735 { 5, "Pull Model Disabled" },
737 { 0, NULL }
740 static const value_string eip_security_psk_usage_vals[] = {
741 { 0, "Server" },
742 { 1, "Client" },
743 { 2, "Any Usage" },
745 { 0, NULL },
748 static const value_string eip_cert_state_vals[] = {
749 { 0, "Non-Existent" },
750 { 1, "Created" },
751 { 2, "Configuring" },
752 { 3, "Verified" },
753 { 4, "Invalid" },
755 { 0, NULL }
758 static const value_string eip_cert_status_vals[] = {
759 { 0, "Not Verified" },
760 { 1, "Verified" },
761 { 2, "Invalid" },
763 { 0, NULL }
766 /* Translate interface handle to string */
767 static const value_string enip_interface_handle_vals[] = {
768 { 0, "CIP" },
770 { 0, NULL }
773 /* Translate function to DLR Frame Type values */
774 static const value_string dlr_frame_type_vals[] = {
775 { DLR_FT_BEACON, "Beacon" },
776 { DLR_FT_NEIGHBOR_REQ, "Neighbor_Check_Request" },
777 { DLR_FT_NEIGHBOR_RES, "Neighbor_Check_Response" },
778 { DLR_FT_LINK_STAT, "Link_Status / Neighbor_Status" },
779 { DLR_FT_LOCATE_FLT, "Locate_Fault" },
780 { DLR_FT_ANNOUNCE, "Announce" },
781 { DLR_FT_SIGN_ON, "Sign_On" },
782 { DLR_FT_ADVERTISE, "Advertise" },
783 { DLR_FT_FLUSH_TABLES, "Flush_Tables" },
784 { DLR_FT_LEARNING_UPDATE, "Learning_Update" },
786 { 0, NULL }
789 /* Translate function to DLR Source Port values */
790 static const value_string dlr_source_port_vals[] = {
791 { 0, "Port 1 or Port 2" },
792 { 1, "Port 1" },
793 { 2, "Port 2" },
795 { 0, NULL }
798 /* Translate function to DLR Ring State values */
799 static const value_string dlr_ring_state_vals[] = {
800 { 1, "RING_NORMAL_STATE" },
801 { 2, "RING_FAULT_STATE" },
803 { 0, NULL }
806 /* Translate function to DLR Advertise State values */
807 static const value_string dlr_adv_state_vals[] = {
808 { 0x01, "ACTIVE_LISTEN_STATE" },
809 { 0x02, "ACTIVE_NORMAL_STATE" },
810 { 0x03, "FAULT_STATE" },
812 { 0, NULL }
815 /* Translate function to DLR Learning Update values */
816 static const value_string dlr_adv_learning_update_vals[] = {
817 { 0, "Disabled" },
818 { 1, "Enabled" },
820 { 0, NULL }
823 /* Translate function to DLR Flush Learning Update values */
824 static const value_string dlr_flush_learning_update_vals[] = {
825 { 0, "Disabled" },
826 { 1, "Enabled" },
828 { 0, NULL }
831 static const true_false_string dlr_lnknbrstatus_frame_type_vals = {
832 "Neighbor_Status Frame",
833 "Link_Status Frame"
836 static void enip_prompt(packet_info *pinfo _U_, char* result)
838 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Dissect unidentified I/O traffic as");
841 static wmem_map_t *enip_request_hashtable;
843 /* Return codes of function classifying packets as query/response */
844 enum enip_packet_type {ENIP_REQUEST_PACKET, ENIP_RESPONSE_PACKET, ENIP_CANNOT_CLASSIFY};
845 enum enip_packet_data_type { EPDT_UNKNOWN, EPDT_CONNECTED_TRANSPORT, EPDT_UNCONNECTED };
847 typedef struct enip_request_key {
848 uint32_t session_handle;
849 enum enip_packet_type requesttype;
850 enum enip_packet_data_type type;
851 uint64_t sender_context;
852 uint32_t conversation;
853 union {
854 struct {
855 uint32_t connid;
856 uint16_t sequence;
857 } connected_transport;
858 } data;
859 } enip_request_key_t;
861 typedef struct enip_request_val {
862 wmem_tree_t *frames;
863 } enip_request_val_t;
866 * Hash Functions
868 static gboolean
869 enip_request_equal(const void *v, const void *w)
871 const enip_request_key_t *v1 = (const enip_request_key_t *)v;
872 const enip_request_key_t *v2 = (const enip_request_key_t *)w;
874 if ( v1->conversation == v2->conversation
875 && v1->session_handle == v2->session_handle
876 && v1->type == v2->type
877 && ( ( v1->sender_context == v2->sender_context /* heuristic approach */
878 && v1->type == EPDT_UNCONNECTED
881 ( v1->data.connected_transport.connid == v2->data.connected_transport.connid
882 && v1->data.connected_transport.sequence == v2->data.connected_transport.sequence
883 && v1->type == EPDT_CONNECTED_TRANSPORT
887 return TRUE;
889 return FALSE;
892 static void
893 enip_fmt_lir_revision( char *result, uint32_t revision )
895 snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (uint8_t)(( revision & 0xFF00 ) >> 8), (uint8_t)(revision & 0xFF) );
898 static unsigned
899 enip_request_hash (const void *v)
901 const enip_request_key_t *key = (const enip_request_key_t *)v;
902 unsigned val;
904 val = (unsigned)(key->conversation * 37 + key->session_handle * 93 + key->type * 765);
906 if (key->type == EPDT_UNCONNECTED)
908 val += ((unsigned)(key->sender_context * 23));
910 else if (key->type == EPDT_CONNECTED_TRANSPORT)
912 val += ((unsigned)(key->data.connected_transport.connid * 87 + key->data.connected_transport.sequence * 834));
915 return val;
918 static enip_request_info_t *
919 enip_match_request( packet_info *pinfo, proto_tree *tree, enip_request_key_t *prequest_key )
921 enip_request_key_t *new_request_key;
922 enip_request_val_t *request_val;
923 enip_request_info_t *request_info;
925 request_info = NULL;
926 request_val = (enip_request_val_t *)wmem_map_lookup( enip_request_hashtable, prequest_key );
927 if (!pinfo->fd->visited)
929 if ( prequest_key && prequest_key->requesttype == ENIP_REQUEST_PACKET )
931 if ( request_val == NULL )
933 new_request_key = (enip_request_key_t *)wmem_memdup(wmem_file_scope(), prequest_key, sizeof(enip_request_key_t));
935 request_val = wmem_new(wmem_file_scope(), enip_request_val_t);
936 request_val->frames = wmem_tree_new(wmem_file_scope());
938 wmem_map_insert(enip_request_hashtable, new_request_key, request_val );
941 request_info = wmem_new(wmem_file_scope(), enip_request_info_t);
942 request_info->req_num = pinfo->num;
943 request_info->rep_num = 0;
944 request_info->req_time = pinfo->abs_ts;
945 request_info->cip_info = NULL;
946 wmem_tree_insert32(request_val->frames, pinfo->num, (void *)request_info);
948 if ( request_val && prequest_key && prequest_key->requesttype == ENIP_RESPONSE_PACKET )
950 request_info = (enip_request_info_t*)wmem_tree_lookup32_le( request_val->frames, pinfo->num );
951 if ( request_info )
953 request_info->rep_num = pinfo->num;
957 else
959 if ( request_val )
960 request_info = (enip_request_info_t *)wmem_tree_lookup32_le( request_val->frames, pinfo->num );
963 if ( tree && request_info )
965 /* print state tracking in the tree */
966 if ( prequest_key && prequest_key->requesttype == ENIP_REQUEST_PACKET )
968 /* This is a request */
969 if (request_info->rep_num)
971 proto_item *it;
973 it = proto_tree_add_uint(tree, hf_enip_response_in,
974 NULL, 0, 0, request_info->rep_num);
975 proto_item_set_generated(it);
977 else
979 expert_add_info(pinfo, tree, &ei_cip_request_no_response);
982 else
984 if ( prequest_key && prequest_key->requesttype == ENIP_RESPONSE_PACKET )
986 /* This is a reply */
987 if (request_info->req_num)
989 proto_item *it;
990 nstime_t ns;
992 it = proto_tree_add_uint(tree, hf_enip_response_to,
993 NULL, 0, 0, request_info->req_num);
994 proto_item_set_generated(it);
996 nstime_delta(&ns, &pinfo->abs_ts, &request_info->req_time);
997 it = proto_tree_add_time(tree, hf_enip_time, NULL, 0, 0, &ns);
998 proto_item_set_generated(it);
1003 return request_info;
1006 typedef struct enip_conn_key {
1007 cip_connection_triad_t triad;
1008 uint32_t O2TConnID;
1009 uint32_t T2OConnID;
1010 } enip_conn_key_t;
1012 // This is a per list of CIP connection IDs per conversation_t.
1013 typedef struct _enip_conv_info_t {
1014 // Connection ID --> cip_conn_info_t
1015 wmem_tree_t *O2TConnIDs;
1016 // Connection ID --> cip_conn_info_t
1017 wmem_tree_t *T2OConnIDs;
1018 } enip_conv_info_t;
1021 * Conversation filter
1023 static bool
1024 enip_io_conv_valid(packet_info *pinfo, void *user_data _U_)
1026 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1028 if (conn == NULL)
1029 return false;
1031 return (((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 0) ||
1032 ((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1));
1035 static char *
1036 enip_io_conv_filter(packet_info *pinfo, void *user_data _U_)
1038 char *buf;
1039 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1041 if (conn == NULL)
1042 return NULL;
1044 if (conn->close_frame > 0)
1046 buf = ws_strdup_printf(
1047 "((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
1048 "((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1049 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1050 conn->open_req_frame, conn->open_reply_frame, conn->close_frame,
1051 conn->O2T.connID, conn->T2O.connID,
1052 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1054 else
1056 /* If Forward Close isn't found, don't limit the (end) frame range */
1057 buf = ws_strdup_printf(
1058 "((frame.number == %u) || (frame.number >= %u)) && " /* Frames starting with ForwardOpen */
1059 "((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1060 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1061 conn->open_req_frame, conn->open_reply_frame,
1062 conn->O2T.connID, conn->T2O.connID,
1063 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1066 return buf;
1069 static bool
1070 enip_exp_conv_valid(packet_info *pinfo, void *user_data _U_)
1072 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1074 if (conn == NULL)
1075 return false;
1077 return (((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 2) ||
1078 ((conn->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 3));
1081 static char *
1082 enip_exp_conv_filter(packet_info *pinfo, void *user_data _U_)
1084 char *buf;
1085 cip_conn_info_t* conn = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
1087 if (conn == NULL)
1088 return NULL;
1090 if (conn->close_frame > 0)
1092 buf = ws_strdup_printf(
1093 "((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
1094 "((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1095 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1096 conn->open_req_frame, conn->open_reply_frame, conn->close_frame,
1097 conn->O2T.connID, conn->T2O.connID,
1098 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1100 else
1102 /* If Forward Close isn't found, don't limit the (end) frame range */
1103 buf = ws_strdup_printf(
1104 "((frame.number == %u) || (frame.number >= %u)) && " /* Frames between ForwardOpen and ForwardClose */
1105 "((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
1106 "((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x)))", /* Connection Triad */
1107 conn->open_req_frame, conn->open_reply_frame,
1108 conn->O2T.connID, conn->T2O.connID,
1109 conn->triad.ConnSerialNumber, conn->triad.VendorID, conn->triad.DeviceSerialNumber);
1111 return buf;
1114 static bool cip_connection_conv_valid(packet_info *pinfo, void *user_data)
1116 return enip_io_conv_valid(pinfo, user_data) || enip_exp_conv_valid(pinfo, user_data);
1119 static char* cip_connection_conv_filter(packet_info *pinfo, void *user_data)
1121 char* buf = NULL;
1123 if (enip_io_conv_valid(pinfo, user_data))
1125 buf = enip_io_conv_filter(pinfo, user_data);
1127 else if (enip_exp_conv_valid(pinfo, user_data))
1129 buf = enip_exp_conv_filter(pinfo, user_data);
1132 return buf;
1136 * Connection management
1139 // Key: (triad, connection IDs), Value: cip_conn_info_t
1140 static wmem_map_t *enip_conn_hashtable;
1141 static uint32_t enip_unique_connid;
1143 static gboolean
1144 enip_conn_equal(const void *v, const void *w)
1146 const enip_conn_key_t *v1 = (const enip_conn_key_t *)v;
1147 const enip_conn_key_t *v2 = (const enip_conn_key_t *)w;
1149 if (cip_connection_triad_match(&v1->triad, &v2->triad) &&
1150 ((v1->O2TConnID == 0) || (v2->O2TConnID == 0) || (v1->O2TConnID == v2->O2TConnID)) &&
1151 ((v1->T2OConnID == 0) || (v2->T2OConnID == 0) || (v1->T2OConnID == v2->T2OConnID)))
1152 return TRUE;
1154 return FALSE;
1157 static unsigned
1158 enip_conn_hash (const void *v)
1160 const enip_conn_key_t *key = (const enip_conn_key_t *)v;
1161 unsigned val;
1163 val = (unsigned)( key->triad.ConnSerialNumber + key->triad.VendorID + key->triad.DeviceSerialNumber );
1165 return val;
1168 // Create a list of connection IDs and attach it to the conversation.
1169 static enip_conv_info_t* create_connection_id_list(conversation_t* conversation)
1171 enip_conv_info_t* enip_info = wmem_new(wmem_file_scope(), enip_conv_info_t);
1172 enip_info->O2TConnIDs = wmem_tree_new(wmem_file_scope());
1173 enip_info->T2OConnIDs = wmem_tree_new(wmem_file_scope());
1175 conversation_add_proto_data(conversation, proto_enip, enip_info);
1177 return enip_info;
1180 static
1181 enip_conv_info_t* get_conversation_info_one_direction(packet_info* pinfo, address* src_address, address* dst_address, cip_connID_info_t* connid_info)
1183 /* default some information if not included */
1184 if ((connid_info->port == 0) || (connid_info->type == CONN_TYPE_MULTICAST))
1186 connid_info->port = ENIP_IO_PORT;
1189 ws_in6_addr ipv6_zero = {0};
1190 if ((connid_info->ipaddress.type == AT_NONE) ||
1191 ((connid_info->ipaddress.type == AT_IPv4) && ((*(const uint32_t*)connid_info->ipaddress.data)) == 0) ||
1192 ((connid_info->ipaddress.type == AT_IPv6) && (memcmp(connid_info->ipaddress.data, &ipv6_zero, sizeof(ipv6_zero)) == 0)) ||
1193 (connid_info->type != CONN_TYPE_MULTICAST))
1195 copy_address_wmem(wmem_file_scope(), &connid_info->ipaddress, dst_address);
1198 address dest_address = ADDRESS_INIT_NONE;
1199 if (connid_info->ipaddress.type == AT_IPv6)
1201 dest_address.type = AT_IPv6;
1202 dest_address.len = 16;
1204 else
1206 dest_address.type = AT_IPv4;
1207 dest_address.len = 4;
1209 dest_address.data = connid_info->ipaddress.data;
1211 // Similar logic to find_or_create_conversation(), but since I/O traffic
1212 // is on UDP, the pinfo parameter doesn't have the correct information.
1213 conversation_t* conversation = find_conversation(pinfo->num, src_address, &dest_address,
1214 CONVERSATION_UDP, connid_info->port, 0, NO_PORT_B);
1215 if (conversation == NULL)
1217 conversation = conversation_new(pinfo->num, src_address, &dest_address,
1218 CONVERSATION_UDP, connid_info->port, 0, NO_PORT2);
1221 enip_conv_info_t* enip_info = (enip_conv_info_t*)conversation_get_proto_data(conversation, proto_enip);
1222 if (enip_info == NULL)
1224 enip_info = create_connection_id_list(conversation);
1227 return enip_info;
1230 // connInfo - Connection Information that is known so far (from the Forward Open Request).
1231 static void enip_open_cip_connection( packet_info *pinfo, cip_conn_info_t* connInfo, uint8_t service)
1233 if (pinfo->fd->visited)
1234 return;
1236 // Don't create connections for Null Forward Opens.
1237 if (connInfo->IsNullFwdOpen)
1239 return;
1242 enip_conn_key_t* conn_key = wmem_new(wmem_file_scope(), enip_conn_key_t);
1243 conn_key->triad = connInfo->triad;
1244 conn_key->O2TConnID = connInfo->O2T.connID;
1245 conn_key->T2OConnID = connInfo->T2O.connID;
1247 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, conn_key );
1248 if ( conn_val == NULL )
1250 conn_val = wmem_new0(wmem_file_scope(), cip_conn_info_t);
1252 // Copy initial connection data from the Forward Open Request.
1253 *conn_val = *connInfo;
1255 // These values are not copies from the Forward Open Request. Initialize these separately.
1256 conn_val->open_reply_frame = pinfo->num;
1257 conn_val->connid = enip_unique_connid++;
1258 conn_val->is_concurrent_connection = (service == SC_CM_CONCURRENT_FWD_OPEN);
1260 wmem_map_insert(enip_conn_hashtable, conn_key, conn_val );
1262 /* I/O connection */
1263 if (((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 0) ||
1264 ((connInfo->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1))
1266 /* check for O->T conversation */
1267 enip_conv_info_t* enip_info = get_conversation_info_one_direction(pinfo, &pinfo->dst, &pinfo->src, &(connInfo->O2T));
1268 wmem_tree_insert32(enip_info->O2TConnIDs, connInfo->O2T.connID, (void*)conn_val);
1270 /* Check if separate T->O conversation is necessary. If either side is multicast
1271 or ports aren't equal, a separate conversation must be generated */
1272 enip_info = get_conversation_info_one_direction(pinfo, &pinfo->src, &pinfo->dst, &(connInfo->T2O));
1273 wmem_tree_insert32(enip_info->T2OConnIDs, connInfo->T2O.connID, (void *)conn_val);
1275 else
1277 /* explicit message connection */
1278 conversation_t* conversation = find_or_create_conversation(pinfo);
1280 enip_conv_info_t* enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip);
1281 if (!enip_info)
1283 enip_info = create_connection_id_list(conversation);
1285 wmem_tree_insert32(enip_info->O2TConnIDs, connInfo->O2T.connID, (void *)conn_val);
1286 wmem_tree_insert32(enip_info->T2OConnIDs, connInfo->T2O.connID, (void *)conn_val);
1290 /* Save the connection info for the conversation filter */
1291 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1294 void
1295 enip_close_cip_connection(packet_info *pinfo, const cip_connection_triad_t* triad)
1297 if (pinfo->fd->visited)
1298 return;
1300 enip_conn_key_t conn_key;
1301 conn_key.triad = *triad;
1302 conn_key.O2TConnID = 0;
1303 conn_key.T2OConnID = 0;
1305 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, &conn_key );
1306 if (!conn_val)
1308 return;
1311 // Only mark the first Forward Close Request for a given connection.
1312 if (conn_val->close_frame == 0)
1314 conn_val->close_frame = pinfo->num;
1317 /* Save the connection info for the conversation filter */
1318 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1321 /* Save the connection info for the conversation filter */
1322 void enip_mark_connection_triad(packet_info *pinfo, const cip_connection_triad_t* triad)
1324 enip_conn_key_t conn_key;
1325 conn_key.triad = *triad;
1326 conn_key.O2TConnID = 0;
1327 conn_key.T2OConnID = 0;
1329 cip_conn_info_t* conn_val = (cip_conn_info_t*)wmem_map_lookup( enip_conn_hashtable, &conn_key );
1330 if ( conn_val )
1332 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_val);
1336 static cip_conn_info_t*
1337 enip_get_explicit_connid(packet_info *pinfo, enip_request_key_t *prequest_key, uint32_t connid)
1339 conversation_t *conversation;
1340 enip_conv_info_t *enip_info;
1341 enum enip_packet_type requesttype = ENIP_REQUEST_PACKET;
1343 if (prequest_key != NULL)
1345 /* Sanity check */
1346 if ((prequest_key->requesttype != ENIP_REQUEST_PACKET) && (prequest_key->requesttype != ENIP_RESPONSE_PACKET ))
1347 return NULL;
1349 requesttype = prequest_key->requesttype;
1353 * Do we have a conversation for this connection?
1355 conversation = find_conversation_pinfo(pinfo, 0);
1356 if (conversation == NULL)
1357 return NULL;
1360 * Do we already have a state structure for this conv
1362 enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip);
1363 if (!enip_info)
1364 return NULL;
1366 cip_conn_info_t* conn_val = NULL;
1367 switch (requesttype )
1369 case ENIP_REQUEST_PACKET:
1370 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->O2TConnIDs, connid );
1371 if ( conn_val == NULL )
1372 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid );
1373 break;
1375 case ENIP_RESPONSE_PACKET:
1376 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid );
1377 if ( conn_val == NULL )
1378 conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->O2TConnIDs, connid );
1379 break;
1380 case ENIP_CANNOT_CLASSIFY:
1381 /* ignore */
1382 break;
1385 if ((conn_val == NULL ) || (conn_val->open_reply_frame > pinfo->num))
1386 return NULL;
1388 return conn_val;
1391 static cip_conn_info_t*
1392 enip_get_io_connid(packet_info *pinfo, uint32_t connid, enum enip_connid_type* pconnid_type)
1394 conversation_t *conversation;
1395 enip_conv_info_t *enip_info;
1396 cip_conn_info_t *conn_val = NULL;
1398 *pconnid_type = ECIDT_UNKNOWN;
1401 * Do we have a conversation for this connection?
1403 conversation = find_conversation(pinfo->num,
1404 &pinfo->src, &pinfo->dst,
1405 conversation_pt_to_conversation_type(pinfo->ptype),
1406 pinfo->destport, 0, NO_PORT_B);
1408 if (conversation == NULL)
1409 return NULL;
1412 * Do we already have a state structure for this conv
1414 if ((enip_info = (enip_conv_info_t *)conversation_get_proto_data(conversation, proto_enip)) == NULL)
1415 return NULL;
1417 if (enip_info->O2TConnIDs != NULL)
1419 conn_val = (cip_conn_info_t*)wmem_tree_lookup32(enip_info->O2TConnIDs, connid);
1420 if (conn_val)
1422 *pconnid_type = ECIDT_O2T;
1426 if ( conn_val == NULL )
1428 if (enip_info->T2OConnIDs != NULL)
1430 if ((conn_val = (cip_conn_info_t*)wmem_tree_lookup32( enip_info->T2OConnIDs, connid)) != NULL)
1431 *pconnid_type = ECIDT_T2O;
1435 if ((conn_val == NULL) || ( conn_val->open_reply_frame > pinfo->num ))
1436 return NULL;
1438 return conn_val;
1441 static int
1442 dissect_tcpip_status(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1443 int offset, int total_len)
1446 static int * const status[] = {
1447 &hf_tcpip_status_interface_config,
1448 &hf_tcpip_status_mcast_pending,
1449 &hf_tcpip_status_interface_config_pending,
1450 &hf_tcpip_status_acd,
1451 &hf_tcpip_acd_fault,
1452 &hf_tcpip_status_iana_port_admin_change,
1453 &hf_tcpip_status_iana_protocol_admin_change,
1454 &hf_tcpip_status_reserved,
1455 NULL
1458 if (total_len < 4)
1460 expert_add_info(pinfo, item, &ei_mal_tcpip_status);
1461 return total_len;
1464 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_status, ett_tcpip_status, status, ENC_LITTLE_ENDIAN);
1465 return 4;
1468 static int
1469 dissect_tcpip_config_cap(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1470 int offset, int total_len)
1473 static int * const capabilities[] = {
1474 &hf_tcpip_config_cap_bootp,
1475 &hf_tcpip_config_cap_dns,
1476 &hf_tcpip_config_cap_dhcp,
1477 &hf_tcpip_config_cap_dhcp_dns_update,
1478 &hf_tcpip_config_cap_config_settable,
1479 &hf_tcpip_config_cap_hardware_config,
1480 &hf_tcpip_config_cap_interface_reset,
1481 &hf_tcpip_config_cap_acd,
1482 &hf_tcpip_config_cap_reserved,
1483 NULL
1486 if (total_len < 4)
1488 expert_add_info(pinfo, item, &ei_mal_tcpip_config_cap);
1489 return total_len;
1492 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_config_cap, ett_tcpip_config_cap, capabilities, ENC_LITTLE_ENDIAN);
1493 return 4;
1496 static int
1497 dissect_tcpip_config_control(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1498 int offset, int total_len)
1501 static int * const control_bits[] = {
1502 &hf_tcpip_config_control_config,
1503 &hf_tcpip_config_control_dns,
1504 &hf_tcpip_config_control_reserved,
1505 NULL
1508 if (total_len < 4)
1510 expert_add_info(pinfo, item, &ei_mal_tcpip_config_control);
1511 return total_len;
1514 proto_tree_add_bitmask(tree, tvb, offset, hf_tcpip_config_control, ett_tcpip_config_control, control_bits, ENC_LITTLE_ENDIAN);
1515 return 4;
1518 static int
1519 dissect_tcpip_physical_link(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1520 int offset, int total_len)
1523 return dissect_padded_epath_len_uint(pinfo, tree, item, tvb, offset, total_len);
1526 static int
1527 dissect_tcpip_interface_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1528 int offset, int total_len)
1531 uint16_t domain_length;
1533 if (total_len < 22)
1535 expert_add_info(pinfo, item, &ei_mal_tcpip_interface_config);
1536 return total_len;
1539 proto_tree_add_item(tree, hf_tcpip_ic_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1540 proto_tree_add_item(tree, hf_tcpip_ic_subnet_mask, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1541 proto_tree_add_item(tree, hf_tcpip_ic_gateway, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1542 proto_tree_add_item(tree, hf_tcpip_ic_name_server, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1543 proto_tree_add_item(tree, hf_tcpip_ic_name_server2, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1545 domain_length = tvb_get_letohs( tvb, offset+20);
1546 proto_tree_add_item(tree, hf_tcpip_ic_domain_name, tvb, offset+22, domain_length, ENC_ASCII);
1548 /* Add padding. */
1549 domain_length += domain_length % 2;
1551 return (22+domain_length);
1554 static int dissect_tcpip_hostname(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1555 int offset, int total_len _U_)
1557 int parsed_len;
1558 parsed_len = dissect_cip_string_type(pinfo, tree, item, tvb, offset, hf_tcpip_hostname, CIP_STRING_TYPE);
1560 /* Add padding. */
1561 parsed_len += parsed_len % 2;
1563 return parsed_len;
1566 static int dissect_tcpip_snn(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1567 int offset, int total_len)
1569 if (total_len < 6)
1571 expert_add_info(pinfo, item, &ei_mal_tcpip_snn);
1572 return total_len;
1575 dissect_cipsafety_snn(tree, tvb, pinfo, offset, hf_tcpip_snn_timestamp, hf_tcpip_snn_date, hf_tcpip_snn_time);
1576 return 6;
1579 static int
1580 dissect_tcpip_mcast_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1581 int offset, int total_len)
1584 if (total_len < 8)
1586 expert_add_info(pinfo, item, &ei_mal_tcpip_mcast_config);
1587 return total_len;
1590 proto_tree_add_item(tree, hf_tcpip_mcast_alloc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1591 proto_tree_add_item(tree, hf_tcpip_mcast_reserved, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1592 proto_tree_add_item(tree, hf_tcpip_mcast_num_mcast, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1593 proto_tree_add_item(tree, hf_tcpip_mcast_addr_start, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1594 return 8;
1597 static int
1598 dissect_tcpip_last_conflict(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1599 int offset, int total_len)
1602 tvbuff_t *next_tvb;
1603 bool save_info;
1605 if (total_len < 35)
1607 expert_add_info(pinfo, item, &ei_mal_tcpip_last_conflict);
1608 return total_len;
1611 proto_tree_add_item(tree, hf_tcpip_lcd_acd_activity, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1612 proto_tree_add_item(tree, hf_tcpip_lcd_remote_mac, tvb, offset+1, 6, ENC_NA);
1614 if ( tvb_get_uint8(tvb, offset) == 0 )
1615 proto_tree_add_item(tree, hf_tcpip_lcd_arp_pdu, tvb, offset+7, 28, ENC_NA);
1616 else
1618 /* Dissect ARP PDU, but don't have it change column info */
1619 save_info = col_get_writable(pinfo->cinfo, -1);
1620 col_set_writable(pinfo->cinfo, -1, false);
1622 next_tvb = tvb_new_subset_length(tvb, offset+7, 28);
1623 call_dissector(arp_handle, next_tvb, pinfo, tree);
1625 col_set_writable(pinfo->cinfo, -1, save_info);
1628 return 35;
1631 static int
1632 dissect_elink_interface_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1633 int offset, int total_len)
1636 static int * const flags[] = {
1637 &hf_elink_iflags_link_status,
1638 &hf_elink_iflags_duplex,
1639 &hf_elink_iflags_neg_status,
1640 &hf_elink_iflags_manual_reset,
1641 &hf_elink_iflags_local_hw_fault,
1642 &hf_elink_iflags_reserved,
1643 NULL
1646 if (total_len < 4)
1648 expert_add_info(pinfo, item, &ei_mal_elink_interface_flags);
1649 return total_len;
1652 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_interface_flags, ett_elink_interface_flags, flags, ENC_LITTLE_ENDIAN);
1653 return 4;
1656 static int
1657 dissect_elink_physical_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1658 int offset, int total_len)
1661 if (total_len < 6)
1663 expert_add_info(pinfo, item, &ei_mal_elink_physical_address);
1664 return total_len;
1667 proto_tree_add_item(tree, hf_elink_physical_address, tvb, offset, 6, ENC_NA);
1668 return 6;
1672 static int
1673 dissect_elink_interface_counters(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1674 int offset, int total_len)
1677 if (total_len < 44)
1679 expert_add_info(pinfo, item, &ei_mal_elink_interface_counters);
1680 return total_len;
1683 proto_tree_add_item(tree, hf_elink_icount_in_octets, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1684 proto_tree_add_item(tree, hf_elink_icount_in_ucast, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1685 proto_tree_add_item(tree, hf_elink_icount_in_nucast, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1686 proto_tree_add_item(tree, hf_elink_icount_in_discards, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1687 proto_tree_add_item(tree, hf_elink_icount_in_errors, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1688 proto_tree_add_item(tree, hf_elink_icount_in_unknown_protos, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
1689 proto_tree_add_item(tree, hf_elink_icount_out_octets, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
1690 proto_tree_add_item(tree, hf_elink_icount_out_ucast, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
1691 proto_tree_add_item(tree, hf_elink_icount_out_nucast, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
1692 proto_tree_add_item(tree, hf_elink_icount_out_discards, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
1693 proto_tree_add_item(tree, hf_elink_icount_out_errors, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
1694 return 44;
1697 static int
1698 dissect_elink_media_counters(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1699 int offset, int total_len)
1702 if (total_len < 48)
1704 expert_add_info(pinfo, item, &ei_mal_elink_media_counters);
1705 return total_len;
1708 proto_tree_add_item(tree, hf_elink_mcount_alignment_errors, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1709 proto_tree_add_item(tree, hf_elink_mcount_fcs_errors, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
1710 proto_tree_add_item(tree, hf_elink_mcount_single_collisions, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
1711 proto_tree_add_item(tree, hf_elink_mcount_multiple_collisions, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
1712 proto_tree_add_item(tree, hf_elink_mcount_sqe_test_errors, tvb, offset+16, 4, ENC_LITTLE_ENDIAN);
1713 proto_tree_add_item(tree, hf_elink_mcount_deferred_transmission, tvb, offset+20, 4, ENC_LITTLE_ENDIAN);
1714 proto_tree_add_item(tree, hf_elink_mcount_late_collisions, tvb, offset+24, 4, ENC_LITTLE_ENDIAN);
1715 proto_tree_add_item(tree, hf_elink_mcount_excessive_collisions, tvb, offset+28, 4, ENC_LITTLE_ENDIAN);
1716 proto_tree_add_item(tree, hf_elink_mcount_mac_transmit_errors, tvb, offset+32, 4, ENC_LITTLE_ENDIAN);
1717 proto_tree_add_item(tree, hf_elink_mcount_carrier_sense_errors, tvb, offset+36, 4, ENC_LITTLE_ENDIAN);
1718 proto_tree_add_item(tree, hf_elink_mcount_frame_too_long, tvb, offset+40, 4, ENC_LITTLE_ENDIAN);
1719 proto_tree_add_item(tree, hf_elink_mcount_mac_receive_errors, tvb, offset+44, 4, ENC_LITTLE_ENDIAN);
1720 return 48;
1723 static int
1724 dissect_elink_interface_capability(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1725 int offset, int total_len _U_)
1727 static int * const bits[] = {
1728 &hf_elink_icapability_capability_bits_manual,
1729 &hf_elink_icapability_capability_bits_auto_neg,
1730 &hf_elink_icapability_capability_bits_auto_mdix,
1731 &hf_elink_icapability_capability_bits_manual_speed,
1732 NULL
1735 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_icapability_capability_bits, ett_elink_icapability_bits, bits, ENC_LITTLE_ENDIAN);
1736 offset += 4;
1738 uint32_t array_count;
1739 proto_tree_add_item_ret_uint(tree, hf_elink_icapability_capability_speed_duplex_array_count, tvb, offset, 1, ENC_NA, &array_count);
1740 offset++;
1742 for (uint32_t i = 0; i < array_count; i++)
1744 proto_tree_add_item(tree, hf_elink_icapability_capability_speed, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1745 offset += 2;
1747 proto_tree_add_item(tree, hf_elink_icapability_capability_duplex, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1748 offset++;
1751 return 4 + 1 + array_count * 3;
1754 static int
1755 dissect_elink_hc_interface_counters(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1756 int offset, int total_len _U_)
1758 proto_tree_add_item(tree, hf_elink_hc_icount_in_octets, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1759 proto_tree_add_item(tree, hf_elink_hc_icount_in_ucast, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
1760 proto_tree_add_item(tree, hf_elink_hc_icount_in_mcast, tvb, offset + 16, 8, ENC_LITTLE_ENDIAN);
1761 proto_tree_add_item(tree, hf_elink_hc_icount_in_broadcast, tvb, offset + 24, 8, ENC_LITTLE_ENDIAN);
1762 proto_tree_add_item(tree, hf_elink_hc_icount_out_octets, tvb, offset + 32, 8, ENC_LITTLE_ENDIAN);
1763 proto_tree_add_item(tree, hf_elink_hc_icount_out_ucast, tvb, offset + 40, 8, ENC_LITTLE_ENDIAN);
1764 proto_tree_add_item(tree, hf_elink_hc_icount_out_mcast, tvb, offset + 48, 8, ENC_LITTLE_ENDIAN);
1765 proto_tree_add_item(tree, hf_elink_hc_icount_out_broadcast, tvb, offset + 56, 8, ENC_LITTLE_ENDIAN);
1767 return 8 * 8;
1770 static int
1771 dissect_elink_hc_media_counters(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
1772 int offset, int total_len _U_)
1774 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_align_errors, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1775 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_fcs_errors, tvb, offset + 8, 8, ENC_LITTLE_ENDIAN);
1776 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_internal_mac_transmit_errors, tvb, offset + 16, 8, ENC_LITTLE_ENDIAN);
1777 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_frame_too_long, tvb, offset + 24, 8, ENC_LITTLE_ENDIAN);
1778 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_internal_mac_receive_errors, tvb, offset + 32, 8, ENC_LITTLE_ENDIAN);
1779 proto_tree_add_item(tree, hf_elink_hc_mcount_stats_symbol_errors, tvb, offset + 40, 8, ENC_LITTLE_ENDIAN);
1781 return 8 * 6;
1784 static int
1785 dissect_elink_interface_control(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1786 int offset, int total_len)
1789 static int * const control_bits[] = {
1790 &hf_elink_icontrol_control_bits_auto_neg,
1791 &hf_elink_icontrol_control_bits_forced_duplex,
1792 &hf_elink_icontrol_control_bits_reserved,
1793 NULL
1796 if (total_len < 4)
1798 expert_add_info(pinfo, item, &ei_mal_elink_interface_control);
1799 return total_len;
1802 proto_tree_add_bitmask(tree, tvb, offset, hf_elink_icontrol_control_bits, ett_elink_icontrol_bits, control_bits, ENC_LITTLE_ENDIAN);
1803 proto_tree_add_item(tree, hf_elink_icontrol_forced_speed, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
1804 return 4;
1807 static int
1808 dissect_dlr_ring_supervisor_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1809 int offset, int total_len)
1812 if (total_len < 12)
1814 expert_add_info(pinfo, item, &ei_mal_dlr_ring_supervisor_config);
1815 return total_len;
1818 proto_tree_add_item(tree, hf_dlr_rsc_ring_supervisor_enable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1819 proto_tree_add_item(tree, hf_dlr_rsc_ring_supervisor_precedence, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1820 proto_tree_add_item(tree, hf_dlr_rsc_beacon_interval, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
1821 proto_tree_add_item(tree, hf_dlr_rsc_beacon_timeout, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
1822 proto_tree_add_item(tree, hf_dlr_rsc_dlr_vlan_id, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
1823 return 12;
1826 static int
1827 dissect_dlr_last_active_node_on_port_1(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1828 int offset, int total_len)
1831 if (total_len < 10)
1833 expert_add_info(pinfo, item, &ei_mal_dlr_last_active_node_on_port_1);
1834 return total_len;
1837 proto_tree_add_item(tree, hf_dlr_lanp1_dev_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1838 proto_tree_add_item(tree, hf_dlr_lanp1_dev_physical_address, tvb, offset+4, 6, ENC_NA);
1839 return 10;
1842 static int
1843 dissect_dlr_last_active_node_on_port_2(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1844 int offset, int total_len)
1847 if (total_len < 10)
1849 expert_add_info(pinfo, item, &ei_mal_dlr_last_active_node_on_port_2);
1850 return total_len;
1853 proto_tree_add_item(tree, hf_dlr_lanp2_dev_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1854 proto_tree_add_item(tree, hf_dlr_lanp2_dev_physical_address, tvb, offset+4, 6, ENC_NA);
1855 return 10;
1858 static int
1859 dissect_dlr_ring_protocol_participants_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1860 int offset, int total_len)
1863 int pos;
1865 if (total_len % 10)
1867 expert_add_info(pinfo, item, &ei_mal_dlr_ring_protocol_participants_list);
1868 return total_len;
1871 pos = 0;
1872 while ( pos < total_len)
1874 proto_tree_add_item(tree, hf_dlr_rppl_dev_ip_addr, tvb, offset+pos, 4, ENC_LITTLE_ENDIAN);
1875 proto_tree_add_item(tree, hf_dlr_rppl_dev_physical_address, tvb, offset+pos+4, 6, ENC_NA);
1876 pos+=10;
1878 return total_len;
1881 static int
1882 dissect_dlr_active_supervisor_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1883 int offset, int total_len)
1886 if (total_len < 10)
1888 expert_add_info(pinfo, item, &ei_mal_dlr_active_supervisor_address);
1889 return total_len;
1892 proto_tree_add_item(tree, hf_dlr_asa_supervisor_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1893 proto_tree_add_item(tree, hf_dlr_asa_supervisor_physical_address, tvb, offset+4, 6, ENC_NA);
1894 return 10;
1897 static int
1898 dissect_dlr_capability_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1899 int offset, int total_len)
1902 static int * const capabilities[] = {
1903 &hf_dlr_capflags_announce_base_node,
1904 &hf_dlr_capflags_beacon_base_node,
1905 &hf_dlr_capflags_reserved1,
1906 &hf_dlr_capflags_supervisor_capable,
1907 &hf_dlr_capflags_redundant_gateway_capable,
1908 &hf_dlr_capflags_flush_frame_capable,
1909 &hf_dlr_capflags_reserved2,
1910 NULL
1913 if (total_len < 4)
1915 expert_add_info(pinfo, item, &ei_mal_dlr_capability_flags);
1916 return total_len;
1919 proto_tree_add_bitmask(tree, tvb, offset, hf_dlr_capability_flags, ett_dlr_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
1920 return 4;
1923 static int
1924 dissect_dlr_redundant_gateway_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1925 int offset, int total_len)
1928 if (total_len < 11)
1930 expert_add_info(pinfo, item, &ei_mal_dlr_redundant_gateway_config);
1931 return total_len;
1934 proto_tree_add_item(tree, hf_dlr_rgc_red_gateway_enable, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1935 proto_tree_add_item(tree, hf_dlr_rgc_gateway_precedence, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1936 proto_tree_add_item(tree, hf_dlr_rgc_advertise_interval, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
1937 proto_tree_add_item(tree, hf_dlr_rgc_advertise_timeout, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
1938 proto_tree_add_item(tree, hf_dlr_rgc_learning_update_enable, tvb, offset+10, 1, ENC_LITTLE_ENDIAN);
1939 return 11;
1942 static int
1943 dissect_dlr_active_gateway_address(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1944 int offset, int total_len)
1947 if (total_len < 10)
1949 expert_add_info(pinfo, item, &ei_mal_dlr_active_gateway_address);
1950 return total_len;
1953 proto_tree_add_item(tree, hf_dlr_aga_ip_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1954 proto_tree_add_item(tree, hf_dlr_aga_physical_address, tvb, offset+4, 6, ENC_NA);
1955 return 10;
1958 static int dissect_cip_security_profiles(packet_info* pinfo _U_, proto_tree* tree, proto_item* item _U_, tvbuff_t* tvb,
1959 int offset, int total_len _U_)
1961 static int* const security_profiles[] = {
1962 &hf_enip_security_profiles_eip_integrity,
1963 &hf_enip_security_profiles_eip_confidentiality,
1964 &hf_enip_security_profiles_cip_authorization,
1965 &hf_enip_security_profiles_cip_user_authentication,
1966 &hf_enip_security_profiles_resource_constrained,
1967 &hf_enip_security_profiles_reserved,
1968 NULL
1971 proto_tree_add_bitmask(tree, tvb, offset, hf_enip_security_profiles, ett_security_profiles, security_profiles, ENC_LITTLE_ENDIAN);
1973 return 2;
1976 static int
1977 dissect_eip_security_cap(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1978 int offset, int total_len)
1981 static int * const capabilities[] = {
1982 &hf_eip_security_capflags_secure_renegotiation,
1983 &hf_eip_security_capflags_reserved,
1984 NULL
1987 if (total_len < 4)
1989 expert_add_info(pinfo, item, &ei_mal_eip_security_capability_flags);
1990 return total_len;
1993 proto_tree_add_bitmask(tree, tvb, offset, hf_eip_security_capability_flags, ett_eip_security_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
1994 return 4;
1997 static int
1998 dissect_eip_security_avail_cipher_suites(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1999 int offset, int total_len)
2002 uint32_t i, num_suites;
2004 if (total_len < 1)
2006 expert_add_info(pinfo, item, &ei_mal_eip_security_avail_cipher_suites);
2007 return total_len;
2010 proto_tree_add_item_ret_uint(tree, hf_eip_security_num_avail_cipher_suites, tvb, offset, 1, ENC_NA, &num_suites);
2011 offset++;
2013 for (i = 0; i < num_suites; i++)
2015 proto_tree_add_item(tree, hf_eip_security_avail_cipher_suite, tvb, offset, 2, ENC_BIG_ENDIAN);
2016 offset += 2;
2019 return ((num_suites*2)+1);
2022 static int
2023 dissect_eip_security_allow_cipher_suites(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2024 int offset, int total_len)
2027 uint32_t i, num_suites;
2029 if (total_len < 1)
2031 expert_add_info(pinfo, item, &ei_mal_eip_security_allow_cipher_suites);
2032 return total_len;
2035 proto_tree_add_item_ret_uint(tree, hf_eip_security_num_allow_cipher_suites, tvb, offset, 1, ENC_NA, &num_suites);
2036 offset++;
2038 for (i = 0; i < num_suites; i++)
2040 proto_tree_add_item(tree, hf_eip_security_allow_cipher_suite, tvb, offset, 2, ENC_BIG_ENDIAN);
2041 offset += 2;
2044 return ((num_suites*2)+1);
2047 static int
2048 dissect_eip_security_preshared_keys(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2049 int offset, int total_len)
2052 uint32_t i, num, id_size, psk_size;
2053 proto_item* ti;
2054 proto_tree* psk_tree;
2055 int start_offset = offset;
2057 if (total_len < 1)
2059 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2060 return total_len;
2063 ti = proto_tree_add_item_ret_uint(tree, hf_eip_security_num_psk, tvb, offset, 1, ENC_NA, &num);
2064 psk_tree = proto_item_add_subtree(ti, ett_eip_security_psk);
2065 offset++;
2067 for (i = 0; i < num; i++)
2069 proto_tree_add_item_ret_uint(psk_tree, hf_eip_security_psk_identity_size, tvb, offset, 1, ENC_NA, &id_size);
2070 if (total_len < (int)(id_size+2))
2072 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2073 return total_len;
2075 offset++;
2076 proto_tree_add_item(psk_tree, hf_eip_security_psk_identity, tvb, offset, id_size, ENC_ASCII);
2077 offset += id_size;
2079 proto_tree_add_item_ret_uint(psk_tree, hf_eip_security_psk_size, tvb, offset, 1, ENC_NA, &psk_size);
2080 offset++;
2081 if (total_len < (int)(id_size+psk_size+2))
2083 expert_add_info(pinfo, item, &ei_mal_eip_security_preshared_keys);
2084 return total_len;
2086 proto_tree_add_item(psk_tree, hf_eip_security_psk, tvb, offset, psk_size, ENC_ASCII);
2087 offset += psk_size;
2089 proto_tree_add_item(psk_tree, hf_eip_security_psk_usage, tvb, offset, 1, ENC_NA);
2090 offset++;
2093 proto_item_set_len(ti, offset-start_offset);
2094 return offset-start_offset;
2097 static int
2098 dissect_eip_security_cert_epath_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len,
2099 expert_field *expert_info, int hf_num_of_certs, const int ett_index)
2101 uint32_t i, num, path_size;
2102 proto_item *ti;
2103 proto_tree* cert_tree;
2104 int start_offset = offset;
2106 if (total_len < 1)
2108 expert_add_info(pinfo, item, expert_info);
2109 return total_len;
2112 ti = proto_tree_add_item_ret_uint(tree, hf_num_of_certs, tvb, offset, 1, ENC_NA, &num);
2113 cert_tree = proto_item_add_subtree(ti, ett_index);
2114 offset++;
2116 for (i = 0; i < num; i++)
2118 path_size = dissect_padded_epath_len_usint(pinfo, cert_tree, ti, tvb, offset, total_len);
2119 offset += path_size;
2121 proto_item_set_len(ti, offset-start_offset);
2122 return offset-start_offset;
2125 static int
2126 dissect_eip_security_active_certs(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len)
2128 return dissect_eip_security_cert_epath_list(pinfo, tree, item, tvb, offset, total_len,
2129 &ei_mal_eip_security_active_certs, hf_eip_security_num_active_certs, ett_eip_security_active_certs);
2132 static int
2133 dissect_eip_security_trusted_auths(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len)
2135 return dissect_eip_security_cert_epath_list(pinfo, tree, item, tvb, offset, total_len,
2136 &ei_mal_eip_security_trusted_auths, hf_eip_security_num_trusted_auths, ett_eip_security_trusted_auths);
2139 static int
2140 dissect_eip_security_cert_revocation_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len)
2142 return dissect_eip_security_cert_epath_list(pinfo, tree, item, tvb, offset, total_len,
2143 &ei_mal_eip_security_crl, hf_eip_security_num_crl, ett_eip_security_crl);
2146 static int
2147 dissect_eip_security_trusted_identities(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len)
2149 return dissect_eip_security_cert_epath_list(pinfo, tree, item, tvb, offset, total_len,
2150 &ei_mal_eip_security_trusted_identities, hf_eip_security_num_trusted_identities, ett_eip_security_trusted_identities);
2153 static int
2154 dissect_eip_cert_cap_flags(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2155 int offset, int total_len)
2157 static int * const capabilities[] = {
2158 &hf_eip_cert_capflags_push,
2159 &hf_eip_cert_capflags_reserved,
2160 NULL
2163 if (total_len < 4)
2165 expert_add_info(pinfo, item, &ei_mal_eip_cert_capability_flags);
2166 return total_len;
2169 proto_tree_add_bitmask(tree, tvb, offset, hf_eip_cert_capability_flags, ett_eip_cert_capability_flags, capabilities, ENC_LITTLE_ENDIAN);
2170 return 4;
2173 static int
2174 dissect_eip_cert_cert_list(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
2175 int offset, int total_len)
2177 uint32_t i, num, path_size;
2178 proto_item *ti;
2179 proto_tree* cert_tree;
2180 int start_offset = offset;
2182 ti = proto_tree_add_item_ret_uint(tree, hf_eip_cert_num_certs, tvb, offset, 1, ENC_NA, &num);
2183 cert_tree = proto_item_add_subtree(ti, ett_eip_cert_num_certs);
2184 offset++;
2186 for (i = 0; i < num; i++)
2188 path_size = tvb_get_uint8( tvb, offset );
2189 proto_tree_add_item(tree, hf_eip_cert_cert_name, tvb, offset+1, path_size, ENC_ASCII);
2190 offset += (1+path_size);
2192 path_size = dissect_padded_epath_len_usint(pinfo, cert_tree, ti, tvb, offset, total_len);
2193 offset += path_size;
2195 proto_item_set_len(ti, offset-start_offset);
2196 return offset-start_offset;
2199 static int
2200 dissect_eip_cert_device_cert(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2201 int offset, int total_len)
2203 uint32_t path_size;
2205 proto_tree_add_item(tree, hf_eip_cert_device_cert_status, tvb, offset, 1, ENC_NA);
2206 offset++;
2208 path_size = dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset, total_len);
2210 return path_size + 1;
2213 static int
2214 dissect_eip_cert_ca_cert(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2215 int offset, int total_len)
2217 uint32_t path_size;
2219 proto_tree_add_item(tree, hf_eip_cert_ca_cert_status, tvb, offset, 1, ENC_NA);
2220 offset++;
2222 path_size = dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset, total_len);
2224 return path_size + 1;
2227 static int dissect_certificate_management_object_verify_certificate(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb, int offset, bool request)
2229 if (request)
2231 proto_tree_add_item(tree, hf_eip_cert_verify_certificate, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2232 return 2;
2234 else
2236 return 0;
2240 /// Ingress Egress - Attributes
2241 int dissect_ingress_tcp_udp_ports_supported(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
2242 int offset, int total_len _U_)
2244 uint32_t port_ranges_array_size;
2245 proto_tree_add_item_ret_uint(tree, hf_ingress_egress_num_ranges, tvb, offset, 2, ENC_LITTLE_ENDIAN, &port_ranges_array_size);
2246 int parsed_len = 2;
2248 for (uint32_t i = 0; i < port_ranges_array_size; i++)
2250 proto_item *port_range_item;
2251 proto_tree *port_range_tree = proto_tree_add_subtree_format(tree, tvb, offset + parsed_len, 4, ett_cmd_data, &port_range_item, "Port Range: %d", i + 1);
2252 proto_tree_add_item(port_range_tree, hf_ingress_egress_port_range_low, tvb, offset + parsed_len, 2, ENC_LITTLE_ENDIAN);
2253 parsed_len += 2;
2254 proto_tree_add_item(port_range_tree, hf_ingress_egress_port_range_high, tvb, offset + parsed_len, 2, ENC_LITTLE_ENDIAN);
2255 parsed_len += 2;
2258 return parsed_len;
2261 int dissect_ingress_egress_rules(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2262 int offset, int total_len _U_)
2264 uint32_t array_size;
2265 proto_tree_add_item_ret_uint(tree, hf_ingress_egress_num_rules, tvb, offset, 2, ENC_LITTLE_ENDIAN, &array_size);
2266 int parsed_len = 2;
2268 proto_item *rule_string_item;
2269 proto_tree *rules_string_tree = proto_tree_add_subtree_format(tree, tvb, offset + parsed_len, 0, ett_cmd_data, &rule_string_item, "Rules: ");
2271 for (uint32_t i = 0; i < array_size; i++)
2273 parsed_len += dissect_cip_string_type(pinfo, rules_string_tree, item, tvb, offset + parsed_len, hf_ingress_egress_rule_string, CIP_SHORT_STRING_TYPE);
2276 return parsed_len;
2280 /// Ingress Egress - Services
2281 int dissect_ingress_egress_set_rules(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb, int offset, bool request)
2283 if (!request)
2285 return 0;
2287 else
2289 proto_tree_add_item(tree, hf_ingress_egress_rules_change_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2291 static int* const apply_behavior[] = {
2292 &hf_ingress_egress_apply_behav_break_connections,
2293 &hf_ingress_egress_apply_behav_reserved,
2294 NULL
2297 proto_tree_add_bitmask(tree, tvb, offset + 4, hf_ingress_egress_apply_behavior, ett_ingress_egress_apply_behavior, apply_behavior, ENC_LITTLE_ENDIAN);
2299 uint32_t instance_rules_array_size;
2300 proto_tree_add_item_ret_uint(tree, hf_ingress_egress_ins_num, tvb, offset + 8, 2, ENC_LITTLE_ENDIAN, &instance_rules_array_size);
2301 int parsed_len = 10;
2303 for (uint32_t i = 0; i < instance_rules_array_size; i++)
2305 proto_item *instance_rule_item;
2306 proto_tree *instance_rule_tree = proto_tree_add_subtree_format(tree, tvb, offset + parsed_len, 0, ett_cmd_data, &instance_rule_item, "Instance Rule: %d", i + 1);
2307 proto_tree_add_item(instance_rule_tree, hf_ingress_egress_ins, tvb, offset + parsed_len, 2, ENC_LITTLE_ENDIAN);
2308 parsed_len += 2;
2310 proto_item *ingress_rules_item;
2311 proto_tree *ingress_rules_tree = proto_tree_add_subtree(instance_rule_tree, tvb, offset + parsed_len, 0, ett_cmd_data, &ingress_rules_item, "Ingress Rules");
2312 parsed_len += dissect_ingress_egress_rules(pinfo, ingress_rules_tree, ingress_rules_item, tvb, offset + parsed_len, tvb_reported_length_remaining(tvb, offset + parsed_len));
2314 proto_item *egress_rules_item;
2315 proto_tree *egress_rules_tree = proto_tree_add_subtree(instance_rule_tree, tvb, offset + parsed_len, 0, ett_cmd_data, &egress_rules_item, "Egress Rules");
2316 parsed_len += dissect_ingress_egress_rules(pinfo, egress_rules_tree, egress_rules_item, tvb, offset + parsed_len, tvb_reported_length_remaining(tvb, offset + parsed_len));
2319 return parsed_len;
2323 // Most of the information for the IANA Port Admin attribute and Set_Port_Admin_State service is the same.
2324 static int dissect_tcpip_port_information(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2325 int offset, bool attribute_version)
2327 int start_offset = offset;
2329 uint32_t port_count;
2330 proto_tree_add_item_ret_uint(tree, hf_tcpip_port_count, tvb, offset, 1, ENC_LITTLE_ENDIAN, &port_count);
2331 offset++;
2333 for (uint32_t i = 0; i < port_count; ++i)
2335 proto_item *port_item;
2336 proto_tree *port_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cmd_data, &port_item, "Port: ");
2338 if (attribute_version == true)
2340 uint8_t length = tvb_get_uint8(tvb, offset);
2341 const char* port_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 1, length, ENC_ASCII);
2343 offset += dissect_cip_string_type(pinfo, port_tree, item, tvb, offset, hf_tcpip_port_name, CIP_SHORT_STRING_TYPE);
2345 proto_item_append_text(port_item, "Name: %s: ", port_name);
2348 uint32_t port_number;
2349 proto_tree_add_item_ret_uint(port_tree, hf_tcpip_port_number, tvb, offset, 2, ENC_LITTLE_ENDIAN, &port_number);
2350 offset += 2;
2351 proto_item_append_text(port_item, "Number: %d", port_number);
2353 proto_tree_add_item(port_tree, hf_tcpip_port_protocol, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2354 offset++;
2356 proto_tree_add_item(port_tree, hf_tcpip_port_admin_state, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2357 offset++;
2359 if (attribute_version == true)
2361 static int* const capability[] = {
2362 &hf_tcpip_admin_capability_configurable,
2363 &hf_tcpip_admin_capability_reset_required,
2364 &hf_tcpip_admin_capability_reserved,
2365 NULL
2368 proto_tree_add_bitmask(port_tree, tvb, offset, hf_tcpip_port_admin_capability, ett_tcpip_admin_capability, capability, ENC_LITTLE_ENDIAN);
2369 offset++;
2373 return offset - start_offset;
2376 static int dissect_tcpip_port_admin(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2377 int offset, int total_len _U_)
2379 return dissect_tcpip_port_information(pinfo, tree, item, tvb, offset, true);
2382 static int dissect_tcpip_set_port_admin_state(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, bool request)
2384 if (request)
2386 return dissect_tcpip_port_information(pinfo, tree, item, tvb, offset, false);
2388 else
2390 return 0;
2394 const attribute_info_t enip_attribute_vals[] = {
2396 /* TCP/IP Object (class attributes) */
2397 {0xF5, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2398 {0xF5, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2399 {0xF5, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2400 {0xF5, true, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2401 {0xF5, true, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2402 {0xF5, true, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2403 {0xF5, true, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2405 /* TCP/IP object (instance attributes) */
2406 {0xF5, false, 1, 0, "Status", cip_dissector_func, NULL, dissect_tcpip_status},
2407 {0xF5, false, 2, 1, "Configuration Capability", cip_dissector_func, NULL, dissect_tcpip_config_cap},
2408 {0xF5, false, 3, 2, "Configuration Control", cip_dissector_func, NULL, dissect_tcpip_config_control},
2409 {0xF5, false, 4, 3, "Physical Link Object", cip_dissector_func, NULL, dissect_tcpip_physical_link},
2410 {0xF5, false, 5, 4, "Interface Configuration", cip_dissector_func, NULL, dissect_tcpip_interface_config},
2411 {0xF5, false, 6, 5, "Host Name", cip_dissector_func, NULL, dissect_tcpip_hostname},
2412 {0xF5, false, 7, 6, "Safety Network Number", cip_dissector_func, NULL, dissect_tcpip_snn},
2413 {0xF5, false, 8, 7, "TTL Value", cip_usint, &hf_tcpip_ttl_value, NULL},
2414 {0xF5, false, 9, 8, "Multicast Configuration", cip_dissector_func, NULL, dissect_tcpip_mcast_config},
2415 {0xF5, false, 10, 9, "Select ACD", cip_bool, &hf_tcpip_select_acd, NULL},
2416 {0xF5, false, 11, 10, "Last Conflict Detected", cip_dissector_func, NULL, dissect_tcpip_last_conflict},
2417 {0xF5, false, 12, 11, "EtherNet/IP Quick Connect", cip_bool, &hf_tcpip_quick_connect, NULL},
2418 {0xF5, false, 13, 12, "Encapsulation Inactivity Timeout", cip_uint, &hf_tcpip_encap_inactivity, NULL},
2419 {0xF5, false, 14, -1, "IANA Port Admin", cip_dissector_func, NULL, dissect_tcpip_port_admin },
2421 /* Ethernet Link Object (class attributes) */
2422 {0xF6, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2423 {0xF6, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2424 {0xF6, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2425 {0xF6, true, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2426 {0xF6, true, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2427 {0xF6, true, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2428 {0xF6, true, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2430 /* Ethernet Link object (instance attributes) */
2431 {0xF6, false, 1, 0, "Interface Speed", cip_dword, &hf_elink_interface_speed, NULL},
2432 {0xF6, false, 2, 1, "Interface Flags", cip_dissector_func, NULL, dissect_elink_interface_flags},
2433 {0xF6, false, 3, 2, "Physical Address", cip_dissector_func, NULL, dissect_elink_physical_address },
2434 {0xF6, false, 4, 3, "Interface Counters", cip_dissector_func, NULL, dissect_elink_interface_counters},
2435 {0xF6, false, 5, 4, "Media Counters", cip_dissector_func, NULL, dissect_elink_media_counters},
2436 {0xF6, false, 6, 5, "Interface Control", cip_dissector_func, NULL, dissect_elink_interface_control},
2437 {0xF6, false, 7, 6, "Interface Type", cip_usint, &hf_elink_interface_type, NULL},
2438 {0xF6, false, 8, 7, "Interface State", cip_usint, &hf_elink_interface_state, NULL},
2439 {0xF6, false, 9, 8, "Admin State", cip_usint, &hf_elink_admin_state, NULL},
2440 {0xF6, false, 10, 9, "Interface Label", cip_short_string, &hf_elink_interface_label, NULL},
2441 {0xF6, false, 11, 10, "Interface Capability", cip_dissector_func, NULL, dissect_elink_interface_capability},
2442 {0xF6, false, 12, 11, "HC Interface Counters", cip_dissector_func, NULL, dissect_elink_hc_interface_counters},
2443 {0xF6, false, 13, 12, "HC Media Counters", cip_dissector_func, NULL, dissect_elink_hc_media_counters},
2445 /* QoS Object (class attributes) */
2446 {0x48, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2447 {0x48, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2448 {0x48, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2449 {0x48, true, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2450 {0x48, true, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2451 {0x48, true, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2452 {0x48, true, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2454 /* QoS object (instance attributes) */
2455 {0x48, false, 1, -1, "802.1Q Tag Enable", cip_bool, &hf_qos_8021q_enable, NULL},
2456 {0x48, false, 2, -1, "DSCP PTP Event", cip_usint, &hf_qos_dscp_ptp_event, NULL},
2457 {0x48, false, 3, -1, "DSCP PTP General", cip_usint, &hf_qos_dscp_ptp_general, NULL},
2458 {0x48, false, 4, -1, "DSCP Urgent", cip_usint, &hf_qos_dscp_urgent, NULL},
2459 {0x48, false, 5, -1, "DSCP Scheduled", cip_usint, &hf_qos_dscp_scheduled, NULL},
2460 {0x48, false, 6, -1, "DSCP High", cip_usint, &hf_qos_dscp_high, NULL},
2461 {0x48, false, 7, -1, "DSCP Low", cip_usint, &hf_qos_dscp_low, NULL},
2462 {0x48, false, 8, -1, "DSCP Explicit", cip_usint, &hf_qos_dscp_explicit, NULL},
2464 /* DLR Object (class attributes) */
2465 {0x47, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2466 {0x47, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2467 {0x47, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2468 {0x47, true, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2469 {0x47, true, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2470 {0x47, true, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2471 {0x47, true, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2473 /* DLR object (instance attributes) */
2474 /* Get Attributes All is not fully parsed here because there are multiple formats. */
2475 {0x47, false, 1, 0, "Network Topology", cip_usint, &hf_dlr_network_topology, NULL},
2476 {0x47, false, 2, 1, "Network Status", cip_usint, &hf_dlr_network_status, NULL},
2477 {0x47, false, 3, -1, "Ring Supervisor Status", cip_usint, &hf_dlr_ring_supervisor_status, NULL},
2478 {0x47, false, 4, -1, "Ring Supervisor Config", cip_dissector_func, NULL, dissect_dlr_ring_supervisor_config},
2479 {0x47, false, 5, -1, "Ring Faults Count", cip_uint, &hf_dlr_ring_faults_count, NULL},
2480 {0x47, false, 6, -1, "Last Active Node on Port 1", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_1},
2481 {0x47, false, 7, -1, "Last Active Node on Port 2", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_2},
2482 {0x47, false, 8, -1, "Ring Protocol Participants Count", cip_uint, &hf_dlr_ring_protocol_participants_count, NULL},
2483 {0x47, false, 9, -1, "Ring Protocol Participants List", cip_dissector_func, NULL, dissect_dlr_ring_protocol_participants_list},
2484 {0x47, false, 10, -1, "Active Supervisor Address", cip_dissector_func, NULL, dissect_dlr_active_supervisor_address},
2485 {0x47, false, 11, -1, "Active Supervisor Precedence", cip_usint, &hf_dlr_active_supervisor_precedence, NULL},
2486 {0x47, false, 12, -1, "Capability Flags", cip_dissector_func, NULL, dissect_dlr_capability_flags},
2487 {0x47, false, 13, -1, "Redundant Gateway Config", cip_dissector_func, NULL, dissect_dlr_redundant_gateway_config},
2488 {0x47, false, 14, -1, "Redundant Gateway Status", cip_usint, &hf_dlr_redundant_gateway_status, NULL},
2489 {0x47, false, 15, -1, "Active Gateway Address", cip_dissector_func, NULL, dissect_dlr_active_gateway_address},
2490 {0x47, false, 16, -1, "Active Gateway Precedence", cip_usint, &hf_dlr_active_gateway_precedence, NULL},
2492 /* CIP Security Object (instance attributes) */
2493 {0x5D, CIP_ATTR_INSTANCE, 1, 0, "State", cip_usint, &hf_cip_security_state, NULL},
2494 {0x5D, CIP_ATTR_INSTANCE, 2, 1, "Security Profiles", cip_dissector_func, NULL, dissect_cip_security_profiles },
2496 /* EtherNet/IP Security object (instance attributes) */
2497 {0x5E, false, 1, 0, "State", cip_usint, &hf_eip_security_state, NULL},
2498 {0x5E, false, 2, 1, "Capability Flags", cip_dissector_func, NULL, dissect_eip_security_cap},
2499 {0x5E, false, 3, 2, "Available Cipher Suites", cip_dissector_func, NULL, dissect_eip_security_avail_cipher_suites},
2500 {0x5E, false, 4, 3, "Allowed Cipher Suites", cip_dissector_func, NULL, dissect_eip_security_allow_cipher_suites},
2501 {0x5E, false, 5, 4, "Pre-Shared Keys", cip_dissector_func, NULL, dissect_eip_security_preshared_keys},
2502 {0x5E, false, 6, 5, "Active Device Certificates", cip_dissector_func, NULL, dissect_eip_security_active_certs},
2503 {0x5E, false, 7, 6, "Trusted Authorities", cip_dissector_func, NULL, dissect_eip_security_trusted_auths},
2504 {0x5E, false, 8, 7, "Certificate Revocation List", cip_dissector_func, NULL, dissect_eip_security_cert_revocation_list},
2505 {0x5E, false, 9, 8, "Verify Client Certificate", cip_bool, &hf_eip_security_verify_client_cert, NULL},
2506 {0x5E, false, 10, 9, "Send Certificate Chain", cip_bool, &hf_eip_security_send_cert_chain, NULL},
2507 {0x5E, false, 11, 10, "Check Expiration", cip_bool, &hf_eip_security_check_expiration, NULL},
2508 {0x5E, false, 12, 11, "Trusted Identities", cip_dissector_func, NULL, dissect_eip_security_trusted_identities},
2510 /* Certificate Management Object (class attributes) */
2511 {0x5F, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
2512 {0x5F, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
2513 {0x5F, true, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
2514 {0x5F, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
2515 {0x5F, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
2516 {0x5F, true, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
2517 {0x5F, true, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
2518 {0x5F, true, 8, 4, "Capability Flags", cip_dissector_func, NULL, dissect_eip_cert_cap_flags },
2519 {0x5F, true, 9, 5, "Certificate List", cip_dissector_func, NULL, dissect_eip_cert_cert_list },
2521 /* Certificate Management Object (instance attributes) */
2522 {0x5F, false, 1, 0, "Name", cip_short_string, &hf_eip_cert_name, NULL},
2523 {0x5F, false, 2, 1, "State", cip_usint, &hf_eip_cert_state, NULL},
2524 {0x5F, false, 3, 2, "Device Certificate", cip_dissector_func, NULL, dissect_eip_cert_device_cert},
2525 {0x5F, false, 4, 3, "CA Certificate", cip_dissector_func, NULL, dissect_eip_cert_ca_cert},
2526 {0x5F, false, 5, 4, "Certificate Encoding", cip_usint, &hf_eip_cert_encoding, NULL },
2528 /* Ingress Egress Object (class attributes) */
2529 {0x63, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL},
2530 {0x63, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL},
2531 {0x63, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL},
2532 {0x63, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list},
2533 {0x63, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list},
2534 {0x63, true, 6, 3, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL},
2535 {0x63, true, 7, 4, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL},
2536 {0x63, true, 8, 5, "Ingress Rules TCP Ports Supported", cip_dissector_func, NULL, dissect_ingress_tcp_udp_ports_supported},
2537 {0x63, true, 9, 6, "Ingress Rules UDP Ports Supported", cip_dissector_func, NULL, dissect_ingress_tcp_udp_ports_supported},
2539 /* Ingress Egress Object (instance attributes) */
2540 {0x63, false, 1, 0, "Ingress Rules", cip_dissector_func, NULL, dissect_ingress_egress_rules},
2541 {0x63, false, 2, 1, "Egress Rules", cip_dissector_func, NULL, dissect_ingress_egress_rules},
2545 // Table of CIP services defined by this dissector.
2546 static cip_service_info_t enip_obj_spec_service_table[] = {
2547 // CIP Security
2548 { 0x5D, 0x4B, "Begin_Config", NULL },
2549 { 0x5D, 0x4C, "Kick_Timer", NULL },
2550 { 0x5D, 0x4D, "End_Config", NULL },
2551 { 0x5D, 0x4E, "Object_Cleanup", NULL },
2553 // EtherNet/IP Security
2554 { 0x5E, 0x4B, "Begin_Config", NULL },
2555 { 0x5E, 0x4C, "Kick_Timer", NULL },
2556 { 0x5E, 0x4E, "Abort_Config", NULL },
2558 // Certificate Management
2559 { 0x5F, 0x4C, "Verify_Certificate", dissect_certificate_management_object_verify_certificate },
2561 // Ingress Egress Object
2562 { 0x63, 0x4B, "Set_Rules", dissect_ingress_egress_set_rules },
2564 // TCP/IP Interface
2565 { 0xF5, 0x4C, "Set_Port_Admin_State", dissect_tcpip_set_port_admin_state },
2568 // Look up a given CIP service from this dissector.
2569 cip_service_info_t* cip_get_service_enip(uint32_t class_id, uint8_t service_id)
2571 return cip_get_service_one_table(&enip_obj_spec_service_table[0],
2572 array_length(enip_obj_spec_service_table),
2573 class_id,
2574 service_id);
2577 static void enip_init_protocol(void)
2579 enip_unique_connid = 0;
2582 // offset - Starts at the "Encapsulation Protocol Version" field.
2583 static void dissect_item_list_identity(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree)
2585 /* Encapsulation version */
2586 proto_tree_add_item(item_tree, hf_enip_encapver, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2588 /* Socket Address */
2589 proto_tree* sockaddr_tree = proto_tree_add_subtree(item_tree, tvb, offset + 2, 16, ett_sockadd, NULL, "Socket Address");
2591 /* Socket address struct - sin_family */
2592 proto_tree_add_item(sockaddr_tree, hf_enip_sinfamily, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2594 /* Socket address struct - sin_port */
2595 proto_tree_add_item(sockaddr_tree, hf_enip_sinport, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
2597 /* Socket address struct - sin_address */
2598 proto_tree_add_item(sockaddr_tree, hf_enip_sinaddr, tvb, offset + 6, 4, ENC_BIG_ENDIAN);
2600 /* Socket address struct - sin_zero */
2601 proto_tree_add_item(sockaddr_tree, hf_enip_sinzero, tvb, offset + 10, 8, ENC_NA);
2603 /* Vendor ID */
2604 proto_tree_add_item(item_tree, hf_enip_lir_vendor, tvb, offset + 18, 2, ENC_LITTLE_ENDIAN);
2606 /* Device Type */
2607 proto_tree_add_item(item_tree, hf_enip_lir_devtype, tvb, offset + 20, 2, ENC_LITTLE_ENDIAN);
2609 /* Product Code */
2610 proto_tree_add_item(item_tree, hf_enip_lir_prodcode, tvb, offset + 22, 2, ENC_LITTLE_ENDIAN);
2612 /* Revision */
2613 proto_tree_add_item(item_tree, hf_enip_lir_revision, tvb, offset + 24, 2, ENC_BIG_ENDIAN);
2615 /* Status */
2616 proto_tree_add_item(item_tree, hf_enip_lir_status, tvb, offset + 26, 2, ENC_LITTLE_ENDIAN);
2618 /* Serial Number */
2619 proto_tree_add_item(item_tree, hf_enip_lir_serial, tvb, offset + 28, 4, ENC_LITTLE_ENDIAN);
2621 /* Product Name Length */
2622 uint32_t name_length;
2623 proto_tree_add_item_ret_uint(item_tree, hf_enip_lir_namelen, tvb, offset + 32, 1, ENC_LITTLE_ENDIAN, &name_length);
2625 /* Product Name */
2626 proto_tree_add_item(item_tree, hf_enip_lir_name, tvb, offset + 33, name_length, ENC_ASCII | ENC_NA);
2628 /* Append product name to info column */
2629 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", tvb_format_text(pinfo->pool, tvb, offset + 33, name_length));
2631 /* State */
2632 proto_tree_add_item(item_tree, hf_enip_lir_state, tvb, offset + name_length + 33, 1, ENC_LITTLE_ENDIAN);
2635 // offset - Starts at the "Security Profiles" field.
2636 static void dissect_item_cip_security_information(tvbuff_t* tvb, int offset, proto_tree* item_tree)
2638 static int * const iana_flags[] = {
2639 &hf_enip_iana_port_state_flags_tcp_44818,
2640 &hf_enip_iana_port_state_flags_udp_44818,
2641 &hf_enip_iana_port_state_flags_udp_2222,
2642 &hf_enip_iana_port_state_flags_tcp_2221,
2643 &hf_enip_iana_port_state_flags_udp_2221,
2644 &hf_enip_iana_port_state_flags_reserved,
2645 NULL
2648 dissect_cip_security_profiles(NULL, item_tree, NULL, tvb, offset, tvb_reported_length_remaining(tvb, offset));
2650 /* CIP Security object state */
2651 proto_tree_add_item(item_tree, hf_enip_cip_security_state, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
2653 /* ENIP Security object state */
2654 proto_tree_add_item(item_tree, hf_enip_eip_security_state, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
2656 /* IANA Port State flags */
2657 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);
2660 // offset - Starts at the "Encapsulation Protocol Version" field.
2661 static void dissect_item_list_services_response(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree)
2663 /* Encapsulation version */
2664 proto_tree_add_item(item_tree, hf_enip_encapver, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2666 /* Capability flags */
2667 static int* const capability_bits[] = {
2668 &hf_enip_lsr_tcp,
2669 &hf_enip_lsr_udp,
2670 NULL
2672 proto_tree_add_bitmask(item_tree, tvb, offset + 2, hf_enip_lsr_capaflags, ett_lsrcf, capability_bits, ENC_LITTLE_ENDIAN);
2674 /* Name of service */
2675 proto_tree_add_item(item_tree, hf_enip_lsr_servicename, tvb, offset + 4, 16, ENC_ASCII | ENC_NA);
2677 /* Append service name to info column */
2678 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
2679 tvb_format_stringzpad(pinfo->pool, tvb, offset + 4, 16));
2682 void display_fwd_open_connection_path(cip_conn_info_t* conn_info, proto_tree* tree, tvbuff_t* tvb, packet_info* pinfo)
2684 if (!conn_info->pFwdOpenPathData)
2686 return;
2689 tvbuff_t* tvbIOI = tvb_new_real_data((const uint8_t*)conn_info->pFwdOpenPathData, conn_info->FwdOpenPathLenBytes, conn_info->FwdOpenPathLenBytes);
2690 if (tvbIOI)
2692 proto_item* pi = NULL;
2693 proto_tree* epath_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_path_info, &pi, "Forward Open Connection Path: ");
2694 proto_item_set_generated(pi);
2696 dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, conn_info->FwdOpenPathLenBytes, true, false, NULL, NULL, NO_DISPLAY, NULL, false);
2697 tvb_free(tvbIOI);
2701 // returns true if this is a likely Heartbeat message
2702 // Note: item_length include the CIP Sequence Count, if applicable.
2703 static bool cip_io_is_likely_heartbeat(const cip_conn_info_t* conn_info, enum enip_connid_type connid_type, uint32_t item_length)
2705 // Heartbeat messages only occur in the O->T direction.
2706 if (connid_type != ECIDT_O2T)
2708 return false;
2711 // Class 0 heartbeat messages have 0 length.
2712 if (item_length == 0)
2714 return true;
2717 // The only other possibility for a heartbeat is for Class 1 (the 2 bytes is the Sequence Count)
2718 if (item_length != 2)
2720 return false;
2723 // The only possibility for a heartbeat is: Class 1 with 2 bytes of data only, and it must be a "Fixed" size.
2724 uint8_t transport_class = conn_info->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK;
2725 if (transport_class == 1 && conn_info->O2T.connection_size_type == CIP_CONNECTION_SIZE_TYPE_FIXED)
2727 return true;
2729 return false;
2732 static void display_connection_information(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, cip_conn_info_t* conn_info,
2733 enum enip_connid_type connid_type, uint32_t item_length)
2735 proto_item* conn_info_item = NULL;
2736 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
2737 proto_item_set_generated(conn_info_item);
2739 if (connid_type == ECIDT_O2T)
2741 proto_item_append_text(conn_info_item, ": O->T");
2743 else if (connid_type == ECIDT_T2O)
2745 proto_item_append_text(conn_info_item, ": T->O");
2748 display_fwd_open_connection_path(conn_info, conn_info_tree, tvb, pinfo);
2750 proto_item* pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_ot_api, tvb, 0, 0, conn_info->O2T.api);
2751 proto_item_set_generated(pi);
2753 pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_to_api, tvb, 0, 0, conn_info->T2O.api);
2754 proto_item_set_generated(pi);
2756 pi = proto_tree_add_uint(conn_info_tree, hf_cip_connection, tvb, 0, 0, conn_info->connid);
2757 proto_item_set_generated(pi);
2759 pi = proto_tree_add_uint(conn_info_tree, hf_enip_fwd_open_in, tvb, 0, 0, conn_info->open_req_frame);
2760 proto_item_set_generated(pi);
2762 if (cip_io_is_likely_heartbeat(conn_info, connid_type, item_length))
2764 expert_add_info(pinfo, conn_info_item, &ei_cip_io_heartbeat);
2768 // This dissects Class 0 or Class 1 I/O.
2769 // offset - Starts at the field after the Item Length field.
2770 static int dissect_cip_io_generic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data)
2772 cip_io_data_input* io_data_input = (cip_io_data_input*)data;
2774 int offset = 0;
2776 proto_item* ti = proto_tree_add_item(tree, proto_cipio, tvb, 0, -1, ENC_NA);
2777 proto_tree* io_tree = proto_item_add_subtree(ti, ett_cip_io_generic);
2779 if (io_data_input != NULL)
2781 if ((io_data_input->conn_info->TransportClass_trigger & CI_TRANSPORT_CLASS_MASK) == 1)
2783 proto_tree_add_item(io_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2784 offset += 2;
2787 if ((tvb_reported_length_remaining(tvb, offset) >= 4) &&
2788 (((io_data_input->connid_type == ECIDT_O2T) && enip_OTrun_idle) ||
2789 ((io_data_input->connid_type == ECIDT_T2O) && enip_TOrun_idle)))
2791 dissect_cip_run_idle(tvb, offset, io_tree);
2792 offset += 4;
2796 proto_tree_add_item(io_tree, hf_cip_io_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
2798 return tvb_captured_length(tvb);
2801 // Dissect the various kinds of CIP Class 0/1 I/O formats. This will determine the appropriate format and
2802 // call the appropriate related dissector.
2803 // offset - Starts at the field after the Item Length field.
2804 static void dissect_cip_class01_io(packet_info* pinfo, tvbuff_t* tvb, int offset,
2805 int item_length, cip_conn_info_t* conn_info, enum enip_connid_type connid_type,
2806 proto_tree* dissector_tree)
2808 if (tvb_reported_length_remaining(tvb, offset) <= 0)
2810 return;
2813 /* Display data */
2814 tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset, item_length);
2815 if (conn_info != NULL)
2817 cip_io_data_input io_data_input;
2818 io_data_input.conn_info = conn_info;
2819 io_data_input.connid_type = connid_type;
2821 if (conn_info->safety.safety_seg == true)
2823 /* Add any possible safety related data */
2824 cip_safety_info_t cip_safety;
2825 cip_safety.conn_type = connid_type;
2826 cip_safety.eip_conn_info = conn_info;
2827 cip_safety.compute_crc = true;
2829 call_dissector_with_data(cipsafety_handle, next_tvb, pinfo, dissector_tree, &cip_safety);
2831 else
2833 dissector_handle_t dissector = dissector_get_uint_handle(subdissector_io_table, conn_info->connection_path.iClass);
2834 if (dissector)
2836 call_dissector_with_data(dissector, next_tvb, pinfo, dissector_tree, &io_data_input);
2838 else
2840 call_dissector_with_data(cip_io_generic_handle, next_tvb, pinfo, dissector_tree, &io_data_input);
2844 else
2846 // This handles the Decode As options
2847 if (!dissector_try_payload_with_data(subdissector_decode_as_io_table, next_tvb, pinfo, dissector_tree, true, NULL))
2849 call_dissector_with_data(cip_io_generic_handle, next_tvb, pinfo, dissector_tree, NULL);
2854 // Dissect CIP Class 2/3 data. This will determine the appropriate format and call the appropriate related dissector.
2855 // offset - Starts at the field after the Item Length field.
2856 static void dissect_cip_class23_data(packet_info* pinfo, tvbuff_t* tvb, int offset,
2857 proto_tree* tree, proto_tree* item_tree, uint32_t item_length,
2858 enip_request_key_t* request_key, cip_conn_info_t* conn_info, proto_tree* dissector_tree)
2860 enip_request_info_t* request_info = NULL;
2862 if (request_key)
2864 request_key->type = EPDT_CONNECTED_TRANSPORT;
2865 request_key->data.connected_transport.sequence = tvb_get_letohs(tvb, offset);
2866 request_info = enip_match_request(pinfo, tree, request_key);
2869 /* Add sequence count ( Transport Class 2,3 ) */
2870 proto_tree_add_item(item_tree, hf_cip_sequence_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2872 /* Call dissector for interface */
2873 tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset + 2, item_length - 2);
2875 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO, request_info);
2877 if (conn_info != NULL)
2879 dissector_handle_t dissector = dissector_get_uint_handle(subdissector_cip_connection_table, conn_info->connection_path.iClass);
2880 if (dissector)
2882 call_dissector_with_data(dissector, next_tvb, pinfo, dissector_tree, GUINT_TO_POINTER(conn_info->connection_path.iClass));
2884 else
2886 call_dissector_with_data(cip_implicit_handle, next_tvb, pinfo, dissector_tree, GUINT_TO_POINTER(conn_info->connection_path.iClass));
2889 else
2891 // Default to Message Router format, since this is the most common. Since we don't have the connection
2892 // info, at least ensure that the data can at least meet the minimum explicit message size.
2893 if (tvb_reported_length(next_tvb) >= 2)
2895 call_dissector(cip_handle, next_tvb, pinfo, dissector_tree);
2899 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2902 // offset - Starts at the sin_family field.
2903 static void dissect_item_sockaddr_info(packet_info *pinfo, tvbuff_t* tvb, int offset, proto_tree* item_tree,
2904 uint32_t item_type_id, bool is_fwd_open)
2906 /* Socket address struct - sin_family */
2907 proto_tree_add_item(item_tree, hf_enip_sinfamily, tvb, offset, 2, ENC_BIG_ENDIAN);
2909 /* Socket address struct - sin_port */
2910 proto_tree_add_item(item_tree, hf_enip_sinport, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
2912 /* Socket address struct - sin_address */
2913 proto_tree_add_item(item_tree, hf_enip_sinaddr, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
2915 /* Socket address struct - sin_zero */
2916 proto_tree_add_item(item_tree, hf_enip_sinzero, tvb, offset + 8, 8, ENC_NA);
2918 if (is_fwd_open)
2920 enip_request_info_t* request_info = (enip_request_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
2921 if (request_info != NULL)
2923 if (item_type_id == CPF_ITEM_SOCK_ADR_INFO_OT)
2925 request_info->cip_info->connInfo->O2T.port = tvb_get_ntohs(tvb, offset + 2);
2926 alloc_address_tvb(wmem_file_scope(), &request_info->cip_info->connInfo->O2T.ipaddress,
2927 AT_IPv4, sizeof(uint32_t), tvb, offset + 4);
2929 else
2931 request_info->cip_info->connInfo->T2O.port = tvb_get_ntohs(tvb, offset + 2);
2932 alloc_address_tvb(wmem_file_scope(), &request_info->cip_info->connInfo->T2O.ipaddress,
2933 AT_IPv4, sizeof(uint32_t), tvb, offset + 4);
2939 // offset - Starts at the Connection ID
2940 // Returns: connid_type, conn_info
2941 static void dissect_item_sequenced_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
2942 proto_tree* tree, enum enip_connid_type* connid_type, cip_conn_info_t** conn_info)
2944 uint32_t connection_id;
2945 proto_tree_add_item_ret_uint(tree, hf_enip_cpf_sai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &connection_id);
2946 proto_item* pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2947 proto_item_set_hidden(pi);
2949 uint32_t sequence_num;
2950 proto_tree_add_item_ret_uint(tree, hf_enip_cpf_sai_seqnum, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &sequence_num);
2952 *conn_info = enip_get_io_connid(pinfo, connection_id, connid_type);
2954 col_add_fstr(pinfo->cinfo, COL_INFO, "Connection: ID=0x%08X, SEQ=%010u", connection_id, sequence_num);
2955 if (*connid_type == ECIDT_O2T)
2957 col_append_str(pinfo->cinfo, COL_INFO, ", O->T");
2959 else if (*connid_type == ECIDT_T2O)
2961 col_append_str(pinfo->cinfo, COL_INFO, ", T->O");
2965 // offset - Starts at the Connection ID
2966 // Returns: conn_info
2967 static void dissect_item_connected_address(packet_info* pinfo, tvbuff_t* tvb, int offset,
2968 proto_tree* item_tree, proto_item* enip_item,
2969 enip_request_key_t* request_key, cip_conn_info_t** conn_info)
2971 uint32_t connection_id;
2972 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_cai_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &connection_id);
2973 proto_item* pi = proto_tree_add_item(item_tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2974 proto_item_set_hidden(pi);
2976 *conn_info = enip_get_explicit_connid(pinfo, request_key, connection_id);
2977 if (request_key)
2979 request_key->type = EPDT_CONNECTED_TRANSPORT;
2980 request_key->data.connected_transport.connid = (*conn_info != NULL) ? (*conn_info)->connid : 0;
2983 /* Add Connection ID to Info col and tree */
2984 col_append_fstr(pinfo->cinfo, COL_INFO, ", Connection: ID=0x%08X", connection_id);
2986 if (enip_item)
2988 proto_item_append_text(enip_item, ", Connection ID: 0x%08X", connection_id);
2992 // offset - Starts at Unconn Msg Type
2993 // returns - input_request_key
2994 // Dissects the following parts of the Unconnected Message over UDP item: Unconn Msg Type, Transaction Number, Status.
2995 // The Unconnected Message field is handled outside of this function.
2996 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)
2998 uint32_t ucmm_request;
2999 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_ucmm_request, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ucmm_request);
3000 proto_tree_add_item(item_tree, hf_enip_cpf_ucmm_msg_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3002 uint32_t trans_id;
3003 proto_tree_add_item_ret_uint(item_tree, hf_enip_cpf_ucmm_trans_id, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN, &trans_id);
3004 proto_tree_add_item(item_tree, hf_enip_cpf_ucmm_status, tvb, offset + 6, 4, ENC_LITTLE_ENDIAN);
3006 if (*input_request_key == NULL)
3009 * Under normal circumstances request_key should always be NULL here
3010 * Duplicating setting up a request (like is done with explicit messaging)
3012 conversation_t* conversation = find_or_create_conversation(pinfo);
3015 * Attach that information to the conversation, and add
3016 * it to the list of information structures later before dissection.
3018 enip_request_key_t* request_key = wmem_new0(pinfo->pool, enip_request_key_t);
3019 request_key->requesttype = ucmm_request ? ENIP_RESPONSE_PACKET : ENIP_REQUEST_PACKET;
3020 request_key->type = EPDT_UNKNOWN;
3022 /* UCMM over UDP doesn't have a session handle, so use conversation
3023 * pointer as "unique-ish ID"
3025 request_key->session_handle = GPOINTER_TO_UINT(conversation);
3026 request_key->sender_context = trans_id;
3027 request_key->conversation = conversation->conv_index;
3029 // Return the new request key.
3030 *input_request_key = request_key;
3034 static bool is_forward_open(uint8_t cip_service)
3036 return (cip_service == SC_CM_FWD_OPEN
3037 || cip_service == SC_CM_CONCURRENT_FWD_OPEN
3038 || cip_service == SC_CM_LARGE_FWD_OPEN);
3041 /* Dissect Common Packet Format */
3042 static void
3043 dissect_cpf(enip_request_key_t *request_key, int command, tvbuff_t *tvb,
3044 packet_info *pinfo, proto_tree *tree, proto_tree *dissector_tree, proto_tree *enip_layer_tree,
3045 proto_item *enip_item, int offset, uint32_t ifacehndl)
3047 proto_item *count_item;
3048 proto_tree *count_tree;
3049 int item_count;
3051 // The following variables are set in one pass of the loop, and read in a second pass.
3052 cip_conn_info_t* conn_info = NULL;
3053 bool FwdOpenRequest = false;
3054 bool FwdOpenReply = false;
3055 enum enip_connid_type connid_type = ECIDT_UNKNOWN;
3057 // Normal "Common Packet Format" configurations. See CIP Volume 2, Section 2-6.4.
3058 // SendRRData (Unconnected):
3059 // Item 1: CPF_ITEM_NULL
3060 // Item 2: CPF_ITEM_UNCONNECTED_DATA
3061 // SendUnitData (Connected, Class 3):
3062 // Item 1: CPF_ITEM_CONNECTED_ADDRESS
3063 // Item 2: CPF_ITEM_CONNECTED_DATA
3064 // Item 3 (Optional): CPF_ITEM_SOCK_ADR_INFO_OT/CPF_ITEM_SOCK_ADR_INFO_TO
3065 // Class 0/1 packet:
3066 // Item 1: CPF_ITEM_SEQUENCED_ADDRESS
3067 // Item 2: CPF_ITEM_CONNECTED_DATA
3068 // Unconnected Message over UDP:
3069 // Item 1: CPF_ITEM_UNCONNECTED_MSG_DTLS
3071 /* Create item count tree */
3072 item_count = tvb_get_letohs( tvb, offset );
3073 count_item = proto_tree_add_item( tree, hf_enip_cpf_itemcount, tvb, offset, 2, ENC_LITTLE_ENDIAN );
3074 count_tree = proto_item_add_subtree( count_item, ett_count_tree );
3075 offset += 2;
3077 while ( item_count-- )
3079 // Verify that we have the minimum CPF Item size.
3080 if (tvb_reported_length_remaining(tvb, offset) < 4)
3082 expert_add_info_format(pinfo, count_item, &ei_mal_cpf_item_minimum_size,
3083 "%s, but Remaining Data Length is %d",
3084 expert_get_summary(&ei_mal_cpf_item_minimum_size), tvb_reported_length_remaining(tvb, offset));
3086 break;
3089 /* Add item type tree to item count tree*/
3090 uint32_t item_type_id;
3091 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 );
3092 proto_tree* item_tree = proto_item_add_subtree( type_item, ett_type_tree );
3093 offset += 2;
3095 /* Add length field to item type tree */
3096 uint32_t item_length;
3097 proto_tree_add_item_ret_uint( item_tree, hf_enip_cpf_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &item_length);
3098 offset += 2;
3100 // Check if the declared item length is more bytes than we have available. But, don't exit early
3101 // so maybe it will be more obvious where the problem is.
3102 if ((int)item_length > tvb_reported_length_remaining(tvb, offset))
3104 expert_add_info_format(pinfo, type_item, &ei_mal_cpf_item_length_mismatch,
3105 "%s: Item Length %d, Remaining Data Length: %d",
3106 expert_get_summary(&ei_mal_cpf_item_length_mismatch), item_length, tvb_reported_length_remaining(tvb, offset));
3109 // offset now starts at the data field after the Item Length field. The name of this
3110 // field varies depending on the item type.
3111 if ( item_length )
3113 /* Add item data field */
3115 switch ( item_type_id )
3117 case CPF_ITEM_CONNECTED_ADDRESS: // 1st Item for: Class 3 Connected Messages
3118 conn_info = NULL;
3119 dissect_item_connected_address(pinfo, tvb, offset, item_tree, enip_item, request_key, &conn_info);
3120 break;
3122 case CPF_ITEM_UNCONNECTED_MSG_DTLS: // Only item for: Unconnected messages over DTLS
3124 ifacehndl = ENIP_CIP_INTERFACE;
3126 dissect_item_unconnected_message_over_udp(pinfo, tvb, offset, item_tree, &request_key);
3128 // Skip over the fields already parsed before falling through.
3129 offset += 10;
3130 item_length -= 10;
3133 /* Intentionally fall through */
3135 case CPF_ITEM_UNCONNECTED_DATA: // 2nd Item for: Unconnected Messages
3137 enip_request_info_t* request_info = NULL;
3138 if ( request_key )
3140 request_key->type = EPDT_UNCONNECTED;
3141 request_info = enip_match_request( pinfo, tree, request_key );
3144 /* Call dissector for interface */
3145 tvbuff_t* next_tvb = tvb_new_subset_length( tvb, offset, item_length);
3146 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO, request_info);
3147 if ( tvb_reported_length_remaining(next_tvb, 0) <= 0 || !dissector_try_uint(subdissector_srrd_table, ifacehndl, next_tvb, pinfo, dissector_tree) )
3149 /* Show the undissected payload */
3150 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
3151 call_data_dissector(next_tvb, pinfo, dissector_tree);
3154 /* Check if this is a ForwardOpen packet, because special handling is needed
3155 to handle connection conversations */
3156 if ((request_info != NULL) && (request_info->cip_info != NULL) &&
3157 (request_info->cip_info->connInfo != NULL) &&
3158 (request_key != NULL) &&
3159 is_forward_open(request_info->cip_info->bService & CIP_SC_MASK) &&
3160 (request_info->cip_info->dissector == dissector_get_uint_handle(subdissector_class_table, CI_CLS_CM)))
3162 if (request_key->requesttype == ENIP_REQUEST_PACKET)
3164 FwdOpenRequest = true;
3166 else
3168 FwdOpenReply = true;
3171 else
3173 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
3175 break;
3178 case CPF_ITEM_CONNECTED_DATA: // 2nd item for: Connected messages (both Class 0/1 and Class 3)
3179 // Save the connection info for the conversation filter
3181 if (conn_info && conn_info->is_concurrent_connection)
3183 int cc_header_len = dissect_concurrent_connection_packet(pinfo, tvb, offset, dissector_tree);
3185 // The header length only includes the beginning part of the header. But, the actual data length
3186 // needs to remove the header AND the CRC field. The CRC field was parsed as part of the previous
3187 // header function.
3188 offset += cc_header_len;
3189 item_length = item_length - cc_header_len - CC_CRC_LENGTH;
3192 if (!pinfo->fd->visited && conn_info)
3194 p_add_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO, conn_info);
3197 if (command == SEND_UNIT_DATA) // Class 2/3 over TCP.
3199 dissect_cip_class23_data(pinfo, tvb, offset, tree, item_tree, item_length, request_key, conn_info, dissector_tree);
3201 else // No command. Send as CPF items only over UDP.
3203 dissect_cip_class01_io(pinfo, tvb, offset, item_length, conn_info, connid_type, dissector_tree);
3206 if (conn_info)
3208 display_connection_information(pinfo, tvb, enip_layer_tree, conn_info, connid_type, item_length);
3211 break;
3213 case CPF_ITEM_CIP_IDENTITY:
3214 dissect_item_list_identity(pinfo, tvb, offset, item_tree);
3215 break;
3217 case CPF_ITEM_CIP_SECURITY:
3218 dissect_item_cip_security_information(tvb, offset, item_tree);
3219 break;
3221 case CPF_ITEM_SOCK_ADR_INFO_OT: // Optional 3rd item for: Unconnected Messages
3222 case CPF_ITEM_SOCK_ADR_INFO_TO:
3224 bool is_fwd_open = (FwdOpenRequest == true) || (FwdOpenReply == true);
3225 dissect_item_sockaddr_info(pinfo, tvb, offset, item_tree, item_type_id, is_fwd_open);
3226 break;
3229 case CPF_ITEM_SEQUENCED_ADDRESS: // 1st item for: Class 0/1 connected data
3230 conn_info = NULL;
3231 dissect_item_sequenced_address(pinfo, tvb, offset, item_tree, &connid_type, &conn_info);
3232 break;
3234 case CPF_ITEM_LIST_SERVICES_RESP:
3235 dissect_item_list_services_response(pinfo, tvb, offset, item_tree);
3236 break;
3238 default:
3239 proto_tree_add_item(item_tree, hf_enip_cpf_data, tvb, offset, item_length, ENC_NA);
3240 break;
3242 } /* end of switch ( item type ) */
3244 } /* end of if ( item length ) */
3246 offset += item_length;
3247 } /* end of while ( item count ) */
3249 /* See if there is a CIP connection to establish */
3250 if (FwdOpenReply == true)
3252 enip_request_info_t* request_info = (enip_request_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
3253 if (request_info != NULL)
3255 enip_open_cip_connection(pinfo, request_info->cip_info->connInfo, request_info->cip_info->bService & CIP_SC_MASK);
3257 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
3259 else if (FwdOpenRequest == true)
3261 p_remove_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
3264 } /* end of dissect_cpf() */
3268 static enum enip_packet_type
3269 classify_packet(packet_info *pinfo)
3271 /* see if nature of packets can be derived from src/dst ports */
3272 /* if so, return as found */
3273 if (((ENIP_ENCAP_PORT == pinfo->srcport && ENIP_ENCAP_PORT != pinfo->destport)) ||
3274 ((ENIP_SECURE_PORT == pinfo->srcport && ENIP_SECURE_PORT != pinfo->destport)))
3276 return ENIP_RESPONSE_PACKET;
3278 else if (((ENIP_ENCAP_PORT != pinfo->srcport && ENIP_ENCAP_PORT == pinfo->destport)) ||
3279 ((ENIP_SECURE_PORT != pinfo->srcport && ENIP_SECURE_PORT == pinfo->destport)))
3281 return ENIP_REQUEST_PACKET;
3283 else
3285 return ENIP_CANNOT_CLASSIFY;
3289 static unsigned
3290 get_enip_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
3292 uint16_t plen;
3295 * Get the length of the data from the encapsulation header.
3297 plen = tvb_get_letohs(tvb, offset + 2);
3300 * That length doesn't include the encapsulation header itself;
3301 * add that in.
3303 return plen + 24;
3306 /* Code to actually dissect the packets */
3307 static int
3308 dissect_enip_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3310 enum enip_packet_type packet_type;
3311 uint16_t encap_cmd, encap_data_length;
3312 const char *pkt_type_str;
3313 uint32_t ifacehndl;
3314 conversation_t *conversation;
3316 /* Set up structures needed to add the protocol subtree and manage it */
3317 proto_item *ti = NULL;
3318 proto_tree *enip_tree, *header_tree = NULL, *csftree;
3320 /* Make entries in Protocol column and Info column on summary display */
3321 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENIP");
3322 col_clear(pinfo->cinfo, COL_INFO);
3324 encap_cmd = tvb_get_letohs( tvb, 0 );
3326 packet_type = classify_packet(pinfo);
3328 switch ( packet_type )
3330 case ENIP_REQUEST_PACKET:
3331 pkt_type_str = "Req";
3332 break;
3334 case ENIP_RESPONSE_PACKET:
3335 pkt_type_str = "Rsp";
3336 break;
3338 case ENIP_CANNOT_CLASSIFY:
3339 default:
3340 pkt_type_str = "?";
3343 /* Add encapsulation command to info column */
3344 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " | ", "%s (%s)",
3345 val_to_str(encap_cmd, encap_cmd_vals, "Unknown Command (0x%04x)"),
3346 pkt_type_str );
3349 * We need to track some state for this protocol on a per conversation
3350 * basis so we can do neat things like request/response tracking
3352 conversation = find_or_create_conversation(pinfo);
3355 * Attach that information to the conversation, and add
3356 * it to the list of information structures later before dissection.
3358 enip_request_key_t request_key = {0};
3359 request_key.requesttype = packet_type;
3360 request_key.type = EPDT_UNKNOWN;
3361 request_key.session_handle = tvb_get_letohl( tvb, 4 );
3362 request_key.sender_context = tvb_get_letoh64( tvb, 12 );
3363 request_key.conversation = conversation->conv_index;
3365 /* create display subtree for the protocol */
3366 ti = proto_tree_add_item(tree, proto_enip, tvb, 0, -1, ENC_NA );
3368 enip_tree = proto_item_add_subtree(ti, ett_enip);
3370 /* Add encapsulation header tree */
3371 header_tree = proto_tree_add_subtree( enip_tree, tvb, 0, 24, ett_enip, NULL, "Encapsulation Header");
3373 /* Add EtherNet/IP encapsulation header */
3374 proto_tree_add_item( header_tree, hf_enip_command, tvb, 0, 2, ENC_LITTLE_ENDIAN );
3376 encap_data_length = tvb_get_letohs( tvb, 2 );
3377 proto_tree_add_item( header_tree, hf_enip_length, tvb, 2, 2, ENC_LITTLE_ENDIAN );
3378 proto_tree_add_item( header_tree, hf_enip_session, tvb, 4, 4, ENC_LITTLE_ENDIAN );
3379 proto_tree_add_item( header_tree, hf_enip_status, tvb, 8, 4, ENC_LITTLE_ENDIAN );
3380 if ((encap_cmd == LIST_IDENTITY) &&
3381 /* Length of 0 probably indicates a request */
3382 ((encap_data_length == 0) || (packet_type == ENIP_REQUEST_PACKET)))
3384 proto_tree_add_item( header_tree, hf_enip_listid_delay, tvb, 12, 2, ENC_LITTLE_ENDIAN );
3385 proto_tree_add_item( header_tree, hf_enip_sendercontex, tvb, 14, 6, ENC_NA );
3387 else
3389 proto_tree_add_item( header_tree, hf_enip_sendercontex, tvb, 12, 8, ENC_NA );
3391 proto_tree_add_item( header_tree, hf_enip_options, tvb, 20, 4, ENC_LITTLE_ENDIAN );
3393 /* Append session and command to the protocol tree */
3394 proto_item_append_text( ti, ", Session: 0x%08X, %s", tvb_get_letohl( tvb, 4 ),
3395 val_to_str( encap_cmd, encap_cmd_vals, "Unknown Command (0x%04x)" ) );
3398 ** For some commands we want to add some info to the info column
3400 switch ( encap_cmd )
3402 case REGISTER_SESSION:
3403 case UNREGISTER_SESSION:
3404 col_append_fstr( pinfo->cinfo, COL_INFO, ", Session: 0x%08X",
3405 tvb_get_letohl( tvb, 4 ) );
3406 break;
3409 /* The packet may have some command specific data, build a sub tree for it */
3410 csftree = proto_tree_add_subtree( enip_tree, tvb, 24, encap_data_length,
3411 ett_command_tree, NULL, "Command Specific Data");
3413 switch ( encap_cmd )
3415 case NOP:
3416 break;
3418 case LIST_SERVICES:
3419 case LIST_IDENTITY:
3420 case LIST_INTERFACES:
3421 if (packet_type == ENIP_RESPONSE_PACKET)
3423 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 24, 0 );
3425 break;
3427 case REGISTER_SESSION:
3428 proto_tree_add_item( csftree, hf_enip_rs_version, tvb, 24, 2, ENC_LITTLE_ENDIAN );
3429 proto_tree_add_item( csftree, hf_enip_rs_optionflags, tvb, 26, 2, ENC_LITTLE_ENDIAN );
3430 break;
3432 case UNREGISTER_SESSION:
3433 break;
3435 case SEND_RR_DATA:
3436 proto_tree_add_item( csftree, hf_enip_srrd_ifacehnd, tvb, 24, 4, ENC_LITTLE_ENDIAN );
3437 proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
3439 ifacehndl = tvb_get_letohl( tvb, 24 );
3440 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, NULL, 30, ifacehndl );
3441 break;
3443 case SEND_UNIT_DATA:
3444 proto_tree_add_item(csftree, hf_enip_sud_ifacehnd, tvb, 24, 4, ENC_LITTLE_ENDIAN);
3445 proto_tree_add_item( csftree, hf_enip_timeout, tvb, 28, 2, ENC_LITTLE_ENDIAN );
3447 ifacehndl = tvb_get_letohl( tvb, 24 );
3448 dissect_cpf( &request_key, encap_cmd, tvb, pinfo, csftree, tree, enip_tree, ti, 30, ifacehndl );
3450 break;
3452 case START_DTLS:
3453 if (packet_type == ENIP_RESPONSE_PACKET)
3455 ssl_starttls_ack(dtls_handle, pinfo, enip_udp_handle);
3457 break;
3459 default:
3460 /* Can not decode - Just show the data */
3461 proto_tree_add_item(header_tree, hf_enip_encap_data, tvb, 24, encap_data_length, ENC_NA);
3462 break;
3464 } /* end of switch () */
3466 col_set_fence(pinfo->cinfo, COL_INFO);
3468 return tvb_captured_length(tvb);
3469 } /* end of dissect_enip_pdu() */
3471 static int
3472 dissect_enip_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3474 /* An ENIP packet is at least 4 bytes long. */
3475 if (tvb_captured_length(tvb) < 4)
3476 return 0;
3478 return dissect_enip_pdu(tvb, pinfo, tree, data);
3481 static int
3482 dissect_enip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3484 // TCP connections for EtherNet/IP are typically open for extended periods of time.
3485 // This means that mostly likely, for real world traffic, a capture initiated for
3486 // EtherNet/IP traffic will start in the middle of a TCP connection. This check
3487 // ignores one byte TCP payloads because it is far more likely that a one byte TCP
3488 // payload is a TCP keep alive message, than a client actually sending real EtherNet/IP
3489 // messages in one byte chunks.
3490 if (tvb_captured_length(tvb) < 2)
3491 return 0;
3493 tcp_dissect_pdus(tvb, pinfo, tree, enip_desegment, 4, get_enip_pdu_len, dissect_enip_pdu, data);
3494 return tvb_captured_length(tvb);
3497 /* Code to actually dissect the io packets*/
3498 static int
3499 dissect_enip_cipio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3501 /* Set up structures needed to add the protocol subtree and manage it */
3502 proto_item *ti;
3503 proto_tree *enip_tree;
3505 /* Make entries in Protocol column and Info column on summary display */
3506 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP I/O");
3508 /* create display subtree for the protocol */
3509 ti = proto_tree_add_item(tree, proto_enip, tvb, 0, -1, ENC_NA );
3511 enip_tree = proto_item_add_subtree(ti, ett_enip);
3513 dissect_cpf( NULL, 0xFFFF, tvb, pinfo, enip_tree, tree, enip_tree, NULL, 0, 0 );
3515 return tvb_captured_length(tvb);
3519 static int
3520 dissect_dlr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3522 proto_item *ti;
3523 proto_tree *dlr_tree;
3524 uint8_t dlr_subtype;
3525 uint8_t dlr_protover;
3526 uint8_t dlr_frametype;
3528 /* Make entries in Protocol column and Info column on summary display */
3529 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLR");
3531 col_clear(pinfo->cinfo, COL_INFO);
3533 /* Create display subtree for the protocol */
3534 ti = proto_tree_add_item(tree, proto_dlr, tvb, 0, -1, ENC_NA );
3535 dlr_tree = proto_item_add_subtree( ti, ett_dlr );
3537 /* Get values for the Common Frame Header Format */
3538 dlr_subtype = tvb_get_uint8(tvb, DLR_CFH_SUB_TYPE);
3539 dlr_protover = tvb_get_uint8(tvb, DLR_CFH_PROTO_VERSION);
3541 /* Dissect the Common Frame Header Format */
3542 proto_tree_add_uint( dlr_tree, hf_dlr_ringsubtype, tvb, DLR_CFH_SUB_TYPE, 1, dlr_subtype );
3543 proto_tree_add_uint( dlr_tree, hf_dlr_ringprotoversion, tvb, DLR_CFH_PROTO_VERSION, 1, dlr_protover );
3545 /* Get values for the DLR Message Payload Fields */
3546 dlr_frametype = tvb_get_uint8(tvb, DLR_MPF_FRAME_TYPE);
3548 /* Dissect the DLR Message Payload Fields */
3549 proto_tree_add_item( dlr_tree, hf_dlr_frametype, tvb, DLR_MPF_FRAME_TYPE, 1, ENC_BIG_ENDIAN );
3550 proto_tree_add_item( dlr_tree, hf_dlr_sourceport, tvb, DLR_MPF_SOURCE_PORT, 1, ENC_BIG_ENDIAN );
3551 proto_tree_add_item( dlr_tree, hf_dlr_sourceip, tvb, DLR_MPF_SOURCE_IP, 4, ENC_BIG_ENDIAN );
3552 proto_tree_add_item( dlr_tree, hf_dlr_sequenceid, tvb, DLR_MPF_SEQUENCE_ID, 4, ENC_BIG_ENDIAN );
3554 /* Add frame type to col info */
3555 col_add_str(pinfo->cinfo, COL_INFO,
3556 val_to_str(dlr_frametype, dlr_frame_type_vals, "Unknown (0x%04x)") );
3558 if ( dlr_frametype == DLR_FT_BEACON )
3560 /* Beacon */
3561 proto_tree_add_item( dlr_tree, hf_dlr_ringstate, tvb, DLR_BE_RING_STATE, 1, ENC_BIG_ENDIAN );
3562 proto_tree_add_item( dlr_tree, hf_dlr_supervisorprecedence, tvb, DLR_BE_SUPERVISOR_PRECEDENCE, 1, ENC_BIG_ENDIAN );
3563 proto_tree_add_item( dlr_tree, hf_dlr_beaconinterval, tvb, DLR_BE_BEACON_INTERVAL, 4, ENC_BIG_ENDIAN );
3564 proto_tree_add_item( dlr_tree, hf_dlr_beacontimeout, tvb, DLR_BE_BEACON_TIMEOUT, 4, ENC_BIG_ENDIAN );
3565 proto_tree_add_item( dlr_tree, hf_dlr_beaconreserved, tvb, DLR_BE_RESERVED, 20, ENC_NA );
3567 else if ( dlr_frametype == DLR_FT_NEIGHBOR_REQ )
3569 /* Neighbor_Check_Request */
3570 proto_tree_add_item( dlr_tree, hf_dlr_nreqreserved, tvb, DLR_NREQ_RESERVED, 30, ENC_NA );
3572 else if ( dlr_frametype == DLR_FT_NEIGHBOR_RES )
3574 /* Neighbor_Check_Response */
3575 proto_tree_add_item( dlr_tree, hf_dlr_nressourceport, tvb, DLR_NRES_SOURCE_PORT, 1, ENC_BIG_ENDIAN );
3576 proto_tree_add_item( dlr_tree, hf_dlr_nresreserved, tvb, DLR_NRES_RESERVED, 29, ENC_NA );
3578 else if ( dlr_frametype == DLR_FT_LINK_STAT )
3580 /* Link_Status/Neighbor_Status */
3581 static int* const bits[] = {
3582 &hf_dlr_lnknbrstatus_port1,
3583 &hf_dlr_lnknbrstatus_port2,
3584 &hf_dlr_lnknbrstatus_reserved,
3585 &hf_dlr_lnknbrstatus_frame_type,
3586 NULL
3589 proto_tree_add_bitmask(dlr_tree, tvb, DLR_LNS_SOURCE_PORT, hf_dlr_lnknbrstatus, ett_dlr_lnknbrstatus_flags, bits, ENC_LITTLE_ENDIAN);
3591 proto_tree_add_item( dlr_tree, hf_dlr_lnknbrreserved, tvb, DLR_LNS_RESERVED, 29, ENC_NA );
3593 else if ( dlr_frametype == DLR_FT_LOCATE_FLT )
3595 /* Locate_Fault */
3596 proto_tree_add_item( dlr_tree, hf_dlr_lfreserved, tvb, DLR_LF_RESERVED, 30, ENC_NA );
3598 else if ( dlr_frametype == DLR_FT_ANNOUNCE )
3600 /* Announce */
3601 proto_tree_add_item( dlr_tree, hf_dlr_ringstate, tvb, DLR_AN_RING_STATE, 1, ENC_BIG_ENDIAN );
3602 proto_tree_add_item( dlr_tree, hf_dlr_anreserved, tvb, DLR_AN_RESERVED, 29, ENC_NA );
3604 else if ( dlr_frametype == DLR_FT_SIGN_ON )
3606 uint16_t nCnt;
3607 uint16_t nNumNodes;
3608 uint16_t nOffset;
3611 /* Sign_On */
3612 nNumNodes = tvb_get_ntohs(tvb, DLR_SO_NUM_NODES);
3614 proto_tree_add_uint( dlr_tree, hf_dlr_sonumnodes, tvb, DLR_SO_NUM_NODES, 2, nNumNodes );
3616 /* Add each node in the list */
3617 for( nCnt = 0, nOffset = DLR_SO_NODE_1_MAC; nCnt < nNumNodes; nCnt++ )
3619 proto_tree_add_item( dlr_tree, hf_dlr_somac, tvb, nOffset, 6, ENC_NA );
3620 nOffset += 6;
3621 proto_tree_add_item( dlr_tree, hf_dlr_soip, tvb, nOffset, 4, ENC_BIG_ENDIAN );
3622 nOffset += 4;
3625 if ( nOffset < 42 )
3627 proto_tree_add_item( dlr_tree, hf_dlr_soreserved, tvb, nOffset, 42 - nOffset, ENC_NA );
3628 /* nOffset += (42 - nOffset); */
3631 else if ( dlr_frametype == DLR_FT_ADVERTISE )
3633 /* Advertise */
3634 proto_tree_add_item( dlr_tree, hf_dlr_advgatewaystate, tvb, DLR_ADV_GATEWAY_STATE, 1, ENC_BIG_ENDIAN );
3635 proto_tree_add_item( dlr_tree, hf_dlr_advgatewayprecedence, tvb, DLR_ADV_GATEWAY_PRECEDENCE, 1, ENC_BIG_ENDIAN );
3636 proto_tree_add_item( dlr_tree, hf_dlr_advadvertiseinterval, tvb, DLR_ADV_ADVERTISE_INTERVAL, 4, ENC_BIG_ENDIAN );
3637 proto_tree_add_item( dlr_tree, hf_dlr_advadvertisetimeout, tvb, DLR_ADV_ADVERTISE_TIMEOUT, 4, ENC_BIG_ENDIAN );
3638 proto_tree_add_item( dlr_tree, hf_dlr_advlearningupdateenable, tvb, DLR_ADV_LEARNING_UPDATE_ENABLE, 1, ENC_BIG_ENDIAN );
3639 proto_tree_add_item( dlr_tree, hf_dlr_advreserved, tvb, DLR_ADV_RESERVED, 19, ENC_NA );
3641 else if ( dlr_frametype == DLR_FT_FLUSH_TABLES )
3643 proto_tree_add_item( dlr_tree, hf_dlr_flushlearningupdateenable, tvb, DLR_FLUSH_LEARNING_UPDATE_ENABLE, 1, ENC_BIG_ENDIAN );
3644 proto_tree_add_item( dlr_tree, hf_dlr_flushreserved, tvb, DLR_FLUSH_RESERVED, 29, ENC_NA );
3646 else if ( dlr_frametype == DLR_FT_LEARNING_UPDATE )
3648 proto_tree_add_item( dlr_tree, hf_dlr_learnreserved, tvb, DLR_LEARN_RESERVED, 34, ENC_NA );
3650 else
3652 /* Unknown Frame type */
3655 return tvb_captured_length(tvb);
3657 } /* end of dissect_dlr() */
3659 static int dissect_cip_class1(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
3661 cip_conn_info_t conn_info;
3662 memset(&conn_info, 0, sizeof(conn_info));
3663 conn_info.TransportClass_trigger = 1;
3665 cip_io_data_input io_data_input;
3666 io_data_input.conn_info = &conn_info;
3667 io_data_input.connid_type = ECIDT_UNKNOWN;
3669 return dissect_cip_io_generic(tvb, pinfo, tree, &io_data_input);
3672 /* Register the protocol with Wireshark */
3674 /* this format is require because a script is used to build the C function
3675 that calls all the protocol registration.
3678 void
3679 proto_register_enip(void)
3681 /* Setup list of header fields */
3682 static hf_register_info hf[] = {
3683 { &hf_enip_command,
3684 { "Command", "enip.command",
3685 FT_UINT16, BASE_HEX, VALS(encap_cmd_vals), 0,
3686 "Encapsulation command", HFILL }},
3688 { &hf_enip_length,
3689 { "Length", "enip.length",
3690 FT_UINT16, BASE_DEC, NULL, 0,
3691 "Encapsulation length", HFILL }},
3693 { &hf_enip_session,
3694 { "Session Handle", "enip.session",
3695 FT_UINT32, BASE_HEX, NULL, 0,
3696 "Session identification", HFILL }},
3698 { &hf_enip_status,
3699 { "Status", "enip.status",
3700 FT_UINT32, BASE_HEX, VALS(encap_status_vals), 0,
3701 "Status code", HFILL }},
3703 { &hf_enip_sendercontex,
3704 { "Sender Context", "enip.context",
3705 FT_BYTES, BASE_NONE, NULL, 0,
3706 "Information pertinent to the sender", HFILL }},
3708 { &hf_enip_listid_delay,
3709 { "Max Response Delay", "enip.listid_delay",
3710 FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliseconds), 0,
3711 "Maximum random delay allowed by target", HFILL }},
3713 { &hf_enip_options,
3714 { "Options", "enip.options",
3715 FT_UINT32, BASE_HEX, NULL, 0,
3716 "Options flags", HFILL }},
3718 { &hf_enip_encapver,
3719 { "Encapsulation Protocol Version", "enip.encapver",
3720 FT_UINT16, BASE_DEC, NULL, 0,
3721 NULL, HFILL }},
3723 { &hf_enip_sinfamily,
3724 { "sin_family", "enip.sinfamily",
3725 FT_UINT16, BASE_DEC, NULL, 0,
3726 "Socket Address.Sin Family", HFILL }},
3728 { &hf_enip_sinport,
3729 { "sin_port", "enip.sinport",
3730 FT_UINT16, BASE_DEC, NULL, 0,
3731 "Socket Address.Sin Port", HFILL }},
3733 { &hf_enip_sinaddr,
3734 { "sin_addr", "enip.sinaddr",
3735 FT_IPv4, BASE_NONE, NULL, 0,
3736 "Socket Address.Sin Addr", HFILL }},
3738 { &hf_enip_sinzero,
3739 { "sin_zero", "enip.sinzero",
3740 FT_BYTES, BASE_NONE, NULL, 0,
3741 "Socket Address.Sin Zero", HFILL }},
3743 { &hf_enip_timeout,
3744 { "Timeout", "enip.timeout",
3745 FT_UINT16, BASE_DEC, NULL, 0,
3746 "Encapsulation Timeout", HFILL }},
3748 { &hf_enip_encap_data,
3749 { "Encap Data", "enip.encap_data",
3750 FT_BYTES, BASE_NONE | BASE_ALLOW_ZERO, NULL, 0,
3751 "Encapsulation Data", HFILL }},
3753 /* List Services Reply */
3754 { &hf_enip_lsr_capaflags,
3755 { "Capability Flags", "enip.lsr.capaflags",
3756 FT_UINT16, BASE_HEX, NULL, 0,
3757 "ListServices Reply: Capability Flags", HFILL }},
3759 { &hf_enip_lsr_tcp,
3760 { "Supports CIP Encapsulation via TCP", "enip.lsr.capaflags.tcp",
3761 FT_BOOLEAN, 16, NULL, 0x0020,
3762 "ListServices Reply: Supports CIP Encapsulation via TCP", HFILL }},
3764 { &hf_enip_lsr_udp,
3765 { "Supports CIP Class 0 or 1 via UDP", "enip.lsr.capaflags.udp",
3766 FT_BOOLEAN, 16, NULL, 0x0100,
3767 "ListServices Reply: Supports CIP Class 0 or 1 via UDP", HFILL }},
3769 { &hf_enip_lsr_servicename,
3770 { "Name of Service", "enip.lsr.servicename",
3771 FT_STRING, BASE_NONE, NULL, 0,
3772 "ListServices Reply: Name of Service", HFILL }},
3774 /* Register Session */
3775 { &hf_enip_rs_version,
3776 { "Protocol Version", "enip.rs.version",
3777 FT_UINT16, BASE_DEC, NULL, 0,
3778 "Register Session: Protocol Version", HFILL }},
3780 { &hf_enip_rs_optionflags,
3781 { "Option Flags", "enip.rs.flags",
3782 FT_UINT16, BASE_HEX, NULL, 0,
3783 "Register Session: Option Flags", HFILL }},
3785 /* Send Request/Reply Data */
3786 { &hf_enip_srrd_ifacehnd,
3787 { "Interface Handle", "enip.srrd.iface",
3788 FT_UINT32, BASE_HEX, VALS(enip_interface_handle_vals), 0,
3789 "SendRRData: Interface handle", HFILL }},
3791 /* Send Unit Data */
3792 { &hf_enip_sud_ifacehnd,
3793 { "Interface Handle", "enip.sud.iface",
3794 FT_UINT32, BASE_HEX, VALS(enip_interface_handle_vals), 0,
3795 "SendUnitData: Interface handle", HFILL }},
3797 /* List identity reply */
3798 { &hf_enip_lir_vendor,
3799 { "Vendor ID", "enip.lir.vendor",
3800 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0,
3801 "ListIdentity Reply: Vendor ID", HFILL }},
3803 { &hf_enip_lir_devtype,
3804 { "Device Type", "enip.lir.devtype",
3805 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &cip_devtype_vals_ext, 0,
3806 "ListIdentity Reply: Device Type", HFILL }},
3808 { &hf_enip_lir_prodcode,
3809 { "Product Code", "enip.lir.prodcode",
3810 FT_UINT16, BASE_DEC, NULL, 0,
3811 "ListIdentity Reply: Product Code", HFILL }},
3813 { &hf_enip_lir_revision,
3814 { "Revision", "enip.lir.revision",
3815 FT_UINT16, BASE_CUSTOM, CF_FUNC(enip_fmt_lir_revision), 0,
3816 "ListIdentity Reply: Revision", HFILL }},
3818 { &hf_enip_lir_status,
3819 { "Status", "enip.lir.status",
3820 FT_UINT16, BASE_HEX, NULL, 0,
3821 "ListIdentity Reply: Status", HFILL }},
3823 { &hf_enip_lir_serial,
3824 { "Serial Number", "enip.lir.serial",
3825 FT_UINT32, BASE_HEX, NULL, 0,
3826 "ListIdentity Reply: Serial Number", HFILL }},
3828 { &hf_enip_lir_namelen,
3829 { "Product Name Length", "enip.lir.namelen",
3830 FT_UINT8, BASE_DEC, NULL, 0,
3831 "ListIdentity Reply: Product Name Length", HFILL }},
3833 { &hf_enip_lir_name,
3834 { "Product Name", "enip.lir.name",
3835 FT_STRING, BASE_NONE, NULL, 0,
3836 "ListIdentity Reply: Product Name", HFILL }},
3838 { &hf_enip_lir_state,
3839 { "State", "enip.lir.state",
3840 FT_UINT8, BASE_HEX, NULL, 0,
3841 "ListIdentity Reply: State", HFILL }},
3843 { &hf_enip_security_profiles,
3844 { "Security Profiles", "enip.security_profiles",
3845 FT_UINT16, BASE_HEX, NULL, 0,
3846 NULL, HFILL }},
3848 { &hf_enip_security_profiles_eip_integrity,
3849 { "EtherNet/IP Integrity Profile", "enip.security_profiles.eip_integrity",
3850 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0001,
3851 NULL, HFILL }},
3853 { &hf_enip_security_profiles_eip_confidentiality,
3854 { "EtherNet/IP Confidentiality Profile", "enip.security_profiles.eip_confidentiality",
3855 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0002,
3856 NULL, HFILL }},
3858 { &hf_enip_security_profiles_cip_authorization,
3859 { "CIP Authorization Profile", "enip.security_profiles.cip_authorization",
3860 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0004,
3861 NULL, HFILL }},
3863 { &hf_enip_security_profiles_cip_user_authentication,
3864 { "CIP User Authentication Profile", "enip.security_profiles.cip_user_authentication",
3865 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0008,
3866 NULL, HFILL }},
3868 { &hf_enip_security_profiles_resource_constrained,
3869 { "Resource-Constrained CIP Security Profile", "enip.security_profiles.resource_constrained",
3870 FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x0010,
3871 NULL, HFILL } },
3873 { &hf_enip_security_profiles_reserved,
3874 { "Reserved", "enip.security_profiles.reserved",
3875 FT_UINT16, BASE_HEX, NULL, 0xFFE0,
3876 NULL, HFILL }},
3878 { &hf_enip_cip_security_state,
3879 { "CIP Security State", "enip.cip_security_state",
3880 FT_UINT8, BASE_DEC, VALS(cip_security_state_vals), 0,
3881 NULL, HFILL }},
3883 { &hf_enip_eip_security_state,
3884 { "EtherNet/IP Security State", "enip.eip_security_state",
3885 FT_UINT8, BASE_DEC, VALS(eip_security_state_vals), 0,
3886 NULL, HFILL }},
3888 { &hf_ingress_egress_num_ranges,
3889 { "Number of Port Ranges", "cip.ingress_egress.num_port_ranges",
3890 FT_UINT16, BASE_DEC, NULL, 0,
3891 NULL, HFILL } },
3892 { &hf_ingress_egress_port_range_low,
3893 { "Port Range Low", "cip.ingress_egress.port_range.low",
3894 FT_UINT16, BASE_DEC, NULL, 0,
3895 NULL, HFILL } },
3896 { &hf_ingress_egress_port_range_high,
3897 { "Port Range High", "cip.ingress_egress.port_range.high",
3898 FT_UINT16, BASE_DEC, NULL, 0,
3899 NULL, HFILL } },
3900 { &hf_ingress_egress_num_rules,
3901 { "Number of Rules", "cip.ingress_egress.num_rules",
3902 FT_UINT16, BASE_DEC, NULL, 0,
3903 NULL, HFILL } },
3904 { &hf_ingress_egress_rule_string,
3905 { "Rule String", "cip.ingress_egress.rule_string",
3906 FT_STRING, BASE_NONE, NULL, 0,
3907 NULL, HFILL } },
3908 { &hf_ingress_egress_rules_change_count,
3909 { "Rules Change Count", "cip.ingress_egress.rules_change_count",
3910 FT_UINT32, BASE_DEC, NULL, 0,
3911 NULL, HFILL } },
3912 { &hf_ingress_egress_apply_behavior,
3913 { "Apply Behavior", "cip.ingress_egress.apply_behavior",
3914 FT_UINT32, BASE_HEX, NULL, 0,
3915 NULL, HFILL } },
3916 { &hf_ingress_egress_apply_behav_break_connections,
3917 { "Break Connections", "cip.ingress_egress.apply_behavior.break_connections",
3918 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000001,
3919 NULL, HFILL } },
3920 { &hf_ingress_egress_apply_behav_reserved,
3921 { "Reserved", "cip.ingress_egress.apply_behavior.reserved",
3922 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFE,
3923 NULL, HFILL } },
3924 { &hf_ingress_egress_ins_num,
3925 { "Number of Instance Rules", "cip.ingress_egress.num_instances",
3926 FT_UINT16, BASE_DEC, NULL, 0,
3927 NULL, HFILL } },
3928 { &hf_ingress_egress_ins,
3929 { "Instance Number", "cip.ingress_egress.instance",
3930 FT_UINT16, BASE_DEC, NULL, 0,
3931 NULL, HFILL } },
3933 { &hf_enip_iana_port_state_flags,
3934 { "IANA Port State", "enip.iana_port_state_flags",
3935 FT_UINT8, BASE_HEX, NULL, 0,
3936 NULL, HFILL }},
3938 { &hf_enip_iana_port_state_flags_tcp_44818,
3939 { "44818/tcp", "enip.security_profiles.iana_port_state_flags.tcp_44818",
3940 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x01,
3941 NULL, HFILL }},
3943 { &hf_enip_iana_port_state_flags_udp_44818,
3944 { "44818/udp", "enip.security_profiles.iana_port_state_flags.udp_44818",
3945 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x02,
3946 NULL, HFILL }},
3948 { &hf_enip_iana_port_state_flags_udp_2222,
3949 { "2222/udp", "enip.security_profiles.iana_port_state_flags.udp_2222",
3950 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x04,
3951 NULL, HFILL }},
3953 { &hf_enip_iana_port_state_flags_tcp_2221,
3954 { "2221/tcp", "enip.security_profiles.iana_port_state_flags.tcp_2221",
3955 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x08,
3956 NULL, HFILL }},
3958 { &hf_enip_iana_port_state_flags_udp_2221,
3959 { "2221/udp", "enip.security_profiles.iana_port_state_flags.udp_2221",
3960 FT_BOOLEAN, 8, TFS(&tfs_open_closed), 0x10,
3961 NULL, HFILL }},
3963 { &hf_enip_iana_port_state_flags_reserved,
3964 { "Reserved", "enip.iana_port_state_flags.reserved",
3965 FT_UINT8, BASE_HEX, NULL, 0xE0,
3966 NULL, HFILL }},
3968 /* Common Packet Format */
3969 { &hf_enip_cpf_itemcount,
3970 { "Item Count", "enip.cpf.itemcount",
3971 FT_UINT16, BASE_DEC, NULL, 0,
3972 "Common Packet Format: Item Count", HFILL }},
3974 { &hf_enip_cpf_typeid,
3975 { "Type ID", "enip.cpf.typeid",
3976 FT_UINT16, BASE_HEX, VALS(cpf_type_vals), 0,
3977 "Common Packet Format: Type of encapsulated item", HFILL }},
3979 { &hf_enip_cpf_length,
3980 { "Length", "enip.cpf.length",
3981 FT_UINT16, BASE_DEC, NULL, 0,
3982 "Common Packet Format: Length", HFILL }},
3984 /* Connected Data Item */
3985 { &hf_cip_sequence_count,
3986 { "CIP Sequence Count", "cip.seq",
3987 FT_UINT16, BASE_DEC, NULL, 0,
3988 NULL, HFILL }},
3990 /* Connection Address Item */
3991 { &hf_enip_cpf_cai_connid,
3992 { "Connection ID", "enip.cpf.cai.connid",
3993 FT_UINT32, BASE_HEX, NULL, 0,
3994 "Common Packet Format: Connection Address Item, Connection Identifier", HFILL }},
3996 { &hf_enip_cpf_ucmm_request,
3997 { "Request/Response", "enip.cpf.ucmm.request",
3998 FT_UINT16, BASE_DEC, VALS(cip_sc_rr), 0x8000,
3999 "Common Packet Format: UCMM Request/Response", HFILL }},
4001 { &hf_enip_cpf_ucmm_msg_type,
4002 { "Unconn Msg Type", "enip.cpf.ucmm.msg_type",
4003 FT_UINT16, BASE_DEC, VALS(unconn_msg_type_vals), 0x7FFF,
4004 "Common Packet Format: UCMM Transaction ID", HFILL }},
4006 { &hf_enip_cpf_ucmm_trans_id,
4007 { "Transaction ID", "enip.cpf.ucmm.trans_id",
4008 FT_UINT32, BASE_HEX, NULL, 0,
4009 "Common Packet Format: UCMM Transaction ID", HFILL }},
4011 { &hf_enip_cpf_ucmm_status,
4012 { "UCMM Status", "enip.cpf.ucmm.status",
4013 FT_UINT32, BASE_HEX, VALS(encap_status_vals), 0,
4014 "Common Packet Format: UCMM Status", HFILL }},
4016 /* Sequenced Address Type */
4017 { &hf_enip_cpf_sai_connid,
4018 { "Connection ID", "enip.cpf.sai.connid",
4019 FT_UINT32, BASE_HEX, NULL, 0,
4020 "Common Packet Format: Sequenced Address Item, Connection Identifier", HFILL }},
4021 { &hf_cip_connid, { "Connection ID", "cip.connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
4023 { &hf_enip_cpf_sai_seqnum,
4024 { "Encapsulation Sequence Number", "enip.cpf.sai.seq",
4025 FT_UINT32, BASE_DEC, NULL, 0,
4026 "Common Packet Format: Sequenced Address Item, Sequence Number", HFILL }},
4028 { &hf_enip_cpf_data,
4029 { "Data", "enip.cpf.data",
4030 FT_BYTES, BASE_NONE, NULL, 0,
4031 "Common Packet Format: Unknown Data", HFILL }},
4033 /* Request/Response Matching */
4034 { &hf_enip_response_in,
4035 { "Response In", "enip.response_in",
4036 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
4037 "The response to this ENIP request is in this frame", HFILL }},
4039 { &hf_enip_response_to,
4040 { "Request In", "enip.response_to",
4041 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
4042 "This is a response to the ENIP request in this frame", HFILL }},
4044 { &hf_enip_time,
4045 { "Time", "enip.time",
4046 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
4047 "The time between the Call and the Reply", HFILL }},
4049 { &hf_enip_fwd_open_in,
4050 { "Forward Open Request In", "enip.fwd_open_in",
4051 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
4053 // Generated API data.
4054 { &hf_cip_cm_ot_api, { "O->T API", "cip.cm.otapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL } },
4055 { &hf_cip_cm_to_api, { "T->O API", "cip.cm.toapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL } },
4057 { &hf_cip_connection,
4058 { "CIP Connection Index", "cip.connection",
4059 FT_UINT32, BASE_DEC, NULL, 0x0,
4060 NULL, HFILL } },
4062 { &hf_cip_io_data,
4063 { "Data", "cipio.data",
4064 FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x0,
4065 NULL, HFILL }},
4067 { &hf_tcpip_status,
4068 { "Status", "cip.tcpip.status",
4069 FT_UINT32, BASE_HEX, NULL, 0,
4070 NULL, HFILL }},
4072 { &hf_tcpip_status_interface_config,
4073 { "Interface Configuration Status", "cip.tcpip.status.interface_config",
4074 FT_UINT32, BASE_DEC, VALS(enip_tcpip_status_interface_config_vals), 0x0000000F,
4075 NULL, HFILL }},
4077 { &hf_tcpip_status_mcast_pending,
4078 { "MCast Pending", "cip.tcpip.status.mcast_pending",
4079 FT_BOOLEAN, 32, NULL, 0x00000010,
4080 NULL, HFILL }},
4082 { &hf_tcpip_status_interface_config_pending,
4083 { "Interface Configuration Pending", "cip.tcpip.status.interface_config_pending",
4084 FT_BOOLEAN, 32, NULL, 0x00000020,
4085 NULL, HFILL }},
4087 { &hf_tcpip_status_acd,
4088 { "ACD Status", "cip.tcpip.status.acd",
4089 FT_UINT32, BASE_DEC, VALS(enip_tcpip_status_acd_vals), 0x00000040,
4090 NULL, HFILL }},
4092 { &hf_tcpip_acd_fault,
4093 { "ACD Fault", "cip.tcpip.status.acd_fault",
4094 FT_BOOLEAN, 32, NULL, 0x00000080,
4095 NULL, HFILL }},
4097 { &hf_tcpip_status_iana_port_admin_change,
4098 { "IANA Port Admin Change Pending", "cip.tcpip.status.iana_port_admin",
4099 FT_BOOLEAN, 32, NULL, 0x00000100,
4100 NULL, HFILL }},
4102 { &hf_tcpip_status_iana_protocol_admin_change,
4103 { "IANA Protocol Admin Change Pending", "cip.tcpip.status.iana_protocol_admin",
4104 FT_BOOLEAN, 32, NULL, 0x00000200,
4105 NULL, HFILL }},
4107 { &hf_tcpip_status_reserved,
4108 { "Reserved", "cip.tcpip.status.reserved",
4109 FT_UINT32, BASE_HEX, NULL, 0xFFFFFC00,
4110 NULL, HFILL }},
4112 { &hf_tcpip_config_cap,
4113 { "Configuration Capability", "cip.tcpip.config_cap",
4114 FT_UINT32, BASE_HEX, NULL, 0,
4115 NULL, HFILL }},
4117 { &hf_tcpip_config_cap_bootp,
4118 { "BOOTP Client", "cip.tcpip.config_cap.bootp",
4119 FT_BOOLEAN, 32, NULL, 0x00000001,
4120 NULL, HFILL }},
4122 { &hf_tcpip_config_cap_dns,
4123 { "DNS Client", "cip.tcpip.config_cap.dns",
4124 FT_BOOLEAN, 32, NULL, 0x00000002,
4125 NULL, HFILL }},
4127 { &hf_tcpip_config_cap_dhcp,
4128 { "DHCP Client", "cip.tcpip.config_cap.dhcp",
4129 FT_BOOLEAN, 32, NULL, 0x00000004,
4130 NULL, HFILL }},
4132 { &hf_tcpip_config_cap_dhcp_dns_update,
4133 { "DHCP-DNS Update", "cip.tcpip.config_cap.dhcp_dns_update",
4134 FT_BOOLEAN, 32, NULL, 0x00000008,
4135 NULL, HFILL }},
4137 { &hf_tcpip_config_cap_config_settable,
4138 { "Configuration Settable", "cip.tcpip.config_cap.config_settable",
4139 FT_BOOLEAN, 32, NULL, 0x00000010,
4140 NULL, HFILL }},
4142 { &hf_tcpip_config_cap_hardware_config,
4143 { "Hardware Configurable", "cip.tcpip.config_cap.hardware_config",
4144 FT_BOOLEAN, 32, NULL, 0x00000020,
4145 NULL, HFILL }},
4147 { &hf_tcpip_config_cap_interface_reset,
4148 { "Interface Configuration Change Requires Reset", "cip.tcpip.config_cap.interface_reset",
4149 FT_BOOLEAN, 32, NULL, 0x00000040,
4150 NULL, HFILL }},
4152 { &hf_tcpip_config_cap_acd,
4153 { "ACD Capable", "cip.tcpip.config_cap.acd",
4154 FT_BOOLEAN, 32, NULL, 0x00000080,
4155 NULL, HFILL }},
4157 { &hf_tcpip_config_cap_reserved,
4158 { "Reserved", "cip.tcpip.config_cap.reserved",
4159 FT_UINT32, BASE_HEX, NULL, 0xFFFFFF00,
4160 NULL, HFILL }},
4162 { &hf_tcpip_config_control,
4163 { "Configuration Control", "cip.tcpip.config_control",
4164 FT_UINT32, BASE_HEX, NULL, 0,
4165 NULL, HFILL }},
4167 { &hf_tcpip_config_control_config,
4168 { "Configuration Method", "cip.tcpip.config_control.config",
4169 FT_UINT32, BASE_DEC, VALS(enip_tcpip_config_control_config_vals), 0x0000000F,
4170 NULL, HFILL }},
4172 { &hf_tcpip_config_control_dns,
4173 { "DNS Enable", "cip.tcpip.config_control.dns",
4174 FT_BOOLEAN, 32, NULL, 0x00000010,
4175 NULL, HFILL }},
4177 { &hf_tcpip_config_control_reserved,
4178 { "Reserved", "cip.tcpip.config_control.reserved",
4179 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFE0,
4180 NULL, HFILL }},
4182 { &hf_tcpip_ic_ip_addr,
4183 { "IP Address", "cip.tcpip.ip_addr",
4184 FT_IPv4, BASE_NONE, NULL, 0,
4185 NULL, HFILL }},
4187 { &hf_tcpip_ic_subnet_mask,
4188 { "Subnet Mask", "cip.tcpip.subnet_mask",
4189 FT_IPv4, BASE_NETMASK, NULL, 0,
4190 NULL, HFILL }},
4192 { &hf_tcpip_ic_gateway,
4193 { "Gateway", "cip.tcpip.gateway",
4194 FT_IPv4, BASE_NONE, NULL, 0,
4195 NULL, HFILL }},
4197 { &hf_tcpip_ic_name_server,
4198 { "Name Server", "cip.tcpip.name_server",
4199 FT_IPv4, BASE_NONE, NULL, 0,
4200 NULL, HFILL }},
4202 { &hf_tcpip_ic_name_server2,
4203 { "Name Server2", "cip.tcpip.name_server2",
4204 FT_IPv4, BASE_NONE, NULL, 0,
4205 NULL, HFILL }},
4207 { &hf_tcpip_ic_domain_name,
4208 { "Domain Name", "cip.tcpip.domain_name",
4209 FT_STRING, BASE_NONE, NULL, 0,
4210 NULL, HFILL }},
4212 { &hf_tcpip_hostname,
4213 { "Hostname", "cip.tcpip.hostname",
4214 FT_STRING, BASE_NONE, NULL, 0,
4215 NULL, HFILL }},
4217 { &hf_tcpip_snn_timestamp,
4218 { "Safety Network Number (Timestamp)", "cip.tcpip.snn.timestamp",
4219 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
4220 NULL, HFILL }
4223 { &hf_tcpip_snn_date,
4224 { "Safety Network Number (Manual) Date", "cip.tcpip.snn.date",
4225 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0,
4226 NULL, HFILL }
4229 { &hf_tcpip_snn_time,
4230 { "Safety Network Number (Manual) Time", "cip.tcpip.snn.time",
4231 FT_UINT32, BASE_HEX, NULL, 0,
4232 NULL, HFILL }
4235 { &hf_tcpip_ttl_value,
4236 { "TTL Value", "cip.tcpip.ttl_value",
4237 FT_UINT8, BASE_DEC, NULL, 0,
4238 NULL, HFILL }},
4240 { &hf_tcpip_mcast_alloc,
4241 { "Alloc Control", "cip.tcpip.mcast.alloc",
4242 FT_UINT8, BASE_DEC, VALS(enip_tcpip_mcast_alloc_vals), 0,
4243 NULL, HFILL }},
4245 { &hf_tcpip_mcast_reserved,
4246 { "Reserved", "cip.tcpip.mcast.reserved",
4247 FT_UINT8, BASE_HEX, NULL, 0,
4248 NULL, HFILL }},
4250 { &hf_tcpip_mcast_num_mcast,
4251 { "Num MCast", "cip.tcpip.mcast.num_mcast",
4252 FT_UINT16, BASE_DEC, NULL, 0,
4253 NULL, HFILL }},
4255 { &hf_tcpip_mcast_addr_start,
4256 { "MCast Start Addr", "cip.tcpip.mcast.addr_start",
4257 FT_IPv4, BASE_NONE, NULL, 0,
4258 NULL, HFILL }},
4260 { &hf_tcpip_select_acd,
4261 { "Select ACD", "cip.tcpip.select_acd",
4262 FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0,
4263 NULL, HFILL }},
4265 { &hf_tcpip_lcd_acd_activity,
4266 { "ACD Activity", "cip.tcpip.last_conflict.acd_activity",
4267 FT_UINT8, BASE_DEC, VALS(enip_tcpip_acd_activity_vals), 0,
4268 NULL, HFILL }},
4270 { &hf_tcpip_lcd_remote_mac,
4271 { "RemoteMAC", "cip.tcpip.last_conflict.remote_mac",
4272 FT_ETHER, BASE_NONE, NULL, 0,
4273 NULL, HFILL }},
4275 { &hf_tcpip_lcd_arp_pdu,
4276 { "Arp PDU", "cip.tcpip.last_conflict.arp_pdu",
4277 FT_BYTES, BASE_NONE, NULL, 0,
4278 NULL, HFILL }},
4280 { &hf_tcpip_quick_connect,
4281 { "Ethernet/IP Quick Connection", "cip.tcpip.quick_connect",
4282 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x1,
4283 NULL, HFILL }},
4285 { &hf_tcpip_encap_inactivity,
4286 { "Encapsulation Inactivity Timeout", "cip.tcpip.encap_inactivity",
4287 FT_UINT16, BASE_DEC, NULL, 0x0,
4288 NULL, HFILL }},
4290 { &hf_tcpip_port_count, { "Port Count", "cip.tcpip.port_count", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
4291 { &hf_tcpip_port_name, { "Port Name", "cip.tcpip.port_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
4292 { &hf_tcpip_port_number, { "Port Number", "cip.tcpip.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
4293 { &hf_tcpip_port_protocol, { "Protocol", "cip.tcpip.protocol", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ipproto_val_ext, 0, NULL, HFILL } },
4294 { &hf_tcpip_port_admin_state, { "Admin State", "cip.tcpip.admin_state", FT_BOOLEAN, BASE_NONE, TFS(&tfs_open_closed), 0, NULL, HFILL } },
4296 { &hf_tcpip_port_admin_capability, { "Admin Capability", "cip.tcpip.admin_capability", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
4297 { &hf_tcpip_admin_capability_configurable, { "Configurable", "cip.tcpip.admin_capability.configurable", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL } },
4298 { &hf_tcpip_admin_capability_reset_required, { "Reset Required", "cip.tcpip.admin_capability.reset_required", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL } },
4299 { &hf_tcpip_admin_capability_reserved, { "Reserved", "cip.tcpip.admin_capability_reserved", FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL } },
4301 { &hf_elink_interface_speed,
4302 { "Interface Speed", "cip.elink.interface_speed",
4303 FT_UINT32, BASE_DEC, NULL, 0,
4304 NULL, HFILL }},
4306 { &hf_elink_interface_flags,
4307 { "Interface Flags", "cip.elink.iflags",
4308 FT_UINT32, BASE_HEX, NULL, 0,
4309 NULL, HFILL }},
4311 { &hf_elink_iflags_link_status,
4312 { "Link Status", "cip.elink.iflags.link_status",
4313 FT_BOOLEAN, 32, TFS(&tfs_active_inactive), 0x00000001,
4314 NULL, HFILL }},
4316 { &hf_elink_iflags_duplex,
4317 { "Duplex", "cip.elink.iflags.duplex",
4318 FT_UINT32, BASE_DEC, VALS(enip_elink_duplex_vals), 0x00000002,
4319 NULL, HFILL }},
4321 { &hf_elink_iflags_neg_status,
4322 { "Negotiation Status", "cip.elink.iflags.neg_status",
4323 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_neg_status_vals), 0x0000001C,
4324 NULL, HFILL }},
4326 { &hf_elink_iflags_manual_reset,
4327 { "Manual Reset Required", "cip.elink.iflags.manual_reset",
4328 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_reset_vals), 0x00000020,
4329 NULL, HFILL }},
4331 { &hf_elink_iflags_local_hw_fault,
4332 { "Local Hardware Fault", "cip.elink.iflags.local_hw_fault",
4333 FT_UINT32, BASE_DEC, VALS(enip_elink_iflags_hw_fault_vals), 0x00000040,
4334 NULL, HFILL }},
4336 { &hf_elink_iflags_reserved,
4337 { "Reserved", "cip.elink.iflags.reserved",
4338 FT_UINT32, BASE_HEX, NULL, 0xFFFFFF80,
4339 NULL, HFILL }},
4341 { &hf_elink_physical_address,
4342 { "Physical Address", "cip.elink.physical_address",
4343 FT_ETHER, BASE_NONE, NULL, 0,
4344 NULL, HFILL }},
4346 { &hf_elink_icount_in_octets,
4347 { "In Octets", "cip.elink.icount.in_octets",
4348 FT_UINT32, BASE_DEC, NULL, 0,
4349 NULL, HFILL }},
4351 { &hf_elink_icount_in_ucast,
4352 { "In Ucast Packets", "cip.elink.icount.in_ucast",
4353 FT_UINT32, BASE_DEC, NULL, 0,
4354 NULL, HFILL }},
4356 { &hf_elink_icount_in_nucast,
4357 { "In NUcast Packets", "cip.elink.icount.in_nucast",
4358 FT_UINT32, BASE_DEC, NULL, 0,
4359 NULL, HFILL }},
4361 { &hf_elink_icount_in_discards,
4362 { "In Discards", "cip.elink.icount.in_discards",
4363 FT_UINT32, BASE_DEC, NULL, 0,
4364 NULL, HFILL }},
4366 { &hf_elink_icount_in_errors,
4367 { "In Errors", "cip.elink.icount.in_errors",
4368 FT_UINT32, BASE_DEC, NULL, 0,
4369 NULL, HFILL }},
4371 { &hf_elink_icount_in_unknown_protos,
4372 { "In Unknown Protos", "cip.elink.icount.in_unknown_protos",
4373 FT_UINT32, BASE_DEC, NULL, 0,
4374 NULL, HFILL }},
4376 { &hf_elink_icount_out_octets,
4377 { "Out Octets", "cip.elink.icount.out_octets",
4378 FT_UINT32, BASE_DEC, NULL, 0,
4379 NULL, HFILL }},
4381 { &hf_elink_icount_out_ucast,
4382 { "Out Ucast Packets", "cip.elink.icount.out_ucast",
4383 FT_UINT32, BASE_DEC, NULL, 0,
4384 NULL, HFILL }},
4386 { &hf_elink_icount_out_nucast,
4387 { "Out NUcast Packets", "cip.elink.icount.out_nucast",
4388 FT_UINT32, BASE_DEC, NULL, 0,
4389 NULL, HFILL }},
4391 { &hf_elink_icount_out_discards,
4392 { "Out Discards", "cip.elink.icount.out_discards",
4393 FT_UINT32, BASE_DEC, NULL, 0,
4394 NULL, HFILL }},
4396 { &hf_elink_icount_out_errors,
4397 { "Out Errors", "cip.elink.icount.out_errors",
4398 FT_UINT32, BASE_DEC, NULL, 0,
4399 NULL, HFILL }},
4401 { &hf_elink_mcount_alignment_errors,
4402 { "Alignment Errors", "cip.elink.mcount.alignment_errors",
4403 FT_UINT32, BASE_DEC, NULL, 0,
4404 NULL, HFILL }},
4406 { &hf_elink_mcount_fcs_errors,
4407 { "FCS Errors", "cip.elink.mcount.fcs_errors",
4408 FT_UINT32, BASE_DEC, NULL, 0,
4409 NULL, HFILL }},
4411 { &hf_elink_mcount_single_collisions,
4412 { "Single Collisions", "cip.elink.mcount.single_collisions",
4413 FT_UINT32, BASE_DEC, NULL, 0,
4414 NULL, HFILL }},
4416 { &hf_elink_mcount_multiple_collisions,
4417 { "Multiple Collisions", "cip.elink.mcount.multiple_collisions",
4418 FT_UINT32, BASE_DEC, NULL, 0,
4419 NULL, HFILL }},
4421 { &hf_elink_mcount_sqe_test_errors,
4422 { "SQE Test Errors", "cip.elink.mcount.sqe_test_errors",
4423 FT_UINT32, BASE_DEC, NULL, 0,
4424 NULL, HFILL }},
4426 { &hf_elink_mcount_deferred_transmission,
4427 { "Deferred Transmission", "cip.elink.mcount.deferred_transmission",
4428 FT_UINT32, BASE_DEC, NULL, 0,
4429 NULL, HFILL }},
4431 { &hf_elink_mcount_late_collisions,
4432 { "Late Collisions", "cip.elink.mcount.late_collisions",
4433 FT_UINT32, BASE_DEC, NULL, 0,
4434 NULL, HFILL }},
4436 { &hf_elink_mcount_excessive_collisions,
4437 { "Excessive Collisions", "cip.elink.mcount.excessive_collisions",
4438 FT_UINT32, BASE_DEC, NULL, 0,
4439 NULL, HFILL }},
4441 { &hf_elink_mcount_mac_transmit_errors,
4442 { "MAC Transmit Errors", "cip.elink.mcount.mac_transmit_errors",
4443 FT_UINT32, BASE_DEC, NULL, 0,
4444 NULL, HFILL }},
4446 { &hf_elink_mcount_carrier_sense_errors,
4447 { "Carrier Sense Errors", "cip.elink.mcount.carrier_sense_errors",
4448 FT_UINT32, BASE_DEC, NULL, 0,
4449 NULL, HFILL }},
4451 { &hf_elink_mcount_frame_too_long,
4452 { "Frame Too Long", "cip.elink.mcount.frame_too_long",
4453 FT_UINT32, BASE_DEC, NULL, 0,
4454 NULL, HFILL }},
4456 { &hf_elink_mcount_mac_receive_errors,
4457 { "MAC Receive Errors", "cip.elink.mcount.mac_receive_errors",
4458 FT_UINT32, BASE_DEC, NULL, 0,
4459 NULL, HFILL }},
4461 { &hf_elink_icontrol_control_bits,
4462 { "Control Bits", "cip.elink.icontrol.control_bits",
4463 FT_UINT16, BASE_HEX, NULL, 0,
4464 NULL, HFILL }},
4466 { &hf_elink_icontrol_control_bits_auto_neg,
4467 { "Auto-negotiate", "cip.elink.icontrol.control_bits.auto_neg",
4468 FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), 0x0001,
4469 NULL, HFILL }},
4471 { &hf_elink_icontrol_control_bits_forced_duplex,
4472 { "Forced Duplex Mode", "cip.elink.icontrol.control_bits.forced_duplex",
4473 FT_UINT16, BASE_DEC, VALS(enip_elink_duplex_vals), 0x0002,
4474 NULL, HFILL }},
4476 { &hf_elink_icontrol_control_bits_reserved,
4477 { "Reserved", "cip.elink.icontrol.control_bits.reserved",
4478 FT_UINT16, BASE_HEX, NULL, 0xFFFC,
4479 NULL, HFILL }},
4481 { &hf_elink_icontrol_forced_speed,
4482 { "Forced Interface Speed", "cip.elink.icontrol.forced_speed",
4483 FT_UINT16, BASE_DEC, NULL, 0,
4484 NULL, HFILL }},
4486 { &hf_elink_icapability_capability_bits,
4487 { "Capability Bits", "cip.elink.icapability.capability_bits",
4488 FT_UINT32, BASE_HEX, NULL, 0,
4489 NULL, HFILL }},
4491 { &hf_elink_icapability_capability_bits_manual,
4492 { "Manual Setting Requires Reset", "cip.elink.icapability.capability_bits.manual",
4493 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000001,
4494 NULL, HFILL }},
4496 { &hf_elink_icapability_capability_bits_auto_neg,
4497 { "Auto-negotiate", "cip.elink.icapability.capability_bits.auto_neg",
4498 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000002,
4499 NULL, HFILL }},
4501 { &hf_elink_icapability_capability_bits_auto_mdix,
4502 { "Auto-MDIX", "cip.elink.icapability.capability_bits.auto_mdix",
4503 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000004,
4504 NULL, HFILL } },
4506 { &hf_elink_icapability_capability_bits_manual_speed,
4507 { "Manual Speed/Duplex", "cip.elink.icapability.capability_bits.manual_speed",
4508 FT_BOOLEAN, 32, TFS(&tfs_enabled_disabled), 0x00000008,
4509 NULL, HFILL } },
4511 { &hf_elink_icapability_capability_speed_duplex_array_count,
4512 { "Speed/Duplex Array Count", "cip.elink.icapability.array_count",
4513 FT_UINT8, BASE_DEC, NULL, 0,
4514 NULL, HFILL } },
4516 { &hf_elink_icapability_capability_speed,
4517 { "Interface Speed", "cip.elink.icapability.speed",
4518 FT_UINT16, BASE_DEC, NULL, 0,
4519 NULL, HFILL } },
4521 { &hf_elink_icapability_capability_duplex,
4522 { "Interface Duplex Mode", "cip.elink.icapability.duplex",
4523 FT_UINT8, BASE_DEC, VALS(enip_elink_duplex_vals), 0,
4524 NULL, HFILL } },
4526 { &hf_elink_interface_type,
4527 { "Interface Type", "cip.elink.interface_type",
4528 FT_UINT8, BASE_DEC, VALS(enip_elink_interface_type_vals), 0,
4529 NULL, HFILL }},
4531 { &hf_elink_interface_state,
4532 { "Interface State", "cip.elink.interface_state",
4533 FT_UINT8, BASE_DEC, VALS(enip_elink_interface_state_vals), 0,
4534 NULL, HFILL }},
4536 { &hf_elink_admin_state,
4537 { "Admin State", "cip.elink.admin_state",
4538 FT_UINT8, BASE_DEC, VALS(enip_elink_admin_state_vals), 0,
4539 NULL, HFILL }},
4541 { &hf_elink_interface_label,
4542 { "Interface Label", "cip.elink.interface_label",
4543 FT_STRING, BASE_NONE, NULL, 0,
4544 NULL, HFILL }},
4546 { &hf_elink_hc_icount_in_octets,
4547 { "In Octets", "cip.elink.hc_icount.in_octets",
4548 FT_UINT64, BASE_DEC, NULL, 0,
4549 NULL, HFILL } },
4551 { &hf_elink_hc_icount_in_ucast,
4552 { "In Ucast Packets", "cip.elink.hc_icount.in_ucast",
4553 FT_UINT64, BASE_DEC, NULL, 0,
4554 NULL, HFILL } },
4556 { &hf_elink_hc_icount_in_mcast,
4557 { "In Multicast Packets", "cip.elink.hc_icount.in_mcast",
4558 FT_UINT64, BASE_DEC, NULL, 0,
4559 NULL, HFILL } },
4561 { &hf_elink_hc_icount_in_broadcast,
4562 { "In Broadcast", "cip.elink.hc_icount.in_broadcast",
4563 FT_UINT64, BASE_DEC, NULL, 0,
4564 NULL, HFILL } },
4566 { &hf_elink_hc_icount_out_octets,
4567 { "Out Octets", "cip.elink.hc_icount.out_octets",
4568 FT_UINT64, BASE_DEC, NULL, 0,
4569 NULL, HFILL } },
4571 { &hf_elink_hc_icount_out_ucast,
4572 { "Out Ucast Packets", "cip.elink.hc_icount.out_ucast",
4573 FT_UINT64, BASE_DEC, NULL, 0,
4574 NULL, HFILL } },
4576 { &hf_elink_hc_icount_out_mcast,
4577 { "Out Multicast Packets", "cip.elink.hc_icount.out_mcast",
4578 FT_UINT64, BASE_DEC, NULL, 0,
4579 NULL, HFILL } },
4581 { &hf_elink_hc_icount_out_broadcast,
4582 { "Out Broadcast Packets", "cip.elink.hc_icount.out_broadcast",
4583 FT_UINT64, BASE_DEC, NULL, 0,
4584 NULL, HFILL } },
4586 { &hf_elink_hc_mcount_stats_align_errors,
4587 { "Stats Alignment Errors", "cip.elink.hc_mcount.stats_align_errors",
4588 FT_UINT64, BASE_DEC, NULL, 0,
4589 NULL, HFILL } },
4591 { &hf_elink_hc_mcount_stats_fcs_errors,
4592 { "Stats FCS Errors", "cip.elink.hc_mcount.stats_fcs_errors",
4593 FT_UINT64, BASE_DEC, NULL, 0,
4594 NULL, HFILL } },
4596 { &hf_elink_hc_mcount_stats_internal_mac_transmit_errors,
4597 { "Stats Internal MAC Transmit Errors", "cip.elink.hc_mcount.internal_mac_transmit_errors",
4598 FT_UINT64, BASE_DEC, NULL, 0,
4599 NULL, HFILL } },
4601 { &hf_elink_hc_mcount_stats_frame_too_long,
4602 { "Stats Frame Too Long", "cip.elink.hc_mcount.stats_frame_too_long",
4603 FT_UINT64, BASE_DEC, NULL, 0,
4604 NULL, HFILL } },
4606 { &hf_elink_hc_mcount_stats_internal_mac_receive_errors,
4607 { "Stats Internal MAC Receive Errors", "cip.elink.hc_mcount.internal_mac_receive_errors",
4608 FT_UINT64, BASE_DEC, NULL, 0,
4609 NULL, HFILL } },
4611 { &hf_elink_hc_mcount_stats_symbol_errors,
4612 { "Stats Symbol Errors", "cip.elink.hc_mcount.stats_symbol_errors",
4613 FT_UINT64, BASE_DEC, NULL, 0,
4614 NULL, HFILL } },
4616 { &hf_qos_8021q_enable,
4617 { "802.1Q Tag Enable", "cip.qos.8021q_enable",
4618 FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x1,
4619 NULL, HFILL }},
4621 { &hf_qos_dscp_ptp_event,
4622 { "DSCP PTP Event", "cip.qos.ptp_event",
4623 FT_UINT8, BASE_DEC, NULL, 0,
4624 NULL, HFILL }},
4626 { &hf_qos_dscp_ptp_general,
4627 { "DSCP PTP General", "cip.qos.ptp_general",
4628 FT_UINT8, BASE_DEC, NULL, 0,
4629 NULL, HFILL }},
4631 { &hf_qos_dscp_urgent,
4632 { "DSCP Urgent", "cip.qos.urgent",
4633 FT_UINT8, BASE_DEC, NULL, 0,
4634 NULL, HFILL }},
4636 { &hf_qos_dscp_scheduled,
4637 { "DSCP Scheduled", "cip.qos.scheduled",
4638 FT_UINT8, BASE_DEC, NULL, 0,
4639 NULL, HFILL }},
4641 { &hf_qos_dscp_high,
4642 { "DSCP High", "cip.qos.high",
4643 FT_UINT8, BASE_DEC, NULL, 0,
4644 NULL, HFILL }},
4646 { &hf_qos_dscp_low,
4647 { "DSCP Low", "cip.qos.low",
4648 FT_UINT8, BASE_DEC, NULL, 0,
4649 NULL, HFILL }},
4651 { &hf_qos_dscp_explicit,
4652 { "DSCP Explicit", "cip.qos.explicit",
4653 FT_UINT8, BASE_DEC, NULL, 0,
4654 NULL, HFILL }},
4656 { &hf_dlr_network_topology,
4657 { "Network Topology", "cip.dlr.network_topology",
4658 FT_UINT8, BASE_DEC, VALS(enip_dlr_network_topology_vals), 0,
4659 NULL, HFILL }},
4661 { &hf_dlr_network_status,
4662 { "Network Status", "cip.dlr.network_status",
4663 FT_UINT8, BASE_DEC, VALS(enip_dlr_network_status_vals), 0,
4664 NULL, HFILL }},
4666 { &hf_dlr_ring_supervisor_status,
4667 { "Ring Supervisor Status", "cip.dlr.ring_supervisor_status",
4668 FT_UINT8, BASE_DEC, VALS(enip_dlr_ring_supervisor_status_vals), 0,
4669 NULL, HFILL }},
4671 { &hf_dlr_rsc_ring_supervisor_enable,
4672 { "Ring Supervisor Enable", "cip.dlr.rscconfig.supervisor_enable",
4673 FT_BOOLEAN, BASE_NONE, NULL, 0,
4674 NULL, HFILL }},
4676 { &hf_dlr_rsc_ring_supervisor_precedence,
4677 { "Ring Supervisor Precedence", "cip.dlr.rscconfig.supervisor_precedence",
4678 FT_UINT8, BASE_DEC, NULL, 0,
4679 NULL, HFILL }},
4681 { &hf_dlr_rsc_beacon_interval,
4682 { "Beacon Interval", "cip.dlr.rscconfig.beacon_interval",
4683 FT_UINT32, BASE_DEC, NULL, 0,
4684 NULL, HFILL }},
4686 { &hf_dlr_rsc_beacon_timeout,
4687 { "Beacon Timeout", "cip.dlr.rscconfig.beacon_timeout",
4688 FT_UINT32, BASE_DEC, NULL, 0,
4689 NULL, HFILL }},
4691 { &hf_dlr_rsc_dlr_vlan_id,
4692 { "DLR VLAN ID", "cip.dlr.rscconfig.dlr_vlan_id",
4693 FT_UINT16, BASE_DEC, NULL, 0,
4694 NULL, HFILL }},
4696 { &hf_dlr_ring_faults_count,
4697 { "Ring Faults Count", "cip.dlr.ring_faults_count",
4698 FT_UINT16, BASE_DEC, NULL, 0,
4699 NULL, HFILL }},
4701 { &hf_dlr_lanp1_dev_ip_addr,
4702 { "Device IP Address", "cip.dlr.lanp1.ip_addr",
4703 FT_IPv4, BASE_NONE, NULL, 0,
4704 NULL, HFILL }},
4706 { &hf_dlr_lanp1_dev_physical_address,
4707 { "Device Physical Address", "cip.dlr.lanp1.physical_address",
4708 FT_ETHER, BASE_NONE, NULL, 0,
4709 NULL, HFILL }},
4711 { &hf_dlr_lanp2_dev_ip_addr,
4712 { "Device IP Address", "cip.dlr.lanp2.ip_addr",
4713 FT_IPv4, BASE_NONE, NULL, 0,
4714 NULL, HFILL }},
4716 { &hf_dlr_lanp2_dev_physical_address,
4717 { "Device Physical Address", "cip.dlr.lanp2.physical_address",
4718 FT_ETHER, BASE_NONE, NULL, 0,
4719 NULL, HFILL }},
4721 { &hf_dlr_ring_protocol_participants_count,
4722 { "Participants Count", "cip.dlr.participants_count",
4723 FT_UINT16, BASE_DEC, NULL, 0,
4724 NULL, HFILL }},
4726 { &hf_dlr_rppl_dev_ip_addr,
4727 { "Device IP Address", "cip.dlr.rppl.ip_addr",
4728 FT_IPv4, BASE_NONE, NULL, 0,
4729 NULL, HFILL }},
4731 { &hf_dlr_rppl_dev_physical_address,
4732 { "Device Physical Address", "cip.dlr.rppl.physical_address",
4733 FT_ETHER, BASE_NONE, NULL, 0,
4734 NULL, HFILL }},
4736 { &hf_dlr_asa_supervisor_ip_addr,
4737 { "Supervisor IP Address", "cip.dlr.asa.ip_addr",
4738 FT_IPv4, BASE_NONE, NULL, 0,
4739 NULL, HFILL }},
4741 { &hf_dlr_asa_supervisor_physical_address,
4742 { "Supervisor Physical Address", "cip.dlr.asa.physical_address",
4743 FT_ETHER, BASE_NONE, NULL, 0,
4744 NULL, HFILL }},
4746 { &hf_dlr_active_supervisor_precedence,
4747 { "Active Supervisor Precedence", "cip.dlr.supervisor_precedence",
4748 FT_UINT8, BASE_DEC, NULL, 0,
4749 NULL, HFILL }},
4751 { &hf_dlr_capability_flags,
4752 { "Capability Flags", "cip.dlr.capflags",
4753 FT_UINT32, BASE_HEX, NULL, 0,
4754 NULL, HFILL }},
4756 { &hf_dlr_capflags_announce_base_node,
4757 { "Announce-based Ring Node", "cip.dlr.capflags.announce_based",
4758 FT_BOOLEAN, 32, NULL, 0x00000001,
4759 NULL, HFILL }},
4761 { &hf_dlr_capflags_beacon_base_node,
4762 { "Beacon-based Ring Node", "cip.dlr.capflags.beacon_based",
4763 FT_BOOLEAN, 32, NULL, 0x00000002,
4764 NULL, HFILL }},
4766 { &hf_dlr_capflags_reserved1,
4767 { "Reserved", "cip.dlr.capflags.reserved1",
4768 FT_BOOLEAN, 32, NULL, 0x0000001C,
4769 NULL, HFILL }},
4771 { &hf_dlr_capflags_supervisor_capable,
4772 { "Supervisor Capable", "cip.dlr.capflags.supervisor_capable",
4773 FT_BOOLEAN, 32, NULL, 0x00000020,
4774 NULL, HFILL }},
4776 { &hf_dlr_capflags_redundant_gateway_capable,
4777 { "Redundant Gateway Capable", "cip.dlr.capflags.redundant_gateway_capable",
4778 FT_BOOLEAN, 32, NULL, 0x00000040,
4779 NULL, HFILL }},
4781 { &hf_dlr_capflags_flush_frame_capable,
4782 { "Flush_Table Frame Capable", "cip.dlr.capflags.flush_frame_capable",
4783 FT_BOOLEAN, 32, NULL, 0x00000080,
4784 NULL, HFILL }},
4786 { &hf_dlr_capflags_reserved2,
4787 { "Reserved", "cip.dlr.capflags.reserved2",
4788 FT_BOOLEAN, 32, NULL, 0xFFFFFF00,
4789 NULL, HFILL }},
4791 { &hf_dlr_rgc_red_gateway_enable,
4792 { "Redundant Gateway Enable", "cip.dlr.rgc.gateway_enable",
4793 FT_BOOLEAN, BASE_NONE, NULL, 0,
4794 NULL, HFILL }},
4796 { &hf_dlr_rgc_gateway_precedence,
4797 { "Gateway Precedence", "cip.dlr.rgc.gateway_precedence",
4798 FT_UINT8, BASE_DEC, NULL, 0,
4799 NULL, HFILL }},
4801 { &hf_dlr_rgc_advertise_interval,
4802 { "Advertise Interval", "cip.dlr.rgc.advertise_interval",
4803 FT_UINT32, BASE_DEC, NULL, 0,
4804 NULL, HFILL }},
4806 { &hf_dlr_rgc_advertise_timeout,
4807 { "Advertise Timeout", "cip.dlr.rgc.advertise_timeout",
4808 FT_UINT32, BASE_DEC, NULL, 0,
4809 NULL, HFILL }},
4811 { &hf_dlr_rgc_learning_update_enable,
4812 { "Learning Update Enable", "cip.dlr.rgc.learning_update_enable",
4813 FT_BOOLEAN, BASE_NONE, NULL, 0,
4814 NULL, HFILL }},
4816 { &hf_dlr_redundant_gateway_status,
4817 { "Redundant Gateway Status", "cip.dlr.redundant_gateway_status",
4818 FT_UINT8, BASE_DEC, VALS(enip_dlr_redundant_gateway_status_vals), 0,
4819 NULL, HFILL }},
4821 { &hf_dlr_aga_ip_addr,
4822 { "Active Gateway IP Address", "cip.dlr.aga.ip_addr",
4823 FT_IPv4, BASE_NONE, NULL, 0,
4824 NULL, HFILL }},
4826 { &hf_dlr_aga_physical_address,
4827 { "Active Gateway Physical Address", "cip.dlr.aga.physical_address",
4828 FT_ETHER, BASE_NONE, NULL, 0,
4829 NULL, HFILL }},
4831 { &hf_dlr_active_gateway_precedence,
4832 { "Active Gateway Precedence", "cip.dlr.active_gateway_precedence",
4833 FT_UINT8, BASE_DEC, NULL, 0,
4834 NULL, HFILL }},
4836 { &hf_cip_security_state, { "State", "cip.security.state", FT_UINT8, BASE_DEC, VALS(cip_security_state_vals), 0, NULL, HFILL } },
4838 { &hf_eip_security_state,
4839 { "State", "cip.eip_security.state",
4840 FT_UINT8, BASE_DEC, VALS(eip_security_state_vals), 0,
4841 NULL, HFILL }},
4843 { &hf_eip_security_verify_client_cert,
4844 { "Verify Client Certificate", "cip.eip_security.verify_client_cert",
4845 FT_BOOLEAN, BASE_NONE, NULL, 0,
4846 NULL, HFILL }},
4848 { &hf_eip_security_send_cert_chain,
4849 { "Send Certificate Chain", "cip.eip_security.send_cert_chain",
4850 FT_BOOLEAN, BASE_NONE, NULL, 0,
4851 NULL, HFILL }},
4853 { &hf_eip_security_check_expiration,
4854 { "Check Expiration", "cip.eip_security.check_expiration",
4855 FT_BOOLEAN, BASE_NONE, NULL, 0,
4856 NULL, HFILL }},
4858 { &hf_eip_security_capability_flags,
4859 { "Capability Flags", "cip.eip_security.capability_flags",
4860 FT_UINT32, BASE_HEX, NULL, 0,
4861 NULL, HFILL }},
4863 { &hf_eip_security_capflags_secure_renegotiation,
4864 { "Secure Renegotiation", "cip.eip_security.capability_flags.secure_renegotiation",
4865 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000001,
4866 NULL, HFILL }},
4868 { &hf_eip_security_capflags_reserved,
4869 { "Reserved", "cip.eip_security.capability_flags.reserved",
4870 FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFE,
4871 NULL, HFILL }},
4873 { &hf_eip_security_num_avail_cipher_suites,
4874 { "Number of Available Cipher Suites", "cip.eip_security.num_avail_cipher_suites",
4875 FT_UINT8, BASE_DEC, NULL, 0,
4876 NULL, HFILL }},
4878 { &hf_eip_security_avail_cipher_suite,
4879 { "Available Cipher Suite", "cip.eip_security.avail_cipher_suite",
4880 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0,
4881 NULL, HFILL }},
4883 { &hf_eip_security_num_allow_cipher_suites,
4884 { "Number of Allowed Cipher Suites", "cip.eip_security.num_allow_cipher_suites",
4885 FT_UINT8, BASE_DEC, NULL, 0,
4886 NULL, HFILL }},
4888 { &hf_eip_security_allow_cipher_suite,
4889 { "Allowed Cipher Suite", "cip.eip_security.allow_cipher_suite",
4890 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0,
4891 NULL, HFILL }},
4893 { &hf_eip_security_num_psk,
4894 { "Number of PSKs", "cip.eip_security.num_psk",
4895 FT_UINT8, BASE_DEC, NULL, 0,
4896 NULL, HFILL }},
4898 { &hf_eip_security_psk_identity_size,
4899 { "PSK Identity Size", "cip.eip_security.psk_identity_size",
4900 FT_UINT8, BASE_DEC, NULL, 0,
4901 NULL, HFILL }},
4903 { &hf_eip_security_psk_identity,
4904 { "PSK Identity", "cip.eip_security.psk_identity",
4905 FT_STRING, BASE_NONE, NULL, 0,
4906 NULL, HFILL }},
4908 { &hf_eip_security_psk_size,
4909 { "PSK Size", "cip.eip_security.psk_size",
4910 FT_UINT8, BASE_DEC, NULL, 0,
4911 NULL, HFILL }},
4913 { &hf_eip_security_psk,
4914 { "PSK", "cip.eip_security.psk",
4915 FT_STRING, BASE_NONE, NULL, 0,
4916 NULL, HFILL }},
4918 { &hf_eip_security_psk_usage,
4919 { "PSK Usage", "cip.eip_security.psk_usage",
4920 FT_UINT8, BASE_DEC, VALS(eip_security_psk_usage_vals), 0,
4921 NULL, HFILL }},
4923 { &hf_eip_security_num_active_certs,
4924 { "Number of Active Certificates", "cip.eip_security.num_active_certs",
4925 FT_UINT8, BASE_DEC, NULL, 0,
4926 NULL, HFILL }},
4928 { &hf_eip_security_num_trusted_auths,
4929 { "Number of Trusted Authorities", "cip.eip_security.num_trusted_auths",
4930 FT_UINT8, BASE_DEC, NULL, 0,
4931 NULL, HFILL }},
4932 { &hf_eip_security_num_trusted_identities,
4933 { "Number of Trusted Identities", "cip.eip_security.num_trusted_identities",
4934 FT_UINT8, BASE_DEC, NULL, 0,
4935 NULL, HFILL }},
4936 { &hf_eip_security_num_crl,
4937 { "Number of Certificate Revocation Lists", "cip.eip_security.num_crl",
4938 FT_UINT8, BASE_DEC, NULL, 0,
4939 NULL, HFILL }},
4941 { &hf_eip_cert_name,
4942 { "Name", "cip.eip_cert.name",
4943 FT_STRING, BASE_NONE, NULL, 0,
4944 NULL, HFILL }},
4946 { &hf_eip_cert_state,
4947 { "State", "cip.eip_cert.state",
4948 FT_UINT8, BASE_DEC, VALS(eip_cert_state_vals), 0,
4949 NULL, HFILL }},
4951 { &hf_eip_cert_encoding,
4952 { "Certificate Encoding", "cip.eip_cert.encoding",
4953 FT_UINT8, BASE_DEC, NULL, 0,
4954 NULL, HFILL } },
4956 { &hf_eip_cert_device_cert_status,
4957 { "Certificate Status", "cip.eip_cert.device_cert.status",
4958 FT_UINT8, BASE_DEC, VALS(eip_cert_status_vals), 0,
4959 NULL, HFILL }},
4961 { &hf_eip_cert_ca_cert_status,
4962 { "Certificate Status", "cip.eip_cert.ca_cert.status",
4963 FT_UINT8, BASE_DEC, VALS(eip_cert_status_vals), 0,
4964 NULL, HFILL }},
4966 { &hf_eip_cert_capflags_push,
4967 { "Push", "cip.eip_cert.capflags.push",
4968 FT_BOOLEAN, 32, NULL, 0x00000001,
4969 NULL, HFILL }},
4971 { &hf_eip_cert_capflags_reserved,
4972 { "Reserved", "cip.eip_cert.capflags.reserved",
4973 FT_BOOLEAN, 32, NULL, 0xFFFFFFFE,
4974 NULL, HFILL }},
4976 { &hf_eip_cert_capability_flags,
4977 { "Capability flags", "cip.eip_cert.capflags",
4978 FT_UINT32, BASE_HEX, NULL, 0,
4979 NULL, HFILL }},
4981 { &hf_eip_cert_num_certs,
4982 { "Number of Certificates", "cip.eip_cert.num_certs",
4983 FT_UINT8, BASE_DEC, NULL, 0,
4984 NULL, HFILL }},
4986 { &hf_eip_cert_cert_name,
4987 { "Certificate name", "cip.eip_cert.cert_name",
4988 FT_STRING, BASE_NONE, NULL, 0,
4989 NULL, HFILL }},
4991 { &hf_eip_cert_verify_certificate,
4992 { "Certificate", "cip.eip_cert.verify_certificate",
4993 FT_UINT16, BASE_DEC, NULL, 0,
4994 NULL, HFILL } },
4996 { &hf_lldp_subtype,
4997 { "ODVA LLDP Subtype", "cip.lldp.subtype",
4998 FT_UINT8, BASE_DEC, VALS(lldp_cip_subtypes), 0,
4999 NULL, HFILL }
5001 { &hf_lldp_mac_address,
5002 { "MAC Address", "cip.lldp.mac_address",
5003 FT_ETHER, BASE_NONE, NULL, 0,
5004 NULL, HFILL }},
5007 /* Setup protocol subtree array */
5008 static int *ett[] = {
5009 &ett_enip,
5010 &ett_cip_io_generic,
5011 &ett_path,
5012 &ett_count_tree,
5013 &ett_type_tree,
5014 &ett_command_tree,
5015 &ett_sockadd,
5016 &ett_lsrcf,
5017 &ett_tcpip_status,
5018 &ett_tcpip_admin_capability,
5019 &ett_tcpip_config_cap,
5020 &ett_tcpip_config_control,
5021 &ett_elink_interface_flags,
5022 &ett_elink_icontrol_bits,
5023 &ett_elink_icapability_bits,
5024 &ett_dlr_capability_flags,
5025 &ett_dlr_lnknbrstatus_flags,
5026 &ett_eip_security_capability_flags,
5027 &ett_eip_security_psk,
5028 &ett_eip_security_active_certs,
5029 &ett_eip_security_trusted_auths,
5030 &ett_eip_security_trusted_identities,
5031 &ett_eip_security_crl,
5032 &ett_eip_cert_capability_flags,
5033 &ett_eip_cert_num_certs,
5034 &ett_security_profiles,
5035 &ett_ingress_egress_apply_behavior,
5036 &ett_iana_port_state_flags,
5037 &ett_connection_info,
5038 &ett_connection_path_info,
5039 &ett_cmd_data
5042 static ei_register_info ei[] = {
5043 { &ei_mal_tcpip_status, { "cip.malformed.tcpip.status", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Status", EXPFILL }},
5044 { &ei_mal_tcpip_config_cap, { "cip.malformed.tcpip.config_cap", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Configuration Capability", EXPFILL }},
5045 { &ei_mal_tcpip_config_control, { "cip.malformed.tcpip.config_control", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Configuration Control", EXPFILL }},
5046 { &ei_mal_tcpip_interface_config, { "cip.malformed.tcpip.interface_config", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Interface Configuration", EXPFILL }},
5047 { &ei_mal_tcpip_snn, { "cip.malformed.tcpip.snn", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Object Safety Network Number", EXPFILL }},
5048 { &ei_mal_tcpip_mcast_config, { "cip.malformed.tcpip.mcast_config", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Multicast Config", EXPFILL }},
5049 { &ei_mal_tcpip_last_conflict, { "cip.malformed.tcpip.last_conflict", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Last Conflict Detected", EXPFILL }},
5050 { &ei_mal_elink_interface_flags, { "cip.malformed.elink.interface_flags", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Flags", EXPFILL }},
5051 { &ei_mal_elink_physical_address, { "cip.malformed.elink.physical_address", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Physical Address", EXPFILL } },
5052 { &ei_mal_elink_interface_counters, { "cip.malformed.elink.interface_counters", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Counters", EXPFILL }},
5053 { &ei_mal_elink_media_counters, { "cip.malformed.elink.media_counters", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Media Counters", EXPFILL }},
5054 { &ei_mal_elink_interface_control, { "cip.malformed.elink.interface_control", PI_MALFORMED, PI_ERROR, "Malformed Ethernet Link Interface Control", EXPFILL }},
5055 { &ei_mal_dlr_ring_supervisor_config, { "cip.malformed.dlr.ring_supervisor_config", PI_MALFORMED, PI_ERROR, "Malformed DLR Ring Supervisor Config", EXPFILL }},
5056 { &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 }},
5057 { &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 }},
5058 { &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 }},
5059 { &ei_mal_dlr_active_supervisor_address, { "cip.malformed.dlr.active_supervisor_address", PI_MALFORMED, PI_ERROR, "Malformed DLR Active Supervisor Address", EXPFILL }},
5060 { &ei_mal_dlr_capability_flags, { "cip.malformed.dlr.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed DLR Capability Flag", EXPFILL }},
5061 { &ei_mal_dlr_redundant_gateway_config, { "cip.malformed.dlr.redundant_gateway_config", PI_MALFORMED, PI_ERROR, "Malformed DLR Redundant Gateway Config", EXPFILL }},
5062 { &ei_mal_dlr_active_gateway_address, { "cip.malformed.dlr.active_gateway_address", PI_MALFORMED, PI_ERROR, "Malformed DLR Active Gateway Address", EXPFILL }},
5063 { &ei_mal_eip_security_capability_flags, { "cip.malformed.eip_security.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Capability Flags", EXPFILL }},
5064 { &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 }},
5065 { &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 }},
5066 { &ei_mal_eip_security_preshared_keys, { "cip.malformed.eip_security.preshared_keys", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Pre-Shared Keys", EXPFILL }},
5067 { &ei_mal_eip_security_active_certs, { "cip.malformed.eip_security.active_certs", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Active Device Certificates", EXPFILL }},
5068 { &ei_mal_eip_security_trusted_auths, { "cip.malformed.eip_security.trusted_auths", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Trusted Authorities", EXPFILL }},
5069 { &ei_mal_eip_security_trusted_identities, { "cip.malformed.eip_security.trusted_identities", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Trusted Identities", EXPFILL }},
5070 { &ei_mal_eip_security_crl, { "cip.malformed.eip_security.crl", PI_MALFORMED, PI_ERROR, "Malformed EIP Security Certificate Revocation List", EXPFILL }},
5071 { &ei_mal_eip_cert_capability_flags, { "cip.malformed.eip_cert.capability_flags", PI_MALFORMED, PI_ERROR, "Malformed EIP Certificate Management Capability Flags", EXPFILL }},
5072 { &ei_mal_cpf_item_length_mismatch, { "enip.malformed.cpf_item_length_mismatch", PI_MALFORMED, PI_ERROR, "CPF Item Length Mismatch", EXPFILL } },
5073 { &ei_mal_cpf_item_minimum_size, { "enip.malformed.cpf_item_minimum_size", PI_MALFORMED, PI_ERROR, "CPF Item Minimum Size is 4", EXPFILL } },
5075 // Analysis Checks
5076 { &ei_cip_request_no_response, { "cip.analysis.request_no_response", PI_PROTOCOL, PI_NOTE, "CIP request without a response", EXPFILL } },
5077 { &ei_cip_io_heartbeat, { "cip.analysis.cip_io_heartbeat", PI_PROTOCOL, PI_NOTE, "[Likely] CIP I/O Heartbeat [Listen/Input Only Connection]", EXPFILL } },
5080 /* Setup list of header fields for DLR See Section 1.6.1 for details*/
5081 static hf_register_info hfdlr[] = {
5082 /* Ring Sub-type */
5083 { &hf_dlr_ringsubtype,
5084 { "Ring Sub-Type", "enip.dlr.ringsubtype",
5085 FT_UINT8, BASE_HEX, NULL, 0,
5086 NULL, HFILL }
5088 /* Ring Protocol Version */
5089 { &hf_dlr_ringprotoversion,
5090 { "Ring Protocol Version", "enip.dlr.protversion",
5091 FT_UINT8, BASE_DEC, NULL, 0,
5092 NULL, HFILL }
5094 /* Frame Type */
5095 { &hf_dlr_frametype,
5096 { "Frame Type", "enip.dlr.frametype",
5097 FT_UINT8, BASE_HEX, VALS(dlr_frame_type_vals), 0,
5098 NULL, HFILL }
5100 /* Source Port */
5101 { &hf_dlr_sourceport,
5102 { "Source Port", "enip.dlr.sourceport",
5103 FT_UINT8, BASE_HEX, VALS(dlr_source_port_vals), 0,
5104 NULL, HFILL }
5106 /* Source IP Address */
5107 { &hf_dlr_sourceip,
5108 { "Source IP", "enip.dlr.sourceip",
5109 FT_IPv4, BASE_NONE, NULL, 0,
5110 "Source IP Address", HFILL }
5112 /* Sequence ID*/
5113 { &hf_dlr_sequenceid,
5114 { "Sequence Id", "enip.dlr.seqid",
5115 FT_UINT32, BASE_HEX, NULL, 0,
5116 NULL, HFILL }
5118 /* Ring State */
5119 { &hf_dlr_ringstate,
5120 { "Ring State", "enip.dlr.state",
5121 FT_UINT8, BASE_HEX, VALS(dlr_ring_state_vals), 0,
5122 NULL, HFILL }
5124 /* Supervisor Precedence */
5125 { &hf_dlr_supervisorprecedence,
5126 { "Supervisor Precedence", "enip.dlr.supervisorprecedence",
5127 FT_UINT8, BASE_DEC, NULL, 0,
5128 NULL, HFILL }
5130 /* Beacon Interval */
5131 { &hf_dlr_beaconinterval,
5132 { "Beacon Interval", "enip.dlr.beaconinterval",
5133 FT_UINT32, BASE_DEC, NULL, 0,
5134 NULL, HFILL }
5136 /* Beacon Timeout */
5137 { &hf_dlr_beacontimeout,
5138 { "Beacon Timeout", "enip.dlr.beacontimeout",
5139 FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
5140 NULL, HFILL }
5142 /* Beacon Reserved */
5143 { &hf_dlr_beaconreserved,
5144 { "Reserved", "enip.dlr.beaconreserved",
5145 FT_BYTES, BASE_NONE, NULL, 0,
5146 "Beacon Reserved", HFILL }
5148 /* Neighbor_Check_Request Reserved */
5149 { &hf_dlr_nreqreserved,
5150 { "Reserved", "enip.dlr.nreqreserved",
5151 FT_BYTES, BASE_NONE, NULL, 0,
5152 "Neighbor_Check_Request Reserved", HFILL }
5154 /* Neighbor_Check_Response Source Port */
5155 { &hf_dlr_nressourceport,
5156 { "Request Source Port", "enip.dlr.nressourceport",
5157 FT_UINT8, BASE_HEX, VALS(dlr_source_port_vals), 0,
5158 "Neighbor_Check_Response Source Port", HFILL }
5160 /* Neighbor_Check_Response Reserved */
5161 { &hf_dlr_nresreserved,
5162 { "Reserved", "enip.dlr.nresreserved",
5163 FT_BYTES, BASE_NONE, NULL, 0,
5164 "Neighbor_Check_Response Reserved", HFILL }
5166 /* Link_Status/Neighbor_Status Status */
5167 { &hf_dlr_lnknbrstatus,
5168 { "Link/Neighbor Status", "enip.dlr.lnknbrstatus.status",
5169 FT_UINT8, BASE_HEX, NULL, 0,
5170 "Link_Status/Neighbor_Status Status", HFILL }
5172 { &hf_dlr_lnknbrstatus_port1,
5173 { "Port 1 Active", "enip.dlr.lnknbrstatus.port1",
5174 FT_BOOLEAN, 8, NULL, 0x01,
5175 NULL, HFILL }
5177 { &hf_dlr_lnknbrstatus_port2,
5178 { "Port 2 Active", "enip.dlr.lnknbrstatus.port2",
5179 FT_BOOLEAN, 8, NULL, 0x02,
5180 NULL, HFILL }
5182 { &hf_dlr_lnknbrstatus_reserved,
5183 { "Reserved", "enip.dlr.lnknbrstatus.reserved",
5184 FT_BOOLEAN, 8, NULL, 0x7C,
5185 NULL, HFILL }
5187 { &hf_dlr_lnknbrstatus_frame_type,
5188 { "Link/Neighbor Status Frame Type", "enip.dlr.lnknbrstatus.frame_type",
5189 FT_BOOLEAN, 8, TFS(&dlr_lnknbrstatus_frame_type_vals), 0x80,
5190 NULL, HFILL }
5192 /* Link_Status/Neighbor_Status Reserved */
5193 { &hf_dlr_lnknbrreserved,
5194 { "Reserved", "enip.dlr.lnknbrreserved",
5195 FT_BYTES, BASE_NONE, NULL, 0,
5196 "Link_Status/Neighbor_Status Reserved", HFILL }
5198 /* Locate_Fault Reserved */
5199 { &hf_dlr_lfreserved,
5200 { "Reserved", "enip.dlr.lfreserved",
5201 FT_BYTES, BASE_NONE, NULL, 0,
5202 "Locate_Fault Reserved", HFILL }
5204 /* Announce Reserved */
5205 { &hf_dlr_anreserved,
5206 { "Reserved", "enip.dlr.anreserved",
5207 FT_BYTES, BASE_NONE, NULL, 0,
5208 "Announce Reserved", HFILL }
5210 /* Number of Nodes in List */
5211 { &hf_dlr_sonumnodes,
5212 { "Num nodes", "enip.dlr.sonumnodes",
5213 FT_UINT16, BASE_DEC, NULL, 0,
5214 "Number of Nodes in List", HFILL }
5216 /* Sign_On Node # MAC Address */
5217 { &hf_dlr_somac,
5218 { "MAC Address", "enip.dlr.somac",
5219 FT_ETHER, BASE_NONE, NULL, 0,
5220 "Sign_On Node MAC Address", HFILL }
5222 /* Node # IP Address */
5223 { &hf_dlr_soip,
5224 { "IP Address", "enip.dlr.soip",
5225 FT_IPv4, BASE_NONE, NULL, 0,
5226 "Sign_On Node IP Address", HFILL }
5228 /* Sign_On Reserved */
5229 { &hf_dlr_soreserved,
5230 { "Reserved", "enip.dlr.soreserved",
5231 FT_BYTES, BASE_NONE, NULL, 0,
5232 "Sign_On Reserved", HFILL }
5234 /* Gateway State */
5235 { &hf_dlr_advgatewaystate,
5236 { "Gateway Status", "enip.dlr.advgatewaystate",
5237 FT_UINT8, BASE_HEX, VALS(dlr_adv_state_vals), 0,
5238 "Gateway State", HFILL }
5240 /* Gateway Precedence */
5241 { &hf_dlr_advgatewayprecedence,
5242 { "Gateway Precedence", "enip.dlr.advgatewayprecedence",
5243 FT_UINT8, BASE_DEC, NULL, 0,
5244 NULL, HFILL }
5246 /* Advertise Interval */
5247 { &hf_dlr_advadvertiseinterval,
5248 { "Advertise Interval", "enip.dlr.advadvertiseinterval",
5249 FT_UINT32, BASE_DEC, NULL, 0,
5250 NULL, HFILL }
5252 /* Advertise Timeout */
5253 { &hf_dlr_advadvertisetimeout,
5254 { "Advertise Interval", "enip.dlr.advadvertisetimeout",
5255 FT_UINT32, BASE_DEC, NULL, 0,
5256 NULL, HFILL }
5258 /* Learning Update Enable */
5259 { &hf_dlr_advlearningupdateenable,
5260 { "Learning Update Enable", "enip.dlr.advlearningupdateenable",
5261 FT_UINT8, BASE_HEX, VALS(dlr_adv_learning_update_vals), 0,
5262 "Advertise Learning Update Enable", HFILL }
5264 /* Advertise Reserved */
5265 { &hf_dlr_advreserved,
5266 { "Reserved", "enip.dlr.advreserved",
5267 FT_BYTES, BASE_NONE, NULL, 0,
5268 "Advertise Reserved", HFILL }
5270 /* Flush_Tables Learning Update Enable */
5271 { &hf_dlr_flushlearningupdateenable,
5272 { "Learning Update Enable", "enip.dlr.flushlearningupdateenable",
5273 FT_UINT8, BASE_HEX, VALS(dlr_flush_learning_update_vals), 0,
5274 "Flush_Tables Learning Update Enable", HFILL }
5276 /* Flush Reserved */
5277 { &hf_dlr_flushreserved,
5278 { "Reserved", "enip.dlr.flushreserved",
5279 FT_BYTES, BASE_NONE, NULL, 0,
5280 "Flush_Tables Reserved", HFILL }
5282 /* Learning_Update Reserved */
5283 { &hf_dlr_learnreserved,
5284 { "Reserved", "enip.dlr.learnreserved",
5285 FT_BYTES, BASE_NONE, NULL, 0,
5286 "Learning_Update Reserved", HFILL }
5290 /* Setup protocol subtree array for DLR */
5291 static int *ettdlr[] = {
5292 &ett_dlr
5295 module_t *enip_module;
5296 expert_module_t* expert_enip;
5298 /* Register the protocol name and description */
5299 proto_enip = proto_register_protocol("EtherNet/IP (Industrial Protocol)", "ENIP", "enip");
5300 proto_cipio = proto_register_protocol("Common Industrial Protocol, I/O", "CIP I/O", "cipio");
5301 proto_cip_class1 = proto_register_protocol_in_name_only(
5302 "Common Industrial Protocol, I/O Class 1",
5303 "CIP Class 1",
5304 "cipio1",
5305 proto_cipio,
5306 FT_PROTOCOL);
5308 enip_tcp_handle = register_dissector("enip", dissect_enip_tcp, proto_enip);
5309 enip_udp_handle = register_dissector("enip.udp", dissect_enip_udp, proto_enip);
5310 enip_cipio_handle = register_dissector_with_description("cipio", "ENIP CIP I/O", dissect_enip_cipio, proto_enip);
5311 cip_class1_handle = register_dissector("cipio_class1", dissect_cip_class1, proto_cip_class1);
5312 cip_io_generic_handle = register_dissector("cipgenericio", dissect_cip_io_generic, proto_cipio);
5314 /* Required function calls to register the header fields and subtrees used */
5315 proto_register_field_array(proto_enip, hf, array_length(hf));
5316 proto_register_subtree_array(ett, array_length(ett));
5318 expert_enip = expert_register_protocol(proto_enip);
5319 expert_register_field_array(expert_enip, ei, array_length(ei));
5321 enip_module = prefs_register_protocol(proto_enip, NULL);
5322 prefs_register_bool_preference(enip_module, "desegment",
5323 "Desegment all EtherNet/IP messages spanning multiple TCP segments",
5324 "Whether the EtherNet/IP dissector should desegment all messages spanning multiple TCP segments",
5325 &enip_desegment);
5327 prefs_register_bool_preference(enip_module, "o2t_run_idle",
5328 "Dissect 32-bit header in the O->T direction",
5329 "Determines whether all I/O connections will assume a 32-bit header in the O->T direction",
5330 &enip_OTrun_idle);
5332 prefs_register_bool_preference(enip_module, "t2o_run_idle",
5333 "Dissect 32-bit header in the T->O direction",
5334 "Determines whether all I/O connections will assume a 32-bit header in the T->O direction",
5335 &enip_TOrun_idle);
5337 prefs_register_obsolete_preference(enip_module, "default_io_dissector");
5339 subdissector_srrd_table = register_dissector_table("enip.srrd.iface",
5340 "ENIP SendRequestReplyData.Interface Handle", proto_enip, FT_UINT32, BASE_HEX);
5342 subdissector_io_table = register_dissector_table("cip.io.iface",
5343 "CIP Class 0/1 Interface Handle", proto_cipio, FT_UINT32, BASE_HEX);
5345 subdissector_cip_connection_table = register_dissector_table("cip.connection.class",
5346 "CIP Class 2/3 Interface Handle", proto_enip, FT_UINT32, BASE_HEX);
5348 enip_request_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), enip_request_hash, enip_request_equal);
5349 enip_conn_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), enip_conn_hash, enip_conn_equal);
5351 register_init_routine(&enip_init_protocol);
5353 /* Register the protocol name and description */
5354 proto_dlr = proto_register_protocol("Device Level Ring", "DLR", "dlr");
5356 /* Required function calls to register the header fields and subtrees used */
5357 proto_register_field_array(proto_dlr, hfdlr, array_length(hfdlr));
5358 proto_register_subtree_array(ettdlr, array_length(ettdlr));
5359 dlr_handle = register_dissector("dlr", dissect_dlr, proto_dlr);
5361 register_conversation_filter("enip", "CIP Connection", cip_connection_conv_valid, cip_connection_conv_filter, NULL);
5363 subdissector_decode_as_io_table = register_decode_as_next_proto(proto_enip, "cip.io", "CIP I/O Payload", enip_prompt);
5364 } /* end of proto_register_enip() */
5366 const value_string lldp_cip_subtypes[] = {
5367 { 1, "Deprecated CIP Identification" },
5368 { 2, "CIP MAC Address" },
5369 { 3, "CIP Interface Label" },
5370 { 4, "Position ID" },
5371 { 5, "T1S PHY Data" },
5372 { 6, "Commission Request" },
5373 { 7, "Commission Response" },
5374 { 8, "Discover Topology Response" },
5375 { 9, "CIP Identification" },
5377 { 0, NULL }
5380 int dissect_lldp_cip_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
5382 int total_len = tvb_reported_length_remaining(tvb, 0);
5383 int offset = 0;
5384 uint32_t subtype;
5385 proto_tree_add_item_ret_uint(tree, hf_lldp_subtype, tvb, offset, 1, ENC_BIG_ENDIAN, &subtype);
5386 offset++;
5388 switch (subtype)
5390 case 1:
5392 dissect_electronic_key_format(tvb, offset, tree, false, CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL, ENC_LITTLE_ENDIAN);
5393 break;
5396 case 2:
5397 proto_tree_add_item(tree, hf_lldp_mac_address, tvb, offset, 6, ENC_NA);
5398 break;
5400 case 3:
5402 // The string is all the data, minus Subtype (1 byte).
5403 int string_len = total_len - 1;
5404 proto_tree_add_item(tree, hf_elink_interface_label, tvb, offset, string_len, ENC_ASCII | ENC_NA);
5405 break;
5408 case 9:
5410 dissect_electronic_key_format(tvb, offset, tree, false, CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL, ENC_BIG_ENDIAN);
5411 break;
5414 default:
5415 break;
5418 return tvb_reported_length(tvb);
5421 void
5422 proto_reg_handoff_enip(void)
5424 /* Register for EtherNet/IP, using TCP */
5425 dissector_add_uint_with_preference("tcp.port", ENIP_ENCAP_PORT, enip_tcp_handle);
5427 /* Register for EtherNet/IP, using UDP */
5428 dissector_add_uint_with_preference("udp.port", ENIP_ENCAP_PORT, enip_udp_handle);
5430 /* Register for EtherNet/IP IO data (UDP) */
5431 dissector_add_uint_with_preference("udp.port", ENIP_IO_PORT, enip_cipio_handle);
5433 /* Register for EtherNet/IP TLS */
5434 ssl_dissector_add(ENIP_SECURE_PORT, enip_tcp_handle);
5435 dtls_dissector_add(ENIP_SECURE_PORT, enip_cipio_handle);
5436 dtls_handle = find_dissector("dtls");
5438 // Allow DecodeAs for DTLS --> ENIP. This supports "UDP-only EtherNet/IP transport profile" over
5439 // port 44818 (for Class 3 and Unconnected Messages)
5440 dissector_add_for_decode_as("dtls.port", enip_udp_handle);
5442 /* Find ARP dissector for TCP/IP object */
5443 arp_handle = find_dissector_add_dependency("arp", proto_enip);
5445 /* I/O data dissectors */
5446 cipsafety_handle = find_dissector("cipsafety");
5448 /* Implicit data dissector */
5449 cip_implicit_handle = find_dissector_add_dependency("cip_implicit", proto_enip);
5451 cip_handle = find_dissector_add_dependency("cip", proto_enip);
5453 /* Register for EtherNet/IP Device Level Ring protocol */
5454 dissector_add_uint("ethertype", ETHERTYPE_DLR, dlr_handle);
5456 subdissector_class_table = find_dissector_table("cip.class.iface");
5458 dissector_add_for_decode_as("cip.io", cip_class1_handle);
5459 } /* end of proto_reg_handoff_enip() */
5462 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5464 * Local variables:
5465 * c-basic-offset: 3
5466 * tab-width: 8
5467 * indent-tabs-mode: nil
5468 * End:
5470 * ex: set shiftwidth=3 tabstop=8 expandtab:
5471 * :indentSize=3:tabSize=8:noTabs=true: