Coverage Report

Created: 2026-06-30 07:22

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