2003-08-16 01:53:41 +00:00
/* packet-enip.c
2003-06-11 22:36:18 +00:00
* Routines for EtherNet / IP ( Industrial Protocol ) dissection
2003-06-11 09:02:19 +00:00
* EtherNet / IP Home : www . odva . org
*
2018-05-18 14:08:08 +00:00
* This dissector includes items from :
2018-06-15 14:45:01 +00:00
* CIP Volume 1 : Common Industrial Protocol , Edition 3.24
* CIP Volume 2 : EtherNet / IP Adaptation of CIP , Edition 1.23
* CIP Volume 8 : CIP Security , Edition 1.6
2018-05-18 14:08:08 +00:00
*
2004-02-04 20:34:53 +00:00
* Copyright 2003 - 2004
2003-06-11 09:02:19 +00:00
* Magnus Hansson < mah @ hms . se >
* Joakim Wiberg < jow @ hms . se >
*
2009-06-26 02:38:23 +00:00
* Conversation data support for CIP
* Jan Bartels , Siempelkamp Maschinen - und Anlagenbau GmbH & Co . KG
* Copyright 2007
*
2011-10-26 04:55:21 +00:00
* Ethernet / IP object support
* Michael Mann
* Copyright 2011
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2003-06-11 09:02:19 +00:00
* Copyright 1998 Gerald Combs
*
2018-02-12 11:23:27 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
2003-06-11 09:02:19 +00:00
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
2003-06-11 09:02:19 +00:00
# include <epan/packet.h>
2015-10-29 03:30:55 +00:00
# include <epan/dissector_filters.h>
2009-06-26 02:38:23 +00:00
# include <epan/prefs.h>
2009-07-09 20:44:28 +00:00
# include <epan/etypes.h>
2011-10-26 04:55:21 +00:00
# include <epan/expert.h>
2015-04-02 21:15:08 +00:00
# include <epan/decode_as.h>
2016-01-25 01:10:20 +00:00
# include <epan/proto_data.h>
2004-01-27 04:43:35 +00:00
# include "packet-tcp.h"
2011-10-02 19:05:20 +00:00
# include "packet-cip.h"
2011-10-26 04:55:21 +00:00
# include "packet-enip.h"
2012-02-27 09:30:26 +00:00
# include "packet-cipsafety.h"
2016-01-28 21:34:14 +00:00
# include "packet-dtls.h"
2018-09-14 15:30:31 +00:00
# include "packet-tls.h"
# include "packet-tls-utils.h"
2003-06-11 09:02:19 +00:00
2013-12-15 23:44:12 +00:00
void proto_register_enip ( void ) ;
void proto_reg_handoff_enip ( void ) ;
2004-09-23 17:34:35 +00:00
/* Communication Ports */
2009-06-26 02:38:23 +00:00
# define ENIP_ENCAP_PORT 44818 /* EtherNet/IP located on port 44818 */
2016-01-28 21:34:14 +00:00
# define ENIP_SECURE_PORT 2221 /* EtherNet/IP TLS/DTLS port */
2009-06-26 02:38:23 +00:00
# define ENIP_IO_PORT 2222 /* EtherNet/IP IO located on port 2222 */
2003-06-11 09:02:19 +00:00
2004-09-23 17:34:35 +00:00
/* EtherNet/IP function codes */
2003-06-11 09:02:19 +00:00
# define NOP 0x0000
# define LIST_SERVICES 0x0004
# define LIST_IDENTITY 0x0063
# define LIST_INTERFACES 0x0064
# define REGISTER_SESSION 0x0065
# define UNREGISTER_SESSION 0x0066
# define SEND_RR_DATA 0x006F
# define SEND_UNIT_DATA 0x0070
# define INDICATE_STATUS 0x0072
# define CANCEL 0x0073
2004-09-23 17:34:35 +00:00
/* EtherNet/IP status codes */
2003-06-11 09:02:19 +00:00
# define SUCCESS 0x0000
# define INVALID_CMD 0x0001
# define NO_RESOURCES 0x0002
# define INCORRECT_DATA 0x0003
# define INVALID_SESSION 0x0064
# define INVALID_LENGTH 0x0065
# define UNSUPPORTED_PROT_REV 0x0069
2016-01-22 19:54:03 +00:00
# define ENCAP_HEADER_ERROR 0x006A
2003-06-11 09:02:19 +00:00
2004-09-23 17:34:35 +00:00
/* EtherNet/IP Common Data Format Type IDs */
2003-06-11 09:02:19 +00:00
# define CDF_NULL 0x0000
# define LIST_IDENTITY_RESP 0x000C
2017-07-20 15:36:59 +00:00
# define LIST_ID_SECURITY 0x0086
2003-06-11 09:02:19 +00:00
# define CONNECTION_BASED 0x00A1
# define CONNECTION_TRANSPORT 0x00B1
# define UNCONNECTED_MSG 0x00B2
# define LIST_SERVICES_RESP 0x0100
# define SOCK_ADR_INFO_OT 0x8000
# define SOCK_ADR_INFO_TO 0x8001
# define SEQ_ADDRESS 0x8002
2016-01-22 19:54:03 +00:00
# define UNCONNECTED_MSG_DTLS 0x8003
2003-06-11 09:02:19 +00:00
2004-09-23 17:34:35 +00:00
/* Initialize the protocol and registered fields */
2012-04-26 16:47:37 +00:00
static int proto_enip = - 1 ;
2018-07-05 14:22:59 +00:00
static int proto_cipio = - 1 ;
static int proto_cip_class1 = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_enip_command = - 1 ;
static int hf_enip_length = - 1 ;
static int hf_enip_options = - 1 ;
static int hf_enip_sendercontex = - 1 ;
2012-11-13 13:14:48 +00:00
static int hf_enip_listid_delay = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_enip_status = - 1 ;
static int hf_enip_session = - 1 ;
static int hf_enip_encapver = - 1 ;
static int hf_enip_sinfamily = - 1 ;
static int hf_enip_sinport = - 1 ;
static int hf_enip_sinaddr = - 1 ;
static int hf_enip_sinzero = - 1 ;
static int hf_enip_timeout = - 1 ;
static int hf_enip_encap_data = - 1 ;
static int hf_enip_lir_vendor = - 1 ;
static int hf_enip_lir_devtype = - 1 ;
static int hf_enip_lir_prodcode = - 1 ;
static int hf_enip_lir_revision = - 1 ;
static int hf_enip_lir_status = - 1 ;
static int hf_enip_lir_serial = - 1 ;
static int hf_enip_lir_namelen = - 1 ;
static int hf_enip_lir_name = - 1 ;
static int hf_enip_lir_state = - 1 ;
static int hf_enip_lsr_capaflags = - 1 ;
static int hf_enip_lsr_tcp = - 1 ;
static int hf_enip_lsr_udp = - 1 ;
2011-04-25 01:37:19 +00:00
static int hf_enip_lsr_servicename = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_enip_rs_version = - 1 ;
static int hf_enip_rs_optionflags = - 1 ;
2004-09-23 17:34:35 +00:00
2017-07-20 15:36:59 +00:00
static int hf_enip_security_profiles = - 1 ;
static int hf_enip_security_profiles_eip_integrity = - 1 ;
static int hf_enip_security_profiles_eip_confidentiality = - 1 ;
static int hf_enip_security_profiles_cip_authorization = - 1 ;
static int hf_enip_security_profiles_cip_integrity = - 1 ;
static int hf_enip_security_profiles_reserved = - 1 ;
static int hf_enip_cip_security_state = - 1 ;
static int hf_enip_eip_security_state = - 1 ;
static int hf_enip_iana_port_state_flags = - 1 ;
static int hf_enip_iana_port_state_flags_tcp_44818 = - 1 ;
static int hf_enip_iana_port_state_flags_udp_44818 = - 1 ;
static int hf_enip_iana_port_state_flags_udp_2222 = - 1 ;
static int hf_enip_iana_port_state_flags_tcp_2221 = - 1 ;
static int hf_enip_iana_port_state_flags_udp_2221 = - 1 ;
static int hf_enip_iana_port_state_flags_reserved = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_enip_srrd_ifacehnd = - 1 ;
2004-09-23 17:34:35 +00:00
2012-04-26 16:47:37 +00:00
static int hf_enip_sud_ifacehnd = - 1 ;
2003-06-11 09:02:19 +00:00
2012-04-26 16:47:37 +00:00
static int hf_enip_cpf_itemcount = - 1 ;
static int hf_enip_cpf_typeid = - 1 ;
static int hf_enip_cpf_length = - 1 ;
2018-06-15 14:45:01 +00:00
static int hf_cip_sequence_count = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_enip_cpf_cai_connid = - 1 ;
static int hf_enip_cpf_sai_connid = - 1 ;
static int hf_enip_cpf_sai_seqnum = - 1 ;
2016-01-22 19:54:03 +00:00
static int hf_enip_cpf_ucmm_request = - 1 ;
static int hf_enip_cpf_ucmm_msg_type = - 1 ;
static int hf_enip_cpf_ucmm_trans_id = - 1 ;
static int hf_enip_cpf_ucmm_status = - 1 ;
2011-12-01 06:05:39 +00:00
2012-04-26 16:47:37 +00:00
static int hf_enip_cpf_data = - 1 ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
static int hf_enip_response_in = - 1 ;
static int hf_enip_response_to = - 1 ;
static int hf_enip_time = - 1 ;
2016-12-05 12:43:03 +00:00
static int hf_enip_fwd_open_in = - 1 ;
2018-06-15 14:45:01 +00:00
static int hf_cip_io_data = - 1 ;
2009-06-26 02:38:23 +00:00
2011-10-26 04:55:21 +00:00
/* Parsed Attributes */
2012-04-26 16:47:37 +00:00
static int hf_tcpip_status = - 1 ;
static int hf_tcpip_status_interface_config = - 1 ;
static int hf_tcpip_status_mcast_pending = - 1 ;
static int hf_tcpip_status_interface_config_pending = - 1 ;
static int hf_tcpip_status_acd = - 1 ;
static int hf_tcpip_status_reserved = - 1 ;
static int hf_tcpip_config_cap = - 1 ;
static int hf_tcpip_config_cap_bootp = - 1 ;
static int hf_tcpip_config_cap_dns = - 1 ;
static int hf_tcpip_config_cap_dhcp = - 1 ;
static int hf_tcpip_config_cap_dhcp_dns_update = - 1 ;
static int hf_tcpip_config_cap_config_settable = - 1 ;
static int hf_tcpip_config_cap_hardware_config = - 1 ;
static int hf_tcpip_config_cap_interface_reset = - 1 ;
static int hf_tcpip_config_cap_acd = - 1 ;
static int hf_tcpip_config_cap_reserved = - 1 ;
static int hf_tcpip_config_control = - 1 ;
static int hf_tcpip_config_control_config = - 1 ;
static int hf_tcpip_config_control_dns = - 1 ;
static int hf_tcpip_config_control_reserved = - 1 ;
static int hf_tcpip_ic_ip_addr = - 1 ;
static int hf_tcpip_ic_subnet_mask = - 1 ;
static int hf_tcpip_ic_gateway = - 1 ;
static int hf_tcpip_ic_name_server = - 1 ;
static int hf_tcpip_ic_name_server2 = - 1 ;
static int hf_tcpip_ic_domain_name = - 1 ;
static int hf_tcpip_hostname = - 1 ;
2016-01-20 15:50:44 +00:00
static int hf_tcpip_snn_timestamp = - 1 ;
static int hf_tcpip_snn_date = - 1 ;
static int hf_tcpip_snn_time = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_tcpip_ttl_value = - 1 ;
static int hf_tcpip_mcast_alloc = - 1 ;
static int hf_tcpip_mcast_reserved = - 1 ;
static int hf_tcpip_mcast_num_mcast = - 1 ;
static int hf_tcpip_mcast_addr_start = - 1 ;
static int hf_tcpip_lcd_acd_activity = - 1 ;
static int hf_tcpip_lcd_remote_mac = - 1 ;
static int hf_tcpip_lcd_arp_pdu = - 1 ;
static int hf_tcpip_select_acd = - 1 ;
static int hf_tcpip_quick_connect = - 1 ;
2016-01-20 15:50:44 +00:00
static int hf_tcpip_encap_inactivity = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_elink_interface_flags = - 1 ;
static int hf_elink_iflags_link_status = - 1 ;
static int hf_elink_iflags_duplex = - 1 ;
static int hf_elink_iflags_neg_status = - 1 ;
static int hf_elink_iflags_manual_reset = - 1 ;
static int hf_elink_iflags_local_hw_fault = - 1 ;
static int hf_elink_iflags_reserved = - 1 ;
static int hf_elink_interface_speed = - 1 ;
static int hf_elink_physical_address = - 1 ;
static int hf_elink_icount_in_octets = - 1 ;
static int hf_elink_icount_in_ucast = - 1 ;
static int hf_elink_icount_in_nucast = - 1 ;
static int hf_elink_icount_in_discards = - 1 ;
static int hf_elink_icount_in_errors = - 1 ;
static int hf_elink_icount_in_unknown_protos = - 1 ;
static int hf_elink_icount_out_octets = - 1 ;
static int hf_elink_icount_out_ucast = - 1 ;
static int hf_elink_icount_out_nucast = - 1 ;
static int hf_elink_icount_out_discards = - 1 ;
static int hf_elink_icount_out_errors = - 1 ;
static int hf_elink_mcount_alignment_errors = - 1 ;
static int hf_elink_mcount_fcs_errors = - 1 ;
static int hf_elink_mcount_single_collisions = - 1 ;
static int hf_elink_mcount_multiple_collisions = - 1 ;
static int hf_elink_mcount_sqe_test_errors = - 1 ;
static int hf_elink_mcount_deferred_transmission = - 1 ;
static int hf_elink_mcount_late_collisions = - 1 ;
static int hf_elink_mcount_excessive_collisions = - 1 ;
static int hf_elink_mcount_mac_transmit_errors = - 1 ;
static int hf_elink_mcount_carrier_sense_errors = - 1 ;
static int hf_elink_mcount_frame_too_long = - 1 ;
static int hf_elink_mcount_mac_receive_errors = - 1 ;
static int hf_elink_icontrol_control_bits = - 1 ;
static int hf_elink_icontrol_control_bits_auto_neg = - 1 ;
2011-10-26 04:55:21 +00:00
static int hf_elink_icontrol_control_bits_forced_duplex = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_elink_icontrol_control_bits_reserved = - 1 ;
static int hf_elink_icontrol_forced_speed = - 1 ;
static int hf_elink_interface_type = - 1 ;
static int hf_elink_interface_state = - 1 ;
static int hf_elink_admin_state = - 1 ;
static int hf_elink_interface_label = - 1 ;
static int hf_qos_8021q_enable = - 1 ;
static int hf_qos_dscp_ptp_event = - 1 ;
static int hf_qos_dscp_ptp_general = - 1 ;
static int hf_qos_dscp_urgent = - 1 ;
static int hf_qos_dscp_scheduled = - 1 ;
static int hf_qos_dscp_high = - 1 ;
static int hf_qos_dscp_low = - 1 ;
static int hf_qos_dscp_explicit = - 1 ;
2011-10-26 04:55:21 +00:00
2012-08-09 16:47:15 +00:00
static int hf_dlr_network_topology = - 1 ;
static int hf_dlr_network_status = - 1 ;
static int hf_dlr_ring_supervisor_status = - 1 ;
static int hf_dlr_rsc_ring_supervisor_enable = - 1 ;
static int hf_dlr_rsc_ring_supervisor_precedence = - 1 ;
static int hf_dlr_rsc_beacon_interval = - 1 ;
static int hf_dlr_rsc_beacon_timeout = - 1 ;
static int hf_dlr_rsc_dlr_vlan_id = - 1 ;
static int hf_dlr_ring_faults_count = - 1 ;
static int hf_dlr_lanp1_dev_ip_addr = - 1 ;
static int hf_dlr_lanp1_dev_physical_address = - 1 ;
static int hf_dlr_lanp2_dev_ip_addr = - 1 ;
static int hf_dlr_lanp2_dev_physical_address = - 1 ;
static int hf_dlr_ring_protocol_participants_count = - 1 ;
static int hf_dlr_rppl_dev_ip_addr = - 1 ;
static int hf_dlr_rppl_dev_physical_address = - 1 ;
static int hf_dlr_asa_supervisor_ip_addr = - 1 ;
static int hf_dlr_asa_supervisor_physical_address = - 1 ;
static int hf_dlr_active_supervisor_precedence = - 1 ;
static int hf_dlr_capability_flags = - 1 ;
static int hf_dlr_capflags_announce_base_node = - 1 ;
static int hf_dlr_capflags_beacon_base_node = - 1 ;
static int hf_dlr_capflags_reserved1 = - 1 ;
static int hf_dlr_capflags_supervisor_capable = - 1 ;
static int hf_dlr_capflags_reserved2 = - 1 ;
2013-04-04 14:34:26 +00:00
static int hf_dlr_capflags_redundant_gateway_capable = - 1 ;
static int hf_dlr_capflags_flush_frame_capable = - 1 ;
static int hf_dlr_rgc_red_gateway_enable = - 1 ;
static int hf_dlr_rgc_gateway_precedence = - 1 ;
static int hf_dlr_rgc_advertise_interval = - 1 ;
static int hf_dlr_rgc_advertise_timeout = - 1 ;
static int hf_dlr_rgc_learning_update_enable = - 1 ;
static int hf_dlr_redundant_gateway_status = - 1 ;
static int hf_dlr_aga_ip_addr = - 1 ;
static int hf_dlr_aga_physical_address = - 1 ;
static int hf_dlr_active_gateway_precedence = - 1 ;
2012-07-18 19:40:56 +00:00
2016-01-28 21:34:14 +00:00
static int hf_eip_security_state = - 1 ;
static int hf_eip_security_verify_client_cert = - 1 ;
static int hf_eip_security_send_cert_chain = - 1 ;
static int hf_eip_security_check_expiration = - 1 ;
static int hf_eip_security_capability_flags = - 1 ;
static int hf_eip_security_capflags_secure_renegotiation = - 1 ;
static int hf_eip_security_capflags_reserved = - 1 ;
static int hf_eip_security_num_avail_cipher_suites = - 1 ;
static int hf_eip_security_avail_cipher_suite = - 1 ;
static int hf_eip_security_num_allow_cipher_suites = - 1 ;
static int hf_eip_security_allow_cipher_suite = - 1 ;
static int hf_eip_security_num_psk = - 1 ;
static int hf_eip_security_psk_identity_size = - 1 ;
static int hf_eip_security_psk_identity = - 1 ;
static int hf_eip_security_psk_size = - 1 ;
static int hf_eip_security_psk = - 1 ;
static int hf_eip_security_num_active_certs = - 1 ;
static int hf_eip_security_num_trusted_auths = - 1 ;
static int hf_eip_cert_name = - 1 ;
static int hf_eip_cert_state = - 1 ;
static int hf_eip_cert_device_cert_status = - 1 ;
static int hf_eip_cert_ca_cert_status = - 1 ;
static int hf_eip_cert_capflags_push = - 1 ;
static int hf_eip_cert_capflags_reserved = - 1 ;
static int hf_eip_cert_capability_flags = - 1 ;
static int hf_eip_cert_num_certs = - 1 ;
static int hf_eip_cert_cert_name = - 1 ;
2003-06-11 09:02:19 +00:00
/* Initialize the subtree pointers */
2012-04-26 16:47:37 +00:00
static gint ett_enip = - 1 ;
2018-06-15 14:45:01 +00:00
static gint ett_cip_io_generic = - 1 ;
2014-08-01 14:08:57 +00:00
static gint ett_path = - 1 ;
2012-04-26 16:47:37 +00:00
static gint ett_count_tree = - 1 ;
static gint ett_type_tree = - 1 ;
static gint ett_command_tree = - 1 ;
static gint ett_sockadd = - 1 ;
static gint ett_lsrcf = - 1 ;
static gint ett_tcpip_status = - 1 ;
static gint ett_tcpip_config_cap = - 1 ;
static gint ett_tcpip_config_control = - 1 ;
2011-10-26 04:55:21 +00:00
static gint ett_elink_interface_flags = - 1 ;
static gint ett_elink_icontrol_bits = - 1 ;
2012-07-18 19:40:56 +00:00
static gint ett_dlr_capability_flags = - 1 ;
2013-04-04 14:34:26 +00:00
static gint ett_dlr_lnknbrstatus_flags = - 1 ;
2016-01-28 21:34:14 +00:00
static gint ett_eip_security_capability_flags = - 1 ;
static gint ett_eip_security_psk = - 1 ;
static gint ett_eip_security_active_certs = - 1 ;
static gint ett_eip_security_trusted_auths = - 1 ;
static gint ett_eip_cert_capability_flags = - 1 ;
static gint ett_eip_cert_num_certs = - 1 ;
2017-07-20 15:36:59 +00:00
static gint ett_security_profiles = - 1 ;
static gint ett_iana_port_state_flags = - 1 ;
2004-09-23 17:34:35 +00:00
2013-05-24 18:02:54 +00:00
static expert_field ei_mal_tcpip_status = EI_INIT ;
static expert_field ei_mal_tcpip_config_cap = EI_INIT ;
static expert_field ei_mal_tcpip_config_control = EI_INIT ;
static expert_field ei_mal_tcpip_interface_config = EI_INIT ;
static expert_field ei_mal_tcpip_mcast_config = EI_INIT ;
static expert_field ei_mal_tcpip_last_conflict = EI_INIT ;
2016-01-20 15:50:44 +00:00
static expert_field ei_mal_tcpip_ssn = EI_INIT ;
2013-05-24 18:02:54 +00:00
static expert_field ei_mal_elink_interface_flags = EI_INIT ;
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
static expert_field ei_mal_elink_physical_address = EI_INIT ;
2013-05-24 18:02:54 +00:00
static expert_field ei_mal_elink_interface_counters = EI_INIT ;
static expert_field ei_mal_elink_media_counters = EI_INIT ;
static expert_field ei_mal_elink_interface_control = EI_INIT ;
static expert_field ei_mal_dlr_ring_supervisor_config = EI_INIT ;
static expert_field ei_mal_dlr_last_active_node_on_port_1 = EI_INIT ;
static expert_field ei_mal_dlr_last_active_node_on_port_2 = EI_INIT ;
static expert_field ei_mal_dlr_ring_protocol_participants_list = EI_INIT ;
static expert_field ei_mal_dlr_active_supervisor_address = EI_INIT ;
static expert_field ei_mal_dlr_capability_flags = EI_INIT ;
static expert_field ei_mal_dlr_redundant_gateway_config = EI_INIT ;
static expert_field ei_mal_dlr_active_gateway_address = EI_INIT ;
2016-01-28 21:34:14 +00:00
static expert_field ei_mal_eip_security_capability_flags = EI_INIT ;
static expert_field ei_mal_eip_security_avail_cipher_suites = EI_INIT ;
static expert_field ei_mal_eip_security_allow_cipher_suites = EI_INIT ;
static expert_field ei_mal_eip_security_preshared_keys = EI_INIT ;
static expert_field ei_mal_eip_security_active_certs = EI_INIT ;
static expert_field ei_mal_eip_security_trusted_auths = EI_INIT ;
static expert_field ei_mal_eip_cert_capability_flags = EI_INIT ;
2013-05-24 18:02:54 +00:00
2004-09-23 17:34:35 +00:00
static dissector_table_t subdissector_srrd_table ;
2015-04-02 21:15:08 +00:00
static dissector_table_t subdissector_io_table ;
2018-06-15 14:45:01 +00:00
static dissector_table_t subdissector_decode_as_io_table ;
2016-01-28 19:13:30 +00:00
static dissector_table_t subdissector_class_table ;
2018-06-27 22:56:17 +00:00
static dissector_table_t subdissector_cip_connection_table ;
2015-04-02 21:15:08 +00:00
2012-02-27 09:30:26 +00:00
static dissector_handle_t arp_handle ;
2012-03-02 03:39:16 +00:00
static dissector_handle_t cipsafety_handle ;
2018-06-15 14:45:01 +00:00
static dissector_handle_t cip_io_generic_handle ;
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
static dissector_handle_t cip_implicit_handle ;
2018-06-27 22:56:17 +00:00
static dissector_handle_t cip_handle ;
2016-12-17 01:06:11 +00:00
static dissector_handle_t enip_tcp_handle ;
2018-07-05 14:22:59 +00:00
static dissector_handle_t cipio_handle ;
static dissector_handle_t cip_class1_handle ;
2004-09-23 17:34:35 +00:00
2012-04-26 16:47:37 +00:00
static gboolean enip_desegment = TRUE ;
2011-12-01 06:05:39 +00:00
static gboolean enip_OTrun_idle = TRUE ;
static gboolean enip_TOrun_idle = FALSE ;
2003-06-11 22:36:18 +00:00
2012-04-26 16:47:37 +00:00
static int proto_dlr = - 1 ;
2009-07-09 20:44:28 +00:00
2012-04-26 16:47:37 +00:00
static int hf_dlr_ringsubtype = - 1 ;
2009-07-09 20:44:28 +00:00
static int hf_dlr_ringprotoversion = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_dlr_frametype = - 1 ;
static int hf_dlr_sourceport = - 1 ;
static int hf_dlr_sourceip = - 1 ;
static int hf_dlr_sequenceid = - 1 ;
2009-07-09 20:44:28 +00:00
2012-04-26 16:47:37 +00:00
static int hf_dlr_ringstate = - 1 ;
2009-07-09 20:44:28 +00:00
static int hf_dlr_supervisorprecedence = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_dlr_beaconinterval = - 1 ;
static int hf_dlr_beacontimeout = - 1 ;
static int hf_dlr_beaconreserved = - 1 ;
2009-07-09 20:44:28 +00:00
2012-04-26 16:47:37 +00:00
static int hf_dlr_nreqreserved = - 1 ;
2009-07-09 20:44:28 +00:00
static int hf_dlr_nressourceport = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_dlr_nresreserved = - 1 ;
2009-07-09 20:44:28 +00:00
2012-04-26 16:47:37 +00:00
static int hf_dlr_lnknbrstatus = - 1 ;
2013-04-04 14:34:26 +00:00
static int hf_dlr_lnknbrstatus_port1 = - 1 ;
static int hf_dlr_lnknbrstatus_port2 = - 1 ;
static int hf_dlr_lnknbrstatus_reserved = - 1 ;
static int hf_dlr_lnknbrstatus_frame_type = - 1 ;
2009-07-09 20:44:28 +00:00
static int hf_dlr_lnknbrreserved = - 1 ;
static int hf_dlr_lfreserved = - 1 ;
static int hf_dlr_anreserved = - 1 ;
static int hf_dlr_sonumnodes = - 1 ;
2012-04-26 16:47:37 +00:00
static int hf_dlr_somac = - 1 ;
static int hf_dlr_soip = - 1 ;
2009-07-09 20:44:28 +00:00
static int hf_dlr_soreserved = - 1 ;
2013-04-04 14:34:26 +00:00
static int hf_dlr_advgatewaystate = - 1 ;
static int hf_dlr_advgatewayprecedence = - 1 ;
static int hf_dlr_advadvertiseinterval = - 1 ;
static int hf_dlr_advadvertisetimeout = - 1 ;
static int hf_dlr_advlearningupdateenable = - 1 ;
static int hf_dlr_advreserved = - 1 ;
static int hf_dlr_flushlearningupdateenable = - 1 ;
static int hf_dlr_flushreserved = - 1 ;
static int hf_dlr_learnreserved = - 1 ;
2009-07-09 20:44:28 +00:00
static gint ett_dlr = - 1 ;
2003-06-11 09:02:19 +00:00
/* Translate function to string - Encapsulation commands */
static const value_string encap_cmd_vals [ ] = {
2009-06-26 02:38:23 +00:00
{ NOP , " NOP " } ,
{ LIST_SERVICES , " List Services " } ,
{ LIST_IDENTITY , " List Identity " } ,
{ LIST_INTERFACES , " List Interfaces " } ,
{ REGISTER_SESSION , " Register Session " } ,
{ UNREGISTER_SESSION , " Unregister Session " } ,
{ SEND_RR_DATA , " Send RR Data " } ,
{ SEND_UNIT_DATA , " Send Unit Data " } ,
{ INDICATE_STATUS , " Indicate Status " } ,
{ CANCEL , " Cancel " } ,
{ 0 , NULL }
2003-06-11 09:02:19 +00:00
} ;
/* Translate function to string - Encapsulation status */
static const value_string encap_status_vals [ ] = {
2012-04-26 16:47:37 +00:00
{ SUCCESS , " Success " } ,
{ INVALID_CMD , " Invalid Command " } ,
{ NO_RESOURCES , " No Memory Resources " } ,
{ INCORRECT_DATA , " Incorrect Data " } ,
{ INVALID_SESSION , " Invalid Session Handle " } ,
{ INVALID_LENGTH , " Invalid Length " } ,
2009-06-26 02:38:23 +00:00
{ UNSUPPORTED_PROT_REV , " Unsupported Protocol Revision " } ,
2016-01-22 19:54:03 +00:00
{ ENCAP_HEADER_ERROR , " Encapsulated CIP service not allowed on this port " } ,
2009-06-26 02:38:23 +00:00
{ 0 , NULL }
2003-06-11 09:02:19 +00:00
} ;
/* Translate function to Common data format values */
static const value_string cdf_type_vals [ ] = {
2012-04-26 16:47:37 +00:00
{ CDF_NULL , " Null Address Item " } ,
{ LIST_IDENTITY_RESP , " List Identity Response " } ,
2017-07-20 15:36:59 +00:00
{ LIST_ID_SECURITY , " CIP Security Information " } ,
2012-04-26 16:47:37 +00:00
{ CONNECTION_BASED , " Connected Address Item " } ,
{ CONNECTION_TRANSPORT , " Connected Data Item " } ,
{ UNCONNECTED_MSG , " Unconnected Data Item " } ,
{ LIST_SERVICES_RESP , " List Services Response " } ,
2009-06-26 02:38:23 +00:00
{ SOCK_ADR_INFO_OT , " Socket Address Info O->T " } ,
{ SOCK_ADR_INFO_TO , " Socket Address Info T->O " } ,
2012-04-26 16:47:37 +00:00
{ SEQ_ADDRESS , " Sequenced Address Item " } ,
2016-01-22 19:54:03 +00:00
{ UNCONNECTED_MSG_DTLS , " Unconnected Message over UDP " } ,
2009-06-26 02:38:23 +00:00
{ 0 , NULL }
2003-06-11 09:02:19 +00:00
} ;
2016-01-22 19:54:03 +00:00
static const value_string unconn_msg_type_vals [ ] = {
{ 0 , " Reserved " } ,
{ 1 , " UCMM_NOACK " } ,
{ 0 , NULL }
} ;
2011-10-26 04:55:21 +00:00
static const value_string enip_tcpip_status_interface_config_vals [ ] = {
{ 0 , " Not configured " } ,
{ 1 , " BOOTP/DHCP/NVS " } ,
{ 2 , " Hardware settings " } ,
{ 0 , NULL }
} ;
static const value_string enip_tcpip_status_acd_vals [ ] = {
{ 0 , " No Address Conflict Detected " } ,
{ 1 , " Address Conflict Detected " } ,
{ 0 , NULL }
} ;
static const value_string enip_tcpip_config_control_config_vals [ ] = {
{ 0 , " Static IP " } ,
{ 1 , " BOOTP " } ,
{ 2 , " DHCP " } ,
{ 0 , NULL }
} ;
static const value_string enip_tcpip_mcast_alloc_vals [ ] = {
{ 0 , " Use default multicast algorithm " } ,
{ 1 , " Use Num Mcast and Mcast Start Addr " } ,
{ 0 , NULL }
} ;
static const value_string enip_tcpip_acd_activity_vals [ ] = {
{ 0 , " No Conflict Detected " } ,
{ 1 , " Probe IPv4 Address " } ,
{ 2 , " Ongoing Detection " } ,
{ 3 , " Semi Active Probe " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_duplex_vals [ ] = {
{ 0 , " Half Duplex " } ,
{ 1 , " Full Duplex " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_iflags_neg_status_vals [ ] = {
{ 0 , " Auto-negotiation in progress " } ,
{ 1 , " Auto-negotiation and speed detection failed " } ,
{ 2 , " Auto-negotiation failed but detected speed " } ,
2015-11-30 18:10:19 +00:00
{ 3 , " Successfully negotiated speed and duplex " } ,
2013-09-20 18:35:10 +00:00
{ 4 , " Auto-negotiation not attempted. Forced speed and duplex " } ,
2011-10-26 04:55:21 +00:00
{ 0 , NULL }
} ;
static const value_string enip_elink_iflags_reset_vals [ ] = {
{ 0 , " Activate change automatically " } ,
{ 1 , " Device requires Reset service for change " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_iflags_hw_fault_vals [ ] = {
{ 0 , " No local hardware fault " } ,
{ 1 , " Local hardware fault detected " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_interface_type_vals [ ] = {
{ 0 , " Unknown type " } ,
{ 1 , " Internal " } ,
{ 2 , " Twisted-pair " } ,
{ 3 , " Optical fiber " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_interface_state_vals [ ] = {
{ 0 , " Unknown state " } ,
{ 1 , " Enabled " } ,
{ 2 , " Disabled " } ,
{ 3 , " Testing " } ,
{ 0 , NULL }
} ;
static const value_string enip_elink_admin_state_vals [ ] = {
{ 1 , " Enabled " } ,
{ 2 , " Disabled " } ,
{ 0 , NULL }
} ;
2012-07-18 19:40:56 +00:00
static const value_string enip_dlr_network_topology_vals [ ] = {
{ 0 , " Linear " } ,
{ 1 , " Ring " } ,
{ 0 , NULL }
} ;
static const value_string enip_dlr_network_status_vals [ ] = {
{ 0 , " Normal " } ,
{ 1 , " Ring Fault " } ,
{ 2 , " Unexpected Loop Detected " } ,
{ 3 , " Partial Network Failure " } ,
{ 4 , " Rapid Fault/Restore Cycle " } ,
{ 0 , NULL }
} ;
static const value_string enip_dlr_ring_supervisor_status_vals [ ] = {
{ 0 , " Backup Ring Supervisor " } ,
{ 1 , " Active Ring Supervisor " } ,
{ 2 , " Ring Node " } ,
{ 3 , " Non-DLR Topology " } ,
{ 4 , " Cannot Support Parameters " } ,
{ 0 , NULL }
} ;
2013-04-04 14:34:26 +00:00
static const value_string enip_dlr_redundant_gateway_status_vals [ ] = {
{ 0 , " Non-Gateway DLR node " } ,
{ 1 , " Backup Gateway " } ,
{ 2 , " Active Gateway " } ,
{ 3 , " Gateway Fault " } ,
{ 4 , " Cannot Support Parameters " } ,
2015-11-30 18:10:19 +00:00
{ 5 , " Partial Network Fault " } ,
2013-04-04 14:34:26 +00:00
{ 0 , NULL }
} ;
2017-07-20 15:36:59 +00:00
static const value_string cip_security_state_vals [ ] = {
{ 0 , " Factory Default Configuration " } ,
{ 1 , " Initial Commissioning In Progress " } ,
{ 2 , " Configured " } ,
{ 3 , " Incomplete Configuration " } ,
{ 0 , NULL }
} ;
2016-01-28 21:34:14 +00:00
static const value_string eip_security_state_vals [ ] = {
{ 0 , " Factory Default Configuration " } ,
{ 1 , " Configuration In Progress " } ,
{ 2 , " Configured " } ,
{ 0 , NULL }
} ;
static const value_string eip_cert_state_vals [ ] = {
{ 0 , " Created " } ,
{ 0 , NULL }
} ;
static const value_string eip_cert_status_vals [ ] = {
{ 0 , " Not Verified " } ,
{ 1 , " Verified " } ,
{ 2 , " Invalid " } ,
{ 0 , NULL }
} ;
2004-09-23 17:34:35 +00:00
/* Translate interface handle to string */
static const value_string enip_interface_handle_vals [ ] = {
2009-06-26 02:38:23 +00:00
{ 0 , " CIP " } ,
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
{ 0 , NULL }
2003-06-11 09:02:19 +00:00
} ;
2009-07-09 20:44:28 +00:00
/* Translate function to DLR Frame Type values */
static const value_string dlr_frame_type_vals [ ] = {
2012-04-26 16:47:37 +00:00
{ DLR_FT_BEACON , " Beacon " } ,
{ DLR_FT_NEIGHBOR_REQ , " Neighbor_Check_Request " } ,
{ DLR_FT_NEIGHBOR_RES , " Neighbor_Check_Response " } ,
2009-07-09 20:44:28 +00:00
{ DLR_FT_LINK_STAT , " Link_Status / Neighbor_Status " } ,
2012-04-26 16:47:37 +00:00
{ DLR_FT_LOCATE_FLT , " Locate_Fault " } ,
{ DLR_FT_ANNOUNCE , " Announce " } ,
{ DLR_FT_SIGN_ON , " Sign_On " } ,
2013-04-04 14:34:26 +00:00
{ DLR_FT_ADVERTISE , " Advertise " } ,
{ DLR_FT_FLUSH_TABLES , " Flush_Tables " } ,
{ DLR_FT_LEARNING_UPDATE , " Learning_Update " } ,
2009-07-09 20:44:28 +00:00
{ 0 , NULL }
} ;
/* Translate function to DLR Source Port values */
static const value_string dlr_source_port_vals [ ] = {
{ 0 , " Port 1 or Port 2 " } ,
{ 1 , " Port 1 " } ,
{ 2 , " Port 2 " } ,
{ 0 , NULL }
} ;
/* Translate function to DLR Ring State values */
static const value_string dlr_ring_state_vals [ ] = {
{ 1 , " RING_NORMAL_STATE " } ,
{ 2 , " RING_FAULT_STATE " } ,
{ 0 , NULL }
} ;
2013-04-04 14:34:26 +00:00
/* Translate function to DLR Advertise State values */
static const value_string dlr_adv_state_vals [ ] = {
{ 0x01 , " ACTIVE_LISTEN_STATE " } ,
{ 0x02 , " ACTIVE_NORMAL_STATE " } ,
{ 0x03 , " FAULT_STATE " } ,
2009-07-09 20:44:28 +00:00
{ 0 , NULL }
} ;
2013-04-04 14:34:26 +00:00
/* Translate function to DLR Learning Update values */
static const value_string dlr_adv_learning_update_vals [ ] = {
{ 0 , " Disabled " } ,
{ 1 , " Enabled " } ,
{ 0 , NULL }
} ;
/* Translate function to DLR Flush Learning Update values */
static const value_string dlr_flush_learning_update_vals [ ] = {
{ 0 , " Disabled " } ,
{ 1 , " Enabled " } ,
{ 0 , NULL }
} ;
static const true_false_string dlr_lnknbrstatus_frame_type_vals = {
2013-09-25 19:13:10 +00:00
" Neighbor_Status Frame " ,
" Link_Status Frame "
2013-04-04 14:34:26 +00:00
} ;
2015-04-02 21:15:08 +00:00
static void enip_prompt ( packet_info * pinfo _U_ , gchar * result )
{
g_snprintf ( result , MAX_DECODE_AS_PROMPT_LEN , " Dissect unidentified I/O traffic as " ) ;
}
2017-02-02 04:13:42 +00:00
static wmem_map_t * enip_request_hashtable = NULL ;
2009-06-26 02:38:23 +00:00
/* Return codes of function classifying packets as query/response */
2011-12-01 06:05:39 +00:00
enum enip_packet_type { ENIP_REQUEST_PACKET , ENIP_RESPONSE_PACKET , ENIP_CANNOT_CLASSIFY } ;
2009-06-26 02:38:23 +00:00
enum enip_packet_data_type { EPDT_UNKNOWN , EPDT_CONNECTED_TRANSPORT , EPDT_UNCONNECTED } ;
typedef struct enip_request_key {
2012-04-26 16:47:37 +00:00
enum enip_packet_type requesttype ;
2009-06-26 02:38:23 +00:00
enum enip_packet_data_type type ;
guint32 session_handle ;
guint64 sender_context ;
guint32 conversation ;
union {
struct {
guint32 connid ;
guint16 sequence ;
} connected_transport ;
} data ;
} enip_request_key_t ;
typedef struct enip_request_val {
2013-08-25 14:23:13 +00:00
wmem_tree_t * frames ;
2009-06-26 02:38:23 +00:00
} enip_request_val_t ;
/*
* Hash Functions
*/
static gint
enip_request_equal ( gconstpointer v , gconstpointer w )
{
2011-10-13 00:00:52 +00:00
const enip_request_key_t * v1 = ( const enip_request_key_t * ) v ;
const enip_request_key_t * v2 = ( const enip_request_key_t * ) w ;
if ( v1 - > conversation = = v2 - > conversation
& & v1 - > session_handle = = v2 - > session_handle
& & v1 - > type = = v2 - > type
& & ( ( v1 - > sender_context = = v2 - > sender_context /* heuristic approach */
& & v1 - > type = = EPDT_UNCONNECTED
)
| |
( v1 - > data . connected_transport . connid = = v2 - > data . connected_transport . connid
& & v1 - > data . connected_transport . sequence = = v2 - > data . connected_transport . sequence
& & v1 - > type = = EPDT_CONNECTED_TRANSPORT
)
)
)
return 1 ;
2009-06-26 02:38:23 +00:00
2011-10-13 00:00:52 +00:00
return 0 ;
2009-06-26 02:38:23 +00:00
}
2011-04-25 01:37:19 +00:00
static void
enip_fmt_lir_revision ( gchar * result , guint32 revision )
{
2012-08-09 16:47:15 +00:00
g_snprintf ( result , ITEM_LABEL_LENGTH , " %d.%02d " , ( guint8 ) ( ( revision & 0xFF00 ) > > 8 ) , ( guint8 ) ( revision & 0xFF ) ) ;
2011-04-25 01:37:19 +00:00
}
2009-06-26 02:38:23 +00:00
static guint
enip_request_hash ( gconstpointer v )
{
const enip_request_key_t * key = ( const enip_request_key_t * ) v ;
guint val ;
2012-02-27 09:30:26 +00:00
val = ( guint ) ( key - > conversation * 37 + key - > session_handle * 93 + key - > type * 765 ) ;
if ( key - > type = = EPDT_UNCONNECTED )
{
val + = ( ( guint ) ( key - > sender_context * 23 ) ) ;
}
else if ( key - > type = = EPDT_CONNECTED_TRANSPORT )
{
val + = ( ( guint ) ( key - > data . connected_transport . connid * 87 + key - > data . connected_transport . sequence * 834 ) ) ;
}
2009-06-26 02:38:23 +00:00
return val ;
}
static enip_request_info_t *
enip_match_request ( packet_info * pinfo , proto_tree * tree , enip_request_key_t * prequest_key )
{
2012-04-26 16:47:37 +00:00
enip_request_key_t * new_request_key ;
enip_request_val_t * request_val ;
2012-08-09 16:47:15 +00:00
enip_request_info_t * request_info ;
2009-06-26 02:38:23 +00:00
request_info = NULL ;
2017-02-02 04:13:42 +00:00
request_val = ( enip_request_val_t * ) wmem_map_lookup ( enip_request_hashtable , prequest_key ) ;
2013-11-21 18:37:26 +00:00
if ( ! pinfo - > fd - > flags . visited )
2009-06-26 02:38:23 +00:00
{
if ( prequest_key & & prequest_key - > requesttype = = ENIP_REQUEST_PACKET )
{
if ( request_val = = NULL )
{
2013-08-25 14:23:13 +00:00
new_request_key = ( enip_request_key_t * ) wmem_memdup ( wmem_file_scope ( ) , prequest_key , sizeof ( enip_request_key_t ) ) ;
2009-06-26 02:38:23 +00:00
2013-08-25 14:23:13 +00:00
request_val = wmem_new ( wmem_file_scope ( ) , enip_request_val_t ) ;
request_val - > frames = wmem_tree_new ( wmem_file_scope ( ) ) ;
2009-06-26 02:38:23 +00:00
2017-02-02 04:13:42 +00:00
wmem_map_insert ( enip_request_hashtable , new_request_key , request_val ) ;
2009-06-26 02:38:23 +00:00
}
2013-08-25 14:23:13 +00:00
request_info = wmem_new ( wmem_file_scope ( ) , enip_request_info_t ) ;
2016-01-24 03:40:51 +00:00
request_info - > req_num = pinfo - > num ;
2009-06-26 02:38:23 +00:00
request_info - > rep_num = 0 ;
2016-01-23 03:50:21 +00:00
request_info - > req_time = pinfo - > abs_ts ;
2009-06-26 02:38:23 +00:00
request_info - > cip_info = NULL ;
2016-01-24 03:40:51 +00:00
wmem_tree_insert32 ( request_val - > frames , pinfo - > num , ( void * ) request_info ) ;
2009-06-26 02:38:23 +00:00
}
2013-11-21 18:37:26 +00:00
if ( request_val & & prequest_key & & prequest_key - > requesttype = = ENIP_RESPONSE_PACKET )
2009-06-26 02:38:23 +00:00
{
2016-01-24 03:40:51 +00:00
request_info = ( enip_request_info_t * ) wmem_tree_lookup32_le ( request_val - > frames , pinfo - > num ) ;
2009-06-26 02:38:23 +00:00
if ( request_info )
{
2016-01-24 03:40:51 +00:00
request_info - > rep_num = pinfo - > num ;
2009-06-26 02:38:23 +00:00
}
}
}
else
{
if ( request_val )
2016-01-24 03:40:51 +00:00
request_info = ( enip_request_info_t * ) wmem_tree_lookup32_le ( request_val - > frames , pinfo - > num ) ;
2009-06-26 02:38:23 +00:00
}
if ( tree & & request_info )
{
/* print state tracking in the tree */
if ( prequest_key & & prequest_key - > requesttype = = ENIP_REQUEST_PACKET )
{
/* This is a request */
if ( request_info - > rep_num )
{
proto_item * it ;
it = proto_tree_add_uint ( tree , hf_enip_response_in ,
NULL , 0 , 0 , request_info - > rep_num ) ;
PROTO_ITEM_SET_GENERATED ( it ) ;
}
}
else
{
if ( prequest_key & & prequest_key - > requesttype = = ENIP_RESPONSE_PACKET )
{
/* This is a reply */
if ( request_info - > req_num )
{
proto_item * it ;
2013-11-21 18:37:26 +00:00
nstime_t ns ;
2009-06-26 02:38:23 +00:00
it = proto_tree_add_uint ( tree , hf_enip_response_to ,
NULL , 0 , 0 , request_info - > req_num ) ;
PROTO_ITEM_SET_GENERATED ( it ) ;
2016-01-23 03:50:21 +00:00
nstime_delta ( & ns , & pinfo - > abs_ts , & request_info - > req_time ) ;
2009-06-26 02:38:23 +00:00
it = proto_tree_add_time ( tree , hf_enip_time , NULL , 0 , 0 , & ns ) ;
PROTO_ITEM_SET_GENERATED ( it ) ;
}
}
}
}
return request_info ;
}
typedef struct enip_conn_key {
2018-05-31 11:24:26 +00:00
cip_connection_triad_t triad ;
2012-02-27 09:30:26 +00:00
guint32 O2TConnID ;
guint32 T2OConnID ;
2009-06-26 02:38:23 +00:00
} enip_conn_key_t ;
typedef struct _enip_conv_info_t {
2013-08-25 14:23:13 +00:00
wmem_tree_t * O2TConnIDs ;
wmem_tree_t * T2OConnIDs ;
2009-06-26 02:38:23 +00:00
} enip_conv_info_t ;
2014-05-27 02:58:48 +00:00
/*
* Conversation filter
*/
static gboolean
enip_io_conv_valid ( packet_info * pinfo )
{
enip_conn_val_t * conn = ( enip_conn_val_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO ) ;
if ( conn = = NULL )
return FALSE ;
return ( ( ( conn - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 0 ) | |
( ( conn - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 1 ) ) ;
}
2015-10-25 14:32:29 +00:00
static gchar *
2014-05-27 02:58:48 +00:00
enip_io_conv_filter ( packet_info * pinfo )
{
char * buf ;
enip_conn_val_t * conn = ( enip_conn_val_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO ) ;
if ( conn = = NULL )
return NULL ;
2014-05-29 15:33:29 +00:00
if ( conn - > close_frame > 0 )
{
buf = g_strdup_printf (
" ((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
" ((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
" ((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x))) " , /* Connection Triad */
conn - > open_frame , conn - > open_reply_frame , conn - > close_frame ,
conn - > O2TConnID , conn - > T2OConnID ,
2018-05-31 11:24:26 +00:00
conn - > triad . ConnSerialNumber , conn - > triad . VendorID , conn - > triad . DeviceSerialNumber ) ;
2014-05-29 15:33:29 +00:00
}
else
{
/* If Forward Close isn't found, don't limit the (end) frame range */
buf = g_strdup_printf (
" ((frame.number == %u) || (frame.number >= %u)) && " /* Frames starting with ForwardOpen */
" ((enip.cpf.sai.connid == 0x%08x || enip.cpf.sai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
" ((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x))) " , /* Connection Triad */
conn - > open_frame , conn - > open_reply_frame ,
conn - > O2TConnID , conn - > T2OConnID ,
2018-05-31 11:24:26 +00:00
conn - > triad . ConnSerialNumber , conn - > triad . VendorID , conn - > triad . DeviceSerialNumber ) ;
2014-05-29 15:33:29 +00:00
}
2014-05-27 02:58:48 +00:00
return buf ;
}
static gboolean
enip_exp_conv_valid ( packet_info * pinfo )
{
enip_conn_val_t * conn = ( enip_conn_val_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO ) ;
if ( conn = = NULL )
return FALSE ;
return ( ( ( conn - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 2 ) | |
( ( conn - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 3 ) ) ;
}
2015-10-25 14:32:29 +00:00
static gchar *
2014-05-27 02:58:48 +00:00
enip_exp_conv_filter ( packet_info * pinfo )
{
char * buf ;
enip_conn_val_t * conn = ( enip_conn_val_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO ) ;
if ( conn = = NULL )
return NULL ;
2014-05-29 15:33:29 +00:00
if ( conn - > close_frame > 0 )
{
buf = g_strdup_printf (
" ((frame.number == %u) || ((frame.number >= %u) && (frame.number <= %u))) && " /* Frames between ForwardOpen and ForwardClose reply */
" ((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
" ((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x))) " , /* Connection Triad */
conn - > open_frame , conn - > open_reply_frame , conn - > close_frame ,
conn - > O2TConnID , conn - > T2OConnID ,
2018-05-31 11:24:26 +00:00
conn - > triad . ConnSerialNumber , conn - > triad . VendorID , conn - > triad . DeviceSerialNumber ) ;
2014-05-29 15:33:29 +00:00
}
else
{
/* If Forward Close isn't found, don't limit the (end) frame range */
buf = g_strdup_printf (
" ((frame.number == %u) || (frame.number >= %u)) && " /* Frames between ForwardOpen and ForwardClose */
" ((enip.cpf.cai.connid == 0x%08x || enip.cpf.cai.connid == 0x%08x) || " /* O->T and T->O Connection IDs */
" ((cip.cm.conn_serial_num == 0x%04x) && (cip.cm.vendor == 0x%04x) && (cip.cm.orig_serial_num == 0x%08x))) " , /* Connection Triad */
conn - > open_frame , conn - > open_reply_frame ,
conn - > O2TConnID , conn - > T2OConnID ,
2018-05-31 11:24:26 +00:00
conn - > triad . ConnSerialNumber , conn - > triad . VendorID , conn - > triad . DeviceSerialNumber ) ;
2014-05-29 15:33:29 +00:00
}
2014-05-27 02:58:48 +00:00
return buf ;
}
2018-07-05 14:22:59 +00:00
static gboolean cip_connection_conv_valid ( packet_info * pinfo )
{
return enip_io_conv_valid ( pinfo ) | | enip_exp_conv_valid ( pinfo ) ;
}
static gchar * cip_connection_conv_filter ( packet_info * pinfo )
{
char * buf = NULL ;
if ( enip_io_conv_valid ( pinfo ) )
{
buf = enip_io_conv_filter ( pinfo ) ;
}
else if ( enip_exp_conv_valid ( pinfo ) )
{
buf = enip_exp_conv_filter ( pinfo ) ;
}
return buf ;
}
2014-05-27 02:58:48 +00:00
/*
* Connection management
*/
2017-02-02 04:13:42 +00:00
static wmem_map_t * enip_conn_hashtable = NULL ;
2009-06-26 02:38:23 +00:00
static guint32 enip_unique_connid = 1 ;
static gint
enip_conn_equal ( gconstpointer v , gconstpointer w )
{
const enip_conn_key_t * v1 = ( const enip_conn_key_t * ) v ;
const enip_conn_key_t * v2 = ( const enip_conn_key_t * ) w ;
2018-05-31 11:24:26 +00:00
if ( ( v1 - > triad . ConnSerialNumber = = v2 - > triad . ConnSerialNumber ) & &
( v1 - > triad . VendorID = = v2 - > triad . VendorID ) & &
( v1 - > triad . DeviceSerialNumber = = v2 - > triad . DeviceSerialNumber ) & &
2012-02-27 09:30:26 +00:00
( ( v1 - > O2TConnID = = 0 ) | | ( v2 - > O2TConnID = = 0 ) | | ( v1 - > O2TConnID = = v2 - > O2TConnID ) ) & &
( ( v1 - > T2OConnID = = 0 ) | | ( v2 - > T2OConnID = = 0 ) | | ( v1 - > T2OConnID = = v2 - > T2OConnID ) ) )
2009-06-26 02:38:23 +00:00
return 1 ;
return 0 ;
}
static guint
enip_conn_hash ( gconstpointer v )
{
const enip_conn_key_t * key = ( const enip_conn_key_t * ) v ;
guint val ;
2018-05-31 11:24:26 +00:00
val = ( guint ) ( key - > triad . ConnSerialNumber + key - > triad . VendorID + key - > triad . DeviceSerialNumber ) ;
2009-06-26 02:38:23 +00:00
return val ;
}
2013-12-16 06:03:17 +00:00
static void
2011-12-01 06:05:39 +00:00
enip_open_cip_connection ( packet_info * pinfo , cip_conn_info_t * connInfo )
2009-06-26 02:38:23 +00:00
{
2012-04-26 16:47:37 +00:00
enip_conn_key_t * conn_key ;
enip_conn_val_t * conn_val ;
conversation_t * conversation , * conversationTO ;
2011-04-25 01:37:19 +00:00
enip_conv_info_t * enip_info ;
2012-04-26 16:47:37 +00:00
address dest_address ;
2017-10-26 08:50:00 +00:00
ws_in6_addr ipv6_zero ;
2009-06-26 02:38:23 +00:00
2011-04-25 01:37:19 +00:00
if ( pinfo - > fd - > flags . visited )
return ;
2009-06-26 02:38:23 +00:00
2018-02-07 13:53:45 +00:00
// Don't create connections for Null Forward Opens.
if ( connInfo - > T2O . type = = CONN_TYPE_NULL & & connInfo - > O2T . type = = CONN_TYPE_NULL )
{
return ;
}
2013-08-25 14:23:13 +00:00
conn_key = wmem_new ( wmem_file_scope ( ) , enip_conn_key_t ) ;
2018-05-31 11:24:26 +00:00
conn_key - > triad = connInfo - > triad ;
2012-02-27 09:30:26 +00:00
conn_key - > O2TConnID = connInfo - > O2T . connID ;
conn_key - > T2OConnID = connInfo - > T2O . connID ;
2009-06-26 02:38:23 +00:00
2017-02-02 04:13:42 +00:00
conn_val = ( enip_conn_val_t * ) wmem_map_lookup ( enip_conn_hashtable , conn_key ) ;
2009-06-26 02:38:23 +00:00
if ( conn_val = = NULL )
{
2013-08-25 14:23:13 +00:00
conn_val = wmem_new ( wmem_file_scope ( ) , enip_conn_val_t ) ;
2009-06-26 02:38:23 +00:00
2018-05-31 11:24:26 +00:00
conn_val - > triad = connInfo - > triad ;
2012-08-09 16:47:15 +00:00
conn_val - > O2TConnID = connInfo - > O2T . connID ;
conn_val - > T2OConnID = connInfo - > T2O . connID ;
2012-02-27 09:30:26 +00:00
conn_val - > TransportClass_trigger = connInfo - > TransportClass_trigger ;
2012-08-09 16:47:15 +00:00
conn_val - > safety = connInfo - > safety ;
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
conn_val - > ClassID = connInfo - > ClassID ;
2018-02-02 16:47:44 +00:00
conn_val - > ConnPoint = connInfo - > ConnPoint ;
2014-05-27 02:58:48 +00:00
conn_val - > open_frame = connInfo - > forward_open_frame ;
2016-01-24 03:40:51 +00:00
conn_val - > open_reply_frame = pinfo - > num ;
2014-05-27 02:58:48 +00:00
conn_val - > close_frame = 0 ;
2012-08-09 16:47:15 +00:00
conn_val - > connid = enip_unique_connid + + ;
2009-06-26 02:38:23 +00:00
2017-02-02 04:13:42 +00:00
wmem_map_insert ( enip_conn_hashtable , conn_key , conn_val ) ;
2009-06-26 02:38:23 +00:00
2011-12-01 06:05:39 +00:00
/* I/O connection */
2012-02-27 09:30:26 +00:00
if ( ( ( connInfo - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 0 ) | |
( ( connInfo - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 1 ) )
2011-12-01 06:05:39 +00:00
{
2012-11-13 13:14:48 +00:00
/* zero out the ipv6 structure for comparison */
memset ( & ipv6_zero , 0 , sizeof ( ipv6_zero ) ) ;
2011-12-01 06:05:39 +00:00
/* default some information if not included */
if ( ( connInfo - > O2T . port = = 0 ) | | ( connInfo - > O2T . type = = CONN_TYPE_MULTICAST ) )
connInfo - > O2T . port = ENIP_IO_PORT ;
2012-11-13 13:14:48 +00:00
if ( ( connInfo - > O2T . ipaddress . type = = AT_NONE ) | |
2013-12-14 14:33:46 +00:00
( ( connInfo - > O2T . ipaddress . type = = AT_IPv4 ) & & ( ( * ( const guint32 * ) connInfo - > O2T . ipaddress . data ) ) = = 0 ) | |
2012-11-13 13:14:48 +00:00
( ( connInfo - > O2T . ipaddress . type = = AT_IPv6 ) & & ( memcmp ( connInfo - > O2T . ipaddress . data , & ipv6_zero , sizeof ( ipv6_zero ) ) = = 0 ) ) | |
( connInfo - > O2T . type ! = CONN_TYPE_MULTICAST ) )
2018-03-03 18:49:22 +00:00
copy_address_wmem ( wmem_file_scope ( ) , & connInfo - > O2T . ipaddress , & pinfo - > src ) ;
2011-12-01 06:05:39 +00:00
if ( ( connInfo - > T2O . port = = 0 ) | | ( connInfo - > T2O . type = = CONN_TYPE_MULTICAST ) )
connInfo - > T2O . port = ENIP_IO_PORT ;
2012-11-13 13:14:48 +00:00
if ( ( connInfo - > T2O . ipaddress . type = = AT_NONE ) | |
2013-12-14 14:33:46 +00:00
( ( connInfo - > T2O . ipaddress . type = = AT_IPv4 ) & & ( ( * ( const guint32 * ) connInfo - > T2O . ipaddress . data ) ) = = 0 ) | |
2012-11-13 13:14:48 +00:00
( ( connInfo - > T2O . ipaddress . type = = AT_IPv6 ) & & ( memcmp ( connInfo - > T2O . ipaddress . data , & ipv6_zero , sizeof ( ipv6_zero ) ) = = 0 ) ) | |
( connInfo - > T2O . type ! = CONN_TYPE_MULTICAST ) )
2018-03-03 18:49:22 +00:00
copy_address_wmem ( wmem_file_scope ( ) , & connInfo - > T2O . ipaddress , & pinfo - > dst ) ;
2011-12-01 06:05:39 +00:00
2012-11-13 13:14:48 +00:00
if ( connInfo - > O2T . ipaddress . type = = AT_IPv6 )
{
dest_address . type = AT_IPv6 ;
2013-11-21 18:37:26 +00:00
dest_address . len = 16 ;
2012-11-13 13:14:48 +00:00
}
else
{
dest_address . type = AT_IPv4 ;
2013-11-21 18:37:26 +00:00
dest_address . len = 4 ;
2012-11-13 13:14:48 +00:00
}
dest_address . data = connInfo - > O2T . ipaddress . data ;
2011-12-01 06:05:39 +00:00
/* check for O->T conversation */
/* similar logic to find_or_create_conversation(), but since I/O traffic
is on UDP , the pinfo parameter doesn ' t have the correct information */
2016-01-24 03:40:51 +00:00
if ( ( conversation = find_conversation ( pinfo - > num , & pinfo - > dst , & dest_address ,
2017-10-29 14:12:59 +00:00
ENDPOINT_UDP , connInfo - > O2T . port , 0 , NO_PORT_B ) ) = = NULL ) {
2011-12-01 06:05:39 +00:00
2016-01-24 03:40:51 +00:00
conversation = conversation_new ( pinfo - > num , & pinfo - > dst , & dest_address ,
2017-10-29 14:12:59 +00:00
ENDPOINT_UDP , connInfo - > O2T . port , 0 , NO_PORT2 ) ;
2012-04-26 16:47:37 +00:00
}
2011-12-01 06:05:39 +00:00
2013-03-14 18:58:42 +00:00
enip_info = ( enip_conv_info_t * ) conversation_get_proto_data ( conversation , proto_enip ) ;
2011-12-01 06:05:39 +00:00
if ( enip_info = = NULL )
{
2013-08-25 14:23:13 +00:00
enip_info = wmem_new ( wmem_file_scope ( ) , enip_conv_info_t ) ;
enip_info - > O2TConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
enip_info - > T2OConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
2010-05-13 18:28:34 +00:00
2011-12-01 06:05:39 +00:00
conversation_add_proto_data ( conversation , proto_enip , enip_info ) ;
}
2013-08-25 14:23:13 +00:00
wmem_tree_insert32 ( enip_info - > O2TConnIDs , connInfo - > O2T . connID , ( void * ) conn_val ) ;
2011-12-01 06:05:39 +00:00
/* Check if separate T->O conversation is necessary. If either side is multicast
or ports aren ' t equal , a separate conversation must be generated */
2014-05-27 02:58:48 +00:00
dest_address . data = connInfo - > T2O . ipaddress . data ;
2016-01-24 03:40:51 +00:00
if ( ( conversationTO = find_conversation ( pinfo - > num , & pinfo - > src , & dest_address ,
2017-10-29 14:12:59 +00:00
ENDPOINT_UDP , connInfo - > T2O . port , 0 , NO_PORT_B ) ) = = NULL ) {
2011-12-01 06:05:39 +00:00
2016-01-24 03:40:51 +00:00
conversationTO = conversation_new ( pinfo - > num , & pinfo - > src ,
2017-10-29 14:12:59 +00:00
& dest_address , ENDPOINT_UDP ,
2012-04-26 16:47:37 +00:00
connInfo - > T2O . port , 0 , NO_PORT2 ) ;
2011-12-01 06:05:39 +00:00
}
2013-03-14 18:58:42 +00:00
enip_info = ( enip_conv_info_t * ) conversation_get_proto_data ( conversationTO , proto_enip ) ;
2011-12-01 06:05:39 +00:00
if ( enip_info = = NULL )
{
2013-08-25 14:23:13 +00:00
enip_info = wmem_new ( wmem_file_scope ( ) , enip_conv_info_t ) ;
enip_info - > O2TConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
enip_info - > T2OConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
2011-12-01 06:05:39 +00:00
conversation_add_proto_data ( conversationTO , proto_enip , enip_info ) ;
}
2013-08-25 14:23:13 +00:00
wmem_tree_insert32 ( enip_info - > T2OConnIDs , connInfo - > T2O . connID , ( void * ) conn_val ) ;
2011-12-01 06:05:39 +00:00
}
else
2009-06-26 02:38:23 +00:00
{
2011-12-01 06:05:39 +00:00
/* explicit message connection */
conversation = find_or_create_conversation ( pinfo ) ;
/* Do we already have a state structure for this conv */
2013-03-14 18:58:42 +00:00
enip_info = ( enip_conv_info_t * ) conversation_get_proto_data ( conversation , proto_enip ) ;
2011-12-01 06:05:39 +00:00
if ( ! enip_info )
{
/*
* No . Attach that information to the conversation , and add
* it to the list of information structures .
*/
2013-08-25 14:23:13 +00:00
enip_info = wmem_new ( wmem_file_scope ( ) , enip_conv_info_t ) ;
enip_info - > O2TConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
enip_info - > T2OConnIDs = wmem_tree_new ( wmem_file_scope ( ) ) ;
2011-12-01 06:05:39 +00:00
conversation_add_proto_data ( conversation , proto_enip , enip_info ) ;
}
2013-08-25 14:23:13 +00:00
wmem_tree_insert32 ( enip_info - > O2TConnIDs , connInfo - > O2T . connID , ( void * ) conn_val ) ;
wmem_tree_insert32 ( enip_info - > T2OConnIDs , connInfo - > T2O . connID , ( void * ) conn_val ) ;
2009-06-26 02:38:23 +00:00
}
}
2014-05-27 02:58:48 +00:00
/* Save the connection info for the conversation filter */
if ( ! pinfo - > fd - > flags . visited )
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO , conn_val ) ;
2009-06-26 02:38:23 +00:00
}
2011-04-25 01:37:19 +00:00
void
2018-05-31 11:24:26 +00:00
enip_close_cip_connection ( packet_info * pinfo , const cip_connection_triad_t * triad )
2009-06-26 02:38:23 +00:00
{
2012-04-26 16:47:37 +00:00
enip_conn_key_t conn_key ;
2011-04-25 01:37:19 +00:00
enip_conn_val_t * conn_val ;
2009-06-26 02:38:23 +00:00
2011-04-25 01:37:19 +00:00
if ( pinfo - > fd - > flags . visited )
return ;
2009-06-26 02:38:23 +00:00
2018-05-31 11:24:26 +00:00
conn_key . triad = * triad ;
2012-08-09 16:47:15 +00:00
conn_key . O2TConnID = 0 ;
conn_key . T2OConnID = 0 ;
2009-06-26 02:38:23 +00:00
2017-02-02 04:13:42 +00:00
conn_val = ( enip_conn_val_t * ) wmem_map_lookup ( enip_conn_hashtable , & conn_key ) ;
2009-06-26 02:38:23 +00:00
if ( conn_val )
{
2016-01-24 03:40:51 +00:00
conn_val - > close_frame = pinfo - > num ;
2014-05-27 02:58:48 +00:00
/* Save the connection info for the conversation filter */
if ( ! pinfo - > fd - > flags . visited )
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO , conn_val ) ;
}
}
/* Save the connection info for the conversation filter */
2018-05-31 11:24:26 +00:00
void enip_mark_connection_triad ( packet_info * pinfo , const cip_connection_triad_t * triad )
2014-05-27 02:58:48 +00:00
{
enip_conn_key_t conn_key ;
enip_conn_val_t * conn_val ;
2018-05-31 11:24:26 +00:00
conn_key . triad = * triad ;
2014-05-27 02:58:48 +00:00
conn_key . O2TConnID = 0 ;
conn_key . T2OConnID = 0 ;
2017-02-02 04:13:42 +00:00
conn_val = ( enip_conn_val_t * ) wmem_map_lookup ( enip_conn_hashtable , & conn_key ) ;
2014-05-27 02:58:48 +00:00
if ( conn_val )
{
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO , conn_val ) ;
2009-06-26 02:38:23 +00:00
}
}
2014-05-29 15:33:29 +00:00
static enip_conn_val_t *
2011-12-01 06:05:39 +00:00
enip_get_explicit_connid ( packet_info * pinfo , enip_request_key_t * prequest_key , guint32 connid )
2009-06-26 02:38:23 +00:00
{
2012-04-26 16:47:37 +00:00
conversation_t * conversation ;
2011-04-25 01:37:19 +00:00
enip_conv_info_t * enip_info ;
2012-04-26 16:47:37 +00:00
enip_conn_val_t * conn_val ;
2014-05-29 15:33:29 +00:00
enum enip_packet_type requesttype = ENIP_REQUEST_PACKET ;
2009-06-26 02:38:23 +00:00
2014-05-29 15:33:29 +00:00
if ( prequest_key ! = NULL )
{
/* Sanity check */
if ( ( prequest_key - > requesttype ! = ENIP_REQUEST_PACKET ) & & ( prequest_key - > requesttype ! = ENIP_RESPONSE_PACKET ) )
return NULL ;
requesttype = prequest_key - > requesttype ;
}
2009-06-26 02:38:23 +00:00
/*
* Do we have a conversation for this connection ?
*/
2017-10-28 13:58:28 +00:00
conversation = find_conversation_pinfo ( pinfo , 0 ) ;
2009-06-26 02:38:23 +00:00
if ( conversation = = NULL )
2014-05-29 15:33:29 +00:00
return NULL ;
2009-06-26 02:38:23 +00:00
/*
* Do we already have a state structure for this conv
*/
2013-03-14 18:58:42 +00:00
enip_info = ( enip_conv_info_t * ) conversation_get_proto_data ( conversation , proto_enip ) ;
2009-06-26 02:38:23 +00:00
if ( ! enip_info )
2014-05-29 15:33:29 +00:00
return NULL ;
2009-06-26 02:38:23 +00:00
conn_val = NULL ;
2014-05-29 15:33:29 +00:00
switch ( requesttype )
2009-06-26 02:38:23 +00:00
{
2013-11-21 18:37:26 +00:00
case ENIP_REQUEST_PACKET :
conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > O2TConnIDs , connid ) ;
if ( conn_val = = NULL )
conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > T2OConnIDs , connid ) ;
break ;
case ENIP_RESPONSE_PACKET :
conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > T2OConnIDs , connid ) ;
if ( conn_val = = NULL )
conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > O2TConnIDs , connid ) ;
break ;
case ENIP_CANNOT_CLASSIFY :
/* ignore */
break ;
2009-06-26 02:38:23 +00:00
}
2016-01-24 03:40:51 +00:00
if ( ( conn_val = = NULL ) | | ( conn_val - > open_reply_frame > pinfo - > num ) )
2014-05-29 15:33:29 +00:00
return NULL ;
2009-06-26 02:38:23 +00:00
2014-05-29 15:33:29 +00:00
return conn_val ;
2009-06-26 02:38:23 +00:00
}
2013-11-21 18:37:26 +00:00
static enip_conn_val_t *
2011-12-01 06:05:39 +00:00
enip_get_io_connid ( packet_info * pinfo , guint32 connid , enum enip_connid_type * pconnid_type )
{
2012-04-26 16:47:37 +00:00
conversation_t * conversation ;
2011-12-01 06:05:39 +00:00
enip_conv_info_t * enip_info ;
2012-04-26 16:47:37 +00:00
enip_conn_val_t * conn_val = NULL ;
2011-12-01 06:05:39 +00:00
* pconnid_type = ECIDT_UNKNOWN ;
2012-02-27 09:30:26 +00:00
2011-12-01 06:05:39 +00:00
/*
* Do we have a conversation for this connection ?
*/
2016-01-24 03:40:51 +00:00
conversation = find_conversation ( pinfo - > num ,
2011-12-01 06:05:39 +00:00
& pinfo - > src , & pinfo - > dst ,
2017-10-29 14:12:59 +00:00
conversation_pt_to_endpoint_type ( pinfo - > ptype ) ,
2012-02-27 09:30:26 +00:00
pinfo - > destport , 0 , NO_PORT_B ) ;
2011-12-01 06:05:39 +00:00
if ( conversation = = NULL )
return NULL ;
/*
* Do we already have a state structure for this conv
*/
2013-03-14 18:58:42 +00:00
if ( ( enip_info = ( enip_conv_info_t * ) conversation_get_proto_data ( conversation , proto_enip ) ) = = NULL )
2011-12-01 06:05:39 +00:00
return NULL ;
if ( enip_info - > O2TConnIDs ! = NULL )
2013-08-25 14:23:13 +00:00
conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > O2TConnIDs , connid ) ;
2011-12-01 06:05:39 +00:00
if ( conn_val = = NULL )
{
if ( enip_info - > T2OConnIDs ! = NULL )
{
2013-08-25 14:23:13 +00:00
if ( ( conn_val = ( enip_conn_val_t * ) wmem_tree_lookup32 ( enip_info - > T2OConnIDs , connid ) ) ! = NULL )
2011-12-01 06:05:39 +00:00
* pconnid_type = ECIDT_T2O ;
}
}
else
{
* pconnid_type = ECIDT_O2T ;
}
2016-01-24 03:40:51 +00:00
if ( ( conn_val = = NULL ) | | ( conn_val - > open_reply_frame > pinfo - > num ) )
2011-12-01 06:05:39 +00:00
return NULL ;
return conn_val ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_status ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2016-01-28 21:34:14 +00:00
static const int * status [ ] = {
& hf_tcpip_status_interface_config ,
& hf_tcpip_status_mcast_pending ,
& hf_tcpip_status_interface_config_pending ,
& hf_tcpip_status_acd ,
& hf_tcpip_status_reserved ,
NULL
} ;
2011-10-26 04:55:21 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_status ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_tcpip_status , ett_tcpip_status , status , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 4 ;
}
2013-12-18 06:51:09 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_config_cap ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2016-01-28 21:34:14 +00:00
static const int * capabilities [ ] = {
& hf_tcpip_config_cap_bootp ,
& hf_tcpip_config_cap_dns ,
& hf_tcpip_config_cap_dhcp ,
& hf_tcpip_config_cap_dhcp_dns_update ,
& hf_tcpip_config_cap_config_settable ,
& hf_tcpip_config_cap_hardware_config ,
& hf_tcpip_config_cap_interface_reset ,
& hf_tcpip_config_cap_acd ,
& hf_tcpip_config_cap_reserved ,
NULL
} ;
2011-10-26 04:55:21 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_config_cap ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_tcpip_config_cap , ett_tcpip_config_cap , capabilities , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 4 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_config_control ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
2011-10-26 04:55:21 +00:00
int offset , int total_len )
{
2016-01-28 21:34:14 +00:00
static const int * control_bits [ ] = {
& hf_tcpip_config_control_config ,
& hf_tcpip_config_control_dns ,
& hf_tcpip_config_control_reserved ,
NULL
} ;
2011-10-26 04:55:21 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_config_control ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_tcpip_config_control , ett_tcpip_config_control , control_bits , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 4 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_physical_link ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2016-02-11 04:15:11 +00:00
return dissect_padded_epath_len_uint ( pinfo , tree , item , tvb , offset , total_len ) ;
2011-10-26 04:55:21 +00:00
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_interface_config ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
guint16 domain_length ;
if ( total_len < 22 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_interface_config ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_tcpip_ic_ip_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_tcpip_ic_subnet_mask , tvb , offset + 4 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_tcpip_ic_gateway , tvb , offset + 8 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_tcpip_ic_name_server , tvb , offset + 12 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( tree , hf_tcpip_ic_name_server2 , tvb , offset + 16 , 4 , ENC_LITTLE_ENDIAN ) ;
domain_length = tvb_get_letohs ( tvb , offset + 20 ) ;
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_tcpip_ic_domain_name , tvb , offset + 22 , domain_length , ENC_ASCII | ENC_NA ) ;
2011-10-26 04:55:21 +00:00
2016-02-11 04:15:11 +00:00
/* Add padding. */
domain_length + = domain_length % 2 ;
2011-10-26 04:55:21 +00:00
return ( 22 + domain_length ) ;
}
2016-10-12 13:36:24 +00:00
static int dissect_tcpip_hostname ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len _U_ )
{
int parsed_len ;
parsed_len = dissect_cip_string_type ( pinfo , tree , item , tvb , offset , hf_tcpip_hostname , CIP_STRING_TYPE ) ;
/* Add padding. */
parsed_len + = parsed_len % 2 ;
return parsed_len ;
}
2016-01-20 15:50:44 +00:00
static int dissect_tcpip_ssn ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
if ( total_len < 6 )
{
expert_add_info ( pinfo , item , & ei_mal_tcpip_ssn ) ;
return total_len ;
}
dissect_cipsafety_ssn ( tree , tvb , pinfo , offset , hf_tcpip_snn_timestamp , hf_tcpip_snn_date , hf_tcpip_snn_time ) ;
return 6 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_mcast_config ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
if ( total_len < 8 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_mcast_config ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_tcpip_mcast_alloc , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_tcpip_mcast_reserved , tvb , offset + 1 , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_tcpip_mcast_num_mcast , tvb , offset + 2 , 2 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( tree , hf_tcpip_mcast_addr_start , tvb , offset + 4 , 4 , ENC_LITTLE_ENDIAN ) ;
return 8 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_tcpip_last_conflict ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2012-02-27 09:30:26 +00:00
tvbuff_t * next_tvb ;
2013-09-20 18:35:10 +00:00
gboolean save_info ;
2012-02-27 09:30:26 +00:00
2011-10-26 04:55:21 +00:00
if ( total_len < 35 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_tcpip_last_conflict ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_tcpip_lcd_acd_activity , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_tcpip_lcd_remote_mac , tvb , offset + 1 , 6 , ENC_NA ) ;
2012-03-02 03:39:16 +00:00
2013-11-21 18:37:26 +00:00
if ( tvb_get_guint8 ( tvb , offset ) = = 0 )
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_tcpip_lcd_arp_pdu , tvb , offset + 7 , 28 , ENC_NA ) ;
2012-02-27 09:30:26 +00:00
else
2013-10-13 19:56:52 +00:00
{
2013-09-20 18:35:10 +00:00
/* Dissect ARP PDU, but don't have it change column info */
2016-06-14 15:55:08 +00:00
save_info = col_get_writable ( pinfo - > cinfo , - 1 ) ;
col_set_writable ( pinfo - > cinfo , - 1 , FALSE ) ;
2013-09-20 18:35:10 +00:00
2014-06-06 14:35:50 +00:00
next_tvb = tvb_new_subset_length ( tvb , offset + 7 , 28 ) ;
2012-02-27 09:30:26 +00:00
call_dissector ( arp_handle , next_tvb , pinfo , tree ) ;
2013-09-20 18:35:10 +00:00
2016-06-14 15:55:08 +00:00
col_set_writable ( pinfo - > cinfo , - 1 , save_info ) ;
2012-02-27 09:30:26 +00:00
}
2012-03-02 03:39:16 +00:00
2011-10-26 04:55:21 +00:00
return 35 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_elink_interface_flags ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2016-01-28 21:34:14 +00:00
static const int * flags [ ] = {
& hf_elink_iflags_link_status ,
& hf_elink_iflags_duplex ,
& hf_elink_iflags_neg_status ,
& hf_elink_iflags_manual_reset ,
& hf_elink_iflags_local_hw_fault ,
& hf_elink_iflags_reserved ,
NULL
} ;
2011-10-26 04:55:21 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_elink_interface_flags ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_elink_interface_flags , ett_elink_interface_flags , flags , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 4 ;
}
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
static int
dissect_elink_physical_address ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
if ( total_len < 6 )
{
expert_add_info ( pinfo , item , & ei_mal_elink_physical_address ) ;
return total_len ;
}
proto_tree_add_item ( tree , hf_elink_physical_address , tvb , offset , 6 , ENC_NA ) ;
return 6 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_elink_interface_counters ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
if ( total_len < 44 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_elink_interface_counters ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_elink_icount_in_octets , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_in_ucast , tvb , offset + 4 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_in_nucast , tvb , offset + 8 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_in_discards , tvb , offset + 12 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_in_errors , tvb , offset + 16 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( tree , hf_elink_icount_in_unknown_protos , tvb , offset + 20 , 4 , ENC_LITTLE_ENDIAN ) ;
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_elink_icount_out_octets , tvb , offset + 24 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_out_ucast , tvb , offset + 28 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_out_nucast , tvb , offset + 32 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_out_discards , tvb , offset + 36 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icount_out_errors , tvb , offset + 40 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 44 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_elink_media_counters ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
2011-10-26 04:55:21 +00:00
int offset , int total_len )
{
if ( total_len < 48 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_elink_media_counters ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_elink_mcount_alignment_errors , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_fcs_errors , tvb , offset + 4 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_single_collisions , tvb , offset + 8 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_multiple_collisions , tvb , offset + 12 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_sqe_test_errors , tvb , offset + 16 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( tree , hf_elink_mcount_deferred_transmission , tvb , offset + 20 , 4 , ENC_LITTLE_ENDIAN ) ;
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_elink_mcount_late_collisions , tvb , offset + 24 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_excessive_collisions , tvb , offset + 28 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_mac_transmit_errors , tvb , offset + 32 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_carrier_sense_errors , tvb , offset + 36 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_frame_too_long , tvb , offset + 40 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_mcount_mac_receive_errors , tvb , offset + 44 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 48 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_elink_interface_control ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2011-10-26 04:55:21 +00:00
{
2016-01-28 21:34:14 +00:00
static const int * control_bits [ ] = {
& hf_elink_icontrol_control_bits_auto_neg ,
& hf_elink_icontrol_control_bits_forced_duplex ,
& hf_elink_icontrol_control_bits_reserved ,
NULL
} ;
2011-10-26 04:55:21 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_elink_interface_control ) ;
2011-10-26 04:55:21 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_elink_icontrol_control_bits , ett_elink_icontrol_bits , control_bits , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_elink_icontrol_forced_speed , tvb , offset + 2 , 2 , ENC_LITTLE_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
return 4 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_ring_supervisor_config ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2012-07-18 19:40:56 +00:00
{
if ( total_len < 12 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_ring_supervisor_config ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_dlr_rsc_ring_supervisor_enable , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rsc_ring_supervisor_precedence , tvb , offset + 1 , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rsc_beacon_interval , tvb , offset + 2 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rsc_beacon_timeout , tvb , offset + 6 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rsc_dlr_vlan_id , tvb , offset + 10 , 2 , ENC_LITTLE_ENDIAN ) ;
2012-07-18 19:40:56 +00:00
return 12 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_last_active_node_on_port_1 ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2012-07-18 19:40:56 +00:00
{
if ( total_len < 10 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_last_active_node_on_port_1 ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_dlr_lanp1_dev_ip_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_dlr_lanp1_dev_physical_address , tvb , offset + 4 , 6 , ENC_NA ) ;
2012-07-18 19:40:56 +00:00
return 10 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_last_active_node_on_port_2 ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2012-07-18 19:40:56 +00:00
{
if ( total_len < 10 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_last_active_node_on_port_2 ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_dlr_lanp2_dev_ip_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_dlr_lanp2_dev_physical_address , tvb , offset + 4 , 6 , ENC_NA ) ;
2012-07-18 19:40:56 +00:00
return 10 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_ring_protocol_participants_list ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2012-07-18 19:40:56 +00:00
{
int pos ;
if ( total_len % 10 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_ring_protocol_participants_list ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2013-11-21 18:37:26 +00:00
pos = 0 ;
while ( pos < total_len )
2012-07-18 19:40:56 +00:00
{
2013-02-01 16:16:05 +00:00
proto_tree_add_item ( tree , hf_dlr_rppl_dev_ip_addr , tvb , offset + pos , 4 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_dlr_rppl_dev_physical_address , tvb , offset + pos + 4 , 6 , ENC_NA ) ;
2012-08-09 16:47:15 +00:00
pos + = 10 ;
2012-07-18 19:40:56 +00:00
}
return total_len ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_active_supervisor_address ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2012-07-18 19:40:56 +00:00
{
if ( total_len < 10 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_active_supervisor_address ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( tree , hf_dlr_asa_supervisor_ip_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_dlr_asa_supervisor_physical_address , tvb , offset + 4 , 6 , ENC_NA ) ;
2012-07-18 19:40:56 +00:00
return 10 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_capability_flags ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
2012-07-18 19:40:56 +00:00
int offset , int total_len )
{
2016-01-28 21:34:14 +00:00
static const int * capabilities [ ] = {
& hf_dlr_capflags_announce_base_node ,
& hf_dlr_capflags_beacon_base_node ,
& hf_dlr_capflags_reserved1 ,
& hf_dlr_capflags_supervisor_capable ,
& hf_dlr_capflags_redundant_gateway_capable ,
& hf_dlr_capflags_flush_frame_capable ,
& hf_dlr_capflags_reserved2 ,
NULL
} ;
2012-07-18 19:40:56 +00:00
if ( total_len < 4 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_capability_flags ) ;
2012-07-18 19:40:56 +00:00
return total_len ;
}
2016-01-28 21:34:14 +00:00
proto_tree_add_bitmask ( tree , tvb , offset , hf_dlr_capability_flags , ett_dlr_capability_flags , capabilities , ENC_LITTLE_ENDIAN ) ;
2012-07-18 19:40:56 +00:00
return 4 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_redundant_gateway_config ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2013-04-04 14:34:26 +00:00
{
if ( total_len < 11 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_redundant_gateway_config ) ;
2013-04-04 14:34:26 +00:00
return total_len ;
}
proto_tree_add_item ( tree , hf_dlr_rgc_red_gateway_enable , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rgc_gateway_precedence , tvb , offset + 1 , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rgc_advertise_interval , tvb , offset + 2 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rgc_advertise_timeout , tvb , offset + 6 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree , hf_dlr_rgc_learning_update_enable , tvb , offset + 10 , 1 , ENC_LITTLE_ENDIAN ) ;
return 11 ;
}
2013-12-16 06:03:17 +00:00
static int
2013-11-21 18:37:26 +00:00
dissect_dlr_active_gateway_address ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2013-04-04 14:34:26 +00:00
{
if ( total_len < 10 )
{
2013-05-24 18:02:54 +00:00
expert_add_info ( pinfo , item , & ei_mal_dlr_active_gateway_address ) ;
2013-04-04 14:34:26 +00:00
return total_len ;
}
proto_tree_add_item ( tree , hf_dlr_aga_ip_addr , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_dlr_aga_physical_address , tvb , offset + 4 , 6 , ENC_NA ) ;
2013-04-04 14:34:26 +00:00
return 10 ;
}
2016-01-28 21:34:14 +00:00
static int
dissect_eip_security_cap ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
static const int * capabilities [ ] = {
& hf_eip_security_capflags_secure_renegotiation ,
& hf_eip_security_capflags_reserved ,
NULL
} ;
if ( total_len < 4 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_capability_flags ) ;
return total_len ;
}
proto_tree_add_bitmask ( tree , tvb , offset , hf_eip_security_capability_flags , ett_eip_security_capability_flags , capabilities , ENC_LITTLE_ENDIAN ) ;
return 4 ;
}
static int
dissect_eip_security_avail_cipher_suites ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
guint32 i , num_suites ;
if ( total_len < 1 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_avail_cipher_suites ) ;
return total_len ;
}
proto_tree_add_item_ret_uint ( tree , hf_eip_security_num_avail_cipher_suites , tvb , offset , 1 , ENC_NA , & num_suites ) ;
for ( i = 0 ; i < num_suites ; i + + )
{
proto_tree_add_item ( tree , hf_eip_security_avail_cipher_suite , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
}
return ( ( num_suites * 2 ) + 1 ) ;
}
static int
dissect_eip_security_allow_cipher_suites ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
guint32 i , num_suites ;
if ( total_len < 1 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_allow_cipher_suites ) ;
return total_len ;
}
proto_tree_add_item_ret_uint ( tree , hf_eip_security_num_allow_cipher_suites , tvb , offset , 1 , ENC_NA , & num_suites ) ;
for ( i = 0 ; i < num_suites ; i + + )
{
proto_tree_add_item ( tree , hf_eip_security_allow_cipher_suite , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
}
return ( ( num_suites * 2 ) + 1 ) ;
}
static int
dissect_eip_security_preshared_keys ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
guint32 i , num , id_size , psk_size ;
proto_item * ti ;
proto_tree * psk_tree ;
int start_offset = offset ;
2018-05-31 16:48:52 +00:00
if ( total_len < 1 )
2016-01-28 21:34:14 +00:00
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_preshared_keys ) ;
return total_len ;
}
ti = proto_tree_add_item_ret_uint ( tree , hf_eip_security_num_psk , tvb , offset , 1 , ENC_NA , & num ) ;
psk_tree = proto_item_add_subtree ( ti , ett_eip_security_psk ) ;
offset + + ;
for ( i = 0 ; i < num ; i + + )
{
proto_tree_add_item_ret_uint ( psk_tree , hf_eip_security_psk_identity_size , tvb , offset , 1 , ENC_NA , & id_size ) ;
if ( total_len < ( int ) ( id_size + 2 ) )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_preshared_keys ) ;
return total_len ;
}
offset + + ;
proto_tree_add_item ( psk_tree , hf_eip_security_psk_identity , tvb , offset , id_size , ENC_NA ) ;
offset + = id_size ;
proto_tree_add_item_ret_uint ( psk_tree , hf_eip_security_psk_size , tvb , offset , 1 , ENC_NA , & psk_size ) ;
offset + + ;
if ( total_len < ( int ) ( id_size + psk_size + 2 ) )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_preshared_keys ) ;
return total_len ;
}
2018-05-31 16:48:52 +00:00
proto_tree_add_item ( psk_tree , hf_eip_security_psk , tvb , offset , psk_size , ENC_NA ) ;
2016-01-28 21:34:14 +00:00
offset + = psk_size ;
}
proto_item_set_len ( ti , offset - start_offset ) ;
return offset - start_offset ;
}
static int
dissect_eip_security_active_certs ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
guint32 i , num , path_size ;
2016-02-11 04:15:11 +00:00
proto_item * ti ;
2016-01-28 21:34:14 +00:00
proto_tree * cert_tree ;
int start_offset = offset ;
if ( total_len < 2 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_active_certs ) ;
return total_len ;
}
ti = proto_tree_add_item_ret_uint ( tree , hf_eip_security_num_active_certs , tvb , offset , 1 , ENC_NA , & num ) ;
cert_tree = proto_item_add_subtree ( ti , ett_eip_security_active_certs ) ;
offset + + ;
for ( i = 0 ; i < num ; i + + )
{
2016-02-11 04:15:11 +00:00
path_size = dissect_padded_epath_len_usint ( pinfo , cert_tree , ti , tvb , offset , total_len ) ;
2016-01-28 21:34:14 +00:00
offset + = path_size ;
}
proto_item_set_len ( ti , offset - start_offset ) ;
return offset - start_offset ;
}
static int
dissect_eip_security_trusted_auths ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
guint32 i , num , path_size ;
2016-02-11 04:15:11 +00:00
proto_item * ti ;
2016-01-28 21:34:14 +00:00
proto_tree * cert_tree ;
int start_offset = offset ;
if ( total_len < 2 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_security_trusted_auths ) ;
return total_len ;
}
ti = proto_tree_add_item_ret_uint ( tree , hf_eip_security_num_trusted_auths , tvb , offset , 1 , ENC_NA , & num ) ;
cert_tree = proto_item_add_subtree ( ti , ett_eip_security_trusted_auths ) ;
offset + + ;
for ( i = 0 ; i < num ; i + + )
{
2016-02-11 04:15:11 +00:00
path_size = dissect_padded_epath_len_usint ( pinfo , cert_tree , ti , tvb , offset , total_len ) ;
2016-01-28 21:34:14 +00:00
offset + = path_size ;
}
proto_item_set_len ( ti , offset - start_offset ) ;
return offset - start_offset ;
}
static int
2016-02-11 04:15:11 +00:00
dissect_eip_security_cert_revocation_list ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2016-01-28 21:34:14 +00:00
{
2016-02-11 04:15:11 +00:00
return dissect_padded_epath_len_usint ( pinfo , tree , item , tvb , offset , total_len ) ;
2016-01-28 21:34:14 +00:00
}
static int
dissect_eip_cert_cap_flags ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
{
static const int * capabilities [ ] = {
& hf_eip_cert_capflags_push ,
& hf_eip_cert_capflags_reserved ,
NULL
} ;
if ( total_len < 4 )
{
expert_add_info ( pinfo , item , & ei_mal_eip_cert_capability_flags ) ;
return total_len ;
}
proto_tree_add_bitmask ( tree , tvb , offset , hf_eip_cert_capability_flags , ett_eip_cert_capability_flags , capabilities , ENC_LITTLE_ENDIAN ) ;
return 4 ;
}
static int
dissect_eip_cert_cert_list ( packet_info * pinfo , proto_tree * tree , proto_item * item _U_ , tvbuff_t * tvb ,
2016-02-11 04:15:11 +00:00
int offset , int total_len )
2016-01-28 21:34:14 +00:00
{
guint32 i , num , path_size ;
2016-02-11 04:15:11 +00:00
proto_item * ti ;
2016-01-28 21:34:14 +00:00
proto_tree * cert_tree ;
int start_offset = offset ;
ti = proto_tree_add_item_ret_uint ( tree , hf_eip_cert_num_certs , tvb , offset , 1 , ENC_NA , & num ) ;
cert_tree = proto_item_add_subtree ( ti , ett_eip_cert_num_certs ) ;
offset + + ;
for ( i = 0 ; i < num ; i + + )
{
path_size = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_item ( tree , hf_eip_cert_cert_name , tvb , offset + 1 , path_size , ENC_ASCII | ENC_NA ) ;
offset + = ( 1 + path_size ) ;
2016-02-11 04:15:11 +00:00
path_size = dissect_padded_epath_len_usint ( pinfo , cert_tree , ti , tvb , offset , total_len ) ;
2016-01-28 21:34:14 +00:00
offset + = path_size ;
}
proto_item_set_len ( ti , offset - start_offset ) ;
return offset - start_offset ;
}
static int
2016-02-11 04:15:11 +00:00
dissect_eip_cert_device_cert ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2016-01-28 21:34:14 +00:00
{
guint32 path_size ;
proto_tree_add_item ( tree , hf_eip_cert_device_cert_status , tvb , offset , 1 , ENC_NA ) ;
offset + + ;
2016-02-11 04:15:11 +00:00
path_size = dissect_padded_epath_len_usint ( pinfo , tree , item , tvb , offset , total_len ) ;
return path_size + 1 ;
2016-01-28 21:34:14 +00:00
}
static int
2016-02-11 04:15:11 +00:00
dissect_eip_cert_ca_cert ( packet_info * pinfo , proto_tree * tree , proto_item * item , tvbuff_t * tvb ,
int offset , int total_len )
2016-01-28 21:34:14 +00:00
{
guint32 path_size ;
proto_tree_add_item ( tree , hf_eip_cert_ca_cert_status , tvb , offset , 1 , ENC_NA ) ;
offset + + ;
2016-02-11 04:15:11 +00:00
path_size = dissect_padded_epath_len_usint ( pinfo , tree , item , tvb , offset , total_len ) ;
return path_size + 1 ;
2016-01-28 21:34:14 +00:00
}
attribute_info_t enip_attribute_vals [ 99 ] = {
2016-01-20 15:50:44 +00:00
/* TCP/IP Object (class attributes) */
{ 0xF5 , TRUE , 1 , 0 , CLASS_ATTRIBUTE_1_NAME , cip_uint , & hf_attr_class_revision , NULL } ,
{ 0xF5 , TRUE , 2 , 1 , CLASS_ATTRIBUTE_2_NAME , cip_uint , & hf_attr_class_max_instance , NULL } ,
{ 0xF5 , TRUE , 3 , 2 , CLASS_ATTRIBUTE_3_NAME , cip_uint , & hf_attr_class_num_instance , NULL } ,
{ 0xF5 , TRUE , 4 , 3 , CLASS_ATTRIBUTE_4_NAME , cip_dissector_func , NULL , dissect_optional_attr_list } ,
{ 0xF5 , TRUE , 5 , 4 , CLASS_ATTRIBUTE_5_NAME , cip_dissector_func , NULL , dissect_optional_service_list } ,
{ 0xF5 , TRUE , 6 , 5 , CLASS_ATTRIBUTE_6_NAME , cip_uint , & hf_attr_class_num_class_attr , NULL } ,
{ 0xF5 , TRUE , 7 , 6 , CLASS_ATTRIBUTE_7_NAME , cip_uint , & hf_attr_class_num_inst_attr , NULL } ,
/* TCP/IP object (instance attributes) */
{ 0xF5 , FALSE , 1 , 0 , " Status " , cip_dissector_func , NULL , dissect_tcpip_status } ,
{ 0xF5 , FALSE , 2 , 1 , " Configuration Capability " , cip_dissector_func , NULL , dissect_tcpip_config_cap } ,
{ 0xF5 , FALSE , 3 , 2 , " Configuration Control " , cip_dissector_func , NULL , dissect_tcpip_config_control } ,
{ 0xF5 , FALSE , 4 , 3 , " Physical Link Object " , cip_dissector_func , NULL , dissect_tcpip_physical_link } ,
{ 0xF5 , FALSE , 5 , 4 , " Interface Configuration " , cip_dissector_func , NULL , dissect_tcpip_interface_config } ,
2016-10-12 13:36:24 +00:00
{ 0xF5 , FALSE , 6 , 5 , " Host Name " , cip_dissector_func , NULL , dissect_tcpip_hostname } ,
2016-01-20 15:50:44 +00:00
{ 0xF5 , FALSE , 7 , 6 , " Safety Network Number " , cip_dissector_func , NULL , dissect_tcpip_ssn } ,
{ 0xF5 , FALSE , 8 , 7 , " TTL Value " , cip_usint , & hf_tcpip_ttl_value , NULL } ,
{ 0xF5 , FALSE , 9 , 8 , " Multicast Configuration " , cip_dissector_func , NULL , dissect_tcpip_mcast_config } ,
{ 0xF5 , FALSE , 10 , 9 , " Select ACD " , cip_bool , & hf_tcpip_select_acd , NULL } ,
{ 0xF5 , FALSE , 11 , 10 , " Last Conflict Detected " , cip_dissector_func , NULL , dissect_tcpip_last_conflict } ,
{ 0xF5 , FALSE , 12 , 11 , " EtherNet/IP Quick Connect " , cip_bool , & hf_tcpip_quick_connect , NULL } ,
{ 0xF5 , FALSE , 13 , 12 , " Encapsulation Inactivity Timeout " , cip_uint , & hf_tcpip_encap_inactivity , NULL } ,
/* Ethernet Link Object (class attributes) */
{ 0xF6 , TRUE , 1 , 0 , CLASS_ATTRIBUTE_1_NAME , cip_uint , & hf_attr_class_revision , NULL } ,
{ 0xF6 , TRUE , 2 , 1 , CLASS_ATTRIBUTE_2_NAME , cip_uint , & hf_attr_class_max_instance , NULL } ,
{ 0xF6 , TRUE , 3 , 2 , CLASS_ATTRIBUTE_3_NAME , cip_uint , & hf_attr_class_num_instance , NULL } ,
{ 0xF6 , TRUE , 4 , 3 , CLASS_ATTRIBUTE_4_NAME , cip_dissector_func , NULL , dissect_optional_attr_list } ,
{ 0xF6 , TRUE , 5 , 4 , CLASS_ATTRIBUTE_5_NAME , cip_dissector_func , NULL , dissect_optional_service_list } ,
{ 0xF6 , TRUE , 6 , 5 , CLASS_ATTRIBUTE_6_NAME , cip_uint , & hf_attr_class_num_class_attr , NULL } ,
{ 0xF6 , TRUE , 7 , 6 , CLASS_ATTRIBUTE_7_NAME , cip_uint , & hf_attr_class_num_inst_attr , NULL } ,
/* Ethernet Link object (instance attributes) */
{ 0xF6 , FALSE , 1 , 0 , " Interface Speed " , cip_dword , & hf_elink_interface_speed , NULL } ,
{ 0xF6 , FALSE , 2 , 1 , " Interface Flags " , cip_dissector_func , NULL , dissect_elink_interface_flags } ,
{ 0xF6 , FALSE , 3 , 2 , " Physical Address " , cip_dissector_func , NULL , dissect_elink_physical_address } ,
{ 0xF6 , FALSE , 4 , 3 , " Interface Counters " , cip_dissector_func , NULL , dissect_elink_interface_counters } ,
{ 0xF6 , FALSE , 5 , 4 , " Media Counters " , cip_dissector_func , NULL , dissect_elink_media_counters } ,
{ 0xF6 , FALSE , 6 , 5 , " Interface Control " , cip_dissector_func , NULL , dissect_elink_interface_control } ,
{ 0xF6 , FALSE , 7 , 6 , " Interface Type " , cip_usint , & hf_elink_interface_type , NULL } ,
{ 0xF6 , FALSE , 8 , 7 , " Interface State " , cip_usint , & hf_elink_interface_state , NULL } ,
{ 0xF6 , FALSE , 9 , 8 , " Admin State " , cip_usint , & hf_elink_admin_state , NULL } ,
{ 0xF6 , FALSE , 10 , 9 , " Interface Label " , cip_short_string , & hf_elink_interface_label , NULL } ,
/* QoS Object (class attributes) */
{ 0x48 , TRUE , 1 , 0 , CLASS_ATTRIBUTE_1_NAME , cip_uint , & hf_attr_class_revision , NULL } ,
{ 0x48 , TRUE , 2 , 1 , CLASS_ATTRIBUTE_2_NAME , cip_uint , & hf_attr_class_max_instance , NULL } ,
{ 0x48 , TRUE , 3 , 2 , CLASS_ATTRIBUTE_3_NAME , cip_uint , & hf_attr_class_num_instance , NULL } ,
{ 0x48 , TRUE , 4 , 3 , CLASS_ATTRIBUTE_4_NAME , cip_dissector_func , NULL , dissect_optional_attr_list } ,
{ 0x48 , TRUE , 5 , 4 , CLASS_ATTRIBUTE_5_NAME , cip_dissector_func , NULL , dissect_optional_service_list } ,
{ 0x48 , TRUE , 6 , 5 , CLASS_ATTRIBUTE_6_NAME , cip_uint , & hf_attr_class_num_class_attr , NULL } ,
{ 0x48 , TRUE , 7 , 6 , CLASS_ATTRIBUTE_7_NAME , cip_uint , & hf_attr_class_num_inst_attr , NULL } ,
/* QoS object (instance attributes) */
{ 0x48 , FALSE , 1 , - 1 , " 802.1Q Tag Enable " , cip_bool , & hf_qos_8021q_enable , NULL } ,
{ 0x48 , FALSE , 2 , - 1 , " DSCP PTP Event " , cip_usint , & hf_qos_dscp_ptp_event , NULL } ,
{ 0x48 , FALSE , 3 , - 1 , " DSCP PTP General " , cip_usint , & hf_qos_dscp_ptp_general , NULL } ,
{ 0x48 , FALSE , 4 , - 1 , " DSCP Urgent " , cip_usint , & hf_qos_dscp_urgent , NULL } ,
{ 0x48 , FALSE , 5 , - 1 , " DSCP Scheduled " , cip_usint , & hf_qos_dscp_scheduled , NULL } ,
{ 0x48 , FALSE , 6 , - 1 , " DSCP High " , cip_usint , & hf_qos_dscp_high , NULL } ,
{ 0x48 , FALSE , 7 , - 1 , " DSCP Low " , cip_usint , & hf_qos_dscp_low , NULL } ,
{ 0x48 , FALSE , 8 , - 1 , " DSCP Explicit " , cip_usint , & hf_qos_dscp_explicit , NULL } ,
/* DLR Object (class attributes) */
{ 0x47 , TRUE , 1 , 0 , CLASS_ATTRIBUTE_1_NAME , cip_uint , & hf_attr_class_revision , NULL } ,
{ 0x47 , TRUE , 2 , 1 , CLASS_ATTRIBUTE_2_NAME , cip_uint , & hf_attr_class_max_instance , NULL } ,
{ 0x47 , TRUE , 3 , 2 , CLASS_ATTRIBUTE_3_NAME , cip_uint , & hf_attr_class_num_instance , NULL } ,
{ 0x47 , TRUE , 4 , 3 , CLASS_ATTRIBUTE_4_NAME , cip_dissector_func , NULL , dissect_optional_attr_list } ,
{ 0x47 , TRUE , 5 , 4 , CLASS_ATTRIBUTE_5_NAME , cip_dissector_func , NULL , dissect_optional_service_list } ,
{ 0x47 , TRUE , 6 , 5 , CLASS_ATTRIBUTE_6_NAME , cip_uint , & hf_attr_class_num_class_attr , NULL } ,
{ 0x47 , TRUE , 7 , 6 , CLASS_ATTRIBUTE_7_NAME , cip_uint , & hf_attr_class_num_inst_attr , NULL } ,
/* DLR object (instance attributes) */
2016-02-11 04:15:11 +00:00
/* Get Attributes All is not fully parsed here because there are multiple formats. */
2016-01-20 15:50:44 +00:00
{ 0x47 , FALSE , 1 , 0 , " Network Topology " , cip_usint , & hf_dlr_network_topology , NULL } ,
{ 0x47 , FALSE , 2 , 1 , " Network Status " , cip_usint , & hf_dlr_network_status , NULL } ,
{ 0x47 , FALSE , 3 , - 1 , " Ring Supervisor Status " , cip_usint , & hf_dlr_ring_supervisor_status , NULL } ,
{ 0x47 , FALSE , 4 , - 1 , " Ring Supervisor Config " , cip_dissector_func , NULL , dissect_dlr_ring_supervisor_config } ,
{ 0x47 , FALSE , 5 , - 1 , " Ring Faults Count " , cip_uint , & hf_dlr_ring_faults_count , NULL } ,
{ 0x47 , FALSE , 6 , - 1 , " Last Active Node on Port 1 " , cip_dissector_func , NULL , dissect_dlr_last_active_node_on_port_1 } ,
{ 0x47 , FALSE , 7 , - 1 , " Last Active Node on Port 2 " , cip_dissector_func , NULL , dissect_dlr_last_active_node_on_port_2 } ,
{ 0x47 , FALSE , 8 , - 1 , " Ring Protocol Participants Count " , cip_uint , & hf_dlr_ring_protocol_participants_count , NULL } ,
{ 0x47 , FALSE , 9 , - 1 , " Ring Protocol Participants List " , cip_dissector_func , NULL , dissect_dlr_ring_protocol_participants_list } ,
{ 0x47 , FALSE , 10 , - 1 , " Active Supervisor Address " , cip_dissector_func , NULL , dissect_dlr_active_supervisor_address } ,
{ 0x47 , FALSE , 11 , - 1 , " Active Supervisor Precedence " , cip_usint , & hf_dlr_active_supervisor_precedence , NULL } ,
{ 0x47 , FALSE , 12 , - 1 , " Capability Flags " , cip_dissector_func , NULL , dissect_dlr_capability_flags } ,
{ 0x47 , FALSE , 13 , - 1 , " Redundant Gateway Config " , cip_dissector_func , NULL , dissect_dlr_redundant_gateway_config } ,
{ 0x47 , FALSE , 14 , - 1 , " Redundant Gateway Status " , cip_usint , & hf_dlr_redundant_gateway_status , NULL } ,
{ 0x47 , FALSE , 15 , - 1 , " Active Gateway Address " , cip_dissector_func , NULL , dissect_dlr_active_gateway_address } ,
{ 0x47 , FALSE , 16 , - 1 , " Active Gateway Precedence " , cip_usint , & hf_dlr_active_gateway_precedence , NULL } ,
2016-01-28 21:34:14 +00:00
/* EtherNet/IP Security object (instance attributes) */
{ 0x5E , FALSE , 1 , 0 , " State " , cip_usint , & hf_eip_security_state , NULL } ,
{ 0x5E , FALSE , 2 , 1 , " Capability Flags " , cip_dissector_func , NULL , dissect_eip_security_cap } ,
{ 0x5E , FALSE , 3 , 2 , " Available Cipher Suites " , cip_dissector_func , NULL , dissect_eip_security_avail_cipher_suites } ,
{ 0x5E , FALSE , 4 , 3 , " Allowed Cipher Suites " , cip_dissector_func , NULL , dissect_eip_security_allow_cipher_suites } ,
{ 0x5E , FALSE , 5 , 4 , " Pre-Shared Keys " , cip_dissector_func , NULL , dissect_eip_security_preshared_keys } ,
{ 0x5E , FALSE , 6 , 5 , " Active Device Certificates " , cip_dissector_func , NULL , dissect_eip_security_active_certs } ,
{ 0x5E , FALSE , 7 , 6 , " Trusted Authorities " , cip_dissector_func , NULL , dissect_eip_security_trusted_auths } ,
{ 0x5E , FALSE , 8 , 7 , " Certificate Revocation List " , cip_dissector_func , NULL , dissect_eip_security_cert_revocation_list } ,
{ 0x5E , FALSE , 9 , 8 , " Verify Client Certificate " , cip_bool , & hf_eip_security_verify_client_cert , NULL } ,
{ 0x5E , FALSE , 10 , 9 , " Send Certificate Chain " , cip_bool , & hf_eip_security_send_cert_chain , NULL } ,
{ 0x5E , FALSE , 11 , 10 , " Check Expiration " , cip_bool , & hf_eip_security_check_expiration , NULL } ,
/* Certificate Management Object (class attributes) */
{ 0x5F , TRUE , 1 , 0 , CLASS_ATTRIBUTE_1_NAME , cip_uint , & hf_attr_class_revision , NULL } ,
{ 0x5F , TRUE , 2 , 1 , CLASS_ATTRIBUTE_2_NAME , cip_uint , & hf_attr_class_max_instance , NULL } ,
{ 0x5F , TRUE , 3 , - 1 , CLASS_ATTRIBUTE_3_NAME , cip_uint , & hf_attr_class_num_instance , NULL } ,
{ 0x5F , TRUE , 4 , - 1 , CLASS_ATTRIBUTE_4_NAME , cip_dissector_func , NULL , dissect_optional_attr_list } ,
{ 0x5F , TRUE , 5 , - 1 , CLASS_ATTRIBUTE_5_NAME , cip_dissector_func , NULL , dissect_optional_service_list } ,
{ 0x5F , TRUE , 6 , 2 , CLASS_ATTRIBUTE_6_NAME , cip_uint , & hf_attr_class_num_class_attr , NULL } ,
{ 0x5F , TRUE , 7 , 3 , CLASS_ATTRIBUTE_7_NAME , cip_uint , & hf_attr_class_num_inst_attr , NULL } ,
{ 0x5F , TRUE , 8 , 4 , " Capability Flags " , cip_dissector_func , NULL , dissect_eip_cert_cap_flags } ,
{ 0x5F , TRUE , 9 , 5 , " Certificate List " , cip_dissector_func , NULL , dissect_eip_cert_cert_list } ,
2016-02-11 04:15:11 +00:00
/* Certificate Management Object (instance attributes) */
2016-01-28 21:34:14 +00:00
{ 0x5F , FALSE , 1 , 0 , " Name " , cip_short_string , & hf_eip_cert_name , NULL } ,
{ 0x5F , FALSE , 2 , 1 , " State " , cip_usint , & hf_eip_cert_state , NULL } ,
{ 0x5F , FALSE , 3 , 2 , " Device Certificate " , cip_dissector_func , NULL , dissect_eip_cert_device_cert } ,
{ 0x5F , FALSE , 4 , 3 , " CA Certificate " , cip_dissector_func , NULL , dissect_eip_cert_ca_cert } ,
2011-10-26 04:55:21 +00:00
} ;
2018-06-11 17:16:31 +00:00
// offset - Starts at the "Encapsulation Protocol Version" field.
static void dissect_item_list_identity ( packet_info * pinfo , tvbuff_t * tvb , int offset , proto_tree * item_tree )
{
/* Encapsulation version */
proto_tree_add_item ( item_tree , hf_enip_encapver , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
/* Socket Address */
proto_tree * sockaddr_tree = proto_tree_add_subtree ( item_tree , tvb , offset + 2 , 16 , ett_sockadd , NULL , " Socket Address " ) ;
/* Socket address struct - sin_family */
proto_tree_add_item ( sockaddr_tree , hf_enip_sinfamily , tvb , offset + 2 , 2 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_port */
proto_tree_add_item ( sockaddr_tree , hf_enip_sinport , tvb , offset + 4 , 2 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_address */
proto_tree_add_item ( sockaddr_tree , hf_enip_sinaddr , tvb , offset + 6 , 4 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_zero */
proto_tree_add_item ( sockaddr_tree , hf_enip_sinzero , tvb , offset + 10 , 8 , ENC_NA ) ;
/* Vendor ID */
proto_tree_add_item ( item_tree , hf_enip_lir_vendor , tvb , offset + 18 , 2 , ENC_LITTLE_ENDIAN ) ;
/* Device Type */
proto_tree_add_item ( item_tree , hf_enip_lir_devtype , tvb , offset + 20 , 2 , ENC_LITTLE_ENDIAN ) ;
/* Product Code */
proto_tree_add_item ( item_tree , hf_enip_lir_prodcode , tvb , offset + 22 , 2 , ENC_LITTLE_ENDIAN ) ;
/* Revision */
proto_tree_add_item ( item_tree , hf_enip_lir_revision , tvb , offset + 24 , 2 , ENC_BIG_ENDIAN ) ;
/* Status */
proto_tree_add_item ( item_tree , hf_enip_lir_status , tvb , offset + 26 , 2 , ENC_LITTLE_ENDIAN ) ;
/* Serial Number */
proto_tree_add_item ( item_tree , hf_enip_lir_serial , tvb , offset + 28 , 4 , ENC_LITTLE_ENDIAN ) ;
/* Product Name Length */
guint32 name_length ;
proto_tree_add_item_ret_uint ( item_tree , hf_enip_lir_namelen , tvb , offset + 32 , 1 , ENC_LITTLE_ENDIAN , & name_length ) ;
/* Product Name */
proto_tree_add_item ( item_tree , hf_enip_lir_name , tvb , offset + 33 , name_length , ENC_ASCII | ENC_NA ) ;
/* Append product name to info column */
col_append_fstr ( pinfo - > cinfo , COL_INFO , " , %s " , tvb_format_text ( tvb , offset + 33 , name_length ) ) ;
/* State */
proto_tree_add_item ( item_tree , hf_enip_lir_state , tvb , offset + name_length + 33 , 1 , ENC_LITTLE_ENDIAN ) ;
}
// offset - Starts at the "Security Profiles" field.
static void dissect_item_cip_security_information ( tvbuff_t * tvb , int offset , proto_tree * item_tree )
{
static const int * security_profiles [ ] = {
& hf_enip_security_profiles_eip_integrity ,
& hf_enip_security_profiles_eip_confidentiality ,
& hf_enip_security_profiles_cip_authorization ,
& hf_enip_security_profiles_cip_integrity ,
& hf_enip_security_profiles_reserved ,
NULL
} ;
static const int * iana_flags [ ] = {
& hf_enip_iana_port_state_flags_tcp_44818 ,
& hf_enip_iana_port_state_flags_udp_44818 ,
& hf_enip_iana_port_state_flags_udp_2222 ,
& hf_enip_iana_port_state_flags_tcp_2221 ,
& hf_enip_iana_port_state_flags_udp_2221 ,
& hf_enip_iana_port_state_flags_reserved ,
NULL
} ;
/* Security profiles */
proto_tree_add_bitmask ( item_tree , tvb , offset , hf_enip_security_profiles , ett_security_profiles , security_profiles , ENC_LITTLE_ENDIAN ) ;
/* CIP Security object state */
proto_tree_add_item ( item_tree , hf_enip_cip_security_state , tvb , offset + 2 , 1 , ENC_LITTLE_ENDIAN ) ;
/* ENIP Security object state */
proto_tree_add_item ( item_tree , hf_enip_eip_security_state , tvb , offset + 3 , 1 , ENC_LITTLE_ENDIAN ) ;
/* IANA Port State flags */
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 ) ;
}
// offset - Starts at the "Encapsulation Protocol Version" field.
static void dissect_item_list_services_response ( packet_info * pinfo , tvbuff_t * tvb , int offset , proto_tree * item_tree )
{
/* Encapsulation version */
proto_tree_add_item ( item_tree , hf_enip_encapver , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
/* Capability flags */
static const int * capability_bits [ ] = {
& hf_enip_lsr_tcp ,
& hf_enip_lsr_udp ,
NULL
} ;
proto_tree_add_bitmask ( item_tree , tvb , offset + 2 , hf_enip_lsr_capaflags , ett_lsrcf , capability_bits , ENC_LITTLE_ENDIAN ) ;
/* Name of service */
proto_tree_add_item ( item_tree , hf_enip_lsr_servicename , tvb , offset + 4 , 16 , ENC_ASCII | ENC_NA ) ;
/* Append service name to info column */
col_append_fstr ( pinfo - > cinfo , COL_INFO , " , %s " ,
tvb_format_stringzpad ( tvb , offset + 4 , 16 ) ) ;
}
// This dissects Class 0 or Class 1 I/O.
// offset - Starts at the field after the Item Length field.
2018-06-15 14:45:01 +00:00
static int dissect_cip_io_generic ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * tree , void * data )
2018-06-11 17:16:31 +00:00
{
2018-06-15 14:45:01 +00:00
cip_io_data_input * io_data_input = ( cip_io_data_input * ) data ;
2018-06-11 17:16:31 +00:00
2018-06-15 14:45:01 +00:00
int offset = 0 ;
2018-07-05 14:22:59 +00:00
proto_item * ti = proto_tree_add_item ( tree , proto_cipio , tvb , 0 , - 1 , ENC_NA ) ;
2018-06-15 14:45:01 +00:00
proto_tree * io_tree = proto_item_add_subtree ( ti , ett_cip_io_generic ) ;
2018-06-23 23:09:51 +00:00
if ( io_data_input ! = NULL ) {
if ( ( io_data_input - > conn_info - > TransportClass_trigger & CI_TRANSPORT_CLASS_MASK ) = = 1 )
{
proto_tree_add_item ( io_tree , hf_cip_sequence_count , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
offset + = 2 ;
}
2018-06-11 17:16:31 +00:00
2018-06-23 23:09:51 +00:00
if ( ( tvb_reported_length_remaining ( tvb , offset ) > = 4 ) & &
( ( ( io_data_input - > connid_type = = ECIDT_O2T ) & & enip_OTrun_idle ) | |
( ( io_data_input - > connid_type = = ECIDT_T2O ) & & enip_TOrun_idle ) ) )
{
dissect_cip_run_idle ( tvb , offset , io_tree ) ;
offset + = 4 ;
}
2018-06-11 17:16:31 +00:00
}
2018-06-15 14:45:01 +00:00
proto_tree_add_item ( io_tree , hf_cip_io_data , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , ENC_NA ) ;
return tvb_captured_length ( tvb ) ;
2018-06-11 17:16:31 +00:00
}
// Dissect the various kinds of CIP Class 0/1 I/O formats. This will determine the appropriate format and
// call the appropriate related dissector.
// offset - Starts at the field after the Item Length field.
static void dissect_cip_class01_io ( packet_info * pinfo , tvbuff_t * tvb , int offset ,
int item_length , enip_conn_val_t * conn_info , enum enip_connid_type connid_type ,
2018-06-15 14:45:01 +00:00
proto_tree * dissector_tree )
2018-06-11 17:16:31 +00:00
{
if ( tvb_reported_length_remaining ( tvb , offset ) < = 0 )
{
return ;
}
/* Display data */
tvbuff_t * next_tvb = tvb_new_subset_length ( tvb , offset , item_length ) ;
if ( conn_info ! = NULL )
{
2018-06-15 14:45:01 +00:00
cip_io_data_input io_data_input ;
io_data_input . conn_info = conn_info ;
io_data_input . connid_type = connid_type ;
2018-06-11 17:16:31 +00:00
if ( conn_info - > safety . safety_seg = = TRUE )
{
/* Add any possible safety related data */
cip_safety_info_t cip_safety ;
cip_safety . conn_type = connid_type ;
cip_safety . eip_conn_info = conn_info ;
cip_safety . compute_crc = TRUE ;
call_dissector_with_data ( cipsafety_handle , next_tvb , pinfo , dissector_tree , & cip_safety ) ;
}
else
{
2018-06-15 14:45:01 +00:00
dissector_handle_t dissector = dissector_get_uint_handle ( subdissector_io_table , conn_info - > ClassID ) ;
if ( dissector )
{
call_dissector_with_data ( dissector , next_tvb , pinfo , dissector_tree , & io_data_input ) ;
}
else
{
call_dissector_with_data ( cip_io_generic_handle , next_tvb , pinfo , dissector_tree , & io_data_input ) ;
}
2018-06-11 17:16:31 +00:00
}
/* Save the connection info for the conversation filter */
if ( ! pinfo - > fd - > flags . visited )
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO , conn_info ) ;
}
else
{
// This handles the Decode As options
2018-06-15 14:45:01 +00:00
if ( ! dissector_try_payload ( subdissector_decode_as_io_table , next_tvb , pinfo , dissector_tree ) )
2018-06-11 17:16:31 +00:00
{
2018-06-23 23:09:51 +00:00
call_dissector_with_data ( cip_io_generic_handle , next_tvb , pinfo , dissector_tree , NULL ) ;
2018-06-11 17:16:31 +00:00
}
}
}
2018-06-27 22:56:17 +00:00
// Dissect CIP Class 2/3 data. This will determine the appropriate format and call the appropriate related dissector.
// offset - Starts at the field after the Item Length field.
static void dissect_cip_class23_data ( packet_info * pinfo , tvbuff_t * tvb , int offset ,
proto_tree * tree , proto_tree * item_tree , guint32 item_length ,
enip_request_key_t * request_key , enip_conn_val_t * conn_info , proto_tree * dissector_tree )
{
enip_request_info_t * request_info = NULL ;
if ( request_key )
{
request_key - > type = EPDT_CONNECTED_TRANSPORT ;
request_key - > data . connected_transport . sequence = tvb_get_letohs ( tvb , offset ) ;
request_info = enip_match_request ( pinfo , tree , request_key ) ;
}
/* Save the connection info for the conversation filter */
if ( ( ! pinfo - > fd - > flags . visited ) & & ( conn_info ! = NULL ) )
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_CONNECTION_INFO , conn_info ) ;
/* Add sequence count ( Transport Class 2,3 ) */
proto_tree_add_item ( item_tree , hf_cip_sequence_count , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
/* Call dissector for interface */
tvbuff_t * next_tvb = tvb_new_subset_length ( tvb , offset + 2 , item_length - 2 ) ;
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO , request_info ) ;
if ( conn_info ! = NULL )
{
dissector_handle_t dissector = dissector_get_uint_handle ( subdissector_cip_connection_table , conn_info - > ClassID ) ;
if ( dissector )
{
call_dissector_with_data ( dissector , next_tvb , pinfo , dissector_tree , GUINT_TO_POINTER ( conn_info - > ClassID ) ) ;
}
else
{
call_dissector_with_data ( cip_implicit_handle , next_tvb , pinfo , dissector_tree , GUINT_TO_POINTER ( conn_info - > ClassID ) ) ;
}
}
else
{
// Default to Message Router format, since this is the most common. Since we don't have the connection
// info, at least ensure that the data can at least meet the minimum explicit message size.
if ( tvb_reported_length ( next_tvb ) > = 2 )
{
call_dissector ( cip_handle , next_tvb , pinfo , dissector_tree ) ;
}
}
p_remove_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
}
2018-06-11 17:16:31 +00:00
// offset - Starts at the sin_family field.
static void dissect_item_sockaddr_info ( packet_info * pinfo , tvbuff_t * tvb , int offset , proto_tree * item_tree ,
guint32 item_type_id , gboolean is_fwd_open )
{
/* Socket address struct - sin_family */
proto_tree_add_item ( item_tree , hf_enip_sinfamily , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_port */
proto_tree_add_item ( item_tree , hf_enip_sinport , tvb , offset + 2 , 2 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_address */
proto_tree_add_item ( item_tree , hf_enip_sinaddr , tvb , offset + 4 , 4 , ENC_BIG_ENDIAN ) ;
/* Socket address struct - sin_zero */
proto_tree_add_item ( item_tree , hf_enip_sinzero , tvb , offset + 8 , 8 , ENC_NA ) ;
if ( is_fwd_open )
{
enip_request_info_t * request_info = ( enip_request_info_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
if ( request_info ! = NULL )
{
if ( item_type_id = = SOCK_ADR_INFO_OT )
{
request_info - > cip_info - > connInfo - > O2T . port = tvb_get_ntohs ( tvb , offset + 2 ) ;
alloc_address_tvb ( wmem_file_scope ( ) , & request_info - > cip_info - > connInfo - > O2T . ipaddress ,
AT_IPv4 , sizeof ( guint32 ) , tvb , offset + 4 ) ;
}
else
{
request_info - > cip_info - > connInfo - > T2O . port = tvb_get_ntohs ( tvb , offset + 2 ) ;
alloc_address_tvb ( wmem_file_scope ( ) , & request_info - > cip_info - > connInfo - > T2O . ipaddress ,
AT_IPv4 , sizeof ( guint32 ) , tvb , offset + 4 ) ;
}
}
}
}
// offset - Starts at the Connection ID
// Returns: connid_type, conn_info
2018-06-22 11:48:58 +00:00
static void dissect_item_sequenced_address ( packet_info * pinfo , tvbuff_t * tvb , int offset ,
2018-06-11 17:16:31 +00:00
proto_tree * item_tree , proto_tree * tree ,
enum enip_connid_type * connid_type , enip_conn_val_t * * conn_info )
{
* conn_info = enip_get_io_connid ( pinfo , tvb_get_letohl ( tvb , offset ) , connid_type ) ;
proto_tree_add_item ( item_tree , hf_enip_cpf_sai_connid , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( item_tree , hf_enip_cpf_sai_seqnum , tvb , offset + 4 , 4 , ENC_LITTLE_ENDIAN ) ;
if ( * conn_info )
{
proto_item * it = proto_tree_add_uint ( tree , hf_enip_fwd_open_in , tvb , 0 , 0 , ( * conn_info ) - > open_frame ) ;
PROTO_ITEM_SET_GENERATED ( it ) ;
}
/* Add info to column */
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Connection: ID=0x%08X, SEQ=%010d " ,
tvb_get_letohl ( tvb , offset ) ,
tvb_get_letohl ( tvb , offset + 4 ) ) ;
}
// offset - Starts at the Connection ID
// Returns: conn_info
2018-06-22 11:48:58 +00:00
static void dissect_item_connected_address ( packet_info * pinfo , tvbuff_t * tvb , int offset ,
2018-06-11 17:16:31 +00:00
proto_tree * item_tree , proto_tree * tree , proto_item * enip_item ,
enip_request_key_t * request_key , enip_conn_val_t * * conn_info )
{
guint32 connection_id ;
proto_tree_add_item_ret_uint ( item_tree , hf_enip_cpf_cai_connid , tvb , offset , 4 , ENC_LITTLE_ENDIAN , & connection_id ) ;
* conn_info = enip_get_explicit_connid ( pinfo , request_key , connection_id ) ;
if ( request_key )
{
request_key - > type = EPDT_CONNECTED_TRANSPORT ;
request_key - > data . connected_transport . connid = ( * conn_info ! = NULL ) ? ( * conn_info ) - > connid : 0 ;
}
/* Add Connection ID to Info col and tree */
col_append_fstr ( pinfo - > cinfo , COL_INFO , " , CONID: 0x%08X " , connection_id ) ;
if ( enip_item )
{
proto_item_append_text ( enip_item , " , Connection ID: 0x%08X " , connection_id ) ;
}
if ( * conn_info )
{
proto_item * it = proto_tree_add_uint ( tree , hf_enip_fwd_open_in , tvb , 0 , 0 , ( * conn_info ) - > open_frame ) ;
PROTO_ITEM_SET_GENERATED ( it ) ;
}
}
// offset - Starts at Unconn Msg Type
// returns - input_request_key
// Dissects the following parts of the Unconnected Message over UDP item: Unconn Msg Type, Transaction Number, Status.
// The Unconnected Messge field is handled outside of this function.
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 )
{
guint32 ucmm_request ;
proto_tree_add_item_ret_uint ( item_tree , hf_enip_cpf_ucmm_request , tvb , offset , 2 , ENC_LITTLE_ENDIAN , & ucmm_request ) ;
proto_tree_add_item ( item_tree , hf_enip_cpf_ucmm_msg_type , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
guint32 trans_id ;
proto_tree_add_item_ret_uint ( item_tree , hf_enip_cpf_ucmm_trans_id , tvb , offset + 2 , 4 , ENC_LITTLE_ENDIAN , & trans_id ) ;
proto_tree_add_item ( item_tree , hf_enip_cpf_ucmm_status , tvb , offset + 6 , 4 , ENC_LITTLE_ENDIAN ) ;
if ( * input_request_key = = NULL )
{
/*
* Under normal circumstances request_key should always be NULL here
* Duplicating setting up a request ( like is done with explicit messaging )
*/
conversation_t * conversation = find_or_create_conversation ( pinfo ) ;
/*
* Attach that information to the conversation , and add
* it to the list of information structures later before dissection .
*/
enip_request_key_t * request_key = wmem_new0 ( wmem_packet_scope ( ) , enip_request_key_t ) ;
request_key - > requesttype = ucmm_request ? ENIP_RESPONSE_PACKET : ENIP_REQUEST_PACKET ;
request_key - > type = EPDT_UNKNOWN ;
/* UCMM over UDP doesn't have a session handle, so use conversation
* pointer as " unique-ish ID "
*/
request_key - > session_handle = GPOINTER_TO_UINT ( conversation ) ;
request_key - > sender_context = trans_id ;
request_key - > conversation = conversation - > conv_index ;
// Return the new request key.
* input_request_key = request_key ;
}
}
2015-11-30 18:10:19 +00:00
/* Dissect Common Packet Format */
2003-06-11 09:02:19 +00:00
static void
2011-04-25 01:37:19 +00:00
dissect_cpf ( enip_request_key_t * request_key , int command , tvbuff_t * tvb ,
2016-10-06 17:57:55 +00:00
packet_info * pinfo , proto_tree * tree , proto_tree * dissector_tree ,
proto_item * enip_item , int offset , guint32 ifacehndl )
2003-06-11 09:02:19 +00:00
{
2018-06-11 17:16:31 +00:00
proto_item * count_item ;
proto_tree * count_tree ;
int item_count ;
// The following variables are set in one pass of the loop, and read in a second pass.
2012-04-26 16:47:37 +00:00
enip_conn_val_t * conn_info = NULL ;
2018-06-11 17:16:31 +00:00
gboolean FwdOpenRequest = FALSE ;
2012-04-26 16:47:37 +00:00
gboolean FwdOpenReply = FALSE ;
enum enip_connid_type connid_type = ECIDT_UNKNOWN ;
2016-01-22 19:54:03 +00:00
2018-06-11 17:16:31 +00:00
// Normal "Common Packet Format" configurations. See CIP Volume 2, Section 2-6.4.
// SendRRData (Unconnected):
// Item 1: CDF_NULL
// Item 2: UNCONNECTED_MSG
// SendUnitData (Connected, Class 3):
// Item 1: CONNECTION_BASED
// Item 2: CONNECTION_TRANSPORT
// Item 3 (Optional): SOCK_ADR_INFO_OT/SOCK_ADR_INFO_TO
// Class 0/1 packet:
// Item 1: SEQ_ADDRESS
// Item 2: CONNECTION_TRANSPORT
// Unconnected Message over UDP:
// Item 1: UNCONNECTED_MSG_DTLS
2012-03-02 03:39:16 +00:00
2009-06-26 02:38:23 +00:00
/* Create item count tree */
item_count = tvb_get_letohs ( tvb , offset ) ;
2011-04-25 01:37:19 +00:00
count_item = proto_tree_add_item ( tree , hf_enip_cpf_itemcount , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
count_tree = proto_item_add_subtree ( count_item , ett_count_tree ) ;
2018-06-11 17:16:31 +00:00
offset + = 2 ;
2003-06-11 22:36:18 +00:00
2013-11-21 18:37:26 +00:00
while ( item_count - - )
2009-06-26 02:38:23 +00:00
{
/* Add item type tree to item count tree*/
2018-06-11 17:16:31 +00:00
guint32 item_type_id ;
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 ) ;
proto_tree * item_tree = proto_item_add_subtree ( type_item , ett_type_tree ) ;
offset + = 2 ;
2004-02-04 20:34:53 +00:00
2011-04-25 01:37:19 +00:00
/* Add length field to item type tree */
2018-06-11 17:16:31 +00:00
guint32 item_length ;
proto_tree_add_item_ret_uint ( item_tree , hf_enip_cpf_length , tvb , offset , 2 , ENC_LITTLE_ENDIAN , & item_length ) ;
offset + = 2 ;
2003-06-11 09:02:19 +00:00
2018-06-11 17:16:31 +00:00
// offset now starts at the data field after the Item Length field. The name of this
// field varies depending on the item type.
2013-11-21 18:37:26 +00:00
if ( item_length )
2009-06-26 02:38:23 +00:00
{
2011-10-13 00:00:52 +00:00
/* Add item data field */
2003-06-11 09:02:19 +00:00
2018-06-11 17:16:31 +00:00
switch ( item_type_id )
2011-10-13 00:00:52 +00:00
{
2018-06-11 17:16:31 +00:00
case CONNECTION_BASED : // 1st Item for: Class 3 Connected Messages
conn_info = NULL ;
dissect_item_connected_address ( pinfo , tvb , offset , item_tree , tree , enip_item , request_key , & conn_info ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2018-06-11 17:16:31 +00:00
case UNCONNECTED_MSG_DTLS : // Only item for: Unconnected messages over DTLS
{
2016-01-22 19:54:03 +00:00
ifacehndl = ENIP_CIP_INTERFACE ;
2018-06-11 17:16:31 +00:00
dissect_item_unconnected_message_over_udp ( pinfo , tvb , offset , item_tree , & request_key ) ;
// Skip over the fields already parsed before falling through.
2016-01-22 19:54:03 +00:00
offset + = 10 ;
item_length - = 10 ;
2018-06-11 17:16:31 +00:00
}
2016-01-22 19:54:03 +00:00
2018-06-11 17:16:31 +00:00
/* Intentionally fall through */
2016-01-22 19:54:03 +00:00
2018-06-11 17:16:31 +00:00
case UNCONNECTED_MSG : // 2nd Item for: Unconnected Messages
{
enip_request_info_t * request_info = NULL ;
2009-06-26 02:38:23 +00:00
if ( request_key )
{
request_key - > type = EPDT_UNCONNECTED ;
request_info = enip_match_request ( pinfo , tree , request_key ) ;
}
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
/* Call dissector for interface */
2018-06-11 17:16:31 +00:00
tvbuff_t * next_tvb = tvb_new_subset_length ( tvb , offset , item_length ) ;
2014-05-27 02:58:48 +00:00
p_add_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO , request_info ) ;
2015-06-23 03:53:46 +00:00
if ( tvb_reported_length_remaining ( next_tvb , 0 ) < = 0 | | ! dissector_try_uint ( subdissector_srrd_table , ifacehndl , next_tvb , pinfo , dissector_tree ) )
2009-06-26 02:38:23 +00:00
{
/* Show the undissected payload */
2015-06-23 03:53:46 +00:00
if ( tvb_reported_length_remaining ( tvb , offset ) > 0 )
2016-03-20 00:33:14 +00:00
call_data_dissector ( next_tvb , pinfo , dissector_tree ) ;
2009-06-26 02:38:23 +00:00
}
2003-06-11 09:02:19 +00:00
2011-12-01 06:05:39 +00:00
/* Check if this is a ForwardOpen packet, because special handling is needed
to handle connection conversations */
if ( ( request_info ! = NULL ) & & ( request_info - > cip_info ! = NULL ) & &
2012-03-02 03:39:16 +00:00
( request_info - > cip_info - > connInfo ! = NULL ) & &
2011-12-01 06:05:39 +00:00
( request_key ! = NULL ) & &
2018-02-02 16:47:44 +00:00
( ( ( request_info - > cip_info - > bService & CIP_SC_MASK ) = = SC_CM_FWD_OPEN ) | |
( ( request_info - > cip_info - > bService & CIP_SC_MASK ) = = SC_CM_LARGE_FWD_OPEN ) ) & &
2011-12-01 06:05:39 +00:00
( request_info - > cip_info - > dissector = = dissector_get_uint_handle ( subdissector_class_table , CI_CLS_CM ) ) )
{
if ( request_key - > requesttype = = ENIP_REQUEST_PACKET )
{
2018-06-11 17:16:31 +00:00
FwdOpenRequest = TRUE ;
2011-12-01 06:05:39 +00:00
}
else
{
FwdOpenReply = TRUE ;
}
}
else
{
2014-05-27 02:58:48 +00:00
p_remove_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
2011-12-01 06:05:39 +00:00
}
2009-06-26 02:38:23 +00:00
break ;
2018-06-11 17:16:31 +00:00
}
2003-06-11 09:02:19 +00:00
2018-06-11 17:16:31 +00:00
case CONNECTION_TRANSPORT : // 2nd item for: Connected messages (both Class 0/1 and Class 3)
2018-06-27 22:56:17 +00:00
if ( command = = SEND_UNIT_DATA ) // Class 2/3 over TCP.
2009-06-26 02:38:23 +00:00
{
2018-06-27 22:56:17 +00:00
dissect_cip_class23_data ( pinfo , tvb , offset , tree , item_tree , item_length , request_key , conn_info , dissector_tree ) ;
2009-06-26 02:38:23 +00:00
}
2018-06-27 22:56:17 +00:00
else // No command. Send as CPF items only over UDP.
2009-06-26 02:38:23 +00:00
{
2018-06-15 14:45:01 +00:00
dissect_cip_class01_io ( pinfo , tvb , offset , item_length , conn_info , connid_type , dissector_tree ) ;
2018-06-27 22:56:17 +00:00
}
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case LIST_IDENTITY_RESP :
2018-06-11 17:16:31 +00:00
dissect_item_list_identity ( pinfo , tvb , offset , item_tree ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2017-07-20 15:36:59 +00:00
case LIST_ID_SECURITY :
2018-06-11 17:16:31 +00:00
dissect_item_cip_security_information ( tvb , offset , item_tree ) ;
2017-07-20 15:36:59 +00:00
break ;
2003-06-11 09:02:19 +00:00
2018-06-11 17:16:31 +00:00
case SOCK_ADR_INFO_OT : // Optional 3rd item for: Unconnected Messages
2009-06-26 02:38:23 +00:00
case SOCK_ADR_INFO_TO :
2018-06-11 17:16:31 +00:00
{
gboolean is_fwd_open = ( FwdOpenRequest = = TRUE ) | | ( FwdOpenReply = = TRUE ) ;
dissect_item_sockaddr_info ( pinfo , tvb , offset , item_tree , item_type_id , is_fwd_open ) ;
2009-06-26 02:38:23 +00:00
break ;
2018-06-11 17:16:31 +00:00
}
2009-06-26 02:38:23 +00:00
2018-06-11 17:16:31 +00:00
case SEQ_ADDRESS : // 1st item for: Class 0/1 connected data
conn_info = NULL ;
dissect_item_sequenced_address ( pinfo , tvb , offset , item_tree , tree , & connid_type , & conn_info ) ;
2009-06-26 02:38:23 +00:00
break ;
2004-06-02 06:30:15 +00:00
2009-06-26 02:38:23 +00:00
case LIST_SERVICES_RESP :
2018-06-11 17:16:31 +00:00
dissect_item_list_services_response ( pinfo , tvb , offset , item_tree ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
default :
2018-06-11 17:16:31 +00:00
proto_tree_add_item ( item_tree , hf_enip_cpf_data , tvb , offset , item_length , ENC_NA ) ;
2009-06-26 02:38:23 +00:00
break ;
2013-11-21 18:37:26 +00:00
} /* end of switch ( item type ) */
2009-06-26 02:38:23 +00:00
2013-11-21 18:37:26 +00:00
} /* end of if ( item length ) */
2009-06-26 02:38:23 +00:00
2018-06-11 17:16:31 +00:00
offset + = item_length ;
2013-11-21 18:37:26 +00:00
} /* end of while ( item count ) */
2003-06-11 09:02:19 +00:00
2011-12-01 06:05:39 +00:00
/* See if there is a CIP connection to establish */
if ( FwdOpenReply = = TRUE )
{
2018-06-11 17:16:31 +00:00
enip_request_info_t * request_info = ( enip_request_info_t * ) p_get_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
2011-12-01 06:05:39 +00:00
if ( request_info ! = NULL )
{
enip_open_cip_connection ( pinfo , request_info - > cip_info - > connInfo ) ;
}
2014-05-27 02:58:48 +00:00
p_remove_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
2011-12-01 06:05:39 +00:00
}
2018-06-11 17:16:31 +00:00
else if ( FwdOpenRequest = = TRUE )
2011-12-01 06:05:39 +00:00
{
2014-05-27 02:58:48 +00:00
p_remove_proto_data ( wmem_file_scope ( ) , pinfo , proto_enip , ENIP_REQUEST_INFO ) ;
2011-12-01 06:05:39 +00:00
}
2004-09-23 17:34:35 +00:00
} /* end of dissect_cpf() */
2003-06-11 09:02:19 +00:00
2013-03-14 18:58:42 +00:00
static enum enip_packet_type
2003-06-11 09:02:19 +00:00
classify_packet ( packet_info * pinfo )
{
2009-06-26 02:38:23 +00:00
/* see if nature of packets can be derived from src/dst ports */
/* if so, return as found */
2016-01-28 21:34:14 +00:00
if ( ( ( ENIP_ENCAP_PORT = = pinfo - > srcport & & ENIP_ENCAP_PORT ! = pinfo - > destport ) ) | |
( ( ENIP_SECURE_PORT = = pinfo - > srcport & & ENIP_SECURE_PORT ! = pinfo - > destport ) ) )
{
return ENIP_RESPONSE_PACKET ;
}
else if ( ( ( ENIP_ENCAP_PORT ! = pinfo - > srcport & & ENIP_ENCAP_PORT = = pinfo - > destport ) ) | |
( ( ENIP_SECURE_PORT ! = pinfo - > srcport & & ENIP_SECURE_PORT = = pinfo - > destport ) ) )
{
return ENIP_REQUEST_PACKET ;
}
else
{
return ENIP_CANNOT_CLASSIFY ;
}
2003-06-11 09:02:19 +00:00
}
2004-01-27 04:43:35 +00:00
static guint
2015-01-25 19:30:13 +00:00
get_enip_pdu_len ( packet_info * pinfo _U_ , tvbuff_t * tvb , int offset , void * data _U_ )
2004-01-27 04:43:35 +00:00
{
guint16 plen ;
/*
* Get the length of the data from the encapsulation header .
*/
plen = tvb_get_letohs ( tvb , offset + 2 ) ;
/*
* That length doesn ' t include the encapsulation header itself ;
* add that in .
*/
return plen + 24 ;
}
2003-06-11 09:02:19 +00:00
/* Code to actually dissect the packets */
2013-11-09 17:46:28 +00:00
static int
dissect_enip_pdu ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2003-06-11 09:02:19 +00:00
{
2013-03-14 18:58:42 +00:00
enum enip_packet_type packet_type ;
2012-04-26 16:47:37 +00:00
guint16 encap_cmd , encap_data_length ;
const char * pkt_type_str = " " ;
guint32 ifacehndl ;
enip_request_key_t request_key ;
conversation_t * conversation ;
2003-06-11 09:02:19 +00:00
/* Set up structures needed to add the protocol subtree and manage it */
2016-10-06 17:57:55 +00:00
proto_item * ti = NULL ;
2009-06-26 02:38:23 +00:00
proto_tree * enip_tree , * header_tree = NULL , * csftree ;
2003-06-11 09:02:19 +00:00
2003-10-01 21:51:59 +00:00
/* Make entries in Protocol column and Info column on summary display */
2009-08-09 06:26:46 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " ENIP " ) ;
2009-08-09 07:36:13 +00:00
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2003-10-01 21:51:59 +00:00
2004-01-27 04:43:35 +00:00
encap_cmd = tvb_get_letohs ( tvb , 0 ) ;
2009-06-26 02:38:23 +00:00
packet_type = classify_packet ( pinfo ) ;
2004-02-04 20:34:53 +00:00
2012-11-13 13:14:48 +00:00
switch ( packet_type )
2003-10-01 21:51:59 +00:00
{
2012-11-13 13:14:48 +00:00
case ENIP_REQUEST_PACKET :
2013-11-21 18:37:26 +00:00
pkt_type_str = " Req " ;
2012-11-13 13:14:48 +00:00
break ;
2003-06-11 09:02:19 +00:00
2012-11-13 13:14:48 +00:00
case ENIP_RESPONSE_PACKET :
2013-11-21 18:37:26 +00:00
pkt_type_str = " Rsp " ;
2012-11-13 13:14:48 +00:00
break ;
2004-02-04 20:34:53 +00:00
2012-11-13 13:14:48 +00:00
case ENIP_CANNOT_CLASSIFY :
default :
2013-11-21 18:37:26 +00:00
pkt_type_str = " ? " ;
2012-11-13 13:14:48 +00:00
}
2003-06-11 09:02:19 +00:00
2012-11-13 13:14:48 +00:00
/* Add encapsulation command to info column */
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " | " , " %s (%s) " ,
2015-11-30 18:10:19 +00:00
val_to_str ( encap_cmd , encap_cmd_vals , " Unknown Command (0x%04x) " ) ,
2012-11-13 13:14:48 +00:00
pkt_type_str ) ;
2009-06-26 02:38:23 +00:00
/*
* We need to track some state for this protocol on a per conversation
* basis so we can do neat things like request / response tracking
*/
2010-05-13 18:28:34 +00:00
conversation = find_or_create_conversation ( pinfo ) ;
2009-06-26 02:38:23 +00:00
/*
2010-05-13 18:28:34 +00:00
* Attach that information to the conversation , and add
2009-06-26 02:38:23 +00:00
* it to the list of information structures later before dissection .
*/
memset ( & request_key , 0 , sizeof ( enip_request_key_t ) ) ;
2012-08-09 16:47:15 +00:00
request_key . requesttype = packet_type ;
request_key . type = EPDT_UNKNOWN ;
2009-06-26 02:38:23 +00:00
request_key . session_handle = tvb_get_letohl ( tvb , 4 ) ;
request_key . sender_context = tvb_get_letoh64 ( tvb , 12 ) ;
2016-06-23 15:51:41 +00:00
request_key . conversation = conversation - > conv_index ;
2009-06-26 02:38:23 +00:00
2018-05-18 14:08:08 +00:00
/* create display subtree for the protocol */
ti = proto_tree_add_item ( tree , proto_enip , tvb , 0 , - 1 , ENC_NA ) ;
2003-06-11 09:02:19 +00:00
2018-05-18 14:08:08 +00:00
enip_tree = proto_item_add_subtree ( ti , ett_enip ) ;
2003-06-11 09:02:19 +00:00
2018-05-18 14:08:08 +00:00
/* Add encapsulation header tree */
header_tree = proto_tree_add_subtree ( enip_tree , tvb , 0 , 24 , ett_enip , NULL , " Encapsulation Header " ) ;
2003-06-11 09:02:19 +00:00
2018-05-18 14:08:08 +00:00
/* Add EtherNet/IP encapsulation header */
proto_tree_add_item ( header_tree , hf_enip_command , tvb , 0 , 2 , ENC_LITTLE_ENDIAN ) ;
2003-06-11 09:02:19 +00:00
2018-05-18 14:08:08 +00:00
encap_data_length = tvb_get_letohs ( tvb , 2 ) ;
proto_tree_add_item ( header_tree , hf_enip_length , tvb , 2 , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_enip_session , tvb , 4 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_enip_status , tvb , 8 , 4 , ENC_LITTLE_ENDIAN ) ;
if ( ( encap_cmd = = LIST_IDENTITY ) & &
/* Length of 0 probably indicates a request */
( ( encap_data_length = = 0 ) | | ( packet_type = = ENIP_REQUEST_PACKET ) ) )
{
proto_tree_add_item ( header_tree , hf_enip_listid_delay , tvb , 12 , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( header_tree , hf_enip_sendercontex , tvb , 14 , 6 , ENC_NA ) ;
}
else
{
proto_tree_add_item ( header_tree , hf_enip_sendercontex , tvb , 12 , 8 , ENC_NA ) ;
}
proto_tree_add_item ( header_tree , hf_enip_options , tvb , 20 , 4 , ENC_LITTLE_ENDIAN ) ;
2003-06-11 09:02:19 +00:00
2018-05-18 14:08:08 +00:00
/* Append session and command to the protocol tree */
proto_item_append_text ( ti , " , Session: 0x%08X, %s " , tvb_get_letohl ( tvb , 4 ) ,
val_to_str ( encap_cmd , encap_cmd_vals , " Unknown Command (0x%04x) " ) ) ;
2004-02-04 20:34:53 +00:00
2012-08-09 16:47:15 +00:00
/*
* * For some commands we want to add some info to the info column
*/
2013-11-21 18:37:26 +00:00
switch ( encap_cmd )
2012-08-09 16:47:15 +00:00
{
2013-11-21 18:37:26 +00:00
case REGISTER_SESSION :
case UNREGISTER_SESSION :
col_append_fstr ( pinfo - > cinfo , COL_INFO , " , Session: 0x%08X " ,
tvb_get_letohl ( tvb , 4 ) ) ;
break ;
2012-11-13 13:14:48 +00:00
}
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
/* Command specific data - create tree */
2013-11-21 18:37:26 +00:00
if ( encap_data_length )
2009-06-26 02:38:23 +00:00
{
2015-11-30 18:10:19 +00:00
/* The packet have some command specific data, build a sub tree for it */
2003-06-11 09:02:19 +00:00
2014-06-26 02:59:50 +00:00
csftree = proto_tree_add_subtree ( enip_tree , tvb , 24 , encap_data_length ,
ett_command_tree , NULL , " Command Specific Data " ) ;
2003-06-11 09:02:19 +00:00
2013-11-21 18:37:26 +00:00
switch ( encap_cmd )
2009-06-26 02:38:23 +00:00
{
case NOP :
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case LIST_SERVICES :
2016-10-06 17:57:55 +00:00
dissect_cpf ( & request_key , encap_cmd , tvb , pinfo , csftree , tree , NULL , 24 , 0 ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case LIST_IDENTITY :
2016-10-06 17:57:55 +00:00
dissect_cpf ( & request_key , encap_cmd , tvb , pinfo , csftree , tree , NULL , 24 , 0 ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case LIST_INTERFACES :
2016-10-06 17:57:55 +00:00
dissect_cpf ( & request_key , encap_cmd , tvb , pinfo , csftree , tree , NULL , 24 , 0 ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case REGISTER_SESSION :
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( csftree , hf_enip_rs_version , tvb , 24 , 2 , ENC_LITTLE_ENDIAN ) ;
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( csftree , hf_enip_rs_optionflags , tvb , 26 , 2 , ENC_LITTLE_ENDIAN ) ;
2009-06-26 02:38:23 +00:00
break ;
2004-09-23 17:34:35 +00:00
2009-06-26 02:38:23 +00:00
case UNREGISTER_SESSION :
break ;
2004-09-23 17:34:35 +00:00
2009-06-26 02:38:23 +00:00
case SEND_RR_DATA :
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( csftree , hf_enip_srrd_ifacehnd , tvb , 24 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( csftree , hf_enip_timeout , tvb , 28 , 2 , ENC_LITTLE_ENDIAN ) ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
ifacehndl = tvb_get_letohl ( tvb , 24 ) ;
2016-10-06 17:57:55 +00:00
dissect_cpf ( & request_key , encap_cmd , tvb , pinfo , csftree , tree , NULL , 30 , ifacehndl ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case SEND_UNIT_DATA :
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( csftree , hf_enip_sud_ifacehnd , tvb , 24 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( csftree , hf_enip_timeout , tvb , 28 , 2 , ENC_LITTLE_ENDIAN ) ;
2009-06-19 05:45:40 +00:00
2009-06-26 02:38:23 +00:00
ifacehndl = tvb_get_letohl ( tvb , 24 ) ;
2016-10-06 17:57:55 +00:00
dissect_cpf ( & request_key , encap_cmd , tvb , pinfo , csftree , tree , ti , 30 , ifacehndl ) ;
2009-06-26 02:38:23 +00:00
break ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
case INDICATE_STATUS :
case CANCEL :
default :
/* Can not decode - Just show the data */
2011-10-13 00:00:52 +00:00
proto_tree_add_item ( header_tree , hf_enip_encap_data , tvb , 24 , encap_data_length , ENC_NA ) ;
2009-06-26 02:38:23 +00:00
break ;
2009-06-19 06:15:52 +00:00
2013-11-21 18:37:26 +00:00
} /* end of switch () */
2003-06-11 09:02:19 +00:00
2013-11-21 18:37:26 +00:00
} /* end of if ( encapsulated data ) */
2013-11-09 17:46:28 +00:00
2016-02-01 03:36:58 +00:00
col_set_fence ( pinfo - > cinfo , COL_INFO ) ;
2015-06-23 03:53:46 +00:00
return tvb_captured_length ( tvb ) ;
2004-09-23 17:34:35 +00:00
} /* end of dissect_enip_pdu() */
2004-01-27 04:43:35 +00:00
static int
2013-11-09 17:46:28 +00:00
dissect_enip_udp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
2004-01-27 04:43:35 +00:00
{
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
/* An ENIP packet is at least 4 bytes long. */
if ( tvb_captured_length ( tvb ) < 4 )
2004-01-27 04:43:35 +00:00
return 0 ;
2013-11-09 17:46:28 +00:00
return dissect_enip_pdu ( tvb , pinfo , tree , data ) ;
2004-01-27 04:43:35 +00:00
}
static int
2013-11-09 17:46:28 +00:00
dissect_enip_tcp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data )
2004-01-27 04:43:35 +00:00
{
2018-02-15 19:11:06 +00:00
// TCP connections for EtherNet/IP are typically open for extended periods of time.
// This means that mostly likely, for real world traffic, a capture initiated for
// EtherNet/IP traffic will start in the middle of a TCP connection. This check
// ignores one byte TCP payloads because it is far more likely that a one byte TCP
// payload is a TCP keep alive message, than a client actually sending real EtherNet/IP
// messages in one byte chunks.
if ( tvb_captured_length ( tvb ) < 2 )
return 0 ;
2013-11-09 17:46:28 +00:00
tcp_dissect_pdus ( tvb , pinfo , tree , enip_desegment , 4 , get_enip_pdu_len , dissect_enip_pdu , data ) ;
2015-06-23 03:53:46 +00:00
return tvb_captured_length ( tvb ) ;
2004-01-27 04:43:35 +00:00
}
2003-06-11 09:02:19 +00:00
/* Code to actually dissect the io packets*/
2015-11-15 13:00:10 +00:00
static int
2018-07-05 14:22:59 +00:00
dissect_cipio ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2003-06-11 09:02:19 +00:00
{
/* Set up structures needed to add the protocol subtree and manage it */
2009-06-26 02:38:23 +00:00
proto_item * ti ;
proto_tree * enip_tree ;
2009-06-19 06:15:52 +00:00
2003-06-11 09:02:19 +00:00
/* Make entries in Protocol column and Info column on summary display */
2018-06-15 14:45:01 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " CIP I/O " ) ;
2003-06-11 09:02:19 +00:00
2012-08-09 16:47:15 +00:00
/* create display subtree for the protocol */
ti = proto_tree_add_item ( tree , proto_enip , tvb , 0 , - 1 , ENC_NA ) ;
2003-08-16 01:53:41 +00:00
2012-08-09 16:47:15 +00:00
enip_tree = proto_item_add_subtree ( ti , ett_enip ) ;
2016-10-06 17:57:55 +00:00
dissect_cpf ( NULL , 0xFFFF , tvb , pinfo , enip_tree , tree , NULL , 0 , 0 ) ;
2008-10-23 21:01:04 +00:00
2015-11-15 13:00:10 +00:00
return tvb_captured_length ( tvb ) ;
2003-08-16 01:53:41 +00:00
} /* end of dissect_enipio() */
2003-06-11 09:02:19 +00:00
2009-07-09 20:44:28 +00:00
static gboolean
2012-09-10 21:40:21 +00:00
dissect_dlr ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
2009-07-09 20:44:28 +00:00
{
proto_item * ti ;
2014-06-26 02:59:50 +00:00
proto_tree * dlr_tree ;
2009-07-09 20:44:28 +00:00
guint8 dlr_subtype ;
guint8 dlr_protover ;
guint8 dlr_frametype ;
/* Make entries in Protocol column and Info column on summary display */
2009-08-09 06:47:24 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " DLR " ) ;
2009-07-09 20:44:28 +00:00
2009-08-09 07:36:13 +00:00
col_clear ( pinfo - > cinfo , COL_INFO ) ;
2009-07-09 20:44:28 +00:00
2014-06-26 02:59:50 +00:00
/* Create display subtree for the protocol */
ti = proto_tree_add_item ( tree , proto_dlr , tvb , 0 , - 1 , ENC_NA ) ;
dlr_tree = proto_item_add_subtree ( ti , ett_dlr ) ;
2009-07-09 20:44:28 +00:00
/* Get values for the Common Frame Header Format */
dlr_subtype = tvb_get_guint8 ( tvb , DLR_CFH_SUB_TYPE ) ;
dlr_protover = tvb_get_guint8 ( tvb , DLR_CFH_PROTO_VERSION ) ;
/* Dissect the Common Frame Header Format */
2012-08-09 16:47:15 +00:00
proto_tree_add_uint ( dlr_tree , hf_dlr_ringsubtype , tvb , DLR_CFH_SUB_TYPE , 1 , dlr_subtype ) ;
2009-07-09 20:44:28 +00:00
proto_tree_add_uint ( dlr_tree , hf_dlr_ringprotoversion , tvb , DLR_CFH_PROTO_VERSION , 1 , dlr_protover ) ;
/* Get values for the DLR Message Payload Fields */
dlr_frametype = tvb_get_guint8 ( tvb , DLR_MPF_FRAME_TYPE ) ;
/* Dissect the DLR Message Payload Fields */
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_frametype , tvb , DLR_MPF_FRAME_TYPE , 1 , ENC_BIG_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_sourceport , tvb , DLR_MPF_SOURCE_PORT , 1 , ENC_BIG_ENDIAN ) ;
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_sourceip , tvb , DLR_MPF_SOURCE_IP , 4 , ENC_BIG_ENDIAN ) ;
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_sequenceid , tvb , DLR_MPF_SEQUENCE_ID , 4 , ENC_BIG_ENDIAN ) ;
2009-07-09 20:44:28 +00:00
/* Add frame type to col info */
2012-11-29 20:15:37 +00:00
col_add_fstr ( pinfo - > cinfo , COL_INFO , " %s " ,
2012-11-13 13:14:48 +00:00
val_to_str ( dlr_frametype , dlr_frame_type_vals , " Unknown (0x%04x) " ) ) ;
2009-07-09 20:44:28 +00:00
2013-11-21 18:37:26 +00:00
if ( dlr_frametype = = DLR_FT_BEACON )
2009-07-09 20:44:28 +00:00
{
/* Beacon */
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_ringstate , tvb , DLR_BE_RING_STATE , 1 , ENC_BIG_ENDIAN ) ;
2011-10-26 04:55:21 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_supervisorprecedence , tvb , DLR_BE_SUPERVISOR_PRECEDENCE , 1 , ENC_BIG_ENDIAN ) ;
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_beaconinterval , tvb , DLR_BE_BEACON_INTERVAL , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_beacontimeout , tvb , DLR_BE_BEACON_TIMEOUT , 4 , ENC_BIG_ENDIAN ) ;
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_beaconreserved , tvb , DLR_BE_RESERVED , 20 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_NEIGHBOR_REQ )
2009-07-09 20:44:28 +00:00
{
/* Neighbor_Check_Request */
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_nreqreserved , tvb , DLR_NREQ_RESERVED , 30 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_NEIGHBOR_RES )
2009-07-09 20:44:28 +00:00
{
/* Neighbor_Check_Response */
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_nressourceport , tvb , DLR_NRES_SOURCE_PORT , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_nresreserved , tvb , DLR_NRES_RESERVED , 29 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_LINK_STAT )
2009-07-09 20:44:28 +00:00
{
/* Link_Status/Neighbor_Status */
2018-05-18 14:08:08 +00:00
static const int * bits [ ] = {
& hf_dlr_lnknbrstatus_port1 ,
& hf_dlr_lnknbrstatus_port2 ,
& hf_dlr_lnknbrstatus_reserved ,
& hf_dlr_lnknbrstatus_frame_type ,
NULL
} ;
proto_tree_add_bitmask ( dlr_tree , tvb , DLR_LNS_SOURCE_PORT , hf_dlr_lnknbrstatus , ett_dlr_lnknbrstatus_flags , bits , ENC_LITTLE_ENDIAN ) ;
2013-04-04 14:34:26 +00:00
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_lnknbrreserved , tvb , DLR_LNS_RESERVED , 29 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_LOCATE_FLT )
2009-07-09 20:44:28 +00:00
{
/* Locate_Fault */
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_lfreserved , tvb , DLR_LF_RESERVED , 30 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_ANNOUNCE )
2009-07-09 20:44:28 +00:00
{
/* Announce */
2012-08-09 16:47:15 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_ringstate , tvb , DLR_AN_RING_STATE , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_anreserved , tvb , DLR_AN_RESERVED , 29 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_SIGN_ON )
2009-07-09 20:44:28 +00:00
{
guint16 nCnt ;
guint16 nNumNodes ;
guint16 nOffset ;
/* Sign_On */
nNumNodes = tvb_get_ntohs ( tvb , DLR_SO_NUM_NODES ) ;
proto_tree_add_uint ( dlr_tree , hf_dlr_sonumnodes , tvb , DLR_SO_NUM_NODES , 2 , nNumNodes ) ;
/* Add each node in the list */
for ( nCnt = 0 , nOffset = DLR_SO_NODE_1_MAC ; nCnt < nNumNodes ; nCnt + + )
{
2011-10-20 14:07:54 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_somac , tvb , nOffset , 6 , ENC_NA ) ;
2009-07-09 20:44:28 +00:00
nOffset + = 6 ;
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_soip , tvb , nOffset , 4 , ENC_BIG_ENDIAN ) ;
2009-07-09 20:44:28 +00:00
nOffset + = 4 ;
}
2013-11-21 18:37:26 +00:00
if ( nOffset < 42 )
2009-07-09 20:44:28 +00:00
{
2011-04-25 01:37:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_soreserved , tvb , nOffset , 42 - nOffset , ENC_NA ) ;
2012-01-04 17:42:10 +00:00
/* nOffset += (42 - nOffset); */
2009-07-09 20:44:28 +00:00
}
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_ADVERTISE )
2013-04-04 14:34:26 +00:00
{
/* Advertise */
proto_tree_add_item ( dlr_tree , hf_dlr_advgatewaystate , tvb , DLR_ADV_GATEWAY_STATE , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_advgatewayprecedence , tvb , DLR_ADV_GATEWAY_PRECEDENCE , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_advadvertiseinterval , tvb , DLR_ADV_ADVERTISE_INTERVAL , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_advadvertisetimeout , tvb , DLR_ADV_ADVERTISE_TIMEOUT , 4 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_advlearningupdateenable , tvb , DLR_ADV_LEARNING_UPDATE_ENABLE , 1 , ENC_BIG_ENDIAN ) ;
2013-09-12 20:34:19 +00:00
proto_tree_add_item ( dlr_tree , hf_dlr_advreserved , tvb , DLR_ADV_RESERVED , 19 , ENC_NA ) ;
2013-04-04 14:34:26 +00:00
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_FLUSH_TABLES )
2013-04-04 14:34:26 +00:00
{
proto_tree_add_item ( dlr_tree , hf_dlr_flushlearningupdateenable , tvb , DLR_FLUSH_LEARNING_UPDATE_ENABLE , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( dlr_tree , hf_dlr_flushreserved , tvb , DLR_FLUSH_RESERVED , 29 , ENC_NA ) ;
}
2013-11-21 18:37:26 +00:00
else if ( dlr_frametype = = DLR_FT_LEARNING_UPDATE )
2013-04-04 14:34:26 +00:00
{
proto_tree_add_item ( dlr_tree , hf_dlr_learnreserved , tvb , DLR_LEARN_RESERVED , 34 , ENC_NA ) ;
}
2009-07-09 20:44:28 +00:00
else
{
/* Unknown Frame type */
}
2015-06-23 03:53:46 +00:00
return tvb_captured_length ( tvb ) ;
2009-07-09 20:44:28 +00:00
} /* end of dissect_dlr() */
2018-07-05 14:22:59 +00:00
static int dissect_cip_class1 ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
enip_conn_val_t conn_info ;
conn_info . TransportClass_trigger = 1 ;
cip_io_data_input io_data_input ;
io_data_input . conn_info = & conn_info ;
io_data_input . connid_type = ECIDT_UNKNOWN ;
return dissect_cip_io_generic ( tvb , pinfo , tree , & io_data_input ) ;
}
2009-07-09 20:44:28 +00:00
2006-05-21 04:49:01 +00:00
/* Register the protocol with Wireshark */
2003-06-11 09:02:19 +00:00
/* this format is require because a script is used to build the C function
that calls all the protocol registration .
*/
void
2004-09-23 17:34:35 +00:00
proto_register_enip ( void )
2003-06-11 09:02:19 +00:00
{
2004-09-23 17:34:35 +00:00
/* Setup list of header fields */
2009-06-26 02:38:23 +00:00
static hf_register_info hf [ ] = {
2012-04-26 16:47:37 +00:00
{ & hf_enip_command ,
{ " Command " , " enip.command " ,
FT_UINT16 , BASE_HEX , VALS ( encap_cmd_vals ) , 0 ,
" Encapsulation command " , HFILL } } ,
{ & hf_enip_length ,
{ " Length " , " enip.length " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Encapsulation length " , HFILL } } ,
{ & hf_enip_session ,
{ " Session Handle " , " enip.session " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" Session identification " , HFILL } } ,
{ & hf_enip_status ,
{ " Status " , " enip.status " ,
FT_UINT32 , BASE_HEX , VALS ( encap_status_vals ) , 0 ,
" Status code " , HFILL } } ,
{ & hf_enip_sendercontex ,
{ " Sender Context " , " enip.context " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
2012-08-09 16:47:15 +00:00
" Information pertinent to the sender " , HFILL } } ,
2012-04-26 16:47:37 +00:00
2012-11-13 13:14:48 +00:00
{ & hf_enip_listid_delay ,
{ " Max Response Delay " , " enip.listid_delay " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Maximum random delay allowed by target " , HFILL } } ,
2012-04-26 16:47:37 +00:00
{ & hf_enip_options ,
{ " Options " , " enip.options " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" Options flags " , HFILL } } ,
{ & hf_enip_encapver ,
{ " Encapsulation Version " , " enip.encapver " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_enip_sinfamily ,
{ " sin_family " , " enip.sinfamily " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Socket Address.Sin Family " , HFILL } } ,
{ & hf_enip_sinport ,
{ " sin_port " , " enip.sinport " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Socket Address.Sin Port " , HFILL } } ,
{ & hf_enip_sinaddr ,
{ " sin_addr " , " enip.sinaddr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
" Socket Address.Sin Addr " , HFILL } } ,
{ & hf_enip_sinzero ,
{ " sin_zero " , " enip.sinzero " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Socket Address.Sin Zero " , HFILL } } ,
{ & hf_enip_timeout ,
{ " Timeout " , " enip.timeout " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Encapsulation Timeout " , HFILL } } ,
{ & hf_enip_encap_data ,
{ " Encap Data " , " enip.encap_data " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Encapsulation Data " , HFILL } } ,
2011-04-25 01:37:19 +00:00
/* List Services Reply */
2012-04-26 16:47:37 +00:00
{ & hf_enip_lsr_capaflags ,
{ " Capability Flags " , " enip.lsr.capaflags " ,
FT_UINT16 , BASE_HEX , NULL , 0 ,
" ListServices Reply: Capability Flags " , HFILL } } ,
{ & hf_enip_lsr_tcp ,
{ " Supports CIP Encapsulation via TCP " , " enip.lsr.capaflags.tcp " ,
FT_BOOLEAN , 16 , TFS ( & tfs_true_false ) , 0x0020 ,
" ListServices Reply: Supports CIP Encapsulation via TCP " , HFILL } } ,
{ & hf_enip_lsr_udp ,
{ " Supports CIP Class 0 or 1 via UDP " , " enip.lsr.capaflags.udp " ,
FT_BOOLEAN , 16 , TFS ( & tfs_true_false ) , 0x0100 ,
" ListServices Reply: Supports CIP Class 0 or 1 via UDP " , HFILL } } ,
{ & hf_enip_lsr_servicename ,
{ " Name of Service " , " enip.lsr.servicename " ,
FT_STRING , BASE_NONE , NULL , 0 ,
" ListServices Reply: Name of Service " , HFILL } } ,
2011-04-25 01:37:19 +00:00
/* Register Session */
2012-04-26 16:47:37 +00:00
{ & hf_enip_rs_version ,
{ " Protocol Version " , " enip.rs.version " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Register Session: Protocol Version " , HFILL } } ,
{ & hf_enip_rs_optionflags ,
{ " Option Flags " , " enip.rs.flags " ,
FT_UINT16 , BASE_HEX , NULL , 0 ,
" Register Session: Option Flags " , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* Send Request/Reply Data */
2012-04-26 16:47:37 +00:00
{ & hf_enip_srrd_ifacehnd ,
{ " Interface Handle " , " enip.srrd.iface " ,
FT_UINT32 , BASE_HEX , VALS ( enip_interface_handle_vals ) , 0 ,
" SendRRData: Interface handle " , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* Send Unit Data */
2012-04-26 16:47:37 +00:00
{ & hf_enip_sud_ifacehnd ,
{ " Interface Handle " , " enip.sud.iface " ,
FT_UINT32 , BASE_HEX , VALS ( enip_interface_handle_vals ) , 0 ,
" SendUnitData: Interface handle " , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* List identity reply */
2012-04-26 16:47:37 +00:00
{ & hf_enip_lir_vendor ,
{ " Vendor ID " , " enip.lir.vendor " ,
FT_UINT16 , BASE_HEX | BASE_EXT_STRING , & cip_vendor_vals_ext , 0 ,
" ListIdentity Reply: Vendor ID " , HFILL } } ,
{ & hf_enip_lir_devtype ,
{ " Device Type " , " enip.lir.devtype " ,
FT_UINT16 , BASE_DEC | BASE_EXT_STRING , & cip_devtype_vals_ext , 0 ,
" ListIdentity Reply: Device Type " , HFILL } } ,
{ & hf_enip_lir_prodcode ,
{ " Product Code " , " enip.lir.prodcode " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" ListIdentity Reply: Product Code " , HFILL } } ,
{ & hf_enip_lir_revision ,
{ " Revision " , " enip.lir.revision " ,
2015-02-16 01:58:12 +00:00
FT_UINT16 , BASE_CUSTOM , CF_FUNC ( enip_fmt_lir_revision ) , 0 ,
2012-04-26 16:47:37 +00:00
" ListIdentity Reply: Revision " , HFILL } } ,
{ & hf_enip_lir_status ,
{ " Status " , " enip.lir.status " ,
FT_UINT16 , BASE_HEX , NULL , 0 ,
" ListIdentity Reply: Status " , HFILL } } ,
{ & hf_enip_lir_serial ,
{ " Serial Number " , " enip.lir.serial " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" ListIdentity Reply: Serial Number " , HFILL } } ,
{ & hf_enip_lir_namelen ,
{ " Product Name Length " , " enip.lir.namelen " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
" ListIdentity Reply: Product Name Length " , HFILL } } ,
{ & hf_enip_lir_name ,
{ " Product Name " , " enip.lir.name " ,
FT_STRING , BASE_NONE , NULL , 0 ,
" ListIdentity Reply: Product Name " , HFILL } } ,
{ & hf_enip_lir_state ,
{ " State " , " enip.lir.state " ,
FT_UINT8 , BASE_HEX , NULL , 0 ,
" ListIdentity Reply: State " , HFILL } } ,
2017-07-20 15:36:59 +00:00
{ & hf_enip_security_profiles ,
{ " Security Profiles " , " enip.security_profiles " ,
FT_UINT16 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_enip_security_profiles_eip_integrity ,
{ " EtherNet/IP Integrity Profile " , " enip.security_profiles.eip_integrity " ,
FT_BOOLEAN , 16 , TFS ( & tfs_supported_not_supported ) , 0x0001 ,
NULL , HFILL } } ,
{ & hf_enip_security_profiles_eip_confidentiality ,
{ " EtherNet/IP Confidentiality Profile " , " enip.security_profiles.eip_confidentiality " ,
FT_BOOLEAN , 16 , TFS ( & tfs_supported_not_supported ) , 0x0002 ,
NULL , HFILL } } ,
{ & hf_enip_security_profiles_cip_authorization ,
{ " CIP Authorization Profile " , " enip.security_profiles.cip_authorization " ,
FT_BOOLEAN , 16 , TFS ( & tfs_supported_not_supported ) , 0x0004 ,
NULL , HFILL } } ,
{ & hf_enip_security_profiles_cip_integrity ,
{ " CIP Integrity Profile " , " enip.security_profiles.cip_integrity " ,
FT_BOOLEAN , 16 , TFS ( & tfs_supported_not_supported ) , 0x0008 ,
NULL , HFILL } } ,
{ & hf_enip_security_profiles_reserved ,
{ " Reserved " , " enip.security_profiles.reserved " ,
FT_UINT16 , BASE_HEX , NULL , 0xFFF0 ,
NULL , HFILL } } ,
{ & hf_enip_cip_security_state ,
{ " CIP Security State " , " enip.cip_security_state " ,
FT_UINT8 , BASE_DEC , VALS ( cip_security_state_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_enip_eip_security_state ,
{ " EIP Security State " , " enip.eip_security_state " ,
FT_UINT8 , BASE_DEC , VALS ( eip_security_state_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags ,
{ " IANA Port State " , " enip.iana_port_state_flags " ,
FT_UINT8 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_tcp_44818 ,
{ " 44818/tcp " , " enip.security_profiles.iana_port_state_flags.tcp_44818 " ,
FT_BOOLEAN , 8 , TFS ( & tfs_open_closed ) , 0x01 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_udp_44818 ,
{ " 44818/udp " , " enip.security_profiles.iana_port_state_flags.udp_44818 " ,
FT_BOOLEAN , 8 , TFS ( & tfs_open_closed ) , 0x02 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_udp_2222 ,
{ " 2222/udp " , " enip.security_profiles.iana_port_state_flags.udp_2222 " ,
FT_BOOLEAN , 8 , TFS ( & tfs_open_closed ) , 0x04 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_tcp_2221 ,
{ " 2221/tcp " , " enip.security_profiles.iana_port_state_flags.tcp_2221 " ,
FT_BOOLEAN , 8 , TFS ( & tfs_open_closed ) , 0x08 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_udp_2221 ,
{ " 2221/udp " , " enip.security_profiles.iana_port_state_flags.udp_2221 " ,
FT_BOOLEAN , 8 , TFS ( & tfs_open_closed ) , 0x10 ,
NULL , HFILL } } ,
{ & hf_enip_iana_port_state_flags_reserved ,
{ " Reserved " , " enip.iana_port_state_flags.reserved " ,
FT_UINT8 , BASE_HEX , NULL , 0xE0 ,
NULL , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* Common Packet Format */
2012-04-26 16:47:37 +00:00
{ & hf_enip_cpf_itemcount ,
{ " Item Count " , " enip.cpf.itemcount " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Common Packet Format: Item Count " , HFILL } } ,
{ & hf_enip_cpf_typeid ,
{ " Type ID " , " enip.cpf.typeid " ,
FT_UINT16 , BASE_HEX , VALS ( cdf_type_vals ) , 0 ,
" Common Packet Format: Type of encapsulated item " , HFILL } } ,
{ & hf_enip_cpf_length ,
{ " Length " , " enip.cpf.length " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Common Packet Format: Length " , HFILL } } ,
2011-04-25 01:37:19 +00:00
/* Connected Data Item */
2018-06-15 14:45:01 +00:00
{ & hf_cip_sequence_count ,
{ " CIP Sequence Count " , " cip.seq " ,
2016-12-05 12:43:03 +00:00
FT_UINT16 , BASE_DEC , NULL , 0 ,
2018-06-15 14:45:01 +00:00
NULL , HFILL } } ,
2012-04-26 16:47:37 +00:00
2011-04-25 01:37:19 +00:00
/* Connection Address Item */
2012-04-26 16:47:37 +00:00
{ & hf_enip_cpf_cai_connid ,
{ " Connection ID " , " enip.cpf.cai.connid " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" Common Packet Format: Connection Address Item, Connection Identifier " , HFILL } } ,
2016-01-22 19:54:03 +00:00
{ & hf_enip_cpf_ucmm_request ,
{ " Request/Response " , " enip.cpf.ucmm.request " ,
FT_UINT16 , BASE_DEC , VALS ( cip_sc_rr ) , 0x8000 ,
" Common Packet Format: UCMM Request/Response " , HFILL } } ,
{ & hf_enip_cpf_ucmm_msg_type ,
{ " Unconn Msg Type " , " enip.cpf.ucmm.msg_type " ,
FT_UINT16 , BASE_DEC , VALS ( unconn_msg_type_vals ) , 0x7FFF ,
" Common Packet Format: UCMM Transaction ID " , HFILL } } ,
{ & hf_enip_cpf_ucmm_trans_id ,
{ " Transaction ID " , " enip.cpf.ucmm.trans_id " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" Common Packet Format: UCMM Transaction ID " , HFILL } } ,
{ & hf_enip_cpf_ucmm_status ,
{ " UCMM Status " , " enip.cpf.ucmm.status " ,
FT_UINT32 , BASE_HEX , VALS ( encap_status_vals ) , 0 ,
" Common Packet Format: UCMM Status " , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* Sequenced Address Type */
2012-04-26 16:47:37 +00:00
{ & hf_enip_cpf_sai_connid ,
{ " Connection ID " , " enip.cpf.sai.connid " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
" Common Packet Format: Sequenced Address Item, Connection Identifier " , HFILL } } ,
{ & hf_enip_cpf_sai_seqnum ,
2016-12-05 12:43:03 +00:00
{ " Encapsulation Sequence Number " , " enip.cpf.sai.seq " ,
2012-04-26 16:47:37 +00:00
FT_UINT32 , BASE_DEC , NULL , 0 ,
" Common Packet Format: Sequenced Address Item, Sequence Number " , HFILL } } ,
{ & hf_enip_cpf_data ,
{ " Data " , " enip.cpf.data " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Common Packet Format: Unknown Data " , HFILL } } ,
2009-06-26 02:38:23 +00:00
/* Request/Response Matching */
2012-04-26 16:47:37 +00:00
{ & hf_enip_response_in ,
{ " Response In " , " enip.response_in " ,
2016-03-20 19:56:15 +00:00
FT_FRAMENUM , BASE_NONE , FRAMENUM_TYPE ( FT_FRAMENUM_RESPONSE ) , 0x0 ,
2012-04-26 16:47:37 +00:00
" The response to this ENIP request is in this frame " , HFILL } } ,
{ & hf_enip_response_to ,
{ " Request In " , " enip.response_to " ,
2016-03-20 19:56:15 +00:00
FT_FRAMENUM , BASE_NONE , FRAMENUM_TYPE ( FT_FRAMENUM_REQUEST ) , 0x0 ,
2012-04-26 16:47:37 +00:00
" This is a response to the ENIP request in this frame " , HFILL } } ,
{ & hf_enip_time ,
{ " Time " , " enip.time " ,
FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 ,
" The time between the Call and the Reply " , HFILL } } ,
2016-12-05 12:43:03 +00:00
{ & hf_enip_fwd_open_in ,
{ " Forward Open Request In " , " enip.fwd_open_in " ,
FT_FRAMENUM , BASE_NONE , NULL , 0 , NULL , HFILL } } ,
2018-06-15 14:45:01 +00:00
{ & hf_cip_io_data ,
{ " Data " , " cipio.data " ,
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
FT_BYTES , BASE_NONE | BASE_ALLOW_ZERO , NULL , 0x0 ,
2018-06-15 14:45:01 +00:00
NULL , HFILL } } ,
2012-04-26 16:47:37 +00:00
{ & hf_tcpip_status ,
{ " Status " , " cip.tcpip.status " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_status_interface_config ,
{ " Interface Configuration Status " , " cip.tcpip.status.interface_config " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_tcpip_status_interface_config_vals ) , 0x0000000F ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_status_mcast_pending ,
{ " MCast Pending " , " cip.tcpip.status.mcast_pending " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000010 ,
NULL , HFILL } } ,
{ & hf_tcpip_status_interface_config_pending ,
{ " Interface Configuration Pending " , " cip.tcpip.status.interface_config_pending " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000020 ,
NULL , HFILL } } ,
{ & hf_tcpip_status_acd ,
{ " ACD Status " , " cip.tcpip.status.acd " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_tcpip_status_acd_vals ) , 0x00000040 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_status_reserved ,
{ " Reserved " , " cip.tcpip.status.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFFFF80 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap ,
{ " Configuration Capability " , " cip.tcpip.config_cap " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_bootp ,
{ " BOOTP Client " , " cip.tcpip.config_cap.bootp " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000001 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_dns ,
{ " DNS Client " , " cip.tcpip.config_cap.dns " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000002 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_dhcp ,
{ " DHCP Client " , " cip.tcpip.config_cap.dhcp " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000004 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_dhcp_dns_update ,
{ " DHCP-DNS Update " , " cip.tcpip.config_cap.dhcp_dns_update " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000008 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_config_settable ,
{ " Configuration Settable " , " cip.tcpip.config_cap.config_settable " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000010 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_hardware_config ,
{ " Hardware Configurable " , " cip.tcpip.config_cap.hardware_config " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000020 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_interface_reset ,
{ " Interface Configuration Change Requires Reset " , " cip.tcpip.config_cap.interface_reset " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000040 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_acd ,
{ " ACD Capable " , " cip.tcpip.config_cap.acd " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000080 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_cap_reserved ,
{ " Reserved " , " cip.tcpip.config_cap.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFFFF00 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_control ,
{ " Configuration Control " , " cip.tcpip.config_control " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_control_config ,
{ " Configuration Method " , " cip.tcpip.config_control.config " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_tcpip_config_control_config_vals ) , 0x0000000F ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_config_control_dns ,
{ " DNS Enable " , " cip.tcpip.config_control.dns " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000010 ,
NULL , HFILL } } ,
{ & hf_tcpip_config_control_reserved ,
{ " Reserved " , " cip.tcpip.config_control.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFFFFE0 ,
NULL , HFILL } } ,
{ & hf_tcpip_ic_ip_addr ,
{ " IP Address " , " cip.tcpip.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_ic_subnet_mask ,
{ " Subnet Mask " , " cip.tcpip.subnet_mask " ,
2015-09-07 01:56:30 +00:00
FT_IPv4 , BASE_NETMASK , NULL , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_ic_gateway ,
{ " Gateway " , " cip.tcpip.gateway " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_ic_name_server ,
{ " Name Server " , " cip.tcpip.name_server " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_ic_name_server2 ,
{ " Name Server2 " , " cip.tcpip.name_server2 " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_ic_domain_name ,
{ " Domain Name " , " cip.tcpip.domain_name " ,
FT_STRING , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_hostname ,
{ " Hostname " , " cip.tcpip.hostname " ,
FT_STRING , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
2016-01-20 15:50:44 +00:00
{ & hf_tcpip_snn_timestamp ,
{ " Safety Network Number (Timestamp) " , " cip.tcpip.snn.timestamp " ,
FT_ABSOLUTE_TIME , ABSOLUTE_TIME_UTC , NULL , 0 ,
NULL , HFILL }
} ,
{ & hf_tcpip_snn_date ,
{ " Safety Network Number (Manual) Date " , " cip.tcpip.snn.date " ,
FT_UINT16 , BASE_HEX , VALS ( cipsafety_ssn_date_vals ) , 0 ,
NULL , HFILL }
} ,
{ & hf_tcpip_snn_time ,
{ " Safety Network Number (Manual) Time " , " cip.tcpip.snn.time " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL }
} ,
2012-04-26 16:47:37 +00:00
{ & hf_tcpip_ttl_value ,
{ " TTL Value " , " cip.tcpip.ttl_value " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_mcast_alloc ,
{ " Alloc Control " , " cip.tcpip.mcast.alloc " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_tcpip_mcast_alloc_vals ) , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_mcast_reserved ,
{ " Reserved " , " cip.tcpip.mcast.reserved " ,
FT_UINT8 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_mcast_num_mcast ,
{ " Num MCast " , " cip.tcpip.mcast.num_mcast " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_mcast_addr_start ,
{ " MCast Start Addr " , " cip.tcpip.mcast.addr_start " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_select_acd ,
{ " Select ACD " , " cip.tcpip.select_acd " ,
FT_BOOLEAN , BASE_NONE , TFS ( & tfs_enabled_disabled ) , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_lcd_acd_activity ,
{ " ACD Activity " , " cip.tcpip.last_conflict.acd_activity " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_tcpip_acd_activity_vals ) , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_tcpip_lcd_remote_mac ,
{ " RemoteMAC " , " cip.tcpip.last_conflict.remote_mac " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_lcd_arp_pdu ,
{ " Arp PDU " , " cip.tcpip.last_conflict.arp_pdu " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_tcpip_quick_connect ,
{ " Ethernet/IP Quick Connection " , " cip.tcpip.quick_connect " ,
FT_BOOLEAN , 8 , TFS ( & tfs_enabled_disabled ) , 0x1 ,
NULL , HFILL } } ,
2016-01-20 15:50:44 +00:00
{ & hf_tcpip_encap_inactivity ,
{ " Encapsulation Inactivity Timeout " , " cip.tcpip.encap_inactivity " ,
FT_UINT16 , BASE_DEC , NULL , 0x0 ,
NULL , HFILL } } ,
2012-04-26 16:47:37 +00:00
{ & hf_elink_interface_speed ,
{ " Interface Speed " , " cip.elink.interface_speed " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_interface_flags ,
{ " Interface Flags " , " cip.elink.iflags " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_iflags_link_status ,
{ " Link Status " , " cip.elink.iflags.link_status " ,
FT_BOOLEAN , 32 , TFS ( & tfs_active_inactive ) , 0x00000001 ,
NULL , HFILL } } ,
{ & hf_elink_iflags_duplex ,
{ " Duplex " , " cip.elink.iflags.duplex " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_elink_duplex_vals ) , 0x00000002 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_iflags_neg_status ,
{ " Negotiation Status " , " cip.elink.iflags.neg_status " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_elink_iflags_neg_status_vals ) , 0x0000001C ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_iflags_manual_reset ,
{ " Manual Reset Required " , " cip.elink.iflags.manual_reset " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_elink_iflags_reset_vals ) , 0x00000020 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_iflags_local_hw_fault ,
{ " Local Hardware Fault " , " cip.elink.iflags.local_hw_fault " ,
2014-05-28 00:33:22 +00:00
FT_UINT32 , BASE_DEC , VALS ( enip_elink_iflags_hw_fault_vals ) , 0x00000040 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_iflags_reserved ,
{ " Reserved " , " cip.elink.iflags.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFFFF80 ,
NULL , HFILL } } ,
{ & hf_elink_physical_address ,
2015-11-30 18:10:19 +00:00
{ " Physical Address " , " cip.elink.physical_address " ,
2012-04-26 16:47:37 +00:00
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_octets ,
{ " In Octets " , " cip.elink.icount.in_octets " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_ucast ,
{ " In Ucast Packets " , " cip.elink.icount.in_ucast " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_nucast ,
{ " In NUcast Packets " , " cip.elink.icount.in_nucast " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_discards ,
{ " In Discards " , " cip.elink.icount.in_discards " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_errors ,
{ " In Errors " , " cip.elink.icount.in_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_in_unknown_protos ,
{ " In Unknown Protos " , " cip.elink.icount.in_unknown_protos " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_out_octets ,
{ " Out Octets " , " cip.elink.icount.out_octets " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_out_ucast ,
{ " Out Ucast Packets " , " cip.elink.icount.out_ucast " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_out_nucast ,
{ " Out NUcast Packets " , " cip.elink.icount.out_nucast " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_out_discards ,
{ " Out Discards " , " cip.elink.icount.out_discards " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icount_out_errors ,
{ " Out Errors " , " cip.elink.icount.out_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_alignment_errors ,
{ " Alignment Errors " , " cip.elink.mcount.alignment_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_fcs_errors ,
{ " FCS Errors " , " cip.elink.mcount.fcs_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_single_collisions ,
{ " Single Collisions " , " cip.elink.mcount.single_collisions " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_multiple_collisions ,
{ " Multiple Collisions " , " cip.elink.mcount.multiple_collisions " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_sqe_test_errors ,
{ " SQE Test Errors " , " cip.elink.mcount.sqe_test_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_deferred_transmission ,
{ " Deferred Transmission " , " cip.elink.mcount.deferred_transmission " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_late_collisions ,
{ " Late Collisions " , " cip.elink.mcount.late_collisions " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_excessive_collisions ,
{ " Excessive Collisions " , " cip.elink.mcount.excessive_collisions " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_mac_transmit_errors ,
{ " MAC Transmit Errors " , " cip.elink.mcount.mac_transmit_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_carrier_sense_errors ,
{ " Carrier Sense Errors " , " cip.elink.mcount.carrier_sense_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_frame_too_long ,
{ " Frame Too Long " , " cip.elink.mcount.frame_too_long " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_mcount_mac_receive_errors ,
{ " MAC Receive Errors " , " cip.elink.mcount.mac_receive_errors " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icontrol_control_bits ,
{ " Control Bits " , " cip.elink.icontrol.control_bits " ,
FT_UINT16 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_icontrol_control_bits_auto_neg ,
{ " Auto-negotiate " , " cip.elink.icontrol.control_bits.auto_neg " ,
FT_BOOLEAN , 16 , TFS ( & tfs_enabled_disabled ) , 0x0001 ,
NULL , HFILL } } ,
{ & hf_elink_icontrol_control_bits_forced_duplex ,
{ " Forced Duplex Mode " , " cip.elink.icontrol.control_bits.forced_duplex " ,
2014-05-28 00:33:22 +00:00
FT_UINT16 , BASE_DEC , VALS ( enip_elink_duplex_vals ) , 0x0002 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_icontrol_control_bits_reserved ,
{ " Reserved " , " cip.elink.icontrol.control_bits.reserved " ,
FT_UINT16 , BASE_HEX , NULL , 0xFFFC ,
NULL , HFILL } } ,
{ & hf_elink_icontrol_forced_speed ,
{ " Forced Interface Speed " , " cip.elink.icontrol.forced_speed " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_elink_interface_type ,
{ " Interface Type " , " cip.elink.interface_type " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_elink_interface_type_vals ) , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_interface_state ,
{ " Interface State " , " cip.elink.interface_state " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_elink_interface_state_vals ) , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_admin_state ,
{ " Admin State " , " cip.elink.admin_state " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_elink_admin_state_vals ) , 0 ,
2012-04-26 16:47:37 +00:00
NULL , HFILL } } ,
{ & hf_elink_interface_label ,
{ " Interface Label " , " cip.elink.interface_label " ,
FT_STRING , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_8021q_enable ,
{ " 802.1Q Tag Enable " , " cip.qos.8021q_enable " ,
FT_BOOLEAN , 8 , TFS ( & tfs_enabled_disabled ) , 0x1 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_ptp_event ,
{ " DSCP PTP Event " , " cip.qos.ptp_event " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_ptp_general ,
{ " DSCP PTP General " , " cip.qos.ptp_general " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_urgent ,
{ " DSCP Urgent " , " cip.qos.urgent " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_scheduled ,
{ " DSCP Scheduled " , " cip.qos.scheduled " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_high ,
{ " DSCP High " , " cip.qos.high " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_low ,
{ " DSCP Low " , " cip.qos.low " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_qos_dscp_explicit ,
{ " DSCP Explicit " , " cip.qos.explicit " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
2012-07-18 19:40:56 +00:00
NULL , HFILL } } ,
{ & hf_dlr_network_topology ,
{ " Network Topology " , " cip.dlr.network_topology " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_dlr_network_topology_vals ) , 0 ,
2012-07-18 19:40:56 +00:00
NULL , HFILL } } ,
{ & hf_dlr_network_status ,
{ " Network Status " , " cip.dlr.network_status " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_dlr_network_status_vals ) , 0 ,
2012-07-18 19:40:56 +00:00
NULL , HFILL } } ,
{ & hf_dlr_ring_supervisor_status ,
{ " Ring Supervisor Status " , " cip.dlr.ring_supervisor_status " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_dlr_ring_supervisor_status_vals ) , 0 ,
2012-07-18 19:40:56 +00:00
NULL , HFILL } } ,
{ & hf_dlr_rsc_ring_supervisor_enable ,
{ " Ring Supervisor Enable " , " cip.dlr.rscconfig.supervisor_enable " ,
FT_BOOLEAN , 8 , TFS ( & tfs_true_false ) , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rsc_ring_supervisor_precedence ,
{ " Ring Supervisor Precedence " , " cip.dlr.rscconfig.supervisor_precedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rsc_beacon_interval ,
{ " Beacon Interval " , " cip.dlr.rscconfig.beacon_interval " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rsc_beacon_timeout ,
{ " Beacon Timeout " , " cip.dlr.rscconfig.beacon_timeout " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rsc_dlr_vlan_id ,
{ " DLR VLAN ID " , " cip.dlr.rscconfig.dlr_vlan_id " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_ring_faults_count ,
{ " Ring Faults Count " , " cip.dlr.ring_faults_count " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_lanp1_dev_ip_addr ,
{ " Device IP Address " , " cip.dlr.lanp1.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_lanp1_dev_physical_address ,
{ " Device Physical Address " , " cip.dlr.lanp1.physical_address " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_lanp2_dev_ip_addr ,
{ " Device IP Address " , " cip.dlr.lanp2.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
2011-10-13 00:00:52 +00:00
2012-07-18 19:40:56 +00:00
{ & hf_dlr_lanp2_dev_physical_address ,
{ " Device Physical Address " , " cip.dlr.lanp2.physical_address " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_ring_protocol_participants_count ,
{ " Participants Count " , " cip.dlr.participants_count " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rppl_dev_ip_addr ,
{ " Device IP Address " , " cip.dlr.rppl.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rppl_dev_physical_address ,
{ " Device Physical Address " , " cip.dlr.rppl.physical_address " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_asa_supervisor_ip_addr ,
{ " Supervisor IP Address " , " cip.dlr.asa.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_asa_supervisor_physical_address ,
{ " Supervisor Physical Address " , " cip.dlr.asa.physical_address " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_active_supervisor_precedence ,
{ " Active Supervisor Precedence " , " cip.dlr.supervisor_precedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_capability_flags ,
{ " Capability Flags " , " cip.dlr.capflags " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_capflags_announce_base_node ,
{ " Announce-based Ring Node " , " cip.dlr.capflags.announce_based " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000001 ,
NULL , HFILL } } ,
{ & hf_dlr_capflags_beacon_base_node ,
{ " Beacon-based Ring Node " , " cip.dlr.capflags.beacon_based " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000002 ,
NULL , HFILL } } ,
{ & hf_dlr_capflags_reserved1 ,
{ " Reserved " , " cip.dlr.capflags.reserved1 " ,
FT_BOOLEAN , 32 , NULL , 0x0000001C ,
NULL , HFILL } } ,
{ & hf_dlr_capflags_supervisor_capable ,
{ " Supervisor Capable " , " cip.dlr.capflags.supervisor_capable " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000020 ,
NULL , HFILL } } ,
2013-04-04 14:34:26 +00:00
{ & hf_dlr_capflags_redundant_gateway_capable ,
2016-10-06 17:57:55 +00:00
{ " Redundant Gateway Capable " , " cip.dlr.capflags.redundant_gateway_capable " ,
2013-04-04 14:34:26 +00:00
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000040 ,
NULL , HFILL } } ,
{ & hf_dlr_capflags_flush_frame_capable ,
{ " Flush_Table Frame Capable " , " cip.dlr.capflags.flush_frame_capable " ,
FT_BOOLEAN , 32 , TFS ( & tfs_true_false ) , 0x00000080 ,
NULL , HFILL } } ,
2012-11-29 20:15:37 +00:00
{ & hf_dlr_capflags_reserved2 ,
2012-07-18 19:40:56 +00:00
{ " Reserved " , " cip.dlr.capflags.reserved2 " ,
2013-04-04 14:34:26 +00:00
FT_BOOLEAN , 32 , NULL , 0xFFFFFF00 ,
NULL , HFILL } } ,
{ & hf_dlr_rgc_red_gateway_enable ,
{ " Redundant Gateway Enable " , " cip.dlr.rgc.gateway_enable " ,
FT_BOOLEAN , 8 , TFS ( & tfs_true_false ) , 0 ,
2013-09-12 20:34:19 +00:00
NULL , HFILL } } ,
2013-04-04 14:34:26 +00:00
{ & hf_dlr_rgc_gateway_precedence ,
{ " Gateway Precedence " , " cip.dlr.rgc.gateway_precedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
2013-09-12 20:34:19 +00:00
NULL , HFILL } } ,
2013-04-04 14:34:26 +00:00
{ & hf_dlr_rgc_advertise_interval ,
{ " Advertise Interval " , " cip.dlr.rgc.advertise_interval " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rgc_advertise_timeout ,
{ " Advertise Timeout " , " cip.dlr.rgc.advertise_timeout " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_rgc_learning_update_enable ,
{ " Learning Update Enable " , " cip.dlr.rgc.learning_update_enable " ,
FT_BOOLEAN , 8 , TFS ( & tfs_true_false ) , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_redundant_gateway_status ,
{ " Redundant Gateway Status " , " cip.dlr.redundant_gateway_status " ,
2014-05-28 00:33:22 +00:00
FT_UINT8 , BASE_DEC , VALS ( enip_dlr_redundant_gateway_status_vals ) , 0 ,
2013-04-04 14:34:26 +00:00
NULL , HFILL } } ,
{ & hf_dlr_aga_ip_addr ,
{ " Active Gateway IP Address " , " cip.dlr.aga.ip_addr " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_dlr_aga_physical_address ,
{ " Active Gateway Physical Address " , " cip.dlr.aga.physical_address " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
2013-09-12 20:34:19 +00:00
2013-04-04 14:34:26 +00:00
{ & hf_dlr_active_gateway_precedence ,
{ " Active Gateway Precedence " , " cip.dlr.active_gateway_precedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
2016-01-28 21:34:14 +00:00
NULL , HFILL } } ,
{ & hf_eip_security_state ,
{ " State " , " cip.eip_security.state " ,
FT_UINT8 , BASE_DEC , VALS ( eip_security_state_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_verify_client_cert ,
{ " Verify Client Certificate " , " cip.eip_security.verify_client_cert " ,
FT_BOOLEAN , 8 , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_send_cert_chain ,
{ " Send Certificate Chain " , " cip.eip_security.send_cert_chain " ,
FT_BOOLEAN , 8 , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_check_expiration ,
{ " Check Expiration " , " cip.eip_security.check_expiration " ,
FT_BOOLEAN , 8 , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_capability_flags ,
{ " Capability Flags " , " cip.eip_security.capability_flags " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_capflags_secure_renegotiation ,
{ " Secure Renegotiation " , " cip.eip_security.capability_flags.secure_renegotiation " ,
FT_BOOLEAN , 32 , TFS ( & tfs_supported_not_supported ) , 0x00000001 ,
NULL , HFILL } } ,
{ & hf_eip_security_capflags_reserved ,
{ " Reserved " , " cip.eip_security.capability_flags.reserved " ,
FT_UINT32 , BASE_HEX , NULL , 0xFFFFFFFE ,
NULL , HFILL } } ,
{ & hf_eip_security_num_avail_cipher_suites ,
{ " Number of Available Cipher Suites " , " cip.eip_security.num_avail_cipher_suites " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_avail_cipher_suite ,
{ " Available Cipher Suite " , " cip.eip_security.avail_cipher_suite " ,
FT_UINT16 , BASE_HEX | BASE_EXT_STRING , & ssl_31_ciphersuite_ext , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_num_allow_cipher_suites ,
{ " Number of Allowed Cipher Suites " , " cip.eip_security.num_allow_cipher_suites " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
2003-06-11 09:02:19 +00:00
2016-01-28 21:34:14 +00:00
{ & hf_eip_security_allow_cipher_suite ,
{ " Allowed Cipher Suite " , " cip.eip_security.allow_cipher_suite " ,
FT_UINT16 , BASE_HEX | BASE_EXT_STRING , & ssl_31_ciphersuite_ext , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_num_psk ,
{ " Number of PSKs " , " cip.eip_security.num_psk " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_psk_identity_size ,
{ " PSK Identity Size " , " cip.eip_security.psk_identity_size " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_psk_identity ,
{ " PSK Identity " , " cip.eip_security.psk_identity " ,
FT_BYTES , BASE_NONE | BASE_ALLOW_ZERO , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_psk_size ,
{ " PSK Size " , " cip.eip_security.psk_size " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_psk ,
{ " PSK " , " cip.eip_security.psk " ,
FT_BYTES , BASE_NONE | BASE_ALLOW_ZERO , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_num_active_certs ,
{ " Number of Active Certificates " , " cip.eip_security.num_active_certs " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_security_num_trusted_auths ,
{ " Number of Trusted Authorities " , " cip.eip_security.num_trusted_auths " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_name ,
{ " Name " , " cip.eip_cert.name " ,
FT_STRING , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_state ,
{ " State " , " cip.eip_cert.state " ,
FT_UINT8 , BASE_DEC , VALS ( eip_cert_state_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_device_cert_status ,
{ " Certificate Status " , " cip.eip_cert.device_cert.status " ,
FT_UINT8 , BASE_DEC , VALS ( eip_cert_status_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_ca_cert_status ,
{ " Certificate Status " , " cip.eip_cert.ca_cert.status " ,
FT_UINT8 , BASE_DEC , VALS ( eip_cert_status_vals ) , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_capflags_push ,
2018-05-31 16:48:52 +00:00
{ " Push " , " cip.eip_cert.capflags.push " ,
2016-01-28 21:34:14 +00:00
FT_BOOLEAN , 32 , NULL , 0x00000001 ,
NULL , HFILL } } ,
{ & hf_eip_cert_capflags_reserved ,
2018-05-31 16:48:52 +00:00
{ " Reserved " , " cip.eip_cert.capflags.reserved " ,
2016-01-28 21:34:14 +00:00
FT_BOOLEAN , 32 , NULL , 0xFFFFFFFE ,
NULL , HFILL } } ,
{ & hf_eip_cert_capability_flags ,
{ " Capability flags " , " cip.eip_cert.capflags " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_num_certs ,
{ " Number of Certificates " , " cip.eip_cert.num_certs " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_eip_cert_cert_name ,
{ " Certificate name " , " cip.eip_cert.cert_name " ,
FT_STRING , BASE_NONE , NULL , 0 ,
NULL , HFILL } } ,
} ;
2003-06-11 09:02:19 +00:00
2009-07-15 19:33:48 +00:00
/* Setup protocol subtree array */
2009-06-26 02:38:23 +00:00
static gint * ett [ ] = {
& ett_enip ,
2018-06-15 14:45:01 +00:00
& ett_cip_io_generic ,
2014-08-01 14:08:57 +00:00
& ett_path ,
2009-06-26 02:38:23 +00:00
& ett_count_tree ,
& ett_type_tree ,
& ett_command_tree ,
& ett_sockadd ,
& ett_lsrcf ,
2011-10-26 04:55:21 +00:00
& ett_tcpip_status ,
& ett_tcpip_config_cap ,
& ett_tcpip_config_control ,
& ett_elink_interface_flags ,
2012-07-18 19:40:56 +00:00
& ett_elink_icontrol_bits ,
2013-04-04 14:34:26 +00:00
& ett_dlr_capability_flags ,
2016-01-28 21:34:14 +00:00
& ett_dlr_lnknbrstatus_flags ,
& ett_eip_security_capability_flags ,
& ett_eip_security_psk ,
& ett_eip_security_active_certs ,
& ett_eip_security_trusted_auths ,
& ett_eip_cert_capability_flags ,
& ett_eip_cert_num_certs ,
2017-07-20 15:36:59 +00:00
& ett_security_profiles ,
& ett_iana_port_state_flags
2009-06-26 02:38:23 +00:00
} ;
2009-07-09 20:44:28 +00:00
2013-05-24 18:02:54 +00:00
static ei_register_info ei [ ] = {
2013-06-08 02:06:24 +00:00
{ & ei_mal_tcpip_status , { " cip.malformed.tcpip.status " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Status " , EXPFILL } } ,
{ & ei_mal_tcpip_config_cap , { " cip.malformed.tcpip.config_cap " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Configuration Capability " , EXPFILL } } ,
{ & ei_mal_tcpip_config_control , { " cip.malformed.tcpip.config_control " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Configuration Control " , EXPFILL } } ,
{ & ei_mal_tcpip_interface_config , { " cip.malformed.tcpip.interface_config " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Interface Configuration " , EXPFILL } } ,
2016-01-20 15:50:44 +00:00
{ & ei_mal_tcpip_ssn , { " cip.malformed.tcpip.ssn " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Object Safety Network Number " , EXPFILL } } ,
2013-06-08 02:06:24 +00:00
{ & ei_mal_tcpip_mcast_config , { " cip.malformed.tcpip.mcast_config " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Multicast Config " , EXPFILL } } ,
{ & ei_mal_tcpip_last_conflict , { " cip.malformed.tcpip.last_conflict " , PI_MALFORMED , PI_ERROR , " Malformed TCP/IP Last Conflict Detected " , EXPFILL } } ,
{ & ei_mal_elink_interface_flags , { " cip.malformed.elink.interface_flags " , PI_MALFORMED , PI_ERROR , " Malformed Ethernet Link Interface Flags " , EXPFILL } } ,
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
{ & ei_mal_elink_physical_address , { " cip.malformed.elink.physical_address " , PI_MALFORMED , PI_ERROR , " Malformed Ethernet Link Physical Address " , EXPFILL } } ,
2013-06-08 02:06:24 +00:00
{ & ei_mal_elink_interface_counters , { " cip.malformed.elink.interface_counters " , PI_MALFORMED , PI_ERROR , " Malformed Ethernet Link Interface Counters " , EXPFILL } } ,
{ & ei_mal_elink_media_counters , { " cip.malformed.elink.media_counters " , PI_MALFORMED , PI_ERROR , " Malformed Ethernet Link Media Counters " , EXPFILL } } ,
{ & ei_mal_elink_interface_control , { " cip.malformed.elink.interface_control " , PI_MALFORMED , PI_ERROR , " Malformed Ethernet Link Interface Control " , EXPFILL } } ,
{ & ei_mal_dlr_ring_supervisor_config , { " cip.malformed.dlr.ring_supervisor_config " , PI_MALFORMED , PI_ERROR , " Malformed DLR Ring Supervisor Config " , EXPFILL } } ,
{ & 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 } } ,
{ & 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 } } ,
{ & 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 } } ,
{ & ei_mal_dlr_active_supervisor_address , { " cip.malformed.dlr.active_supervisor_address " , PI_MALFORMED , PI_ERROR , " Malformed DLR Active Supervisor Address " , EXPFILL } } ,
{ & ei_mal_dlr_capability_flags , { " cip.malformed.dlr.capability_flags " , PI_MALFORMED , PI_ERROR , " Malformed DLR Capability Flag " , EXPFILL } } ,
{ & ei_mal_dlr_redundant_gateway_config , { " cip.malformed.dlr.redundant_gateway_config " , PI_MALFORMED , PI_ERROR , " Malformed DLR Redundant Gateway Config " , EXPFILL } } ,
{ & ei_mal_dlr_active_gateway_address , { " cip.malformed.dlr.active_gateway_address " , PI_MALFORMED , PI_ERROR , " Malformed DLR Active Gateway Address " , EXPFILL } } ,
2016-01-28 21:34:14 +00:00
{ & ei_mal_eip_security_capability_flags , { " cip.malformed.eip_security.capability_flags " , PI_MALFORMED , PI_ERROR , " Malformed EIP Security Capability Flags " , EXPFILL } } ,
{ & 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 } } ,
{ & 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 } } ,
{ & ei_mal_eip_security_preshared_keys , { " cip.malformed.eip_security.preshared_keys " , PI_MALFORMED , PI_ERROR , " Malformed EIP Security Pre-Shared Keys " , EXPFILL } } ,
{ & ei_mal_eip_security_active_certs , { " cip.malformed.eip_security.active_certs " , PI_MALFORMED , PI_ERROR , " Malformed EIP Security Active Device Certificates " , EXPFILL } } ,
{ & ei_mal_eip_security_trusted_auths , { " cip.malformed.eip_security.trusted_auths " , PI_MALFORMED , PI_ERROR , " Malformed EIP Security Trusted Authorities " , EXPFILL } } ,
{ & ei_mal_eip_cert_capability_flags , { " cip.malformed.eip_cert.capability_flags " , PI_MALFORMED , PI_ERROR , " Malformed EIP Certificate Management Capability Flags " , EXPFILL } } ,
2013-05-24 18:02:54 +00:00
} ;
2009-07-09 20:44:28 +00:00
/* Setup list of header fields for DLR See Section 1.6.1 for details*/
2011-10-13 00:00:52 +00:00
static hf_register_info hfdlr [ ] = {
/* Ring Sub-type */
2009-07-09 20:44:28 +00:00
{ & hf_dlr_ringsubtype ,
2013-10-02 01:43:39 +00:00
{ " Ring Sub-Type " , " enip.dlr.ringsubtype " ,
2011-10-13 00:00:52 +00:00
FT_UINT8 , BASE_HEX , NULL , 0 ,
2013-10-02 01:43:39 +00:00
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Ring Protocol Version */
{ & hf_dlr_ringprotoversion ,
2013-10-02 01:43:39 +00:00
{ " Ring Protocol Version " , " enip.dlr.protversion " ,
2011-10-13 00:00:52 +00:00
FT_UINT8 , BASE_DEC , NULL , 0 ,
2013-10-02 01:43:39 +00:00
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Frame Type */
{ & hf_dlr_frametype ,
2013-10-02 01:43:39 +00:00
{ " Frame Type " , " enip.dlr.frametype " ,
2011-10-13 00:00:52 +00:00
FT_UINT8 , BASE_HEX , VALS ( dlr_frame_type_vals ) , 0 ,
2013-10-02 01:43:39 +00:00
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Source Port */
{ & hf_dlr_sourceport ,
2013-10-02 01:43:39 +00:00
{ " Source Port " , " enip.dlr.sourceport " ,
2011-10-13 00:00:52 +00:00
FT_UINT8 , BASE_HEX , VALS ( dlr_source_port_vals ) , 0 ,
2013-10-02 01:43:39 +00:00
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Source IP Address */
{ & hf_dlr_sourceip ,
2011-10-13 00:00:52 +00:00
{ " Source IP " , " enip.dlr.sourceip " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
" Source IP Address " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Sequence ID*/
{ & hf_dlr_sequenceid ,
2011-10-13 00:00:52 +00:00
{ " Sequence Id " , " enip.dlr.seqid " ,
FT_UINT32 , BASE_HEX , NULL , 0 ,
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Ring State */
{ & hf_dlr_ringstate ,
2011-10-13 00:00:52 +00:00
{ " Ring State " , " enip.dlr.state " ,
FT_UINT8 , BASE_HEX , VALS ( dlr_ring_state_vals ) , 0 ,
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Supervisor Precedence */
{ & hf_dlr_supervisorprecedence ,
2011-10-13 00:00:52 +00:00
{ " Supervisor Precedence " , " enip.dlr.supervisorprecedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Beacon Interval */
{ & hf_dlr_beaconinterval ,
2011-10-13 00:00:52 +00:00
{ " Beacon Interval " , " enip.dlr.beaconinterval " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Beacon Timeout */
{ & hf_dlr_beacontimeout ,
2011-10-13 00:00:52 +00:00
{ " Beacon Timeout " , " enip.dlr.beacontimeout " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Beacon Reserved */
{ & hf_dlr_beaconreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.beaconreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Beacon Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Neighbor_Check_Request Reserved */
{ & hf_dlr_nreqreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.nreqreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Neighbor_Check_Request Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Neighbor_Check_Response Source Port */
{ & hf_dlr_nressourceport ,
2013-10-02 01:43:39 +00:00
{ " Request Source Port " , " enip.dlr.nressourceport " ,
2011-10-13 00:00:52 +00:00
FT_UINT8 , BASE_HEX , VALS ( dlr_source_port_vals ) , 0 ,
" Neighbor_Check_Response Source Port " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Neighbor_Check_Response Reserved */
{ & hf_dlr_nresreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.nresreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Neighbor_Check_Response Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Link_Status/Neighbor_Status Status */
{ & hf_dlr_lnknbrstatus ,
2014-11-27 01:41:16 +00:00
{ " Link/Neighbor Status " , " enip.dlr.lnknbrstatus.status " ,
2013-04-04 14:34:26 +00:00
FT_UINT8 , BASE_HEX , NULL , 0 ,
2011-10-13 00:00:52 +00:00
" Link_Status/Neighbor_Status Status " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
2013-04-04 14:34:26 +00:00
{ & hf_dlr_lnknbrstatus_port1 ,
2014-11-27 01:41:16 +00:00
{ " Port 1 Active " , " enip.dlr.lnknbrstatus.port1 " ,
2013-04-04 14:34:26 +00:00
FT_BOOLEAN , 8 , TFS ( & tfs_true_false ) , 0x01 ,
NULL , HFILL }
} ,
{ & hf_dlr_lnknbrstatus_port2 ,
2014-11-27 01:41:16 +00:00
{ " Port 2 Active " , " enip.dlr.lnknbrstatus.port2 " ,
2013-04-04 14:34:26 +00:00
FT_BOOLEAN , 8 , TFS ( & tfs_true_false ) , 0x02 ,
NULL , HFILL }
} ,
{ & hf_dlr_lnknbrstatus_reserved ,
{ " Reserved " , " enip.dlr.lnknbrstatus.reserved " ,
FT_BOOLEAN , 8 , NULL , 0x7C ,
NULL , HFILL }
} ,
{ & hf_dlr_lnknbrstatus_frame_type ,
2014-11-27 01:41:16 +00:00
{ " Link/Neighbor Status Frame Type " , " enip.dlr.lnknbrstatus.frame_type " ,
2013-04-04 14:34:26 +00:00
FT_BOOLEAN , 8 , TFS ( & dlr_lnknbrstatus_frame_type_vals ) , 0x80 ,
NULL , HFILL }
} ,
2009-07-09 20:44:28 +00:00
/* Link_Status/Neighbor_Status Reserved */
{ & hf_dlr_lnknbrreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.lnknbrreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Link_Status/Neighbor_Status Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Locate_Fault Reserved */
{ & hf_dlr_lfreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.lfreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Locate_Fault Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Announce Reserved */
{ & hf_dlr_anreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.anreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Announce Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Number of Nodes in List */
{ & hf_dlr_sonumnodes ,
2011-10-13 00:00:52 +00:00
{ " Num nodes " , " enip.dlr.sonumnodes " ,
FT_UINT16 , BASE_DEC , NULL , 0 ,
" Number of Nodes in List " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Sign_On Node # MAC Address */
{ & hf_dlr_somac ,
2011-10-13 00:00:52 +00:00
{ " MAC Address " , " enip.dlr.somac " ,
FT_ETHER , BASE_NONE , NULL , 0 ,
" Sign_On Node MAC Address " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Node # IP Address */
{ & hf_dlr_soip ,
2011-10-13 00:00:52 +00:00
{ " IP Address " , " enip.dlr.soip " ,
FT_IPv4 , BASE_NONE , NULL , 0 ,
" Sign_On Node IP Address " , HFILL }
2009-07-09 20:44:28 +00:00
} ,
/* Sign_On Reserved */
{ & hf_dlr_soreserved ,
2011-10-13 00:00:52 +00:00
{ " Reserved " , " enip.dlr.soreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Sign_On Reserved " , HFILL }
2013-04-04 14:34:26 +00:00
} ,
/* Gateway State */
{ & hf_dlr_advgatewaystate ,
{ " Gateway Status " , " enip.dlr.advgatewaystate " ,
FT_UINT8 , BASE_HEX , VALS ( dlr_adv_state_vals ) , 0 ,
" Gateway State " , HFILL }
} ,
/* Gateway Precedence */
{ & hf_dlr_advgatewayprecedence ,
{ " Gateway Precedence " , " enip.dlr.advgatewayprecedence " ,
FT_UINT8 , BASE_DEC , NULL , 0 ,
2013-04-04 15:00:27 +00:00
NULL , HFILL }
2013-04-04 14:34:26 +00:00
} ,
/* Advertise Interval */
{ & hf_dlr_advadvertiseinterval ,
{ " Advertise Interval " , " enip.dlr.advadvertiseinterval " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
2013-04-04 15:00:27 +00:00
NULL , HFILL }
2013-04-04 14:34:26 +00:00
} ,
/* Advertise Timeout */
{ & hf_dlr_advadvertisetimeout ,
{ " Advertise Interval " , " enip.dlr.advadvertisetimeout " ,
FT_UINT32 , BASE_DEC , NULL , 0 ,
2013-04-04 15:00:27 +00:00
NULL , HFILL }
2013-04-04 14:34:26 +00:00
} ,
/* Learning Update Enable */
{ & hf_dlr_advlearningupdateenable ,
{ " Learning Update Enable " , " enip.dlr.advlearningupdateenable " ,
FT_UINT8 , BASE_HEX , VALS ( dlr_adv_learning_update_vals ) , 0 ,
" Advertise Learning Update Enable " , HFILL }
} ,
/* Advertise Reserved */
{ & hf_dlr_advreserved ,
{ " Reserved " , " enip.dlr.advreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Advertise Reserved " , HFILL }
} ,
/* Flush_Tables Learning Update Enable */
{ & hf_dlr_flushlearningupdateenable ,
{ " Learning Update Enable " , " enip.dlr.flushlearningupdateenable " ,
FT_UINT8 , BASE_HEX , VALS ( dlr_flush_learning_update_vals ) , 0 ,
" Flush_Tables Learning Update Enable " , HFILL }
} ,
/* Flush Reserved */
{ & hf_dlr_flushreserved ,
{ " Reserved " , " enip.dlr.flushreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Flush_Tables Reserved " , HFILL }
} ,
/* Learning_Update Reserved */
{ & hf_dlr_learnreserved ,
{ " Reserved " , " enip.dlr.learnreserved " ,
FT_BYTES , BASE_NONE , NULL , 0 ,
" Learning_Update Reserved " , HFILL }
2009-07-09 20:44:28 +00:00
}
} ;
/* Setup protocol subtree array for DLR */
2011-04-25 01:37:19 +00:00
static gint * ettdlr [ ] = {
2011-10-13 00:00:52 +00:00
& ett_dlr
2011-04-25 01:37:19 +00:00
} ;
2009-07-09 20:44:28 +00:00
2009-06-26 02:38:23 +00:00
module_t * enip_module ;
2013-05-24 18:02:54 +00:00
expert_module_t * expert_enip ;
2003-06-11 09:02:19 +00:00
2009-07-15 19:33:48 +00:00
/* Register the protocol name and description */
2012-02-27 09:30:26 +00:00
proto_enip = proto_register_protocol ( " EtherNet/IP (Industrial Protocol) " , " ENIP " , " enip " ) ;
2018-07-05 14:22:59 +00:00
proto_cipio = proto_register_protocol ( " Common Industrial Protocol, I/O " , " CIP I/O " , " cipio " ) ;
proto_cip_class1 = proto_register_protocol_in_name_only (
" Common Industrial Protocol, I/O Class 1 " ,
" CIP Class 1 " ,
" cipio1 " ,
proto_cipio ,
FT_PROTOCOL ) ;
2003-06-11 09:02:19 +00:00
2016-12-17 01:06:11 +00:00
enip_tcp_handle = register_dissector ( " enip " , dissect_enip_tcp , proto_enip ) ;
2018-07-05 14:22:59 +00:00
cipio_handle = register_dissector ( " cipio " , dissect_cipio , proto_cipio ) ;
cip_class1_handle = register_dissector ( " cipio_class1 " , dissect_cip_class1 , proto_cip_class1 ) ;
2018-06-15 14:45:01 +00:00
2018-07-05 14:22:59 +00:00
cip_io_generic_handle = register_dissector ( " cipgenericio " , dissect_cip_io_generic , proto_cipio ) ;
2015-01-24 23:34:53 +00:00
2009-07-15 19:33:48 +00:00
/* Required function calls to register the header fields and subtrees used */
2009-06-26 02:38:23 +00:00
proto_register_field_array ( proto_enip , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2003-08-16 01:53:41 +00:00
2013-05-24 18:02:54 +00:00
expert_enip = expert_register_protocol ( proto_enip ) ;
expert_register_field_array ( expert_enip , ei , array_length ( ei ) ) ;
2009-06-26 02:38:23 +00:00
enip_module = prefs_register_protocol ( proto_enip , NULL ) ;
prefs_register_bool_preference ( enip_module , " desegment " ,
2011-10-13 00:00:52 +00:00
" Desegment all EtherNet/IP messages spanning multiple TCP segments " ,
" Whether the EtherNet/IP dissector should desegment all messages spanning multiple TCP segments " ,
& enip_desegment ) ;
2004-09-23 17:34:35 +00:00
2011-12-01 06:05:39 +00:00
prefs_register_bool_preference ( enip_module , " o2t_run_idle " ,
" Dissect 32-bit header in the O->T direction " ,
" Determines whether all I/O connections will assume a 32-bit header in the O->T direction " ,
& enip_OTrun_idle ) ;
prefs_register_bool_preference ( enip_module , " t2o_run_idle " ,
" Dissect 32-bit header in the T->O direction " ,
" Determines whether all I/O connections will assume a 32-bit header in the T->O direction " ,
& enip_TOrun_idle ) ;
2015-04-02 21:15:08 +00:00
prefs_register_obsolete_preference ( enip_module , " default_io_dissector " ) ;
2012-07-18 19:40:56 +00:00
2009-06-26 02:38:23 +00:00
subdissector_srrd_table = register_dissector_table ( " enip.srrd.iface " ,
2016-08-30 22:51:54 +00:00
" ENIP SendRequestReplyData.Interface Handle " , proto_enip , FT_UINT32 , BASE_HEX ) ;
2004-09-23 17:34:35 +00:00
2018-06-15 14:45:01 +00:00
subdissector_io_table = register_dissector_table ( " cip.io.iface " ,
2018-07-05 14:22:59 +00:00
" CIP Class 0/1 Interface Handle " , proto_cipio , FT_UINT32 , BASE_HEX ) ;
2018-06-15 14:45:01 +00:00
2018-06-27 22:56:17 +00:00
subdissector_cip_connection_table = register_dissector_table ( " cip.connection.class " ,
" CIP Class 2/3 Interface Handle " , proto_enip , FT_UINT32 , BASE_HEX ) ;
2017-02-02 04:13:42 +00:00
enip_request_hashtable = wmem_map_new_autoreset ( wmem_epan_scope ( ) , wmem_file_scope ( ) , enip_request_hash , enip_request_equal ) ;
enip_conn_hashtable = wmem_map_new_autoreset ( wmem_epan_scope ( ) , wmem_file_scope ( ) , enip_conn_hash , enip_conn_equal ) ;
2009-07-09 20:44:28 +00:00
/* Register the protocol name and description */
proto_dlr = proto_register_protocol ( " Device Level Ring " , " DLR " , " dlr " ) ;
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array ( proto_dlr , hfdlr , array_length ( hfdlr ) ) ;
proto_register_subtree_array ( ettdlr , array_length ( ettdlr ) ) ;
2018-07-05 14:22:59 +00:00
register_conversation_filter ( " enip " , " CIP Connection " , cip_connection_conv_valid , cip_connection_conv_filter ) ;
2014-05-27 02:58:48 +00:00
2018-06-15 14:45:01 +00:00
subdissector_decode_as_io_table = register_decode_as_next_proto ( proto_enip , " CIP I/O " , " cip.io " , " CIP I/O Payload " , enip_prompt ) ;
2004-09-23 17:34:35 +00:00
} /* end of proto_register_enip() */
2003-06-11 09:02:19 +00:00
void
2004-09-23 17:34:35 +00:00
proto_reg_handoff_enip ( void )
2003-06-11 09:02:19 +00:00
{
2016-12-17 01:06:11 +00:00
dissector_handle_t enip_udp_handle ;
2009-07-09 20:44:28 +00:00
dissector_handle_t dlr_handle ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
/* Register for EtherNet/IP, using TCP */
2016-10-07 20:25:01 +00:00
dissector_add_uint_with_preference ( " tcp.port " , ENIP_ENCAP_PORT , enip_tcp_handle ) ;
2004-09-23 17:34:35 +00:00
2009-06-26 02:38:23 +00:00
/* Register for EtherNet/IP, using UDP */
2015-12-09 03:49:44 +00:00
enip_udp_handle = create_dissector_handle ( dissect_enip_udp , proto_enip ) ;
2016-10-05 20:33:54 +00:00
dissector_add_uint_with_preference ( " udp.port " , ENIP_ENCAP_PORT , enip_udp_handle ) ;
2003-06-11 09:02:19 +00:00
2009-06-26 02:38:23 +00:00
/* Register for EtherNet/IP IO data (UDP) */
2018-07-05 14:22:59 +00:00
dissector_add_uint_with_preference ( " udp.port " , ENIP_IO_PORT , cipio_handle ) ;
2016-01-28 21:34:14 +00:00
/* Register for EtherNet/IP TLS */
ssl_dissector_add ( ENIP_SECURE_PORT , enip_tcp_handle ) ;
2018-07-05 14:22:59 +00:00
dtls_dissector_add ( ENIP_SECURE_PORT , cipio_handle ) ;
2003-08-16 01:53:41 +00:00
2012-02-27 09:30:26 +00:00
/* Find ARP dissector for TCP/IP object */
2016-03-16 13:02:52 +00:00
arp_handle = find_dissector_add_dependency ( " arp " , proto_enip ) ;
2012-02-27 09:30:26 +00:00
2012-03-02 03:39:16 +00:00
/* I/O data dissectors */
cipsafety_handle = find_dissector ( " cipsafety " ) ;
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
/* Implicit data dissector */
2018-06-27 22:56:17 +00:00
cip_implicit_handle = find_dissector_add_dependency ( " cip_implicit " , proto_enip ) ;
cip_handle = find_dissector_add_dependency ( " cip " , proto_enip ) ;
Enhancements for EtherNet/IP and CIP
EtherNet/IP
1. EtherNet Link object parsed Physical Address attribute response incorrectly.
2. Display Unknown Commands as ENIP instead of just TCP data.
CIP
1. For connected data, don't interpret it as a Message Router Request/Response format when the Forward Open connection was not directed to the Message Router. Previously, this data would be incorrectly shown as explicit CIP data. In many cases, this would show as malformed. This traffic will now just display as Data in the Wireshark tree, and "Implicit Data - Class (0x123)" in the Info column. Make this data filterable by "cip.conn_path_class == 0x123".
2. Fix parsing of Unconnected Send responses. Previously, for most cases, the response was not fully parsed, and would just show "Data", or it would parse the response as if the request class was the Connection Manager, which is incorrect. Now, also show the request path of the original embedded message in the tree.
3. Add some detailed error data for malformed Forward Close response.
Change-Id: I1c98ce516373d8c0ed6e049e25342f726bc370ea
Reviewed-on: https://code.wireshark.org/review/12339
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: D. Ulis <daulis0@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
2015-12-01 19:25:52 +00:00
2009-07-09 20:44:28 +00:00
/* Register for EtherNet/IP Device Level Ring protocol */
2015-12-09 03:49:44 +00:00
dlr_handle = create_dissector_handle ( dissect_dlr , proto_dlr ) ;
2010-12-20 05:35:29 +00:00
dissector_add_uint ( " ethertype " , ETHERTYPE_DLR , dlr_handle ) ;
2009-07-09 20:44:28 +00:00
2016-01-28 19:13:30 +00:00
subdissector_class_table = find_dissector_table ( " cip.class.iface " ) ;
2012-08-09 16:47:15 +00:00
2018-07-05 14:22:59 +00:00
dissector_add_for_decode_as ( " cip.io " , cip_class1_handle ) ;
2004-09-23 17:34:35 +00:00
} /* end of proto_reg_handoff_enip() */
2011-10-13 00:00:52 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 3
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* ex : set shiftwidth = 3 tabstop = 8 expandtab :
* : indentSize = 3 : tabSize = 8 : noTabs = true :
*/