1 /* packet-cipsafety.c
2  * Routines for CIP (Common Industrial Protocol) Safety dissection
3  * CIP Safety Home: www.odva.org
4  *
5  * This dissector includes items from:
6  *    CIP Volume 1: Common Industrial Protocol, Edition 3.24
7  *    CIP Volume 5: CIP Safety, Edition 2.17
8  *
9  * Copyright 2011
10  * Michael Mann <mmann@pyramidsolutions.com>
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * SPDX-License-Identifier: GPL-2.0-or-later
17  */
18 
19 #include "config.h"
20 
21 #include <epan/packet.h>
22 #include <epan/expert.h>
23 #include <epan/proto_data.h>
24 
25 #include <wsutil/pint.h>
26 #include <wsutil/crc8.h>
27 #include <wsutil/crc16.h>
28 #include <wsutil/crc32.h>
29 #include "packet-cip.h"
30 #include "packet-cipsafety.h"
31 
32 
33 void proto_register_cipsafety(void);
34 void proto_reg_handoff_cipsafety(void);
35 /* The entry point to the actual dissection is: dissect_cipsafety */
36 
37 /* Protocol handle for CIP Safety */
38 static int proto_cipsafety                = -1;
39 static int proto_cipsafety_base_data      = -1;
40 static int proto_cipsafety_extended_data  = -1;
41 static int proto_cipsafety_base_time_coord      = -1;
42 static int proto_cipsafety_extended_time_coord  = -1;
43 static int proto_cip_class_s_supervisor   = -1;
44 static int proto_cip_class_s_validator    = -1;
45 static int proto_cip                      = -1;
46 
47 static dissector_table_t subdissector_class_table;
48 static dissector_handle_t cip_class_s_validator_handle;
49 
50 /* CIP Safety field identifiers */
51 static int hf_cipsafety_data                      = -1;
52 static int hf_cipsafety_mode_byte                 = -1;
createUI(final JComponent c)53 static int hf_cipsafety_mode_byte_run_idle        = -1;
54 static int hf_cipsafety_mode_byte_not_run_idle    = -1;
55 static int hf_cipsafety_mode_byte_tbd_2_bit       = -1;
56 static int hf_cipsafety_mode_byte_tbd_2_copy      = -1;
57 static int hf_cipsafety_mode_byte_ping_count      = -1;
58 static int hf_cipsafety_mode_byte_tbd             = -1;
installUI(final JComponent c)59 static int hf_cipsafety_mode_byte_not_tbd         = -1;
60 static int hf_cipsafety_crc_s1                    = -1;
61 static int hf_cipsafety_crc_s1_status             = -1;
62 static int hf_cipsafety_crc_s2                    = -1;
63 static int hf_cipsafety_crc_s2_status             = -1;
64 static int hf_cipsafety_crc_s3                    = -1;
getPreferredSize(JComponent c)65 static int hf_cipsafety_crc_s3_status             = -1;
66 static int hf_cipsafety_complement_crc_s3         = -1;
67 static int hf_cipsafety_complement_crc_s3_status  = -1;
68 static int hf_cipsafety_timestamp                 = -1;
69 static int hf_cipsafety_ack_byte                  = -1;
70 static int hf_cipsafety_ack_byte_ping_count_reply = -1;
71 static int hf_cipsafety_ack_byte_reserved1        = -1;
72 static int hf_cipsafety_ack_byte_ping_response    = -1;
73 static int hf_cipsafety_ack_byte_reserved2        = -1;
74 static int hf_cipsafety_ack_byte_parity_even      = -1;
75 static int hf_cipsafety_ack_byte2                 = -1;
76 static int hf_cipsafety_consumer_time_value       = -1;
77 static int hf_cipsafety_mcast_byte                = -1;
78 static int hf_cipsafety_mcast_byte_consumer_num   = -1;
79 static int hf_cipsafety_mcast_byte_reserved1      = -1;
80 static int hf_cipsafety_mcast_byte_mai            = -1;
81 static int hf_cipsafety_mcast_byte_reserved2      = -1;
82 static int hf_cipsafety_mcast_byte_parity_even    = -1;
83 static int hf_cipsafety_mcast_byte2               = -1;
84 static int hf_cipsafety_time_correction           = -1;
paint(Graphics g, JComponent c)85 static int hf_cipsafety_crc_s5_0                  = -1;
86 static int hf_cipsafety_crc_s5_1                  = -1;
87 static int hf_cipsafety_crc_s5_2                  = -1;
88 static int hf_cipsafety_crc_s5_status             = -1;
89 static int hf_cipsafety_complement_data           = -1;
90 
91 /* CIP Safety header field identifiers */
92 static int hf_cip_reqrsp            = -1;
93 static int hf_cip_data              = -1;
94 
95 /* Safety Supervisor header field identifiers */
96 static int hf_cip_ssupervisor_sc = -1;
97 static int hf_cip_ssupervisor_recover_data = -1;
98 static int hf_cip_ssupervisor_perform_diag_data = -1;
99 static int hf_cip_ssupervisor_configure_request_password = -1;
100 static int hf_cip_ssupervisor_configure_request_tunid = -1;
101 static int hf_cip_ssupervisor_configure_request_tunid_snn_timestamp = -1;
102 static int hf_cip_ssupervisor_configure_request_tunid_snn_date = -1;
103 static int hf_cip_ssupervisor_configure_request_tunid_snn_time = -1;
104 static int hf_cip_ssupervisor_configure_request_tunid_nodeid = -1;
105 static int hf_cip_ssupervisor_configure_request_ounid = -1;
106 static int hf_cip_ssupervisor_configure_request_ounid_snn_timestamp = -1;
107 static int hf_cip_ssupervisor_configure_request_ounid_snn_date = -1;
108 static int hf_cip_ssupervisor_configure_request_ounid_snn_time = -1;
109 static int hf_cip_ssupervisor_configure_request_ounid_nodeid = -1;
110 static int hf_cip_ssupervisor_validate_configuration_sccrc = -1;
111 static int hf_cip_ssupervisor_validate_configuration_scts_timestamp = -1;
112 static int hf_cip_ssupervisor_validate_configuration_scts_date = -1;
113 static int hf_cip_ssupervisor_validate_configuration_scts_time = -1;
114 static int hf_cip_ssupervisor_validate_configuration_ext_error = -1;
115 static int hf_cip_ssupervisor_set_password_current_password = -1;
116 static int hf_cip_ssupervisor_set_password_new_password = -1;
117 static int hf_cip_ssupervisor_configure_lock_value = -1;
118 static int hf_cip_ssupervisor_configure_lock_password = -1;
119 static int hf_cip_ssupervisor_configure_lock_tunid = -1;
120 static int hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp = -1;
121 static int hf_cip_ssupervisor_configure_lock_tunid_snn_date = -1;
122 static int hf_cip_ssupervisor_configure_lock_tunid_snn_time = -1;
123 static int hf_cip_ssupervisor_configure_lock_tunid_nodeid = -1;
124 static int hf_cip_ssupervisor_mode_change_value = -1;
125 static int hf_cip_ssupervisor_mode_change_password = -1;
126 static int hf_cip_ssupervisor_reset_type = -1;
127 static int hf_cip_ssupervisor_reset_password = -1;
128 static int hf_cip_ssupervisor_reset_tunid = -1;
129 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp = -1;
130 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_date = -1;
131 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_time = -1;
132 static int hf_cip_ssupervisor_reset_tunid_nodeid = -1;
133 static int hf_cip_ssupervisor_reset_attr_bitmap = -1;
134 static int hf_cip_ssupervisor_reset_attr_bitmap_macid = -1;
135 static int hf_cip_ssupervisor_reset_attr_bitmap_baudrate = -1;
136 static int hf_cip_ssupervisor_reset_attr_bitmap_tunid = -1;
137 static int hf_cip_ssupervisor_reset_attr_bitmap_password = -1;
138 static int hf_cip_ssupervisor_reset_attr_bitmap_cfunid = -1;
139 static int hf_cip_ssupervisor_reset_attr_bitmap_ocpunid = -1;
140 static int hf_cip_ssupervisor_reset_attr_bitmap_reserved = -1;
141 static int hf_cip_ssupervisor_reset_attr_bitmap_extended = -1;
142 static int hf_cip_ssupervisor_reset_password_data_size = -1;
143 static int hf_cip_ssupervisor_reset_password_data = -1;
144 static int hf_cip_ssupervisor_propose_tunid_tunid = -1;
145 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp = -1;
146 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_date = -1;
147 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_time = -1;
148 static int hf_cip_ssupervisor_propose_tunid_tunid_nodeid = -1;
149 static int hf_cip_ssupervisor_apply_tunid_tunid = -1;
150 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp = -1;
151 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_date = -1;
152 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_time = -1;
153 static int hf_cip_ssupervisor_apply_tunid_tunid_nodeid = -1;
154 
155 static int hf_cip_ssupervisor_class_subclass = -1;
156 static int hf_cip_ssupervisor_num_attr = -1;
157 static int hf_cip_ssupervisor_attr_list = -1;
158 static int hf_cip_ssupervisor_manufacture_name = -1;
159 static int hf_cip_ssupervisor_manufacture_model_number = -1;
160 static int hf_cip_ssupervisor_sw_rev_level = -1;
161 static int hf_cip_ssupervisor_hw_rev_level = -1;
162 static int hf_cip_ssupervisor_manufacture_serial_number = -1;
163 static int hf_cip_ssupervisor_device_config = -1;
164 static int hf_cip_ssupervisor_device_status = -1;
165 static int hf_cip_ssupervisor_exception_status = -1;
166 static int hf_cip_ssupervisor_exception_detail_ced_size = -1;
167 static int hf_cip_ssupervisor_exception_detail_ced_detail = -1;
168 static int hf_cip_ssupervisor_exception_detail_ded_size = -1;
169 static int hf_cip_ssupervisor_exception_detail_ded_detail = -1;
170 static int hf_cip_ssupervisor_exception_detail_med_size = -1;
171 static int hf_cip_ssupervisor_exception_detail_med_detail = -1;
172 static int hf_cip_ssupervisor_alarm_enable = -1;
173 static int hf_cip_ssupervisor_warning_enable = -1;
174 static int hf_cip_ssupervisor_time = -1;
175 static int hf_cip_ssupervisor_clock_power_cycle_behavior = -1;
176 static int hf_cip_ssupervisor_last_maintenance_date = -1;
177 static int hf_cip_ssupervisor_next_scheduled_maintenance_date = -1;
178 static int hf_cip_ssupervisor_scheduled_maintenance_expiration_timer = -1;
179 static int hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable = -1;
180 static int hf_cip_ssupervisor_run_hours = -1;
181 static int hf_cip_ssupervisor_configuration_lock = -1;
182 static int hf_cip_ssupervisor_configuration_unid_snn_timestamp = -1;
183 static int hf_cip_ssupervisor_configuration_unid_snn_date = -1;
184 static int hf_cip_ssupervisor_configuration_unid_snn_time = -1;
185 static int hf_cip_ssupervisor_configuration_unid_nodeid = -1;
186 static int hf_cip_ssupervisor_safety_configuration_id_snn_timestamp = -1;
187 static int hf_cip_ssupervisor_safety_configuration_id_snn_date = -1;
188 static int hf_cip_ssupervisor_safety_configuration_id_snn_time = -1;
189 static int hf_cip_ssupervisor_safety_configuration_id_sccrc = -1;
190 static int hf_cip_ssupervisor_target_unid_snn_timestamp = -1;
191 static int hf_cip_ssupervisor_target_unid_snn_date = -1;
192 static int hf_cip_ssupervisor_target_unid_snn_time = -1;
193 static int hf_cip_ssupervisor_target_unid_nodeid = -1;
194 static int hf_cip_ssupervisor_cp_owners_num_entries = -1;
195 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp = -1;
196 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date = -1;
197 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time = -1;
198 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid = -1;
199 static int hf_cip_ssupervisor_cp_owners_app_path_size = -1;
200 static int hf_cip_ssupervisor_proposed_tunid_snn_timestamp = -1;
201 static int hf_cip_ssupervisor_proposed_tunid_snn_date = -1;
202 static int hf_cip_ssupervisor_proposed_tunid_snn_time = -1;
203 static int hf_cip_ssupervisor_proposed_tunid_nodeid = -1;
204 static int hf_cip_ssupervisor_instance_subclass = -1;
205 
206 
207 /* Safety Validator header field identifiers */
208 static int hf_cip_svalidator_sc = -1;
209 
210 static int hf_cip_svalidator_sconn_fault_count = -1;
211 static int hf_cip_svalidator_state = -1;
212 static int hf_cip_svalidator_type = -1;
213 static int hf_cip_svalidator_type_pc = -1;
214 static int hf_cip_svalidator_type_conn_type = -1;
215 static int hf_cip_svalidator_ping_eri = -1;
216 static int hf_cip_svalidator_time_coord_msg_min_mult_size = -1;
217 static int hf_cip_svalidator_time_coord_msg_min_mult_item = -1;
218 static int hf_cip_svalidator_network_time_multiplier_size = -1;
219 static int hf_cip_svalidator_network_time_multiplier_item = -1;
220 static int hf_cip_svalidator_timeout_multiplier_size = -1;
221 static int hf_cip_svalidator_timeout_multiplier_item = -1;
222 static int hf_cip_svalidator_max_consumer_num = -1;
223 static int hf_cip_svalidator_data_conn_inst = -1;
224 static int hf_cip_svalidator_coordination_conn_inst_size = -1;
225 static int hf_cip_svalidator_coordination_conn_inst_item = -1;
226 static int hf_cip_svalidator_correction_conn_inst = -1;
227 static int hf_cip_svalidator_cco_binding = -1;
228 static int hf_cip_svalidator_max_data_age = -1;
229 static int hf_cip_svalidator_error_code = -1;
230 static int hf_cip_svalidator_prod_cons_fault_count_size = -1;
231 static int hf_cip_svalidator_prod_cons_fault_count_item = -1;
232 
233 static int hf_cip_sercosiii_link_snn = -1;
234 static int hf_cip_sercosiii_link_communication_cycle_time = -1;
235 static int hf_cip_sercosiii_link_interface_status = -1;
236 static int hf_cip_sercosiii_link_error_count_mstps = -1;
237 static int hf_cip_sercosiii_link_sercos_address = -1;
238 static int hf_cip_sercosiii_link_error_count_p1 = -1;
239 static int hf_cip_sercosiii_link_error_count_p2 = -1;
240 
241 /* Initialize the subtree pointers */
242 static gint ett_cip_safety                = -1;
243 static gint ett_path                      = -1;
244 static gint ett_cipsafety_mode_byte       = -1;
245 static gint ett_cipsafety_ack_byte        = -1;
246 static gint ett_cipsafety_mcast_byte      = -1;
247 
248 static gint ett_cip_class_s_supervisor    = -1;
249 static gint ett_ssupervisor_rrsc          = -1;
250 static gint ett_ssupervisor_cmd_data      = -1;
251 static gint ett_ssupervisor_propose_tunid = -1;
252 static gint ett_ssupervisor_propose_tunid_snn = -1;
253 static gint ett_ssupervisor_configure_request_tunid = -1;
254 static gint ett_ssupervisor_configure_request_tunid_snn = -1;
255 static gint ett_ssupervisor_configure_request_ounid = -1;
256 static gint ett_ssupervisor_configure_request_ounid_snn = -1;
257 static gint ett_ssupervisor_configure_lock_tunid = -1;
258 static gint ett_ssupervisor_configure_lock_tunid_snn = -1;
259 static gint ett_ssupervisor_reset_tunid = -1;
260 static gint ett_ssupervisor_reset_tunid_snn = -1;
261 static gint ett_ssupervisor_apply_tunid = -1;
262 static gint ett_ssupervisor_apply_tunid_snn = -1;
263 static gint ett_exception_detail_common = -1;
264 static gint ett_exception_detail_device = -1;
265 static gint ett_exception_detail_manufacturer = -1;
266 static gint ett_ssupervisor_configuration_unid = -1;
267 static gint ett_ssupervisor_configuration_unid_snn = -1;
268 static gint ett_ssupervisor_target_unid = -1;
269 static gint ett_ssupervisor_target_unid_snn = -1;
270 static gint ett_ssupervisor_output_cp_owners = -1;
271 static gint ett_ssupervisor_output_cp_owners_ocpunid = -1;
272 static gint ett_ssupervisor_output_cp_owners_ocpunid_snn = -1;
273 static gint ett_ssupervisor_proposed_tunid = -1;
274 static gint ett_ssupervisor_proposed_tunid_snn = -1;
275 static gint ett_cip_ssupervisor_reset_attr_bitmap = -1;
276 
277 static gint ett_cip_class_s_validator     = -1;
278 static gint ett_svalidator_rrsc           = -1;
279 static gint ett_svalidator_cmd_data       = -1;
280 static gint ett_svalidator_type           = -1;
281 
282 static const unit_name_string units_safety_128us = { " (128 us increment)", " (128 us increments)" };
283 
284 static expert_field ei_cipsafety_tbd2_not_complemented = EI_INIT;
285 static expert_field ei_cipsafety_tbd_not_copied = EI_INIT;
286 static expert_field ei_cipsafety_run_idle_not_complemented = EI_INIT;
287 static expert_field ei_mal_io = EI_INIT;
288 static expert_field ei_mal_sercosiii_link_error_count_p1p2 = EI_INIT;
289 static expert_field ei_cipsafety_not_complement_data = EI_INIT;
290 static expert_field ei_cipsafety_crc_s1 = EI_INIT;
291 static expert_field ei_cipsafety_crc_s2 = EI_INIT;
292 static expert_field ei_cipsafety_crc_s3 = EI_INIT;
293 static expert_field ei_cipsafety_complement_crc_s3 = EI_INIT;
294 static expert_field ei_cipsafety_crc_s5 = EI_INIT;
295 
296 static expert_field ei_mal_ssupervisor_exception_detail_ced = EI_INIT;
297 static expert_field ei_mal_ssupervisor_exception_detail_ded = EI_INIT;
298 static expert_field ei_mal_ssupervisor_exception_detail_med = EI_INIT;
299 static expert_field ei_mal_ssupervisor_configuration_unid = EI_INIT;
300 static expert_field ei_mal_ssupervisor_safety_configuration_id = EI_INIT;
301 static expert_field ei_mal_ssupervisor_target_unid = EI_INIT;
302 static expert_field ei_mal_ssupervisor_cp_owners = EI_INIT;
303 static expert_field ei_mal_ssupervisor_cp_owners_entry = EI_INIT;
304 static expert_field ei_mal_ssupervisor_cp_owners_app_path_size = EI_INIT;
305 static expert_field ei_mal_ssupervisor_proposed_tunid = EI_INIT;
306 
307 static expert_field ei_mal_svalidator_type = EI_INIT;
308 static expert_field ei_mal_svalidator_time_coord_msg_min_mult = EI_INIT;
309 static expert_field ei_mal_svalidator_network_time_multiplier = EI_INIT;
310 static expert_field ei_mal_svalidator_timeout_multiplier = EI_INIT;
311 static expert_field ei_mal_svalidator_coordination_conn_inst = EI_INIT;
312 static expert_field ei_mal_svalidator_prod_cons_fault_count = EI_INIT;
313 
314 static dissector_handle_t cipsafety_handle;
315 static dissector_handle_t cipsafety_base_data_handle;
316 static dissector_handle_t cipsafety_extended_data_handle;
317 static dissector_handle_t cipsafety_base_time_coord_handle;
318 static dissector_handle_t cipsafety_extended_time_coord_handle;
319 
320 typedef struct cip_safety_packet_data {
321    guint16 rollover_value;
322    guint16 timestamp_value;
323 } cip_safety_packet_data_t;
324 
325 #define MODE_BYTE_CRC_S1_MASK  0xE0
326 #define MODE_BYTE_CRC_S1_TIME_STAMP_MASK  0x1F
327 #define MODE_BYTE_CRC_S3_MASK  0xE0
328 #define MODE_BYTE_CRC_S5_BASE_MASK  0xE0
329 #define MODE_BYTE_CRC_S5_EXTENDED_MASK  0x1F
330 
331 const value_string cipsafety_snn_date_vals[8] = {
332 
333    { 0,     "NULL SNN" },
334    { 1,     "Manual Setting - Backplane" },
335    { 2,     "Manual Setting - ControlNet" },
336    { 4,     "Manual Setting - EtherNet/IP" },
337    { 5,     "Manual Setting - DeviceNet" },
338    { 6,     "Manual Setting - SERCOS III" },
339    { 65535, "No SNN Set" },
340 
341    { 0,     NULL }
342 };
343 
344 static const true_false_string cip_safety_vals_active_idle = {
345    "Active",
346    "Idle",
347 };
348 
349 /* Translate function to string - CIP Service codes for Safety Supervisor */
350 static const value_string cip_sc_vals_ssupervisor[] = {
351    GENERIC_SC_LIST
352 
353    /* Some class specific services */
354    { SC_SSUPER_RECOVER,                "Recover" },
355    { SC_SSUPER_PERFORM_DIAGNOSTICS,    "Perform Diagnostics" },
356    { SC_SSUPER_CONFIGURE_REQUEST,      "Configure Request" },
357    { SC_SSUPER_VALIDATE_CONFIGURATION, "Validate Configuration" },
358    { SC_SSUPER_SET_PASSWORD,           "Set Password" },
359    { SC_SSUPER_CONFIGURATION_LOCK,     "Configuration (Un)Lock" },
360    { SC_SSUPER_MODE_CHANGE,            "Mode Change" },
361    { SC_SSUPER_SAFETY_RESET,           "Safety Reset" },
362    { SC_SSUPER_RESET_PASSWORD,         "Reset Password" },
363    { SC_SSUPER_PROPOSE_TUNID,          "Propose TUNID" },
364    { SC_SSUPER_APPLY_TUNID,            "Apply TUNID" },
365    { SC_SSUPER_PROPOSE_TUNID_LIST,     "Propose TUNID List" },
366    { SC_SSUPER_APPLY_TUNID_LIST,       "Apply TUNID List" },
367 
368    { 0,                       NULL }
369 };
370 
371 #define SC_SVALID_RESET_ERROR                 0x4B
372 
373 /* Translate function to string - CIP Service codes for Safety Validator */
374 static const value_string cip_sc_vals_svalidator[] = {
375    GENERIC_SC_LIST
376 
377    /* Some class specific services */
378    { SC_SVALID_RESET_ERROR,                "Reset Error" },
379 
380    { 0,                       NULL }
381 };
382 
383 static const value_string cip_ssupervisor_validate_configuration_ext_error_vals[] = {
384    { 1,        "CRC mismatch" },
385    { 2,        "Invalid Configuration Parameter"     },
386    { 3,        "TUNID Not Set"     },
387 
388    { 0,        NULL          }
389 };
390 
391 static const value_string cip_ssupervisor_lock_vals[] = {
392    { 0,        "Unlocked" },
393    { 1,        "Locked"     },
394 
395    { 0,        NULL          }
396 };
397 
398 static const value_string cip_ssupervisor_change_mode_vals[] = {
399    { 0,        "Idle" },
400    { 1,        "Executing"   },
401 
402    { 0,        NULL          }
403 };
404 
405 static const value_string cip_ssupervisor_device_status_type_vals[] = {
406    { 0,        "Undefined" },
407    { 1,        "Self-Testing"   },
408    { 2,        "Idle"   },
409    { 3,        "Self-Testing Exception"   },
410    { 4,        "Executing"   },
411    { 5,        "Abort"   },
412    { 6,        "Critical Fault"   },
413    { 7,        "Configuring"   },
414    { 8,        "Waiting for TUNID"   },
415    { 51,       "Waiting for TUNID with Torque Permitted" },
416    { 52,       "Executing with Torque Permitted" },
417 
418    { 0,        NULL          }
419 };
420 
421 static const value_string cip_ssupervisor_clock_power_cycle_type_vals[] = {
422    { 0,        "Clock always resets" },
423    { 1,        "Clock in NVS at power down"   },
424    { 2,        "Clock is battery-backed"   },
425 
426    { 0,        NULL          }
427 };
428 
429 static const value_string cip_svalidator_state_vals[] = {
430    { 0,        "Unallocated" },
431    { 1,        "Initializing"   },
432    { 2,        "Established"   },
433    { 3,        "Connection failed"   },
434 
435    { 0,        NULL          }
436 };
437 
438 static const value_string cip_svalidator_type_pc_vals[] = {
439    { 0,        "Producer" },
440    { 1,        "Consumer" },
441 
442    { 0,        NULL          }
443 };
444 
445 static const value_string cip_svalidator_type_conn_type_vals[] = {
446    { 0,        "Unallocated" },
447    { 1,        "Single-cast" },
448    { 2,        "Multi-cast"  },
449 
450    { 0,        NULL          }
451 };
452 
453 void
454 dissect_unid(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_item *pi,
455              const char* snn_name, int hf_snn_timestamp,
456              int hf_snn_date, int hf_snn_time, int hf_nodeid, gint ett, gint ett_snn)
457 {
458    proto_tree *tree, *snn_tree;
459 
460    tree = proto_item_add_subtree(pi, ett);
461 
462    snn_tree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_snn, NULL, snn_name);
463    dissect_cipsafety_snn(snn_tree, tvb, pinfo, offset, hf_snn_timestamp, hf_snn_date, hf_snn_time);
464 
465    proto_tree_add_item(tree, hf_nodeid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
466 }
467 
468 void dissect_cipsafety_snn(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
469                            int hf_real_datetime, int hf_date, int hf_time)
470 {
471    guint16 date;
472 
473    date = tvb_get_letohs(tvb, offset+4);
474 
475    if ((date >= 11688) && (date <= 65534))
476    {
477       /* value is an actual timestamp */
478       dissect_cip_date_and_time(tree, tvb, offset, hf_real_datetime);
479    }
480    else
481    {
482       /* Treated as UINT16 and UINT32 values */
483       proto_tree_add_item(tree, hf_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
484       proto_tree_add_item(tree, hf_date, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
485    }
486 }
487 
488 static void dissect_safety_supervisor_safety_reset(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
489 {
490    guint32 reset_type;
491    proto_tree_add_item_ret_uint(cmd_data_tree, hf_cip_ssupervisor_reset_type, tvb, offset, 1, ENC_LITTLE_ENDIAN, &reset_type);
492 
493    proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password, tvb, offset + 1, 16, ENC_NA);
494    proto_item* pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_tunid, tvb, offset + 17, 10, ENC_NA);
495    dissect_unid(tvb, pinfo, offset + 17, pi, "TUNID SNN",
496       hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp,
497       hf_cip_ssupervisor_reset_tunid_tunid_snn_date,
498       hf_cip_ssupervisor_reset_tunid_tunid_snn_time,
499       hf_cip_ssupervisor_reset_tunid_nodeid,
500       ett_ssupervisor_reset_tunid,
501       ett_ssupervisor_reset_tunid_snn);
502 
503    /* Attribute bitmap only included on Reset Type 2 */
504    if (reset_type == 2)
505    {
506       pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_attr_bitmap, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
507 
508       proto_tree* bitmap_tree = proto_item_add_subtree(pi, ett_cip_ssupervisor_reset_attr_bitmap);
509       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_macid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
510       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_baudrate, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
511       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_tunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
512       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_password, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
513       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_cfunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
514       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_ocpunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
515       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_reserved, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
516       proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_extended, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
517    }
518 }
519 
520 /************************************************
521  *
522  * Dissector for CIP Safety Supervisor Object
523  *
524  ************************************************/
525 static void
526 dissect_cip_s_supervisor_data( proto_tree *item_tree,
527                                tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
528 {
529    proto_item                *pi, *rrsc_item;
530    proto_tree                *rrsc_tree, *cmd_data_tree;
531    int                        req_path_size;
532    int                        temp_data;
533    guint8                     service, gen_status, add_stat_size;
534    cip_simple_request_info_t  req_data;
535 
536    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Supervisor");
537 
538    /* Add Service code & Request/Response tree */
539    service   = tvb_get_guint8( tvb, offset );
540    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_ssupervisor_rrsc, &rrsc_item, "Service: " );
541 
542    /* Add Request/Response */
543    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
544 
545    proto_item_append_text( rrsc_item, "%s (%s)",
546                val_to_str( ( service & CIP_SC_MASK ), cip_sc_vals_ssupervisor , "Unknown Service (0x%02x)"),
547                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7, cip_sc_rr, "") );
548 
549    /* Add Service code */
550    proto_tree_add_item(rrsc_tree, hf_cip_ssupervisor_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
551 
552    load_cip_request_data(pinfo, &req_data);
553 
554    if (service & CIP_SC_RESPONSE_MASK)
555    {
556       /* Response message */
557 
558       /* Add additional status size */
559       gen_status = tvb_get_guint8( tvb, offset+2 );
560       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
561 
562       /* If there is any command specific data create a sub-tree for it */
563       if( ( item_length-4-add_stat_size ) != 0 )
564       {
565          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size,
566                          item_length-4-add_stat_size, ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
567 
568          if( gen_status == CI_GRC_SUCCESS )
569          {
570             switch (service & CIP_SC_MASK)
571             {
572             case SC_SSUPER_VALIDATE_CONFIGURATION:
573                proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
574                          tvb, offset+4+add_stat_size, 4, ENC_LITTLE_ENDIAN);
575                dissect_cipsafety_snn(cmd_data_tree,
576                          tvb, pinfo, offset+4+add_stat_size+4,
577                          hf_cip_ssupervisor_validate_configuration_scts_timestamp,
578                          hf_cip_ssupervisor_validate_configuration_scts_date,
579                          hf_cip_ssupervisor_validate_configuration_scts_time);
580                break;
581             }
582          }
583          else if ((gen_status == 0xD0) && ((service & CIP_SC_MASK) == SC_SSUPER_VALIDATE_CONFIGURATION))
584          {
585             if (add_stat_size > 0)
586             {
587                proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_ext_error,
588                          tvb, offset+4, 2, ENC_LITTLE_ENDIAN);
589             }
590          }
591          else
592          {
593             /* Error responses */
594 
595             /* Add data */
596             proto_tree_add_item(cmd_data_tree, hf_cip_data,
597                          tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
598          }
599       }
600 
601    } /* End of if reply */
602    else
603    {
604       /* Request message */
605 
606       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
607 
608       /* If there is any command specific data create a sub-tree for it */
609       if( (item_length-req_path_size-2) != 0 )
610       {
611          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
612                                    ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
613 
614          /* Check what service code that received */
615          switch (service)
616          {
617          case SC_SSUPER_RECOVER:
618             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_recover_data,
619                          tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
620             break;
621          case SC_SSUPER_PERFORM_DIAGNOSTICS:
622             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_perform_diag_data,
623                          tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
624             break;
625          case SC_SSUPER_CONFIGURE_REQUEST:
626             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_password,
627                          tvb, offset+2+req_path_size, 16, ENC_NA);
628             pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_tunid,
629                          tvb, offset+2+req_path_size+16, 10, ENC_NA);
630             dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "TUNID SNN",
631                          hf_cip_ssupervisor_configure_request_tunid_snn_timestamp,
632                          hf_cip_ssupervisor_configure_request_tunid_snn_date,
633                          hf_cip_ssupervisor_configure_request_tunid_snn_time,
634                          hf_cip_ssupervisor_configure_request_tunid_nodeid,
635                          ett_ssupervisor_configure_request_tunid,
636                          ett_ssupervisor_configure_request_tunid_snn);
637             pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_ounid,
638                                      tvb, offset+2+req_path_size+26, 10, ENC_NA);
639             dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "OUNID SNN",
640                          hf_cip_ssupervisor_configure_request_ounid_snn_timestamp,
641                          hf_cip_ssupervisor_configure_request_ounid_snn_date,
642                          hf_cip_ssupervisor_configure_request_ounid_snn_time,
643                          hf_cip_ssupervisor_configure_request_ounid_nodeid,
644                          ett_ssupervisor_configure_request_ounid,
645                          ett_ssupervisor_configure_request_ounid_snn);
646             break;
647          case SC_SSUPER_VALIDATE_CONFIGURATION:
648             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
649                          tvb, offset+2+req_path_size, 4, ENC_LITTLE_ENDIAN);
650             dissect_cipsafety_snn(cmd_data_tree, tvb, pinfo, offset+2+req_path_size+4,
651                          hf_cip_ssupervisor_validate_configuration_scts_timestamp,
652                          hf_cip_ssupervisor_validate_configuration_scts_date,
653                          hf_cip_ssupervisor_validate_configuration_scts_time);
654             break;
655          case SC_SSUPER_SET_PASSWORD:
656             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_current_password,
657                          tvb, offset+2+req_path_size, 16, ENC_NA);
658             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_new_password,
659                          tvb, offset+2+req_path_size+16, 16, ENC_NA);
660             break;
661          case SC_SSUPER_CONFIGURATION_LOCK:
662             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_value,
663                          tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
664             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_password,
665                          tvb, offset+2+req_path_size+1, 16, ENC_NA);
666             pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_tunid,
667                          tvb, offset+2+req_path_size+17, 10, ENC_NA);
668             dissect_unid(tvb, pinfo, offset+2+req_path_size+17, pi, "TUNID SNN",
669                          hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp,
670                          hf_cip_ssupervisor_configure_lock_tunid_snn_date,
671                          hf_cip_ssupervisor_configure_lock_tunid_snn_time,
672                          hf_cip_ssupervisor_configure_lock_tunid_nodeid,
673                          ett_ssupervisor_configure_lock_tunid,
674                          ett_ssupervisor_configure_lock_tunid_snn);
675             break;
676          case SC_SSUPER_MODE_CHANGE:
677             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_value,
678                          tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
679             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_password,
680                          tvb, offset+2+req_path_size+1, 16, ENC_NA);
681             break;
682          case SC_SSUPER_SAFETY_RESET:
683             dissect_safety_supervisor_safety_reset(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
684             break;
685          case SC_SSUPER_RESET_PASSWORD:
686             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data_size,
687                          tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
688             temp_data = tvb_get_guint8(tvb, offset+2+req_path_size);
689             proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data,
690                          tvb, offset+2+req_path_size+1, temp_data, ENC_NA);
691             break;
692          case SC_SSUPER_PROPOSE_TUNID:
693             pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_propose_tunid_tunid,
694                          tvb, offset+2+req_path_size, 10, ENC_NA);
695             dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SNN",
696                          hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp,
697                          hf_cip_ssupervisor_propose_tunid_tunid_snn_date,
698                          hf_cip_ssupervisor_propose_tunid_tunid_snn_time,
699                          hf_cip_ssupervisor_propose_tunid_tunid_nodeid,
700                          ett_ssupervisor_propose_tunid,
701                          ett_ssupervisor_propose_tunid_snn);
702             break;
703          case SC_SSUPER_APPLY_TUNID:
704             pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_apply_tunid_tunid,
705                          tvb, offset+2+req_path_size, 10, ENC_NA);
706             dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SNN",
707                          hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp,
708                          hf_cip_ssupervisor_apply_tunid_tunid_snn_date,
709                          hf_cip_ssupervisor_apply_tunid_tunid_snn_time,
710                          hf_cip_ssupervisor_apply_tunid_tunid_nodeid,
711                          ett_ssupervisor_apply_tunid,
712                          ett_ssupervisor_apply_tunid_snn);
713             break;
714          default:
715             proto_tree_add_item(cmd_data_tree, hf_cip_data,
716                          tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
717          }
718 
719       } /* End of if command-specific data present */
720 
721    } /* End of if-else( request ) */
722 
723    add_cip_service_to_info_column(pinfo, service, cip_sc_vals_ssupervisor);
724 }
725 
726 static int
727 dissect_cip_class_s_supervisor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
728 {
729    proto_item *ti;
730    proto_tree *class_tree;
731 
732    /* Create display subtree for the protocol */
733    ti = proto_tree_add_item(tree, proto_cip_class_s_supervisor, tvb, 0, -1, ENC_NA);
734    class_tree = proto_item_add_subtree( ti, ett_cip_class_s_supervisor );
735 
736    dissect_cip_s_supervisor_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
737 
738    return tvb_reported_length(tvb);
739 }
740 
741 static int dissect_s_supervisor_exception_detail(proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int hf_size, int hf_data)
742 {
743    guint32 size;
744    proto_tree_add_item_ret_uint(tree, hf_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
745 
746    proto_tree_add_item(tree, hf_data, tvb, offset+1, size, ENC_NA );
747    proto_item_set_len(item, size+1);
748 
749    return size+1;
750 }
751 
752 static int dissect_s_supervisor_exception_detail_common(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
753                              int offset, int total_len)
754 {
755    proto_item *pi;
756    proto_tree *item_tree;
757    int total_size = 0, size;
758 
759    item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_common, &pi, "Common Exception Detail");
760    size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
761                hf_cip_ssupervisor_exception_detail_ced_size,
762                hf_cip_ssupervisor_exception_detail_ced_detail);
763    if (size == 0)
764    {
765       expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_ced);
766       return total_len;
767    }
768    total_size += size;
769 
770    item_tree = proto_tree_add_subtree(tree, tvb, offset + total_size, 1, ett_exception_detail_device, &pi, "Device Exception Detail");
771    size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset + total_size,
772                hf_cip_ssupervisor_exception_detail_ded_size,
773                hf_cip_ssupervisor_exception_detail_ded_detail);
774    if (size == 0)
775    {
776       expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_ded);
777       return total_len;
778    }
779    total_size += size;
780 
781    item_tree = proto_tree_add_subtree(tree, tvb, offset + total_size, 1, ett_exception_detail_manufacturer, &pi, "Manufacturer Exception Detail");
782    size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset + total_size,
783                hf_cip_ssupervisor_exception_detail_med_size,
784                hf_cip_ssupervisor_exception_detail_med_detail);
785    if (size == 0)
786    {
787       expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_med);
788       return total_len;
789    }
790    total_size += size;
791 
792    return total_size;
793 }
794 
795 static int dissect_s_supervisor_configuration_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
796                                                    tvbuff_t *tvb, int offset, int total_len)
797 {
798    if (total_len < 10)
799    {
800       expert_add_info(pinfo, item, &ei_mal_ssupervisor_configuration_unid);
801       return total_len;
802    }
803 
804    dissect_unid(tvb, pinfo, offset, item, "CFUNID SNN",
805                   hf_cip_ssupervisor_configuration_unid_snn_timestamp,
806                   hf_cip_ssupervisor_configuration_unid_snn_date,
807                   hf_cip_ssupervisor_configuration_unid_snn_time,
808                   hf_cip_ssupervisor_configuration_unid_nodeid,
809                   ett_ssupervisor_configuration_unid,
810                   ett_ssupervisor_configuration_unid_snn);
811    return 10;
812 }
813 
814 static int dissect_s_supervisor_safety_configuration_id(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
815                                                         tvbuff_t *tvb, int offset, int total_len)
816 {
817    if (total_len < 10)
818    {
819       expert_add_info(pinfo, item, &ei_mal_ssupervisor_safety_configuration_id);
820       return total_len;
821    }
822 
823    proto_tree_add_item(tree, hf_cip_ssupervisor_safety_configuration_id_sccrc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
824 
825    dissect_cipsafety_snn(tree, tvb, pinfo, offset + 4,
826       hf_cip_ssupervisor_safety_configuration_id_snn_timestamp,
827       hf_cip_ssupervisor_safety_configuration_id_snn_date,
828       hf_cip_ssupervisor_safety_configuration_id_snn_time);
829 
830    return 10;
831 }
832 
833 static int dissect_s_supervisor_target_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
834                                             tvbuff_t *tvb, int offset, int total_len)
835 {
836    if (total_len < 10)
837    {
838       expert_add_info(pinfo, item, &ei_mal_ssupervisor_target_unid);
839       return total_len;
840    }
841 
842    dissect_unid(tvb, pinfo, offset, item, "TUNID SNN",
843                   hf_cip_ssupervisor_target_unid_snn_timestamp,
844                   hf_cip_ssupervisor_target_unid_snn_date,
845                   hf_cip_ssupervisor_target_unid_snn_time,
846                   hf_cip_ssupervisor_target_unid_nodeid,
847                   ett_ssupervisor_target_unid,
848                   ett_ssupervisor_target_unid_snn);
849    return 10;
850 }
851 
852 static int dissect_s_supervisor_output_connection_point_owners(packet_info *pinfo, proto_tree *tree, proto_item *item,
853                                                                tvbuff_t *tvb, int offset, int total_len)
854 {
855    guint16     i, num_entries;
856    proto_item *entry_item, *app_path_item;
857    proto_tree *entry_tree, *epath_tree;
858    int         attr_len = 0, app_path_size;
859 
860    if (total_len < 2)
861    {
862       expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners);
863       return total_len;
864    }
865 
866    entry_item = proto_tree_add_item(tree, hf_cip_ssupervisor_cp_owners_num_entries,
867                          tvb, offset, 2, ENC_LITTLE_ENDIAN );
868    num_entries = tvb_get_letohs(tvb, offset);
869    attr_len += 2;
870 
871    if (num_entries > 0)
872    {
873       entry_tree = proto_item_add_subtree(entry_item, ett_ssupervisor_output_cp_owners);
874 
875       for (i = 0; i < num_entries; i++)
876       {
877          if (total_len < attr_len+11)
878          {
879             expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_entry);
880             return total_len;
881          }
882 
883          dissect_unid(tvb, pinfo, offset+attr_len, entry_item, "OCPUNID SNN",
884                          hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp,
885                          hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date,
886                          hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time,
887                          hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid,
888                          ett_ssupervisor_output_cp_owners_ocpunid,
889                          ett_ssupervisor_output_cp_owners_ocpunid_snn);
890          attr_len += 10;
891 
892          proto_tree_add_item(entry_tree, hf_cip_ssupervisor_cp_owners_app_path_size,
893                          tvb, offset+attr_len, 1, ENC_LITTLE_ENDIAN );
894          app_path_size = tvb_get_guint8( tvb, offset+attr_len);
895          attr_len += 1;
896 
897          if (total_len < attr_len+app_path_size)
898          {
899             expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_app_path_size);
900             return total_len;
901          }
902 
903          epath_tree = proto_tree_add_subtree(entry_tree,
904                          tvb, offset+attr_len, app_path_size, ett_path, &app_path_item, "Application Resource: ");
905          dissect_epath(tvb, pinfo, epath_tree, app_path_item, offset+attr_len, app_path_size, FALSE, TRUE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
906          attr_len += app_path_size;
907       }
908    }
909 
910    return attr_len;
911 }
912 
913 static int dissect_s_supervisor_proposed_tunid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
914                                                tvbuff_t *tvb, int offset, int total_len)
915 {
916    if (total_len < 10)
917    {
918       expert_add_info(pinfo, item, &ei_mal_ssupervisor_proposed_tunid);
919       return total_len;
920    }
921 
922    dissect_unid(tvb, pinfo, offset, item, "Proposed TUNID SNN",
923                   hf_cip_ssupervisor_proposed_tunid_snn_timestamp,
924                   hf_cip_ssupervisor_proposed_tunid_snn_date,
925                   hf_cip_ssupervisor_proposed_tunid_snn_time,
926                   hf_cip_ssupervisor_proposed_tunid_nodeid,
927                   ett_ssupervisor_proposed_tunid,
928                   ett_ssupervisor_proposed_tunid_snn);
929 
930    return 10;
931 }
932 
933 /************************************************
934  *
935  * Dissector for CIP Safety Validator Object
936  *
937  ************************************************/
938 static int dissect_s_validator_type(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
939                                     int offset, int total_len)
940 {
941    if (total_len < 1)
942    {
943       expert_add_info(pinfo, item, &ei_mal_svalidator_type);
944       return total_len;
945    }
946 
947    static int* const bits[] = {
948       &hf_cip_svalidator_type_pc,
949       &hf_cip_svalidator_type_conn_type,
950       NULL
951    };
952    proto_tree_add_bitmask(tree, tvb, offset, hf_cip_svalidator_type, ett_svalidator_type, bits, ENC_LITTLE_ENDIAN);
953 
954    return 1;
955 }
956 
957 static int dissect_s_validator_time_coord_msg_min_mult(packet_info *pinfo, proto_tree *tree, proto_item *item,
958                                                        tvbuff_t *tvb, int offset, int total_len)
959 {
960    int i, size;
961 
962    proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_size,
963                          tvb, offset, 1, ENC_LITTLE_ENDIAN );
964    size = tvb_get_guint8( tvb, offset )*2;
965 
966    if (total_len < size+1)
967    {
968       expert_add_info(pinfo, item, &ei_mal_svalidator_time_coord_msg_min_mult);
969       return total_len;
970    }
971 
972    for (i = 0; i < size; i+=2)
973    {
974       proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_item,
975                          tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
976    }
977 
978    return (size+1);
979 }
980 
981 static int dissect_s_validator_network_time_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item,
982                                                        tvbuff_t *tvb, int offset, int total_len)
983 {
984    int i, size;
985 
986    proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_size,
987                        tvb, offset, 1, ENC_LITTLE_ENDIAN );
988    size = tvb_get_guint8( tvb, offset )*2;
989 
990    if (total_len < size+1)
991    {
992       expert_add_info(pinfo, item, &ei_mal_svalidator_network_time_multiplier);
993       return total_len;
994    }
995 
996    for (i = 0; i < size; i+=2)
997    {
998       proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_item,
999                           tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
1000    }
1001 
1002    return (size+1);
1003 }
1004 
1005 static int dissect_s_validator_timeout_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1006                              int offset, int total_len)
1007 {
1008    int i, size;
1009 
1010    proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_size,
1011                        tvb, offset, 1, ENC_LITTLE_ENDIAN );
1012    size = tvb_get_guint8( tvb, offset );
1013 
1014    if (total_len < size+1)
1015    {
1016       expert_add_info(pinfo, item, &ei_mal_svalidator_timeout_multiplier);
1017       return total_len;
1018    }
1019 
1020    for (i = 0; i < size; i++)
1021    {
1022       proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_item,
1023                           tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
1024    }
1025 
1026    return (size+1);
1027 }
1028 
1029 static int dissect_s_validator_coordination_conn_inst(packet_info *pinfo, proto_tree *tree, proto_item *item,
1030                                                       tvbuff_t *tvb, int offset, int total_len)
1031 {
1032    int i, size;
1033 
1034    proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_size,
1035                        tvb, offset, 1, ENC_LITTLE_ENDIAN );
1036    size = tvb_get_guint8( tvb, offset )*2;
1037 
1038    if (total_len < size+1)
1039    {
1040       expert_add_info(pinfo, item, &ei_mal_svalidator_coordination_conn_inst);
1041       return total_len;
1042    }
1043 
1044    for (i = 0; i < size; i+=2)
1045    {
1046       proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_item,
1047                           tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
1048    }
1049 
1050    return (size+1);
1051 }
1052 
1053 static int dissect_s_validator_app_data_path(packet_info *pinfo, proto_tree *tree,
1054                                              proto_item *item _U_, tvbuff_t *tvb, int offset, int total_len)
1055 {
1056    proto_item* pi;
1057    proto_tree* epath_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_path, &pi, "Application Data Path: ");
1058    dissect_epath(tvb, pinfo, epath_tree, pi, offset, total_len, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
1059    return total_len;
1060 }
1061 
1062 static int dissect_s_validator_prod_cons_fault_count(packet_info *pinfo, proto_tree *tree, proto_item *item,
1063                                                      tvbuff_t *tvb, int offset, int total_len)
1064 {
1065    int i, size;
1066 
1067    proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_size,
1068                          tvb, offset, 1, ENC_LITTLE_ENDIAN );
1069    size = tvb_get_guint8( tvb, offset );
1070 
1071    if (total_len < size+1)
1072    {
1073       expert_add_info(pinfo, item, &ei_mal_svalidator_prod_cons_fault_count);
1074       return total_len;
1075    }
1076 
1077    for (i = 0; i < size; i++)
1078    {
1079       proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_item,
1080                          tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
1081    }
1082 
1083    return (size+1);
1084 }
1085 
1086 static void
1087 dissect_cip_s_validator_data( proto_tree *item_tree,
1088                               tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
1089 {
1090    proto_item                *pi, *rrsc_item;
1091    proto_tree                *rrsc_tree, *cmd_data_tree;
1092    int                        req_path_size;
1093    guint8                     service, gen_status, add_stat_size;
1094    cip_simple_request_info_t  req_data;
1095 
1096    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Validator");
1097 
1098    /* Add Service code & Request/Response tree */
1099    service   = tvb_get_guint8( tvb, offset );
1100    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_svalidator_rrsc, &rrsc_item, "Service: " );
1101 
1102    /* Add Request/Response */
1103    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
1104 
1105    proto_item_append_text( rrsc_item, "%s (%s)",
1106                val_to_str( ( service & CIP_SC_MASK ),
1107                   cip_sc_vals_svalidator , "Unknown Service (0x%02x)"),
1108                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
1109                   cip_sc_rr, "") );
1110 
1111    /* Add Service code */
1112    proto_tree_add_item(rrsc_tree, hf_cip_svalidator_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
1113 
1114    load_cip_request_data(pinfo, &req_data);
1115 
1116    if (service & CIP_SC_RESPONSE_MASK)
1117    {
1118       /* Response message */
1119 
1120       /* Add additional status size */
1121       gen_status = tvb_get_guint8( tvb, offset+2 );
1122       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
1123 
1124       /* If there is any command specific data create a sub-tree for it */
1125       if( ( item_length-4-add_stat_size ) != 0 )
1126       {
1127          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
1128                                 ett_ssupervisor_cmd_data, &pi, "Command Specific Data" );
1129 
1130          if( gen_status == CI_GRC_SUCCESS )
1131          {
1132             /* Success responses */
1133             if (((service & CIP_SC_MASK) == SC_GET_ATT_ALL) &&
1134                 (req_data.iInstance != SEGMENT_VALUE_NOT_SET) &&
1135                 (req_data.iInstance != 0))
1136             {
1137                 dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset + 4 + add_stat_size, &req_data);
1138             }
1139             else
1140             {
1141                /* Add data */
1142                proto_tree_add_item(cmd_data_tree, hf_cip_data,
1143                                    tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
1144             }
1145          }
1146          else
1147          {
1148             /* Error responses */
1149 
1150             /* Add data */
1151             proto_tree_add_item(cmd_data_tree, hf_cip_data,
1152                                 tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
1153          } /* end of if-else( CI_CRC_SUCCESS ) */
1154 
1155       } /* End of if command-specific data present */
1156 
1157    } /* End of if reply */
1158    else
1159    {
1160       /* Request message */
1161 
1162       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
1163 
1164       /* If there is any command specific data create a sub-tree for it */
1165       if( (item_length-req_path_size-2) != 0 )
1166       {
1167          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
1168                                                 ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
1169          proto_tree_add_item(cmd_data_tree, hf_cip_data,
1170                          tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
1171       }
1172 
1173    }
1174 
1175    add_cip_service_to_info_column(pinfo, service, cip_sc_vals_svalidator);
1176 }
1177 
1178 static int
1179 dissect_cip_class_s_validator(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1180 {
1181    proto_item *ti;
1182    proto_tree *class_tree;
1183 
1184    /* Create display subtree for the protocol */
1185    ti = proto_tree_add_item(tree, proto_cip_class_s_validator, tvb, 0, -1, ENC_NA);
1186    class_tree = proto_item_add_subtree( ti, ett_cip_class_s_validator );
1187 
1188    dissect_cip_s_validator_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
1189 
1190    return tvb_reported_length(tvb);
1191 }
1192 
1193 static gboolean
1194 dissect_class_svalidator_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1195 {
1196    unsigned char   service, service_code, ioilen, segment;
1197    cip_req_info_t* preq_info;
1198    guint32         classid = 0;
1199    int             offset  = 0;
1200 
1201    service = tvb_get_guint8( tvb, offset );
1202    service_code = service & CIP_SC_MASK;
1203 
1204    /* Handle GetAttributeAll and SetAttributeAll in CCO class */
1205    if (service_code == SC_GET_ATT_ALL)
1206    {
1207       if (service & CIP_SC_RESPONSE_MASK)
1208       {
1209          /* Service response */
1210          preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
1211          if ((preq_info != NULL) &&
1212              (preq_info->dissector == dissector_get_uint_handle( subdissector_class_table, CI_CLS_SAFETY_VALIDATOR)))
1213          {
1214             call_dissector(preq_info->dissector, tvb, pinfo, tree);
1215             return TRUE;
1216          }
1217       }
1218       else
1219       {
1220          /* Service request */
1221          ioilen = tvb_get_guint8( tvb, offset + 1 );
1222          if (ioilen > 1)
1223          {
1224             segment = tvb_get_guint8( tvb, offset + 2 );
1225             if (((segment & CI_SEGMENT_TYPE_MASK) == CI_LOGICAL_SEGMENT) &&
1226                 ((segment & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_CLASS_ID))
1227             {
1228                /* Logical Class ID, do a format check */
1229                switch ( segment & CI_LOGICAL_SEG_FORMAT_MASK )
1230                {
1231                case CI_LOGICAL_SEG_8_BIT:
1232                   classid = tvb_get_guint8( tvb, offset + 3 );
1233                   break;
1234                case CI_LOGICAL_SEG_16_BIT:
1235                   if ( ioilen >= 2 )
1236                      classid = tvb_get_letohs( tvb, offset + 4 );
1237                   break;
1238                case CI_LOGICAL_SEG_32_BIT:
1239                   if ( ioilen >= 3 )
1240                      classid = tvb_get_letohl( tvb, offset + 4 );
1241                   break;
1242                }
1243             }
1244          }
1245 
1246          if (classid == CI_CLS_SAFETY_VALIDATOR)
1247          {
1248             call_dissector(cip_class_s_validator_handle, tvb, pinfo, tree );
1249             return TRUE;
1250          }
1251 
1252       }
1253    }
1254 
1255    return FALSE;
1256 }
1257 
1258 /************************************************
1259  *
1260  * CRC handling
1261  *
1262  ************************************************/
1263 static guint8 compute_crc_s1_pid(const cip_connection_triad_t* triad)
1264 {
1265     guint8 temp_buf[8];
1266     memcpy(temp_buf, &triad->VendorID, 2);
1267     memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1268     memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1269 
1270     return crc8_0x37(temp_buf, 8, 0);
1271 }
1272 
1273 static guint8 compute_crc_s1_timestamp(guint8 pid_seed, guint8 mode_byte_mask, guint16 timestamp)
1274 {
1275     guint8 mode_byte_crc = crc8_0x37(&mode_byte_mask, 1, pid_seed);
1276     guint8 timestamp_crc = crc8_0x37((guint8*)&timestamp, 2, mode_byte_crc);
1277 
1278     return timestamp_crc;
1279 }
1280 
1281 static guint8 compute_crc_s1_data(guint8 pid_seed, guint8 mode_byte_mask, const guint8 *buf, int len)
1282 {
1283     guint8 mode_byte_crc = crc8_0x37(&mode_byte_mask, 1, pid_seed);
1284 
1285     return crc8_0x37(buf, len, mode_byte_crc);
1286 }
1287 
1288 static guint8 compute_crc_s2_data(guint8 pid_seed, guint8 mode_byte_mask, guint8 *comp_buf, int len)
1289 {
1290     int i;
1291     guint8 mode_byte_crc = crc8_0x3B(&mode_byte_mask, 1, pid_seed);
1292 
1293     for (i = 0; i < len; i++)
1294         comp_buf[i] ^= 0xFF;
1295 
1296     return crc8_0x3B(comp_buf, len, mode_byte_crc);
1297 }
1298 
1299 static guint16 compute_crc_s3_pid(const cip_connection_triad_t* triad)
1300 {
1301     guint8 temp_buf[8];
1302     memcpy(temp_buf, &triad->VendorID, 2);
1303     memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1304     memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1305 
1306     return crc16_0x080F_seed(temp_buf, 8, 0);
1307 }
1308 
1309 static guint16 compute_crc_s3_base_data(guint16 pid_seed, guint8 mode_byte_mask, const guint8 *buf, int len)
1310 {
1311     guint16 mode_byte_crc = crc16_0x080F_seed(&mode_byte_mask, 1, pid_seed);
1312 
1313     return crc16_0x080F_seed(buf, len, mode_byte_crc);
1314 }
1315 
1316 static guint16 compute_crc_s3_extended_data(guint16 pid_seed, guint16 rollover_value, guint8 mode_byte_mask, const guint8 *buf, int len)
1317 {
1318     guint16 rollover_crc = crc16_0x080F_seed((guint8*)&rollover_value, 2, pid_seed);
1319     guint16 mode_byte_crc = crc16_0x080F_seed(&mode_byte_mask, 1, rollover_crc);
1320 
1321     return crc16_0x080F_seed(buf, len, mode_byte_crc);
1322 }
1323 
1324 static guint16 compute_crc_s3_time(guint16 pid_seed, guint8 ack_mcast_byte, guint16 timestamp_value)
1325 {
1326     guint16 mode_byte_crc = crc16_0x080F_seed(&ack_mcast_byte, 1, pid_seed);
1327     guint16 timestamp_crc;
1328 
1329     timestamp_crc = crc16_0x080F_seed((guint8*)&timestamp_value, 2, mode_byte_crc);
1330 
1331     return timestamp_crc;
1332 }
1333 
1334 static guint32 compute_crc_s5_pid(const cip_connection_triad_t* triad)
1335 {
1336     guint8 temp_buf[8];
1337     memcpy(temp_buf, &triad->VendorID, 2);
1338     memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1339     memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1340 
1341     return crc32_0x5D6DCB_seed(temp_buf, 8, 0);
1342 }
1343 
1344 static guint32 compute_crc_s5_short_data(guint32 pid_seed, guint16 rollover_value, guint8 mode_byte_mask, guint16 timestamp_value, const guint8 *buf, int len)
1345 {
1346     guint32 rollover_crc = crc32_0x5D6DCB_seed((guint8*)&rollover_value, 2, pid_seed);
1347     guint32 mode_byte_crc = crc32_0x5D6DCB_seed(&mode_byte_mask, 1, rollover_crc);
1348     guint32 data_crc, timestamp_crc;
1349 
1350     data_crc = crc32_0x5D6DCB_seed(buf, len, mode_byte_crc);
1351     timestamp_crc = crc32_0x5D6DCB_seed((guint8*)&timestamp_value, 2, data_crc);
1352 
1353     return timestamp_crc;
1354 }
1355 
1356 static guint32 compute_crc_s5_long_data(guint32 pid_seed, guint16 rollover_value, guint8 mode_byte_mask, guint16 timestamp_value, guint8 *comp_buf, int len)
1357 {
1358     int i;
1359     guint32 rollover_crc = crc32_0x5D6DCB_seed((guint8*)&rollover_value, 2, pid_seed);
1360     guint32 mode_byte_crc = crc32_0x5D6DCB_seed(&mode_byte_mask, 1, rollover_crc);
1361     guint32 comp_data_crc, timestamp_crc;
1362 
1363     for (i = 0; i < len; i++)
1364         comp_buf[i] ^= 0xFF;
1365 
1366     comp_data_crc = crc32_0x5D6DCB_seed(comp_buf, len, mode_byte_crc);
1367     timestamp_crc = crc32_0x5D6DCB_seed((guint8*)&timestamp_value, 2, comp_data_crc);
1368 
1369     return timestamp_crc;
1370 }
1371 
1372 static guint32 compute_crc_s5_time(guint32 pid_seed, guint8 ack_mcast_byte, guint16 timestamp_value)
1373 {
1374     guint32 mode_byte_crc = crc32_0x5D6DCB_seed(&ack_mcast_byte, 1, pid_seed);
1375     guint32 timestamp_crc;
1376 
1377     timestamp_crc = crc32_0x5D6DCB_seed((guint8*)&timestamp_value, 2, mode_byte_crc);
1378 
1379     return timestamp_crc;
1380 }
1381 
1382 static gboolean verify_compliment_data(tvbuff_t *tvb, int data_offset, int complement_data_offset, int data_size)
1383 {
1384     const guint8 *data = tvb_get_ptr(tvb, data_offset, data_size);
1385     const guint8 *complement_data = tvb_get_ptr(tvb, complement_data_offset, data_size);
1386     int i;
1387 
1388     for (i = 0; i < data_size; i++)
1389     {
1390         if ((data[i] ^ complement_data[i])!= 0xFF)
1391             return FALSE;
1392     }
1393 
1394     return TRUE;
1395 }
1396 
1397 static void validate_crc_s5(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, gboolean compute_crc,
1398    guint32 crc_s5_0, guint32 crc_s5_1, guint32 crc_s5_2, guint32 computed_crc_s5)
1399 {
1400    proto_item* crc_s5_status_item;
1401 
1402    /* CRC-S5 doesn't use proto_tree_add_checksum because the checksum is broken up into multiple fields */
1403    if (compute_crc)
1404    {
1405       guint32 value_s5 = crc_s5_0;
1406       value_s5 += ((crc_s5_1 << 8) & 0xFF00);
1407       value_s5 += ((crc_s5_2 << 16) & 0xFF0000);
1408 
1409       if (computed_crc_s5 == value_s5)
1410       {
1411          crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_GOOD);
1412       }
1413       else
1414       {
1415          crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_BAD);
1416          expert_add_info_format(pinfo, crc_s5_status_item, &ei_cipsafety_crc_s5, "%s [should be 0x%08x]", expert_get_summary(&ei_cipsafety_crc_s5), computed_crc_s5);
1417       }
1418    }
1419    else
1420    {
1421       crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_UNVERIFIED);
1422    }
1423 
1424    proto_item_set_generated(crc_s5_status_item);
1425 }
1426 
1427 /************************************************
1428  *
1429  * Dissector for CIP Safety I/O Data
1430  *
1431  ************************************************/
1432 static void
1433 dissect_mode_byte( proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
1434 {
1435    proto_item *mode_item, *run_idle_item, *tbd_item, *tbd2_item;
1436    proto_tree *mode_tree;
1437    guint8      mode_byte;
1438 
1439    mode_byte = tvb_get_guint8(tvb, offset);
1440 
1441    /* dissect Mode Byte bits */
1442    mode_item = proto_tree_add_item(tree, hf_cipsafety_mode_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1443    mode_tree = proto_item_add_subtree( mode_item, ett_cipsafety_mode_byte);
1444 
1445    proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_ping_count,               tvb, offset, 1, ENC_LITTLE_ENDIAN);
1446    proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_tbd,                  tvb, offset, 1, ENC_LITTLE_ENDIAN);
1447    proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_copy,               tvb, offset, 1, ENC_LITTLE_ENDIAN);
1448    proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_run_idle,             tvb, offset, 1, ENC_LITTLE_ENDIAN);
1449    tbd_item  = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd,          tvb, offset, 1, ENC_LITTLE_ENDIAN);
1450    tbd2_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_bit,    tvb, offset, 1, ENC_LITTLE_ENDIAN);
1451    run_idle_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_run_idle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1452 
1453    /* verify Mode Byte bits */
1454    /* TBD */
1455    if ((((mode_byte & 0x20) >> 5) & 0x01) == (((mode_byte & 0x04) >> 2) & 0x01))
1456       expert_add_info(pinfo, tbd_item, &ei_cipsafety_tbd2_not_complemented);
1457 
1458    /* TBD 2 */
1459    if ((((mode_byte & 0x40) >> 6) & 0x01) != (((mode_byte & 0x08) >> 3) & 0x01))
1460       expert_add_info(pinfo, tbd2_item, &ei_cipsafety_tbd_not_copied);
1461 
1462    /* Run/Idle */
1463    if ((((mode_byte & 0x80) >> 7) & 0x01) == (((mode_byte & 0x10) >> 4) & 0x01))
1464       expert_add_info(pinfo, run_idle_item, &ei_cipsafety_run_idle_not_complemented);
1465 }
1466 
1467 static void
1468 dissect_ack_byte( proto_tree *tree, tvbuff_t *tvb, int offset)
1469 {
1470    // TODO: add ack_byte validation
1471    static int* const bits[] = {
1472       &hf_cipsafety_ack_byte_ping_count_reply,
1473       &hf_cipsafety_ack_byte_reserved1,
1474       &hf_cipsafety_ack_byte_ping_response,
1475       &hf_cipsafety_ack_byte_reserved2,
1476       &hf_cipsafety_ack_byte_parity_even,
1477       NULL
1478    };
1479 
1480    proto_tree_add_bitmask(tree, tvb, offset, hf_cipsafety_ack_byte, ett_cipsafety_ack_byte, bits, ENC_LITTLE_ENDIAN);
1481 }
1482 
1483 static void
1484 dissect_mcast_byte( proto_tree *tree, tvbuff_t *tvb, int offset)
1485 {
1486    // TODO: add mcast_byte validation
1487    static int* const bits[] = {
1488       &hf_cipsafety_mcast_byte_consumer_num,
1489       &hf_cipsafety_mcast_byte_reserved1,
1490       &hf_cipsafety_mcast_byte_mai,
1491       &hf_cipsafety_mcast_byte_reserved2,
1492       &hf_cipsafety_mcast_byte_parity_even,
1493       NULL
1494    };
1495 
1496    proto_tree_add_bitmask(tree, tvb, offset, hf_cipsafety_mcast_byte, ett_cipsafety_mcast_byte, bits, ENC_LITTLE_ENDIAN);
1497 }
1498 
1499 static void
1500 dissect_cip_safety_data( proto_tree *tree, proto_item *item, tvbuff_t *tvb, int item_length, packet_info *pinfo, cip_safety_info_t* safety_info)
1501 {
1502    int base_length, io_data_size;
1503    gboolean multicast = in4_addr_is_multicast(pntoh32(pinfo->dst.data));
1504    gboolean server_dir = FALSE;
1505    enum enip_connid_type conn_type = ECIDT_UNKNOWN;
1506    enum cip_safety_format_type format = CIP_SAFETY_BASE_FORMAT;
1507    guint16 timestamp;
1508    guint8 mode_byte;
1509    cip_safety_packet_data_t* packet_data = NULL;
1510    proto_item *complement_item;
1511    gboolean short_format = TRUE;
1512    gboolean compute_crc = ((safety_info != NULL) && (safety_info->compute_crc == TRUE));
1513    cip_connection_triad_t connection_triad = {0};
1514 
1515    /* Make entries in Protocol column and Info column on summary display */
1516    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Safety");
1517 
1518    /* determine the connection type as it affects the fields dissected */
1519    if (safety_info != NULL && safety_info->eip_conn_info != NULL)
1520    {
1521       conn_type = safety_info->conn_type;
1522       format = safety_info->eip_conn_info->safety.format;
1523       server_dir = (safety_info->eip_conn_info->TransportClass_trigger & CI_PRODUCTION_DIR_MASK) ? TRUE : FALSE;
1524    }
1525 
1526    /* compute the base packet length to determine what is actual I/O data */
1527    base_length = multicast ? 12 : 6;
1528 
1529    if (item_length < base_length) {
1530       expert_add_info(pinfo, item, &ei_mal_io);
1531       return;
1532    }
1533 
1534    if (((conn_type == ECIDT_O2T) && (server_dir == FALSE)) ||
1535        ((conn_type == ECIDT_T2O) && (server_dir == TRUE)))
1536    {
1537       if (compute_crc)
1538       {
1539          if ((conn_type == ECIDT_O2T) && (server_dir == FALSE))
1540          {
1541             connection_triad = safety_info->eip_conn_info->triad;
1542          }
1543          else
1544          {
1545             connection_triad = safety_info->eip_conn_info->safety.target_triad;
1546          }
1547       }
1548 
1549       /* consumer data */
1550       dissect_ack_byte(tree, tvb, 0);
1551       proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
1552       timestamp = tvb_get_letohs(tvb, 1);
1553 
1554       switch (format)
1555       {
1556       case CIP_SAFETY_BASE_FORMAT:
1557          proto_tree_add_item(tree, hf_cipsafety_ack_byte2, tvb, 3, 1, ENC_LITTLE_ENDIAN);
1558          if (compute_crc)
1559          {
1560             proto_tree_add_checksum(tree, tvb, 4,
1561                         hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1562                         compute_crc_s3_time(compute_crc_s3_pid(&connection_triad),
1563                                                                 tvb_get_guint8(tvb, 0), /* ack byte */
1564                                                                 timestamp),
1565                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1566          }
1567          else
1568          {
1569             proto_tree_add_checksum(tree, tvb, 4,
1570                         hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1571                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1572          }
1573          break;
1574       case CIP_SAFETY_EXTENDED_FORMAT:
1575       {
1576          guint32 crc_s5_0, crc_s5_1, crc_s5_2;
1577          proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, 3, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
1578          proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, 4, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
1579          proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, 5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
1580 
1581          guint32 computed_crc_s5 = compute_crc_s5_time(compute_crc_s5_pid(&connection_triad),
1582             tvb_get_guint8(tvb, 0), /* ack byte */
1583             timestamp);
1584          validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1585 
1586          break;
1587       }
1588       }
1589    }
1590    else if (((conn_type == ECIDT_O2T) && (server_dir == TRUE)) ||
1591             ((conn_type == ECIDT_T2O) && (server_dir == FALSE)))
1592    {
1593       if (compute_crc)
1594       {
1595          if ((conn_type == ECIDT_O2T) && (server_dir == TRUE))
1596          {
1597             connection_triad = safety_info->eip_conn_info->triad;
1598          }
1599          else
1600          {
1601             connection_triad = safety_info->eip_conn_info->safety.target_triad;
1602          }
1603       }
1604 
1605       if (item_length-base_length > 2)
1606          short_format = FALSE;
1607 
1608       /* producer data */
1609       switch (format)
1610       {
1611       case CIP_SAFETY_BASE_FORMAT:
1612          if (short_format)
1613          {
1614             io_data_size = item_length-base_length;
1615 
1616             /* Short Format (1-2 bytes I/O data) */
1617             proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1618             dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1619             mode_byte = tvb_get_guint8(tvb, io_data_size);
1620 
1621             if (compute_crc)
1622             {
1623                proto_tree_add_checksum(tree, tvb, io_data_size+1,
1624                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
1625                         compute_crc_s1_data(compute_crc_s1_pid(&connection_triad),
1626                                 (mode_byte & MODE_BYTE_CRC_S1_MASK),
1627                                 tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
1628                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1629 
1630                proto_tree_add_checksum(tree, tvb, io_data_size+2,
1631                         hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2, pinfo,
1632                         compute_crc_s2_data(compute_crc_s1_pid(&connection_triad),
1633                                 ((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S1_MASK),
1634                                 /* I/O data is duplicated because it will be complemented inline */
1635                                 (guint8*)tvb_memdup(pinfo->pool, tvb, 0, io_data_size), io_data_size),
1636                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1637             }
1638             else
1639             {
1640                proto_tree_add_checksum(tree, tvb, io_data_size+1,
1641                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
1642                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1643                proto_tree_add_checksum(tree, tvb, io_data_size+2,
1644                         hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2,
1645                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1646             }
1647             proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, io_data_size+3, 2, ENC_LITTLE_ENDIAN);
1648             timestamp = tvb_get_letohs(tvb, io_data_size+3);
1649             if (compute_crc)
1650             {
1651                proto_tree_add_checksum(tree, tvb, io_data_size+5,
1652                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
1653                         compute_crc_s1_timestamp(compute_crc_s1_pid(&connection_triad),
1654                                 (mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
1655                                 timestamp),
1656                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1657             }
1658             else
1659             {
1660                proto_tree_add_checksum(tree, tvb, io_data_size+5,
1661                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
1662                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1663             }
1664 
1665             if (multicast)
1666             {
1667                dissect_mcast_byte(tree, tvb, item_length-6);
1668                proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
1669                proto_tree_add_item(tree, hf_cipsafety_mcast_byte2,     tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
1670                proto_tree_add_item(tree, hf_cipsafety_crc_s3,          tvb, item_length-2, 2, ENC_LITTLE_ENDIAN);
1671             }
1672          }
1673          else
1674          {
1675             /* Long Format (3-250 bytes I/O data) */
1676             if (item_length%2 == 1)
1677             {
1678                /* Malformed packet */
1679                expert_add_info(pinfo, item, &ei_mal_io);
1680                return;
1681             }
1682 
1683             io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
1684 
1685             proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1686             dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1687             mode_byte = tvb_get_guint8(tvb, io_data_size);
1688 
1689             if (compute_crc)
1690             {
1691                proto_tree_add_checksum(tree, tvb, io_data_size+1,
1692                         hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1693                         compute_crc_s3_base_data(compute_crc_s3_pid(&connection_triad),
1694                                 mode_byte & MODE_BYTE_CRC_S3_MASK, tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
1695                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1696             }
1697             else
1698             {
1699                proto_tree_add_checksum(tree, tvb, io_data_size+1,
1700                         hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1701                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1702             }
1703 
1704             complement_item = proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size+3, io_data_size, ENC_NA);
1705             if (!verify_compliment_data(tvb, 0, io_data_size+3, io_data_size))
1706                 expert_add_info(pinfo, complement_item, &ei_cipsafety_not_complement_data);
1707 
1708             if (compute_crc)
1709             {
1710                proto_tree_add_checksum(tree, tvb, (io_data_size*2)+3,
1711                         hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3, pinfo,
1712                         compute_crc_s3_base_data(compute_crc_s3_pid(&connection_triad),
1713                                 ((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S3_MASK),
1714                                 tvb_get_ptr(tvb, io_data_size+3, io_data_size), io_data_size),
1715                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1716             }
1717             else
1718             {
1719                proto_tree_add_checksum(tree, tvb, (io_data_size*2)+3,
1720                         hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3,
1721                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1722             }
1723             proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size*2)+5, 2, ENC_LITTLE_ENDIAN);
1724             timestamp = tvb_get_letohs(tvb, (io_data_size*2)+5);
1725             if (compute_crc)
1726             {
1727                proto_tree_add_checksum(tree, tvb, (io_data_size*2)+7,
1728                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
1729                         compute_crc_s1_timestamp(compute_crc_s1_pid(&connection_triad),
1730                                 (mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
1731                                 timestamp),
1732                         ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1733             }
1734             else
1735             {
1736                proto_tree_add_checksum(tree, tvb, (io_data_size*2)+7,
1737                         hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
1738                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1739             }
1740 
1741             if (multicast)
1742             {
1743                dissect_mcast_byte(tree, tvb, (io_data_size*2)+5);
1744                proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+6, 2, ENC_LITTLE_ENDIAN);
1745                proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, (io_data_size*2)+8, 1, ENC_LITTLE_ENDIAN);
1746                proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
1747             }
1748          }
1749          break;
1750       case CIP_SAFETY_EXTENDED_FORMAT:
1751          if (short_format)
1752          {
1753             io_data_size = item_length-base_length;
1754             timestamp = tvb_get_letohs(tvb, io_data_size+3);
1755          }
1756          else
1757          {
1758             io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
1759             timestamp = tvb_get_letohs(tvb, (io_data_size*2)+5);
1760          }
1761          mode_byte = tvb_get_guint8(tvb, io_data_size);
1762 
1763          if (compute_crc)
1764          {
1765             /* Determine if packet timestamp results in rollover count increment */
1766             if (!pinfo->fd->visited)
1767             {
1768                if ((timestamp != 0) && (timestamp < safety_info->eip_conn_info->safety.running_timestamp_value))
1769                {
1770                   safety_info->eip_conn_info->safety.running_rollover_value++;
1771                }
1772 
1773                safety_info->eip_conn_info->safety.running_timestamp_value = timestamp;
1774 
1775                /* Save the rollover value for CRC calculations */
1776                packet_data = wmem_new0(wmem_file_scope(), cip_safety_packet_data_t);
1777                packet_data->rollover_value = safety_info->eip_conn_info->safety.running_rollover_value;
1778 
1779                p_add_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0, packet_data);
1780             }
1781             else
1782             {
1783                packet_data = (cip_safety_packet_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0);
1784             }
1785          }
1786 
1787          if (short_format)
1788          {
1789             /* Short Format (1-2 bytes I/O data) */
1790             proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1791             dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1792 
1793             guint32 crc_s5_0, crc_s5_1, crc_s5_2;
1794             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, io_data_size+1, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
1795             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, io_data_size+2, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
1796             proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, io_data_size+3, 2, ENC_LITTLE_ENDIAN);
1797             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, io_data_size+5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
1798 
1799             guint32 computed_crc_s5 = 0;
1800             if (packet_data != NULL)
1801             {
1802                computed_crc_s5 = compute_crc_s5_short_data(compute_crc_s5_pid(&connection_triad),
1803                   ((timestamp != 0) ? packet_data->rollover_value : 0),
1804                   mode_byte & MODE_BYTE_CRC_S5_BASE_MASK,
1805                   timestamp,
1806                   tvb_get_ptr(tvb, 0, io_data_size),
1807                   io_data_size);
1808             }
1809             validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1810 
1811             if (multicast)
1812             {
1813                dissect_mcast_byte(tree, tvb, item_length-6);
1814                proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, item_length-5, 2, ENC_LITTLE_ENDIAN);
1815                proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, item_length-3, 1, ENC_LITTLE_ENDIAN);
1816                proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, item_length-2, 1, ENC_LITTLE_ENDIAN);
1817                proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, item_length-1, 1, ENC_LITTLE_ENDIAN);
1818             }
1819          }
1820          else
1821          {
1822             /* Long Format (3-250 bytes I/O data) */
1823             if (item_length%2 == 1)
1824             {
1825                /* Malformed packet */
1826                expert_add_info(pinfo, item, &ei_mal_io);
1827                return;
1828             }
1829 
1830             proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1831             dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1832 
1833             if (compute_crc)
1834             {
1835                /* Determine if packet timestamp results in rollover count increment */
1836                if (!pinfo->fd->visited)
1837                {
1838                   if ((timestamp != 0) && (timestamp < safety_info->eip_conn_info->safety.running_timestamp_value))
1839                   {
1840                      safety_info->eip_conn_info->safety.running_rollover_value++;
1841                   }
1842 
1843                   safety_info->eip_conn_info->safety.running_timestamp_value = timestamp;
1844 
1845                   /* Save the rollover value for CRC calculations */
1846                   packet_data = wmem_new0(wmem_file_scope(), cip_safety_packet_data_t);
1847                   packet_data->rollover_value = safety_info->eip_conn_info->safety.running_rollover_value;
1848 
1849                   p_add_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0, packet_data);
1850                }
1851                else
1852                {
1853                   packet_data = (cip_safety_packet_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0);
1854                }
1855 
1856                if (packet_data != NULL)
1857                {
1858                   proto_tree_add_checksum(tree, tvb, io_data_size+1,
1859                            hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1860                            compute_crc_s3_extended_data(compute_crc_s3_pid(&connection_triad),
1861                                 ((timestamp != 0) ? packet_data->rollover_value : 0), mode_byte & MODE_BYTE_CRC_S3_MASK, tvb_get_ptr(tvb, 0, io_data_size), io_data_size),
1862                            ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1863                }
1864             }
1865             else
1866             {
1867                proto_tree_add_checksum(tree, tvb, io_data_size+1,
1868                         hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1869                         pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1870 
1871             }
1872             complement_item = proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size+3, io_data_size, ENC_NA);
1873             if (!verify_compliment_data(tvb, 0, io_data_size+3, io_data_size))
1874                 expert_add_info(pinfo, complement_item, &ei_cipsafety_not_complement_data);
1875 
1876 			guint32 crc_s5_0, crc_s5_1, crc_s5_2;
1877             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, (io_data_size*2)+3, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
1878             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, (io_data_size*2)+4, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
1879             proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size*2)+5, 2, ENC_LITTLE_ENDIAN);
1880             proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, (io_data_size*2)+7, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
1881 
1882             guint32 computed_crc_s5 = 0;
1883             if (packet_data != NULL)
1884             {
1885                computed_crc_s5 = compute_crc_s5_long_data(compute_crc_s5_pid(&connection_triad),
1886                   ((timestamp != 0) ? packet_data->rollover_value : 0),
1887                   mode_byte & MODE_BYTE_CRC_S5_EXTENDED_MASK,
1888                   timestamp,
1889                   /* I/O data is duplicated because it will be complemented inline */
1890                   (guint8*)tvb_memdup(pinfo->pool, tvb, 0, io_data_size),
1891                   io_data_size);
1892             }
1893             validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1894 
1895             if (multicast)
1896             {
1897                dissect_mcast_byte(tree, tvb, (io_data_size*2)+8);
1898                proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, (io_data_size*2)+9, 2, ENC_LITTLE_ENDIAN);
1899                proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, (io_data_size*2)+11, 1, ENC_LITTLE_ENDIAN);
1900                proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, (io_data_size*2)+12, 1, ENC_LITTLE_ENDIAN);
1901                proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, (io_data_size*2)+13, 1, ENC_LITTLE_ENDIAN);
1902             }
1903          }
1904          break;
1905       }
1906    }
1907    else
1908    {
1909       /* Shouldn't happen, but at least dissect it as data */
1910       proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, item_length, ENC_NA);
1911    }
1912 }
1913 
1914 static int
1915 dissect_cipsafety(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1916 {
1917    proto_item *ti;
1918    proto_tree *safety_tree;
1919    cip_safety_info_t* safety_info = (cip_safety_info_t*)data;
1920 
1921    /* Create display subtree for the protocol */
1922    ti = proto_tree_add_item(tree, proto_cipsafety, tvb, 0, -1, ENC_NA);
1923    safety_tree = proto_item_add_subtree( ti, ett_cip_safety);
1924 
1925    dissect_cip_safety_data(safety_tree, ti, tvb, tvb_reported_length(tvb), pinfo, safety_info);
1926    return tvb_captured_length(tvb);
1927 }
1928 
1929 static int dissect_cipsafety_base_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1930 {
1931    cip_safety_info_t safety_info;
1932    cip_conn_info_t eip_conn_info;
1933    memset(&eip_conn_info, 0, sizeof(eip_conn_info));
1934    safety_info.eip_conn_info = &eip_conn_info;
1935    safety_info.compute_crc = FALSE;
1936 
1937    // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
1938    safety_info.conn_type = ECIDT_T2O;
1939    safety_info.eip_conn_info->TransportClass_trigger = 0;
1940    safety_info.eip_conn_info->safety.format = CIP_SAFETY_BASE_FORMAT;
1941 
1942    return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
1943 }
1944 
1945 static int dissect_cipsafety_extended_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1946 {
1947    cip_safety_info_t safety_info;
1948    cip_conn_info_t eip_conn_info;
1949    memset(&eip_conn_info, 0, sizeof(eip_conn_info));
1950    safety_info.eip_conn_info = &eip_conn_info;
1951    safety_info.compute_crc = FALSE;
1952 
1953    // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
1954    safety_info.conn_type = ECIDT_T2O;
1955    safety_info.eip_conn_info->TransportClass_trigger = 0;
1956    safety_info.eip_conn_info->safety.format = CIP_SAFETY_EXTENDED_FORMAT;
1957 
1958    return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
1959 }
1960 
1961 static int dissect_cipsafety_base_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1962 {
1963    cip_safety_info_t safety_info;
1964    cip_conn_info_t eip_conn_info;
1965    memset(&eip_conn_info, 0, sizeof(eip_conn_info));
1966    safety_info.eip_conn_info = &eip_conn_info;
1967    safety_info.compute_crc = FALSE;
1968 
1969    // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
1970    safety_info.conn_type = ECIDT_O2T;
1971    safety_info.eip_conn_info->TransportClass_trigger = 0;
1972    safety_info.eip_conn_info->safety.format = CIP_SAFETY_BASE_FORMAT;
1973 
1974    return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
1975 }
1976 
1977 static int dissect_cipsafety_extended_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1978 {
1979    cip_safety_info_t safety_info;
1980    cip_conn_info_t eip_conn_info;
1981    memset(&eip_conn_info, 0, sizeof(eip_conn_info));
1982    safety_info.eip_conn_info = &eip_conn_info;
1983    safety_info.compute_crc = FALSE;
1984 
1985    // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
1986    safety_info.conn_type = ECIDT_O2T;
1987    safety_info.eip_conn_info->TransportClass_trigger = 0;
1988    safety_info.eip_conn_info->safety.format = CIP_SAFETY_EXTENDED_FORMAT;
1989 
1990    return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
1991 }
1992 
1993 static int dissect_sercosiii_link_error_count_p1p2(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1994                              int offset, int total_len)
1995 {
1996    if (total_len < 4)
1997    {
1998       expert_add_info(pinfo, item, &ei_mal_sercosiii_link_error_count_p1p2);
1999       return total_len;
2000    }
2001 
2002    proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p1, tvb, offset, 2, ENC_LITTLE_ENDIAN );
2003    proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p2, tvb, offset+2, 2, ENC_LITTLE_ENDIAN );
2004    return 4;
2005 }
2006 
2007 static int dissect_sercosiii_safety_network_number(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
2008     int offset, int total_len _U_)
2009 {
2010     proto_tree_add_item(tree, hf_cip_sercosiii_link_snn, tvb, offset, 6, ENC_NA);
2011     return 6;
2012 }
2013 
2014 attribute_info_t cip_safety_attribute_vals[] = {
2015 
2016    /* Safety Supervisor */
2017    {0x39, TRUE, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_class_subclass, NULL},
2018    {0x39, FALSE, 1, -1, "Number of Attributes", cip_usint, &hf_cip_ssupervisor_num_attr, NULL},
2019    {0x39, FALSE, 2, -1, "Attribute List", cip_usint_array, &hf_cip_ssupervisor_attr_list, NULL},
2020    {0x39, FALSE, 5, -1, "Manufacturer Name", cip_short_string, &hf_cip_ssupervisor_manufacture_name, NULL},
2021    {0x39, FALSE, 6, -1, "Manufacturer Model Number", cip_short_string, &hf_cip_ssupervisor_manufacture_model_number, NULL},
2022    {0x39, FALSE, 7, -1, "Software Revision Level", cip_short_string, &hf_cip_ssupervisor_sw_rev_level, NULL},
2023    {0x39, FALSE, 8, -1, "Hardware Revision Level", cip_short_string, &hf_cip_ssupervisor_hw_rev_level, NULL},
2024    {0x39, FALSE, 9, -1, "Manufacturer Serial Number", cip_short_string, &hf_cip_ssupervisor_manufacture_serial_number, NULL},
2025    {0x39, FALSE, 10, -1, "Device Configuration", cip_short_string, &hf_cip_ssupervisor_device_config, NULL},
2026    {0x39, FALSE, 11, -1, "Device Status", cip_usint, &hf_cip_ssupervisor_device_status, NULL},
2027    {0x39, FALSE, 12, -1, "Exception Status", cip_byte, &hf_cip_ssupervisor_exception_status, NULL},
2028    {0x39, FALSE, 13, -1, "Exception Detail Alarm", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_common},
2029    {0x39, FALSE, 14, -1, "Exception Detail Warning", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_common},
2030    {0x39, FALSE, 15, -1, "Alarm Enable", cip_bool, &hf_cip_ssupervisor_alarm_enable, NULL},
2031    {0x39, FALSE, 16, -1, "Warning Enable", cip_bool, &hf_cip_ssupervisor_warning_enable, NULL},
2032    {0x39, FALSE, 17, -1, "Time", cip_date_and_time, &hf_cip_ssupervisor_time, NULL},
2033    {0x39, FALSE, 18, -1, "Clock Power Cycle Behavior", cip_usint, &hf_cip_ssupervisor_clock_power_cycle_behavior, NULL},
2034    {0x39, FALSE, 19, -1, "Last Maintenance Date", cip_date, &hf_cip_ssupervisor_last_maintenance_date, NULL},
2035    {0x39, FALSE, 20, -1, "Next Scheduled Maintenance Date", cip_date, &hf_cip_ssupervisor_next_scheduled_maintenance_date, NULL},
2036    {0x39, FALSE, 21, -1, "Scheduled Maintenance Expiration Timer", cip_int, &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer, NULL},
2037    {0x39, FALSE, 22, -1, "Scheduled Maintenance Expiration Warning Enable", cip_bool, &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable, NULL},
2038    {0x39, FALSE, 23, -1, "Run Hours", cip_udint, &hf_cip_ssupervisor_run_hours, NULL},
2039    {0x39, FALSE, 24, -1, "Configuration Lock", cip_bool, &hf_cip_ssupervisor_configuration_lock, NULL},
2040    {0x39, FALSE, 25, -1, "Configuration UNID", cip_dissector_func, NULL, dissect_s_supervisor_configuration_unid},
2041    {0x39, FALSE, 26, -1, "Safety Configuration Identifier", cip_dissector_func, NULL, dissect_s_supervisor_safety_configuration_id},
2042    {0x39, FALSE, 27, -1, "Target UNID", cip_dissector_func, NULL, dissect_s_supervisor_target_unid},
2043    {0x39, FALSE, 28, -1, "Output Connection Point Owners", cip_dissector_func, NULL, dissect_s_supervisor_output_connection_point_owners},
2044    {0x39, FALSE, 29, -1, "Proposed TUNID", cip_dissector_func, NULL, dissect_s_supervisor_proposed_tunid},
2045    {0x39, FALSE, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_instance_subclass, NULL},
2046 
2047    /* Safety Validator */
2048    {0x3A, TRUE, 8, -1, "Safety Connection Fault Count", cip_uint, &hf_cip_svalidator_sconn_fault_count, NULL},
2049    {0x3A, FALSE, 1, 0, "Safety Validator State", cip_usint, &hf_cip_svalidator_state, NULL},
2050    {0x3A, FALSE, 2, 1, "Safety Validator Type", cip_dissector_func, NULL, dissect_s_validator_type},
2051    {0x3A, FALSE, 3, 2, "Ping Interval ERI Multiplier", cip_uint, &hf_cip_svalidator_ping_eri, NULL},
2052    {0x3A, FALSE, 4, 3, "Time Coord Msg Min Multiplier", cip_dissector_func, NULL, dissect_s_validator_time_coord_msg_min_mult},
2053    {0x3A, FALSE, 5, 4, "Network Time Expectation Multiplier", cip_dissector_func, NULL, dissect_s_validator_network_time_multiplier},
2054    {0x3A, FALSE, 6, 5, "Timeout Multiplier", cip_dissector_func, NULL, dissect_s_validator_timeout_multiplier},
2055    {0x3A, FALSE, 7, 6, "Max Consumer Number", cip_usint, &hf_cip_svalidator_max_consumer_num, NULL},
2056    {0x3A, FALSE, 8, 7, "Data Connection Instance", cip_uint, &hf_cip_svalidator_data_conn_inst, NULL},
2057    {0x3A, FALSE, 9, 8, "Coordination Connection Instance", cip_dissector_func, NULL, dissect_s_validator_coordination_conn_inst},
2058    {0x3A, FALSE, 10, 9, "Correction Connection Instance", cip_uint, &hf_cip_svalidator_correction_conn_inst, NULL},
2059    {0x3A, FALSE, 11, 10, "CCO Binding", cip_uint, &hf_cip_svalidator_cco_binding, NULL},
2060    {0x3A, FALSE, 12, 11, "Max Data Age", cip_uint, &hf_cip_svalidator_max_data_age, NULL},
2061    {0x3A, FALSE, 13, 12, "Application Data Path", cip_dissector_func, NULL, dissect_s_validator_app_data_path},
2062    /* TODO: GAA code can't get to "Error Code", because dissect_s_validator_app_data_path() will use
2063       all remaining bytes. Waiting on clarification in a future spec update. */
2064    {0x3A, FALSE, 14, 13, "Error Code", cip_uint, &hf_cip_svalidator_error_code, NULL},
2065    {0x3A, FALSE, 15, -1, "Producer/Consumer Fault Counters", cip_dissector_func, NULL, dissect_s_validator_prod_cons_fault_count},
2066 
2067    /* Sercos III Link */
2068    {0x4C, FALSE, 1, -1, "Safety Network Number", cip_dissector_func, NULL, dissect_sercosiii_safety_network_number},
2069    {0x4C, FALSE, 2, -1, "Communication Cycle Time", cip_dint, &hf_cip_sercosiii_link_communication_cycle_time, NULL},
2070    {0x4C, FALSE, 3, -1, "Interface Status", cip_word, &hf_cip_sercosiii_link_interface_status, NULL},
2071    {0x4C, FALSE, 4, -1, "Error counter MST-P/S", cip_int, &hf_cip_sercosiii_link_error_count_mstps, NULL},
2072    {0x4C, FALSE, 5, -1, "Error counter Port1 and Port2", cip_dissector_func, NULL, dissect_sercosiii_link_error_count_p1p2},
2073    {0x4C, FALSE, 6, -1, "SERCOS address", cip_int, &hf_cip_sercosiii_link_sercos_address, NULL},
2074 };
2075 
2076 /*
2077  * Protocol initialization
2078  */
2079 
2080 /*
2081  * Function name: proto_register_cipsafety
2082  *
2083  * Purpose: Register the protocol with Wireshark, a script will add this protocol
2084  * to the list of protocols during the build process. This function is where the
2085  * header fields and subtree identifiers are registered.
2086  *
2087  * Returns: void
2088  */
2089 void
2090 proto_register_cipsafety(void)
2091 {
2092    /* This is a list of header fields that can be used in the dissection or
2093    * to use in a filter expression */
2094    static hf_register_info hf[] =
2095    {
2096       { &hf_cip_reqrsp,
2097         { "Request/Response", "cip.rr",
2098           FT_UINT8, BASE_HEX, VALS(cip_sc_rr), CIP_SC_RESPONSE_MASK, "Request or Response message", HFILL }
2099       },
2100       { &hf_cip_data,
2101         { "Data", "cip.data",
2102           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2103       },
2104 
2105       { &hf_cipsafety_data,
2106         { "Data", "cipsafety.data",
2107           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2108       },
2109       { &hf_cipsafety_mode_byte,
2110         { "Mode Byte", "cipsafety.mode_byte",
2111           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2112       },
2113       { &hf_cipsafety_mode_byte_ping_count,
2114         { "Ping Count", "cipsafety.mode_byte.ping_count",
2115           FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL }
2116       },
2117       { &hf_cipsafety_mode_byte_not_tbd,
2118         { "Not TBD Bit", "cipsafety.mode_byte.not_tbd",
2119           FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }
2120       },
2121       { &hf_cipsafety_mode_byte_tbd_2_copy,
2122         { "TBD 2 Bit Copy", "cipsafety.mode_byte.tbd_2_copy",
2123           FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
2124       },
2125       { &hf_cipsafety_mode_byte_not_run_idle,
2126         { "Not Run/Idle", "cipsafety.mode_byte.not_run_idle",
2127           FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }
2128       },
2129       { &hf_cipsafety_mode_byte_tbd,
2130         { "TBD Bit", "cipsafety.mode_byte.tbd",
2131           FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }
2132       },
2133       { &hf_cipsafety_mode_byte_tbd_2_bit,
2134         { "TBD 2 Bit", "cipsafety.mode_byte.tbd_2_bit",
2135           FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
2136       },
2137       { &hf_cipsafety_mode_byte_run_idle,
2138         { "Run/Idle", "cipsafety.mode_byte.run_idle",
2139           FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2140       },
2141       { &hf_cipsafety_crc_s1,
2142         { "CRC S1", "cipsafety.crc_s1",
2143           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2144       },
2145       { &hf_cipsafety_crc_s1_status,
2146         { "CRC S1 Status", "cipsafety.crc_s1.status",
2147           FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2148       },
2149       { &hf_cipsafety_crc_s2,
2150         { "CRC S2", "cipsafety.crc_s2",
2151           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2152       },
2153       { &hf_cipsafety_crc_s2_status,
2154         { "CRC S2 Status", "cipsafety.crc_s2.status",
2155           FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2156       },
2157       { &hf_cipsafety_crc_s3,
2158         { "CRC S3", "cipsafety.crc_s3",
2159           FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2160       },
2161       { &hf_cipsafety_crc_s3_status,
2162         { "CRC S3 Status", "cipsafety.crc_s3.status",
2163           FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2164       },
2165       { &hf_cipsafety_complement_crc_s3,
2166         { "Complement CRC S3", "cipsafety.complement_crc_s3",
2167           FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2168       },
2169       { &hf_cipsafety_complement_crc_s3_status,
2170         { "Complement CRC S3 Status", "cipsafety.complement_crc_s3.status",
2171           FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2172       },
2173       { &hf_cipsafety_timestamp,
2174         { "Timestamp", "cipsafety.timestamp",
2175           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2176       },
2177       { &hf_cipsafety_ack_byte,
2178         { "ACK Byte", "cipsafety.ack_byte",
2179           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2180       },
2181       { &hf_cipsafety_ack_byte_ping_count_reply,
2182         { "Ping Count Reply", "cipsafety.ack_byte.ping_count_reply",
2183           FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }
2184       },
2185       { &hf_cipsafety_ack_byte_reserved1,
2186         { "Reserved", "cipsafety.ack_byte.reserved1",
2187           FT_UINT8, BASE_HEX, NULL, 0x04, NULL, HFILL }
2188       },
2189       { &hf_cipsafety_ack_byte_ping_response,
2190         { "Ping Response", "cipsafety.ack_byte.ping_response",
2191           FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
2192       },
2193       { &hf_cipsafety_ack_byte_reserved2,
2194         { "Reserved", "cipsafety.ack_byte.reserved2",
2195           FT_UINT8, BASE_HEX, NULL, 0x70, NULL, HFILL }
2196       },
2197       { &hf_cipsafety_ack_byte_parity_even,
2198         { "Parity Even", "cipsafety.ack_byte.parity_even",
2199           FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2200       },
2201       { &hf_cipsafety_ack_byte2,
2202         { "ACK Byte 2", "cipsafety.ack_byte2",
2203           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2204       },
2205       { &hf_cipsafety_consumer_time_value,
2206         { "Consumer Time Value", "cipsafety.consumer_time_value",
2207           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2208       },
2209       { &hf_cipsafety_mcast_byte,
2210         { "MCAST Byte", "cipsafety.mcast_byte",
2211           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2212       },
2213       { &hf_cipsafety_mcast_byte_consumer_num,
2214         { "Consumer #", "cipsafety.mcast_byte.consumer_num",
2215           FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
2216       },
2217       { &hf_cipsafety_mcast_byte_reserved1,
2218         { "Reserved", "cipsafety.mcast_byte.reserved1",
2219           FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
2220       },
2221       { &hf_cipsafety_mcast_byte_mai,
2222         { "Multicast Active/Idle", "cipsafety.mcast_byte.active_idle",
2223           FT_BOOLEAN, 8, TFS(&cip_safety_vals_active_idle), 0x20, NULL, HFILL }
2224       },
2225       { &hf_cipsafety_mcast_byte_reserved2,
2226         { "Reserved", "cipsafety.mcast_byte.reserved2",
2227           FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
2228       },
2229       { &hf_cipsafety_mcast_byte_parity_even,
2230         { "Parity Even", "cipsafety.mcast_byte.parity_even",
2231           FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2232       },
2233       { &hf_cipsafety_mcast_byte2,
2234         { "MCAST Byte 2", "cipsafety.mcast_byte2",
2235           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2236       },
2237       { &hf_cipsafety_time_correction,
2238         { "Time Correction", "cipsafety.time_correction",
2239           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2240       },
2241       { &hf_cipsafety_crc_s5_0,
2242         { "CRC S5_0", "cipsafety.crc_s5_0",
2243           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2244       },
2245       { &hf_cipsafety_crc_s5_1,
2246         { "CRC S5_1", "cipsafety.crc_s5_1",
2247           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2248       },
2249       { &hf_cipsafety_crc_s5_2,
2250         { "CRC S5_2", "cipsafety.crc_s5_2",
2251           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2252       },
2253       { &hf_cipsafety_crc_s5_status,
2254         { "CRC S5 Status", "cipsafety.crc_s5.status",
2255           FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2256       },
2257       { &hf_cipsafety_complement_data,
2258         { "Complement Data", "cipsafety.complement_data",
2259           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2260       },
2261 
2262       { &hf_cip_sercosiii_link_snn,
2263         { "Data", "cipsafety.sercosiii_link.snn",
2264           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2265       },
2266       { &hf_cip_sercosiii_link_communication_cycle_time,
2267         { "Communication Cycle Time", "cipsafety.sercosiii_link.communication_cycle_time",
2268           FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL }
2269       },
2270       { &hf_cip_sercosiii_link_interface_status,
2271         { "Communication Cycle Time", "cipsafety.sercosiii_link.interface_status",
2272           FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2273       },
2274       { &hf_cip_sercosiii_link_error_count_mstps,
2275         { "Error Counter MST-P/S", "cipsafety.sercosiii_link.error_count_mstps",
2276           FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2277       },
2278       { &hf_cip_sercosiii_link_error_count_p1,
2279         { "Error Count Port 1", "cipsafety.sercosiii_link.error_count_p1",
2280           FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2281       },
2282       { &hf_cip_sercosiii_link_error_count_p2,
2283         { "Error Count Port 2", "cipsafety.sercosiii_link.error_count_p2",
2284           FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2285       },
2286       { &hf_cip_sercosiii_link_sercos_address,
2287         { "SERCOS Address", "cipsafety.sercosiii_link.sercos_address",
2288           FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2289       },
2290    };
2291 
2292    static hf_register_info hf_ssupervisor[] = {
2293       { &hf_cip_ssupervisor_sc,
2294         { "Service", "cipsafety.ssupervisor.sc",
2295           FT_UINT8, BASE_HEX, VALS(cip_sc_vals_ssupervisor), CIP_SC_MASK, NULL, HFILL }
2296       },
2297       { &hf_cip_ssupervisor_recover_data,
2298         { "Data", "cipsafety.ssupervisor.recover.data",
2299           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2300       },
2301       { &hf_cip_ssupervisor_perform_diag_data,
2302         { "Data", "cipsafety.ssupervisor.perform_diag.data",
2303           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2304       },
2305       { &hf_cip_ssupervisor_configure_request_password,
2306         { "Password", "cipsafety.ssupervisor.configure_request.password",
2307           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2308       },
2309       { &hf_cip_ssupervisor_configure_request_tunid,
2310         { "Target UNID", "cipsafety.ssupervisor.configure_request.tunid",
2311           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2312       },
2313       { &hf_cip_ssupervisor_configure_request_tunid_snn_timestamp,
2314         { "TUNID SNN Timestamp", "cipsafety.ssupervisor.configure_request.tunid.snn.timestamp",
2315           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2316       },
2317       { &hf_cip_ssupervisor_configure_request_tunid_snn_date,
2318         { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_request.tunid.snn.date",
2319           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2320       },
2321       { &hf_cip_ssupervisor_configure_request_tunid_snn_time,
2322         { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_request.tunid.snn.time",
2323           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2324       },
2325       { &hf_cip_ssupervisor_configure_request_tunid_nodeid,
2326         { "Node ID", "cipsafety.ssupervisor.configure_request.tunid.nodeid",
2327           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2328       },
2329       { &hf_cip_ssupervisor_configure_request_ounid,
2330         { "Originator UNID", "cipsafety.ssupervisor.configure_request.ounid",
2331           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2332       },
2333       { &hf_cip_ssupervisor_configure_request_ounid_snn_timestamp,
2334         { "OUNID SNN Timestamp", "cipsafety.ssupervisor.configure_request.ounid.snn.timestamp",
2335           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2336       },
2337       { &hf_cip_ssupervisor_configure_request_ounid_snn_date,
2338         { "OUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_request.ounid.snn.date",
2339           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2340       },
2341       { &hf_cip_ssupervisor_configure_request_ounid_snn_time,
2342         { "OUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_request.ounid.snn.time",
2343           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2344       },
2345       { &hf_cip_ssupervisor_configure_request_ounid_nodeid,
2346         { "Node ID", "cipsafety.ssupervisor.configure_request.ounid.nodeid",
2347           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2348       },
2349       { &hf_cip_ssupervisor_validate_configuration_sccrc,
2350         { "SCCRC", "cipsafety.ssupervisor.validate_configuration.sccrc",
2351           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2352       },
2353       { &hf_cip_ssupervisor_validate_configuration_scts_timestamp,
2354         { "SCTS (Timestamp)", "cipsafety.ssupervisor.validate_configuration.scts.timestamp",
2355           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2356       },
2357       { &hf_cip_ssupervisor_validate_configuration_scts_date,
2358         { "SCTS (Manual) Date", "cipsafety.ssupervisor.validate_configuration.scts.date",
2359           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2360       },
2361       { &hf_cip_ssupervisor_validate_configuration_scts_time,
2362         { "SCTS (Manual) Time", "cipsafety.ssupervisor.validate_configuration.scts.time",
2363           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2364       },
2365       { &hf_cip_ssupervisor_validate_configuration_ext_error,
2366         { "Extended Error", "cipsafety.ssupervisor.validate_configuration.ext_error",
2367           FT_UINT16, BASE_DEC, VALS(cip_ssupervisor_validate_configuration_ext_error_vals), 0, NULL, HFILL }
2368       },
2369       { &hf_cip_ssupervisor_set_password_current_password,
2370         { "Current Password", "cipsafety.ssupervisor.set_password.current_pass",
2371           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2372       },
2373       { &hf_cip_ssupervisor_set_password_new_password,
2374         { "New Password", "cipsafety.ssupervisor.set_password.new_pass",
2375           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2376       },
2377       { &hf_cip_ssupervisor_configure_lock_value,
2378         { "Lock Value", "cipsafety.ssupervisor.configure_lock.lock",
2379           FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
2380       },
2381       { &hf_cip_ssupervisor_configure_lock_password,
2382         { "Password", "cipsafety.ssupervisor.configure_lock.password",
2383           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2384       },
2385       { &hf_cip_ssupervisor_configure_lock_tunid,
2386         { "Target UNID", "cipsafety.ssupervisor.configure_lock.tunid",
2387           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2388       },
2389       { &hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp,
2390         { "TUNID SNN Timestamp", "cipsafety.ssupervisor.configure_lock.tunid.snn.timestamp",
2391           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2392       },
2393       { &hf_cip_ssupervisor_configure_lock_tunid_snn_date,
2394         { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_lock.tunid.snn.date",
2395           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2396       },
2397       { &hf_cip_ssupervisor_configure_lock_tunid_snn_time,
2398         { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_lock.tunid.snn.time",
2399           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2400       },
2401       { &hf_cip_ssupervisor_configure_lock_tunid_nodeid,
2402         { "Node ID", "cipsafety.ssupervisor.configure_lock.tunid.nodeid",
2403           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2404       },
2405       { &hf_cip_ssupervisor_mode_change_value,
2406         { "Value", "cipsafety.ssupervisor.mode_change.value",
2407           FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_change_mode_vals), 0, NULL, HFILL }
2408       },
2409       { &hf_cip_ssupervisor_mode_change_password,
2410         { "Password", "cipsafety.ssupervisor.mode_change.password",
2411           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2412       },
2413       { &hf_cip_ssupervisor_reset_type,
2414         { "Reset Type", "cipsafety.ssupervisor.reset.type",
2415           FT_UINT8, BASE_DEC, VALS(cip_reset_type_vals), 0, NULL, HFILL }
2416       },
2417       { &hf_cip_ssupervisor_reset_password,
2418         { "Password", "cipsafety.ssupervisor.reset.password",
2419           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2420       },
2421       { &hf_cip_ssupervisor_reset_tunid,
2422         { "Target UNID", "cipsafety.ssupervisor.reset.tunid",
2423           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2424       },
2425       { &hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp,
2426         { "TUNID SNN Timestamp", "cipsafety.ssupervisor.reset.tunid.snn.timestamp",
2427           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2428       },
2429       { &hf_cip_ssupervisor_reset_tunid_tunid_snn_date,
2430         { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.reset.tunid.snn.date",
2431           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2432       },
2433       { &hf_cip_ssupervisor_reset_tunid_tunid_snn_time,
2434         { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.reset.tunid.snn.time",
2435           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2436       },
2437       { &hf_cip_ssupervisor_reset_tunid_nodeid,
2438         { "Node ID", "cipsafety.ssupervisor.reset.tunid.nodeid",
2439           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2440       },
2441       { &hf_cip_ssupervisor_reset_attr_bitmap,
2442         { "Attribute Bit Map", "cipsafety.ssupervisor.reset.attr_bitmap",
2443           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2444       },
2445       { &hf_cip_ssupervisor_reset_attr_bitmap_macid,
2446         { "Preserve MacID", "cipsafety.ssupervisor.reset.attr_bitmap.macid",
2447           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x01, NULL, HFILL }
2448       },
2449       { &hf_cip_ssupervisor_reset_attr_bitmap_baudrate,
2450         { "Preserve Baud Rate", "cipsafety.ssupervisor.reset.attr_bitmap.baudrate",
2451           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x02, NULL, HFILL }
2452       },
2453       { &hf_cip_ssupervisor_reset_attr_bitmap_tunid,
2454         { "Preserve TUNID", "cipsafety.ssupervisor.reset.attr_bitmap.tunid",
2455           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x04, NULL, HFILL }
2456       },
2457       { &hf_cip_ssupervisor_reset_attr_bitmap_password,
2458         { "Preserve Password", "cipsafety.ssupervisor.reset.attr_bitmap.password",
2459           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x08, NULL, HFILL }
2460       },
2461       { &hf_cip_ssupervisor_reset_attr_bitmap_cfunid,
2462         { "Preserve CFUNID", "cipsafety.ssupervisor.reset.attr_bitmap.cfunid",
2463           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x10, NULL, HFILL }
2464       },
2465       { &hf_cip_ssupervisor_reset_attr_bitmap_ocpunid,
2466         { "Preserve OPCUNID", "cipsafety.ssupervisor.reset.attr_bitmap.ocpunid",
2467           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x20, NULL, HFILL }
2468       },
2469       { &hf_cip_ssupervisor_reset_attr_bitmap_reserved,
2470         { "Reserved", "cipsafety.ssupervisor.reset.attr_bitmap.reserved",
2471           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x40, NULL, HFILL }
2472       },
2473       { &hf_cip_ssupervisor_reset_attr_bitmap_extended,
2474         { "Use Extended Map", "cipsafety.ssupervisor.reset.attr_bitmap.extended",
2475           FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x80, NULL, HFILL }
2476       },
2477       { &hf_cip_ssupervisor_reset_password_data_size,
2478         { "Data Size", "cipsafety.ssupervisor.reset_password.data_size",
2479           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2480       },
2481       { &hf_cip_ssupervisor_reset_password_data,
2482         { "Password Data", "cipsafety.ssupervisor.reset_password.password_data",
2483           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2484       },
2485       { &hf_cip_ssupervisor_propose_tunid_tunid,
2486         { "Target UNID", "cipsafety.ssupervisor.propose_tunid.tunid",
2487           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2488       },
2489       { &hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp,
2490         { "TUNID SNN Timestamp", "cipsafety.ssupervisor.propose_tunid.tunid.snn.timestamp",
2491           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2492       },
2493       { &hf_cip_ssupervisor_propose_tunid_tunid_snn_date,
2494         { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.propose_tunid.tunid.snn.date",
2495           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2496       },
2497       { &hf_cip_ssupervisor_propose_tunid_tunid_snn_time,
2498         { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.propose_tunid.tunid.snn.time",
2499           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2500       },
2501       { &hf_cip_ssupervisor_propose_tunid_tunid_nodeid,
2502         { "Node ID", "cipsafety.ssupervisor.propose_tunid.tunid.nodeid",
2503           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2504       },
2505       { &hf_cip_ssupervisor_apply_tunid_tunid,
2506         { "Target UNID", "cipsafety.ssupervisor.apply_tunid.tunid",
2507           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2508       },
2509       { &hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp,
2510         { "TUNID SNN Timestamp", "cipsafety.ssupervisor.apply_tunid.tunid.snn.timestamp",
2511           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2512       },
2513       { &hf_cip_ssupervisor_apply_tunid_tunid_snn_date,
2514         { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.apply_tunid.tunid.snn.date",
2515           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2516       },
2517       { &hf_cip_ssupervisor_apply_tunid_tunid_snn_time,
2518         { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.apply_tunid.tunid.snn.time",
2519           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2520       },
2521       { &hf_cip_ssupervisor_apply_tunid_tunid_nodeid,
2522         { "Node ID", "cipsafety.ssupervisor.apply_tunid.tunid.nodeid",
2523           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2524       },
2525       { &hf_cip_ssupervisor_class_subclass,
2526         { "Subclass", "cipsafety.ssupervisor.class_subclass",
2527           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2528       },
2529       { &hf_cip_ssupervisor_num_attr,
2530         { "Number of Attributes", "cipsafety.ssupervisor.num_attr",
2531           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2532       },
2533       { &hf_cip_ssupervisor_attr_list,
2534         { "Attributes List Item", "cipsafety.ssupervisor.attr_item",
2535           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2536       },
2537       { &hf_cip_ssupervisor_manufacture_name,
2538         { "Manufacturer Name", "cipsafety.ssupervisor.manufacture_name",
2539           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2540       },
2541       { &hf_cip_ssupervisor_manufacture_model_number,
2542         { "Manufacturer Model Number", "cipsafety.ssupervisor.manufacture_model_number",
2543           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2544       },
2545       { &hf_cip_ssupervisor_sw_rev_level,
2546         { "Software Revision Level", "cipsafety.ssupervisor.sw_rev_level",
2547           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2548       },
2549       { &hf_cip_ssupervisor_hw_rev_level,
2550         { "Hardware Revision Level", "cipsafety.ssupervisor.hw_rev_level",
2551           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2552       },
2553       { &hf_cip_ssupervisor_manufacture_serial_number,
2554         { "Manufacturer Serial Number", "cipsafety.ssupervisor.manufacture_serial_number",
2555           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2556       },
2557       { &hf_cip_ssupervisor_device_config,
2558         { "Device Configuration", "cipsafety.ssupervisor.device_config",
2559           FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2560       },
2561       { &hf_cip_ssupervisor_device_status,
2562         { "Device Status", "cipsafety.ssupervisor.device_status",
2563           FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_device_status_type_vals), 0, NULL, HFILL }
2564       },
2565       { &hf_cip_ssupervisor_exception_status,
2566         { "Exception Status", "cipsafety.ssupervisor.exception_status",
2567           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2568       },
2569       { &hf_cip_ssupervisor_exception_detail_ced_size,
2570         { "Common Exception Detail Size", "cipsafety.ssupervisor.exception_detail.ced.size",
2571           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2572       },
2573       { &hf_cip_ssupervisor_exception_detail_ced_detail,
2574         { "Common Exception Detail Data", "cipsafety.ssupervisor.exception_detail.ced.detail",
2575           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2576       },
2577       { &hf_cip_ssupervisor_exception_detail_ded_size,
2578         { "Device Exception Detail Size", "cipsafety.ssupervisor.exception_detail.ded.size",
2579           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2580       },
2581       { &hf_cip_ssupervisor_exception_detail_ded_detail,
2582         { "Device Exception Detail Data", "cipsafety.ssupervisor.exception_detail.ded.detail",
2583           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2584       },
2585       { &hf_cip_ssupervisor_exception_detail_med_size,
2586         { "Manufacturer Exception Detail Size", "cipsafety.ssupervisor.exception_detail.med.size",
2587           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2588       },
2589       { &hf_cip_ssupervisor_exception_detail_med_detail,
2590         { "Manufacturer Exception Detail Data", "cipsafety.ssupervisor.exception_detail.med.detail",
2591           FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2592       },
2593       { &hf_cip_ssupervisor_alarm_enable,
2594         { "Exception Detail Alarm", "cipsafety.ssupervisor.alarm_enable",
2595           FT_BOOLEAN, BASE_NONE, TFS(&tfs_true_false), 0, NULL, HFILL }
2596       },
2597       { &hf_cip_ssupervisor_warning_enable,
2598         { "Exception Detail Warning", "cipsafety.ssupervisor.warning_enable",
2599           FT_BOOLEAN, BASE_NONE, TFS(&tfs_true_false), 0, NULL, HFILL }
2600       },
2601       { &hf_cip_ssupervisor_time,
2602         { "Time", "cipsafety.ssupervisor.time",
2603           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2604       },
2605       { &hf_cip_ssupervisor_clock_power_cycle_behavior,
2606         { "Clock Power Cycle Behavior", "cipsafety.ssupervisor.clock_power_cycle_behavior",
2607           FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_clock_power_cycle_type_vals), 0, NULL, HFILL }
2608       },
2609       { &hf_cip_ssupervisor_last_maintenance_date,
2610         { "Last Maintenance Date", "cipsafety.ssupervisor.last_maintenance_date",
2611           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2612       },
2613       { &hf_cip_ssupervisor_next_scheduled_maintenance_date,
2614         { "Next Scheduled Maintenance Date", "cipsafety.ssupervisor.next_scheduled_maintenance_date",
2615           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2616       },
2617       { &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer,
2618         { "Scheduled Maintenance Expiration Timer", "cipsafety.ssupervisor.scheduled_maintenance_expiration_timer",
2619           FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2620       },
2621       { &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable,
2622         { "Scheduled Maintenance Expiration Warning Enable", "cipsafety.ssupervisor.scheduled_maintenance_expiration_warning",
2623           FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }
2624       },
2625       { &hf_cip_ssupervisor_run_hours,
2626         { "Run Hours", "cipsafety.ssupervisor.run_hours",
2627           FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
2628       },
2629       { &hf_cip_ssupervisor_configuration_lock,
2630         { "Configuration Lock", "cipsafety.ssupervisor.configuration_lock",
2631           FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
2632       },
2633       { &hf_cip_ssupervisor_configuration_unid_snn_timestamp,
2634         { "Configuration UNID SNN Timestamp", "cipsafety.ssupervisor.configuration_unid.snn.timestamp",
2635           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2636       },
2637       { &hf_cip_ssupervisor_configuration_unid_snn_date,
2638         { "Configuration UNID SNN (Manual) Date", "cipsafety.ssupervisor.configuration_unid.snn.date",
2639           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2640       },
2641       { &hf_cip_ssupervisor_configuration_unid_snn_time,
2642         { "Configuration UNID SNN (Manual) Time", "cipsafety.ssupervisor.configuration_unid.snn.time",
2643           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2644       },
2645       { &hf_cip_ssupervisor_configuration_unid_nodeid,
2646         { "Configuration UNID Node ID", "cipsafety.ssupervisor.configuration_unid.nodeid",
2647           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2648       },
2649       { &hf_cip_ssupervisor_safety_configuration_id_snn_timestamp,
2650         { "Safety Configuration ID SNN Timestamp", "cipsafety.ssupervisor.safety_configuration_id.snn.timestamp",
2651           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2652       },
2653       { &hf_cip_ssupervisor_safety_configuration_id_snn_date,
2654         { "Safety Configuration ID SNN (Manual) Date", "cipsafety.ssupervisor.safety_configuration_id.snn.date",
2655           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2656       },
2657       { &hf_cip_ssupervisor_safety_configuration_id_snn_time,
2658         { "Safety Configuration ID SNN (Manual) Time", "cipsafety.ssupervisor.safety_configuration_id.snn.time",
2659           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2660       },
2661       { &hf_cip_ssupervisor_safety_configuration_id_sccrc,
2662         { "Safety Configuration ID SCCRC", "cipsafety.ssupervisor.safety_configuration_id.sccrc",
2663          FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2664       },
2665       { &hf_cip_ssupervisor_target_unid_snn_timestamp,
2666         { "Target UNID SNN Timestamp", "cipsafety.ssupervisor.target_unid.snn.timestamp",
2667           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2668       },
2669       { &hf_cip_ssupervisor_target_unid_snn_date,
2670         { "Target UNID SNN (Manual) Date", "cipsafety.ssupervisor.target_unid.snn.date",
2671           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2672       },
2673       { &hf_cip_ssupervisor_target_unid_snn_time,
2674         { "Target UNID SNN (Manual) Time", "cipsafety.ssupervisor.target_unid.snn.time",
2675           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2676       },
2677       { &hf_cip_ssupervisor_target_unid_nodeid,
2678         { "Target UNID Node ID", "cipsafety.ssupervisor.target_unid.nodeid",
2679           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2680       },
2681       { &hf_cip_ssupervisor_cp_owners_num_entries,
2682         { "Number of Array Entries", "cipsafety.ssupervisor.cp_owners.num_entries",
2683           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2684       },
2685       { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp,
2686         { "OCPUNID SNN Timestamp", "cipsafety.ssupervisor.cp_owners.snn.timestamp",
2687           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2688       },
2689       { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date,
2690         { "OCPUNID SNN (Manual) Date", "cipsafety.ssupervisor.cp_owners.snn.date",
2691           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2692       },
2693       { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time,
2694         { "OCPUNID SNN (Manual) Time", "cipsafety.ssupervisor.cp_owners.snn.time",
2695           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2696       },
2697       { &hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid,
2698         { "OCPUNID Node ID", "cipsafety.ssupervisor.cp_owners.ocpunid.nodeid",
2699           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2700       },
2701       { &hf_cip_ssupervisor_cp_owners_app_path_size,
2702         { "EPATH Size", "cipsafety.ssupervisor.cp_owners.epath_size",
2703           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2704       },
2705       { &hf_cip_ssupervisor_proposed_tunid_snn_timestamp,
2706         { "Proposed TUNID SNN Timestamp", "cipsafety.ssupervisor.proposed_tunid.snn.timestamp",
2707           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2708       },
2709       { &hf_cip_ssupervisor_proposed_tunid_snn_date,
2710         { "Proposed TUNID SNN (Manual) Date", "cipsafety.ssupervisor.proposed_tunid.snn.date",
2711           FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2712       },
2713       { &hf_cip_ssupervisor_proposed_tunid_snn_time,
2714         { "Proposed TUNID SNN (Manual) Time", "cipsafety.ssupervisor.proposed_tunid.snn.time",
2715           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2716       },
2717       { &hf_cip_ssupervisor_proposed_tunid_nodeid,
2718         { "Proposed TUNID Node ID", "cipsafety.ssupervisor.proposed_tunid.nodeid",
2719           FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2720       },
2721       { &hf_cip_ssupervisor_instance_subclass,
2722         { "Subclass", "cipsafety.ssupervisor.instance_subclass",
2723           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2724       }
2725    };
2726 
2727    static hf_register_info hf_svalidator[] = {
2728       { &hf_cip_svalidator_sc,
2729         { "Service", "cipsafety.svalidator.sc",
2730           FT_UINT8, BASE_HEX, VALS(cip_sc_vals_svalidator), CIP_SC_MASK, NULL, HFILL }
2731       },
2732 
2733       { &hf_cip_svalidator_sconn_fault_count,
2734         { "Safety Connection Fault Count", "cipsafety.svalidator.sconn_fault_count",
2735           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2736       },
2737       { &hf_cip_svalidator_state,
2738         { "Safety Validator State", "cipsafety.svalidator.state",
2739           FT_UINT8, BASE_DEC, VALS(cip_svalidator_state_vals), 0, NULL, HFILL }
2740       },
2741       { &hf_cip_svalidator_type,
2742         { "Safety Validator Type", "cipsafety.svalidator.type",
2743           FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2744       },
2745       { &hf_cip_svalidator_type_pc,
2746         { "Producer/Consumer", "cipsafety.svalidator.type.pc",
2747           FT_UINT8, BASE_HEX, VALS(cip_svalidator_type_pc_vals), 0x80, NULL, HFILL }
2748       },
2749       { &hf_cip_svalidator_type_conn_type,
2750         { "Safety Connection Type", "cipsafety.svalidator.type.conn_type",
2751           FT_UINT8, BASE_DEC, VALS(cip_svalidator_type_conn_type_vals), 0x7F, NULL, HFILL }
2752       },
2753       { &hf_cip_svalidator_ping_eri,
2754         { "Ping Interval EPI Multiplier", "cipsafety.svalidator.ping_eri",
2755           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2756       },
2757       { &hf_cip_svalidator_time_coord_msg_min_mult_size,
2758         { "Time Coord Msg Min Multiplier Array Size", "cipsafety.svalidator.time_coord_msg_min_mult.size",
2759           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2760       },
2761       { &hf_cip_svalidator_time_coord_msg_min_mult_item,
2762         { "Time Coord Msg Min Multiplier", "cipsafety.svalidator.time_coord_msg_min_mult.item",
2763           FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_safety_128us, 0, NULL, HFILL }
2764       },
2765       { &hf_cip_svalidator_network_time_multiplier_size,
2766         { "Network Time Expectation Multiplier Array Size", "cipsafety.svalidator.network_time_multiplier.size",
2767           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2768       },
2769       { &hf_cip_svalidator_network_time_multiplier_item,
2770         { "Network Time Expectation Multiplier", "cipsafety.svalidator.network_time_multiplier.item",
2771           FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_safety_128us, 0, NULL, HFILL }
2772       },
2773       { &hf_cip_svalidator_timeout_multiplier_size,
2774         { "Timeout Multiplier Array Size", "cipsafety.svalidator.timeout_multiplier.size",
2775           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2776       },
2777       { &hf_cip_svalidator_timeout_multiplier_item,
2778         { "Timeout Multiplier", "cipsafety.svalidator.timeout_multiplier.item",
2779           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2780       },
2781       { &hf_cip_svalidator_max_consumer_num,
2782         { "Max Consumer Number", "cipsafety.svalidator.max_consumer_num",
2783           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2784       },
2785       { &hf_cip_svalidator_data_conn_inst,
2786         { "Data Connection Instance", "cipsafety.svalidator.data_conn_inst",
2787           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2788       },
2789       { &hf_cip_svalidator_coordination_conn_inst_size,
2790         { "Coordination Connection Instance Size", "cipsafety.svalidator.coordination_conn_inst.size",
2791           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2792       },
2793       { &hf_cip_svalidator_coordination_conn_inst_item,
2794         { "Coordination Connection Instance Item", "cipsafety.svalidator.coordination_conn_inst.item",
2795           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2796       },
2797       { &hf_cip_svalidator_correction_conn_inst,
2798         { "Correction Connection Instance", "cipsafety.svalidator.correction_conn_inst",
2799           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2800       },
2801       { &hf_cip_svalidator_cco_binding,
2802         { "CCO Binding", "cipsafety.svalidator.cco_binding",
2803           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2804       },
2805       { &hf_cip_svalidator_max_data_age,
2806         { "Max Data Age", "cipsafety.svalidator.max_data_age",
2807           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2808       },
2809       { &hf_cip_svalidator_error_code,
2810         { "Error Code", "cipsafety.svalidator.error_code",
2811           FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2812       },
2813       { &hf_cip_svalidator_prod_cons_fault_count_size,
2814         { "Producer/Consumer Counter Array Size", "cipsafety.svalidator.prod_cons_fault_count.size",
2815           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2816       },
2817       { &hf_cip_svalidator_prod_cons_fault_count_item,
2818         { "Producer/Consumer Fault Counter", "cipsafety.svalidator.prod_cons_fault_count.item",
2819           FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2820       }
2821    };
2822 
2823    static gint *ett[] = {
2824       &ett_cip_safety,
2825       &ett_path,
2826       &ett_cipsafety_mode_byte,
2827       &ett_cipsafety_ack_byte,
2828       &ett_cipsafety_mcast_byte
2829    };
2830 
2831    static gint *ett_ssupervisor[] = {
2832       &ett_cip_class_s_supervisor,
2833       &ett_ssupervisor_rrsc,
2834       &ett_ssupervisor_cmd_data,
2835       &ett_ssupervisor_propose_tunid,
2836       &ett_ssupervisor_propose_tunid_snn,
2837       &ett_ssupervisor_configure_request_tunid,
2838       &ett_ssupervisor_configure_request_tunid_snn,
2839       &ett_ssupervisor_configure_request_ounid,
2840       &ett_ssupervisor_configure_request_ounid_snn,
2841       &ett_ssupervisor_configure_lock_tunid,
2842       &ett_ssupervisor_configure_lock_tunid_snn,
2843       &ett_ssupervisor_reset_tunid,
2844       &ett_ssupervisor_reset_tunid_snn,
2845       &ett_ssupervisor_apply_tunid,
2846       &ett_ssupervisor_apply_tunid_snn,
2847       &ett_exception_detail_common,
2848       &ett_exception_detail_device,
2849       &ett_exception_detail_manufacturer,
2850       &ett_ssupervisor_configuration_unid,
2851       &ett_ssupervisor_configuration_unid_snn,
2852       &ett_ssupervisor_target_unid,
2853       &ett_ssupervisor_target_unid_snn,
2854       &ett_ssupervisor_output_cp_owners,
2855       &ett_ssupervisor_output_cp_owners_ocpunid,
2856       &ett_ssupervisor_output_cp_owners_ocpunid_snn,
2857       &ett_ssupervisor_proposed_tunid,
2858       &ett_ssupervisor_proposed_tunid_snn,
2859       &ett_cip_ssupervisor_reset_attr_bitmap
2860    };
2861 
2862    static gint *ett_svalidator[] = {
2863       &ett_cip_class_s_validator,
2864       &ett_svalidator_rrsc,
2865       &ett_svalidator_cmd_data,
2866       &ett_svalidator_type
2867    };
2868 
2869    static ei_register_info ei[] = {
2870       { &ei_cipsafety_tbd2_not_complemented, { "cipsafety.tbd2_not_complemented", PI_PROTOCOL, PI_WARN, "TBD_2_bit not complemented", EXPFILL }},
2871       { &ei_cipsafety_tbd_not_copied, { "cipsafety.tbd_not_copied", PI_PROTOCOL, PI_WARN, "TBD bit not copied", EXPFILL }},
2872       { &ei_cipsafety_run_idle_not_complemented, { "cipsafety.run_idle_not_complemented", PI_PROTOCOL, PI_WARN, "Run/Idle bit not complemented", EXPFILL }},
2873       { &ei_mal_io, { "cipsafety.malformed.io", PI_MALFORMED, PI_ERROR, "Malformed CIP Safety I/O packet", EXPFILL }},
2874       { &ei_mal_sercosiii_link_error_count_p1p2, { "cipsafety.malformed.sercosiii_link.error_count_p1p2", PI_MALFORMED, PI_ERROR, "Malformed SERCOS III Attribute 5", EXPFILL }},
2875       { &ei_cipsafety_not_complement_data, { "cipsafety.not_complement_data", PI_PROTOCOL, PI_WARN, "Data not complemented", EXPFILL }},
2876       { &ei_cipsafety_crc_s1, { "cipsafety.crc_s1.incorrect", PI_PROTOCOL, PI_WARN, "CRC-S1 incorrect", EXPFILL }},
2877       { &ei_cipsafety_crc_s2, { "cipsafety.crc_s2.incorrect", PI_PROTOCOL, PI_WARN, "CRC-S2 incorrect", EXPFILL }},
2878       { &ei_cipsafety_crc_s3, { "cipsafety.crc_s3.incorrect", PI_PROTOCOL, PI_WARN, "CRC-S3 incorrect", EXPFILL }},
2879       { &ei_cipsafety_complement_crc_s3, { "cipsafety.complement_crc_s3.incorrect", PI_PROTOCOL, PI_WARN, "Complement CRC-S3 incorrect", EXPFILL }},
2880       { &ei_cipsafety_crc_s5, { "cipsafety.crc_s5.incorrect", PI_PROTOCOL, PI_WARN, "CRC-S5 incorrect", EXPFILL }},
2881       };
2882 
2883    static ei_register_info ei_ssupervisor[] = {
2884       { &ei_mal_ssupervisor_exception_detail_ced, { "cipsafety.ssupervisor.malformed.exception_detail.ced", PI_MALFORMED, PI_ERROR,
2885                         "Malformed Safety Supervisor Exception Detail (Common Exception Detail)", EXPFILL }},
2886       { &ei_mal_ssupervisor_exception_detail_ded, { "cipsafety.ssupervisor.malformed.exception_detail.ded", PI_MALFORMED, PI_ERROR,
2887                         "Malformed Safety Supervisor Exception Detail (Device Exception Detail)", EXPFILL }},
2888       { &ei_mal_ssupervisor_exception_detail_med, { "cipsafety.ssupervisor.malformed.exception_detail.med", PI_MALFORMED, PI_ERROR,
2889                         "Malformed Safety Supervisor Exception Detail (Manufacturer Exception Detail)", EXPFILL }},
2890       { &ei_mal_ssupervisor_configuration_unid, { "cipsafety.ssupervisor.malformed.configuration_unid", PI_MALFORMED, PI_ERROR,
2891                         "Malformed Safety Supervisor Configuration UNID", EXPFILL }},
2892       { &ei_mal_ssupervisor_safety_configuration_id, { "cipsafety.ssupervisor.malformed.safety_configuration_id", PI_MALFORMED, PI_ERROR,
2893                         "Malformed Safety Supervisor Safety Configuration Identifier", EXPFILL }},
2894       { &ei_mal_ssupervisor_target_unid, { "cipsafety.ssupervisor.malformed.target_unid", PI_MALFORMED, PI_ERROR,
2895                         "Malformed Safety Supervisor Target UNID", EXPFILL }},
2896       { &ei_mal_ssupervisor_cp_owners, { "cipsafety.ssupervisor.malformed.cp_owners", PI_MALFORMED, PI_ERROR,
2897                         "Malformed Safety Supervisor Output Connection Point Owners", EXPFILL }},
2898       { &ei_mal_ssupervisor_cp_owners_entry, { "cipsafety.ssupervisor.malformed.cp_owners.entry", PI_MALFORMED, PI_ERROR,
2899                         "Malformed Safety Supervisor Output Connection Point Owners (UNID)", EXPFILL }},
2900       { &ei_mal_ssupervisor_cp_owners_app_path_size, { "cipsafety.ssupervisor.malformed.cp_owners.app_path_size", PI_MALFORMED, PI_ERROR,
2901                         "Malformed Safety Supervisor Output Connection Point Owners (EPATH)", EXPFILL }},
2902       { &ei_mal_ssupervisor_proposed_tunid, { "cipsafety.ssupervisor.malformed.proposed_tunid", PI_MALFORMED, PI_ERROR,
2903                         "Malformed Safety Supervisor Proposed TUNID", EXPFILL }},
2904    };
2905 
2906    static ei_register_info ei_svalidator[] = {
2907       { &ei_mal_svalidator_type, { "cipsafety.ssupervisor.malformed.svalidator.type", PI_MALFORMED, PI_ERROR,
2908                         "Malformed Safety Validator Type", EXPFILL }},
2909       { &ei_mal_svalidator_time_coord_msg_min_mult, { "cipsafety.ssupervisor.malformed.svalidator.time_coord_msg_min_mult", PI_MALFORMED, PI_ERROR,
2910                         "Malformed Safety Validator Time Coord Msg Min Multiplier", EXPFILL }},
2911       { &ei_mal_svalidator_network_time_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.network_time_multiplier", PI_MALFORMED, PI_ERROR,
2912                         "Malformed Safety Validator Network Time Expectation Multiplier", EXPFILL }},
2913       { &ei_mal_svalidator_timeout_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.timeout_multiplier", PI_MALFORMED, PI_ERROR,
2914                         "Malformed Safety Validator Timeout Multiplier", EXPFILL }},
2915       { &ei_mal_svalidator_coordination_conn_inst, { "cipsafety.ssupervisor.malformed.svalidator.coordination_conn_inst", PI_MALFORMED, PI_ERROR,
2916                         "Malformed Safety Validator Coordination Connection Instance", EXPFILL }},
2917       { &ei_mal_svalidator_prod_cons_fault_count, { "cipsafety.ssupervisor.malformed.svalidator.prod_cons_fault_count", PI_MALFORMED, PI_ERROR,
2918                         "Malformed Safety Validator Produce/Consume Fault Counters", EXPFILL }},
2919    };
2920 
2921    expert_module_t* expert_cip_safety;
2922    expert_module_t* expert_cip_class_s_supervisor;
2923    expert_module_t* expert_cip_class_s_validator;
2924 
2925    /* Create a CIP Safety protocol handle */
2926    proto_cipsafety = proto_register_protocol("Common Industrial Protocol, Safety", "CIP Safety", "cipsafety");
2927    proto_register_field_array(proto_cipsafety, hf, array_length(hf));
2928    proto_register_subtree_array(ett, array_length(ett));
2929    expert_cip_safety = expert_register_protocol(proto_cipsafety);
2930    expert_register_field_array(expert_cip_safety, ei, array_length(ei));
2931 
2932    cipsafety_handle = register_dissector( "cipsafety", dissect_cipsafety, proto_cipsafety);
2933 
2934    // Register different protocols for "Decode As".
2935    proto_cipsafety_base_data = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Base - Data",
2936       "CIP Safety - Base - Data",
2937       "cipsafety_bd",
2938       proto_cipsafety,
2939       FT_PROTOCOL);
2940    cipsafety_base_data_handle = register_dissector("cipsafety_bd", dissect_cipsafety_base_data, proto_cipsafety_base_data);
2941 
2942    proto_cipsafety_extended_data = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Extended - Data",
2943       "CIP Safety - Extended - Data",
2944       "cipsafety_ed",
2945       proto_cipsafety,
2946       FT_PROTOCOL);
2947    cipsafety_extended_data_handle = register_dissector("cipsafety_ed", dissect_cipsafety_extended_data, proto_cipsafety_extended_data);
2948 
2949    proto_cipsafety_base_time_coord = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Base - Time Coordination",
2950       "CIP Safety - Base - Time Coordination",
2951       "cipsafety_bt",
2952       proto_cipsafety,
2953       FT_PROTOCOL);
2954    cipsafety_base_time_coord_handle = register_dissector("cipsafety_bt", dissect_cipsafety_base_time_coord, proto_cipsafety_base_time_coord);
2955 
2956    proto_cipsafety_extended_time_coord = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Extended - Time Coordination",
2957       "CIP Safety - Extended - Time Coordination",
2958       "cipsafety_et",
2959       proto_cipsafety,
2960       FT_PROTOCOL);
2961    cipsafety_extended_time_coord_handle = register_dissector("cipsafety_et", dissect_cipsafety_extended_time_coord, proto_cipsafety_extended_time_coord);
2962 
2963 
2964    /* Register CIP Safety objects */
2965    proto_cip_class_s_supervisor = proto_register_protocol("CIP Safety Supervisor",
2966        "CIPSSupervisor", "cipssupervisor");
2967    proto_register_field_array(proto_cip_class_s_supervisor, hf_ssupervisor, array_length(hf_ssupervisor));
2968    proto_register_subtree_array(ett_ssupervisor, array_length(ett_ssupervisor));
2969    expert_cip_class_s_supervisor = expert_register_protocol(proto_cip_class_s_supervisor);
2970    expert_register_field_array(expert_cip_class_s_supervisor, ei_ssupervisor, array_length(ei_ssupervisor));
2971 
2972    proto_cip_class_s_validator = proto_register_protocol("CIP Safety Validator",
2973        "CIPSValidator", "cipsvalidator");
2974    proto_register_field_array(proto_cip_class_s_validator, hf_svalidator, array_length(hf_svalidator));
2975    proto_register_subtree_array(ett_svalidator, array_length(ett_svalidator));
2976    expert_cip_class_s_validator = expert_register_protocol(proto_cip_class_s_validator);
2977    expert_register_field_array(expert_cip_class_s_validator, ei_svalidator, array_length(ei_svalidator));
2978 }
2979 
2980 /*
2981  * Function name: proto_reg_handoff_cipsafety
2982  *
2983  * Purpose: This function will setup the automatic dissection of the CIP Safety datagram,
2984  * it is called by Wireshark when the protocol is registered
2985  *
2986  * Returns: void
2987  */
2988 void
2989 proto_reg_handoff_cipsafety(void)
2990 {
2991    dissector_handle_t cip_class_s_supervisor_handle;
2992 
2993    /* Create and register dissector handle for Safety Supervisor */
2994    cip_class_s_supervisor_handle = create_dissector_handle( dissect_cip_class_s_supervisor, proto_cip_class_s_supervisor );
2995    dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_SUPERVISOR, cip_class_s_supervisor_handle );
2996 
2997    /* Create and register dissector handle for Safety Validator */
2998    cip_class_s_validator_handle = create_dissector_handle( dissect_cip_class_s_validator, proto_cip_class_s_validator );
2999    dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_VALIDATOR, cip_class_s_validator_handle );
3000    heur_dissector_add("cip.sc", dissect_class_svalidator_heur, "CIP Safety Validator", "s_validator_cip", proto_cip_class_s_validator, HEURISTIC_ENABLE);
3001 
3002    /* Register dissector for I/O data handling */
3003    dissector_add_for_decode_as("cip.io", cipsafety_base_data_handle );
3004    dissector_add_for_decode_as("cip.io", cipsafety_extended_data_handle );
3005    dissector_add_for_decode_as("cip.io", cipsafety_base_time_coord_handle );
3006    dissector_add_for_decode_as("cip.io", cipsafety_extended_time_coord_handle );
3007 
3008    proto_cip = proto_get_id_by_filter_name( "cip" );
3009    subdissector_class_table = find_dissector_table("cip.class.iface");
3010 }
3011 
3012 
3013 /*
3014 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3015 *
3016 * Local variables:
3017 * c-basic-offset: 3
3018 * tab-width: 8
3019 * indent-tabs-mode: nil
3020 * End:
3021 *
3022 * ex: set shiftwidth=3 tabstop=8 expandtab:
3023 * :indentSize=3:tabSize=8:noTabs=true:
3024 */
3025