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