Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cipsafety.c
blob254e24b00088a0b30cc2b77d320773a2554f5164
1 /* packet-cipsafety.c
2 * Routines for CIP (Common Industrial Protocol) Safety dissection
3 * CIP Safety Home: www.odva.org
5 * This dissector includes items from:
6 * CIP Volume 1: Common Industrial Protocol, Edition 3.24
7 * CIP Volume 5: CIP Safety, Edition 2.22
9 * Copyright 2011
10 * Michael Mann <mmann@pyramidsolutions.com>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include "config.h"
21 #include <stdio.h>
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include <epan/proto_data.h>
25 #include <epan/tfs.h>
27 #include <wsutil/pint.h>
28 #include <wsutil/crc8.h>
29 #include <wsutil/crc16.h>
30 #include <wsutil/crc32.h>
31 #include "packet-cip.h"
32 #include "packet-cipsafety.h"
35 void proto_register_cipsafety(void);
36 void proto_reg_handoff_cipsafety(void);
37 /* The entry point to the actual dissection is: dissect_cipsafety */
39 /* Protocol handle for CIP Safety */
40 static int proto_cipsafety;
41 static int proto_cipsafety_base_data;
42 static int proto_cipsafety_extended_data;
43 static int proto_cipsafety_base_time_coord;
44 static int proto_cipsafety_extended_time_coord;
45 static int proto_cip_class_s_supervisor;
46 static int proto_cip_class_s_validator;
47 static int proto_cip;
49 static dissector_table_t subdissector_class_table;
50 static dissector_handle_t cip_class_s_supervisor_handle;
51 static dissector_handle_t cip_class_s_validator_handle;
53 /* CIP Safety field identifiers */
54 static int hf_cipsafety_data;
55 static int hf_cipsafety_mode_byte;
56 static int hf_cipsafety_mode_byte_run_idle;
57 static int hf_cipsafety_mode_byte_not_run_idle;
58 static int hf_cipsafety_mode_byte_tbd_2_bit;
59 static int hf_cipsafety_mode_byte_tbd_2_copy;
60 static int hf_cipsafety_mode_byte_ping_count;
61 static int hf_cipsafety_mode_byte_tbd;
62 static int hf_cipsafety_mode_byte_not_tbd;
63 static int hf_cipsafety_crc_s1;
64 static int hf_cipsafety_crc_s1_status;
65 static int hf_cipsafety_crc_s2;
66 static int hf_cipsafety_crc_s2_status;
67 static int hf_cipsafety_crc_s3;
68 static int hf_cipsafety_crc_s3_status;
69 static int hf_cipsafety_complement_crc_s3;
70 static int hf_cipsafety_complement_crc_s3_status;
71 static int hf_cipsafety_timestamp;
72 static int hf_cipsafety_ack_byte;
73 static int hf_cipsafety_ack_byte_ping_count_reply;
74 static int hf_cipsafety_ack_byte_reserved1;
75 static int hf_cipsafety_ack_byte_ping_response;
76 static int hf_cipsafety_ack_byte_reserved2;
77 static int hf_cipsafety_ack_byte_parity_even;
78 static int hf_cipsafety_ack_byte2;
79 static int hf_cipsafety_consumer_time_value;
80 static int hf_cipsafety_mcast_byte;
81 static int hf_cipsafety_mcast_byte_consumer_num;
82 static int hf_cipsafety_mcast_byte_reserved1;
83 static int hf_cipsafety_mcast_byte_mai;
84 static int hf_cipsafety_mcast_byte_reserved2;
85 static int hf_cipsafety_mcast_byte_parity_even;
86 static int hf_cipsafety_mcast_byte2;
87 static int hf_cipsafety_time_correction;
88 static int hf_cipsafety_crc_s5_0;
89 static int hf_cipsafety_crc_s5_1;
90 static int hf_cipsafety_crc_s5_2;
91 static int hf_cipsafety_crc_s5_status;
92 static int hf_cipsafety_complement_data;
93 static int hf_cip_safety_message_encoding;
95 /* CIP Safety header field identifiers */
96 static int hf_cip_reqrsp;
97 static int hf_cip_data;
99 /* Safety Supervisor header field identifiers */
100 static int hf_cip_ssupervisor_sc;
101 static int hf_cip_ssupervisor_recover_data;
102 static int hf_cip_ssupervisor_perform_diag_data;
103 static int hf_cip_ssupervisor_configure_request_password;
104 static int hf_cip_ssupervisor_configure_request_tunid;
105 static int hf_cip_ssupervisor_configure_request_tunid_snn_timestamp;
106 static int hf_cip_ssupervisor_configure_request_tunid_snn_date;
107 static int hf_cip_ssupervisor_configure_request_tunid_snn_time;
108 static int hf_cip_ssupervisor_configure_request_tunid_nodeid;
109 static int hf_cip_ssupervisor_configure_request_ounid;
110 static int hf_cip_ssupervisor_configure_request_ounid_snn_timestamp;
111 static int hf_cip_ssupervisor_configure_request_ounid_snn_date;
112 static int hf_cip_ssupervisor_configure_request_ounid_snn_time;
113 static int hf_cip_ssupervisor_configure_request_ounid_nodeid;
114 static int hf_cip_ssupervisor_validate_configuration_sccrc;
115 static int hf_cip_ssupervisor_validate_configuration_scts_timestamp;
116 static int hf_cip_ssupervisor_validate_configuration_scts_date;
117 static int hf_cip_ssupervisor_validate_configuration_scts_time;
118 static int hf_cip_ssupervisor_validate_configuration_ext_error;
119 static int hf_cip_ssupervisor_set_password_current_password;
120 static int hf_cip_ssupervisor_set_password_new_password;
121 static int hf_cip_ssupervisor_configure_lock_value;
122 static int hf_cip_ssupervisor_configure_lock_password;
123 static int hf_cip_ssupervisor_configure_lock_tunid;
124 static int hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp;
125 static int hf_cip_ssupervisor_configure_lock_tunid_snn_date;
126 static int hf_cip_ssupervisor_configure_lock_tunid_snn_time;
127 static int hf_cip_ssupervisor_configure_lock_tunid_nodeid;
128 static int hf_cip_ssupervisor_mode_change_value;
129 static int hf_cip_ssupervisor_mode_change_password;
130 static int hf_cip_ssupervisor_reset_type;
131 static int hf_cip_ssupervisor_reset_password;
132 static int hf_cip_ssupervisor_reset_tunid;
133 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp;
134 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_date;
135 static int hf_cip_ssupervisor_reset_tunid_tunid_snn_time;
136 static int hf_cip_ssupervisor_reset_tunid_nodeid;
137 static int hf_cip_ssupervisor_reset_attr_bitmap;
138 static int hf_cip_ssupervisor_reset_attr_bitmap_macid;
139 static int hf_cip_ssupervisor_reset_attr_bitmap_baudrate;
140 static int hf_cip_ssupervisor_reset_attr_bitmap_tunid;
141 static int hf_cip_ssupervisor_reset_attr_bitmap_password;
142 static int hf_cip_ssupervisor_reset_attr_bitmap_cfunid;
143 static int hf_cip_ssupervisor_reset_attr_bitmap_ocpunid;
144 static int hf_cip_ssupervisor_reset_attr_bitmap_reserved;
145 static int hf_cip_ssupervisor_reset_attr_bitmap_extended;
146 static int hf_cip_ssupervisor_reset_password_data_size;
147 static int hf_cip_ssupervisor_reset_password_data;
148 static int hf_cip_ssupervisor_propose_tunid_tunid;
149 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp;
150 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_date;
151 static int hf_cip_ssupervisor_propose_tunid_tunid_snn_time;
152 static int hf_cip_ssupervisor_propose_tunid_tunid_nodeid;
153 static int hf_cip_ssupervisor_apply_tunid_tunid;
154 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp;
155 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_date;
156 static int hf_cip_ssupervisor_apply_tunid_tunid_snn_time;
157 static int hf_cip_ssupervisor_apply_tunid_tunid_nodeid;
159 static int hf_cip_ssupervisor_class_subclass;
160 static int hf_cip_ssupervisor_num_attr;
161 static int hf_cip_ssupervisor_attr_list;
162 static int hf_cip_ssupervisor_manufacture_name;
163 static int hf_cip_ssupervisor_manufacture_model_number;
164 static int hf_cip_ssupervisor_sw_rev_level;
165 static int hf_cip_ssupervisor_hw_rev_level;
166 static int hf_cip_ssupervisor_manufacture_serial_number;
167 static int hf_cip_ssupervisor_device_config;
168 static int hf_cip_ssupervisor_device_status;
169 static int hf_cip_ssupervisor_exception_status;
170 static int hf_cip_ssupervisor_exception_detail_ced_size;
171 static int hf_cip_ssupervisor_exception_detail_ced_detail;
172 static int hf_cip_ssupervisor_exception_detail_ded_size;
173 static int hf_cip_ssupervisor_exception_detail_ded_detail;
174 static int hf_cip_ssupervisor_exception_detail_med_size;
175 static int hf_cip_ssupervisor_exception_detail_med_detail;
176 static int hf_cip_ssupervisor_alarm_enable;
177 static int hf_cip_ssupervisor_warning_enable;
178 static int hf_cip_ssupervisor_time;
179 static int hf_cip_ssupervisor_clock_power_cycle_behavior;
180 static int hf_cip_ssupervisor_last_maintenance_date;
181 static int hf_cip_ssupervisor_next_scheduled_maintenance_date;
182 static int hf_cip_ssupervisor_scheduled_maintenance_expiration_timer;
183 static int hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable;
184 static int hf_cip_ssupervisor_run_hours;
185 static int hf_cip_ssupervisor_configuration_lock;
186 static int hf_cip_ssupervisor_configuration_unid_snn_timestamp;
187 static int hf_cip_ssupervisor_configuration_unid_snn_date;
188 static int hf_cip_ssupervisor_configuration_unid_snn_time;
189 static int hf_cip_ssupervisor_configuration_unid_nodeid;
190 static int hf_cip_ssupervisor_safety_configuration_id_snn_timestamp;
191 static int hf_cip_ssupervisor_safety_configuration_id_snn_date;
192 static int hf_cip_ssupervisor_safety_configuration_id_snn_time;
193 static int hf_cip_ssupervisor_safety_configuration_id_sccrc;
194 static int hf_cip_ssupervisor_target_unid_snn_timestamp;
195 static int hf_cip_ssupervisor_target_unid_snn_date;
196 static int hf_cip_ssupervisor_target_unid_snn_time;
197 static int hf_cip_ssupervisor_target_unid_nodeid;
198 static int hf_cip_ssupervisor_cp_owners_num_entries;
199 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp;
200 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date;
201 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time;
202 static int hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid;
203 static int hf_cip_ssupervisor_cp_owners_app_path_size;
204 static int hf_cip_ssupervisor_proposed_tunid_snn_timestamp;
205 static int hf_cip_ssupervisor_proposed_tunid_snn_date;
206 static int hf_cip_ssupervisor_proposed_tunid_snn_time;
207 static int hf_cip_ssupervisor_proposed_tunid_nodeid;
208 static int hf_cip_ssupervisor_instance_subclass;
211 /* Safety Validator header field identifiers */
212 static int hf_cip_svalidator_sc;
214 static int hf_cip_svalidator_sconn_fault_count;
215 static int hf_cip_svalidator_state;
216 static int hf_cip_svalidator_type;
217 static int hf_cip_svalidator_type_pc;
218 static int hf_cip_svalidator_type_conn_type;
219 static int hf_cip_svalidator_ping_epi;
220 static int hf_cip_svalidator_time_coord_msg_min_mult_size;
221 static int hf_cip_svalidator_time_coord_msg_min_mult_item;
222 static int hf_cip_svalidator_network_time_multiplier_size;
223 static int hf_cip_svalidator_network_time_multiplier_item;
224 static int hf_cip_svalidator_timeout_multiplier_size;
225 static int hf_cip_svalidator_timeout_multiplier_item;
226 static int hf_cip_svalidator_max_consumer_num;
227 static int hf_cip_svalidator_data_conn_inst;
228 static int hf_cip_svalidator_coordination_conn_inst_size;
229 static int hf_cip_svalidator_coordination_conn_inst_item;
230 static int hf_cip_svalidator_correction_conn_inst;
231 static int hf_cip_svalidator_cco_binding;
232 static int hf_cip_svalidator_max_data_age;
233 static int hf_cip_svalidator_error_code;
234 static int hf_cip_svalidator_prod_cons_fault_count_size;
235 static int hf_cip_svalidator_prod_cons_fault_count_item;
237 static int hf_cip_sercosiii_link_snn;
238 static int hf_cip_sercosiii_link_communication_cycle_time;
239 static int hf_cip_sercosiii_link_interface_status;
240 static int hf_cip_sercosiii_link_error_count_mstps;
241 static int hf_cip_sercosiii_link_sercos_address;
242 static int hf_cip_sercosiii_link_error_count_p1;
243 static int hf_cip_sercosiii_link_error_count_p2;
245 /* Initialize the subtree pointers */
246 static int ett_cip_safety;
247 static int ett_path;
248 static int ett_cipsafety_mode_byte;
249 static int ett_cipsafety_ack_byte;
250 static int ett_cipsafety_mcast_byte;
252 static int ett_cip_class_s_supervisor;
253 static int ett_ssupervisor_rrsc;
254 static int ett_ssupervisor_cmd_data;
255 static int ett_ssupervisor_propose_tunid;
256 static int ett_ssupervisor_propose_tunid_snn;
257 static int ett_ssupervisor_configure_request_tunid;
258 static int ett_ssupervisor_configure_request_tunid_snn;
259 static int ett_ssupervisor_configure_request_ounid;
260 static int ett_ssupervisor_configure_request_ounid_snn;
261 static int ett_ssupervisor_configure_lock_tunid;
262 static int ett_ssupervisor_configure_lock_tunid_snn;
263 static int ett_ssupervisor_reset_tunid;
264 static int ett_ssupervisor_reset_tunid_snn;
265 static int ett_ssupervisor_apply_tunid;
266 static int ett_ssupervisor_apply_tunid_snn;
267 static int ett_exception_detail_common;
268 static int ett_exception_detail_device;
269 static int ett_exception_detail_manufacturer;
270 static int ett_ssupervisor_configuration_unid;
271 static int ett_ssupervisor_configuration_unid_snn;
272 static int ett_ssupervisor_target_unid;
273 static int ett_ssupervisor_target_unid_snn;
274 static int ett_ssupervisor_output_cp_owners;
275 static int ett_ssupervisor_output_cp_owners_ocpunid;
276 static int ett_ssupervisor_output_cp_owners_ocpunid_snn;
277 static int ett_ssupervisor_proposed_tunid;
278 static int ett_ssupervisor_proposed_tunid_snn;
279 static int ett_cip_ssupervisor_reset_attr_bitmap;
281 static int ett_cip_class_s_validator;
282 static int ett_svalidator_rrsc;
283 static int ett_svalidator_cmd_data;
284 static int ett_svalidator_type;
286 static expert_field ei_cipsafety_tbd_not_complemented;
287 static expert_field ei_cipsafety_tbd2_not_copied;
288 static expert_field ei_cipsafety_run_idle_not_complemented;
289 static expert_field ei_mal_io;
290 static expert_field ei_mal_sercosiii_link_error_count_p1p2;
291 static expert_field ei_cipsafety_not_complement_data;
292 static expert_field ei_cipsafety_crc_s1;
293 static expert_field ei_cipsafety_crc_s2;
294 static expert_field ei_cipsafety_crc_s3;
295 static expert_field ei_cipsafety_complement_crc_s3;
296 static expert_field ei_cipsafety_crc_s5;
298 static expert_field ei_mal_ssupervisor_exception_detail_ced;
299 static expert_field ei_mal_ssupervisor_exception_detail_ded;
300 static expert_field ei_mal_ssupervisor_exception_detail_med;
301 static expert_field ei_mal_ssupervisor_configuration_unid;
302 static expert_field ei_mal_ssupervisor_safety_configuration_id;
303 static expert_field ei_mal_ssupervisor_target_unid;
304 static expert_field ei_mal_ssupervisor_cp_owners;
305 static expert_field ei_mal_ssupervisor_cp_owners_entry;
306 static expert_field ei_mal_ssupervisor_cp_owners_app_path_size;
307 static expert_field ei_mal_ssupervisor_proposed_tunid;
308 static expert_field ei_info_ssupervisor_tunid_cancel;
310 static expert_field ei_mal_svalidator_type;
311 static expert_field ei_mal_svalidator_time_coord_msg_min_mult;
312 static expert_field ei_mal_svalidator_network_time_multiplier;
313 static expert_field ei_mal_svalidator_timeout_multiplier;
314 static expert_field ei_mal_svalidator_coordination_conn_inst;
315 static expert_field ei_mal_svalidator_prod_cons_fault_count;
317 static dissector_handle_t cipsafety_handle;
318 static dissector_handle_t cipsafety_base_data_handle;
319 static dissector_handle_t cipsafety_extended_data_handle;
320 static dissector_handle_t cipsafety_base_time_coord_handle;
321 static dissector_handle_t cipsafety_extended_time_coord_handle;
323 typedef struct cip_safety_packet_data {
324 uint16_t rollover_value;
325 } cip_safety_packet_data_t;
327 #define MODE_BYTE_CRC_S1_MASK 0xE0
328 #define MODE_BYTE_CRC_S1_TIME_STAMP_MASK 0x1F
329 #define MODE_BYTE_CRC_S3_MASK 0xE0
330 #define MODE_BYTE_CRC_S5_BASE_MASK 0xE0
331 #define MODE_BYTE_CRC_S5_EXTENDED_MASK 0x1F
333 const value_string cipsafety_snn_date_vals[8] = {
335 { 0, "NULL SNN" },
336 { 1, "Manual Setting - Backplane" },
337 { 2, "Manual Setting - ControlNet" },
338 { 4, "Manual Setting - EtherNet/IP" },
339 { 5, "Manual Setting - DeviceNet" },
340 { 6, "Manual Setting - SERCOS III" },
341 { 65535, "No SNN Set" },
343 { 0, NULL }
346 static const true_false_string cip_safety_vals_active_idle = {
347 "Active",
348 "Idle",
351 /* Translate function to string - CIP Service codes for Safety Supervisor */
352 static const value_string cip_sc_vals_ssupervisor[] = {
353 GENERIC_SC_LIST
355 /* Some class specific services */
356 { SC_SSUPER_RECOVER, "Recover" },
357 { SC_SSUPER_PERFORM_DIAGNOSTICS, "Perform Diagnostics" },
358 { SC_SSUPER_CONFIGURE_REQUEST, "Configure Request" },
359 { SC_SSUPER_VALIDATE_CONFIGURATION, "Validate Configuration" },
360 { SC_SSUPER_SET_PASSWORD, "Set Password" },
361 { SC_SSUPER_CONFIGURATION_LOCK, "Configuration (Un)Lock" },
362 { SC_SSUPER_MODE_CHANGE, "Mode Change" },
363 { SC_SSUPER_SAFETY_RESET, "Safety Reset" },
364 { SC_SSUPER_RESET_PASSWORD, "Reset Password" },
365 { SC_SSUPER_PROPOSE_TUNID, "Propose TUNID" },
366 { SC_SSUPER_APPLY_TUNID, "Apply TUNID" },
367 { SC_SSUPER_PROPOSE_TUNID_LIST, "Propose TUNID List" },
368 { SC_SSUPER_APPLY_TUNID_LIST, "Apply TUNID List" },
370 { 0, NULL }
373 #define SC_SVALID_RESET_ERROR 0x4B
375 /* Translate function to string - CIP Service codes for Safety Validator */
376 static const value_string cip_sc_vals_svalidator[] = {
377 GENERIC_SC_LIST
379 /* Some class specific services */
380 { SC_SVALID_RESET_ERROR, "Reset Error" },
382 { 0, NULL }
385 static const value_string cip_ssupervisor_validate_configuration_ext_error_vals[] = {
386 { 1, "CRC mismatch" },
387 { 2, "Invalid Configuration Parameter" },
388 { 3, "TUNID Not Set" },
390 { 0, NULL }
393 static const value_string cip_ssupervisor_lock_vals[] = {
394 { 0, "Unlocked" },
395 { 1, "Locked" },
397 { 0, NULL }
400 static const value_string cip_ssupervisor_change_mode_vals[] = {
401 { 0, "Idle" },
402 { 1, "Executing" },
404 { 0, NULL }
407 static const value_string cip_ssupervisor_device_status_type_vals[] = {
408 { 0, "Undefined" },
409 { 1, "Self-Testing" },
410 { 2, "Idle" },
411 { 3, "Self-Test Exception" },
412 { 4, "Executing" },
413 { 5, "Abort" },
414 { 6, "Critical Fault" },
415 { 7, "Configuring" },
416 { 8, "Waiting for TUNID" },
417 { 51, "Waiting for TUNID with Torque Permitted" },
418 { 52, "Executing with Torque Permitted" },
420 { 0, NULL }
423 static const value_string cip_ssupervisor_clock_power_cycle_type_vals[] = {
424 { 0, "Clock always resets" },
425 { 1, "Clock in NVS at power down" },
426 { 2, "Clock is battery-backed" },
428 { 0, NULL }
431 static const value_string cip_svalidator_state_vals[] = {
432 { 0, "Unallocated" },
433 { 1, "Initializing" },
434 { 2, "Established" },
435 { 3, "Connection failed" },
437 { 0, NULL }
440 static const value_string cip_svalidator_type_pc_vals[] = {
441 { 0, "Producer" },
442 { 1, "Consumer" },
444 { 0, NULL }
447 static const value_string cip_svalidator_type_conn_type_vals[] = {
448 { 0, "Unallocated" },
449 { 1, "Single-cast" },
450 { 2, "Multi-cast" },
452 { 0, NULL }
455 const range_string safety_max_consumer_numbers[] = {
456 { 1, 1, "Single-cast" },
457 { 2, 15, "Multicast" },
459 { 0, 0, NULL }
462 enum message_encoding_type {
463 MSG_ENCODING_BASE_1_2_BYTE_DATA,
464 MSG_ENCODING_EXTENDED_1_2_BYTE_DATA,
465 MSG_ENCODING_BASE_3_250_BYTE_DATA,
466 MSG_ENCODING_EXTENDED_3_250_BYTE_DATA,
467 MSG_ENCODING_BASE_TIME_STAMP,
468 MSG_ENCODING_BASE_TIME_COORDINATION,
469 MSG_ENCODING_EXTENDED_TIME_COORDINATION,
470 MSG_ENCODING_BASE_TIME_CORRECTION,
471 MSG_ENCODING_EXTENDED_TIME_CORRECTION,
474 static const value_string safety_message_encoding_vals[] = {
475 { MSG_ENCODING_BASE_1_2_BYTE_DATA, "Base Format, 1 or 2 Byte Data Section" },
476 { MSG_ENCODING_EXTENDED_1_2_BYTE_DATA, "Extended Format, 1 or 2 Byte Data Section" },
477 { MSG_ENCODING_BASE_3_250_BYTE_DATA, "Base Format, 3 to 250 Byte Data Section" },
478 { MSG_ENCODING_EXTENDED_3_250_BYTE_DATA, "Extended Format, 3 to 250 Byte Data Section" },
479 { MSG_ENCODING_BASE_TIME_STAMP, "Base Format, Time Stamp Section" },
480 { MSG_ENCODING_BASE_TIME_COORDINATION, "Base Format, Time Coordination Section" },
481 { MSG_ENCODING_EXTENDED_TIME_COORDINATION, "Extended Format, Time Coordination Section" },
482 { MSG_ENCODING_BASE_TIME_CORRECTION, "Base Format, Time Correction Section" },
483 { MSG_ENCODING_EXTENDED_TIME_CORRECTION, "Extended Format, Time Correction Section" },
485 { 0, NULL }
488 void cip_safety_128us_fmt(char *s, uint32_t value)
490 // Each tick is 128us.
491 snprintf(s, ITEM_LABEL_LENGTH, "%d (%.3fms)", value, value * 0.128);
494 void
495 dissect_unid(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_item *pi,
496 const char* snn_name, int hf_snn_timestamp,
497 int hf_snn_date, int hf_snn_time, int hf_nodeid, int ett, int ett_snn)
499 proto_tree *tree, *snn_tree;
501 tree = proto_item_add_subtree(pi, ett);
503 snn_tree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_snn, NULL, snn_name);
504 dissect_cipsafety_snn(snn_tree, tvb, pinfo, offset, hf_snn_timestamp, hf_snn_date, hf_snn_time);
506 proto_tree_add_item(tree, hf_nodeid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN);
509 void dissect_cipsafety_snn(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
510 int hf_real_datetime, int hf_date, int hf_time)
512 uint16_t date;
514 date = tvb_get_letohs(tvb, offset+4);
516 if ((date >= 11688) && (date <= 65534))
518 /* value is an actual timestamp */
519 dissect_cip_date_and_time(tree, tvb, offset, hf_real_datetime);
521 else
523 /* Treated as UINT16 and UINT32 values */
524 proto_tree_add_item(tree, hf_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
525 proto_tree_add_item(tree, hf_date, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
529 static void dissect_safety_supervisor_safety_reset(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
531 uint32_t reset_type;
532 proto_tree_add_item_ret_uint(cmd_data_tree, hf_cip_ssupervisor_reset_type, tvb, offset, 1, ENC_LITTLE_ENDIAN, &reset_type);
534 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password, tvb, offset + 1, 16, ENC_NA);
535 proto_item* pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_tunid, tvb, offset + 17, 10, ENC_NA);
536 dissect_unid(tvb, pinfo, offset + 17, pi, "TUNID SNN",
537 hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp,
538 hf_cip_ssupervisor_reset_tunid_tunid_snn_date,
539 hf_cip_ssupervisor_reset_tunid_tunid_snn_time,
540 hf_cip_ssupervisor_reset_tunid_nodeid,
541 ett_ssupervisor_reset_tunid,
542 ett_ssupervisor_reset_tunid_snn);
544 /* Attribute bitmap only included on Reset Type 2 */
545 if (reset_type == 2)
547 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_attr_bitmap, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
549 proto_tree* bitmap_tree = proto_item_add_subtree(pi, ett_cip_ssupervisor_reset_attr_bitmap);
550 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_macid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
551 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_baudrate, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
552 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_tunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
553 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_password, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
554 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_cfunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
555 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_ocpunid, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
556 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_reserved, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
557 proto_tree_add_item(bitmap_tree, hf_cip_ssupervisor_reset_attr_bitmap_extended, tvb, offset + 27, 1, ENC_LITTLE_ENDIAN);
561 static void detect_cancel_propose_apply_operation(tvbuff_t* tvb, int offset, packet_info* pinfo, proto_item* item)
563 // Check for all FFs.
564 uint64_t part1 = tvb_get_uint64(tvb, offset, ENC_LITTLE_ENDIAN);
565 uint16_t part2 = tvb_get_uint16(tvb, offset + 8, ENC_LITTLE_ENDIAN);
566 if (part1 == 0xFFFFFFFFFFFFFFFF && part2 == 0xFFFF)
568 expert_add_info(pinfo, item, &ei_info_ssupervisor_tunid_cancel);
572 /************************************************
574 * Dissector for CIP Safety Supervisor Object
576 ************************************************/
577 static void
578 dissect_cip_s_supervisor_data( proto_tree *item_tree,
579 tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
581 proto_item *pi, *rrsc_item;
582 proto_tree *rrsc_tree, *cmd_data_tree;
583 int req_path_size;
584 int temp_data;
585 uint8_t service, gen_status, add_stat_size;
586 cip_simple_request_info_t req_data;
588 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Supervisor");
590 /* Add Service code & Request/Response tree */
591 service = tvb_get_uint8( tvb, offset );
592 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_ssupervisor_rrsc, &rrsc_item, "Service: " );
594 /* Add Request/Response */
595 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
597 proto_item_append_text( rrsc_item, "%s (%s)",
598 val_to_str( ( service & CIP_SC_MASK ), cip_sc_vals_ssupervisor , "Unknown Service (0x%02x)"),
599 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7, cip_sc_rr, "") );
601 /* Add Service code */
602 proto_tree_add_item(rrsc_tree, hf_cip_ssupervisor_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
604 load_cip_request_data(pinfo, &req_data);
606 if (service & CIP_SC_RESPONSE_MASK)
608 /* Response message */
610 /* Add additional status size */
611 gen_status = tvb_get_uint8( tvb, offset+2 );
612 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
614 /* If there is any command specific data create a sub-tree for it */
615 if( ( item_length-4-add_stat_size ) != 0 )
617 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size,
618 item_length-4-add_stat_size, ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
620 if( gen_status == CI_GRC_SUCCESS )
622 switch (service & CIP_SC_MASK)
624 case SC_SSUPER_VALIDATE_CONFIGURATION:
625 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
626 tvb, offset+4+add_stat_size, 4, ENC_LITTLE_ENDIAN);
627 dissect_cipsafety_snn(cmd_data_tree,
628 tvb, pinfo, offset+4+add_stat_size+4,
629 hf_cip_ssupervisor_validate_configuration_scts_timestamp,
630 hf_cip_ssupervisor_validate_configuration_scts_date,
631 hf_cip_ssupervisor_validate_configuration_scts_time);
632 break;
635 else if ((gen_status == 0xD0) && ((service & CIP_SC_MASK) == SC_SSUPER_VALIDATE_CONFIGURATION))
637 if (add_stat_size > 0)
639 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_ext_error,
640 tvb, offset+4, 2, ENC_LITTLE_ENDIAN);
643 else
645 /* Error responses */
647 /* Add data */
648 proto_tree_add_item(cmd_data_tree, hf_cip_data,
649 tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
653 } /* End of if reply */
654 else
656 /* Request message */
658 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
660 /* If there is any command specific data create a sub-tree for it */
661 if( (item_length-req_path_size-2) != 0 )
663 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
664 ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
666 /* Check what service code that received */
667 switch (service)
669 case SC_SSUPER_RECOVER:
670 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_recover_data,
671 tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
672 break;
673 case SC_SSUPER_PERFORM_DIAGNOSTICS:
674 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_perform_diag_data,
675 tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
676 break;
677 case SC_SSUPER_CONFIGURE_REQUEST:
678 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_password,
679 tvb, offset+2+req_path_size, 16, ENC_NA);
680 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_tunid,
681 tvb, offset+2+req_path_size+16, 10, ENC_NA);
682 dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "TUNID SNN",
683 hf_cip_ssupervisor_configure_request_tunid_snn_timestamp,
684 hf_cip_ssupervisor_configure_request_tunid_snn_date,
685 hf_cip_ssupervisor_configure_request_tunid_snn_time,
686 hf_cip_ssupervisor_configure_request_tunid_nodeid,
687 ett_ssupervisor_configure_request_tunid,
688 ett_ssupervisor_configure_request_tunid_snn);
689 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_request_ounid,
690 tvb, offset+2+req_path_size+26, 10, ENC_NA);
691 dissect_unid(tvb, pinfo, offset+2+req_path_size+16, pi, "OUNID SNN",
692 hf_cip_ssupervisor_configure_request_ounid_snn_timestamp,
693 hf_cip_ssupervisor_configure_request_ounid_snn_date,
694 hf_cip_ssupervisor_configure_request_ounid_snn_time,
695 hf_cip_ssupervisor_configure_request_ounid_nodeid,
696 ett_ssupervisor_configure_request_ounid,
697 ett_ssupervisor_configure_request_ounid_snn);
698 break;
699 case SC_SSUPER_VALIDATE_CONFIGURATION:
700 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_validate_configuration_sccrc,
701 tvb, offset+2+req_path_size, 4, ENC_LITTLE_ENDIAN);
702 dissect_cipsafety_snn(cmd_data_tree, tvb, pinfo, offset+2+req_path_size+4,
703 hf_cip_ssupervisor_validate_configuration_scts_timestamp,
704 hf_cip_ssupervisor_validate_configuration_scts_date,
705 hf_cip_ssupervisor_validate_configuration_scts_time);
706 break;
707 case SC_SSUPER_SET_PASSWORD:
708 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_current_password,
709 tvb, offset+2+req_path_size, 16, ENC_NA);
710 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_set_password_new_password,
711 tvb, offset+2+req_path_size+16, 16, ENC_NA);
712 break;
713 case SC_SSUPER_CONFIGURATION_LOCK:
714 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_value,
715 tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
716 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_password,
717 tvb, offset+2+req_path_size+1, 16, ENC_NA);
718 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_configure_lock_tunid,
719 tvb, offset+2+req_path_size+17, 10, ENC_NA);
720 dissect_unid(tvb, pinfo, offset+2+req_path_size+17, pi, "TUNID SNN",
721 hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp,
722 hf_cip_ssupervisor_configure_lock_tunid_snn_date,
723 hf_cip_ssupervisor_configure_lock_tunid_snn_time,
724 hf_cip_ssupervisor_configure_lock_tunid_nodeid,
725 ett_ssupervisor_configure_lock_tunid,
726 ett_ssupervisor_configure_lock_tunid_snn);
727 break;
728 case SC_SSUPER_MODE_CHANGE:
729 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_value,
730 tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
731 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_mode_change_password,
732 tvb, offset+2+req_path_size+1, 16, ENC_NA);
733 break;
734 case SC_SSUPER_SAFETY_RESET:
735 dissect_safety_supervisor_safety_reset(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
736 break;
737 case SC_SSUPER_RESET_PASSWORD:
738 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data_size,
739 tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
740 temp_data = tvb_get_uint8(tvb, offset+2+req_path_size);
741 proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_reset_password_data,
742 tvb, offset+2+req_path_size+1, temp_data, ENC_NA);
743 break;
744 case SC_SSUPER_PROPOSE_TUNID:
745 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_propose_tunid_tunid,
746 tvb, offset+2+req_path_size, 10, ENC_NA);
747 dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SNN",
748 hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp,
749 hf_cip_ssupervisor_propose_tunid_tunid_snn_date,
750 hf_cip_ssupervisor_propose_tunid_tunid_snn_time,
751 hf_cip_ssupervisor_propose_tunid_tunid_nodeid,
752 ett_ssupervisor_propose_tunid,
753 ett_ssupervisor_propose_tunid_snn);
755 detect_cancel_propose_apply_operation(tvb, offset + 2 + req_path_size, pinfo, pi);
756 break;
757 case SC_SSUPER_APPLY_TUNID:
758 pi = proto_tree_add_item(cmd_data_tree, hf_cip_ssupervisor_apply_tunid_tunid,
759 tvb, offset+2+req_path_size, 10, ENC_NA);
760 dissect_unid(tvb, pinfo, offset+2+req_path_size, pi, "TUNID SNN",
761 hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp,
762 hf_cip_ssupervisor_apply_tunid_tunid_snn_date,
763 hf_cip_ssupervisor_apply_tunid_tunid_snn_time,
764 hf_cip_ssupervisor_apply_tunid_tunid_nodeid,
765 ett_ssupervisor_apply_tunid,
766 ett_ssupervisor_apply_tunid_snn);
768 detect_cancel_propose_apply_operation(tvb, offset + 2 + req_path_size, pinfo, pi);
769 break;
770 default:
771 proto_tree_add_item(cmd_data_tree, hf_cip_data,
772 tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
775 } /* End of if command-specific data present */
777 } /* End of if-else( request ) */
779 add_cip_service_to_info_column(pinfo, service, cip_sc_vals_ssupervisor);
782 static int
783 dissect_cip_class_s_supervisor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
785 proto_item *ti;
786 proto_tree *class_tree;
788 /* Create display subtree for the protocol */
789 ti = proto_tree_add_item(tree, proto_cip_class_s_supervisor, tvb, 0, -1, ENC_NA);
790 class_tree = proto_item_add_subtree( ti, ett_cip_class_s_supervisor );
792 dissect_cip_s_supervisor_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
794 return tvb_reported_length(tvb);
797 static int dissect_s_supervisor_exception_detail(proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset, int hf_size, int hf_data)
799 uint32_t size;
800 proto_tree_add_item_ret_uint(tree, hf_size, tvb, offset, 1, ENC_LITTLE_ENDIAN, &size);
802 proto_tree_add_item(tree, hf_data, tvb, offset+1, size, ENC_NA );
803 proto_item_set_len(item, size+1);
805 return size+1;
808 static int dissect_s_supervisor_exception_detail_common(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
809 int offset, int total_len)
811 proto_item *pi;
812 proto_tree *item_tree;
813 int total_size = 0, size;
815 item_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_exception_detail_common, &pi, "Common Exception Detail");
816 size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset,
817 hf_cip_ssupervisor_exception_detail_ced_size,
818 hf_cip_ssupervisor_exception_detail_ced_detail);
819 if (size == 0)
821 expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_ced);
822 return total_len;
824 total_size += size;
826 item_tree = proto_tree_add_subtree(tree, tvb, offset + total_size, 1, ett_exception_detail_device, &pi, "Device Exception Detail");
827 size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset + total_size,
828 hf_cip_ssupervisor_exception_detail_ded_size,
829 hf_cip_ssupervisor_exception_detail_ded_detail);
830 if (size == 0)
832 expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_ded);
833 return total_len;
835 total_size += size;
837 item_tree = proto_tree_add_subtree(tree, tvb, offset + total_size, 1, ett_exception_detail_manufacturer, &pi, "Manufacturer Exception Detail");
838 size = dissect_s_supervisor_exception_detail(item_tree, pi, tvb, offset + total_size,
839 hf_cip_ssupervisor_exception_detail_med_size,
840 hf_cip_ssupervisor_exception_detail_med_detail);
841 if (size == 0)
843 expert_add_info(pinfo, item, &ei_mal_ssupervisor_exception_detail_med);
844 return total_len;
846 total_size += size;
848 return total_size;
851 static int dissect_s_supervisor_configuration_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
852 tvbuff_t *tvb, int offset, int total_len)
854 if (total_len < 10)
856 expert_add_info(pinfo, item, &ei_mal_ssupervisor_configuration_unid);
857 return total_len;
860 dissect_unid(tvb, pinfo, offset, item, "CFUNID SNN",
861 hf_cip_ssupervisor_configuration_unid_snn_timestamp,
862 hf_cip_ssupervisor_configuration_unid_snn_date,
863 hf_cip_ssupervisor_configuration_unid_snn_time,
864 hf_cip_ssupervisor_configuration_unid_nodeid,
865 ett_ssupervisor_configuration_unid,
866 ett_ssupervisor_configuration_unid_snn);
867 return 10;
870 static int dissect_s_supervisor_safety_configuration_id(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
871 tvbuff_t *tvb, int offset, int total_len)
873 if (total_len < 10)
875 expert_add_info(pinfo, item, &ei_mal_ssupervisor_safety_configuration_id);
876 return total_len;
879 proto_tree_add_item(tree, hf_cip_ssupervisor_safety_configuration_id_sccrc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
881 dissect_cipsafety_snn(tree, tvb, pinfo, offset + 4,
882 hf_cip_ssupervisor_safety_configuration_id_snn_timestamp,
883 hf_cip_ssupervisor_safety_configuration_id_snn_date,
884 hf_cip_ssupervisor_safety_configuration_id_snn_time);
886 return 10;
889 static int dissect_s_supervisor_target_unid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
890 tvbuff_t *tvb, int offset, int total_len)
892 if (total_len < 10)
894 expert_add_info(pinfo, item, &ei_mal_ssupervisor_target_unid);
895 return total_len;
898 dissect_unid(tvb, pinfo, offset, item, "TUNID SNN",
899 hf_cip_ssupervisor_target_unid_snn_timestamp,
900 hf_cip_ssupervisor_target_unid_snn_date,
901 hf_cip_ssupervisor_target_unid_snn_time,
902 hf_cip_ssupervisor_target_unid_nodeid,
903 ett_ssupervisor_target_unid,
904 ett_ssupervisor_target_unid_snn);
905 return 10;
908 static int dissect_s_supervisor_output_connection_point_owners(packet_info *pinfo, proto_tree *tree, proto_item *item,
909 tvbuff_t *tvb, int offset, int total_len)
911 uint16_t i, num_entries;
912 proto_item *entry_item, *app_path_item;
913 proto_tree *entry_tree, *epath_tree;
914 int attr_len = 0, app_path_size;
916 if (total_len < 2)
918 expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners);
919 return total_len;
922 entry_item = proto_tree_add_item(tree, hf_cip_ssupervisor_cp_owners_num_entries,
923 tvb, offset, 2, ENC_LITTLE_ENDIAN );
924 num_entries = tvb_get_letohs(tvb, offset);
925 attr_len += 2;
927 if (num_entries > 0)
929 entry_tree = proto_item_add_subtree(entry_item, ett_ssupervisor_output_cp_owners);
931 for (i = 0; i < num_entries; i++)
933 if (total_len < attr_len+11)
935 expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_entry);
936 return total_len;
939 dissect_unid(tvb, pinfo, offset+attr_len, entry_item, "OCPUNID SNN",
940 hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp,
941 hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date,
942 hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time,
943 hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid,
944 ett_ssupervisor_output_cp_owners_ocpunid,
945 ett_ssupervisor_output_cp_owners_ocpunid_snn);
946 attr_len += 10;
948 proto_tree_add_item(entry_tree, hf_cip_ssupervisor_cp_owners_app_path_size,
949 tvb, offset+attr_len, 1, ENC_LITTLE_ENDIAN );
950 app_path_size = tvb_get_uint8( tvb, offset+attr_len);
951 attr_len += 1;
953 if (total_len < attr_len+app_path_size)
955 expert_add_info(pinfo, item, &ei_mal_ssupervisor_cp_owners_app_path_size);
956 return total_len;
959 epath_tree = proto_tree_add_subtree(entry_tree,
960 tvb, offset+attr_len, app_path_size, ett_path, &app_path_item, "Application Resource: ");
961 dissect_epath(tvb, pinfo, epath_tree, app_path_item, offset+attr_len, app_path_size, false, true, NULL, NULL, NO_DISPLAY, NULL, false);
962 attr_len += app_path_size;
966 return attr_len;
969 static int dissect_s_supervisor_proposed_tunid(packet_info *pinfo, proto_tree *tree _U_, proto_item *item,
970 tvbuff_t *tvb, int offset, int total_len)
972 if (total_len < 10)
974 expert_add_info(pinfo, item, &ei_mal_ssupervisor_proposed_tunid);
975 return total_len;
978 dissect_unid(tvb, pinfo, offset, item, "Proposed TUNID SNN",
979 hf_cip_ssupervisor_proposed_tunid_snn_timestamp,
980 hf_cip_ssupervisor_proposed_tunid_snn_date,
981 hf_cip_ssupervisor_proposed_tunid_snn_time,
982 hf_cip_ssupervisor_proposed_tunid_nodeid,
983 ett_ssupervisor_proposed_tunid,
984 ett_ssupervisor_proposed_tunid_snn);
986 return 10;
989 /************************************************
991 * Dissector for CIP Safety Validator Object
993 ************************************************/
994 static int dissect_s_validator_type(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
995 int offset, int total_len)
997 if (total_len < 1)
999 expert_add_info(pinfo, item, &ei_mal_svalidator_type);
1000 return total_len;
1003 static int* const bits[] = {
1004 &hf_cip_svalidator_type_pc,
1005 &hf_cip_svalidator_type_conn_type,
1006 NULL
1008 proto_tree_add_bitmask(tree, tvb, offset, hf_cip_svalidator_type, ett_svalidator_type, bits, ENC_LITTLE_ENDIAN);
1010 return 1;
1013 static int dissect_s_validator_time_coord_msg_min_mult(packet_info *pinfo, proto_tree *tree, proto_item *item,
1014 tvbuff_t *tvb, int offset, int total_len)
1016 int i, size;
1018 proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_size,
1019 tvb, offset, 1, ENC_LITTLE_ENDIAN );
1020 size = tvb_get_uint8( tvb, offset )*2;
1022 if (total_len < size+1)
1024 expert_add_info(pinfo, item, &ei_mal_svalidator_time_coord_msg_min_mult);
1025 return total_len;
1028 for (i = 0; i < size; i+=2)
1030 proto_tree_add_item(tree, hf_cip_svalidator_time_coord_msg_min_mult_item,
1031 tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
1034 return (size+1);
1037 static int dissect_s_validator_network_time_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item,
1038 tvbuff_t *tvb, int offset, int total_len)
1040 int i, size;
1042 proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_size,
1043 tvb, offset, 1, ENC_LITTLE_ENDIAN );
1044 size = tvb_get_uint8( tvb, offset )*2;
1046 if (total_len < size+1)
1048 expert_add_info(pinfo, item, &ei_mal_svalidator_network_time_multiplier);
1049 return total_len;
1052 for (i = 0; i < size; i+=2)
1054 proto_tree_add_item(tree, hf_cip_svalidator_network_time_multiplier_item,
1055 tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
1058 return (size+1);
1061 static int dissect_s_validator_timeout_multiplier(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
1062 int offset, int total_len)
1064 int i, size;
1066 proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_size,
1067 tvb, offset, 1, ENC_LITTLE_ENDIAN );
1068 size = tvb_get_uint8( tvb, offset );
1070 if (total_len < size+1)
1072 expert_add_info(pinfo, item, &ei_mal_svalidator_timeout_multiplier);
1073 return total_len;
1076 for (i = 0; i < size; i++)
1078 proto_tree_add_item(tree, hf_cip_svalidator_timeout_multiplier_item,
1079 tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
1082 return (size+1);
1085 static int dissect_s_validator_coordination_conn_inst(packet_info *pinfo, proto_tree *tree, proto_item *item,
1086 tvbuff_t *tvb, int offset, int total_len)
1088 int i, size;
1090 proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_size,
1091 tvb, offset, 1, ENC_LITTLE_ENDIAN );
1092 size = tvb_get_uint8( tvb, offset )*2;
1094 if (total_len < size+1)
1096 expert_add_info(pinfo, item, &ei_mal_svalidator_coordination_conn_inst);
1097 return total_len;
1100 for (i = 0; i < size; i+=2)
1102 proto_tree_add_item(tree, hf_cip_svalidator_coordination_conn_inst_item,
1103 tvb, offset+1+i, 2, ENC_LITTLE_ENDIAN );
1106 return (size+1);
1109 static int dissect_s_validator_app_data_path(packet_info *pinfo, proto_tree *tree,
1110 proto_item *item _U_, tvbuff_t *tvb, int offset, int total_len)
1112 proto_item* pi;
1113 proto_tree* epath_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_path, &pi, "Application Data Path: ");
1114 dissect_epath(tvb, pinfo, epath_tree, pi, offset, total_len, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
1115 return total_len;
1118 static int dissect_s_validator_prod_cons_fault_count(packet_info *pinfo, proto_tree *tree, proto_item *item,
1119 tvbuff_t *tvb, int offset, int total_len)
1121 int i, size;
1123 proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_size,
1124 tvb, offset, 1, ENC_LITTLE_ENDIAN );
1125 size = tvb_get_uint8( tvb, offset );
1127 if (total_len < size+1)
1129 expert_add_info(pinfo, item, &ei_mal_svalidator_prod_cons_fault_count);
1130 return total_len;
1133 for (i = 0; i < size; i++)
1135 proto_tree_add_item(tree, hf_cip_svalidator_prod_cons_fault_count_item,
1136 tvb, offset+1+i, 1, ENC_LITTLE_ENDIAN );
1139 return (size+1);
1142 static void
1143 dissect_cip_s_validator_data( proto_tree *item_tree,
1144 tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
1146 proto_item *pi, *rrsc_item;
1147 proto_tree *rrsc_tree, *cmd_data_tree;
1148 int req_path_size;
1149 uint8_t service, gen_status, add_stat_size;
1150 cip_simple_request_info_t req_data;
1152 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIPS Validator");
1154 /* Add Service code & Request/Response tree */
1155 service = tvb_get_uint8( tvb, offset );
1156 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_svalidator_rrsc, &rrsc_item, "Service: " );
1158 /* Add Request/Response */
1159 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
1161 proto_item_append_text( rrsc_item, "%s (%s)",
1162 val_to_str( ( service & CIP_SC_MASK ),
1163 cip_sc_vals_svalidator , "Unknown Service (0x%02x)"),
1164 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
1165 cip_sc_rr, "") );
1167 /* Add Service code */
1168 proto_tree_add_item(rrsc_tree, hf_cip_svalidator_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
1170 load_cip_request_data(pinfo, &req_data);
1172 if (service & CIP_SC_RESPONSE_MASK)
1174 /* Response message */
1176 /* Add additional status size */
1177 gen_status = tvb_get_uint8( tvb, offset+2 );
1178 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
1180 /* If there is any command specific data create a sub-tree for it */
1181 if( ( item_length-4-add_stat_size ) != 0 )
1183 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
1184 ett_ssupervisor_cmd_data, &pi, "Command Specific Data" );
1186 if( gen_status == CI_GRC_SUCCESS )
1188 /* Success responses */
1189 if (((service & CIP_SC_MASK) == SC_GET_ATT_ALL) &&
1190 (req_data.iInstance != SEGMENT_VALUE_NOT_SET) &&
1191 (req_data.iInstance != 0))
1193 dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset + 4 + add_stat_size, &req_data);
1195 else
1197 /* Add data */
1198 proto_tree_add_item(cmd_data_tree, hf_cip_data,
1199 tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
1202 else
1204 /* Error responses */
1206 /* Add data */
1207 proto_tree_add_item(cmd_data_tree, hf_cip_data,
1208 tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
1209 } /* end of if-else( CI_CRC_SUCCESS ) */
1211 } /* End of if command-specific data present */
1213 } /* End of if reply */
1214 else
1216 /* Request message */
1218 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
1220 /* If there is any command specific data create a sub-tree for it */
1221 if( (item_length-req_path_size-2) != 0 )
1223 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
1224 ett_ssupervisor_cmd_data, NULL, "Command Specific Data" );
1225 proto_tree_add_item(cmd_data_tree, hf_cip_data,
1226 tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
1231 add_cip_service_to_info_column(pinfo, service, cip_sc_vals_svalidator);
1234 static int
1235 dissect_cip_class_s_validator(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1237 proto_item *ti;
1238 proto_tree *class_tree;
1240 /* Create display subtree for the protocol */
1241 ti = proto_tree_add_item(tree, proto_cip_class_s_validator, tvb, 0, -1, ENC_NA);
1242 class_tree = proto_item_add_subtree( ti, ett_cip_class_s_validator );
1244 dissect_cip_s_validator_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
1246 return tvb_reported_length(tvb);
1249 static bool
1250 dissect_class_svalidator_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1252 unsigned char service, service_code, ioilen, segment;
1253 cip_req_info_t* preq_info;
1254 uint32_t classid = 0;
1255 int offset = 0;
1257 service = tvb_get_uint8( tvb, offset );
1258 service_code = service & CIP_SC_MASK;
1260 /* Handle GetAttributeAll and SetAttributeAll in CCO class */
1261 if (service_code == SC_GET_ATT_ALL)
1263 if (service & CIP_SC_RESPONSE_MASK)
1265 /* Service response */
1266 preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
1267 if ((preq_info != NULL) &&
1268 (preq_info->dissector == dissector_get_uint_handle( subdissector_class_table, CI_CLS_SAFETY_VALIDATOR)))
1270 call_dissector(preq_info->dissector, tvb, pinfo, tree);
1271 return true;
1274 else
1276 /* Service request */
1277 ioilen = tvb_get_uint8( tvb, offset + 1 );
1278 if (ioilen > 1)
1280 segment = tvb_get_uint8( tvb, offset + 2 );
1281 if (((segment & CI_SEGMENT_TYPE_MASK) == CI_LOGICAL_SEGMENT) &&
1282 ((segment & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_CLASS_ID))
1284 /* Logical Class ID, do a format check */
1285 switch ( segment & CI_LOGICAL_SEG_FORMAT_MASK )
1287 case CI_LOGICAL_SEG_8_BIT:
1288 classid = tvb_get_uint8( tvb, offset + 3 );
1289 break;
1290 case CI_LOGICAL_SEG_16_BIT:
1291 if ( ioilen >= 2 )
1292 classid = tvb_get_letohs( tvb, offset + 4 );
1293 break;
1294 case CI_LOGICAL_SEG_32_BIT:
1295 if ( ioilen >= 3 )
1296 classid = tvb_get_letohl( tvb, offset + 4 );
1297 break;
1302 if (classid == CI_CLS_SAFETY_VALIDATOR)
1304 call_dissector(cip_class_s_validator_handle, tvb, pinfo, tree );
1305 return true;
1311 return false;
1314 /************************************************
1316 * CRC handling
1318 ************************************************/
1319 static uint8_t compute_crc_s1_pid(const cip_connection_triad_t* triad)
1321 uint8_t temp_buf[8];
1322 memcpy(temp_buf, &triad->VendorID, 2);
1323 memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1324 memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1326 return crc8_0x37(temp_buf, 8, 0);
1329 static uint8_t compute_crc_s1_timestamp(uint8_t pid_seed, uint8_t mode_byte_mask, uint16_t timestamp)
1331 uint8_t mode_byte_crc = crc8_0x37(&mode_byte_mask, 1, pid_seed);
1332 uint8_t timestamp_crc = crc8_0x37((uint8_t*)&timestamp, 2, mode_byte_crc);
1334 return timestamp_crc;
1337 static uint8_t compute_crc_s1_data(uint8_t pid_seed, uint8_t mode_byte_mask, const uint8_t *buf, int len)
1339 uint8_t mode_byte_crc = crc8_0x37(&mode_byte_mask, 1, pid_seed);
1341 return crc8_0x37(buf, len, mode_byte_crc);
1344 static uint8_t compute_crc_s2_data(uint8_t pid_seed, uint8_t mode_byte_mask, uint8_t *comp_buf, int len)
1346 int i;
1347 uint8_t mode_byte_crc = crc8_0x3B(&mode_byte_mask, 1, pid_seed);
1349 for (i = 0; i < len; i++)
1350 comp_buf[i] ^= 0xFF;
1352 return crc8_0x3B(comp_buf, len, mode_byte_crc);
1355 static uint16_t compute_crc_s3_pid(const cip_connection_triad_t* triad)
1357 uint8_t temp_buf[8];
1358 memcpy(temp_buf, &triad->VendorID, 2);
1359 memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1360 memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1362 return crc16_0x080F_seed(temp_buf, 8, 0);
1365 static uint16_t compute_crc_s3_base_data(uint16_t pid_seed, uint8_t mode_byte_mask, const uint8_t *buf, int len)
1367 uint16_t mode_byte_crc = crc16_0x080F_seed(&mode_byte_mask, 1, pid_seed);
1369 return crc16_0x080F_seed(buf, len, mode_byte_crc);
1372 static uint16_t compute_crc_s3_extended_data(uint16_t pid_seed, uint16_t rollover_value, uint8_t mode_byte_mask, const uint8_t *buf, int len)
1374 uint16_t rollover_crc = crc16_0x080F_seed((uint8_t*)&rollover_value, 2, pid_seed);
1375 uint16_t mode_byte_crc = crc16_0x080F_seed(&mode_byte_mask, 1, rollover_crc);
1377 return crc16_0x080F_seed(buf, len, mode_byte_crc);
1380 static uint16_t compute_crc_s3_time(uint16_t pid_seed, uint8_t ack_mcast_byte, uint16_t timestamp_value)
1382 uint16_t mode_byte_crc = crc16_0x080F_seed(&ack_mcast_byte, 1, pid_seed);
1383 uint16_t timestamp_crc;
1385 timestamp_crc = crc16_0x080F_seed((uint8_t*)&timestamp_value, 2, mode_byte_crc);
1387 return timestamp_crc;
1390 static uint32_t compute_crc_s5_pid(const cip_connection_triad_t* triad)
1392 uint8_t temp_buf[8];
1393 memcpy(temp_buf, &triad->VendorID, 2);
1394 memcpy(&temp_buf[2], &triad->DeviceSerialNumber, 4);
1395 memcpy(&temp_buf[6], &triad->ConnSerialNumber, 2);
1397 return crc32_0x5D6DCB_seed(temp_buf, 8, 0);
1400 static uint32_t compute_crc_s5_short_data(uint32_t pid_seed, uint16_t rollover_value, uint8_t mode_byte_mask, uint16_t timestamp_value, const uint8_t *buf, int len)
1402 uint32_t rollover_crc = crc32_0x5D6DCB_seed((uint8_t*)&rollover_value, 2, pid_seed);
1403 uint32_t mode_byte_crc = crc32_0x5D6DCB_seed(&mode_byte_mask, 1, rollover_crc);
1404 uint32_t data_crc, timestamp_crc;
1406 data_crc = crc32_0x5D6DCB_seed(buf, len, mode_byte_crc);
1407 timestamp_crc = crc32_0x5D6DCB_seed((uint8_t*)&timestamp_value, 2, data_crc);
1409 return timestamp_crc;
1412 static uint32_t compute_crc_s5_long_data(uint32_t pid_seed, uint16_t rollover_value, uint8_t mode_byte_mask, uint16_t timestamp_value, const uint8_t *comp_buf, int len)
1414 uint32_t rollover_crc = crc32_0x5D6DCB_seed((uint8_t*)&rollover_value, 2, pid_seed);
1415 uint32_t mode_byte_crc = crc32_0x5D6DCB_seed(&mode_byte_mask, 1, rollover_crc);
1416 uint32_t comp_data_crc, timestamp_crc;
1418 comp_data_crc = crc32_0x5D6DCB_seed(comp_buf, len, mode_byte_crc);
1419 timestamp_crc = crc32_0x5D6DCB_seed((uint8_t*)&timestamp_value, 2, comp_data_crc);
1421 return timestamp_crc;
1424 static uint32_t compute_crc_s5_time(uint32_t pid_seed, uint8_t ack_mcast_byte, uint16_t timestamp_value)
1426 uint32_t mode_byte_crc = crc32_0x5D6DCB_seed(&ack_mcast_byte, 1, pid_seed);
1427 uint32_t timestamp_crc;
1429 timestamp_crc = crc32_0x5D6DCB_seed((uint8_t*)&timestamp_value, 2, mode_byte_crc);
1431 return timestamp_crc;
1434 static bool verify_compliment_data(tvbuff_t *tvb, int data_offset, int complement_data_offset, int data_size)
1436 const uint8_t *data = tvb_get_ptr(tvb, data_offset, data_size);
1437 const uint8_t *complement_data = tvb_get_ptr(tvb, complement_data_offset, data_size);
1438 int i;
1440 for (i = 0; i < data_size; i++)
1442 if ((data[i] ^ complement_data[i])!= 0xFF)
1443 return false;
1446 return true;
1449 static void validate_crc_s5(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, bool compute_crc,
1450 uint32_t crc_s5_0, uint32_t crc_s5_1, uint32_t crc_s5_2, uint32_t computed_crc_s5)
1452 proto_item* crc_s5_status_item;
1454 /* CRC-S5 doesn't use proto_tree_add_checksum because the checksum is broken up into multiple fields */
1455 if (compute_crc)
1457 uint32_t value_s5 = crc_s5_0;
1458 value_s5 += ((crc_s5_1 << 8) & 0xFF00);
1459 value_s5 += ((crc_s5_2 << 16) & 0xFF0000);
1461 if (computed_crc_s5 == value_s5)
1463 crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_GOOD);
1465 else
1467 crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_BAD);
1468 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);
1471 else
1473 crc_s5_status_item = proto_tree_add_uint(tree, hf_cipsafety_crc_s5_status, tvb, 0, 0, PROTO_CHECKSUM_E_UNVERIFIED);
1476 proto_item_set_generated(crc_s5_status_item);
1479 /************************************************
1481 * Dissector for CIP Safety I/O Data
1483 ************************************************/
1484 static void
1485 dissect_mode_byte( proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
1487 proto_item *mode_item, *run_idle_item, *tbd_item, *tbd2_item;
1488 proto_tree *mode_tree;
1489 uint8_t mode_byte;
1491 mode_byte = tvb_get_uint8(tvb, offset);
1493 /* dissect Mode Byte bits */
1494 mode_item = proto_tree_add_item(tree, hf_cipsafety_mode_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1495 mode_tree = proto_item_add_subtree( mode_item, ett_cipsafety_mode_byte);
1497 proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_ping_count, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1498 proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_tbd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1499 proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_copy, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1500 proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_not_run_idle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1501 tbd_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1502 tbd2_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_tbd_2_bit, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1503 run_idle_item = proto_tree_add_item(mode_tree, hf_cipsafety_mode_byte_run_idle, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1505 /* verify Mode Byte bits */
1506 /* TBD */
1507 if ((((mode_byte & 0x20) >> 5) & 0x01) == (((mode_byte & 0x04) >> 2) & 0x01))
1508 expert_add_info(pinfo, tbd_item, &ei_cipsafety_tbd_not_complemented);
1510 /* TBD 2 */
1511 if ((((mode_byte & 0x40) >> 6) & 0x01) != (((mode_byte & 0x08) >> 3) & 0x01))
1512 expert_add_info(pinfo, tbd2_item, &ei_cipsafety_tbd2_not_copied);
1514 /* Run/Idle */
1515 if ((((mode_byte & 0x80) >> 7) & 0x01) == (((mode_byte & 0x10) >> 4) & 0x01))
1516 expert_add_info(pinfo, run_idle_item, &ei_cipsafety_run_idle_not_complemented);
1519 static void
1520 dissect_ack_byte( proto_tree *tree, tvbuff_t *tvb, int offset)
1522 // TODO: add ack_byte validation
1523 static int* const bits[] = {
1524 &hf_cipsafety_ack_byte_ping_count_reply,
1525 &hf_cipsafety_ack_byte_reserved1,
1526 &hf_cipsafety_ack_byte_ping_response,
1527 &hf_cipsafety_ack_byte_reserved2,
1528 &hf_cipsafety_ack_byte_parity_even,
1529 NULL
1532 proto_tree_add_bitmask(tree, tvb, offset, hf_cipsafety_ack_byte, ett_cipsafety_ack_byte, bits, ENC_LITTLE_ENDIAN);
1535 static void
1536 dissect_mcast_byte( proto_tree *tree, tvbuff_t *tvb, int offset)
1538 // TODO: add mcast_byte validation
1539 static int* const bits[] = {
1540 &hf_cipsafety_mcast_byte_consumer_num,
1541 &hf_cipsafety_mcast_byte_reserved1,
1542 &hf_cipsafety_mcast_byte_mai,
1543 &hf_cipsafety_mcast_byte_reserved2,
1544 &hf_cipsafety_mcast_byte_parity_even,
1545 NULL
1548 proto_tree_add_bitmask(tree, tvb, offset, hf_cipsafety_mcast_byte, ett_cipsafety_mcast_byte, bits, ENC_LITTLE_ENDIAN);
1551 // Base Format Time Correction Message
1552 static void dissect_base_format_time_correction_message(proto_tree* tree, tvbuff_t* tvb, int offset)
1554 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_BASE_TIME_CORRECTION);
1555 proto_item_set_generated(it);
1557 dissect_mcast_byte(tree, tvb, offset);
1558 proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
1559 proto_tree_add_item(tree, hf_cipsafety_mcast_byte2, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
1560 proto_tree_add_item(tree, hf_cipsafety_crc_s3, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
1563 // Extended Format Time Correction Message
1564 static void dissect_extended_format_time_correction_message(proto_tree* tree, tvbuff_t* tvb, int offset)
1566 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_EXTENDED_TIME_CORRECTION);
1567 proto_item_set_generated(it);
1569 dissect_mcast_byte(tree, tvb, offset);
1570 proto_tree_add_item(tree, hf_cipsafety_time_correction, tvb, offset + 1, 2, ENC_LITTLE_ENDIAN);
1571 proto_tree_add_item(tree, hf_cipsafety_crc_s5_0, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
1572 proto_tree_add_item(tree, hf_cipsafety_crc_s5_1, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN);
1573 proto_tree_add_item(tree, hf_cipsafety_crc_s5_2, tvb, offset + 5, 1, ENC_LITTLE_ENDIAN);
1575 // TODO: Validate CRC S5.
1578 // Base Format, Time Stamp Section Format
1579 static void dissect_base_format_time_stamp_section(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int offset,
1580 bool compute_crc, uint8_t mode_byte, const cip_connection_triad_t* connection_triad)
1582 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_BASE_TIME_STAMP);
1583 proto_item_set_generated(it);
1585 proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1586 uint16_t timestamp = tvb_get_letohs(tvb, offset);
1588 if (compute_crc)
1590 uint8_t computed_crc_s1 = compute_crc_s1_timestamp(compute_crc_s1_pid(connection_triad),
1591 (mode_byte & MODE_BYTE_CRC_S1_TIME_STAMP_MASK),
1592 timestamp);
1593 proto_tree_add_checksum(tree, tvb, offset + 2,
1594 hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
1595 computed_crc_s1, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1597 else
1599 proto_tree_add_checksum(tree, tvb, offset + 2,
1600 hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
1601 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1605 // Base Format Time Coordination Message
1606 // Note: All data starts from the beginning of the tvb buffer.
1607 static void dissect_base_format_time_coordination_message(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb,
1608 bool compute_crc, const cip_connection_triad_t* connection_triad)
1610 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_BASE_TIME_COORDINATION);
1611 proto_item_set_generated(it);
1613 dissect_ack_byte(tree, tvb, 0);
1614 uint8_t ack_byte = tvb_get_uint8(tvb, 0);
1616 proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
1617 uint16_t timestamp = tvb_get_letohs(tvb, 1);
1619 proto_tree_add_item(tree, hf_cipsafety_ack_byte2, tvb, 3, 1, ENC_LITTLE_ENDIAN);
1621 if (compute_crc)
1623 uint16_t computed_crc_s3 = compute_crc_s3_time(compute_crc_s3_pid(connection_triad), ack_byte, timestamp);
1624 proto_tree_add_checksum(tree, tvb, 4,
1625 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1626 computed_crc_s3, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1628 else
1630 proto_tree_add_checksum(tree, tvb, 4,
1631 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1632 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1636 // Extended Format Time Coordination Message
1637 // Note: All data starts from the beginning of the tvb buffer.
1638 static void dissect_extended_format_time_coordination_message(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb,
1639 bool compute_crc, const cip_connection_triad_t* connection_triad)
1641 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_EXTENDED_TIME_COORDINATION);
1642 proto_item_set_generated(it);
1644 dissect_ack_byte(tree, tvb, 0);
1645 uint8_t ack_byte = tvb_get_uint8(tvb, 0);
1647 proto_tree_add_item(tree, hf_cipsafety_consumer_time_value, tvb, 1, 2, ENC_LITTLE_ENDIAN);
1648 uint16_t timestamp = tvb_get_letohs(tvb, 1);
1650 uint32_t crc_s5_0, crc_s5_1, crc_s5_2;
1651 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, 3, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
1652 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, 4, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
1653 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, 5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
1655 uint32_t computed_crc_s5 = compute_crc_s5_time(compute_crc_s5_pid(connection_triad),
1656 ack_byte,
1657 timestamp);
1658 validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1661 // 1 or 2 Byte Data section, Base Format
1662 // Note: All data starts from the beginning of the tvb buffer.
1663 static void dissect_base_format_1_or_2_byte_data(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int io_data_size,
1664 bool compute_crc, const cip_connection_triad_t* connection_triad)
1666 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_BASE_1_2_BYTE_DATA);
1667 proto_item_set_generated(it);
1669 proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1670 dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1671 uint8_t mode_byte = tvb_get_uint8(tvb, io_data_size);
1673 if (compute_crc)
1675 uint8_t computed_crc_s1 = compute_crc_s1_data(compute_crc_s1_pid(connection_triad),
1676 (mode_byte & MODE_BYTE_CRC_S1_MASK),
1677 tvb_get_ptr(tvb, 0, io_data_size), io_data_size);
1679 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1680 hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1, pinfo,
1681 computed_crc_s1, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1683 uint8_t computed_crc_s2 = compute_crc_s2_data(compute_crc_s1_pid(connection_triad),
1684 ((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S1_MASK),
1685 /* I/O data is duplicated because it will be complemented inline */
1686 (uint8_t*)tvb_memdup(pinfo->pool, tvb, 0, io_data_size), io_data_size);
1688 proto_tree_add_checksum(tree, tvb, io_data_size + 2,
1689 hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2, pinfo,
1690 computed_crc_s2, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1692 else
1694 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1695 hf_cipsafety_crc_s1, hf_cipsafety_crc_s1_status, &ei_cipsafety_crc_s1,
1696 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1697 proto_tree_add_checksum(tree, tvb, io_data_size + 2,
1698 hf_cipsafety_crc_s2, hf_cipsafety_crc_s2_status, &ei_cipsafety_crc_s2,
1699 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1703 // 3 to 250 Byte Data section, Base Format
1704 // Note: All data starts from the beginning of the tvb buffer.
1705 static void dissect_base_format_3_to_250_byte_data(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int io_data_size,
1706 bool compute_crc, const cip_connection_triad_t* connection_triad)
1708 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_BASE_3_250_BYTE_DATA);
1709 proto_item_set_generated(it);
1711 proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1712 dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1713 unsigned mode_byte = tvb_get_uint8(tvb, io_data_size);
1715 if (compute_crc)
1717 uint16_t computed_crc_s3 = compute_crc_s3_base_data(compute_crc_s3_pid(connection_triad),
1718 mode_byte & MODE_BYTE_CRC_S3_MASK, tvb_get_ptr(tvb, 0, io_data_size), io_data_size);
1720 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1721 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1722 computed_crc_s3, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1724 else
1726 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1727 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1728 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1731 proto_item* complement_item = proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size + 3, io_data_size, ENC_NA);
1732 if (!verify_compliment_data(tvb, 0, io_data_size + 3, io_data_size))
1733 expert_add_info(pinfo, complement_item, &ei_cipsafety_not_complement_data);
1735 if (compute_crc)
1737 uint16_t computed_crc_s3 = compute_crc_s3_base_data(compute_crc_s3_pid(connection_triad),
1738 ((mode_byte ^ 0xFF) & MODE_BYTE_CRC_S3_MASK),
1739 tvb_get_ptr(tvb, io_data_size + 3, io_data_size), io_data_size);
1741 proto_tree_add_checksum(tree, tvb, (io_data_size * 2) + 3,
1742 hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3, pinfo,
1743 computed_crc_s3, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1745 else
1747 proto_tree_add_checksum(tree, tvb, (io_data_size * 2) + 3,
1748 hf_cipsafety_complement_crc_s3, hf_cipsafety_complement_crc_s3_status, &ei_cipsafety_complement_crc_s3,
1749 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1753 // 1 or 2 Byte Data Section, Extended Format
1754 // Note: All data starts from the beginning of the tvb buffer.
1755 static void dissect_extended_format_1_or_2_byte_data(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int io_data_size,
1756 bool compute_crc, const cip_connection_triad_t* connection_triad, const cip_safety_packet_data_t* packet_data)
1758 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_EXTENDED_1_2_BYTE_DATA);
1759 proto_item_set_generated(it);
1761 proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1762 dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1763 unsigned mode_byte = tvb_get_uint8(tvb, io_data_size);
1765 uint32_t crc_s5_0, crc_s5_1, crc_s5_2;
1766 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_0, tvb, io_data_size + 1, 1, ENC_LITTLE_ENDIAN, &crc_s5_0);
1767 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_1, tvb, io_data_size + 2, 1, ENC_LITTLE_ENDIAN, &crc_s5_1);
1768 proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, io_data_size + 3, 2, ENC_LITTLE_ENDIAN);
1769 proto_tree_add_item_ret_uint(tree, hf_cipsafety_crc_s5_2, tvb, io_data_size + 5, 1, ENC_LITTLE_ENDIAN, &crc_s5_2);
1771 uint16_t timestamp = tvb_get_letohs(tvb, io_data_size + 3);
1773 uint32_t computed_crc_s5 = 0;
1774 if (packet_data != NULL)
1776 computed_crc_s5 = compute_crc_s5_short_data(compute_crc_s5_pid(connection_triad),
1777 packet_data->rollover_value,
1778 mode_byte & MODE_BYTE_CRC_S5_BASE_MASK,
1779 timestamp,
1780 tvb_get_ptr(tvb, 0, io_data_size),
1781 io_data_size);
1784 validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1787 // 3 to 250 Byte Data section, Extended Format
1788 // Note: All data starts from the beginning of the tvb buffer.
1789 static void dissect_extended_format_3_to_250_byte_data(packet_info* pinfo, proto_tree* tree, tvbuff_t* tvb, int io_data_size,
1790 bool compute_crc, const cip_connection_triad_t* connection_triad, const cip_safety_packet_data_t* packet_data)
1792 proto_item* it = proto_tree_add_uint(tree, hf_cip_safety_message_encoding, tvb, 0, 0, MSG_ENCODING_EXTENDED_3_250_BYTE_DATA);
1793 proto_item_set_generated(it);
1795 proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, io_data_size, ENC_NA);
1796 dissect_mode_byte(tree, tvb, io_data_size, pinfo);
1797 unsigned mode_byte = tvb_get_uint8(tvb, io_data_size);
1799 uint16_t timestamp = tvb_get_letohs(tvb, (io_data_size * 2) + 5);
1801 if (compute_crc)
1803 if (packet_data != NULL)
1805 uint16_t computed_crc_s3 = compute_crc_s3_extended_data(compute_crc_s3_pid(connection_triad),
1806 packet_data->rollover_value,
1807 mode_byte & MODE_BYTE_CRC_S3_MASK,
1808 tvb_get_ptr(tvb, 0, io_data_size), io_data_size);
1810 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1811 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3, pinfo,
1812 computed_crc_s3, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
1815 else
1817 proto_tree_add_checksum(tree, tvb, io_data_size + 1,
1818 hf_cipsafety_crc_s3, hf_cipsafety_crc_s3_status, &ei_cipsafety_crc_s3,
1819 pinfo, 0, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1822 proto_item* complement_item = proto_tree_add_item(tree, hf_cipsafety_complement_data, tvb, io_data_size + 3, io_data_size, ENC_NA);
1823 if (!verify_compliment_data(tvb, 0, io_data_size + 3, io_data_size))
1824 expert_add_info(pinfo, complement_item, &ei_cipsafety_not_complement_data);
1826 uint32_t crc_s5_0, crc_s5_1, crc_s5_2;
1827 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);
1828 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);
1829 proto_tree_add_item(tree, hf_cipsafety_timestamp, tvb, (io_data_size * 2) + 5, 2, ENC_LITTLE_ENDIAN);
1830 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);
1832 uint32_t computed_crc_s5 = 0;
1833 if (packet_data != NULL)
1835 computed_crc_s5 = compute_crc_s5_long_data(compute_crc_s5_pid(connection_triad),
1836 packet_data->rollover_value,
1837 mode_byte & MODE_BYTE_CRC_S5_EXTENDED_MASK,
1838 timestamp,
1839 tvb_get_ptr(tvb, io_data_size + 3, io_data_size),
1840 io_data_size);
1842 validate_crc_s5(pinfo, tree, tvb, compute_crc, crc_s5_0, crc_s5_1, crc_s5_2, computed_crc_s5);
1845 // Note: This updates the running timestamp/rollover data in safety_info during the first pass.
1846 static cip_safety_packet_data_t* get_timestamp_packet_data(packet_info* pinfo, cip_safety_info_t* safety_info, uint16_t timestamp)
1848 cip_safety_packet_data_t* packet_data = NULL;
1850 /* Determine if packet timestamp results in rollover count increment */
1851 if (!pinfo->fd->visited)
1853 packet_data = wmem_new0(wmem_file_scope(), cip_safety_packet_data_t);
1855 if ((timestamp == 0) && !safety_info->eip_conn_info->safety.seen_non_zero_timestamp)
1857 // The rollover value is zero, until the Time Coordination exchange is done.
1858 // When the timestamp is zero, that means we haven't seen the Time Coordination message.
1859 packet_data->rollover_value = 0;
1861 else
1863 safety_info->eip_conn_info->safety.seen_non_zero_timestamp = true;
1865 if (timestamp < safety_info->eip_conn_info->safety.running_timestamp_value)
1867 safety_info->eip_conn_info->safety.running_rollover_value++;
1870 /* Save the rollover value for CRC calculations */
1871 packet_data->rollover_value = safety_info->eip_conn_info->safety.running_rollover_value;
1872 safety_info->eip_conn_info->safety.running_timestamp_value = timestamp;
1875 p_add_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0, packet_data);
1877 else
1879 packet_data = (cip_safety_packet_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cipsafety, 0);
1882 return packet_data;
1885 enum cip_safety_data_type {CIP_SAFETY_DATA_TYPE_UNKNOWN, CIP_SAFETY_PRODUCE, CIP_SAFETY_CONSUME};
1886 static enum cip_safety_data_type get_cip_safety_data_type(enum enip_connid_type conn_type, const cip_safety_epath_info_t* safety)
1888 if (conn_type == ECIDT_O2T && safety->originator_type == CIP_SAFETY_ORIGINATOR_PRODUCER)
1890 return CIP_SAFETY_PRODUCE;
1892 else if (conn_type == ECIDT_O2T && safety->originator_type == CIP_SAFETY_ORIGINATOR_CONSUMER)
1894 return CIP_SAFETY_CONSUME;
1896 else if (conn_type == ECIDT_T2O && safety->originator_type == CIP_SAFETY_ORIGINATOR_PRODUCER)
1898 return CIP_SAFETY_CONSUME;
1900 else if (conn_type == ECIDT_T2O && safety->originator_type == CIP_SAFETY_ORIGINATOR_CONSUMER)
1902 return CIP_SAFETY_PRODUCE;
1904 else
1906 return CIP_SAFETY_DATA_TYPE_UNKNOWN;
1910 void add_safety_data_type_to_info_column(packet_info *pinfo, enum enip_connid_type conn_type, const cip_safety_epath_info_t* safety)
1912 enum cip_safety_data_type data_type = get_cip_safety_data_type(conn_type, safety);
1914 if (data_type == CIP_SAFETY_CONSUME)
1916 col_append_str(pinfo->cinfo, COL_INFO, " [C->P]");
1918 else // CIP_SAFETY_PRODUCE
1920 col_append_str(pinfo->cinfo, COL_INFO, " [P->C]");
1924 static void
1925 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)
1927 bool multicast = in4_addr_is_multicast(pntoh32(pinfo->dst.data));
1928 bool server_dir = false;
1929 enum enip_connid_type conn_type = ECIDT_UNKNOWN;
1930 enum cip_safety_format_type format = CIP_SAFETY_BASE_FORMAT;
1931 bool compute_crc = ((safety_info != NULL) && (safety_info->compute_crc == true));
1932 cip_connection_triad_t connection_triad = {0};
1934 /* Make entries in Protocol column and Info column on summary display */
1935 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP Safety");
1937 /* determine the connection type as it affects the fields dissected */
1938 if (safety_info != NULL && safety_info->eip_conn_info != NULL)
1940 conn_type = safety_info->conn_type;
1941 format = safety_info->eip_conn_info->safety.format;
1942 server_dir = (safety_info->eip_conn_info->TransportClass_trigger & CI_PRODUCTION_DIR_MASK) ? true : false;
1945 /* compute the base packet length to determine what is actual I/O data */
1946 int base_length = multicast ? 12 : 6;
1948 if (item_length < base_length) {
1949 expert_add_info(pinfo, item, &ei_mal_io);
1950 return;
1953 if (((conn_type == ECIDT_O2T) && (server_dir == false)) ||
1954 ((conn_type == ECIDT_T2O) && (server_dir == true)))
1956 if (compute_crc)
1958 if ((conn_type == ECIDT_O2T) && (server_dir == false))
1960 connection_triad = safety_info->eip_conn_info->triad;
1962 else
1964 connection_triad = safety_info->eip_conn_info->safety.target_triad;
1968 /* consumer data */
1969 proto_item_append_text(item, " [Consume]");
1970 col_append_str(pinfo->cinfo, COL_INFO, " [C->P]");
1972 switch (format)
1974 case CIP_SAFETY_BASE_FORMAT:
1975 dissect_base_format_time_coordination_message(pinfo, tree, tvb, compute_crc, &connection_triad);
1976 break;
1977 case CIP_SAFETY_EXTENDED_FORMAT:
1978 dissect_extended_format_time_coordination_message(pinfo, tree, tvb, compute_crc, &connection_triad);
1979 break;
1982 else if (((conn_type == ECIDT_O2T) && (server_dir == true)) ||
1983 ((conn_type == ECIDT_T2O) && (server_dir == false)))
1985 if (compute_crc)
1987 if ((conn_type == ECIDT_O2T) && (server_dir == true))
1989 connection_triad = safety_info->eip_conn_info->triad;
1991 else
1993 connection_triad = safety_info->eip_conn_info->safety.target_triad;
1997 bool short_format = true;
1998 if (item_length-base_length > 2)
1999 short_format = false;
2001 /* producer data */
2002 proto_item_append_text(item, " [Produce]");
2003 col_append_str(pinfo->cinfo, COL_INFO, " [P->C]");
2005 switch (format)
2007 case CIP_SAFETY_BASE_FORMAT:
2008 if (short_format)
2010 int io_data_size = item_length-base_length;
2011 uint8_t mode_byte = tvb_get_uint8(tvb, io_data_size);
2013 dissect_base_format_1_or_2_byte_data(pinfo, tree, tvb, io_data_size, compute_crc, &connection_triad);
2014 dissect_base_format_time_stamp_section(pinfo, tree, tvb, io_data_size + 3, compute_crc, mode_byte, &connection_triad);
2016 if (multicast)
2018 dissect_base_format_time_correction_message(tree, tvb, item_length - 6);
2021 else
2023 /* 3 to 250 Byte Data section, Base Format */
2024 if (item_length%2 == 1)
2026 /* Malformed packet */
2027 expert_add_info(pinfo, item, &ei_mal_io);
2028 return;
2031 int io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
2032 uint8_t mode_byte = tvb_get_uint8(tvb, io_data_size);
2034 dissect_base_format_3_to_250_byte_data(pinfo, tree, tvb, io_data_size, compute_crc, &connection_triad);
2035 dissect_base_format_time_stamp_section(pinfo, tree, tvb, (io_data_size * 2) + 5, compute_crc, mode_byte, &connection_triad);
2037 if (multicast)
2039 dissect_base_format_time_correction_message(tree, tvb, (io_data_size * 2) + 5);
2042 break;
2043 case CIP_SAFETY_EXTENDED_FORMAT:
2045 int io_data_size;
2046 uint16_t timestamp;
2048 if (short_format)
2050 io_data_size = item_length-base_length;
2051 timestamp = tvb_get_letohs(tvb, io_data_size+3);
2053 else
2055 io_data_size = multicast ? ((item_length-14)/2) : ((item_length-8)/2);
2056 timestamp = tvb_get_letohs(tvb, (io_data_size*2)+5);
2059 cip_safety_packet_data_t* packet_data = NULL;
2060 if (compute_crc)
2062 packet_data = get_timestamp_packet_data(pinfo, safety_info, timestamp);
2065 if (short_format)
2067 dissect_extended_format_1_or_2_byte_data(pinfo, tree, tvb, io_data_size, compute_crc, &connection_triad, packet_data);
2069 if (multicast)
2071 dissect_extended_format_time_correction_message(tree, tvb, item_length - 6);
2074 else
2076 /* 3 to 250 Byte Data section, Extended Format */
2077 if (item_length%2 == 1)
2079 /* Malformed packet */
2080 expert_add_info(pinfo, item, &ei_mal_io);
2081 return;
2084 dissect_extended_format_3_to_250_byte_data(pinfo, tree, tvb, io_data_size, compute_crc, &connection_triad, packet_data);
2086 if (multicast)
2088 dissect_extended_format_time_correction_message(tree, tvb, (io_data_size * 2) + 8);
2091 break;
2092 } // END case CIP_SAFETY_EXTENDED_FORMAT
2093 } // END switch
2095 else
2097 /* Shouldn't happen, but at least dissect it as data */
2098 proto_tree_add_item(tree, hf_cipsafety_data, tvb, 0, item_length, ENC_NA);
2102 static int
2103 dissect_cipsafety(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2105 proto_item *ti;
2106 proto_tree *safety_tree;
2107 cip_safety_info_t* safety_info = (cip_safety_info_t*)data;
2109 /* Create display subtree for the protocol */
2110 ti = proto_tree_add_item(tree, proto_cipsafety, tvb, 0, -1, ENC_NA);
2111 safety_tree = proto_item_add_subtree( ti, ett_cip_safety);
2113 dissect_cip_safety_data(safety_tree, ti, tvb, tvb_reported_length(tvb), pinfo, safety_info);
2114 return tvb_captured_length(tvb);
2117 static int dissect_cipsafety_base_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2119 cip_safety_info_t safety_info;
2120 cip_conn_info_t eip_conn_info;
2121 memset(&eip_conn_info, 0, sizeof(eip_conn_info));
2122 safety_info.eip_conn_info = &eip_conn_info;
2123 safety_info.compute_crc = false;
2125 // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
2126 safety_info.conn_type = ECIDT_T2O;
2127 safety_info.eip_conn_info->TransportClass_trigger = 0;
2128 safety_info.eip_conn_info->safety.format = CIP_SAFETY_BASE_FORMAT;
2130 return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
2133 static int dissect_cipsafety_extended_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2135 cip_safety_info_t safety_info;
2136 cip_conn_info_t eip_conn_info;
2137 memset(&eip_conn_info, 0, sizeof(eip_conn_info));
2138 safety_info.eip_conn_info = &eip_conn_info;
2139 safety_info.compute_crc = false;
2141 // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
2142 safety_info.conn_type = ECIDT_T2O;
2143 safety_info.eip_conn_info->TransportClass_trigger = 0;
2144 safety_info.eip_conn_info->safety.format = CIP_SAFETY_EXTENDED_FORMAT;
2146 return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
2149 static int dissect_cipsafety_base_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2151 cip_safety_info_t safety_info;
2152 cip_conn_info_t eip_conn_info;
2153 memset(&eip_conn_info, 0, sizeof(eip_conn_info));
2154 safety_info.eip_conn_info = &eip_conn_info;
2155 safety_info.compute_crc = false;
2157 // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
2158 safety_info.conn_type = ECIDT_O2T;
2159 safety_info.eip_conn_info->TransportClass_trigger = 0;
2160 safety_info.eip_conn_info->safety.format = CIP_SAFETY_BASE_FORMAT;
2162 return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
2165 static int dissect_cipsafety_extended_time_coord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2167 cip_safety_info_t safety_info;
2168 cip_conn_info_t eip_conn_info;
2169 memset(&eip_conn_info, 0, sizeof(eip_conn_info));
2170 safety_info.eip_conn_info = &eip_conn_info;
2171 safety_info.compute_crc = false;
2173 // Set up parameters that will trigger dissect_cip_safety_data to parse the correct format.
2174 safety_info.conn_type = ECIDT_O2T;
2175 safety_info.eip_conn_info->TransportClass_trigger = 0;
2176 safety_info.eip_conn_info->safety.format = CIP_SAFETY_EXTENDED_FORMAT;
2178 return dissect_cipsafety(tvb, pinfo, tree, &safety_info);
2181 static int dissect_sercosiii_link_error_count_p1p2(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
2182 int offset, int total_len)
2184 if (total_len < 4)
2186 expert_add_info(pinfo, item, &ei_mal_sercosiii_link_error_count_p1p2);
2187 return total_len;
2190 proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p1, tvb, offset, 2, ENC_LITTLE_ENDIAN );
2191 proto_tree_add_item(tree, hf_cip_sercosiii_link_error_count_p2, tvb, offset+2, 2, ENC_LITTLE_ENDIAN );
2192 return 4;
2195 static int dissect_sercosiii_safety_network_number(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
2196 int offset, int total_len _U_)
2198 proto_tree_add_item(tree, hf_cip_sercosiii_link_snn, tvb, offset, 6, ENC_NA);
2199 return 6;
2202 const attribute_info_t cip_safety_attribute_vals[] = {
2204 /* Safety Supervisor */
2205 {0x39, true, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_class_subclass, NULL},
2206 {0x39, false, 1, -1, "Number of Attributes", cip_usint, &hf_cip_ssupervisor_num_attr, NULL},
2207 {0x39, false, 2, -1, "Attribute List", cip_usint_array, &hf_cip_ssupervisor_attr_list, NULL},
2208 {0x39, false, 5, -1, "Manufacturer Name", cip_short_string, &hf_cip_ssupervisor_manufacture_name, NULL},
2209 {0x39, false, 6, -1, "Manufacturer Model Number", cip_short_string, &hf_cip_ssupervisor_manufacture_model_number, NULL},
2210 {0x39, false, 7, -1, "Software Revision Level", cip_short_string, &hf_cip_ssupervisor_sw_rev_level, NULL},
2211 {0x39, false, 8, -1, "Hardware Revision Level", cip_short_string, &hf_cip_ssupervisor_hw_rev_level, NULL},
2212 {0x39, false, 9, -1, "Manufacturer Serial Number", cip_short_string, &hf_cip_ssupervisor_manufacture_serial_number, NULL},
2213 {0x39, false, 10, -1, "Device Configuration", cip_short_string, &hf_cip_ssupervisor_device_config, NULL},
2214 {0x39, false, 11, -1, "Device Status", cip_usint, &hf_cip_ssupervisor_device_status, NULL},
2215 {0x39, false, 12, -1, "Exception Status", cip_byte, &hf_cip_ssupervisor_exception_status, NULL},
2216 {0x39, false, 13, -1, "Exception Detail Alarm", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_common},
2217 {0x39, false, 14, -1, "Exception Detail Warning", cip_dissector_func, NULL, dissect_s_supervisor_exception_detail_common},
2218 {0x39, false, 15, -1, "Alarm Enable", cip_bool, &hf_cip_ssupervisor_alarm_enable, NULL},
2219 {0x39, false, 16, -1, "Warning Enable", cip_bool, &hf_cip_ssupervisor_warning_enable, NULL},
2220 {0x39, false, 17, -1, "Time", cip_date_and_time, &hf_cip_ssupervisor_time, NULL},
2221 {0x39, false, 18, -1, "Clock Power Cycle Behavior", cip_usint, &hf_cip_ssupervisor_clock_power_cycle_behavior, NULL},
2222 {0x39, false, 19, -1, "Last Maintenance Date", cip_date, &hf_cip_ssupervisor_last_maintenance_date, NULL},
2223 {0x39, false, 20, -1, "Next Scheduled Maintenance Date", cip_date, &hf_cip_ssupervisor_next_scheduled_maintenance_date, NULL},
2224 {0x39, false, 21, -1, "Scheduled Maintenance Expiration Timer", cip_int, &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer, NULL},
2225 {0x39, false, 22, -1, "Scheduled Maintenance Expiration Warning Enable", cip_bool, &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable, NULL},
2226 {0x39, false, 23, -1, "Run Hours", cip_udint, &hf_cip_ssupervisor_run_hours, NULL},
2227 {0x39, false, 24, -1, "Configuration Lock", cip_bool, &hf_cip_ssupervisor_configuration_lock, NULL},
2228 {0x39, false, 25, -1, "Configuration UNID (CFUNID)", cip_dissector_func, NULL, dissect_s_supervisor_configuration_unid},
2229 {0x39, false, 26, -1, "Safety Configuration Identifier (SCID)", cip_dissector_func, NULL, dissect_s_supervisor_safety_configuration_id},
2230 {0x39, false, 27, -1, "Target UNID (TUNID)", cip_dissector_func, NULL, dissect_s_supervisor_target_unid},
2231 {0x39, false, 28, -1, "Output Connection Point Owners", cip_dissector_func, NULL, dissect_s_supervisor_output_connection_point_owners},
2232 {0x39, false, 29, -1, "Proposed TUNID", cip_dissector_func, NULL, dissect_s_supervisor_proposed_tunid},
2233 {0x39, false, 99, -1, "Subclass", cip_uint, &hf_cip_ssupervisor_instance_subclass, NULL},
2235 /* Safety Validator */
2236 {0x3A, true, 8, -1, "Safety Connection Fault Count", cip_uint, &hf_cip_svalidator_sconn_fault_count, NULL},
2237 {0x3A, false, 1, 0, "Safety Validator State", cip_usint, &hf_cip_svalidator_state, NULL},
2238 {0x3A, false, 2, 1, "Safety Validator Type", cip_dissector_func, NULL, dissect_s_validator_type},
2239 {0x3A, false, 3, 2, "Ping Interval EPI Multiplier", cip_uint, &hf_cip_svalidator_ping_epi, NULL},
2240 {0x3A, false, 4, 3, "Time Coord Msg Min Multiplier", cip_dissector_func, NULL, dissect_s_validator_time_coord_msg_min_mult},
2241 {0x3A, false, 5, 4, "Network Time Expectation Multiplier", cip_dissector_func, NULL, dissect_s_validator_network_time_multiplier},
2242 {0x3A, false, 6, 5, "Timeout Multiplier", cip_dissector_func, NULL, dissect_s_validator_timeout_multiplier},
2243 {0x3A, false, 7, 6, "Max Consumer Number", cip_usint, &hf_cip_svalidator_max_consumer_num, NULL},
2244 {0x3A, false, 8, 7, "Data Connection Instance", cip_uint, &hf_cip_svalidator_data_conn_inst, NULL},
2245 {0x3A, false, 9, 8, "Coordination Connection Instance", cip_dissector_func, NULL, dissect_s_validator_coordination_conn_inst},
2246 {0x3A, false, 10, 9, "Correction Connection Instance", cip_uint, &hf_cip_svalidator_correction_conn_inst, NULL},
2247 {0x3A, false, 11, 10, "CCO Binding", cip_uint, &hf_cip_svalidator_cco_binding, NULL},
2248 {0x3A, false, 12, 11, "Max Data Age", cip_uint, &hf_cip_svalidator_max_data_age, NULL},
2249 {0x3A, false, 13, 12, "Application Data Path", cip_dissector_func, NULL, dissect_s_validator_app_data_path},
2250 /* Note: Get Attributes All can't get to "Error Code", because dissect_s_validator_app_data_path() will use
2251 all remaining bytes. */
2252 {0x3A, false, 14, 13, "Error Code", cip_uint, &hf_cip_svalidator_error_code, NULL},
2253 {0x3A, false, 15, -1, "Producer/Consumer Fault Counters", cip_dissector_func, NULL, dissect_s_validator_prod_cons_fault_count},
2255 /* SERCOS III Link */
2256 {0x4C, false, 1, -1, "Safety Network Number", cip_dissector_func, NULL, dissect_sercosiii_safety_network_number},
2257 {0x4C, false, 2, -1, "Communication Cycle Time", cip_udint, &hf_cip_sercosiii_link_communication_cycle_time, NULL},
2258 {0x4C, false, 3, -1, "Interface Status", cip_word, &hf_cip_sercosiii_link_interface_status, NULL},
2259 {0x4C, false, 4, -1, "Error counter MST-P/S", cip_uint, &hf_cip_sercosiii_link_error_count_mstps, NULL},
2260 {0x4C, false, 5, -1, "Error counter Port1 and Port2", cip_dissector_func, NULL, dissect_sercosiii_link_error_count_p1p2},
2261 {0x4C, false, 6, -1, "SERCOS address", cip_uint, &hf_cip_sercosiii_link_sercos_address, NULL},
2265 * Protocol initialization
2269 * Function name: proto_register_cipsafety
2271 * Purpose: Register the protocol with Wireshark, a script will add this protocol
2272 * to the list of protocols during the build process. This function is where the
2273 * header fields and subtree identifiers are registered.
2275 * Returns: void
2277 void
2278 proto_register_cipsafety(void)
2280 /* This is a list of header fields that can be used in the dissection or
2281 * to use in a filter expression */
2282 static hf_register_info hf[] =
2284 { &hf_cip_reqrsp,
2285 { "Request/Response", "cip.rr",
2286 FT_UINT8, BASE_HEX, VALS(cip_sc_rr), CIP_SC_RESPONSE_MASK, "Request or Response message", HFILL }
2288 { &hf_cip_data,
2289 { "Data", "cip.data",
2290 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2293 { &hf_cipsafety_data,
2294 { "Data", "cipsafety.data",
2295 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2297 { &hf_cipsafety_mode_byte,
2298 { "Mode Byte", "cipsafety.mode_byte",
2299 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2301 { &hf_cipsafety_mode_byte_ping_count,
2302 { "Ping Count", "cipsafety.mode_byte.ping_count",
2303 FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL }
2305 { &hf_cipsafety_mode_byte_not_tbd,
2306 { "Not TBD Bit", "cipsafety.mode_byte.not_tbd",
2307 FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }
2309 { &hf_cipsafety_mode_byte_tbd_2_copy,
2310 { "TBD 2 Bit Copy", "cipsafety.mode_byte.tbd_2_copy",
2311 FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
2313 { &hf_cipsafety_mode_byte_not_run_idle,
2314 { "Not Run/Idle", "cipsafety.mode_byte.not_run_idle",
2315 FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }
2317 { &hf_cipsafety_mode_byte_tbd,
2318 { "TBD Bit", "cipsafety.mode_byte.tbd",
2319 FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }
2321 { &hf_cipsafety_mode_byte_tbd_2_bit,
2322 { "TBD 2 Bit", "cipsafety.mode_byte.tbd_2_bit",
2323 FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
2325 { &hf_cipsafety_mode_byte_run_idle,
2326 { "Run/Idle", "cipsafety.mode_byte.run_idle",
2327 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2329 { &hf_cipsafety_crc_s1,
2330 { "CRC S1", "cipsafety.crc_s1",
2331 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2333 { &hf_cipsafety_crc_s1_status,
2334 { "CRC S1 Status", "cipsafety.crc_s1.status",
2335 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2337 { &hf_cipsafety_crc_s2,
2338 { "CRC S2", "cipsafety.crc_s2",
2339 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2341 { &hf_cipsafety_crc_s2_status,
2342 { "CRC S2 Status", "cipsafety.crc_s2.status",
2343 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2345 { &hf_cipsafety_crc_s3,
2346 { "CRC S3", "cipsafety.crc_s3",
2347 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2349 { &hf_cipsafety_crc_s3_status,
2350 { "CRC S3 Status", "cipsafety.crc_s3.status",
2351 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2353 { &hf_cipsafety_complement_crc_s3,
2354 { "Complement CRC S3", "cipsafety.complement_crc_s3",
2355 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2357 { &hf_cipsafety_complement_crc_s3_status,
2358 { "Complement CRC S3 Status", "cipsafety.complement_crc_s3.status",
2359 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2361 { &hf_cipsafety_timestamp,
2362 { "Timestamp", "cipsafety.timestamp",
2363 FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }
2365 { &hf_cipsafety_ack_byte,
2366 { "ACK Byte", "cipsafety.ack_byte",
2367 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2369 { &hf_cipsafety_ack_byte_ping_count_reply,
2370 { "Ping Count Reply", "cipsafety.ack_byte.ping_count_reply",
2371 FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }
2373 { &hf_cipsafety_ack_byte_reserved1,
2374 { "Reserved", "cipsafety.ack_byte.reserved1",
2375 FT_UINT8, BASE_HEX, NULL, 0x04, NULL, HFILL }
2377 { &hf_cipsafety_ack_byte_ping_response,
2378 { "Ping Response", "cipsafety.ack_byte.ping_response",
2379 FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
2381 { &hf_cipsafety_ack_byte_reserved2,
2382 { "Reserved", "cipsafety.ack_byte.reserved2",
2383 FT_UINT8, BASE_HEX, NULL, 0x70, NULL, HFILL }
2385 { &hf_cipsafety_ack_byte_parity_even,
2386 { "Parity Even", "cipsafety.ack_byte.parity_even",
2387 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2389 { &hf_cipsafety_ack_byte2,
2390 { "ACK Byte 2", "cipsafety.ack_byte2",
2391 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2393 { &hf_cipsafety_consumer_time_value,
2394 { "Consumer Time Value", "cipsafety.consumer_time_value",
2395 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2397 { &hf_cipsafety_mcast_byte,
2398 { "MCAST Byte", "cipsafety.mcast_byte",
2399 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2401 { &hf_cipsafety_mcast_byte_consumer_num,
2402 { "Consumer #", "cipsafety.mcast_byte.consumer_num",
2403 FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
2405 { &hf_cipsafety_mcast_byte_reserved1,
2406 { "Reserved", "cipsafety.mcast_byte.reserved1",
2407 FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
2409 { &hf_cipsafety_mcast_byte_mai,
2410 { "Multicast Active/Idle", "cipsafety.mcast_byte.active_idle",
2411 FT_BOOLEAN, 8, TFS(&cip_safety_vals_active_idle), 0x20, NULL, HFILL }
2413 { &hf_cipsafety_mcast_byte_reserved2,
2414 { "Reserved", "cipsafety.mcast_byte.reserved2",
2415 FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL }
2417 { &hf_cipsafety_mcast_byte_parity_even,
2418 { "Parity Even", "cipsafety.mcast_byte.parity_even",
2419 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2421 { &hf_cipsafety_mcast_byte2,
2422 { "MCAST Byte 2", "cipsafety.mcast_byte2",
2423 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2425 { &hf_cipsafety_time_correction,
2426 { "Time Correction", "cipsafety.time_correction",
2427 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2429 { &hf_cipsafety_crc_s5_0,
2430 { "CRC S5_0", "cipsafety.crc_s5_0",
2431 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2433 { &hf_cipsafety_crc_s5_1,
2434 { "CRC S5_1", "cipsafety.crc_s5_1",
2435 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2437 { &hf_cipsafety_crc_s5_2,
2438 { "CRC S5_2", "cipsafety.crc_s5_2",
2439 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2441 { &hf_cipsafety_crc_s5_status,
2442 { "CRC S5 Status", "cipsafety.crc_s5.status",
2443 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL }
2445 { &hf_cipsafety_complement_data,
2446 { "Complement Data", "cipsafety.complement_data",
2447 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2450 { &hf_cip_safety_message_encoding,
2451 { "Safety Message Encoding", "cipsafety.message_encoding",
2452 FT_UINT32, BASE_DEC, VALS(safety_message_encoding_vals), 0, NULL, HFILL }
2455 { &hf_cip_sercosiii_link_snn,
2456 { "Data", "cipsafety.sercosiii_link.snn",
2457 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2459 { &hf_cip_sercosiii_link_communication_cycle_time,
2460 { "Communication Cycle Time", "cipsafety.sercosiii_link.communication_cycle_time",
2461 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
2463 { &hf_cip_sercosiii_link_interface_status,
2464 { "Interface Status", "cipsafety.sercosiii_link.interface_status",
2465 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }
2467 { &hf_cip_sercosiii_link_error_count_mstps,
2468 { "Error Counter MST-P/S", "cipsafety.sercosiii_link.error_count_mstps",
2469 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2471 { &hf_cip_sercosiii_link_error_count_p1,
2472 { "Error Count Port 1", "cipsafety.sercosiii_link.error_count_p1",
2473 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2475 { &hf_cip_sercosiii_link_error_count_p2,
2476 { "Error Count Port 2", "cipsafety.sercosiii_link.error_count_p2",
2477 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2479 { &hf_cip_sercosiii_link_sercos_address,
2480 { "SERCOS Address", "cipsafety.sercosiii_link.sercos_address",
2481 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2485 static hf_register_info hf_ssupervisor[] = {
2486 { &hf_cip_ssupervisor_sc,
2487 { "Service", "cipsafety.ssupervisor.sc",
2488 FT_UINT8, BASE_HEX, VALS(cip_sc_vals_ssupervisor), CIP_SC_MASK, NULL, HFILL }
2490 { &hf_cip_ssupervisor_recover_data,
2491 { "Data", "cipsafety.ssupervisor.recover.data",
2492 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2494 { &hf_cip_ssupervisor_perform_diag_data,
2495 { "Data", "cipsafety.ssupervisor.perform_diag.data",
2496 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2498 { &hf_cip_ssupervisor_configure_request_password,
2499 { "Password", "cipsafety.ssupervisor.configure_request.password",
2500 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2502 { &hf_cip_ssupervisor_configure_request_tunid,
2503 { "Target UNID", "cipsafety.ssupervisor.configure_request.tunid",
2504 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2506 { &hf_cip_ssupervisor_configure_request_tunid_snn_timestamp,
2507 { "TUNID SNN Timestamp", "cipsafety.ssupervisor.configure_request.tunid.snn.timestamp",
2508 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2510 { &hf_cip_ssupervisor_configure_request_tunid_snn_date,
2511 { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_request.tunid.snn.date",
2512 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2514 { &hf_cip_ssupervisor_configure_request_tunid_snn_time,
2515 { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_request.tunid.snn.time",
2516 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2518 { &hf_cip_ssupervisor_configure_request_tunid_nodeid,
2519 { "Node ID", "cipsafety.ssupervisor.configure_request.tunid.nodeid",
2520 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2522 { &hf_cip_ssupervisor_configure_request_ounid,
2523 { "Originator UNID", "cipsafety.ssupervisor.configure_request.ounid",
2524 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2526 { &hf_cip_ssupervisor_configure_request_ounid_snn_timestamp,
2527 { "OUNID SNN Timestamp", "cipsafety.ssupervisor.configure_request.ounid.snn.timestamp",
2528 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2530 { &hf_cip_ssupervisor_configure_request_ounid_snn_date,
2531 { "OUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_request.ounid.snn.date",
2532 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2534 { &hf_cip_ssupervisor_configure_request_ounid_snn_time,
2535 { "OUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_request.ounid.snn.time",
2536 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2538 { &hf_cip_ssupervisor_configure_request_ounid_nodeid,
2539 { "Node ID", "cipsafety.ssupervisor.configure_request.ounid.nodeid",
2540 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2542 { &hf_cip_ssupervisor_validate_configuration_sccrc,
2543 { "SCCRC", "cipsafety.ssupervisor.validate_configuration.sccrc",
2544 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2546 { &hf_cip_ssupervisor_validate_configuration_scts_timestamp,
2547 { "SCTS (Timestamp)", "cipsafety.ssupervisor.validate_configuration.scts.timestamp",
2548 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2550 { &hf_cip_ssupervisor_validate_configuration_scts_date,
2551 { "SCTS (Manual) Date", "cipsafety.ssupervisor.validate_configuration.scts.date",
2552 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2554 { &hf_cip_ssupervisor_validate_configuration_scts_time,
2555 { "SCTS (Manual) Time", "cipsafety.ssupervisor.validate_configuration.scts.time",
2556 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2558 { &hf_cip_ssupervisor_validate_configuration_ext_error,
2559 { "Extended Error", "cipsafety.ssupervisor.validate_configuration.ext_error",
2560 FT_UINT16, BASE_DEC, VALS(cip_ssupervisor_validate_configuration_ext_error_vals), 0, NULL, HFILL }
2562 { &hf_cip_ssupervisor_set_password_current_password,
2563 { "Current Password", "cipsafety.ssupervisor.set_password.current_pass",
2564 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2566 { &hf_cip_ssupervisor_set_password_new_password,
2567 { "New Password", "cipsafety.ssupervisor.set_password.new_pass",
2568 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2570 { &hf_cip_ssupervisor_configure_lock_value,
2571 { "Lock Value", "cipsafety.ssupervisor.configure_lock.lock",
2572 FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
2574 { &hf_cip_ssupervisor_configure_lock_password,
2575 { "Password", "cipsafety.ssupervisor.configure_lock.password",
2576 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2578 { &hf_cip_ssupervisor_configure_lock_tunid,
2579 { "Target UNID", "cipsafety.ssupervisor.configure_lock.tunid",
2580 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2582 { &hf_cip_ssupervisor_configure_lock_tunid_snn_timestamp,
2583 { "TUNID SNN Timestamp", "cipsafety.ssupervisor.configure_lock.tunid.snn.timestamp",
2584 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2586 { &hf_cip_ssupervisor_configure_lock_tunid_snn_date,
2587 { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.configure_lock.tunid.snn.date",
2588 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2590 { &hf_cip_ssupervisor_configure_lock_tunid_snn_time,
2591 { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.configure_lock.tunid.snn.time",
2592 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2594 { &hf_cip_ssupervisor_configure_lock_tunid_nodeid,
2595 { "Node ID", "cipsafety.ssupervisor.configure_lock.tunid.nodeid",
2596 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2598 { &hf_cip_ssupervisor_mode_change_value,
2599 { "Value", "cipsafety.ssupervisor.mode_change.value",
2600 FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_change_mode_vals), 0, NULL, HFILL }
2602 { &hf_cip_ssupervisor_mode_change_password,
2603 { "Password", "cipsafety.ssupervisor.mode_change.password",
2604 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2606 { &hf_cip_ssupervisor_reset_type,
2607 { "Reset Type", "cipsafety.ssupervisor.reset.type",
2608 FT_UINT8, BASE_DEC, VALS(cip_reset_type_vals), 0, NULL, HFILL }
2610 { &hf_cip_ssupervisor_reset_password,
2611 { "Password", "cipsafety.ssupervisor.reset.password",
2612 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2614 { &hf_cip_ssupervisor_reset_tunid,
2615 { "Target UNID", "cipsafety.ssupervisor.reset.tunid",
2616 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2618 { &hf_cip_ssupervisor_reset_tunid_tunid_snn_timestamp,
2619 { "TUNID SNN Timestamp", "cipsafety.ssupervisor.reset.tunid.snn.timestamp",
2620 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2622 { &hf_cip_ssupervisor_reset_tunid_tunid_snn_date,
2623 { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.reset.tunid.snn.date",
2624 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2626 { &hf_cip_ssupervisor_reset_tunid_tunid_snn_time,
2627 { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.reset.tunid.snn.time",
2628 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2630 { &hf_cip_ssupervisor_reset_tunid_nodeid,
2631 { "Node ID", "cipsafety.ssupervisor.reset.tunid.nodeid",
2632 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2634 { &hf_cip_ssupervisor_reset_attr_bitmap,
2635 { "Attribute Bit Map", "cipsafety.ssupervisor.reset.attr_bitmap",
2636 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2638 { &hf_cip_ssupervisor_reset_attr_bitmap_macid,
2639 { "Preserve MacID", "cipsafety.ssupervisor.reset.attr_bitmap.macid",
2640 FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }
2642 { &hf_cip_ssupervisor_reset_attr_bitmap_baudrate,
2643 { "Preserve Baud Rate", "cipsafety.ssupervisor.reset.attr_bitmap.baudrate",
2644 FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }
2646 { &hf_cip_ssupervisor_reset_attr_bitmap_tunid,
2647 { "Preserve TUNID", "cipsafety.ssupervisor.reset.attr_bitmap.tunid",
2648 FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }
2650 { &hf_cip_ssupervisor_reset_attr_bitmap_password,
2651 { "Preserve Password", "cipsafety.ssupervisor.reset.attr_bitmap.password",
2652 FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
2654 { &hf_cip_ssupervisor_reset_attr_bitmap_cfunid,
2655 { "Preserve CFUNID", "cipsafety.ssupervisor.reset.attr_bitmap.cfunid",
2656 FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }
2658 { &hf_cip_ssupervisor_reset_attr_bitmap_ocpunid,
2659 { "Preserve OPCUNID", "cipsafety.ssupervisor.reset.attr_bitmap.ocpunid",
2660 FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }
2662 { &hf_cip_ssupervisor_reset_attr_bitmap_reserved,
2663 { "Reserved", "cipsafety.ssupervisor.reset.attr_bitmap.reserved",
2664 FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
2666 { &hf_cip_ssupervisor_reset_attr_bitmap_extended,
2667 { "Use Extended Map", "cipsafety.ssupervisor.reset.attr_bitmap.extended",
2668 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
2670 { &hf_cip_ssupervisor_reset_password_data_size,
2671 { "Data Size", "cipsafety.ssupervisor.reset_password.data_size",
2672 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2674 { &hf_cip_ssupervisor_reset_password_data,
2675 { "Password Data", "cipsafety.ssupervisor.reset_password.password_data",
2676 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2678 { &hf_cip_ssupervisor_propose_tunid_tunid,
2679 { "Target UNID", "cipsafety.ssupervisor.propose_tunid.tunid",
2680 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2682 { &hf_cip_ssupervisor_propose_tunid_tunid_snn_timestamp,
2683 { "TUNID SNN Timestamp", "cipsafety.ssupervisor.propose_tunid.tunid.snn.timestamp",
2684 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2686 { &hf_cip_ssupervisor_propose_tunid_tunid_snn_date,
2687 { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.propose_tunid.tunid.snn.date",
2688 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2690 { &hf_cip_ssupervisor_propose_tunid_tunid_snn_time,
2691 { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.propose_tunid.tunid.snn.time",
2692 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2694 { &hf_cip_ssupervisor_propose_tunid_tunid_nodeid,
2695 { "Node ID", "cipsafety.ssupervisor.propose_tunid.tunid.nodeid",
2696 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2698 { &hf_cip_ssupervisor_apply_tunid_tunid,
2699 { "Target UNID", "cipsafety.ssupervisor.apply_tunid.tunid",
2700 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2702 { &hf_cip_ssupervisor_apply_tunid_tunid_snn_timestamp,
2703 { "TUNID SNN Timestamp", "cipsafety.ssupervisor.apply_tunid.tunid.snn.timestamp",
2704 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2706 { &hf_cip_ssupervisor_apply_tunid_tunid_snn_date,
2707 { "TUNID SNN (Manual) Date", "cipsafety.ssupervisor.apply_tunid.tunid.snn.date",
2708 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2710 { &hf_cip_ssupervisor_apply_tunid_tunid_snn_time,
2711 { "TUNID SNN (Manual) Time", "cipsafety.ssupervisor.apply_tunid.tunid.snn.time",
2712 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2714 { &hf_cip_ssupervisor_apply_tunid_tunid_nodeid,
2715 { "Node ID", "cipsafety.ssupervisor.apply_tunid.tunid.nodeid",
2716 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2718 { &hf_cip_ssupervisor_class_subclass,
2719 { "Subclass", "cipsafety.ssupervisor.class_subclass",
2720 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2722 { &hf_cip_ssupervisor_num_attr,
2723 { "Number of Attributes", "cipsafety.ssupervisor.num_attr",
2724 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2726 { &hf_cip_ssupervisor_attr_list,
2727 { "Attributes List Item", "cipsafety.ssupervisor.attr_item",
2728 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2730 { &hf_cip_ssupervisor_manufacture_name,
2731 { "Manufacturer Name", "cipsafety.ssupervisor.manufacture_name",
2732 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2734 { &hf_cip_ssupervisor_manufacture_model_number,
2735 { "Manufacturer Model Number", "cipsafety.ssupervisor.manufacture_model_number",
2736 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2738 { &hf_cip_ssupervisor_sw_rev_level,
2739 { "Software Revision Level", "cipsafety.ssupervisor.sw_rev_level",
2740 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2742 { &hf_cip_ssupervisor_hw_rev_level,
2743 { "Hardware Revision Level", "cipsafety.ssupervisor.hw_rev_level",
2744 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2746 { &hf_cip_ssupervisor_manufacture_serial_number,
2747 { "Manufacturer Serial Number", "cipsafety.ssupervisor.manufacture_serial_number",
2748 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2750 { &hf_cip_ssupervisor_device_config,
2751 { "Device Configuration", "cipsafety.ssupervisor.device_config",
2752 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
2754 { &hf_cip_ssupervisor_device_status,
2755 { "Device Status", "cipsafety.ssupervisor.device_status",
2756 FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_device_status_type_vals), 0, NULL, HFILL }
2758 { &hf_cip_ssupervisor_exception_status,
2759 { "Exception Status", "cipsafety.ssupervisor.exception_status",
2760 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2762 { &hf_cip_ssupervisor_exception_detail_ced_size,
2763 { "Common Exception Detail Size", "cipsafety.ssupervisor.exception_detail.ced.size",
2764 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2766 { &hf_cip_ssupervisor_exception_detail_ced_detail,
2767 { "Common Exception Detail Data", "cipsafety.ssupervisor.exception_detail.ced.detail",
2768 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2770 { &hf_cip_ssupervisor_exception_detail_ded_size,
2771 { "Device Exception Detail Size", "cipsafety.ssupervisor.exception_detail.ded.size",
2772 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2774 { &hf_cip_ssupervisor_exception_detail_ded_detail,
2775 { "Device Exception Detail Data", "cipsafety.ssupervisor.exception_detail.ded.detail",
2776 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2778 { &hf_cip_ssupervisor_exception_detail_med_size,
2779 { "Manufacturer Exception Detail Size", "cipsafety.ssupervisor.exception_detail.med.size",
2780 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2782 { &hf_cip_ssupervisor_exception_detail_med_detail,
2783 { "Manufacturer Exception Detail Data", "cipsafety.ssupervisor.exception_detail.med.detail",
2784 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2786 { &hf_cip_ssupervisor_alarm_enable,
2787 { "Exception Detail Alarm", "cipsafety.ssupervisor.alarm_enable",
2788 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
2790 { &hf_cip_ssupervisor_warning_enable,
2791 { "Exception Detail Warning", "cipsafety.ssupervisor.warning_enable",
2792 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
2794 { &hf_cip_ssupervisor_time,
2795 { "Time", "cipsafety.ssupervisor.time",
2796 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2798 { &hf_cip_ssupervisor_clock_power_cycle_behavior,
2799 { "Clock Power Cycle Behavior", "cipsafety.ssupervisor.clock_power_cycle_behavior",
2800 FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_clock_power_cycle_type_vals), 0, NULL, HFILL }
2802 { &hf_cip_ssupervisor_last_maintenance_date,
2803 { "Last Maintenance Date", "cipsafety.ssupervisor.last_maintenance_date",
2804 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2806 { &hf_cip_ssupervisor_next_scheduled_maintenance_date,
2807 { "Next Scheduled Maintenance Date", "cipsafety.ssupervisor.next_scheduled_maintenance_date",
2808 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2810 { &hf_cip_ssupervisor_scheduled_maintenance_expiration_timer,
2811 { "Scheduled Maintenance Expiration Timer", "cipsafety.ssupervisor.scheduled_maintenance_expiration_timer",
2812 FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }
2814 { &hf_cip_ssupervisor_scheduled_maintenance_expiration_warning_enable,
2815 { "Scheduled Maintenance Expiration Warning Enable", "cipsafety.ssupervisor.scheduled_maintenance_expiration_warning",
2816 FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }
2818 { &hf_cip_ssupervisor_run_hours,
2819 { "Run Hours", "cipsafety.ssupervisor.run_hours",
2820 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
2822 { &hf_cip_ssupervisor_configuration_lock,
2823 { "Configuration Lock", "cipsafety.ssupervisor.configuration_lock",
2824 FT_UINT8, BASE_DEC, VALS(cip_ssupervisor_lock_vals), 0, NULL, HFILL }
2826 { &hf_cip_ssupervisor_configuration_unid_snn_timestamp,
2827 { "Configuration UNID SNN Timestamp", "cipsafety.ssupervisor.configuration_unid.snn.timestamp",
2828 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2830 { &hf_cip_ssupervisor_configuration_unid_snn_date,
2831 { "Configuration UNID SNN (Manual) Date", "cipsafety.ssupervisor.configuration_unid.snn.date",
2832 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2834 { &hf_cip_ssupervisor_configuration_unid_snn_time,
2835 { "Configuration UNID SNN (Manual) Time", "cipsafety.ssupervisor.configuration_unid.snn.time",
2836 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2838 { &hf_cip_ssupervisor_configuration_unid_nodeid,
2839 { "Configuration UNID Node ID", "cipsafety.ssupervisor.configuration_unid.nodeid",
2840 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2842 { &hf_cip_ssupervisor_safety_configuration_id_snn_timestamp,
2843 { "Safety Configuration ID SNN Timestamp", "cipsafety.ssupervisor.safety_configuration_id.snn.timestamp",
2844 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2846 { &hf_cip_ssupervisor_safety_configuration_id_snn_date,
2847 { "Safety Configuration ID SNN (Manual) Date", "cipsafety.ssupervisor.safety_configuration_id.snn.date",
2848 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2850 { &hf_cip_ssupervisor_safety_configuration_id_snn_time,
2851 { "Safety Configuration ID SNN (Manual) Time", "cipsafety.ssupervisor.safety_configuration_id.snn.time",
2852 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2854 { &hf_cip_ssupervisor_safety_configuration_id_sccrc,
2855 { "Safety Configuration ID SCCRC", "cipsafety.ssupervisor.safety_configuration_id.sccrc",
2856 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2858 { &hf_cip_ssupervisor_target_unid_snn_timestamp,
2859 { "Target UNID SNN Timestamp", "cipsafety.ssupervisor.target_unid.snn.timestamp",
2860 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2862 { &hf_cip_ssupervisor_target_unid_snn_date,
2863 { "Target UNID SNN (Manual) Date", "cipsafety.ssupervisor.target_unid.snn.date",
2864 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2866 { &hf_cip_ssupervisor_target_unid_snn_time,
2867 { "Target UNID SNN (Manual) Time", "cipsafety.ssupervisor.target_unid.snn.time",
2868 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2870 { &hf_cip_ssupervisor_target_unid_nodeid,
2871 { "Target UNID Node ID", "cipsafety.ssupervisor.target_unid.nodeid",
2872 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2874 { &hf_cip_ssupervisor_cp_owners_num_entries,
2875 { "Number of Array Entries", "cipsafety.ssupervisor.cp_owners.num_entries",
2876 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2878 { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_timestamp,
2879 { "OCPUNID SNN Timestamp", "cipsafety.ssupervisor.cp_owners.snn.timestamp",
2880 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2882 { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_date,
2883 { "OCPUNID SNN (Manual) Date", "cipsafety.ssupervisor.cp_owners.snn.date",
2884 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2886 { &hf_cip_ssupervisor_output_cp_owners_ocpunid_snn_time,
2887 { "OCPUNID SNN (Manual) Time", "cipsafety.ssupervisor.cp_owners.snn.time",
2888 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2890 { &hf_cip_ssupervisor_output_cp_owners_ocpunid_nodeid,
2891 { "OCPUNID Node ID", "cipsafety.ssupervisor.cp_owners.ocpunid.nodeid",
2892 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2894 { &hf_cip_ssupervisor_cp_owners_app_path_size,
2895 { "EPATH Size", "cipsafety.ssupervisor.cp_owners.epath_size",
2896 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2898 { &hf_cip_ssupervisor_proposed_tunid_snn_timestamp,
2899 { "Proposed TUNID SNN Timestamp", "cipsafety.ssupervisor.proposed_tunid.snn.timestamp",
2900 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }
2902 { &hf_cip_ssupervisor_proposed_tunid_snn_date,
2903 { "Proposed TUNID SNN (Manual) Date", "cipsafety.ssupervisor.proposed_tunid.snn.date",
2904 FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }
2906 { &hf_cip_ssupervisor_proposed_tunid_snn_time,
2907 { "Proposed TUNID SNN (Manual) Time", "cipsafety.ssupervisor.proposed_tunid.snn.time",
2908 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2910 { &hf_cip_ssupervisor_proposed_tunid_nodeid,
2911 { "Proposed TUNID Node ID", "cipsafety.ssupervisor.proposed_tunid.nodeid",
2912 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2914 { &hf_cip_ssupervisor_instance_subclass,
2915 { "Subclass", "cipsafety.ssupervisor.instance_subclass",
2916 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2920 static hf_register_info hf_svalidator[] = {
2921 { &hf_cip_svalidator_sc,
2922 { "Service", "cipsafety.svalidator.sc",
2923 FT_UINT8, BASE_HEX, VALS(cip_sc_vals_svalidator), CIP_SC_MASK, NULL, HFILL }
2926 { &hf_cip_svalidator_sconn_fault_count,
2927 { "Safety Connection Fault Count", "cipsafety.svalidator.sconn_fault_count",
2928 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2930 { &hf_cip_svalidator_state,
2931 { "Safety Validator State", "cipsafety.svalidator.state",
2932 FT_UINT8, BASE_DEC, VALS(cip_svalidator_state_vals), 0, NULL, HFILL }
2934 { &hf_cip_svalidator_type,
2935 { "Safety Validator Type", "cipsafety.svalidator.type",
2936 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
2938 { &hf_cip_svalidator_type_pc,
2939 { "Producer/Consumer", "cipsafety.svalidator.type.pc",
2940 FT_UINT8, BASE_HEX, VALS(cip_svalidator_type_pc_vals), 0x80, NULL, HFILL }
2942 { &hf_cip_svalidator_type_conn_type,
2943 { "Safety Connection Type", "cipsafety.svalidator.type.conn_type",
2944 FT_UINT8, BASE_DEC, VALS(cip_svalidator_type_conn_type_vals), 0x7F, NULL, HFILL }
2946 { &hf_cip_svalidator_ping_epi,
2947 { "Ping Interval EPI Multiplier", "cipsafety.svalidator.ping_epi",
2948 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2950 { &hf_cip_svalidator_time_coord_msg_min_mult_size,
2951 { "Time Coord Msg Min Multiplier Array Size", "cipsafety.svalidator.time_coord_msg_min_mult.size",
2952 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2954 { &hf_cip_svalidator_time_coord_msg_min_mult_item,
2955 { "Time Coord Msg Min Multiplier", "cipsafety.svalidator.time_coord_msg_min_mult.item",
2956 FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }
2958 { &hf_cip_svalidator_network_time_multiplier_size,
2959 { "Network Time Expectation Multiplier Array Size", "cipsafety.svalidator.network_time_multiplier.size",
2960 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2962 { &hf_cip_svalidator_network_time_multiplier_item,
2963 { "Network Time Expectation Multiplier", "cipsafety.svalidator.network_time_multiplier.item",
2964 FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }
2966 { &hf_cip_svalidator_timeout_multiplier_size,
2967 { "Timeout Multiplier Array Size", "cipsafety.svalidator.timeout_multiplier.size",
2968 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2970 { &hf_cip_svalidator_timeout_multiplier_item,
2971 { "Timeout Multiplier", "cipsafety.svalidator.timeout_multiplier.item",
2972 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2974 { &hf_cip_svalidator_max_consumer_num,
2975 { "Max Consumer Number", "cipsafety.svalidator.max_consumer_num",
2976 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(safety_max_consumer_numbers), 0, NULL, HFILL }
2978 { &hf_cip_svalidator_data_conn_inst,
2979 { "Data Connection Instance", "cipsafety.svalidator.data_conn_inst",
2980 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2982 { &hf_cip_svalidator_coordination_conn_inst_size,
2983 { "Coordination Connection Instance Size", "cipsafety.svalidator.coordination_conn_inst.size",
2984 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2986 { &hf_cip_svalidator_coordination_conn_inst_item,
2987 { "Coordination Connection Instance Item", "cipsafety.svalidator.coordination_conn_inst.item",
2988 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2990 { &hf_cip_svalidator_correction_conn_inst,
2991 { "Correction Connection Instance", "cipsafety.svalidator.correction_conn_inst",
2992 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2994 { &hf_cip_svalidator_cco_binding,
2995 { "CCO Binding", "cipsafety.svalidator.cco_binding",
2996 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2998 { &hf_cip_svalidator_max_data_age,
2999 { "Max Data Age", "cipsafety.svalidator.max_data_age",
3000 FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }
3002 { &hf_cip_svalidator_error_code,
3003 { "Error Code", "cipsafety.svalidator.error_code",
3004 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
3006 { &hf_cip_svalidator_prod_cons_fault_count_size,
3007 { "Producer/Consumer Counter Array Size", "cipsafety.svalidator.prod_cons_fault_count.size",
3008 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
3010 { &hf_cip_svalidator_prod_cons_fault_count_item,
3011 { "Producer/Consumer Fault Counter", "cipsafety.svalidator.prod_cons_fault_count.item",
3012 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
3016 static int *ett[] = {
3017 &ett_cip_safety,
3018 &ett_path,
3019 &ett_cipsafety_mode_byte,
3020 &ett_cipsafety_ack_byte,
3021 &ett_cipsafety_mcast_byte
3024 static int *ett_ssupervisor[] = {
3025 &ett_cip_class_s_supervisor,
3026 &ett_ssupervisor_rrsc,
3027 &ett_ssupervisor_cmd_data,
3028 &ett_ssupervisor_propose_tunid,
3029 &ett_ssupervisor_propose_tunid_snn,
3030 &ett_ssupervisor_configure_request_tunid,
3031 &ett_ssupervisor_configure_request_tunid_snn,
3032 &ett_ssupervisor_configure_request_ounid,
3033 &ett_ssupervisor_configure_request_ounid_snn,
3034 &ett_ssupervisor_configure_lock_tunid,
3035 &ett_ssupervisor_configure_lock_tunid_snn,
3036 &ett_ssupervisor_reset_tunid,
3037 &ett_ssupervisor_reset_tunid_snn,
3038 &ett_ssupervisor_apply_tunid,
3039 &ett_ssupervisor_apply_tunid_snn,
3040 &ett_exception_detail_common,
3041 &ett_exception_detail_device,
3042 &ett_exception_detail_manufacturer,
3043 &ett_ssupervisor_configuration_unid,
3044 &ett_ssupervisor_configuration_unid_snn,
3045 &ett_ssupervisor_target_unid,
3046 &ett_ssupervisor_target_unid_snn,
3047 &ett_ssupervisor_output_cp_owners,
3048 &ett_ssupervisor_output_cp_owners_ocpunid,
3049 &ett_ssupervisor_output_cp_owners_ocpunid_snn,
3050 &ett_ssupervisor_proposed_tunid,
3051 &ett_ssupervisor_proposed_tunid_snn,
3052 &ett_cip_ssupervisor_reset_attr_bitmap
3055 static int *ett_svalidator[] = {
3056 &ett_cip_class_s_validator,
3057 &ett_svalidator_rrsc,
3058 &ett_svalidator_cmd_data,
3059 &ett_svalidator_type
3062 static ei_register_info ei[] = {
3063 { &ei_cipsafety_tbd_not_complemented, { "cipsafety.tbd_not_complemented", PI_PROTOCOL, PI_ERROR, "TBD bit not complemented", EXPFILL }},
3064 { &ei_cipsafety_tbd2_not_copied, { "cipsafety.tbd2_not_copied", PI_PROTOCOL, PI_ERROR, "TBD2 bit not copied", EXPFILL }},
3065 { &ei_cipsafety_run_idle_not_complemented, { "cipsafety.run_idle_not_complemented", PI_PROTOCOL, PI_ERROR, "Run/Idle bit not complemented", EXPFILL }},
3066 { &ei_mal_io, { "cipsafety.malformed.io", PI_MALFORMED, PI_ERROR, "Malformed CIP Safety I/O packet", EXPFILL }},
3067 { &ei_mal_sercosiii_link_error_count_p1p2, { "cipsafety.malformed.sercosiii_link.error_count_p1p2", PI_MALFORMED, PI_ERROR, "Malformed SERCOS III Attribute 5", EXPFILL }},
3068 { &ei_cipsafety_not_complement_data, { "cipsafety.not_complement_data", PI_PROTOCOL, PI_ERROR, "Data not complemented", EXPFILL }},
3069 { &ei_cipsafety_crc_s1, { "cipsafety.crc_s1.incorrect", PI_PROTOCOL, PI_ERROR, "CRC-S1 incorrect", EXPFILL }},
3070 { &ei_cipsafety_crc_s2, { "cipsafety.crc_s2.incorrect", PI_PROTOCOL, PI_ERROR, "CRC-S2 incorrect", EXPFILL }},
3071 { &ei_cipsafety_crc_s3, { "cipsafety.crc_s3.incorrect", PI_PROTOCOL, PI_ERROR, "CRC-S3 incorrect", EXPFILL }},
3072 { &ei_cipsafety_complement_crc_s3, { "cipsafety.complement_crc_s3.incorrect", PI_PROTOCOL, PI_ERROR, "Complement CRC-S3 incorrect", EXPFILL }},
3073 { &ei_cipsafety_crc_s5, { "cipsafety.crc_s5.incorrect", PI_PROTOCOL, PI_ERROR, "CRC-S5 incorrect", EXPFILL }},
3076 static ei_register_info ei_ssupervisor[] = {
3077 { &ei_mal_ssupervisor_exception_detail_ced, { "cipsafety.ssupervisor.malformed.exception_detail.ced", PI_MALFORMED, PI_ERROR,
3078 "Malformed Safety Supervisor Exception Detail (Common Exception Detail)", EXPFILL }},
3079 { &ei_mal_ssupervisor_exception_detail_ded, { "cipsafety.ssupervisor.malformed.exception_detail.ded", PI_MALFORMED, PI_ERROR,
3080 "Malformed Safety Supervisor Exception Detail (Device Exception Detail)", EXPFILL }},
3081 { &ei_mal_ssupervisor_exception_detail_med, { "cipsafety.ssupervisor.malformed.exception_detail.med", PI_MALFORMED, PI_ERROR,
3082 "Malformed Safety Supervisor Exception Detail (Manufacturer Exception Detail)", EXPFILL }},
3083 { &ei_mal_ssupervisor_configuration_unid, { "cipsafety.ssupervisor.malformed.configuration_unid", PI_MALFORMED, PI_ERROR,
3084 "Malformed Safety Supervisor Configuration UNID", EXPFILL }},
3085 { &ei_mal_ssupervisor_safety_configuration_id, { "cipsafety.ssupervisor.malformed.safety_configuration_id", PI_MALFORMED, PI_ERROR,
3086 "Malformed Safety Supervisor Safety Configuration Identifier", EXPFILL }},
3087 { &ei_mal_ssupervisor_target_unid, { "cipsafety.ssupervisor.malformed.target_unid", PI_MALFORMED, PI_ERROR,
3088 "Malformed Safety Supervisor Target UNID", EXPFILL }},
3089 { &ei_mal_ssupervisor_cp_owners, { "cipsafety.ssupervisor.malformed.cp_owners", PI_MALFORMED, PI_ERROR,
3090 "Malformed Safety Supervisor Output Connection Point Owners", EXPFILL }},
3091 { &ei_mal_ssupervisor_cp_owners_entry, { "cipsafety.ssupervisor.malformed.cp_owners.entry", PI_MALFORMED, PI_ERROR,
3092 "Malformed Safety Supervisor Output Connection Point Owners (UNID)", EXPFILL }},
3093 { &ei_mal_ssupervisor_cp_owners_app_path_size, { "cipsafety.ssupervisor.malformed.cp_owners.app_path_size", PI_MALFORMED, PI_ERROR,
3094 "Malformed Safety Supervisor Output Connection Point Owners (EPATH)", EXPFILL }},
3095 { &ei_mal_ssupervisor_proposed_tunid, { "cipsafety.ssupervisor.malformed.proposed_tunid", PI_MALFORMED, PI_ERROR,
3096 "Malformed Safety Supervisor Proposed TUNID", EXPFILL }},
3097 { &ei_info_ssupervisor_tunid_cancel, { "cipsafety.ssupervisor.info.cancel_propose_apply", PI_PROTOCOL, PI_WARN,
3098 "Cancel Proposed/Apply Operation", EXPFILL } },
3101 static ei_register_info ei_svalidator[] = {
3102 { &ei_mal_svalidator_type, { "cipsafety.ssupervisor.malformed.svalidator.type", PI_MALFORMED, PI_ERROR,
3103 "Malformed Safety Validator Type", EXPFILL }},
3104 { &ei_mal_svalidator_time_coord_msg_min_mult, { "cipsafety.ssupervisor.malformed.svalidator.time_coord_msg_min_mult", PI_MALFORMED, PI_ERROR,
3105 "Malformed Safety Validator Time Coord Msg Min Multiplier", EXPFILL }},
3106 { &ei_mal_svalidator_network_time_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.network_time_multiplier", PI_MALFORMED, PI_ERROR,
3107 "Malformed Safety Validator Network Time Expectation Multiplier", EXPFILL }},
3108 { &ei_mal_svalidator_timeout_multiplier, { "cipsafety.ssupervisor.malformed.svalidator.timeout_multiplier", PI_MALFORMED, PI_ERROR,
3109 "Malformed Safety Validator Timeout Multiplier", EXPFILL }},
3110 { &ei_mal_svalidator_coordination_conn_inst, { "cipsafety.ssupervisor.malformed.svalidator.coordination_conn_inst", PI_MALFORMED, PI_ERROR,
3111 "Malformed Safety Validator Coordination Connection Instance", EXPFILL }},
3112 { &ei_mal_svalidator_prod_cons_fault_count, { "cipsafety.ssupervisor.malformed.svalidator.prod_cons_fault_count", PI_MALFORMED, PI_ERROR,
3113 "Malformed Safety Validator Produce/Consume Fault Counters", EXPFILL }},
3116 expert_module_t* expert_cip_safety;
3117 expert_module_t* expert_cip_class_s_supervisor;
3118 expert_module_t* expert_cip_class_s_validator;
3120 /* Create a CIP Safety protocol handle */
3121 proto_cipsafety = proto_register_protocol("Common Industrial Protocol, Safety", "CIP Safety", "cipsafety");
3122 proto_register_field_array(proto_cipsafety, hf, array_length(hf));
3123 proto_register_subtree_array(ett, array_length(ett));
3124 expert_cip_safety = expert_register_protocol(proto_cipsafety);
3125 expert_register_field_array(expert_cip_safety, ei, array_length(ei));
3127 cipsafety_handle = register_dissector( "cipsafety", dissect_cipsafety, proto_cipsafety);
3129 // Register different protocols for "Decode As".
3130 proto_cipsafety_base_data = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Base - Data",
3131 "CIP Safety - Base - Data",
3132 "cipsafety_bd",
3133 proto_cipsafety,
3134 FT_PROTOCOL);
3135 cipsafety_base_data_handle = register_dissector("cipsafety_bd", dissect_cipsafety_base_data, proto_cipsafety_base_data);
3137 proto_cipsafety_extended_data = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Extended - Data",
3138 "CIP Safety - Extended - Data",
3139 "cipsafety_ed",
3140 proto_cipsafety,
3141 FT_PROTOCOL);
3142 cipsafety_extended_data_handle = register_dissector("cipsafety_ed", dissect_cipsafety_extended_data, proto_cipsafety_extended_data);
3144 proto_cipsafety_base_time_coord = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Base - Time Coordination",
3145 "CIP Safety - Base - Time Coordination",
3146 "cipsafety_bt",
3147 proto_cipsafety,
3148 FT_PROTOCOL);
3149 cipsafety_base_time_coord_handle = register_dissector("cipsafety_bt", dissect_cipsafety_base_time_coord, proto_cipsafety_base_time_coord);
3151 proto_cipsafety_extended_time_coord = proto_register_protocol_in_name_only("Common Industrial Protocol, Safety - Extended - Time Coordination",
3152 "CIP Safety - Extended - Time Coordination",
3153 "cipsafety_et",
3154 proto_cipsafety,
3155 FT_PROTOCOL);
3156 cipsafety_extended_time_coord_handle = register_dissector("cipsafety_et", dissect_cipsafety_extended_time_coord, proto_cipsafety_extended_time_coord);
3159 /* Register CIP Safety objects */
3160 proto_cip_class_s_supervisor = proto_register_protocol("CIP Safety Supervisor",
3161 "CIPSSupervisor", "cipssupervisor");
3162 cip_class_s_supervisor_handle = register_dissector("cipssupervisor", dissect_cip_class_s_supervisor, proto_cip_class_s_supervisor );
3163 proto_register_field_array(proto_cip_class_s_supervisor, hf_ssupervisor, array_length(hf_ssupervisor));
3164 proto_register_subtree_array(ett_ssupervisor, array_length(ett_ssupervisor));
3165 expert_cip_class_s_supervisor = expert_register_protocol(proto_cip_class_s_supervisor);
3166 expert_register_field_array(expert_cip_class_s_supervisor, ei_ssupervisor, array_length(ei_ssupervisor));
3168 proto_cip_class_s_validator = proto_register_protocol("CIP Safety Validator",
3169 "CIPSValidator", "cipsvalidator");
3170 cip_class_s_validator_handle = register_dissector("cipsvalidator", dissect_cip_class_s_validator, proto_cip_class_s_validator );
3171 proto_register_field_array(proto_cip_class_s_validator, hf_svalidator, array_length(hf_svalidator));
3172 proto_register_subtree_array(ett_svalidator, array_length(ett_svalidator));
3173 expert_cip_class_s_validator = expert_register_protocol(proto_cip_class_s_validator);
3174 expert_register_field_array(expert_cip_class_s_validator, ei_svalidator, array_length(ei_svalidator));
3178 * Function name: proto_reg_handoff_cipsafety
3180 * Purpose: This function will setup the automatic dissection of the CIP Safety datagram,
3181 * it is called by Wireshark when the protocol is registered
3183 * Returns: void
3185 void
3186 proto_reg_handoff_cipsafety(void)
3188 /* Register dissector handle for Safety Supervisor */
3189 dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_SUPERVISOR, cip_class_s_supervisor_handle );
3191 /* Register dissector handle for Safety Validator */
3192 dissector_add_uint( "cip.class.iface", CI_CLS_SAFETY_VALIDATOR, cip_class_s_validator_handle );
3193 heur_dissector_add("cip.sc", dissect_class_svalidator_heur, "CIP Safety Validator", "s_validator_cip", proto_cip_class_s_validator, HEURISTIC_ENABLE);
3195 /* Register dissector for I/O data handling */
3196 dissector_add_for_decode_as("cip.io", cipsafety_base_data_handle );
3197 dissector_add_for_decode_as("cip.io", cipsafety_extended_data_handle );
3198 dissector_add_for_decode_as("cip.io", cipsafety_base_time_coord_handle );
3199 dissector_add_for_decode_as("cip.io", cipsafety_extended_time_coord_handle );
3201 proto_cip = proto_get_id_by_filter_name( "cip" );
3202 subdissector_class_table = find_dissector_table("cip.class.iface");
3207 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3209 * Local variables:
3210 * c-basic-offset: 3
3211 * tab-width: 8
3212 * indent-tabs-mode: nil
3213 * End:
3215 * ex: set shiftwidth=3 tabstop=8 expandtab:
3216 * :indentSize=3:tabSize=8:noTabs=true: