From fc511c3f11d1e744adbf8fff6b1e46adc9776c94 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Wed, 20 Jan 2016 10:50:44 -0500 Subject: [PATCH] CIP: Add support for Get Attributes All Get Attributes All is a predefined list of existing attribute IDs for a given class. Add a new index for each attribute for their place in GetAttributesAll response. Then a hash table of classes for existing attributes are created to handle the GetAttributesAll service. Added more TCP/IP object attributes since more have been added to the spec. Moved TCP/IP object attributes all to ENIP dissector. Bug: 11996 Change-Id: I7f50c9aadf04efdb17ef31f39e6a991c0a84bef2 Reviewed-on: https://code.wireshark.org/review/13186 Petri-Dish: Michael Mann Tested-by: Petri Dish Buildbot Reviewed-by: Michael Mann --- epan/dissectors/packet-cip.c | 323 ++++++++++++++++++++++------- epan/dissectors/packet-cip.h | 35 +++- epan/dissectors/packet-cipsafety.c | 139 +++++-------- epan/dissectors/packet-cipsafety.h | 2 +- epan/dissectors/packet-enip.c | 179 +++++++++++----- epan/dissectors/packet-enip.h | 2 +- 6 files changed, 465 insertions(+), 215 deletions(-) diff --git a/epan/dissectors/packet-cip.c b/epan/dissectors/packet-cip.c index 2eedd44926..6bee51db8a 100644 --- a/epan/dissectors/packet-cip.c +++ b/epan/dissectors/packet-cip.c @@ -70,15 +70,15 @@ static int proto_cip_class_cco = -1; static int proto_enip = -1; static int proto_modbus = -1; -static int hf_attr_class_revision = -1; -static int hf_attr_class_max_instance = -1; -static int hf_attr_class_num_instance = -1; -static int hf_attr_class_opt_attr_num = -1; -static int hf_attr_class_attr_num = -1; -static int hf_attr_class_opt_service_num = -1; -static int hf_attr_class_service_code = -1; -static int hf_attr_class_num_class_attr = -1; -static int hf_attr_class_num_inst_attr = -1; +int hf_attr_class_revision = -1; +int hf_attr_class_max_instance = -1; +int hf_attr_class_num_instance = -1; +int hf_attr_class_opt_attr_num = -1; +int hf_attr_class_attr_num = -1; +int hf_attr_class_opt_service_num = -1; +int hf_attr_class_service_code = -1; +int hf_attr_class_num_class_attr = -1; +int hf_attr_class_num_inst_attr = -1; static int hf_cip_data = -1; static int hf_cip_service = -1; static int hf_cip_service_code = -1; @@ -314,6 +314,7 @@ static int hf_cip_reserved8 = -1; static int hf_cip_reserved24 = -1; static int hf_cip_pad8 = -1; +static int hf_cip_sc_get_attr_all_attr_item = -1; static int hf_cip_sc_get_attr_list_attr_count = -1; static int hf_cip_sc_get_attr_list_attr_item = -1; static int hf_cip_sc_get_attr_list_attr_status = -1; @@ -487,6 +488,7 @@ static gint ett_status_item = -1; static gint ett_add_status_item = -1; static gint ett_cmd_data = -1; +static gint ett_cip_get_attributes_all_item = -1; static gint ett_cip_get_attribute_list = -1; static gint ett_cip_get_attribute_list_item = -1; static gint ett_cip_set_attribute_list = -1; @@ -2530,7 +2532,7 @@ static const value_string cip_class_names_vals[] = { { 0xF3, "Connection Configuration Object" }, { 0xF4, "Port Object" }, { 0xF5, "TCP/IP Interface Object" }, - { 0xF6, "EtherNet Link Object" }, + { 0xF6, "Ethernet Link Object" }, { 0xF7, "CompoNet Object" }, { 0xF8, "CompoNet Repeater Object" }, @@ -3040,7 +3042,7 @@ static int dissect_time_sync_sys_time_and_offset(packet_info *pinfo, proto_tree return 16; } -static int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, +int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len) { guint32 i; @@ -3062,7 +3064,7 @@ static int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, prot return 2 + num_attr * 2; } -static int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, +int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len) { guint32 i; @@ -3087,61 +3089,96 @@ static int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, p static attribute_info_t cip_attribute_vals[] = { - /* Identity Object */ - {0x01, FALSE, 1, "Vendor ID", cip_uint, &hf_id_vendor_id, NULL}, - {0x01, FALSE, 2, "Device Type", cip_uint, &hf_id_device_type, NULL}, - {0x01, FALSE, 3, "Product Code", cip_uint, &hf_id_produce_code, NULL}, - {0x01, FALSE, 4, "Revision", cip_dissector_func, NULL, dissect_id_revision}, - {0x01, FALSE, 5, "Status", cip_word, &hf_id_status, NULL}, - {0x01, FALSE, 6, "Serial Number", cip_udint, &hf_id_serial_number, NULL}, - {0x01, FALSE, 7, "Product Name", cip_short_string, &hf_id_product_name, NULL}, + /* Identity Object (class attributes) */ + {0x01, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL }, + {0x01, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL }, + {0x01, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL }, + {0x01, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list }, + {0x01, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list }, + {0x01, TRUE, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL }, + {0x01, TRUE, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL }, - /* Message Router Object */ - {0x02, FALSE, 1, "Object List", cip_dissector_func, NULL, dissect_msg_rout_num_classes}, - {0x02, FALSE, 2, "Number Available", cip_uint, &hf_msg_rout_num_available, NULL}, - {0x02, FALSE, 3, "Number Active", cip_uint, &hf_msg_rout_num_active, NULL}, - {0x02, FALSE, 4, "Active Connections", cip_uint_array, &hf_msg_rout_active_connections, NULL}, + /* Identity Object (instance attributes) */ + {0x01, FALSE, 1, 0, "Vendor ID", cip_uint, &hf_id_vendor_id, NULL}, + {0x01, FALSE, 2, 1, "Device Type", cip_uint, &hf_id_device_type, NULL}, + {0x01, FALSE, 3, 2, "Product Code", cip_uint, &hf_id_produce_code, NULL}, + {0x01, FALSE, 4, 3, "Revision", cip_dissector_func, NULL, dissect_id_revision}, + {0x01, FALSE, 5, 4, "Status", cip_word, &hf_id_status, NULL}, + {0x01, FALSE, 6, 5, "Serial Number", cip_udint, &hf_id_serial_number, NULL}, + {0x01, FALSE, 7, 6, "Product Name", cip_short_string, &hf_id_product_name, NULL}, - /* Connection Manager Object */ - {0x06, FALSE, 1, "Open Requests", cip_uint, &hf_conn_mgr_open_requests, NULL}, - {0x06, FALSE, 2, "Open Format Rejects", cip_uint, &hf_conn_mgr_open_format_rejects, NULL}, - {0x06, FALSE, 3, "Open Resource Rejects", cip_uint, &hf_conn_mgr_open_resource_rejects, NULL}, - {0x06, FALSE, 4, "Other Open Rejects", cip_uint, &hf_conn_mgr_other_open_rejects, NULL}, - {0x06, FALSE, 5, "Close Requests", cip_uint, &hf_conn_mgr_close_requests, NULL}, - {0x06, FALSE, 6, "Close Format Requests", cip_uint, &hf_conn_close_format_requests, NULL}, - {0x06, FALSE, 7, "Close Other Requests", cip_uint, &hf_conn_mgr_close_other_requests, NULL}, - {0x06, FALSE, 8, "Connection Timeouts", cip_uint, &hf_conn_mgr_conn_timouts, NULL}, + /* Message Router Object (class attributes) */ + {0x02, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL }, + {0x02, TRUE, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL }, + {0x02, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL }, + {0x02, TRUE, 4, 1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list }, + {0x02, TRUE, 5, 2, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list }, + {0x02, TRUE, 6, 3, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL }, + {0x02, TRUE, 7, 4, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL }, - /* Time Sync Object */ - {0x43, FALSE, 1, "PTP Enable", cip_bool, &hf_time_sync_ptp_enable, NULL}, - {0x43, FALSE, 2, "Is Synchronized", cip_bool, &hf_time_sync_is_synchronized, NULL}, - {0x43, FALSE, 3, "System Time (Microseconds)", cip_ulint, &hf_time_sync_sys_time_micro, NULL}, - {0x43, FALSE, 4, "System Time (Nanoseconds)", cip_ulint, &hf_time_sync_sys_time_nano, NULL}, - {0x43, FALSE, 5, "Offset from Master", cip_lint, &hf_time_sync_offset_from_master, NULL}, - {0x43, FALSE, 6, "Max Offset from Master", cip_ulint, &hf_time_sync_max_offset_from_master, NULL}, - {0x43, FALSE, 7, "Mean Path Delay To Master", cip_lint, &hf_time_sync_mean_path_delay_to_master, NULL}, - {0x43, FALSE, 8, "Grand Master Clock Info", cip_dissector_func, NULL, dissect_time_sync_grandmaster_clock}, - {0x43, FALSE, 9, "Parent Clock Info", cip_dissector_func, NULL, dissect_time_sync_parent_clock}, - {0x43, FALSE, 10, "Local Clock Info", cip_dissector_func, NULL, dissect_time_sync_local_clock}, - {0x43, FALSE, 11, "Number of Ports", cip_uint, &hf_time_sync_num_ports, NULL}, - {0x43, FALSE, 12, "Port State Info", cip_dissector_func, NULL, dissect_time_sync_port_state_info}, - {0x43, FALSE, 13, "Port Enable Cfg", cip_dissector_func, NULL, dissect_time_sync_port_enable_cfg}, - {0x43, FALSE, 14, "Port Log Announcement Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_announce}, - {0x43, FALSE, 15, "Port Log Sync Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_sync}, - {0x43, FALSE, 16, "Priority1", cip_usint, &hf_time_sync_priority1, NULL}, - {0x43, FALSE, 17, "Priority2", cip_usint, &hf_time_sync_priority2, NULL}, - {0x43, FALSE, 18, "Domain number", cip_usint, &hf_time_sync_domain_number, NULL}, - {0x43, FALSE, 19, "Clock Type", cip_dissector_func, NULL, dissect_time_sync_clock_type}, - {0x43, FALSE, 20, "Manufacture Identity", cip_dissector_func, NULL, dissect_time_sync_manufacture_id}, - {0x43, FALSE, 21, "Product Description", cip_dissector_func, NULL, dissect_time_sync_prod_desc}, - {0x43, FALSE, 22, "Revision Data", cip_dissector_func, NULL, dissect_time_sync_revision_data}, - {0x43, FALSE, 23, "User Description", cip_dissector_func, NULL, dissect_time_sync_user_desc}, - {0x43, FALSE, 24, "Port Profile Identity Info", cip_dissector_func, NULL, dissect_time_sync_port_profile_id_info}, - {0x43, FALSE, 25, "Port Physical Address Info", cip_dissector_func, NULL, dissect_time_sync_port_phys_addr_info}, - {0x43, FALSE, 26, "Port Protocol Address Info", cip_dissector_func, NULL, dissect_time_sync_port_proto_addr_info}, - {0x43, FALSE, 27, "Steps Removed", cip_uint, &hf_time_sync_steps_removed, NULL}, - {0x43, FALSE, 28, "System Time and Offset", cip_dissector_func, NULL, dissect_time_sync_sys_time_and_offset}, + /* Message Router Object (instance attributes) */ + {0x02, FALSE, 1, 0, "Object List", cip_dissector_func, NULL, dissect_msg_rout_num_classes}, + {0x02, FALSE, 2, 1, "Number Available", cip_uint, &hf_msg_rout_num_available, NULL}, + {0x02, FALSE, 3, 2, "Number Active", cip_uint, &hf_msg_rout_num_active, NULL}, + {0x02, FALSE, 4, 3, "Active Connections", cip_uint_array, &hf_msg_rout_active_connections, NULL}, + /* Connection Manager Object (class attributes) */ + {0x06, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL }, + {0x06, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL }, + {0x06, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL }, + {0x06, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list }, + {0x06, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list }, + {0x06, TRUE, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL }, + {0x06, TRUE, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL }, + + /* Connection Manager Object (instance attributes) */ + {0x06, FALSE, 1, 0, "Open Requests", cip_uint, &hf_conn_mgr_open_requests, NULL}, + {0x06, FALSE, 2, 1, "Open Format Rejects", cip_uint, &hf_conn_mgr_open_format_rejects, NULL}, + {0x06, FALSE, 3, 2, "Open Resource Rejects", cip_uint, &hf_conn_mgr_open_resource_rejects, NULL}, + {0x06, FALSE, 4, 3, "Other Open Rejects", cip_uint, &hf_conn_mgr_other_open_rejects, NULL}, + {0x06, FALSE, 5, 4, "Close Requests", cip_uint, &hf_conn_mgr_close_requests, NULL}, + {0x06, FALSE, 6, 5, "Close Format Requests", cip_uint, &hf_conn_close_format_requests, NULL}, + {0x06, FALSE, 7, 6, "Close Other Requests", cip_uint, &hf_conn_mgr_close_other_requests, NULL}, + {0x06, FALSE, 8, 7, "Connection Timeouts", cip_uint, &hf_conn_mgr_conn_timouts, NULL}, + + /* Time Sync Object (class attributes) */ + {0x43, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL }, + {0x43, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL }, + {0x43, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL }, + {0x43, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list }, + {0x43, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list }, + {0x43, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL }, + {0x43, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL }, + + /* Time Sync Object (instance attributes) */ + {0x43, FALSE, 1, -1, "PTP Enable", cip_bool, &hf_time_sync_ptp_enable, NULL}, + {0x43, FALSE, 2, -1, "Is Synchronized", cip_bool, &hf_time_sync_is_synchronized, NULL}, + {0x43, FALSE, 3, -1, "System Time (Microseconds)", cip_ulint, &hf_time_sync_sys_time_micro, NULL}, + {0x43, FALSE, 4, -1, "System Time (Nanoseconds)", cip_ulint, &hf_time_sync_sys_time_nano, NULL}, + {0x43, FALSE, 5, -1, "Offset from Master", cip_lint, &hf_time_sync_offset_from_master, NULL}, + {0x43, FALSE, 6, -1, "Max Offset from Master", cip_ulint, &hf_time_sync_max_offset_from_master, NULL}, + {0x43, FALSE, 7, -1, "Mean Path Delay To Master", cip_lint, &hf_time_sync_mean_path_delay_to_master, NULL}, + {0x43, FALSE, 8, -1, "Grand Master Clock Info", cip_dissector_func, NULL, dissect_time_sync_grandmaster_clock}, + {0x43, FALSE, 9, -1, "Parent Clock Info", cip_dissector_func, NULL, dissect_time_sync_parent_clock}, + {0x43, FALSE, 10, -1, "Local Clock Info", cip_dissector_func, NULL, dissect_time_sync_local_clock}, + {0x43, FALSE, 11, -1, "Number of Ports", cip_uint, &hf_time_sync_num_ports, NULL}, + {0x43, FALSE, 12, -1, "Port State Info", cip_dissector_func, NULL, dissect_time_sync_port_state_info}, + {0x43, FALSE, 13, -1, "Port Enable Cfg", cip_dissector_func, NULL, dissect_time_sync_port_enable_cfg}, + {0x43, FALSE, 14, -1, "Port Log Announcement Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_announce}, + {0x43, FALSE, 15, -1, "Port Log Sync Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_sync}, + {0x43, FALSE, 16, -1, "Priority1", cip_usint, &hf_time_sync_priority1, NULL}, + {0x43, FALSE, 17, -1, "Priority2", cip_usint, &hf_time_sync_priority2, NULL}, + {0x43, FALSE, 18, -1, "Domain number", cip_usint, &hf_time_sync_domain_number, NULL}, + {0x43, FALSE, 19, -1, "Clock Type", cip_dissector_func, NULL, dissect_time_sync_clock_type}, + {0x43, FALSE, 20, -1, "Manufacture Identity", cip_dissector_func, NULL, dissect_time_sync_manufacture_id}, + {0x43, FALSE, 21, -1, "Product Description", cip_dissector_func, NULL, dissect_time_sync_prod_desc}, + {0x43, FALSE, 22, -1, "Revision Data", cip_dissector_func, NULL, dissect_time_sync_revision_data}, + {0x43, FALSE, 23, -1, "User Description", cip_dissector_func, NULL, dissect_time_sync_user_desc}, + {0x43, FALSE, 24, -1, "Port Profile Identity Info", cip_dissector_func, NULL, dissect_time_sync_port_profile_id_info}, + {0x43, FALSE, 25, -1, "Port Physical Address Info", cip_dissector_func, NULL, dissect_time_sync_port_phys_addr_info}, + {0x43, FALSE, 26, -1, "Port Protocol Address Info", cip_dissector_func, NULL, dissect_time_sync_port_proto_addr_info}, + {0x43, FALSE, 27, -1, "Steps Removed", cip_uint, &hf_time_sync_steps_removed, NULL}, + {0x43, FALSE, 28, -1, "System Time and Offset", cip_dissector_func, NULL, dissect_time_sync_sys_time_and_offset}, }; typedef struct attribute_val_array { @@ -3149,22 +3186,19 @@ typedef struct attribute_val_array { attribute_info_t* attrs; } attribute_val_array_t; +/* Each entry in this table (eg: cip_attribute_vals) is a list of: + Attribute information (class_id/class_instance/attribute) to attribute property + + Note: If more items are added to the individual tables, it may make sense + to switch to a more efficient implementation (eg: hash table). +*/ + static attribute_val_array_t all_attribute_vals[] = { {sizeof(cip_attribute_vals)/sizeof(attribute_info_t), cip_attribute_vals}, {sizeof(enip_attribute_vals)/sizeof(attribute_info_t), enip_attribute_vals}, {sizeof(cip_safety_attribute_vals)/sizeof(attribute_info_t), cip_safety_attribute_vals} }; -attribute_info_t class_attribute_vals[] = { - { 0, TRUE, 1, "Revision", cip_uint, &hf_attr_class_revision, NULL }, - { 0, TRUE, 2, "Max Instance", cip_uint, &hf_attr_class_max_instance, NULL }, - { 0, TRUE, 3, "Number of Instances", cip_uint, &hf_attr_class_num_instance, NULL }, - { 0, TRUE, 4, "Optional Attribute List", cip_dissector_func, NULL, dissect_optional_attr_list }, - { 0, TRUE, 5, "Optional Service List", cip_dissector_func, NULL, dissect_optional_service_list }, - { 0, TRUE, 6, "Maximum ID Number Class Attributes", cip_uint, &hf_attr_class_num_class_attr, NULL }, - { 0, TRUE, 7, "Maximum ID Number Instance Attributes", cip_uint, &hf_attr_class_num_inst_attr, NULL }, -}; - static void dissect_cip_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, packet_info *pinfo, cip_req_info_t *preq_info ); @@ -3174,6 +3208,16 @@ attribute_info_t* cip_get_attribute(guint class_id, guint instance, guint attrib attribute_val_array_t* att_array; attribute_info_t* pattr; + static attribute_info_t class_attribute_vals[] = { + { 0, TRUE, 1, -1, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL }, + { 0, TRUE, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL }, + { 0, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL }, + { 0, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list }, + { 0, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list }, + { 0, TRUE, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL }, + { 0, TRUE, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL }, + }; + for (i = 0; i < sizeof(all_attribute_vals)/sizeof(attribute_val_array_t); i++) { att_array = &all_attribute_vals[i]; @@ -4587,6 +4631,134 @@ dissect_cip_generic_service_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t return tvb_reported_length(tvb); } +typedef struct cip_gaa_key { + guint32 cip_class; + gboolean class_instance; +} cip_gaa_key_t; + +typedef struct cip_gaa_val { + GList *attributes; +} cip_gaa_val_t; + +static wmem_map_t *cip_gaa_hashtable = NULL; + +static guint +cip_gaa_hash (gconstpointer v) +{ + const cip_gaa_key_t *key = (const cip_gaa_key_t *)v; + guint val; + + val = (guint)((key->cip_class << 1) & 0xFFFFFFFE); + val |= (key->class_instance & 1); + + return val; +} + +static gint +cip_gaa_equal(gconstpointer v, gconstpointer w) +{ + const cip_gaa_key_t *v1 = (const cip_gaa_key_t *)v; + const cip_gaa_key_t *v2 = (const cip_gaa_key_t *)w; + + if ((v1->cip_class == v2->cip_class) && + (v1->class_instance == v2->class_instance)) + return 1; + + return 0; +} + +static void build_get_attr_all_table(void) +{ + size_t i, j; + attribute_val_array_t* att_array; + attribute_info_t* pattr; + cip_gaa_key_t key; + cip_gaa_key_t* new_key; + cip_gaa_val_t *gaa_val; + int last_attribute_index = -1; + + cip_gaa_hashtable = wmem_map_new(wmem_epan_scope(), cip_gaa_hash, cip_gaa_equal); + + for (i = 0; i < sizeof(all_attribute_vals)/sizeof(attribute_val_array_t); i++) + { + att_array = &all_attribute_vals[i]; + for (j = 0; j < att_array->size; j++) + { + pattr = &att_array->attrs[j]; + key.cip_class = pattr->class_id; + key.class_instance = pattr->class_instance; + + gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key ); + if (gaa_val == NULL) + { + new_key = (cip_gaa_key_t*)wmem_memdup(wmem_epan_scope(), &key, sizeof(cip_gaa_key_t)); + gaa_val = wmem_new0(wmem_epan_scope(), cip_gaa_val_t); + + wmem_map_insert(cip_gaa_hashtable, new_key, gaa_val ); + last_attribute_index = -1; + } + + if ((pattr->gaa_index >= 0) && (pattr->gaa_index > last_attribute_index)) + { + gaa_val->attributes = g_list_append(gaa_val->attributes, pattr); + last_attribute_index = pattr->gaa_index; + } + } + } +} + +static void +dissect_cip_get_attribute_all_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + int offset, cip_simple_request_info_t* req_data) +{ + int att_size; + gint len_remain; + attribute_info_t* attr; + proto_item *att_item; + proto_tree *att_tree; + cip_gaa_key_t key; + cip_gaa_val_t *gaa_val; + GList *attribute_list; + + key.cip_class = req_data->iClass; + key.class_instance = (req_data->iInstance == 0); + + gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key ); + if (gaa_val == NULL) + { + proto_tree_add_item(tree, hf_cip_sc_get_attribute_all_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); + return; + } + + for (attribute_list = g_list_first(gaa_val->attributes); + (attribute_list != NULL); + attribute_list = g_list_next(attribute_list)) + { + attr = (attribute_info_t *)attribute_list->data; + len_remain = tvb_reported_length_remaining(tvb, offset); + + /* If there are no more attributes defined or there is no data left. */ + if (attr == NULL || len_remain <= 0) + break; + + att_item = proto_tree_add_uint_format_value(tree, hf_cip_sc_get_attr_all_attr_item, + tvb, offset, 0, 0, "%d (%s)", attr->attribute, attr->text); + att_tree = proto_item_add_subtree(att_item, ett_cip_get_attributes_all_item); + + att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, len_remain); + offset += att_size; + + proto_item_set_len(att_item, att_size); + } + + /* Add whatever is left as raw data. */ + len_remain = tvb_reported_length_remaining(tvb, offset); + if (len_remain > 0) + { + proto_tree_add_item(tree, hf_cip_sc_get_attribute_all_data, tvb, offset, len_remain, ENC_NA); + } +} + static void dissect_cip_get_attribute_list_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item, int offset, cip_simple_request_info_t* req_data) @@ -4875,7 +5047,7 @@ dissect_cip_generic_service_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t switch(service) { case SC_GET_ATT_ALL: - proto_tree_add_item(cmd_data_tree, hf_cip_sc_get_attribute_all_data, tvb, offset+4+add_stat_size, tvb_reported_length_remaining(tvb, offset+4+add_stat_size), ENC_NA); + dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset+4+add_stat_size, &req_data); break; case SC_SET_ATT_ALL: proto_tree_add_item(cmd_data_tree, hf_cip_sc_set_attribute_all_data, tvb, offset+4+add_stat_size, tvb_reported_length_remaining(tvb, offset+4+add_stat_size), ENC_NA); @@ -6663,6 +6835,7 @@ proto_register_cip(void) { &hf_cip_reserved24, { "Reserved", "cip.reserved", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL }}, { &hf_cip_pad8, { "Pad Byte", "cip.pad", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }}, + { &hf_cip_sc_get_attr_all_attr_item, { "Attribute", "cip.getall.attr_item", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_cip_sc_get_attr_list_attr_count, { "Attribute Count", "cip.getlist.attr_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_cip_sc_get_attr_list_attr_item, { "Attribute", "cip.getlist.attr_item", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_cip_sc_get_attr_list_attr_status, { "General Status", "cip.getlist.attr_status", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }}, @@ -6986,6 +7159,7 @@ proto_register_cip(void) &ett_cip_seg_safety_ounid_ssn, &ett_status_item, &ett_add_status_item, + &ett_cip_get_attributes_all_item, &ett_cip_get_attribute_list, &ett_cip_get_attribute_list_item, &ett_cip_set_attribute_list, @@ -7136,6 +7310,7 @@ proto_register_cip(void) * can override the dissector for common services */ heur_subdissector_service = register_heur_dissector_list("cip.sc"); + build_get_attr_all_table(); } /* end of proto_register_cip() */ diff --git a/epan/dissectors/packet-cip.h b/epan/dissectors/packet-cip.h index 76c4556570..817e37a744 100644 --- a/epan/dissectors/packet-cip.h +++ b/epan/dissectors/packet-cip.h @@ -28,6 +28,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifndef PACKET_CIP_H +#define PACKET_CIP_H + /* CIP Service Codes */ #define SC_GET_ATT_ALL 0x01 #define SC_SET_ATT_ALL 0x02 @@ -191,8 +194,8 @@ /* Define common services */ #define GENERIC_SC_LIST \ - { SC_GET_ATT_ALL, "Get Attribute All" }, \ - { SC_SET_ATT_ALL, "Set Attribute All" }, \ + { SC_GET_ATT_ALL, "Get Attributes All" }, \ + { SC_SET_ATT_ALL, "Set Attributes All" }, \ { SC_GET_ATT_LIST, "Get Attribute List" }, \ { SC_SET_ATT_LIST, "Set Attribute List" }, \ { SC_RESET, "Reset" }, \ @@ -264,6 +267,7 @@ typedef struct attribute_info { guint class_id; gboolean class_instance; guint attribute; + int gaa_index; /* Index of attribute in GetAttributeAll response (< 0 means not in GetAttrbuteAll */ const char *text; enum cip_datatype datatype; int* phf; @@ -328,6 +332,31 @@ extern value_string_ext cip_vendor_vals_ext; extern value_string_ext cip_devtype_vals_ext; extern value_string_ext cip_class_names_vals_ext; +/* Common class attributes and attribute dissection functions*/ +extern int hf_attr_class_revision; +extern int hf_attr_class_max_instance; +extern int hf_attr_class_num_instance; +extern int hf_attr_class_opt_attr_num; +extern int hf_attr_class_attr_num; +extern int hf_attr_class_opt_service_num; +extern int hf_attr_class_service_code; +extern int hf_attr_class_num_class_attr; +extern int hf_attr_class_num_inst_attr; + +#define CLASS_ATTRIBUTE_1_NAME "Revision" +#define CLASS_ATTRIBUTE_2_NAME "Max Instance" +#define CLASS_ATTRIBUTE_3_NAME "Number of Instances" +#define CLASS_ATTRIBUTE_4_NAME "Optional Attribute List" +#define CLASS_ATTRIBUTE_5_NAME "Optional Service List" +#define CLASS_ATTRIBUTE_6_NAME "Maximum ID Number Class Attributes" +#define CLASS_ATTRIBUTE_7_NAME "Maximum ID Number Instance Attributes" + +extern int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, + int offset, int total_len); +extern int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, + int offset, int total_len); + + /* * Editor modelines * @@ -340,3 +369,5 @@ extern value_string_ext cip_class_names_vals_ext; * ex: set shiftwidth=3 tabstop=8 expandtab: * :indentSize=3:tabSize=8:noTabs=true: */ + +#endif /* PACKET_CIP_H */ diff --git a/epan/dissectors/packet-cipsafety.c b/epan/dissectors/packet-cipsafety.c index ea7f029526..927d8eec03 100644 --- a/epan/dissectors/packet-cipsafety.c +++ b/epan/dissectors/packet-cipsafety.c @@ -236,10 +236,6 @@ static int hf_cip_sercosiii_link_sercos_address = -1; static int hf_cip_sercosiii_link_error_count_p1 = -1; static int hf_cip_sercosiii_link_error_count_p2 = -1; -static int hf_tcpip_snn_timestamp = -1; -static int hf_tcpip_snn_date = -1; -static int hf_tcpip_snn_time = -1; - /* Initialize the subtree pointers */ static gint ett_cip_safety = -1; static gint ett_path = -1; @@ -291,7 +287,6 @@ static expert_field ei_cipsafety_tbd_not_copied = EI_INIT; static expert_field ei_cipsafety_run_idle_not_complemented = EI_INIT; static expert_field ei_mal_io = EI_INIT; static expert_field ei_mal_sercosiii_link_error_count_p1p2 = EI_INIT; -static expert_field ei_mal_tcpip_ssn = EI_INIT; static expert_field ei_mal_ssupervisor_exception_detail_alarm_ced = EI_INIT; static expert_field ei_mal_ssupervisor_exception_detail_alarm_ded = EI_INIT; @@ -1633,80 +1628,64 @@ static int dissect_sercosiii_link_error_count_p1p2(packet_info *pinfo, proto_tre return 4; } -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; -} - -attribute_info_t cip_safety_attribute_vals[52] = { +attribute_info_t cip_safety_attribute_vals[51] = { /* Safety Supervisor */ - {0x39, TRUE, 99, "Subclass", cip_uint, &hf_cip_ssupervisor_class_subclass, NULL}, - {0x39, FALSE, 1, "Number of Attributes", cip_usint, &hf_cip_ssupervisor_num_attr, NULL}, - {0x39, FALSE, 2, "Attribute List", cip_usint_array, &hf_cip_ssupervisor_attr_list, NULL}, - {0x39, FALSE, 5, "Manufacturer Name", cip_short_string, &hf_cip_ssupervisor_manufacture_name, NULL}, - {0x39, FALSE, 6, "Manufacturer Model Number", cip_short_string, &hf_cip_ssupervisor_manufacture_model_number, NULL}, - {0x39, FALSE, 7, "Software Revision Level", cip_short_string, &hf_cip_ssupervisor_sw_rev_level, NULL}, - {0x39, FALSE, 8, "Hardware Revision Level", cip_short_string, &hf_cip_ssupervisor_hw_rev_level, NULL}, - {0x39, FALSE, 9, "Manufacturer Serial Number", cip_short_string, &hf_cip_ssupervisor_manufacture_serial_number, NULL}, - {0x39, FALSE, 10, "Device Configuration", cip_short_string, &hf_cip_ssupervisor_device_config, NULL}, - {0x39, FALSE, 11, "Device Status", cip_usint, &hf_cip_ssupervisor_device_status, NULL}, - {0x39, FALSE, 12, "Exception Status", cip_byte, &hf_cip_ssupervisor_exception_status, NULL}, - {0x39, FALSE, 13, "Exception Detail Alarm", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_alarm}, - {0x39, FALSE, 14, "Exception Detail Warning", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_warning}, - {0x39, FALSE, 15, "Alarm Enable", cip_bool, &hf_cip_ssupervisor_alarm_enable, NULL}, - {0x39, FALSE, 16, "Warning Enable", cip_bool, &hf_cip_ssupervisor_warning_enable, NULL}, - {0x39, FALSE, 17, "Time", cip_date_and_time, &hf_cip_ssupervisor_time, NULL}, - {0x39, FALSE, 18, "Clock Power Cycle Behavior", cip_usint, &hf_cip_ssupervisor_clock_power_cycle_behavior, NULL}, - {0x39, FALSE, 19, "Last Maintenance Date", cip_date, &hf_cip_ssupervisor_last_maintenance_date, NULL}, - {0x39, FALSE, 20, "Next Scheduled Maintenance Date", cip_date, &hf_cip_ssupervisor_next_scheduled_maintenance_date, NULL}, - {0x39, FALSE, 21, "Scheduled Maintenance Expiration Timer", cip_int, &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer, NULL}, - {0x39, FALSE, 22, "Scheduled Maintenance Expiration Warning Enable", cip_bool, &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable, NULL}, - {0x39, FALSE, 23, "Run Hours", cip_udint, &hf_cip_ssupervisor_run_hours, NULL}, - {0x39, FALSE, 24, "Configuration Lock", cip_bool, &hf_cip_ssupervisor_configuration_lock, NULL}, - {0x39, FALSE, 25, "Configuration UNID", cip_dissector_func, NULL, dissect_s_supervisor_configuration_unid}, - {0x39, FALSE, 26, "Safety Configuration Identifier", cip_dissector_func, NULL, dissect_s_supervisor_safety_configuration_id}, - {0x39, FALSE, 27, "Target UNID", cip_dissector_func, NULL, dissect_s_supervisor_target_unid}, - {0x39, FALSE, 28, "Output Connection Point Owners", cip_dissector_func, NULL, dissect_s_supervisor_output_connection_point_owners}, - {0x39, FALSE, 29, "Proposed TUNID", cip_dissector_func, NULL, dissect_s_supervisor_proposed_tunid}, - {0x39, FALSE, 99, "Subclass", cip_uint, &hf_cip_ssupervisor_instance_subclass, NULL}, + {0x39, TRUE, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_class_subclass, NULL}, + {0x39, FALSE, 1, -1, "Number of Attributes", cip_usint, &hf_cip_ssupervisor_num_attr, NULL}, + {0x39, FALSE, 2, -1, "Attribute List", cip_usint_array, &hf_cip_ssupervisor_attr_list, NULL}, + {0x39, FALSE, 5, -1, "Manufacturer Name", cip_short_string, &hf_cip_ssupervisor_manufacture_name, NULL}, + {0x39, FALSE, 6, -1, "Manufacturer Model Number", cip_short_string, &hf_cip_ssupervisor_manufacture_model_number, NULL}, + {0x39, FALSE, 7, -1, "Software Revision Level", cip_short_string, &hf_cip_ssupervisor_sw_rev_level, NULL}, + {0x39, FALSE, 8, -1, "Hardware Revision Level", cip_short_string, &hf_cip_ssupervisor_hw_rev_level, NULL}, + {0x39, FALSE, 9, -1, "Manufacturer Serial Number", cip_short_string, &hf_cip_ssupervisor_manufacture_serial_number, NULL}, + {0x39, FALSE, 10, -1, "Device Configuration", cip_short_string, &hf_cip_ssupervisor_device_config, NULL}, + {0x39, FALSE, 11, -1, "Device Status", cip_usint, &hf_cip_ssupervisor_device_status, NULL}, + {0x39, FALSE, 12, -1, "Exception Status", cip_byte, &hf_cip_ssupervisor_exception_status, NULL}, + {0x39, FALSE, 13, -1, "Exception Detail Alarm", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_alarm}, + {0x39, FALSE, 14, -1, "Exception Detail Warning", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_warning}, + {0x39, FALSE, 15, -1, "Alarm Enable", cip_bool, &hf_cip_ssupervisor_alarm_enable, NULL}, + {0x39, FALSE, 16, -1, "Warning Enable", cip_bool, &hf_cip_ssupervisor_warning_enable, NULL}, + {0x39, FALSE, 17, -1, "Time", cip_date_and_time, &hf_cip_ssupervisor_time, NULL}, + {0x39, FALSE, 18, -1, "Clock Power Cycle Behavior", cip_usint, &hf_cip_ssupervisor_clock_power_cycle_behavior, NULL}, + {0x39, FALSE, 19, -1, "Last Maintenance Date", cip_date, &hf_cip_ssupervisor_last_maintenance_date, NULL}, + {0x39, FALSE, 20, -1, "Next Scheduled Maintenance Date", cip_date, &hf_cip_ssupervisor_next_scheduled_maintenance_date, NULL}, + {0x39, FALSE, 21, -1, "Scheduled Maintenance Expiration Timer", cip_int, &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer, NULL}, + {0x39, FALSE, 22, -1, "Scheduled Maintenance Expiration Warning Enable", cip_bool, &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable, NULL}, + {0x39, FALSE, 23, -1, "Run Hours", cip_udint, &hf_cip_ssupervisor_run_hours, NULL}, + {0x39, FALSE, 24, -1, "Configuration Lock", cip_bool, &hf_cip_ssupervisor_configuration_lock, NULL}, + {0x39, FALSE, 25, -1, "Configuration UNID", cip_dissector_func, NULL, dissect_s_supervisor_configuration_unid}, + {0x39, FALSE, 26, -1, "Safety Configuration Identifier", cip_dissector_func, NULL, dissect_s_supervisor_safety_configuration_id}, + {0x39, FALSE, 27, -1, "Target UNID", cip_dissector_func, NULL, dissect_s_supervisor_target_unid}, + {0x39, FALSE, 28, -1, "Output Connection Point Owners", cip_dissector_func, NULL, dissect_s_supervisor_output_connection_point_owners}, + {0x39, FALSE, 29, -1, "Proposed TUNID", cip_dissector_func, NULL, dissect_s_supervisor_proposed_tunid}, + {0x39, FALSE, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_instance_subclass, NULL}, /* Safety Validator */ - {0x3A, TRUE, 8, "Safety Connection Fault Count", cip_uint, &hf_cip_svalidator_sconn_fault_count, NULL}, - {0x3A, FALSE, 1, "Safety Validator State", cip_usint, &hf_cip_svalidator_state, NULL}, - {0x3A, FALSE, 2, "Safety Validator Type", cip_dissector_func, NULL, dissect_s_validator_type}, - {0x3A, FALSE, 3, "Ping Interval ERI Multiplier", cip_uint, &hf_cip_svalidator_ping_eri, NULL}, - {0x3A, FALSE, 4, "Time Coord Msg Min Multiplier", cip_dissector_func, NULL, dissect_s_validator_time_coord_msg_min_mult}, - {0x3A, FALSE, 5, "Network Time Expectation Multiplier", cip_dissector_func, NULL, dissect_s_validator_network_time_multiplier}, - {0x3A, FALSE, 6, "Timeout Multiplier", cip_dissector_func, NULL, dissect_s_validator_timeout_multiplier}, - {0x3A, FALSE, 7, "Max Consumer Number", cip_usint, &hf_cip_svalidator_max_consumer_num, NULL}, - {0x3A, FALSE, 8, "Data Connection Instance", cip_uint, &hf_cip_svalidator_data_conn_inst, NULL}, - {0x3A, FALSE, 9, "Coordination Connection Instance", cip_dissector_func, NULL, dissect_s_validator_coordination_conn_inst}, - {0x3A, FALSE, 10, "Correction Connection Instance", cip_uint, &hf_cip_svalidator_correction_conn_inst, NULL}, - {0x3A, FALSE, 11, "CCO Binding", cip_uint, &hf_cip_svalidator_cco_binding, NULL}, - {0x3A, FALSE, 12, "Max Data Age", cip_uint, &hf_cip_svalidator_max_data_age, NULL}, - {0x3A, FALSE, 13, "Application Data Path", cip_dissector_func, NULL, dissect_s_validator_app_data_path}, - {0x3A, FALSE, 14, "Error Code", cip_uint, &hf_cip_svalidator_error_code, NULL}, - {0x3A, FALSE, 15, "Producer/Consumer Fault Counters", cip_dissector_func, NULL, dissect_s_validator_prod_cons_fault_count}, + {0x3A, TRUE, 8, -1, "Safety Connection Fault Count", cip_uint, &hf_cip_svalidator_sconn_fault_count, NULL}, + {0x3A, FALSE, 1, 0, "Safety Validator State", cip_usint, &hf_cip_svalidator_state, NULL}, + {0x3A, FALSE, 2, 1, "Safety Validator Type", cip_dissector_func, NULL, dissect_s_validator_type}, + {0x3A, FALSE, 3, 2, "Ping Interval ERI Multiplier", cip_uint, &hf_cip_svalidator_ping_eri, NULL}, + {0x3A, FALSE, 4, 3, "Time Coord Msg Min Multiplier", cip_dissector_func, NULL, dissect_s_validator_time_coord_msg_min_mult}, + {0x3A, FALSE, 5, 4, "Network Time Expectation Multiplier", cip_dissector_func, NULL, dissect_s_validator_network_time_multiplier}, + {0x3A, FALSE, 6, 5, "Timeout Multiplier", cip_dissector_func, NULL, dissect_s_validator_timeout_multiplier}, + {0x3A, FALSE, 7, 6, "Max Consumer Number", cip_usint, &hf_cip_svalidator_max_consumer_num, NULL}, + {0x3A, FALSE, 8, 7, "Data Connection Instance", cip_uint, &hf_cip_svalidator_data_conn_inst, NULL}, + {0x3A, FALSE, 9, 8, "Coordination Connection Instance", cip_dissector_func, NULL, dissect_s_validator_coordination_conn_inst}, + {0x3A, FALSE, 10, 9, "Correction Connection Instance", cip_uint, &hf_cip_svalidator_correction_conn_inst, NULL}, + {0x3A, FALSE, 11, 10, "CCO Binding", cip_uint, &hf_cip_svalidator_cco_binding, NULL}, + {0x3A, FALSE, 12, 11, "Max Data Age", cip_uint, &hf_cip_svalidator_max_data_age, NULL}, + {0x3A, FALSE, 13, 12, "Application Data Path", cip_dissector_func, NULL, dissect_s_validator_app_data_path}, + {0x3A, FALSE, 14, 13, "Error Code", cip_uint, &hf_cip_svalidator_error_code, NULL}, + {0x3A, FALSE, 15, -1, "Producer/Consumer Fault Counters", cip_dissector_func, NULL, dissect_s_validator_prod_cons_fault_count}, /* Sercos III Link */ - {0x4C, FALSE, 1, "Safety Network Number", cip_byte_array, &hf_cip_sercosiii_link_snn, NULL}, - {0x4C, FALSE, 2, "Communication Cycle Time", cip_dint, &hf_cip_sercosiii_link_communication_cycle_time, NULL}, - {0x4C, FALSE, 3, "Interface Status", cip_word, &hf_cip_sercosiii_link_interface_status, NULL}, - {0x4C, FALSE, 4, "Error counter MST-P/S", cip_int, &hf_cip_sercosiii_link_error_count_mstps, NULL}, - {0x4C, FALSE, 5, "Error counter Port1 and Port2", cip_dissector_func, NULL, dissect_sercosiii_link_error_count_p1p2}, - {0x4C, FALSE, 6, "SERCOS address", cip_int, &hf_cip_sercosiii_link_sercos_address, NULL}, - - /* TCP/IP object (CIP-Safety specific) */ - {0xF5, FALSE, 7, "Safety Network Number", cip_dissector_func, NULL, dissect_tcpip_ssn} + {0x4C, FALSE, 1, -1, "Safety Network Number", cip_byte_array, &hf_cip_sercosiii_link_snn, NULL}, + {0x4C, FALSE, 2, -1, "Communication Cycle Time", cip_dint, &hf_cip_sercosiii_link_communication_cycle_time, NULL}, + {0x4C, FALSE, 3, -1, "Interface Status", cip_word, &hf_cip_sercosiii_link_interface_status, NULL}, + {0x4C, FALSE, 4, -1, "Error counter MST-P/S", cip_int, &hf_cip_sercosiii_link_error_count_mstps, NULL}, + {0x4C, FALSE, 5, -1, "Error counter Port1 and Port2", cip_dissector_func, NULL, dissect_sercosiii_link_error_count_p1p2}, + {0x4C, FALSE, 6, -1, "SERCOS address", cip_int, &hf_cip_sercosiii_link_sercos_address, NULL}, }; /* @@ -1899,19 +1878,6 @@ proto_register_cipsafety(void) { "SERCOS Address", "cipsafety.sercosiii_link.sercos_address", FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL } }, - - { &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 } - }, }; static hf_register_info hf_ssupervisor[] = { @@ -2526,7 +2492,6 @@ proto_register_cipsafety(void) { &ei_cipsafety_run_idle_not_complemented, { "cipsafety.run_idle_not_complemented", PI_PROTOCOL, PI_WARN, "Run/Idle bit not complemented", EXPFILL }}, { &ei_mal_io, { "cipsafety.malformed.io", PI_MALFORMED, PI_ERROR, "Malformed CIP Safety I/O packet", EXPFILL }}, { &ei_mal_sercosiii_link_error_count_p1p2, { "cipsafety.malformed.sercosiii_link.error_count_p1p2", PI_MALFORMED, PI_ERROR, "Malformed SERCOS III Attribute 5", EXPFILL }}, - { &ei_mal_tcpip_ssn, { "cip.malformed.tcpip.ssn", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Object Safety Network Number", EXPFILL }}, }; static ei_register_info ei_ssupervisor[] = { diff --git a/epan/dissectors/packet-cipsafety.h b/epan/dissectors/packet-cipsafety.h index 84f8afcec3..b17ffa1805 100644 --- a/epan/dissectors/packet-cipsafety.h +++ b/epan/dissectors/packet-cipsafety.h @@ -64,6 +64,6 @@ extern void dissect_cipsafety_ssn(proto_tree *tree, tvbuff_t *tvb, packet_info * ** Exported variables */ extern const value_string cipsafety_ssn_date_vals[8]; -extern attribute_info_t cip_safety_attribute_vals[52]; +extern attribute_info_t cip_safety_attribute_vals[51]; #endif /* PACKET_CIPSAFETY_H */ diff --git a/epan/dissectors/packet-enip.c b/epan/dissectors/packet-enip.c index d4dda663d2..b1a29b57de 100644 --- a/epan/dissectors/packet-enip.c +++ b/epan/dissectors/packet-enip.c @@ -180,6 +180,9 @@ 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; +static int hf_tcpip_snn_timestamp = -1; +static int hf_tcpip_snn_date = -1; +static int hf_tcpip_snn_time = -1; static int hf_tcpip_ttl_value = -1; static int hf_tcpip_mcast_alloc = -1; static int hf_tcpip_mcast_reserved = -1; @@ -190,6 +193,7 @@ 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; +static int hf_tcpip_encap_inactivity = -1; static int hf_elink_interface_flags = -1; static int hf_elink_iflags_link_status = -1; @@ -303,6 +307,7 @@ static expert_field ei_mal_tcpip_physical_link_size = 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; +static expert_field ei_mal_tcpip_ssn = EI_INIT; static expert_field ei_mal_elink_interface_flags = EI_INIT; static expert_field ei_mal_elink_physical_address = EI_INIT; static expert_field ei_mal_elink_interface_counters = EI_INIT; @@ -1390,6 +1395,19 @@ dissect_tcpip_interface_config(packet_info *pinfo, proto_tree *tree, proto_item return (22+domain_length); } +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; +} + static int dissect_tcpip_mcast_config(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int total_len) @@ -1711,60 +1729,98 @@ dissect_dlr_active_gateway_address(packet_info *pinfo, proto_tree *tree, proto_i return 10; } -attribute_info_t enip_attribute_vals[45] = { +attribute_info_t enip_attribute_vals[75] = { - /* TCP/IP object */ - {0xF5, FALSE, 1, "Status", cip_dissector_func, NULL, dissect_tcpip_status}, - {0xF5, FALSE, 2, "Configuration Capability", cip_dissector_func, NULL, dissect_tcpip_config_cap}, - {0xF5, FALSE, 3, "Configuration Control", cip_dissector_func, NULL, dissect_tcpip_config_control}, - {0xF5, FALSE, 4, "Physical Link Object", cip_dissector_func, NULL, dissect_tcpip_physical_link}, - {0xF5, FALSE, 5, "Interface Configuration", cip_dissector_func, NULL, dissect_tcpip_interface_config}, - {0xF5, FALSE, 6, "Host Name", cip_string, &hf_tcpip_hostname, NULL}, - {0xF5, FALSE, 8, "TTL Value", cip_usint, &hf_tcpip_ttl_value, NULL}, - {0xF5, FALSE, 9, "Multicast Configuration", cip_dissector_func, NULL, dissect_tcpip_mcast_config}, - {0xF5, FALSE, 10, "Select ACD", cip_bool, &hf_tcpip_select_acd, NULL}, - {0xF5, FALSE, 11, "Last Conflict Detected", cip_dissector_func, NULL, dissect_tcpip_last_conflict}, - {0xF5, FALSE, 12, "EtherNet/IP Quick Connect", cip_bool, &hf_tcpip_quick_connect, NULL}, + /* 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 }, - /* Ethernet Link object */ - {0xF6, FALSE, 1, "Interface Speed", cip_dword, &hf_elink_interface_speed, NULL}, - {0xF6, FALSE, 2, "Interface Flags", cip_dissector_func, NULL, dissect_elink_interface_flags}, - {0xF6, FALSE, 3, "Physical Address", cip_dissector_func, NULL, dissect_elink_physical_address }, - {0xF6, FALSE, 4, "Interface Counters", cip_dissector_func, NULL, dissect_elink_interface_counters}, - {0xF6, FALSE, 5, "Media Counters", cip_dissector_func, NULL, dissect_elink_media_counters}, - {0xF6, FALSE, 6, "Interface Control", cip_dissector_func, NULL, dissect_elink_interface_control}, - {0xF6, FALSE, 7, "Interface Type", cip_usint, &hf_elink_interface_type, NULL}, - {0xF6, FALSE, 8, "Interface State", cip_usint, &hf_elink_interface_state, NULL}, - {0xF6, FALSE, 9, "Admin State", cip_usint, &hf_elink_admin_state, NULL}, - {0xF6, FALSE, 10, "Interface Label", cip_short_string, &hf_elink_interface_label, 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}, + {0xF5, FALSE, 6, 5, "Host Name", cip_string, &hf_tcpip_hostname, NULL}, + {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}, - /* QoS object */ - {0x48, FALSE, 1, "802.1Q Tag Enable", cip_bool, &hf_qos_8021q_enable, NULL}, - {0x48, FALSE, 2, "DSCP PTP Event", cip_usint, &hf_qos_dscp_ptp_event, NULL}, - {0x48, FALSE, 3, "DSCP PTP General", cip_usint, &hf_qos_dscp_ptp_general, NULL}, - {0x48, FALSE, 4, "DSCP Urgent", cip_usint, &hf_qos_dscp_urgent, NULL}, - {0x48, FALSE, 5, "DSCP Scheduled", cip_usint, &hf_qos_dscp_scheduled, NULL}, - {0x48, FALSE, 6, "DSCP High", cip_usint, &hf_qos_dscp_high, NULL}, - {0x48, FALSE, 7, "DSCP Low", cip_usint, &hf_qos_dscp_low, NULL}, - {0x48, FALSE, 8, "DSCP Explicit", cip_usint, &hf_qos_dscp_explicit, 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 }, - /* DLR object */ - {0x47, FALSE, 1, "Network Topology", cip_usint, &hf_dlr_network_topology, NULL}, - {0x47, FALSE, 2, "Network Status", cip_usint, &hf_dlr_network_status, NULL}, - {0x47, FALSE, 3, "Ring Supervisor Status", cip_usint, &hf_dlr_ring_supervisor_status, NULL}, - {0x47, FALSE, 4, "Ring Supervisor Config", cip_dissector_func, NULL, dissect_dlr_ring_supervisor_config}, - {0x47, FALSE, 5, "Ring Faults Count", cip_uint, &hf_dlr_ring_faults_count, NULL}, - {0x47, FALSE, 6, "Last Active Node on Port 1", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_1}, - {0x47, FALSE, 7, "Last Active Node on Port 2", cip_dissector_func, NULL, dissect_dlr_last_active_node_on_port_2}, - {0x47, FALSE, 8, "Ring Protocol Participants Count", cip_uint, &hf_dlr_ring_protocol_participants_count, NULL}, - {0x47, FALSE, 9, "Ring Protocol Participants List", cip_dissector_func, NULL, dissect_dlr_ring_protocol_participants_list}, - {0x47, FALSE, 10, "Active Supervisor Address", cip_dissector_func, NULL, dissect_dlr_active_supervisor_address}, - {0x47, FALSE, 11, "Active Supervisor Precedence", cip_usint, &hf_dlr_active_supervisor_precedence, NULL}, - {0x47, FALSE, 12, "Capability Flags", cip_dissector_func, NULL, dissect_dlr_capability_flags}, - {0x47, FALSE, 13, "Redundant Gateway Config", cip_dissector_func, NULL, dissect_dlr_redundant_gateway_config}, - {0x47, FALSE, 14, "Redundant Gateway Status", cip_usint, &hf_dlr_redundant_gateway_status, NULL}, - {0x47, FALSE, 15, "Active Gateway Address", cip_dissector_func, NULL, dissect_dlr_active_gateway_address}, - {0x47, FALSE, 16, "Active Gateway Precedence", cip_usint, &hf_dlr_active_gateway_precedence, 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) */ + {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}, }; @@ -2970,6 +3026,24 @@ proto_register_enip(void) FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, + { &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 } + }, + { &hf_tcpip_ttl_value, { "TTL Value", "cip.tcpip.ttl_value", FT_UINT8, BASE_DEC, NULL, 0, @@ -3020,6 +3094,10 @@ proto_register_enip(void) FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x1, NULL, HFILL }}, + { &hf_tcpip_encap_inactivity, + { "Encapsulation Inactivity Timeout", "cip.tcpip.encap_inactivity", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, { &hf_elink_interface_speed, { "Interface Speed", "cip.elink.interface_speed", @@ -3474,6 +3552,7 @@ proto_register_enip(void) { &ei_mal_tcpip_config_control, { "cip.malformed.tcpip.config_control", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Configuration Control", EXPFILL }}, { &ei_mal_tcpip_physical_link_size, { "cip.malformed.tcpip.physical_link_size", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Physical Link Object", EXPFILL }}, { &ei_mal_tcpip_interface_config, { "cip.malformed.tcpip.interface_config", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Interface Configuration", EXPFILL }}, + { &ei_mal_tcpip_ssn, { "cip.malformed.tcpip.ssn", PI_MALFORMED, PI_ERROR, "Malformed TCP/IP Object Safety Network Number", EXPFILL }}, { &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 }}, diff --git a/epan/dissectors/packet-enip.h b/epan/dissectors/packet-enip.h index 4b5ab0bb13..22ceaaee62 100644 --- a/epan/dissectors/packet-enip.h +++ b/epan/dissectors/packet-enip.h @@ -112,6 +112,6 @@ enum enip_connid_type {ECIDT_UNKNOWN, ECIDT_O2T, ECIDT_T2O}; void enip_close_cip_connection( packet_info *pinfo, guint16 ConnSerialNumber, guint16 VendorID, guint32 DeviceSerialNumber ); void enip_mark_connection_triad( packet_info *pinfo, guint16 ConnSerialNumber, guint16 VendorID, guint32 DeviceSerialNumber ); -extern attribute_info_t enip_attribute_vals[45]; +extern attribute_info_t enip_attribute_vals[75]; #endif /* PACKET_ENIP_H */