wireshark/epan/dissectors/packet-cipsafety.c
D. Ulis 8cdc182aff CIP: Attribute updates
1. Switched to common way to parse Get Attr All, using dissect_cip_get_attribute_all_rsp, for CCO (class version) and CIP Validator. This also fixed a missing attribute in the old CIP Validator code.
2. Add cip_string2 attribute implementation
3. For CIP Validator, set the protocol as "CIPS Validator", previously this was "CIPS Supervisor".
4. For classes with subdissectors, add the service to the Info column in the response.

Change-Id: Id9593ca39497261075df8146cf63ee9581462e2a
Reviewed-on: https://code.wireshark.org/review/14837
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
2016-04-07 06:14:45 +00:00

2570 lines
119 KiB
C

/* packet-cipsafety.c
* Routines for CIP (Common Industrial Protocol) Safety dissection
* CIP Safety Home: www.odva.org
*
* Copyright 2011
* Michael Mann <mmann@pyramidsolutions.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/proto_data.h>
#include <wsutil/pint.h>
#include "packet-cip.h"
#include "packet-cipsafety.h"
void proto_register_cipsafety(void);
void proto_reg_handoff_cipsafety(void);
/* The entry point to the actual dissection is: dissect_cipsafety */
/* Protocol handle for CIP Safety */
static int proto_cipsafety = -1;
static int proto_cip_class_s_supervisor = -1;
static int proto_cip_class_s_validator = -1;
static int proto_cip = -1;
static dissector_table_t subdissector_class_table;
static dissector_handle_t cip_class_s_validator_handle;
/* CIP Safety field identifiers */
static int hf_cipsafety_data = -1;
static int hf_cipsafety_mode_byte = -1;
static int hf_cipsafety_mode_byte_run_idle = -1;
static int hf_cipsafety_mode_byte_not_run_idle = -1;
static int hf_cipsafety_mode_byte_tbd_2_bit = -1;
static int hf_cipsafety_mode_byte_tbd_2_copy = -1;
static int hf_cipsafety_mode_byte_ping_count = -1;
static int hf_cipsafety_mode_byte_tbd = -1;
static int hf_cipsafety_mode_byte_not_tbd = -1;
static int hf_cipsafety_crc_s1 = -1;
static int hf_cipsafety_crc_s2 = -1;
static int hf_cipsafety_crc_s3 = -1;
static int hf_cipsafety_timestamp = -1;
static int hf_cipsafety_ack_byte = -1;
static int hf_cipsafety_ack_byte_ping_count_reply = -1;
static int hf_cipsafety_ack_byte_reserved1 = -1;
static int hf_cipsafety_ack_byte_ping_response = -1;
static int hf_cipsafety_ack_byte_reserved2 = -1;
static int hf_cipsafety_ack_byte_parity_even = -1;
static int hf_cipsafety_ack_byte2 = -1;
static int hf_cipsafety_consumer_time_value = -1;
static int hf_cipsafety_mcast_byte = -1;
static int hf_cipsafety_mcast_byte_consumer_num = -1;
static int hf_cipsafety_mcast_byte_reserved1 = -1;
static int hf_cipsafety_mcast_byte_mai = -1;
static int hf_cipsafety_mcast_byte_reserved2 = -1;
static int hf_cipsafety_mcast_byte_parity_even = -1;
static int hf_cipsafety_mcast_byte2 = -1;
static int hf_cipsafety_time_correction = -1;
static int hf_cipsafety_crc_s5_0 = -1;
static int hf_cipsafety_crc_s5_1 = -1;
static int hf_cipsafety_crc_s5_2 = -1;
static int hf_cipsafety_complement_data = -1;
/* CIP Safety header field identifiers */
static int hf_cip_reqrsp = -1;
static int hf_cip_data = -1;
/* Safety Supervisor header field identifiers */
static int hf_cip_ssupervisor_sc = -1;
static int hf_cip_ssupervisor_recover_data = -1;
static int hf_cip_ssupervisor_perform_diag_data = -1;
static int hf_cip_ssupervisor_configure_request_password = -1;
static int hf_cip_ssupervisor_configure_request_tunid = -1;
static int hf_cip_ssupervisor_configure_request_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_configure_request_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_configure_request_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_configure_request_tunid_macid = -1;
static int hf_cip_ssupervisor_configure_request_ounid = -1;
static int hf_cip_ssupervisor_configure_request_ounid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_configure_request_ounid_ssn_date = -1;
static int hf_cip_ssupervisor_configure_request_ounid_ssn_time = -1;
static int hf_cip_ssupervisor_configure_request_ounid_macid = -1;
static int hf_cip_ssupervisor_validate_configuration_sccrc = -1;
static int hf_cip_ssupervisor_validate_configuration_scts_timestamp = -1;
static int hf_cip_ssupervisor_validate_configuration_scts_date = -1;
static int hf_cip_ssupervisor_validate_configuration_scts_time = -1;
static int hf_cip_ssupervisor_validate_configuration_ext_error = -1;
static int hf_cip_ssupervisor_set_password_current_password = -1;
static int hf_cip_ssupervisor_set_password_new_password = -1;
static int hf_cip_ssupervisor_configure_lock_value = -1;
static int hf_cip_ssupervisor_configure_lock_password = -1;
static int hf_cip_ssupervisor_configure_lock_tunid = -1;
static int hf_cip_ssupervisor_configure_lock_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_configure_lock_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_configure_lock_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_configure_lock_tunid_macid = -1;
static int hf_cip_ssupervisor_mode_change_value = -1;
static int hf_cip_ssupervisor_mode_change_password = -1;
static int hf_cip_ssupervisor_reset_type = -1;
static int hf_cip_ssupervisor_reset_password = -1;
static int hf_cip_ssupervisor_reset_tunid = -1;
static int hf_cip_ssupervisor_reset_tunid_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_reset_tunid_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_reset_tunid_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_reset_tunid_macid = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_macid = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_baudrate = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_tunid = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_password = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_cfunid = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_ocpunid = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_reserved = -1;
static int hf_cip_ssupervisor_reset_attr_bitmap_extended = -1;
static int hf_cip_ssupervisor_reset_password_data_size = -1;
static int hf_cip_ssupervisor_reset_password_data = -1;
static int hf_cip_ssupervisor_propose_tunid_tunid = -1;
static int hf_cip_ssupervisor_propose_tunid_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_propose_tunid_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_propose_tunid_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_propose_tunid_tunid_macid = -1;
static int hf_cip_ssupervisor_apply_tunid_tunid = -1;
static int hf_cip_ssupervisor_apply_tunid_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_apply_tunid_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_apply_tunid_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_apply_tunid_tunid_macid = -1;
static int hf_cip_ssupervisor_class_subclass = -1;
static int hf_cip_ssupervisor_num_attr = -1;
static int hf_cip_ssupervisor_attr_list = -1;
static int hf_cip_ssupervisor_manufacture_name = -1;
static int hf_cip_ssupervisor_manufacture_model_number = -1;
static int hf_cip_ssupervisor_sw_rev_level = -1;
static int hf_cip_ssupervisor_hw_rev_level = -1;
static int hf_cip_ssupervisor_manufacture_serial_number = -1;
static int hf_cip_ssupervisor_device_config = -1;
static int hf_cip_ssupervisor_device_status = -1;
static int hf_cip_ssupervisor_exception_status = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_ced_size = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_ced_detail = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_ded_size = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_ded_detail = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_med_size = -1;
static int hf_cip_ssupervisor_exception_detail_alarm_med_detail = -1;
static int hf_cip_ssupervisor_exception_detail_warning_ced_size = -1;
static int hf_cip_ssupervisor_exception_detail_warning_ced_detail = -1;
static int hf_cip_ssupervisor_exception_detail_warning_ded_size = -1;
static int hf_cip_ssupervisor_exception_detail_warning_ded_detail = -1;
static int hf_cip_ssupervisor_exception_detail_warning_med_size = -1;
static int hf_cip_ssupervisor_exception_detail_warning_med_detail = -1;
static int hf_cip_ssupervisor_alarm_enable = -1;
static int hf_cip_ssupervisor_warning_enable = -1;
static int hf_cip_ssupervisor_time = -1;
static int hf_cip_ssupervisor_clock_power_cycle_behavior = -1;
static int hf_cip_ssupervisor_last_maintenance_date = -1;
static int hf_cip_ssupervisor_next_scheduled_maintenance_date = -1;
static int hf_cip_ssupervisor_scheduled_maintenance_expiration_timer = -1;
static int hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable = -1;
static int hf_cip_ssupervisor_run_hours = -1;
static int hf_cip_ssupervisor_configuration_lock = -1;
static int hf_cip_ssupervisor_configuration_unid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_configuration_unid_ssn_date = -1;
static int hf_cip_ssupervisor_configuration_unid_ssn_time = -1;
static int hf_cip_ssupervisor_configuration_unid_macid = -1;
static int hf_cip_ssupervisor_safety_configuration_id_ssn_timestamp = -1;
static int hf_cip_ssupervisor_safety_configuration_id_ssn_date = -1;
static int hf_cip_ssupervisor_safety_configuration_id_ssn_time = -1;
static int hf_cip_ssupervisor_safety_configuration_id_macid = -1;
static int hf_cip_ssupervisor_target_unid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_target_unid_ssn_date = -1;
static int hf_cip_ssupervisor_target_unid_ssn_time = -1;
static int hf_cip_ssupervisor_target_unid_macid = -1;
static int hf_cip_ssupervisor_cp_owners_num_entries = -1;
static int hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_date = -1;
static int hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_time = -1;
static int hf_cip_ssupervisor_output_cp_owners_ocpunid_macid = -1;
static int hf_cip_ssupervisor_cp_owners_app_path_size = -1;
static int hf_cip_ssupervisor_proposed_tunid_ssn_timestamp = -1;
static int hf_cip_ssupervisor_proposed_tunid_ssn_date = -1;
static int hf_cip_ssupervisor_proposed_tunid_ssn_time = -1;
static int hf_cip_ssupervisor_proposed_tunid_macid = -1;
static int hf_cip_ssupervisor_instance_subclass = -1;
/* Safety Validator header field identifiers */
static int hf_cip_svalidator_sc = -1;
static int hf_cip_svalidator_sconn_fault_count = -1;
static int hf_cip_svalidator_state = -1;
static int hf_cip_svalidator_type = -1;
static int hf_cip_svalidator_type_pc = -1;
static int hf_cip_svalidator_type_conn_type = -1;
static int hf_cip_svalidator_ping_eri = -1;
static int hf_cip_svalidator_time_coord_msg_min_mult_size = -1;
static int hf_cip_svalidator_time_coord_msg_min_mult_item = -1;
static int hf_cip_svalidator_network_time_multiplier_size = -1;
static int hf_cip_svalidator_network_time_multiplier_item = -1;
static int hf_cip_svalidator_timeout_multiplier_size = -1;
static int hf_cip_svalidator_timeout_multiplier_item = -1;
static int hf_cip_svalidator_max_consumer_num = -1;
static int hf_cip_svalidator_data_conn_inst = -1;
static int hf_cip_svalidator_coordination_conn_inst_size = -1;
static int hf_cip_svalidator_coordination_conn_inst_item = -1;
static int hf_cip_svalidator_correction_conn_inst = -1;
static int hf_cip_svalidator_cco_binding = -1;
static int hf_cip_svalidator_max_data_age = -1;
static int hf_cip_svalidator_error_code = -1;
static int hf_cip_svalidator_prod_cons_fault_count_size = -1;
static int hf_cip_svalidator_prod_cons_fault_count_item = -1;
static int hf_cip_sercosiii_link_snn = -1;
static int hf_cip_sercosiii_link_communication_cycle_time = -1;
static int hf_cip_sercosiii_link_interface_status = -1;
static int hf_cip_sercosiii_link_error_count_mstps = -1;
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;
/* Initialize the subtree pointers */
static gint ett_cip_safety = -1;
static gint ett_path = -1;
static gint ett_cipsafety_mode_byte = -1;
static gint ett_cipsafety_ack_byte = -1;
static gint ett_cipsafety_mcast_byte = -1;
static gint ett_cip_class_s_supervisor = -1;
static gint ett_ssupervisor_rrsc = -1;
static gint ett_ssupervisor_cmd_data = -1;
static gint ett_ssupervisor_propose_tunid = -1;
static gint ett_ssupervisor_propose_tunid_ssn = -1;
static gint ett_ssupervisor_configure_request_tunid = -1;
static gint ett_ssupervisor_configure_request_tunid_ssn = -1;
static gint ett_ssupervisor_configure_request_ounid = -1;
static gint ett_ssupervisor_configure_request_ounid_ssn = -1;
static gint ett_ssupervisor_configure_lock_tunid = -1;
static gint ett_ssupervisor_configure_lock_tunid_ssn = -1;
static gint ett_ssupervisor_reset_tunid = -1;
static gint ett_ssupervisor_reset_tunid_ssn = -1;
static gint ett_ssupervisor_apply_tunid = -1;
static gint ett_ssupervisor_apply_tunid_ssn = -1;
static gint ett_exception_detail_alarm_common = -1;
static gint ett_exception_detail_alarm_device = -1;
static gint ett_exception_detail_alarm_manufacturer = -1;
static gint ett_exception_detail_warning_common = -1;
static gint ett_exception_detail_warning_device = -1;
static gint ett_exception_detail_warning_manufacturer = -1;
static gint ett_ssupervisor_configuration_unid = -1;
static gint ett_ssupervisor_configuration_unid_ssn = -1;
static gint ett_ssupervisor_safety_configuration_id = -1;
static gint ett_ssupervisor_safety_configuration_id_ssn = -1;
static gint ett_ssupervisor_target_unid = -1;
static gint ett_ssupervisor_target_unid_ssn = -1;
static gint ett_ssupervisor_output_cp_owners = -1;
static gint ett_ssupervisor_output_cp_owners_ocpunid = -1;
static gint ett_ssupervisor_output_cp_owners_ocpunid_ssn = -1;
static gint ett_ssupervisor_proposed_tunid = -1;
static gint ett_ssupervisor_proposed_tunid_ssn = -1;
static gint ett_cip_ssupervisor_reset_attr_bitmap = -1;
static gint ett_cip_class_s_validator = -1;
static gint ett_svalidator_rrsc = -1;
static gint ett_svalidator_cmd_data = -1;
static gint ett_svalidator_type = -1;
static expert_field ei_cipsafety_tbd2_not_complemented = EI_INIT;
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_ssupervisor_exception_detail_alarm_ced = EI_INIT;
static expert_field ei_mal_ssupervisor_exception_detail_alarm_ded = EI_INIT;
static expert_field ei_mal_ssupervisor_exception_detail_alarm_med = EI_INIT;
static expert_field ei_mal_ssupervisor_detail_warning_ced = EI_INIT;
static expert_field ei_mal_ssupervisor_detail_warning_ded = EI_INIT;
static expert_field ei_mal_ssupervisor_detail_warning_med = EI_INIT;
static expert_field ei_mal_ssupervisor_configuration_unid = EI_INIT;
static expert_field ei_mal_ssupervisor_safety_configuration_id = EI_INIT;
static expert_field ei_mal_ssupervisor_target_unid = EI_INIT;
static expert_field ei_mal_ssupervisor_cp_owners = EI_INIT;
static expert_field ei_mal_ssupervisor_cp_owners_entry = EI_INIT;
static expert_field ei_mal_ssupervisor_cp_owners_app_path_size = EI_INIT;
static expert_field ei_mal_ssupervisor_proposed_tunid = EI_INIT;
static expert_field ei_mal_svalidator_type = EI_INIT;
static expert_field ei_mal_svalidator_time_coord_msg_min_mult = EI_INIT;
static expert_field ei_mal_svalidator_network_time_multiplier = EI_INIT;
static expert_field ei_mal_svalidator_timeout_multiplier = EI_INIT;
static expert_field ei_mal_svalidator_coordination_conn_inst = EI_INIT;
static expert_field ei_mal_svalidator_prod_cons_fault_count = EI_INIT;
static dissector_handle_t cipsafety_handle;
const value_string cipsafety_ssn_date_vals[8] = {
{ 0, "NULL SSN" },
{ 1, "Manual Setting - Backplane" },
{ 2, "Manual Setting - ControlNet" },
{ 4, "Manual Setting - EtherNet/IP" },
{ 5, "Manual Setting - DeviceNet" },
{ 6, "Manual Setting - SERCOS III" },
{ 65535, "No SSN Set" },
{ 0, NULL }
};
static const true_false_string cip_safety_vals_active_idle = {
"Idle",
"Active"
};
/* Translate function to string - CIP Service codes for Safety Supervisor */
static const value_string cip_sc_vals_ssupervisor[] = {
GENERIC_SC_LIST
/* Some class specific services */
{ SC_SSUPER_RECOVER, "Recover" },
{ SC_SSUPER_PERFORM_DIAGNOSTICS, "Perform Diagnostics" },
{ SC_SSUPER_CONFIGURE_REQUEST, "Configure Request" },
{ SC_SSUPER_VALIDATE_CONFIGURATION, "Validate Configuration" },
{ SC_SSUPER_SET_PASSWORD, "Set Password" },
{ SC_SSUPER_CONFIGURATION_LOCK, "Configuration (Un)Lock" },
{ SC_SSUPER_MODE_CHANGE, "Mode Change" },
{ SC_SSUPER_SAFETY_RESET, "Safety Reset" },
{ SC_SSUPER_RESET_PASSWORD, "Reset Password" },
{ SC_SSUPER_PROPOSE_TUNID, "Propose TUNID" },
{ SC_SSUPER_APPLY_TUNID, "Apply TUNID" },
{ 0, NULL }
};
#define SC_SVALID_RESET_ERROR 0x4B
/* Translate function to string - CIP Service codes for Safety Validator */
static const value_string cip_sc_vals_svalidator[] = {
GENERIC_SC_LIST
/* Some class specific services */
{ SC_SVALID_RESET_ERROR, "Reset Error" },
{ 0, NULL }
};
static const value_string cip_ssupervisor_validate_configuration_ext_error_vals[] = {
{ 1, "CRC mismatch" },
{ 2, "Invalid Configuration Parameter" },
{ 3, "TUNID Not Set" },
{ 0, NULL }
};
static const value_string cip_ssupervisor_lock_vals[] = {
{ 0, "Unlocked" },
{ 1, "Locked" },
{ 0, NULL }
};
static const value_string cip_ssupervisor_change_mode_vals[] = {
{ 0, "Idle" },
{ 1, "Executing" },
{ 0, NULL }
};
static const value_string cip_ssupervisor_device_status_type_vals[] = {
{ 0, "Undefined" },
{ 1, "Self-Testing" },
{ 2, "Idle" },
{ 3, "Self-Testing Exception" },
{ 4, "Executing" },
{ 5, "Abort" },
{ 6, "Critical Fault" },
{ 7, "Configuring" },
{ 8, "Waiting for TUNID" },
{ 0, NULL }
};
static const value_string cip_ssupervisor_clock_power_cycle_type_vals[] = {
{ 0, "Clock always resets" },
{ 1, "Clock in NVS at power down" },
{ 2, "Clock is battery-backed" },
{ 0, NULL }
};
static const value_string cip_svalidator_state_vals[] = {
{ 0, "Unallocated" },
{ 1, "Initializing" },
{ 2, "Established" },
{ 3, "Connection failed" },
{ 0, NULL }
};
static const value_string cip_svalidator_type_pc_vals[] = {
{ 0, "Producer" },
{ 1, "Consumer" },
{ 0, NULL }
};
static const value_string cip_svalidator_type_conn_type_vals[] = {
{ 0, "Unallocated" },
{ 1, "Single-cast" },
{ 2, "Multi-cast" },
{ 0, NULL }
};
void
dissect_unid(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_item *pi,
const char* ssn_name, int hf_ssn_timestamp,
int hf_ssn_date, int hf_ssn_time, int hf_macid, gint ett, gint ett_ssn)
{
proto_tree *tree, *ssn_tree;
tree = proto_item_add_subtree(pi, ett);
ssn_tree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_ssn, NULL, ssn_name);
dissect_cipsafety_ssn(ssn_tree, tvb, pinfo, offset, hf_ssn_timestamp, hf_ssn_date, hf_ssn_time);
proto_tree_add_item(tree, hf_macid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
}
void dissect_cipsafety_ssn(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
int hf_real_datetime, int hf_date, int hf_time)
{
guint16 date;
date = tvb_get_letohs( tvb, offset);
if ((date >= 11688) && (date <= 65534))
{
/* value is an actual timestamp */
dissect_cip_date_and_time(tree, tvb, offset, hf_real_datetime);
}
else
{
/* Treated as UINT16 and UINT32 values */
proto_tree_add_item(tree, hf_date, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_time, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
}
}
/************************************************
*
* Dissector for CIP Safety Supervisor Object
*
************************************************/
static void
dissect_cip_s_supervisor_data( proto_tree *item_tree,
tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
{
proto_item *pi, *rrsc_item;
proto_tree *rrsc_tree, *cmd_data_tree, *bitmap_tree;
int req_path_size;
int temp_data;
guint8 service, gen_status, add_stat_size;
cip_req_info_t* preq_info;
cip_simple_request_info_t req_data;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Supervisor");
/* Add Service code & Request/Response tree */
service = tvb_get_guint8( tvb, offset );
rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_ssupervisor_rrsc, &rrsc_item, "Service: " );
/* Add Request/Response */
proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
proto_item_append_text( rrsc_item, "%s (%s)",
val_to_str( ( service & 0x7F ), cip_sc_vals_ssupervisor , "Unknown Service (0x%02x)"),
val_to_str_const( ( service & 0x80 )>>7, cip_sc_rr, "") );
/* Add Service code */
proto_tree_add_item(rrsc_tree, hf_cip_ssupervisor_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
if ((preq_info != NULL) &&
(preq_info->ciaData != NULL))
{
memcpy(&req_data, preq_info->ciaData, sizeof(cip_simple_request_info_t));
}
else
{
req_data.iClass = (guint32)-1;
req_data.iInstance = (guint32)-1;
req_data.iAttribute = (guint32)-1;
req_data.iMember = (guint32)-1;
}
if(service & 0x80 )
{
/* Response message */
/* Add additional status size */
gen_status = tvb_get_guint8( tvb, offset+2 );
add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
/* If there is any command specific data create a sub-tree for it */
if( ( item_length-4-add_stat_size ) != 0 )
{
cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size,
item_length-4-add_stat_size, ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
if( gen_status == CI_GRC_SUCCESS || gen_status == CI_GRC_SERVICE_ERROR )
{
switch (service & 0x7F)
{
case SC_SSUPER_VALIDATE_CONFIGURATION:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
tvb, offset+4+add_stat_size, 4, ENC_LITTLE_ENDIAN);
dissect_cipsafety_ssn(cmd_data_tree,
tvb, pinfo, offset+4+add_stat_size+4,
hf_cip_ssupervisor_validate_configuration_scts_timestamp,
hf_cip_ssupervisor_validate_configuration_scts_date,
hf_cip_ssupervisor_validate_configuration_scts_time);
break;
}
}
else if ((gen_status == 0xD0) && ((service & 0x7F) == SC_SSUPER_VALIDATE_CONFIGURATION))
{
if (add_stat_size > 0)
{
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_ext_error,
tvb, offset+4, 2, ENC_LITTLE_ENDIAN);
}
}
else
{
/* Error responses */
/* Add data */
proto_tree_add_item(cmd_data_tree, hf_cip_data,
tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
}
}
} /* End of if reply */
else
{
/* Request message */
req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
/* If there is any command specific data create a sub-tree for it */
if( (item_length-req_path_size-2) != 0 )
{
cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
/* Check what service code that received */
switch (service)
{
case SC_SSUPER_RECOVER:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_recover_data,
tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
break;
case SC_SSUPER_PERFORM_DIAGNOSTICS:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_perform_diag_data,
tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
break;
case SC_SSUPER_CONFIGURE_REQUEST:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_password,
tvb, offset+2+req_path_size, 16, ENC_NA);
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_tunid,
tvb, offset+2+req_path_size+16, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "TUNID SSN",
hf_cip_ssupervisor_configure_request_tunid_ssn_timestamp,
hf_cip_ssupervisor_configure_request_tunid_ssn_date,
hf_cip_ssupervisor_configure_request_tunid_ssn_time,
hf_cip_ssupervisor_configure_request_tunid_macid,
ett_ssupervisor_configure_request_tunid,
ett_ssupervisor_configure_request_tunid_ssn);
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_ounid,
tvb, offset+2+req_path_size+26, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "OUNID SSN",
hf_cip_ssupervisor_configure_request_ounid_ssn_timestamp,
hf_cip_ssupervisor_configure_request_ounid_ssn_date,
hf_cip_ssupervisor_configure_request_ounid_ssn_time,
hf_cip_ssupervisor_configure_request_ounid_macid,
ett_ssupervisor_configure_request_ounid,
ett_ssupervisor_configure_request_ounid_ssn);
break;
case SC_SSUPER_VALIDATE_CONFIGURATION:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
tvb, offset+2+req_path_size, 4, ENC_LITTLE_ENDIAN);
dissect_cipsafety_ssn(cmd_data_tree, tvb, pinfo, offset+2+req_path_size+4,
hf_cip_ssupervisor_validate_configuration_scts_timestamp,
hf_cip_ssupervisor_validate_configuration_scts_date,
hf_cip_ssupervisor_validate_configuration_scts_time);
break;
case SC_SSUPER_SET_PASSWORD:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_current_password,
tvb, offset+2+req_path_size, 16, ENC_NA);
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_new_password,
tvb, offset+2+req_path_size+16, 16, ENC_NA);
break;
case SC_SSUPER_CONFIGURATION_LOCK:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_value,
tvb, offset+2+req_path_size+1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_password,
tvb, offset+2+req_path_size+1, 16, ENC_NA);
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_tunid,
tvb, offset+2+req_path_size+17, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size+17, pi, "TUNID SSN",
hf_cip_ssupervisor_configure_lock_tunid_ssn_timestamp,
hf_cip_ssupervisor_configure_lock_tunid_ssn_date,
hf_cip_ssupervisor_configure_lock_tunid_ssn_time,
hf_cip_ssupervisor_configure_lock_tunid_macid,
ett_ssupervisor_configure_lock_tunid,
ett_ssupervisor_configure_lock_tunid_ssn);
break;
case SC_SSUPER_MODE_CHANGE:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_value,
tvb, offset+2+req_path_size+1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_password,
tvb, offset+2+req_path_size+1, 16, ENC_NA);
break;
case SC_SSUPER_SAFETY_RESET:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_type,
tvb, offset+2+req_path_size+1, 1, ENC_LITTLE_ENDIAN);
temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+1 );
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password,
tvb, offset+2+req_path_size+1, 16, ENC_NA);
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_tunid,
tvb, offset+2+req_path_size+17, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size+17, pi, "TUNID SSN",
hf_cip_ssupervisor_reset_tunid_tunid_ssn_timestamp,
hf_cip_ssupervisor_reset_tunid_tunid_ssn_date,
hf_cip_ssupervisor_reset_tunid_tunid_ssn_time,
hf_cip_ssupervisor_reset_tunid_macid,
ett_ssupervisor_reset_tunid,
ett_ssupervisor_reset_tunid_ssn);
/* Attribute bitmap only included on Reset Type 2 */
if (temp_data == 2)
{
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_attr_bitmap,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
bitmap_tree = proto_item_add_subtree(pi, ett_cip_ssupervisor_reset_attr_bitmap);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_macid,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_baudrate,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_tunid,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_password,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_cfunid,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_ocpunid,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_reserved,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_extended,
tvb, offset+2+req_path_size+27, 1, ENC_LITTLE_ENDIAN);
}
break;
case SC_SSUPER_RESET_PASSWORD:
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data_size,
tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
temp_data = tvb_get_guint8(tvb, offset+2+req_path_size);
proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data,
tvb, offset+2+req_path_size+1, temp_data, ENC_NA);
break;
case SC_SSUPER_PROPOSE_TUNID:
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_propose_tunid_tunid,
tvb, offset+2+req_path_size, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SSN",
hf_cip_ssupervisor_propose_tunid_tunid_ssn_timestamp,
hf_cip_ssupervisor_propose_tunid_tunid_ssn_date,
hf_cip_ssupervisor_propose_tunid_tunid_ssn_time,
hf_cip_ssupervisor_propose_tunid_tunid_macid,
ett_ssupervisor_propose_tunid,
ett_ssupervisor_propose_tunid_ssn);
break;
case SC_SSUPER_APPLY_TUNID:
pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_apply_tunid_tunid,
tvb, offset+2+req_path_size, 10, ENC_NA);
dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SSN",
hf_cip_ssupervisor_apply_tunid_tunid_ssn_timestamp,
hf_cip_ssupervisor_apply_tunid_tunid_ssn_date,
hf_cip_ssupervisor_apply_tunid_tunid_ssn_time,
hf_cip_ssupervisor_apply_tunid_tunid_macid,
ett_ssupervisor_apply_tunid,
ett_ssupervisor_apply_tunid_ssn);
break;
default:
proto_tree_add_item(cmd_data_tree, hf_cip_data,
tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
}
} /* End of if command-specific data present */
} /* End of if-else( request ) */
add_cip_service_to_info_column(pinfo, service, cip_sc_vals_ssupervisor);
}
static int
dissect_cip_class_s_supervisor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *ti;
proto_tree *class_tree;
/* Create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_cip_class_s_supervisor, tvb, 0, -1, ENC_NA);
class_tree = proto_item_add_subtree( ti, ett_cip_class_s_supervisor );
dissect_cip_s_supervisor_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
return tvb_reported_length(tvb);
}
static int dissect_s_supervisor_exception_detail(proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int hf_size, int hf_data)
{
int size;
proto_tree_add_item(tree, hf_size, tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset);
proto_tree_add_item(tree, hf_data, tvb, offset+1, size, ENC_NA );
proto_item_set_len(item, size+1);
return size+1;
}
static int dissect_s_supervisor_exception_detail_alarm(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
int offset, int total_len)
{
proto_item *pi;
proto_tree *item_tree;
int total_size = 0, size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_alarm_common, &pi, "Common Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_alarm_ced_size,
hf_cip_ssupervisor_exception_detail_alarm_ced_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_alarm_ced);
return total_len;
}
total_size += size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_alarm_device, &pi, "Device Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_alarm_ded_size,
hf_cip_ssupervisor_exception_detail_alarm_ded_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_alarm_ded);
return total_len;
}
total_size += size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_alarm_manufacturer, &pi, "Manufacturer Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_alarm_med_size,
hf_cip_ssupervisor_exception_detail_alarm_med_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_alarm_med);
return total_len;
}
total_size += size;
return total_size;
}
static int dissect_s_supervisor_exception_detail_warning(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
proto_item *pi;
proto_tree *item_tree;
int total_size = 0, size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_warning_common, &pi, "Common Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_warning_ced_size,
hf_cip_ssupervisor_exception_detail_warning_ced_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_detail_warning_ced);
return total_len;
}
total_size += size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_warning_device, &pi, "Device Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_warning_ded_size,
hf_cip_ssupervisor_exception_detail_warning_ded_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_detail_warning_ded);
return total_len;
}
total_size += size;
item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_warning_manufacturer, &pi, "Manufacturer Exception Detail");
size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
hf_cip_ssupervisor_exception_detail_warning_med_size,
hf_cip_ssupervisor_exception_detail_warning_med_detail);
if (size == 0)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_detail_warning_med);
return total_len;
}
total_size += size;
return total_size;
}
static int dissect_s_supervisor_configuration_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
if (total_len < 10)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_configuration_unid);
return total_len;
}
dissect_unid(tvb, pinfo, offset, item, "CFUNID SSN",
hf_cip_ssupervisor_configuration_unid_ssn_timestamp,
hf_cip_ssupervisor_configuration_unid_ssn_date,
hf_cip_ssupervisor_configuration_unid_ssn_time,
hf_cip_ssupervisor_configuration_unid_macid,
ett_ssupervisor_configuration_unid,
ett_ssupervisor_configuration_unid_ssn);
return 10;
}
static int dissect_s_supervisor_safety_configuration_id(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
if (total_len < 10)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_safety_configuration_id);
return total_len;
}
dissect_unid(tvb, pinfo, offset, item, "SCID SSN",
hf_cip_ssupervisor_safety_configuration_id_ssn_timestamp,
hf_cip_ssupervisor_safety_configuration_id_ssn_date,
hf_cip_ssupervisor_safety_configuration_id_ssn_time,
hf_cip_ssupervisor_safety_configuration_id_macid,
ett_ssupervisor_safety_configuration_id,
ett_ssupervisor_safety_configuration_id_ssn);
return 10;
}
static int dissect_s_supervisor_target_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
if (total_len < 10)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_target_unid);
return total_len;
}
dissect_unid(tvb, pinfo, offset, item, "TUNID SSN",
hf_cip_ssupervisor_target_unid_ssn_timestamp,
hf_cip_ssupervisor_target_unid_ssn_date,
hf_cip_ssupervisor_target_unid_ssn_time,
hf_cip_ssupervisor_target_unid_macid,
ett_ssupervisor_target_unid,
ett_ssupervisor_target_unid_ssn);
return 10;
}
static int dissect_s_supervisor_output_connection_point_owners(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
guint16 i, num_entries;
proto_item *entry_item, *app_path_item;
proto_tree *entry_tree, *epath_tree;
int attr_len = 0, app_path_size;
if (total_len < 2)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners);
return total_len;
}
entry_item = proto_tree_add_item(tree, hf_cip_ssupervisor_cp_owners_num_entries,
tvb, offset, 2, ENC_LITTLE_ENDIAN );
num_entries = tvb_get_letohs(tvb, offset);
attr_len += 2;
if (num_entries > 0)
{
entry_tree = proto_item_add_subtree(entry_item, ett_ssupervisor_output_cp_owners);
for (i = 0; i < num_entries; i++)
{
if (total_len < attr_len+11)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_entry);
return total_len;
}
dissect_unid(tvb, pinfo, offset+attr_len, entry_item, "OCPUNID SSN",
hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_timestamp,
hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_date,
hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_time,
hf_cip_ssupervisor_output_cp_owners_ocpunid_macid,
ett_ssupervisor_output_cp_owners_ocpunid,
ett_ssupervisor_output_cp_owners_ocpunid_ssn);
attr_len += 10;
proto_tree_add_item(entry_tree, hf_cip_ssupervisor_cp_owners_app_path_size,
tvb, offset+attr_len, 1, ENC_LITTLE_ENDIAN );
app_path_size = tvb_get_guint8( tvb, offset+attr_len);
attr_len += 1;
if (total_len < attr_len+app_path_size)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_app_path_size);
return total_len;
}
epath_tree = proto_tree_add_subtree(entry_tree,
tvb, offset+attr_len, app_path_size, ett_path, &app_path_item, "Application Resource: ");
dissect_epath(tvb, pinfo, epath_tree, app_path_item, offset+attr_len, app_path_size, FALSE, TRUE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
attr_len += app_path_size;
}
}
return attr_len;
}
static int dissect_s_supervisor_proposed_tunid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
if (total_len < 10)
{
expert_add_info(pinfo, item, &ei_mal_ssupervisor_proposed_tunid);
return total_len;
}
dissect_unid(tvb, pinfo, offset, item, "Proposed TUNID SSN",
hf_cip_ssupervisor_proposed_tunid_ssn_timestamp,
hf_cip_ssupervisor_proposed_tunid_ssn_date,
hf_cip_ssupervisor_proposed_tunid_ssn_time,
hf_cip_ssupervisor_proposed_tunid_macid,
ett_ssupervisor_proposed_tunid,
ett_ssupervisor_proposed_tunid_ssn);
return 10;
}
/************************************************
*
* Dissector for CIP Safety Validator Object
*
************************************************/
static int dissect_s_validator_type(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
int offset, int total_len)
{
proto_item *pi;
proto_tree *item_tree;
if (total_len < 1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_type);
return total_len;
}
pi = proto_tree_add_item(tree, hf_cip_svalidator_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
item_tree = proto_item_add_subtree(pi, ett_svalidator_type);
proto_tree_add_item(item_tree, hf_cip_svalidator_type_pc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
proto_tree_add_item(item_tree, hf_cip_svalidator_type_conn_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
return 1;
}
static int dissect_s_validator_time_coord_msg_min_mult(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
int i, size;
proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_size,
tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset )*2;
if (total_len < size+1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_time_coord_msg_min_mult);
return total_len;
}
for (i = 0; i < size; i+=2)
{
proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_item,
tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
}
return (size+1);
}
static int dissect_s_validator_network_time_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
int i, size;
proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_size,
tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset )*2;
if (total_len < size+1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_network_time_multiplier);
return total_len;
}
for (i = 0; i < size; i+=2)
{
proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_item,
tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
}
return (size+1);
}
static int dissect_s_validator_timeout_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
int offset, int total_len)
{
int i, size;
proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_size,
tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset );
if (total_len < size+1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_timeout_multiplier);
return total_len;
}
for (i = 0; i < size; i++)
{
proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_item,
tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
}
return (size+1);
}
static int dissect_s_validator_coordination_conn_inst(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
int i, size;
proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_size,
tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset )*2;
if (total_len < size+1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_coordination_conn_inst);
return total_len;
}
for (i = 0; i < size; i+=2)
{
proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_item,
tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
}
return (size+1);
}
static int dissect_s_validator_app_data_path(packet_info *pinfo, proto_tree *tree,
proto_item *item _U_, tvbuff_t *tvb, int offset, int total_len)
{
proto_item* pi;
proto_tree* epath_tree = proto_tree_add_subtree(tree, NULL, 0, 0, ett_path, &pi, "Application Data Path: ");
dissect_epath(tvb, pinfo, epath_tree, pi, offset, total_len, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
return total_len;
}
static int dissect_s_validator_prod_cons_fault_count(packet_info *pinfo, proto_tree *tree, proto_item *item,
tvbuff_t *tvb, int offset, int total_len)
{
int i, size;
proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_size,
tvb, offset, 1, ENC_LITTLE_ENDIAN );
size = tvb_get_guint8( tvb, offset );
if (total_len < size+1)
{
expert_add_info(pinfo, item, &ei_mal_svalidator_prod_cons_fault_count);
return total_len;
}
for (i = 0; i < size; i++)
{
proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_item,
tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
}
return (size+1);
}
static void
dissect_cip_s_validator_data( proto_tree *item_tree,
tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
{
proto_item *pi, *rrsc_item;
proto_tree *rrsc_tree, *cmd_data_tree;
int req_path_size;
guint8 service, gen_status, add_stat_size;
cip_req_info_t* preq_info;
cip_simple_request_info_t req_data;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Validator");
/* Add Service code & Request/Response tree */
service = tvb_get_guint8( tvb, offset );
rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_svalidator_rrsc, &rrsc_item, "Service: " );
/* Add Request/Response */
proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
proto_item_append_text( rrsc_item, "%s (%s)",
val_to_str( ( service & 0x7F ),
cip_sc_vals_svalidator , "Unknown Service (0x%02x)"),
val_to_str_const( ( service & 0x80 )>>7,
cip_sc_rr, "") );
/* Add Service code */
proto_tree_add_item(rrsc_tree, hf_cip_svalidator_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
if ((preq_info != NULL) &&
(preq_info->ciaData != NULL))
{
memcpy(&req_data, preq_info->ciaData, sizeof(cip_simple_request_info_t));
}
else
{
req_data.iClass = (guint32)-1;
req_data.iInstance = (guint32)-1;
req_data.iAttribute = (guint32)-1;
req_data.iMember = (guint32)-1;
}
if(service & 0x80 )
{
/* Response message */
/* Add additional status size */
gen_status = tvb_get_guint8( tvb, offset+2 );
add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
/* If there is any command specific data create a sub-tree for it */
if( ( item_length-4-add_stat_size ) != 0 )
{
cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
ett_ssupervisor_cmd_data, &pi, "Command Specific Data" );
if( gen_status == CI_GRC_SUCCESS || gen_status == CI_GRC_SERVICE_ERROR )
{
/* Success responses */
if (((service & 0x7F) == SC_GET_ATT_ALL) &&
(req_data.iInstance != (guint32)-1) &&
(req_data.iInstance != 0))
{
dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset + 4 + add_stat_size, &req_data);
}
else
{
/* Add data */
proto_tree_add_item(cmd_data_tree, hf_cip_data,
tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
}
}
else
{
/* Error responses */
/* Add data */
proto_tree_add_item(cmd_data_tree, hf_cip_data,
tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
} /* end of if-else( CI_CRC_SUCCESS ) */
} /* End of if command-specific data present */
} /* End of if reply */
else
{
/* Request message */
req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
/* If there is any command specific data create a sub-tree for it */
if( (item_length-req_path_size-2) != 0 )
{
cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
proto_tree_add_item(cmd_data_tree, hf_cip_data,
tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
}
}
add_cip_service_to_info_column(pinfo, service, cip_sc_vals_svalidator);
}
static int
dissect_cip_class_s_validator(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
proto_item *ti;
proto_tree *class_tree;
/* Create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_cip_class_s_validator, tvb, 0, -1, ENC_NA);
class_tree = proto_item_add_subtree( ti, ett_cip_class_s_validator );
dissect_cip_s_validator_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
return tvb_reported_length(tvb);
}
static gboolean
dissect_class_svalidator_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
unsigned char service, service_code, ioilen, segment;
cip_req_info_t* preq_info;
guint32 classid = 0;
int offset = 0;
service = tvb_get_guint8( tvb, offset );
service_code = service & 0x7F;
/* Handle GetAttributeAll and SetAttributeAll in CCO class */
if (service_code == SC_GET_ATT_ALL)
{
if (service & 0x80)
{
/* Service response */
preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
if ((preq_info != NULL) &&
(preq_info->dissector == dissector_get_uint_handle( subdissector_class_table, CI_CLS_SAFETY_VALIDATOR)))
{
call_dissector(preq_info->dissector, tvb, pinfo, tree);
return TRUE;
}
}
else
{
/* Service request */
ioilen = tvb_get_guint8( tvb, offset + 1 );
if (ioilen > 1)
{
segment = tvb_get_guint8( tvb, offset + 2 );
if (((segment & CI_SEGMENT_TYPE_MASK) == CI_LOGICAL_SEGMENT) &&
((segment & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_CLASS_ID))
{
/* Logical Class ID, do a format check */
switch ( segment & CI_LOGICAL_SEG_FORMAT_MASK )
{
case CI_LOGICAL_SEG_8_BIT:
classid = tvb_get_guint8( tvb, offset + 3 );
break;
case CI_LOGICAL_SEG_16_BIT:
if ( ioilen >= 2 )
classid = tvb_get_letohs( tvb, offset + 4 );
break;
case CI_LOGICAL_SEG_32_BIT:
if ( ioilen >= 3 )
classid = tvb_get_letohl( tvb, offset + 4 );
break;
}
}
}
if (classid == CI_CLS_SAFETY_VALIDATOR)
{
call_dissector(cip_class_s_validator_handle, tvb, pinfo, tree );
return TRUE;
}
}
}
return FALSE;
}
/************************************************
*
* Dissector for CIP Safety I/O Data
*
************************************************/
static void
dissect_mode_byte( proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
proto_item *mode_item, *run_idle_item, *tbd_item, *tbd2_item;
proto_tree *mode_tree;
guint8 mode_byte;
mode_byte = tvb_get_guint8(tvb, offset);
/* dissect Mode Byte bits */
mode_item = proto_tree_add_item(tree, hf_cipsafety_mode_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
mode_tree = proto_item_add_subtree( mode_item, ett_cipsafety_mode_byte);
proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_ping_count, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_tbd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_copy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_run_idle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
tbd_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
tbd2_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_bit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
run_idle_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_run_idle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
/* verify Mode Byte bits */
/* TBD */
if ((((mode_byte & 0x20) >> 5) & 0x01) == (((mode_byte & 0x04) >> 2) & 0x01))
expert_add_info(pinfo, tbd_item, &ei_cipsafety_tbd2_not_complemented);
/* TBD 2 */
if ((((mode_byte & 0x40) >> 6) & 0x01) != (((mode_byte & 0x08) >> 3) & 0x01))
expert_add_info(pinfo, tbd2_item, &ei_cipsafety_tbd_not_copied);
/* Run/Idle */
if ((((mode_byte & 0x80) >> 7) & 0x01) == (((mode_byte & 0x10) >> 4) & 0x01))
expert_add_info(pinfo, run_idle_item, &ei_cipsafety_run_idle_not_complemented);
}
static void
dissect_ack_byte( proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo _U_)
{
proto_item *ack_item;
proto_tree *ack_tree;
#if 0 /***** Placeholder reminder to add ack_byte validation */
guint8 ack_byte;
ack_byte = tvb_get_guint8(tvb, offset);
#endif
if (!tree)
return;
/* dissect Ack Byte bits */
ack_item = proto_tree_add_item(tree, hf_cipsafety_ack_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
ack_tree = proto_item_add_subtree( ack_item, ett_cipsafety_ack_byte);
proto_tree_add_item(ack_tree, hf_cipsafety_ack_byte_ping_count_reply, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(ack_tree, hf_cipsafety_ack_byte_reserved1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(ack_tree, hf_cipsafety_ack_byte_ping_response, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(ack_tree, hf_cipsafety_ack_byte_reserved2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(ack_tree, hf_cipsafety_ack_byte_parity_even, tvb, offset, 1, ENC_LITTLE_ENDIAN);
}
static void
dissect_mcast_byte( proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo _U_)
{
proto_item *mcast_item;
proto_tree *mcast_tree;
#if 0 /*** Placeholder reminder to add mcast_byte validation */
guint8 mcast_byte;
mcast_byte = tvb_get_guint8(tvb, offset);
#endif
/* dissect MCast Byte bits */
mcast_item = proto_tree_add_item(tree, hf_cipsafety_mcast_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
mcast_tree = proto_item_add_subtree( mcast_item, ett_cipsafety_mcast_byte);
proto_tree_add_item(mcast_tree, hf_cipsafety_mcast_byte_consumer_num, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mcast_tree, hf_cipsafety_mcast_byte_reserved1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mcast_tree, hf_cipsafety_mcast_byte_mai, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mcast_tree, hf_cipsafety_mcast_byte_reserved2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(mcast_tree, hf_cipsafety_mcast_byte_parity_even, tvb, offset, 1, ENC_LITTLE_ENDIAN);
}
static void
dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int item_length, packet_info *pinfo)
{
int base_length, io_data_size;
gboolean multicast = (((pntoh32(pinfo->dst.data)) & 0xf0000000) == 0xe0000000);
gboolean server_dir = FALSE;
enum enip_connid_type conn_type = ECIDT_UNKNOWN;
enum cip_safety_format_type format = CIP_SAFETY_BASE_FORMAT;
cip_safety_info_t* safety_info = (cip_safety_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0 );
/* Make entries in Protocol column and Info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Safety");
/* determine the connection type as it affects the fields dissected */
if (safety_info != NULL)
{
conn_type = safety_info->conn_type;
format = safety_info->format;
server_dir = safety_info->server_dir;
}
/* compute the base packet length to determine what is actual I/O data */
base_length = multicast ? 12 : 6;
if (((conn_type == ECIDT_O2T) && (server_dir == FALSE)) ||
((conn_type == ECIDT_T2O) && (server_dir == TRUE)))
{
/* consumer data */
dissect_ack_byte(tree, tvb, 0, pinfo);
proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
switch (format)
{
case CIP_SAFETY_BASE_FORMAT:
proto_tree_add_item(tree, hf_cipsafety_ack_byte2, tvb, 3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, 4, 2, ENC_LITTLE_ENDIAN);
break;
case CIP_SAFETY_EXTENDED_FORMAT:
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, 3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, 4, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, 5, 1, ENC_LITTLE_ENDIAN);
break;
}
}
else if (((conn_type == ECIDT_O2T) && (server_dir == TRUE)) ||
((conn_type == ECIDT_T2O) && (server_dir == FALSE)))
{
/* producer data */
switch (format)
{
case CIP_SAFETY_BASE_FORMAT:
if (item_length-base_length <= 2)
{
/* Short Format (1-2 bytes I/O data) */
proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, item_length-base_length, ENC_NA);
dissect_mode_byte(tree, tvb, item_length-base_length, pinfo);
proto_tree_add_item(tree, hf_cipsafety_crc_s1, tvb, item_length-base_length+1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s2, tvb, item_length-base_length+2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, item_length-base_length+3, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s1, tvb, item_length-base_length+5, 1, ENC_LITTLE_ENDIAN);
if (multicast)
{
dissect_mcast_byte(tree, tvb, item_length-6, pinfo);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, item_length-2, 2, ENC_LITTLE_ENDIAN);
}
}
else
{
/* Long Format (3-250 bytes I/O data) */
if (item_length%2 == 1)
{
/* Malformed packet */
expert_add_info(pinfo, item, &ei_mal_io);
return;
}
io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
dissect_mode_byte(tree, tvb, io_data_size, pinfo);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, io_data_size+1, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size+3, io_data_size, ENC_NA);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, (io_data_size*2)+3, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size*2)+5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s1, tvb, (io_data_size*2)+7, 1, ENC_LITTLE_ENDIAN);
if (multicast)
{
dissect_mcast_byte(tree, tvb, (io_data_size*2)+5, pinfo);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+6, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, (io_data_size*2)+8, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
}
}
break;
case CIP_SAFETY_EXTENDED_FORMAT:
if (item_length-base_length <= 2)
{
/* Short Format (1-2 bytes I/O data) */
proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, item_length-base_length, ENC_NA);
dissect_mode_byte(tree, tvb, item_length-base_length, pinfo);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, item_length-base_length+1, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, item_length-base_length+2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, item_length-base_length+3, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, item_length-base_length+5, 1, ENC_LITTLE_ENDIAN);
if (multicast)
{
dissect_mcast_byte(tree, tvb, item_length-6, pinfo);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, item_length-2, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, item_length-1, 1, ENC_LITTLE_ENDIAN);
}
}
else
{
/* Long Format (3-250 bytes I/O data) */
if (item_length%2 == 1)
{
/* Malformed packet */
expert_add_info(pinfo, item, &ei_mal_io);
return;
}
io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
dissect_mode_byte(tree, tvb, io_data_size, pinfo);
proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, io_data_size+1, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size+3, io_data_size, ENC_NA);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, (io_data_size*2)+3, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, (io_data_size*2)+4, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size*2)+5, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, (io_data_size*2)+7, 1, ENC_LITTLE_ENDIAN);
if (multicast)
{
dissect_mcast_byte(tree, tvb, (io_data_size*2)+8, pinfo);
proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, (io_data_size*2)+11, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, (io_data_size*2)+12, 1, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, (io_data_size*2)+13, 1, ENC_LITTLE_ENDIAN);
}
}
break;
}
}
else
{
/* Shouldn't happen, but at least dissect it as data */
proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, item_length, ENC_NA);
}
}
static int
dissect_cipsafety(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ti;
proto_tree *safety_tree;
/* Create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_cipsafety, tvb, 0, -1, ENC_NA);
safety_tree = proto_item_add_subtree( ti, ett_cip_safety);
dissect_cip_safety_data(safety_tree, ti, tvb, tvb_reported_length(tvb), pinfo );
return tvb_captured_length(tvb);
}
static int dissect_sercosiii_link_error_count_p1p2(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
int offset, int total_len)
{
if (total_len < 4)
{
expert_add_info(pinfo, item, &ei_mal_sercosiii_link_error_count_p1p2);
return total_len;
}
proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p1, tvb, offset, 2, ENC_LITTLE_ENDIAN );
proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p2, tvb, offset+2, 2, ENC_LITTLE_ENDIAN );
return 4;
}
attribute_info_t cip_safety_attribute_vals[51] = {
/* Safety Supervisor */
{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, -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},
/* TODO: GAA code can't get to "Error Code", because dissect_s_validator_app_data_path() will use
all remaining bytes. Waiting on clarification in a future spec update. */
{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, -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},
};
/*
* Protocol initialization
*/
/*
* Function name: proto_register_cipsafety
*
* Purpose: Register the protocol with Wireshark, a script will add this protocol
* to the list of protocols during the build process. This function is where the
* header fields and subtree identifiers are registered.
*
* Returns: void
*/
void
proto_register_cipsafety(void)
{
/* This is a list of header fields that can be used in the dissection or
* to use in a filter expression */
static hf_register_info hf[] =
{
{ &hf_cip_reqrsp,
{ "Request/Response", "cip.rr",
FT_UINT8, BASE_HEX, VALS(cip_sc_rr), 0x80, "Request or Response message", HFILL }
},
{ &hf_cip_data,
{ "Data", "cip.data",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_data,
{ "Data", "enip.connection_transport_data",
FT_BYTES, BASE_NONE, NULL, 0, "Connection Transport Data", HFILL }
},
{ &hf_cipsafety_mode_byte,
{ "Mode Byte", "cipsafety.mode_byte",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_ping_count,
{ "Ping Count", "cipsafety.mode_byte.ping_count",
FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_not_tbd,
{ "Not TBD Bit", "cipsafety.mode_byte.not_tbd",
FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_tbd_2_copy,
{ "TBD 2 Bit Copy", "cipsafety.mode_byte.tbd_2_copy",
FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_not_run_idle,
{ "Not Run/Idle", "cipsafety.mode_byte.not_run_idle",
FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_tbd,
{ "TBD Bit", "cipsafety.mode_byte.tbd",
FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_tbd_2_bit,
{ "TBD 2 Bit", "cipsafety.mode_byte.tbd_2_bit",
FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
},
{ &hf_cipsafety_mode_byte_run_idle,
{ "Run/Idle", "cipsafety.mode_byte.run_idle",
FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
},
{ &hf_cipsafety_crc_s1,
{ "CRC S1", "cipsafety.crc_s1",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_crc_s2,
{ "CRC S2", "cipsafety.crc_s2",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_crc_s3,
{ "CRC S3", "cipsafety.crc_s3",
FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_timestamp,
{ "Timestamp", "cipsafety.timestamp",
FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte,
{ "ACK Byte", "cipsafety.ack_byte",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte_ping_count_reply,
{ "Ping Count Reply", "cipsafety.ack_byte.ping_count_reply",
FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte_reserved1,
{ "Reserved", "cipsafety.ack_byte.reserved1",
FT_UINT8, BASE_HEX, NULL, 0x04, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte_ping_response,
{ "Ping Response", "cipsafety.ack_byte.ping_response",
FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte_reserved2,
{ "Reserved", "cipsafety.ack_byte.reserved2",
FT_UINT8, BASE_HEX, NULL, 0x70, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte_parity_even,
{ "Parity Even", "cipsafety.ack_byte.parity_even",
FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
},
{ &hf_cipsafety_ack_byte2,
{ "ACK Byte 2", "cipsafety.ack_byte2",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_consumer_time_value,
{ "Consumer Time Value", "cipsafety.consumer_time_value",
FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte,
{ "MCAST Byte", "cipsafety.mcast_byte",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte_consumer_num,
{ "Consumer #", "cipsafety.mcast_byte.consumer_num",
FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte_reserved1,
{ "Reserved", "cipsafety.mcast_byte.reserved1",
FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte_mai,
{ "Multicast Active/Idle", "cipsafety.mcast_byte.active_idle",
FT_BOOLEAN, 8, TFS(&cip_safety_vals_active_idle), 0x20, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte_reserved2,
{ "Reserved", "cipsafety.mcast_byte.reserved2",
FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte_parity_even,
{ "Parity Even", "cipsafety.mcast_byte.parity_even",
FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
},
{ &hf_cipsafety_mcast_byte2,
{ "MCAST Byte 2", "cipsafety.mcast_byte2",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_time_correction,
{ "Time Correction", "cipsafety.time_correction",
FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_crc_s5_0,
{ "CRC S5_0", "cipsafety.crc_s5_0",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_crc_s5_1,
{ "CRC S5_1", "cipsafety.crc_s5_1",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_crc_s5_2,
{ "CRC S5_2", "cipsafety.crc_s5_2",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cipsafety_complement_data,
{ "Complement Data", "cipsafety.complement_data",
FT_BYTES, BASE_NONE, NULL, 0, "Connection Transport Data", HFILL }
},
{ &hf_cip_sercosiii_link_snn,
{ "Data", "cipsafety.sercosiii_link.snn",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_communication_cycle_time,
{ "Communication Cycle Time", "cipsafety.sercosiii_link.communication_cycle_time",
FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_interface_status,
{ "Communication Cycle Time", "cipsafety.sercosiii_link.interface_status",
FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_error_count_mstps,
{ "Error Counter MST-P/S", "cipsafety.sercosiii_link.error_count_mstps",
FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_error_count_p1,
{ "Error Count Port 1", "cipsafety.sercosiii_link.error_count_p1",
FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_error_count_p2,
{ "Error Count Port 2", "cipsafety.sercosiii_link.error_count_p2",
FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_sercosiii_link_sercos_address,
{ "SERCOS Address", "cipsafety.sercosiii_link.sercos_address",
FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
};
static hf_register_info hf_ssupervisor[] = {
{ &hf_cip_ssupervisor_sc,
{ "Service", "cipsafety.ssupervisor.sc",
FT_UINT8, BASE_HEX, VALS(cip_sc_vals_ssupervisor), 0x7F, NULL, HFILL }
},
{ &hf_cip_ssupervisor_recover_data,
{ "Data", "cipsafety.ssupervisor.recover.data",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_perform_diag_data,
{ "Data", "cipsafety.ssupervisor.perform_diag.data",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_password,
{ "Password", "cipsafety.ssupervisor.configure_request.password",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_tunid,
{ "Target UNID", "cipsafety.ssupervisor.configure_request.tunid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_tunid_ssn_timestamp,
{ "TUNID SSN Timestamp", "cipsafety.ssupervisor.configure_request.tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_tunid_ssn_date,
{ "TUNID SSN (Manual) Date", "cipsafety.ssupervisor.configure_request.tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_tunid_ssn_time,
{ "TUNID SSN (Manual) Time", "cipsafety.ssupervisor.configure_request.tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_tunid_macid,
{ "MAC ID", "cipsafety.ssupervisor.configure_request.tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_ounid,
{ "Originator UNID", "cipsafety.ssupervisor.configure_request.ounid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_ounid_ssn_timestamp,
{ "OUNID SSN Timestamp", "cipsafety.ssupervisor.configure_request.ounid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_ounid_ssn_date,
{ "OUNID SSN (Manual) Date", "cipsafety.ssupervisor.configure_request.ounid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_ounid_ssn_time,
{ "OUNID SSN (Manual) Time", "cipsafety.ssupervisor.configure_request.ounid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_request_ounid_macid,
{ "MAC ID", "cipsafety.ssupervisor.configure_request.ounid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_validate_configuration_sccrc,
{ "SCCRC", "cipsafety.ssupervisor.validate_configuration.sccrc",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_validate_configuration_scts_timestamp,
{ "SCTS (Timestamp)", "cipsafety.ssupervisor.validate_configuration.scts.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_validate_configuration_scts_date,
{ "SCTS (Manual) Date", "cipsafety.ssupervisor.validate_configuration.scts.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_validate_configuration_scts_time,
{ "SCTS (Manual) Time", "cipsafety.ssupervisor.validate_configuration.scts.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_validate_configuration_ext_error,
{ "Extended Error", "cipsafety.ssupervisor.validate_configuration.ext_error",
FT_UINT16, BASE_DEC, VALS(cip_ssupervisor_validate_configuration_ext_error_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_set_password_current_password,
{ "Current Password", "cipsafety.ssupervisor.set_password.current_pass",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_set_password_new_password,
{ "New Password", "cipsafety.ssupervisor.set_password.new_pass",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_value,
{ "Lock Value", "cipsafety.ssupervisor.configure_lock.lock",
FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_password,
{ "Password", "cipsafety.ssupervisor.configure_lock.password",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_tunid,
{ "Target UNID", "cipsafety.ssupervisor.configure_lock.tunid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_tunid_ssn_timestamp,
{ "TUNID SSN Timestamp", "cipsafety.ssupervisor.configure_lock.tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_tunid_ssn_date,
{ "TUNID SSN (Manual) Date", "cipsafety.ssupervisor.configure_lock.tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_tunid_ssn_time,
{ "TUNID SSN (Manual) Time", "cipsafety.ssupervisor.configure_lock.tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configure_lock_tunid_macid,
{ "MAC ID", "cipsafety.ssupervisor.configure_lock.tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_mode_change_value,
{ "Value", "cipsafety.ssupervisor.mode_change.value",
FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_change_mode_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_mode_change_password,
{ "Password", "cipsafety.ssupervisor.mode_change.password",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_type,
{ "Reset Type", "cipsafety.ssupervisor.reset.type",
FT_UINT8, BASE_DEC, VALS(cip_reset_type_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_password,
{ "Password", "cipsafety.ssupervisor.reset.password",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_tunid,
{ "Target UNID", "cipsafety.ssupervisor.reset.tunid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_tunid_tunid_ssn_timestamp,
{ "TUNID SSN Timestamp", "cipsafety.ssupervisor.reset.tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_tunid_tunid_ssn_date,
{ "TUNID SSN (Manual) Date", "cipsafety.ssupervisor.reset.tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_tunid_tunid_ssn_time,
{ "TUNID SSN (Manual) Time", "cipsafety.ssupervisor.reset.tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_tunid_macid,
{ "MAC ID", "cipsafety.ssupervisor.reset.tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap,
{ "Attribute Bit Map", "cipsafety.ssupervisor.reset.attr_bitmap",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_macid,
{ "Preserve MacID", "cipsafety.ssupervisor.reset.attr_bitmap.macid",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_baudrate,
{ "Preserve Baud Rate", "cipsafety.ssupervisor.reset.attr_bitmap.baudrate",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x02, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_tunid,
{ "Preserve TUNID", "cipsafety.ssupervisor.reset.attr_bitmap.tunid",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x04, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_password,
{ "Preserve Password", "cipsafety.ssupervisor.reset.attr_bitmap.password",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x08, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_cfunid,
{ "Preserve CFUNID", "cipsafety.ssupervisor.reset.attr_bitmap.cfunid",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x10, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_ocpunid,
{ "Preserve OPCUNID", "cipsafety.ssupervisor.reset.attr_bitmap.ocpunid",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x20, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_reserved,
{ "Reserved", "cipsafety.ssupervisor.reset.attr_bitmap.reserved",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x40, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_attr_bitmap_extended,
{ "Use Extended Map", "cipsafety.ssupervisor.reset.attr_bitmap.extended",
FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x80, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_password_data_size,
{ "Data Size", "cipsafety.ssupervisor.reset_password.data_size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_reset_password_data,
{ "Password Data", "cipsafety.ssupervisor.reset_password.password_data",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_propose_tunid_tunid,
{ "Target UNID", "cipsafety.ssupervisor.propose_tunid.tunid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_propose_tunid_tunid_ssn_timestamp,
{ "TUNID SSN Timestamp", "cipsafety.ssupervisor.propose_tunid.tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_propose_tunid_tunid_ssn_date,
{ "TUNID SSN (Manual) Date", "cipsafety.ssupervisor.propose_tunid.tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_propose_tunid_tunid_ssn_time,
{ "TUNID SSN (Manual) Time", "cipsafety.ssupervisor.propose_tunid.tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_propose_tunid_tunid_macid,
{ "MAC ID", "cipsafety.ssupervisor.propose_tunid.tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_apply_tunid_tunid,
{ "Target UNID", "cipsafety.ssupervisor.apply_tunid.tunid",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_apply_tunid_tunid_ssn_timestamp,
{ "TUNID SSN Timestamp", "cipsafety.ssupervisor.apply_tunid.tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_apply_tunid_tunid_ssn_date,
{ "TUNID SSN (Manual) Date", "cipsafety.ssupervisor.apply_tunid.tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_apply_tunid_tunid_ssn_time,
{ "TUNID SSN (Manual) Time", "cipsafety.ssupervisor.apply_tunid.tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_apply_tunid_tunid_macid,
{ "MAC ID", "cipsafety.ssupervisor.apply_tunid.tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_class_subclass,
{ "Subclass", "cipsafety.ssupervisor.class_subclass",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_num_attr,
{ "Number of Attributes", "cipsafety.ssupervisor.num_attr",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_attr_list,
{ "Attributes List Item", "cipsafety.ssupervisor.attr_item",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_manufacture_name,
{ "Manufacturer Name", "cipsafety.ssupervisor.manufacture_name",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_manufacture_model_number,
{ "Manufacturer Model Number", "cipsafety.ssupervisor.manufacture_model_number",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_sw_rev_level,
{ "Software Revision Level", "cipsafety.ssupervisor.sw_rev_level",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_hw_rev_level,
{ "Hardware Revision Level", "cipsafety.ssupervisor.hw_rev_level",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_manufacture_serial_number,
{ "Manufacturer Serial Number", "cipsafety.ssupervisor.manufacture_serial_number",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_device_config,
{ "Device Configuration", "cipsafety.ssupervisor.device_config",
FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_device_status,
{ "Device Status", "cipsafety.ssupervisor.device_status",
FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_device_status_type_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_status,
{ "Exception Status", "cipsafety.ssupervisor.exception_status",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_ced_size,
{ "Common Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_alarm.ced.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_ced_detail,
{ "Common Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_alarm.ced.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_ded_size,
{ "Device Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_alarm.ded.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_ded_detail,
{ "Device Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_alarm.ded.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_med_size,
{ "Manufacturer Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_alarm.med.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_alarm_med_detail,
{ "Manufacturer Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_alarm.med.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_ced_size,
{ "Common Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_warning.ced.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_ced_detail,
{ "Common Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_warning.ced.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_ded_size,
{ "Device Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_warning.ded.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_ded_detail,
{ "Device Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_warning.ded.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_med_size,
{ "Manufacturer Exeception Detail Size", "cipsafety.ssupervisor.exception_detail_warning.med.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_exception_detail_warning_med_detail,
{ "Manufacturer Exeception Detail Data", "cipsafety.ssupervisor.exception_detail_warning.med.detail",
FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_alarm_enable,
{ "Exception Detail Alarm", "cipsafety.ssupervisor.alarm_enable",
FT_BOOLEAN, BASE_NONE, TFS(&tfs_true_false), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_warning_enable,
{ "Exception Detail Warning", "cipsafety.ssupervisor.warning_enable",
FT_BOOLEAN, BASE_NONE, TFS(&tfs_true_false), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_time,
{ "Time", "cipsafety.ssupervisor.time",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_clock_power_cycle_behavior,
{ "Clock Power Cycle Behavior", "cipsafety.ssupervisor.clock_power_cycle_behavior",
FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_clock_power_cycle_type_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_last_maintenance_date,
{ "Last Maintenance Date", "cipsafety.ssupervisor.last_maintenance_date",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_next_scheduled_maintenance_date,
{ "Next Scheduled Maintenance Date", "cipsafety.ssupervisor.next_scheduled_maintenance_date",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer,
{ "Scheduled Maintenance Expiration Timer", "cipsafety.ssupervisor.scheduled_maintenance_expiration_timer",
FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable,
{ "Scheduled Maintenance Expiration Warning Enable", "cipsafety.ssupervisor.scheduled_maintenance_expiration_warning",
FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_run_hours,
{ "Run Hours", "cipsafety.ssupervisor.run_hours",
FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configuration_lock,
{ "Configuration Lock", "cipsafety.ssupervisor.configuration_lock",
FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configuration_unid_ssn_timestamp,
{ "Configuration UNID SSN Timestamp", "cipsafety.ssupervisor.configuration_unid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configuration_unid_ssn_date,
{ "Configuration UNID SSN (Manual) Date", "cipsafety.ssupervisor.configuration_unid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configuration_unid_ssn_time,
{ "Configuration UNID SSN (Manual) Time", "cipsafety.ssupervisor.configuration_unid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_configuration_unid_macid,
{ "Configuration UNID MAC ID", "cipsafety.ssupervisor.configuration_unid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_safety_configuration_id_ssn_timestamp,
{ "Safety Configuration ID SSN Timestamp", "cipsafety.ssupervisor.safety_configuration_id.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_safety_configuration_id_ssn_date,
{ "Safety Configuration ID SSN (Manual) Date", "cipsafety.ssupervisor.safety_configuration_id.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_safety_configuration_id_ssn_time,
{ "Safety Configuration ID SSN (Manual) Time", "cipsafety.ssupervisor.safety_configuration_id.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_safety_configuration_id_macid,
{ "Safety Configuration ID MAC ID", "cipsafety.ssupervisor.safety_configuration_id.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_target_unid_ssn_timestamp,
{ "Target UNID SSN Timestamp", "cipsafety.ssupervisor.target_unid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_target_unid_ssn_date,
{ "Target UNID SSN (Manual) Date", "cipsafety.ssupervisor.target_unid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_target_unid_ssn_time,
{ "Target UNID SSN (Manual) Time", "cipsafety.ssupervisor.target_unid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_target_unid_macid,
{ "Target UNID MAC ID", "cipsafety.ssupervisor.target_unid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_cp_owners_num_entries,
{ "Number of Array Entries", "cipsafety.ssupervisor.cp_owners.num_entries",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_timestamp,
{ "OCPUNID SSN Timestamp", "cipsafety.ssupervisor.cp_owners.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_date,
{ "OCPUNID SSN (Manual) Date", "cipsafety.ssupervisor.cp_owners.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_output_cp_owners_ocpunid_ssn_time,
{ "OCPUNID SSN (Manual) Time", "cipsafety.ssupervisor.cp_owners.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_output_cp_owners_ocpunid_macid,
{ "OCPUNID MAC ID", "cipsafety.ssupervisor.cp_owners.ocpunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_cp_owners_app_path_size,
{ "EPATH Size", "cipsafety.ssupervisor.cp_owners.epath_size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_proposed_tunid_ssn_timestamp,
{ "Proposed TUNID SSN Timestamp", "cipsafety.ssupervisor.proposed_tunid.ssn.timestamp",
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_proposed_tunid_ssn_date,
{ "Proposed TUNID SSN (Manual) Date", "cipsafety.ssupervisor.proposed_tunid.ssn.date",
FT_UINT16, BASE_HEX, VALS(cipsafety_ssn_date_vals), 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_proposed_tunid_ssn_time,
{ "Proposed TUNID SSN (Manual) Time", "cipsafety.ssupervisor.proposed_tunid.ssn.time",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_proposed_tunid_macid,
{ "Proposed TUNID MAC ID", "cipsafety.ssupervisor.proposed_tunid.macid",
FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_ssupervisor_instance_subclass,
{ "Subclass", "cipsafety.ssupervisor.instance_subclass",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
}
};
static hf_register_info hf_svalidator[] = {
{ &hf_cip_svalidator_sc,
{ "Service", "cipsafety.svalidator.sc",
FT_UINT8, BASE_HEX, VALS(cip_sc_vals_svalidator), 0x7F, NULL, HFILL }
},
{ &hf_cip_svalidator_sconn_fault_count,
{ "Safety Connection Fault Count", "cipsafety.svalidator.sconn_fault_count",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_state,
{ "Safety Validator State", "cipsafety.svalidator.state",
FT_UINT8, BASE_DEC, VALS(cip_svalidator_state_vals), 0, NULL, HFILL }
},
{ &hf_cip_svalidator_type,
{ "Safety Validator Type", "cipsafety.svalidator.type",
FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_type_pc,
{ "Producer/Consumer", "cipsafety.svalidator.type.pc",
FT_UINT8, BASE_HEX, VALS(cip_svalidator_type_pc_vals), 0x80, NULL, HFILL }
},
{ &hf_cip_svalidator_type_conn_type,
{ "Safety Connection Type", "cipsafety.svalidator.type.conn_type",
FT_UINT8, BASE_DEC, VALS(cip_svalidator_type_conn_type_vals), 0x7F, NULL, HFILL }
},
{ &hf_cip_svalidator_ping_eri,
{ "Ping Interval EPI Multipler", "cipsafety.svalidator.ping_eri",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_time_coord_msg_min_mult_size,
{ "Time Coord Msg Min Multiplier Size", "cipsafety.svalidator.time_coord_msg_min_mult.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_time_coord_msg_min_mult_item,
{ "Time Coord Msg Min Multiplier Item", "cipsafety.svalidator.time_coord_msg_min_mult.item",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_network_time_multiplier_size,
{ "Network Time Expectation Multipler Size", "cipsafety.svalidator.network_time_multiplier.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_network_time_multiplier_item,
{ "Network Time Expectation Multipler Item", "cipsafety.svalidator.network_time_multiplier.item",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_timeout_multiplier_size,
{ "Timeout Multiplier Size", "cipsafety.svalidator.timeout_multiplier.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_timeout_multiplier_item,
{ "Timeout Multiplier Item", "cipsafety.svalidator.timeout_multiplier.item",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_max_consumer_num,
{ "Max Consumer Number", "cipsafety.svalidator.max_consumer_num",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_data_conn_inst,
{ "Data Connection Instance", "cipsafety.svalidator.data_conn_inst",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_coordination_conn_inst_size,
{ "Coordination Connection Instance Size", "cipsafety.svalidator.coordination_conn_inst.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_coordination_conn_inst_item,
{ "Coordination Connection Instance Item", "cipsafety.svalidator.coordination_conn_inst.item",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_correction_conn_inst,
{ "Correction Connection Instance", "cipsafety.svalidator.correction_conn_inst",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_cco_binding,
{ "CCO Binding", "cipsafety.svalidator.cco_binding",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_max_data_age,
{ "Max Data Age", "cipsafety.svalidator.max_data_age",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_error_code,
{ "Error Code", "cipsafety.svalidator.error_code",
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_prod_cons_fault_count_size,
{ "Producer/Consumer Counter Size", "cipsafety.svalidator.prod_cons_fault_count.size",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_cip_svalidator_prod_cons_fault_count_item,
{ "Producer/Consumer Counter Item", "cipsafety.svalidator.prod_cons_fault_count.item",
FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
}
};
static gint *ett[] = {
&ett_cip_safety,
&ett_path,
&ett_cipsafety_mode_byte,
&ett_cipsafety_ack_byte,
&ett_cipsafety_mcast_byte
};
static gint *ett_ssupervisor[] = {
&ett_cip_class_s_supervisor,
&ett_ssupervisor_rrsc,
&ett_ssupervisor_cmd_data,
&ett_ssupervisor_propose_tunid,
&ett_ssupervisor_propose_tunid_ssn,
&ett_ssupervisor_configure_request_tunid,
&ett_ssupervisor_configure_request_tunid_ssn,
&ett_ssupervisor_configure_request_ounid,
&ett_ssupervisor_configure_request_ounid_ssn,
&ett_ssupervisor_configure_lock_tunid,
&ett_ssupervisor_configure_lock_tunid_ssn,
&ett_ssupervisor_reset_tunid,
&ett_ssupervisor_reset_tunid_ssn,
&ett_ssupervisor_apply_tunid,
&ett_ssupervisor_apply_tunid_ssn,
&ett_exception_detail_alarm_common,
&ett_exception_detail_alarm_device,
&ett_exception_detail_alarm_manufacturer,
&ett_exception_detail_warning_common,
&ett_exception_detail_warning_device,
&ett_exception_detail_warning_manufacturer,
&ett_ssupervisor_configuration_unid,
&ett_ssupervisor_configuration_unid_ssn,
&ett_ssupervisor_safety_configuration_id,
&ett_ssupervisor_safety_configuration_id_ssn,
&ett_ssupervisor_target_unid,
&ett_ssupervisor_target_unid_ssn,
&ett_ssupervisor_output_cp_owners,
&ett_ssupervisor_output_cp_owners_ocpunid,
&ett_ssupervisor_output_cp_owners_ocpunid_ssn,
&ett_ssupervisor_proposed_tunid,
&ett_ssupervisor_proposed_tunid_ssn,
&ett_cip_ssupervisor_reset_attr_bitmap
};
static gint *ett_svalidator[] = {
&ett_cip_class_s_validator,
&ett_svalidator_rrsc,
&ett_svalidator_cmd_data,
&ett_svalidator_type
};
static ei_register_info ei[] = {
{ &ei_cipsafety_tbd2_not_complemented, { "cipsafety.tbd2_not_complemented", PI_PROTOCOL, PI_WARN, "TBD_2_bit not complemented", EXPFILL }},
{ &ei_cipsafety_tbd_not_copied, { "cipsafety.tbd_not_copied", PI_PROTOCOL, PI_WARN, "TBD bit not copied", EXPFILL }},
{ &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 }},
};
static ei_register_info ei_ssupervisor[] = {
{ &ei_mal_ssupervisor_exception_detail_alarm_ced, { "cipsafety.ssupervisor.malformed.exception_detail_alarm.ced", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Alarm (Common Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_exception_detail_alarm_ded, { "cipsafety.ssupervisor.malformed.exception_detail_alarm.ded", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Alarm (Device Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_exception_detail_alarm_med, { "cipsafety.ssupervisor.malformed.exception_detail_alarm.med", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Alarm (Manufacturer Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_detail_warning_ced, { "cipsafety.ssupervisor.malformed.detail_warning.ced", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Warning (Common Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_detail_warning_ded, { "cipsafety.ssupervisor.malformed.detail_warning.ded", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Warning (Device Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_detail_warning_med, { "cipsafety.ssupervisor.malformed.detail_warning.med", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Exception Detail Warning (Manufacturer Exception Detail)", EXPFILL }},
{ &ei_mal_ssupervisor_configuration_unid, { "cipsafety.ssupervisor.malformed.configuration_unid", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Configuration UNID", EXPFILL }},
{ &ei_mal_ssupervisor_safety_configuration_id, { "cipsafety.ssupervisor.malformed.safety_configuration_id", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Safety Configuration Identifier", EXPFILL }},
{ &ei_mal_ssupervisor_target_unid, { "cipsafety.ssupervisor.malformed.target_unid", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Target UNID", EXPFILL }},
{ &ei_mal_ssupervisor_cp_owners, { "cipsafety.ssupervisor.malformed.cp_owners", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Output Connection Point Owners", EXPFILL }},
{ &ei_mal_ssupervisor_cp_owners_entry, { "cipsafety.ssupervisor.malformed.cp_owners.entry", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Output Connection Point Owners (UNID)", EXPFILL }},
{ &ei_mal_ssupervisor_cp_owners_app_path_size, { "cipsafety.ssupervisor.malformed.cp_owners.app_path_size", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Output Connection Point Owners (EPATH)", EXPFILL }},
{ &ei_mal_ssupervisor_proposed_tunid, { "cipsafety.ssupervisor.malformed.proposed_tunid", PI_MALFORMED, PI_ERROR,
"Malformed Safety Supervisor Proposed TUNID", EXPFILL }},
};
static ei_register_info ei_svalidator[] = {
{ &ei_mal_svalidator_type, { "cipsafety.ssupervisor.malformed.svalidator.type", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Type", EXPFILL }},
{ &ei_mal_svalidator_time_coord_msg_min_mult, { "cipsafety.ssupervisor.malformed.svalidator.time_coord_msg_min_mult", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Time Coord Msg Min Multiplier", EXPFILL }},
{ &ei_mal_svalidator_network_time_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.network_time_multiplier", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Network Time Expectation Multiplier", EXPFILL }},
{ &ei_mal_svalidator_timeout_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.timeout_multiplier", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Timeout Multiplier", EXPFILL }},
{ &ei_mal_svalidator_coordination_conn_inst, { "cipsafety.ssupervisor.malformed.svalidator.coordination_conn_inst", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Coordination Connection Instance", EXPFILL }},
{ &ei_mal_svalidator_prod_cons_fault_count, { "cipsafety.ssupervisor.malformed.svalidator.prod_cons_fault_count", PI_MALFORMED, PI_ERROR,
"Malformed Safety Validator Produce/Consume Fault Counters", EXPFILL }},
};
expert_module_t* expert_cip_safety;
expert_module_t* expert_cip_class_s_supervisor;
expert_module_t* expert_cip_class_s_validator;
/* Create a CIP Safety protocol handle */
proto_cipsafety = proto_register_protocol("Common Industrial Protocol, Safety", "CIP Safety", "cipsafety");
proto_register_field_array(proto_cipsafety, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_cip_safety = expert_register_protocol(proto_cipsafety);
expert_register_field_array(expert_cip_safety, ei, array_length(ei));
cipsafety_handle = register_dissector( "cipsafety", dissect_cipsafety, proto_cipsafety);
/* Register CIP Safety objects */
proto_cip_class_s_supervisor = proto_register_protocol("CIP Safety Supervisor",
"CIPSSupervisor", "cipssupervisor");
proto_register_field_array(proto_cip_class_s_supervisor, hf_ssupervisor, array_length(hf_ssupervisor));
proto_register_subtree_array(ett_ssupervisor, array_length(ett_ssupervisor));
expert_cip_class_s_supervisor = expert_register_protocol(proto_cip_class_s_supervisor);
expert_register_field_array(expert_cip_class_s_supervisor, ei_ssupervisor, array_length(ei_ssupervisor));
proto_cip_class_s_validator = proto_register_protocol("CIP Safety Validator",
"CIPSValidator", "cipsvalidator");
proto_register_field_array(proto_cip_class_s_validator, hf_svalidator, array_length(hf_svalidator));
proto_register_subtree_array(ett_svalidator, array_length(ett_svalidator));
expert_cip_class_s_validator = expert_register_protocol(proto_cip_class_s_validator);
expert_register_field_array(expert_cip_class_s_validator, ei_svalidator, array_length(ei_svalidator));
}
/*
* Function name: proto_reg_handoff_cipsafety
*
* Purpose: This function will setup the automatic dissection of the CIP Safety datagram,
* it is called by Wireshark when the protocol is registered
*
* Returns: void
*/
void
proto_reg_handoff_cipsafety(void)
{
dissector_handle_t cip_class_s_supervisor_handle;
/* Create and register dissector handle for Safety Supervisor */
cip_class_s_supervisor_handle = create_dissector_handle( dissect_cip_class_s_supervisor, proto_cip_class_s_supervisor );
dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_SUPERVISOR, cip_class_s_supervisor_handle );
/* Create and register dissector handle for Safety Validator */
cip_class_s_validator_handle = create_dissector_handle( dissect_cip_class_s_validator, proto_cip_class_s_validator );
dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_VALIDATOR, cip_class_s_validator_handle );
heur_dissector_add("cip.sc", dissect_class_svalidator_heur, "CIP Safety Validator", "s_validator_cip", proto_cip_class_s_validator, HEURISTIC_ENABLE);
/* Register dissector for I/O data handling */
dissector_add_for_decode_as("enip.io", cipsafety_handle );
proto_cip = proto_get_id_by_filter_name( "cip" );
subdissector_class_table = find_dissector_table("cip.class.iface");
}
/*
* 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:
*/