Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cip.c
blobc702a4f4cdce6d930f02620e78f8065128f290dc
1 /* packet-cip.c
2 * Routines for Common Industrial Protocol (CIP) dissection
3 * CIP Home: www.odva.org
5 * This dissector includes items from:
6 * CIP Volume 1: Common Industrial Protocol, Edition 3.34
7 * CIP Volume 5: CIP Safety, Edition 2.25
8 * CIP Volume 7A: Integration of Modbus Devices into the CIP Architecture, Edition 1.9
9 * CIP Volume 8: CIP Security, Edition 1.11
11 * Copyright 2004
12 * Magnus Hansson <mah@hms.se>
13 * Joakim Wiberg <jow@hms.se>
15 * Added support for Connection Configuration Object
16 * ryan wamsley * Copyright 2007
18 * Object dependend services based on IOI
19 * Jan Bartels, Siempelkamp Maschinen- und Anlagenbau GmbH & Co. KG
20 * Copyright 2007
22 * Improved support for CoCo, CM, MB objects
23 * Heuristic object support for common services
24 * Michael Mann * Copyright 2011
26 * Added support for PCCC Objects
27 * Jared Rittle - Cisco Talos
28 * Copyright 2017
30 * Wireshark - Network traffic analyzer
31 * By Gerald Combs <gerald@wireshark.org>
32 * Copyright 1998 Gerald Combs
34 * SPDX-License-Identifier: GPL-2.0-or-later
37 // There are multiple different ways to add functionality based on CIP class-specific behavior:
38 // 1. Dissector Table "cip.io.iface" - Use this when Class 0/1 I/O needs different parsing based on
39 // the CIP Class in the Forward Open
40 // 2. Dissector Table "cip.connection.class" - Use this when Class 2/3 data needs different parsing
41 // based on the CIP Class in the Forward Open
42 // 3. Dissector Table "cip.class.iface" - Use this when a CIP Class has significantly different
43 // behavior that would be best handled through a separate dissector
44 // 4. Dissector Table "cip.data_segment.iface" - Unknown. This may be removed in the future
45 // 5. attribute_info_t: Use this to add handling for an attribute, using a 3 tuple key (Class, Instance, Attribute)
46 // See 'cip_attribute_vals' for an example.
47 // 6. cip_service_info_t: Use this to add handling for a service, using a 2 tuple key (Class, Service)
48 // See 'cip_obj_spec_service_table' for an example.
50 #include "config.h"
52 #include <epan/packet.h>
53 #include <epan/expert.h>
54 #include <epan/prefs.h>
55 #include <epan/proto_data.h>
56 #include <epan/wmem_scopes.h>
57 #include <epan/tfs.h>
58 #include <epan/unit_strings.h>
59 #include <wsutil/array.h>
60 #include "packet-cip.h"
61 #include "packet-cipmotion.h"
62 #include "packet-cipsafety.h"
63 #include "packet-mbtcp.h"
65 void proto_register_cip(void);
66 void proto_reg_handoff_cip(void);
68 typedef struct mr_mult_req_info {
69 uint8_t service;
70 int num_services;
71 cip_req_info_t *requests;
72 } mr_mult_req_info_t;
74 static dissector_handle_t cip_handle;
75 static dissector_handle_t cip_class_generic_handle;
76 static dissector_handle_t cip_class_cm_handle;
77 static dissector_handle_t cip_class_pccc_handle;
78 static dissector_handle_t cip_class_mb_handle;
79 static dissector_handle_t modbus_handle;
80 static dissector_handle_t cip_class_cco_handle;
81 static heur_dissector_list_t heur_subdissector_service;
83 static bool cip_enhanced_info_column = true;
85 /* Initialize the protocol and registered fields */
86 static int proto_cip;
87 static int proto_cip_class_generic;
88 static int proto_cip_class_cm;
89 static int proto_cip_class_pccc;
90 static int proto_cip_class_mb;
91 static int proto_cip_class_cco;
92 static int proto_enip;
93 static int proto_modbus;
95 int hf_attr_class_revision;
96 int hf_attr_class_max_instance;
97 int hf_attr_class_num_instance;
98 int hf_attr_class_opt_attr_num;
99 int hf_attr_class_attr_num;
100 int hf_attr_class_opt_service_num;
101 int hf_attr_class_service_code;
102 int hf_attr_class_num_class_attr;
103 int hf_attr_class_num_inst_attr;
104 static int hf_cip_data;
105 static int hf_cip_service;
106 static int hf_cip_service_code;
107 static int hf_cip_reqrsp;
108 static int hf_cip_epath;
109 static int hf_cip_genstat;
110 static int hf_cip_addstat_size;
111 static int hf_cip_add_stat;
112 static int hf_cip_request_path_size;
114 static int hf_cip_cm_sc;
115 static int hf_cip_cm_genstat;
116 static int hf_cip_cm_addstat_size;
117 static int hf_cip_cm_add_status;
118 static int hf_cip_cm_ext_status;
119 static int hf_cip_cm_priority;
120 static int hf_cip_cm_tick_time;
121 static int hf_cip_cm_timeout_tick;
122 static int hf_cip_cm_timeout;
123 static int hf_cip_cm_ot_connid;
124 static int hf_cip_cm_to_connid;
125 static int hf_cip_connid;
126 static int hf_cip_cm_conn_serial_num;
127 static int hf_cip_cm_orig_serial_num;
128 static int hf_cip_cm_vendor;
129 static int hf_cip_cm_timeout_multiplier;
130 static int hf_cip_cm_ot_rpi;
131 static int hf_cip_cm_ot_timeout;
132 static int hf_cip_cm_ot_net_params32;
133 static int hf_cip_cm_ot_net_params16;
134 static int hf_cip_cm_to_rpi;
135 static int hf_cip_cm_to_timeout;
137 static int hf_cip_safety_nte_ms;
139 static int hf_cip_cm_to_net_params32;
140 static int hf_cip_cm_to_net_params16;
141 static int hf_cip_cm_transport_type_trigger;
142 static int hf_cip_cm_conn_path_size;
143 static int hf_cip_cm_ot_api;
144 static int hf_cip_cm_to_api;
145 static int hf_cip_cm_app_reply_size;
146 static int hf_cip_cm_app_reply_data;
147 static int hf_cip_cm_consumer_number;
148 static int hf_cip_cm_targ_vendor_id;
149 static int hf_cip_cm_targ_dev_serial_num;
150 static int hf_cip_cm_targ_conn_serial_num;
151 static int hf_cip_cm_initial_timestamp;
152 static int hf_cip_cm_initial_rollover;
153 static int hf_cip_cm_remain_path_size;
154 static int hf_cip_cm_msg_req_size;
155 static int hf_cip_cm_route_path_size;
156 static int hf_cip_cm_fwo_con_size;
157 static int hf_cip_cm_lfwo_con_size;
158 static int hf_cip_cm_fwo_fixed_var;
159 static int hf_cip_cm_lfwo_fixed_var;
160 static int hf_cip_cm_fwo_prio;
161 static int hf_cip_cm_lfwo_prio;
162 static int hf_cip_cm_fwo_typ;
163 static int hf_cip_cm_lfwo_typ;
164 static int hf_cip_cm_fwo_own;
165 static int hf_cip_cm_lfwo_own;
166 static int hf_cip_cm_fwo_dir;
167 static int hf_cip_cm_fwo_trigg;
168 static int hf_cip_cm_fwo_class;
169 static int hf_cip_cm_gco_conn;
170 static int hf_cip_cm_gco_coo_conn;
171 static int hf_cip_cm_gco_roo_conn;
172 static int hf_cip_cm_gco_last_action;
173 static int hf_cip_cm_ext112_ot_rpi_type;
174 static int hf_cip_cm_ext112_to_rpi_type;
175 static int hf_cip_cm_ext112_ot_rpi;
176 static int hf_cip_cm_ext112_to_rpi;
177 static int hf_cip_cm_ext126_size;
178 static int hf_cip_cm_ext127_size;
179 static int hf_cip_cm_ext128_size;
181 static int hf_cip_pccc_sc;
182 static int hf_cip_pccc_req_id_len;
183 static int hf_cip_pccc_cip_vend_id;
184 static int hf_cip_pccc_cip_serial_num;
185 static int hf_cip_pccc_cmd_code;
186 static int hf_cip_pccc_sts_code;
187 static int hf_cip_pccc_ext_sts_code;
188 static int hf_cip_pccc_tns_code;
189 static int hf_cip_pccc_fnc_code_06;
190 static int hf_cip_pccc_fnc_code_07;
191 static int hf_cip_pccc_fnc_code_0f;
192 static int hf_cip_pccc_byte_size;
193 static int hf_cip_pccc_file_num;
194 static int hf_cip_pccc_file_type;
195 static int hf_cip_pccc_element_num;
196 static int hf_cip_pccc_subelement_num;
197 #if 0
198 static int hf_cip_pccc_cpu_mode_3a;
199 #endif
200 static int hf_cip_pccc_cpu_mode_80;
201 static int hf_cip_pccc_resp_code;
202 static int hf_cip_pccc_execute_multi_count;
203 static int hf_cip_pccc_execute_multi_len;
204 static int hf_cip_pccc_execute_multi_fnc;
205 static int hf_cip_pccc_data;
207 static int hf_cip_mb_sc;
208 static int hf_cip_mb_read_coils_start_addr;
209 static int hf_cip_mb_read_coils_num_coils;
210 static int hf_cip_mb_read_coils_data;
211 static int hf_cip_mb_read_discrete_inputs_start_addr;
212 static int hf_cip_mb_read_discrete_inputs_num_inputs;
213 static int hf_cip_mb_read_discrete_inputs_data;
214 static int hf_cip_mb_read_holding_register_start_addr;
215 static int hf_cip_mb_read_holding_register_num_registers;
216 static int hf_cip_mb_read_holding_register_data;
217 static int hf_cip_mb_read_input_register_start_addr;
218 static int hf_cip_mb_read_input_register_num_registers;
219 static int hf_cip_mb_read_input_register_data;
220 static int hf_cip_mb_write_coils_start_addr;
221 static int hf_cip_mb_write_coils_outputs_forced;
222 static int hf_cip_mb_write_coils_num_coils;
223 static int hf_cip_mb_write_coils_data;
224 static int hf_cip_mb_write_registers_start_addr;
225 static int hf_cip_mb_write_registers_outputs_forced;
226 static int hf_cip_mb_write_registers_num_registers;
227 static int hf_cip_mb_write_registers_data;
228 static int hf_cip_mb_data;
230 static int hf_cip_cco_con_type;
231 static int hf_cip_cco_ot_rtf;
232 static int hf_cip_cco_to_rtf;
233 static int hf_cip_cco_sc;
234 static int hf_cip_cco_format_number;
235 static int hf_cip_cco_edit_signature;
236 static int hf_cip_cco_con_flags;
237 static int hf_cip_cco_tdi_vendor;
238 static int hf_cip_cco_tdi_devtype;
239 static int hf_cip_cco_tdi_prodcode;
240 static int hf_cip_cco_tdi_compatibility;
241 static int hf_cip_cco_tdi_comp_bit;
242 static int hf_cip_cco_tdi_majorrev;
243 static int hf_cip_cco_tdi_minorrev;
244 static int hf_cip_cco_pdi_vendor;
245 static int hf_cip_cco_pdi_devtype;
246 static int hf_cip_cco_pdi_prodcode;
247 static int hf_cip_cco_pdi_compatibility;
248 static int hf_cip_cco_pdi_comp_bit;
249 static int hf_cip_cco_pdi_majorrev;
250 static int hf_cip_cco_pdi_minorrev;
251 static int hf_cip_cco_cs_data_index;
252 static int hf_cip_cco_ot_rpi;
253 static int hf_cip_cco_to_rpi;
254 static int hf_cip_cco_ot_net_param16;
255 static int hf_cip_cco_to_net_param16;
256 static int hf_cip_cco_fwo_own;
257 static int hf_cip_cco_fwo_typ;
258 static int hf_cip_cco_fwo_prio;
259 static int hf_cip_cco_fwo_fixed_var;
260 static int hf_cip_cco_fwo_con_size;
261 static int hf_cip_cco_ot_net_param32;
262 static int hf_cip_cco_to_net_param32;
263 static int hf_cip_cco_lfwo_own;
264 static int hf_cip_cco_lfwo_typ;
265 static int hf_cip_cco_lfwo_prio;
266 static int hf_cip_cco_lfwo_fixed_var;
267 static int hf_cip_cco_lfwo_con_size;
268 static int hf_cip_cco_conn_path_size;
269 static int hf_cip_cco_proxy_config_size;
270 static int hf_cip_cco_target_config_size;
271 static int hf_cip_cco_iomap_format_number;
272 static int hf_cip_cco_iomap_size;
273 static int hf_cip_cco_connection_disable;
274 static int hf_cip_cco_net_conn_param_attr;
275 static int hf_cip_cco_timeout_multiplier;
276 static int hf_cip_cco_transport_type_trigger;
277 static int hf_cip_cco_fwo_dir;
278 static int hf_cip_cco_fwo_trigger;
279 static int hf_cip_cco_fwo_class;
280 static int hf_cip_cco_proxy_config_data;
281 static int hf_cip_cco_target_config_data;
282 static int hf_cip_cco_iomap_attribute;
283 static int hf_cip_cco_safety;
284 static int hf_cip_cco_change_type;
285 static int hf_cip_cco_connection_name;
286 static int hf_cip_cco_ext_status;
288 static int hf_cip_path_segment;
289 static int hf_cip_path_segment_type;
290 static int hf_cip_port_ex_link_addr;
291 static int hf_cip_port;
292 static int hf_cip_port_extended;
293 static int hf_cip_link_address_size;
294 static int hf_cip_link_address_byte;
295 static int hf_cip_link_address_string;
296 static int hf_cip_logical_seg_type;
297 static int hf_cip_logical_seg_format;
298 static int hf_cip_class8;
299 static int hf_cip_class16;
300 static int hf_cip_class32;
301 static int hf_cip_instance8;
302 static int hf_cip_instance16;
303 static int hf_cip_instance32;
304 static int hf_cip_member8;
305 static int hf_cip_member16;
306 static int hf_cip_member32;
307 static int hf_cip_attribute8;
308 static int hf_cip_attribute16;
309 static int hf_cip_attribute32;
310 static int hf_cip_conpoint8;
311 static int hf_cip_conpoint16;
312 static int hf_cip_conpoint32;
313 static int hf_cip_serviceid8;
314 static int hf_cip_ekey_format;
315 static int hf_cip_ekey_vendor;
316 static int hf_cip_ekey_devtype;
317 static int hf_cip_ekey_prodcode;
318 static int hf_cip_ekey_compatibility;
319 static int hf_cip_ekey_comp_bit;
320 static int hf_cip_ekey_majorrev;
321 static int hf_cip_ekey_minorrev;
322 static int hf_cip_ekey_serial_number;
323 static int hf_cip_ext_logical8;
324 static int hf_cip_ext_logical16;
325 static int hf_cip_ext_logical32;
326 static int hf_cip_ext_logical_type;
327 static int hf_cip_data_seg_type;
328 static int hf_cip_data_seg_size_simple;
329 static int hf_cip_data_seg_size_extended;
330 static int hf_cip_data_seg_item;
331 static int hf_cip_symbol;
332 static int hf_cip_symbol_size;
333 static int hf_cip_symbol_ascii;
334 static int hf_cip_symbol_extended_format;
335 static int hf_cip_symbol_numeric_format;
336 static int hf_cip_symbol_double_size;
337 static int hf_cip_symbol_triple_size;
338 static int hf_cip_numeric_usint;
339 static int hf_cip_numeric_uint;
340 static int hf_cip_numeric_udint;
341 static int hf_cip_network_seg_type;
342 static int hf_cip_seg_schedule;
343 static int hf_cip_seg_fixed_tag;
344 static int hf_cip_seg_prod_inhibit_time;
345 static int hf_cip_seg_prod_inhibit_time_us;
346 static int hf_cip_seg_network_size;
347 static int hf_cip_seg_network_subtype;
348 static int hf_cip_seg_safety_format;
349 static int hf_cip_seg_safety_reserved;
350 static int hf_cip_seg_safety_configuration_crc;
351 static int hf_cip_seg_safety_configuration_timestamp;
352 static int hf_cip_seg_safety_configuration_date;
353 static int hf_cip_seg_safety_configuration_time;
354 static int hf_cip_seg_safety_time_correction_epi;
355 static int hf_cip_seg_safety_time_correction_net_params;
356 static int hf_cip_seg_safety_time_correction_own;
357 static int hf_cip_seg_safety_time_correction_typ;
358 static int hf_cip_seg_safety_time_correction_prio;
359 static int hf_cip_seg_safety_time_correction_fixed_var;
360 static int hf_cip_seg_safety_time_correction_con_size;
361 static int hf_cip_seg_safety_tunid;
362 static int hf_cip_seg_safety_tunid_snn_timestamp;
363 static int hf_cip_seg_safety_tunid_snn_date;
364 static int hf_cip_seg_safety_tunid_snn_time;
365 static int hf_cip_seg_safety_tunid_nodeid;
366 static int hf_cip_seg_safety_ounid;
367 static int hf_cip_seg_safety_ounid_snn_timestamp;
368 static int hf_cip_seg_safety_ounid_snn_date;
369 static int hf_cip_seg_safety_ounid_snn_time;
370 static int hf_cip_seg_safety_ounid_nodeid;
371 static int hf_cip_seg_safety_ping_epi_multiplier;
372 static int hf_cip_seg_safety_time_coord_msg_min_multiplier;
373 static int hf_cip_seg_safety_network_time_expected_multiplier;
374 static int hf_cip_seg_safety_timeout_multiplier;
375 static int hf_cip_seg_safety_max_consumer_number;
376 static int hf_cip_seg_safety_conn_param_crc;
377 static int hf_cip_seg_safety_time_correction_conn_id;
378 static int hf_cip_seg_safety_max_fault_number;
379 static int hf_cip_seg_safety_init_timestamp;
380 static int hf_cip_seg_safety_init_rollover;
381 static int hf_cip_seg_safety_data;
382 static int hf_cip_class_max_inst32;
383 static int hf_cip_class_num_inst32;
384 static int hf_cip_reserved8;
385 static int hf_cip_reserved24;
386 static int hf_cip_pad8;
388 static int hf_cip_sc_get_attr_list_attr_count;
389 static int hf_cip_sc_get_attr_list_attr_status;
390 static int hf_cip_sc_set_attr_list_attr_count;
391 static int hf_cip_sc_set_attr_list_attr_status;
392 static int hf_cip_sc_reset_param;
393 static int hf_cip_sc_create_instance;
394 static int hf_cip_sc_mult_serv_pack_num_services;
395 static int hf_cip_sc_mult_serv_pack_offset;
396 static int hf_cip_find_next_object_max_instance;
397 static int hf_cip_find_next_object_num_instances;
398 static int hf_cip_find_next_object_instance_item;
399 static int hf_cip_sc_group_sync_is_sync;
401 /* Parsed Attributes */
402 static int hf_id_vendor_id;
403 static int hf_id_device_type;
404 static int hf_id_product_code;
405 static int hf_id_major_rev;
406 static int hf_id_minor_rev;
407 static int hf_id_status;
408 static int hf_id_serial_number;
409 static int hf_id_product_name;
410 static int hf_id_state;
411 static int hf_id_config_value;
412 static int hf_id_heartbeat;
413 static int hf_id_status_owned;
414 static int hf_id_status_conf;
415 static int hf_id_status_extended1;
416 static int hf_id_status_minor_fault_rec;
417 static int hf_id_status_minor_fault_unrec;
418 static int hf_id_status_major_fault_rec;
419 static int hf_id_status_major_fault_unrec;
420 static int hf_id_status_extended2;
421 static int hf_msg_rout_num_classes;
422 static int hf_msg_rout_classes;
423 static int hf_msg_rout_num_available;
424 static int hf_msg_rout_num_active;
425 static int hf_msg_rout_active_connections;
426 static int hf_conn_mgr_open_requests;
427 static int hf_conn_mgr_open_format_rejects;
428 static int hf_conn_mgr_open_resource_rejects;
429 static int hf_conn_mgr_other_open_rejects;
430 static int hf_conn_mgr_close_requests;
431 static int hf_conn_close_format_requests;
432 static int hf_conn_mgr_close_other_requests;
433 static int hf_conn_mgr_conn_timouts;
434 static int hf_conn_mgr_num_conn_entries;
435 static int hf_conn_mgr_num_conn_entries_bytes;
436 static int hf_conn_mgr_conn_open_bits;
437 static int hf_conn_mgr_cpu_utilization;
438 static int hf_conn_mgr_max_buff_size;
439 static int hf_conn_mgr_buff_size_remaining;
440 static int hf_stringi_number_char;
441 static int hf_stringi_language_char;
442 static int hf_stringi_char_string_struct;
443 static int hf_stringi_char_set;
444 static int hf_stringi_international_string;
445 static int hf_file_filename;
446 static int hf_time_sync_ptp_enable;
447 static int hf_time_sync_is_synchronized;
448 static int hf_time_sync_sys_time_micro;
449 static int hf_time_sync_sys_time_nano;
450 static int hf_time_sync_offset_from_master;
451 static int hf_time_sync_max_offset_from_master;
452 static int hf_time_sync_mean_path_delay_to_master;
453 static int hf_time_sync_gm_clock_clock_id;
454 static int hf_time_sync_gm_clock_clock_class;
455 static int hf_time_sync_gm_clock_time_accuracy;
456 static int hf_time_sync_gm_clock_offset_scaled_log_variance;
457 static int hf_time_sync_gm_clock_current_utc_offset;
458 static int hf_time_sync_gm_clock_time_property_flags;
459 static int hf_time_sync_gm_clock_time_property_flags_leap61;
460 static int hf_time_sync_gm_clock_time_property_flags_leap59;
461 static int hf_time_sync_gm_clock_time_property_flags_current_utc_valid;
462 static int hf_time_sync_gm_clock_time_property_flags_ptp_timescale;
463 static int hf_time_sync_gm_clock_time_property_flags_time_traceable;
464 static int hf_time_sync_gm_clock_time_property_flags_freq_traceable;
465 static int hf_time_sync_gm_clock_time_source;
466 static int hf_time_sync_gm_clock_priority1;
467 static int hf_time_sync_gm_clock_priority2;
468 static int hf_time_sync_parent_clock_clock_id;
469 static int hf_time_sync_parent_clock_port_number;
470 static int hf_time_sync_parent_clock_observed_offset_scaled_log_variance;
471 static int hf_time_sync_parent_clock_observed_phase_change_rate;
472 static int hf_time_sync_local_clock_clock_id;
473 static int hf_time_sync_local_clock_clock_class;
474 static int hf_time_sync_local_clock_time_accuracy;
475 static int hf_time_sync_local_clock_offset_scaled_log_variance;
476 static int hf_time_sync_local_clock_current_utc_offset;
477 static int hf_time_sync_local_clock_time_property_flags;
478 static int hf_time_sync_local_clock_time_property_flags_leap61;
479 static int hf_time_sync_local_clock_time_property_flags_leap59;
480 static int hf_time_sync_local_clock_time_property_flags_current_utc_valid;
481 static int hf_time_sync_local_clock_time_property_flags_ptp_timescale;
482 static int hf_time_sync_local_clock_time_property_flags_time_traceable;
483 static int hf_time_sync_local_clock_time_property_flags_freq_traceable;
484 static int hf_time_sync_local_clock_time_source;
485 static int hf_time_sync_num_ports;
486 static int hf_time_sync_port_state_info_num_ports;
487 static int hf_time_sync_port_state_info_port_num;
488 static int hf_time_sync_port_state_info_port_state;
489 static int hf_time_sync_port_enable_cfg_num_ports;
490 static int hf_time_sync_port_enable_cfg_port_num;
491 static int hf_time_sync_port_enable_cfg_port_enable;
492 static int hf_time_sync_port_log_announce_num_ports;
493 static int hf_time_sync_port_log_announce_port_num;
494 static int hf_time_sync_port_log_announce_interval;
495 static int hf_time_sync_port_log_sync_num_ports;
496 static int hf_time_sync_port_log_sync_port_num;
497 static int hf_time_sync_port_log_sync_port_log_sync_interval;
498 static int hf_time_sync_priority1;
499 static int hf_time_sync_priority2;
500 static int hf_time_sync_domain_number;
501 static int hf_time_sync_clock_type;
502 static int hf_time_sync_clock_type_ordinary;
503 static int hf_time_sync_clock_type_boundary;
504 static int hf_time_sync_clock_type_end_to_end;
505 static int hf_time_sync_clock_type_management;
506 static int hf_time_sync_clock_type_slave_only;
507 static int hf_time_sync_manufacture_id_oui;
508 static int hf_time_sync_manufacture_id_reserved;
509 static int hf_time_sync_prod_desc_size;
510 static int hf_time_sync_prod_desc_str;
511 static int hf_time_sync_revision_data_size;
512 static int hf_time_sync_revision_data_str;
513 static int hf_time_sync_user_desc_size;
514 static int hf_time_sync_user_desc_str;
515 static int hf_time_sync_port_profile_id_info_num_ports;
516 static int hf_time_sync_port_profile_id_info_port_num;
517 static int hf_time_sync_port_profile_id_info_profile_id;
518 static int hf_time_sync_port_phys_addr_info_num_ports;
519 static int hf_time_sync_port_phys_addr_info_port_num;
520 static int hf_time_sync_port_phys_addr_info_phys_proto;
521 static int hf_time_sync_port_phys_addr_info_addr_size;
522 static int hf_time_sync_port_phys_addr_info_phys_addr;
523 static int hf_time_sync_port_proto_addr_info_num_ports;
524 static int hf_time_sync_port_proto_addr_info_port_num;
525 static int hf_time_sync_port_proto_addr_info_network_proto;
526 static int hf_time_sync_port_proto_addr_info_addr_size;
527 static int hf_time_sync_port_proto_addr_info_port_proto_addr;
528 static int hf_time_sync_steps_removed;
529 static int hf_time_sync_sys_time_and_offset_time;
530 static int hf_time_sync_sys_time_and_offset_offset;
531 static int hf_port_entry_port;
532 static int hf_port_type;
533 static int hf_port_number;
534 static int hf_port_min_node_num;
535 static int hf_port_max_node_num;
536 static int hf_port_name;
537 static int hf_port_num_comm_object_entries;
538 static int hf_path_len_usint;
539 static int hf_path_len_uint;
541 static int hf_32bitheader;
542 static int hf_32bitheader_roo;
543 static int hf_32bitheader_coo;
544 static int hf_32bitheader_run_idle;
546 static int hf_cip_connection;
547 static int hf_cip_fwd_open_in;
548 static int hf_cip_fwd_close_in;
550 /* Initialize the subtree pointers */
551 static int ett_cip;
552 static int ett_cip_class_generic;
553 static int ett_cip_class_cm;
554 static int ett_cip_class_pccc;
555 static int ett_cip_class_mb;
556 static int ett_cip_class_cco;
558 static int ett_path;
559 static int ett_path_seg;
560 static int ett_mcsc;
561 static int ett_cia_path;
562 static int ett_data_seg;
563 static int ett_port_path;
564 static int ett_network_seg;
565 static int ett_network_seg_safety;
566 static int ett_network_seg_safety_time_correction_net_params;
567 static int ett_cip_seg_safety_tunid;
568 static int ett_cip_seg_safety_tunid_snn;
569 static int ett_cip_seg_safety_ounid;
570 static int ett_cip_seg_safety_ounid_snn;
572 static int ett_rrsc;
573 static int ett_status_item;
574 static int ett_add_status_item;
575 static int ett_cmd_data;
577 static int ett_cip_get_attributes_all_item;
578 static int ett_cip_get_attribute_list;
579 static int ett_cip_get_attribute_list_item;
580 static int ett_cip_set_attribute_list;
581 static int ett_cip_set_attribute_list_item;
582 static int ett_cip_mult_service_packet;
583 static int ett_cip_msp_offset;
585 static int ett_cm_rrsc;
586 static int ett_cm_ncp;
587 static int ett_cm_mes_req;
588 static int ett_cm_cmd_data;
589 static int ett_cm_ttt;
590 static int ett_cm_add_status_item;
591 static int ett_cip_cm_pid;
592 static int ett_cip_cm_safety;
594 static int ett_pccc_rrsc;
595 static int ett_pccc_req_id;
596 static int ett_pccc_cmd_data;
598 static int ett_mb_rrsc;
599 static int ett_mb_cmd_data;
601 static int ett_cco_iomap;
602 static int ett_cco_con_status;
603 static int ett_cco_con_flag;
604 static int ett_cco_tdi;
605 static int ett_cco_pdi;
606 static int ett_cco_ncp;
607 static int ett_cco_rrsc;
608 static int ett_cco_cmd_data;
609 static int ett_cco_ttt;
611 static int ett_time_sync_gm_clock_flags;
612 static int ett_time_sync_local_clock_flags;
613 static int ett_time_sync_port_state_info;
614 static int ett_time_sync_port_enable_cfg;
615 static int ett_time_sync_port_log_announce;
616 static int ett_time_sync_port_log_sync;
617 static int ett_time_sync_clock_type;
618 static int ett_time_sync_port_profile_id_info;
619 static int ett_time_sync_port_phys_addr_info;
620 static int ett_time_sync_port_proto_addr_info;
621 static int ett_id_status;
622 static int ett_32bitheader_tree;
624 static int ett_connection_info;
626 static expert_field ei_mal_identity_revision;
627 static expert_field ei_mal_identity_status;
628 static expert_field ei_mal_msg_rout_num_classes;
629 static expert_field ei_mal_time_sync_gm_clock;
630 static expert_field ei_mal_time_sync_parent_clock;
631 static expert_field ei_mal_time_sync_local_clock;
632 static expert_field ei_mal_time_sync_port_state_info;
633 static expert_field ei_mal_time_sync_port_state_info_ports;
634 static expert_field ei_mal_time_sync_port_enable_cfg;
635 static expert_field ei_mal_time_sync_port_enable_cfg_ports;
636 static expert_field ei_mal_time_sync_port_log_announce;
637 static expert_field ei_mal_time_sync_port_log_announce_ports;
638 static expert_field ei_mal_time_sync_port_log_sync;
639 static expert_field ei_mal_time_sync_port_log_sync_ports;
640 static expert_field ei_mal_time_sync_clock_type;
641 static expert_field ei_mal_time_sync_manufacture_id;
642 static expert_field ei_mal_time_sync_prod_desc;
643 static expert_field ei_mal_time_sync_prod_desc_64;
644 static expert_field ei_mal_time_sync_prod_desc_size;
645 static expert_field ei_mal_time_sync_revision_data;
646 static expert_field ei_mal_time_sync_revision_data_32;
647 static expert_field ei_mal_time_sync_revision_data_size;
648 static expert_field ei_mal_time_sync_user_desc;
649 static expert_field ei_mal_time_sync_user_desc_128;
650 static expert_field ei_mal_time_sync_user_desc_size;
651 static expert_field ei_mal_time_sync_port_profile_id_info;
652 static expert_field ei_mal_time_sync_port_profile_id_info_ports;
653 static expert_field ei_mal_time_sync_port_phys_addr_info;
654 static expert_field ei_mal_time_sync_port_phys_addr_info_ports;
655 static expert_field ei_mal_time_sync_port_proto_addr_info;
656 static expert_field ei_mal_time_sync_port_proto_addr_info_ports;
657 static expert_field ei_mal_time_sync_sys_time_and_offset;
658 static expert_field ei_proto_log_seg_format;
659 static expert_field ei_mal_incomplete_epath;
660 static expert_field ei_proto_electronic_key_format;
661 static expert_field ei_proto_special_segment_format;
662 static expert_field ei_proto_log_seg_type;
663 static expert_field ei_proto_log_sub_seg_type;
664 static expert_field ei_proto_ext_string_format;
665 static expert_field ei_proto_ext_network;
666 static expert_field ei_proto_seg_type;
667 static expert_field ei_proto_unsupported_datatype;
668 static expert_field ei_mal_serv_gal;
669 static expert_field ei_mal_serv_gal_count;
670 static expert_field ei_mal_serv_sal;
671 static expert_field ei_mal_serv_sal_count;
672 static expert_field ei_mal_msp_services;
673 static expert_field ei_mal_msp_inv_offset;
674 static expert_field ei_mal_msp_missing_services;
675 static expert_field ei_mal_serv_find_next_object;
676 static expert_field ei_mal_serv_find_next_object_count;
677 static expert_field ei_mal_rpi_no_data;
678 static expert_field ei_mal_fwd_close_missing_data;
679 static expert_field ei_mal_opt_attr_list;
680 static expert_field ei_mal_opt_service_list;
681 static expert_field ei_mal_padded_epath_size;
682 static expert_field ei_mal_missing_string_data;
684 static expert_field ei_cip_null_fwd_open;
685 static expert_field ei_cip_safety_open_type1;
686 static expert_field ei_cip_safety_open_type2a;
687 static expert_field ei_cip_safety_open_type2b;
688 static expert_field ei_cip_no_fwd_close;
689 static expert_field ei_cip_safety_input;
690 static expert_field ei_cip_safety_output;
691 static expert_field ei_cip_listen_input_connection;
693 //// Concurrent Connections
694 static int hf_cip_cm_cc_version;
696 static int hf_cip_cc_packet_length;
697 static int hf_cip_cc_packet_options;
698 static int hf_cip_cc_packet_type;
699 static int hf_cip_cc_packet_keepalive;
700 static int hf_cip_cc_packet_keepalive_hop_count;
701 static int hf_cip_cc_packet_reserved;
702 static int hf_cip_cc_packet_seq_number;
703 static int hf_cip_cc_crc;
704 static int hf_cip_cc_crc_status;
706 // Parameters for Concurrent Extended Network Segment
707 static int hf_ext_net_seg_hops_count;
708 static int hf_ext_net_seg_length;
709 static int hf_ext_net_seg_hop;
710 static int hf_ext_net_seg_hop_egress_cip_port;
711 static int hf_ext_net_seg_hop_link_adr_type;
712 static int hf_ext_net_seg_hop_number_of_linkadr;
713 static int hf_ext_net_seg_link_address;
714 static int hf_ext_net_seg_link_ipv4;
715 static int hf_ext_net_seg_link_hostname;
717 static int proto_cc;
719 /* Define the tree for the frame */
720 static int ett_cc_header;
721 static int ett_cc_hop;
723 static expert_field ei_cc_invalid_header_type;
724 static expert_field ei_cc_crc;
726 static const value_string cc_link_adr_type[] = {
727 { 0, "8-bit numeric link addresses" },
728 { 1, "IPv4 addresses" },
729 { 2, "Hostnames" },
731 { 0, NULL }
734 static const value_string cc_packet_type_vals[] = {
735 { 0, "Invalid" },
736 { 1, "Concurrent Connection Packet Format" },
738 { 0, NULL }
741 static int* ett_cc[] =
743 &ett_cc_header,
744 &ett_cc_hop,
747 static dissector_table_t subdissector_class_table;
748 static dissector_table_t subdissector_symbol_table;
750 /* Translate function to string - CIP Service codes */
751 static const value_string cip_sc_vals[] = {
752 GENERIC_SC_LIST
754 { 0, NULL }
757 /* Translate function to string - CIP Service codes for CM */
758 static const value_string cip_sc_vals_cm[] = {
759 GENERIC_SC_LIST
761 /* Some class specific services */
762 { SC_CM_FWD_CLOSE, "Forward Close" },
763 { SC_CM_FWD_OPEN, "Forward Open" },
764 { SC_CM_UNCON_SEND, "Unconnected Send" },
765 { SC_CM_LARGE_FWD_OPEN, "Large Forward Open" },
766 { SC_CM_GET_CONN_DATA, "Get Connection Data" },
767 { SC_CM_SEARCH_CONN_DATA, "Search Connection Data" },
768 { SC_CM_GET_CONN_OWNER, "Get Connection Owner" },
769 { SC_CM_CONCURRENT_FWD_OPEN, "Concurrent Forward Open" },
770 { SC_CM_CONCURRENT_FWD_CLOSE, "Concurrent Forward Close" },
772 { 0, NULL }
775 /* Translate function to string - CIP Service codes for PCCC */
776 static const value_string cip_sc_vals_pccc[] = {
777 GENERIC_SC_LIST
779 /* Some class specific services */
780 { SC_PCCC_EXECUTE_PCCC, "Execute PCCC" },
782 { 0, NULL }
785 /* Translate function to string - CIP Service codes for MB */
786 static const value_string cip_sc_vals_mb[] = {
787 GENERIC_SC_LIST
789 /* Some class specific services */
790 { SC_MB_READ_DISCRETE_INPUTS, "Read Discrete" },
791 { SC_MB_READ_COILS, "Read Coils" },
792 { SC_MB_READ_INPUT_REGISTERS, "Read Input Registers" },
793 { SC_MB_READ_HOLDING_REGISTERS, "Read Holding Registers" },
794 { SC_MB_WRITE_COILS, "Write Coils" },
795 { SC_MB_WRITE_HOLDING_REGISTERS, "Write Holding Registers" },
796 { SC_MB_PASSTHROUGH, "Modbus Passthrough" },
798 { 0, NULL }
801 /* Translate function to string - CIP Service codes for CCO */
802 static const value_string cip_sc_vals_cco[] = {
803 GENERIC_SC_LIST
805 /* Some class specific services */
806 { SC_CCO_KICK_TIMER, "Kick Timer" },
807 { SC_CCO_OPEN_CONN, "Open Connection" },
808 { SC_CCO_CLOSE_CONN, "Close Connection" },
809 { SC_CCO_STOP_CONN, "Stop Connection" },
810 { SC_CCO_CHANGE_START, "Change Start" },
811 { SC_CCO_GET_STATUS, "Get Status" },
812 { SC_CCO_CHANGE_COMPLETE, "Change Complete" },
813 { SC_CCO_AUDIT_CHANGE, "Audit Changes" },
815 { 0, NULL }
818 /* Translate function to string - CIP Request/Response */
819 const value_string cip_sc_rr[] = {
820 { 0, "Request" },
821 { 1, "Response" },
823 { 0, NULL }
826 /* Translate function to string - Compatibility */
827 static const value_string cip_com_bit_vals[] = {
828 { 0, "Bit Cleared" },
829 { 1, "Bit Set" },
831 { 0, NULL }
834 const value_string cip_reset_type_vals[] = {
835 { 0, "Cycle Power" },
836 { 1, "Factory Default" },
837 { 2, "Keep Communication Parameters" },
839 { 0, NULL }
842 /* Translate function to string - Connection priority */
843 const value_string cip_con_prio_vals[] = {
844 { 0, "Low Priority" },
845 { 1, "High Priority" },
846 { 2, "Scheduled" },
847 { 3, "Urgent" },
849 { 0, NULL }
852 /* Translate function to string - Connection size fixed or variable */
853 static const value_string cip_con_fw_vals[] = {
854 { 0, "Fixed" },
855 { 1, "Variable" },
857 { 0, NULL }
860 /* Translate function to string - Connection owner */
861 static const value_string cip_con_owner_vals[] = {
862 { 0, "Non-Redundant" },
863 { 1, "Redundant" },
865 { 0, NULL }
868 /* Translate function to string - Connection type*/
869 static const value_string cip_con_vals[] = {
870 { 0, "Originator" },
871 { 1, "Target" },
873 { 0, NULL }
876 /* Translate function to string - Production trigger */
877 static const value_string cip_con_trigg_vals[] = {
878 { 0, "Cyclic" },
879 { 1, "Change-Of-State" },
880 { 2, "Application Object" },
882 { 0, NULL }
885 /* Translate function to string - Transport class */
886 static const value_string cip_con_class_vals[] = {
887 { 0, "0" },
888 { 1, "1" },
889 { 2, "2" },
890 { 3, "3" },
892 { 0, NULL }
895 /* Translate function to string - Connection type */
896 const value_string cip_con_type_vals[] = {
897 { CONN_TYPE_NULL, "Null" },
898 { CONN_TYPE_MULTICAST, "Multicast" },
899 { CONN_TYPE_P2P, "Point to Point" },
900 { CONN_TYPE_RESERVED, "Reserved" },
902 { 0, NULL }
905 /* Translate function to string - Timeout Multiplier */
906 const value_string cip_con_time_mult_vals[] = {
907 { 0, "*4" },
908 { 1, "*8" },
909 { 2, "*16" },
910 { 3, "*32" },
911 { 4, "*64" },
912 { 5, "*128" },
913 { 6, "*256" },
914 { 7, "*512" },
916 { 0, NULL }
919 /* Translate function to string - Connection Last Action */
920 static const value_string cip_con_last_action_vals[] = {
921 { 0, "No Owner" },
922 { 1, "Owner Is Idle Mode" },
923 { 2, "Owner Is Run Mode" },
924 { 255, "Implementation not supported" },
926 { 0, NULL }
929 /* Translate function to string - real time transfer format type */
930 static const value_string cip_con_rtf_vals[] = {
931 { 0, "32-bit Header" },
932 { 1, "Zero data length idle mode"},
933 { 2, "Modeless" },
934 { 3, "Heartbeat" },
935 { 4, "Reserved" },
936 { 5, "Safety" },
938 { 0, NULL }
941 /* Translate function to string - CCO change type */
942 static const value_string cip_cco_change_type_vals[] = {
943 { 0, "Full" },
944 { 1, "Incremental" },
946 { 0, NULL }
949 static const value_string cip_time_sync_clock_class_vals[] = {
950 { 6, "Primary Reference" },
951 { 7, "Primary Reference (Hold)" },
952 { 52, "Degraded Reference A (Master only)" },
953 { 187, "Degraded Reference B (Master/Slave)" },
954 { 248, "Default" },
955 { 255, "Slave Only" },
957 { 0, NULL }
960 static const value_string cip_time_sync_time_accuracy_vals[] = {
961 { 0x20, "Accurate to within 25ns" },
962 { 0x21, "Accurate to within 100ns" },
963 { 0x22, "Accurate to within 250ns" },
964 { 0x23, "Accurate to within 1us" },
965 { 0x24, "Accurate to within 2.5us" },
966 { 0x25, "Accurate to within 10us" },
967 { 0x26, "Accurate to within 25us" },
968 { 0x27, "Accurate to within 100us" },
969 { 0x28, "Accurate to within 250us" },
970 { 0x29, "Accurate to within 1ms" },
971 { 0x2A, "Accurate to within 2.5ms" },
972 { 0x2B, "Accurate to within 10ms" },
973 { 0x2C, "Accurate to within 25ms" },
974 { 0x2D, "Accurate to within 100ms" },
975 { 0x2E, "Accurate to within 250ms" },
976 { 0x2F, "Accurate to within 1s" },
977 { 0x30, "Accurate to within 10s" },
978 { 0x31, "Accurate to >10s" },
979 { 0, NULL }
982 static const value_string cip_time_sync_time_source_vals[] = {
983 { 0x10, "Atomic Clock" },
984 { 0x20, "GPS" },
985 { 0x30, "Terrestrial Radio" },
986 { 0x40, "PTP" },
987 { 0x50, "NTP" },
988 { 0x60, "Hand Set" },
989 { 0x90, "Other" },
990 { 0xA0, "Internal Oscillator" },
991 { 0, NULL }
994 static const value_string cip_time_sync_port_state_vals[] = {
995 { 1, "INITIALIZING" },
996 { 2, "FAULTY" },
997 { 3, "DISABLED" },
998 { 4, "LISTENING" },
999 { 5, "PRE_MASTER" },
1000 { 6, "MASTER" },
1001 { 7, "PASSIVE" },
1002 { 8, "UNCALIBRATED" },
1003 { 9, "SLAVE" },
1004 { 0, NULL }
1007 static const value_string cip_time_sync_network_protocol_vals[] = {
1008 { 1, "UDP/IPv4" },
1009 { 2, "UDP/IPv6" },
1010 { 3, "IEEE 802.3" },
1011 { 4, "DeviceNet" },
1012 { 5, "ControlNet" },
1013 { 0xFFFF, "Local or Unknown protocol" },
1014 { 0, NULL }
1017 static const value_string cip_path_seg_vals[] = {
1018 { ((CI_PORT_SEGMENT>>5)&7), "Port Segment" },
1019 { ((CI_LOGICAL_SEGMENT>>5)&7), "Logical Segment" },
1020 { ((CI_NETWORK_SEGMENT>>5)&7), "Network Segment" },
1021 { ((CI_SYMBOLIC_SEGMENT>>5)&7), "Symbolic Segment" },
1022 { ((CI_DATA_SEGMENT>>5)&7), "Data Segment" },
1023 { 5, "Constructed Data Type" },
1024 { 6, "Elementary Data Type" },
1025 { 7, "Reserved" },
1027 { 0, NULL }
1030 static const value_string cip_logical_segment_type_vals[] = {
1031 { ((CI_LOGICAL_SEG_CLASS_ID>>2)&7), "Class ID" },
1032 { ((CI_LOGICAL_SEG_INST_ID>>2)&7), "Instance ID" },
1033 { ((CI_LOGICAL_SEG_MBR_ID>>2)&7), "Member ID" },
1034 { ((CI_LOGICAL_SEG_CON_POINT>>2)&7), "Connection Point" },
1035 { ((CI_LOGICAL_SEG_ATTR_ID>>2)&7), "Attribute ID" },
1036 { ((CI_LOGICAL_SEG_SPECIAL>>2)&7), "Special" },
1037 { ((CI_LOGICAL_SEG_SERV_ID>>2)&7), "Service ID" },
1038 { ((CI_LOGICAL_SEG_EXT_LOGICAL>>2)&7), "Extended Logical" },
1040 { 0, NULL }
1043 static const value_string cip_logical_segment_format_vals[] = {
1044 { CI_LOGICAL_SEG_8_BIT, "8-bit Logical Segment" },
1045 { CI_LOGICAL_SEG_16_BIT, "16-bit Logical Segment" },
1046 { CI_LOGICAL_SEG_32_BIT, "32-bit Logical Segment" },
1047 { CI_LOGICAL_SEG_RES_2, "Reserved" },
1049 { 0, NULL }
1052 static const value_string cip_logical_seg_vals[] = {
1053 {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Class Segment"},
1054 {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Class Segment"},
1055 {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Class Segment"},
1057 {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Instance Segment"},
1058 {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Instance Segment"},
1059 {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Instance Segment"},
1061 {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Member Segment"},
1062 {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Member Segment"},
1063 {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Member Segment"},
1065 {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Connection Point Segment"},
1066 {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Connection Point Segment"},
1067 {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Connection Point Segment"},
1069 {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Attribute Segment"},
1070 {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Attribute Segment"},
1071 {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Attribute Segment"},
1073 {((CI_LOGICAL_SEG_SERV_ID & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_8_BIT), "8-Bit Service ID Segment"},
1075 {CI_LOGICAL_SEG_SPECIAL, "Electronic Key Segment"},
1077 {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_8_BIT), "8-Bit Extended Logical Segment"},
1078 {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_16_BIT), "16-Bit Extended Logical Segment"},
1079 {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_32_BIT), "32-Bit Extended Logical Segment"},
1081 { 0, NULL }
1084 static const value_string cip_ext_logical_segment_format_vals[] = {
1085 { 0, "Reserved" },
1086 { 1, "Array Index" },
1087 { 2, "Indirect Array Index" },
1088 { 3, "Bit Index" },
1089 { 4, "Indirect Bit Index" },
1090 { 5, "Structure Member Number" },
1091 { 6, "Structure Member Handle" },
1093 { 0, NULL }
1096 static const value_string cip_data_segment_type_vals[] = {
1097 {CI_DATA_SEG_SIMPLE, "Simple Data Segment"},
1098 {CI_DATA_SEG_SYMBOL, "ANSI Extended Symbol Segment"},
1100 { 0, NULL }
1103 static const value_string cip_network_segment_type_vals[] = {
1104 {CI_NETWORK_SEG_SCHEDULE, "Schedule Segment"},
1105 {CI_NETWORK_SEG_FIXED_TAG, "Fixed Tag Segment"},
1106 {CI_NETWORK_SEG_PROD_INHI, "Production Inhibit Time in Milliseconds"},
1107 {CI_NETWORK_SEG_SAFETY, "Safety Segment"},
1108 {CI_NETWORK_SEG_PROD_INHI_US, "Production Inhibit Time in Microseconds"},
1109 {CI_NETWORK_SEG_EXTENDED, "Extended Network Segment"},
1111 { 0, NULL }
1114 static const value_string cip_symbolic_format_vals[] = {
1115 { 1, "Double Byte Segment" },
1116 { 2, "Triple Byte Segment" },
1117 { 6, "Numeric Segment" },
1119 { 0, NULL }
1122 static const value_string cip_symbolic_numeric_format_vals[] = {
1123 { 6, "USINT" },
1124 { 7, "UINT" },
1125 { 8, "UDINT" },
1127 { 0, NULL }
1130 static const value_string cip_safety_segment_format_type_vals[] = {
1131 {0, "Target Format"},
1132 {1, "Router Format"},
1133 {2, "Extended Format"},
1135 { 0, NULL }
1138 static const value_string cip_cm_rpi_type_vals[] = {
1139 {0, "RPI acceptable"},
1140 {1, "Unspecified"},
1141 {2, "Minimum acceptable RPI"},
1142 {3, "Maximum acceptable RPI"},
1143 {4, "Required RPI to correct mismatch"},
1145 { 0, NULL }
1148 /* Translate function to string - CIP General Status codes */
1149 static const value_string cip_gs_vals[] = {
1150 { CI_GRC_SUCCESS, "Success" },
1151 { CI_GRC_FAILURE, "Connection failure" },
1152 { CI_GRC_NO_RESOURCE, "Resource unavailable" },
1153 { CI_GRC_BAD_DATA, "Invalid parameter value" },
1154 { CI_GRC_BAD_PATH, "Path segment error" },
1155 { CI_GRC_BAD_CLASS_INSTANCE, "Path destination unknown" },
1156 { CI_GRC_PARTIAL_DATA, "Partial transfer" },
1157 { CI_GRC_CONN_LOST, "Connection lost" },
1158 { CI_GRC_BAD_SERVICE, "Service not supported" },
1159 { CI_GRC_BAD_ATTR_DATA, "Invalid attribute value" },
1160 { CI_GRC_ATTR_LIST_ERROR, "Attribute list error" },
1161 { CI_GRC_ALREADY_IN_MODE, "Already in requested mode/state" },
1162 { CI_GRC_BAD_OBJ_MODE, "Object state conflict" },
1163 { CI_GRC_OBJ_ALREADY_EXISTS, "Object already exists" },
1164 { CI_GRC_ATTR_NOT_SETTABLE, "Attribute not settable" },
1165 { CI_GRC_PERMISSION_DENIED, "Privilege violation" },
1166 { CI_GRC_DEV_IN_WRONG_STATE, "Device state conflict" },
1167 { CI_GRC_REPLY_DATA_TOO_LARGE,"Reply data too large" },
1168 { CI_GRC_FRAGMENT_PRIMITIVE, "Fragmentation of a primitive value" },
1169 { CI_GRC_CONFIG_TOO_SMALL, "Not enough data" },
1170 { CI_GRC_UNDEFINED_ATTR, "Attribute not supported" },
1171 { CI_GRC_CONFIG_TOO_BIG, "Too much data" },
1172 { CI_GRC_OBJ_DOES_NOT_EXIST, "Object does not exist" },
1173 { CI_GRC_NO_FRAGMENTATION, "Service fragmentation sequence not in progress" },
1174 { CI_GRC_DATA_NOT_SAVED, "No stored attribute data" },
1175 { CI_GRC_DATA_WRITE_FAILURE, "Store operation failure" },
1176 { CI_GRC_REQUEST_TOO_LARGE, "Routing failure, request packet too large" },
1177 { CI_GRC_RESPONSE_TOO_LARGE, "Routing failure, response packet too large" },
1178 { CI_GRC_MISSING_LIST_DATA, "Missing attribute list entry data" },
1179 { CI_GRC_INVALID_LIST_STATUS, "Invalid attribute value list" },
1180 { CI_GRC_SERVICE_ERROR, "Embedded service error" },
1181 { CI_GRC_CONN_RELATED_FAILURE,"Vendor specific error" },
1182 { CI_GRC_INVALID_PARAMETER, "Invalid parameter" },
1183 { CI_GRC_WRITE_ONCE_FAILURE, "Write-once value or medium already written" },
1184 { CI_GRC_INVALID_REPLY, "Invalid reply received" },
1185 { CI_GRC_BUFFER_OVERFLOW, "Buffer overflow" },
1186 { CI_GRC_MESSAGE_FORMAT, "Invalid message format" },
1187 { CI_GRC_BAD_KEY_IN_PATH, "Key failure in path" },
1188 { CI_GRC_BAD_PATH_SIZE, "Path size invalid" },
1189 { CI_GRC_UNEXPECTED_ATTR, "Unexpected attribute in list" },
1190 { CI_GRC_INVALID_MEMBER, "Invalid Member ID" },
1191 { CI_GRC_MEMBER_NOT_SETTABLE, "Member not settable" },
1192 { CI_GRC_G2_SERVER_FAILURE, "Group 2 only server general failure" },
1193 { CI_GRC_UNKNOWN_MB_ERROR, "Unknown Modbus error" },
1194 { CI_GRC_ATTRIBUTE_NOT_GET, "Attribute not gettable" },
1196 { 0, NULL }
1199 value_string_ext cip_gs_vals_ext = VALUE_STRING_EXT_INIT(cip_gs_vals);
1201 /* Connection Manager Extended Status codes */
1202 #define CM_ES_DUP_FWD_OPEN 0x100
1203 #define CM_ES_CLASS_AND_TRIGGER 0x103
1204 #define CM_ES_OWNERSHIP_CONFLICT 0x106
1205 #define CM_ES_TARGET_CONN_NOT_FOUND 0x107
1206 #define CM_ES_INVALID_NET_CONN_PARAM 0x108
1207 #define CM_ES_INVALID_CONNECTION_SIZE 0x109
1208 #define CM_ES_TARGET_CONNECTION_NOT_CONFIGURED 0x110
1209 #define CM_ES_RPI_NOT_SUPPORTED 0x111
1210 #define CM_ES_RPI_NOT_ACCEPTABLE 0x112
1211 #define CM_ES_OUT_OF_CONNECTIONS 0x113
1212 #define CM_ES_VENDOR_ID_OR_PRODUCT_CODE_MISMATCH 0x114
1213 #define CM_ES_DEVICE_TYPE_MISMATCH 0x115
1214 #define CM_ES_REVISION_MISMATCH 0x116
1215 #define CM_ES_INVALID_PROD_CONS_APP_PATH 0x117
1216 #define CM_ES_INVALID_OR_INCONSISTENT_CONF_APP_PATH 0x118
1217 #define CM_ES_NON_LISTEN_ONLY_CONN_NOT_OPENED 0x119
1218 #define CM_ES_TARGET_OBJECT_OUT_OF_CONNECTIONS 0x11A
1219 #define CM_ES_RPI_SMALLER_THAN_PROD_INHIBIT_TIME 0x11B
1220 #define CM_ES_TRANSPORT_CLASS_NOT_SUPPORTED 0x11C
1221 #define CM_ES_PRODUCTION_TRIGGER_NOT_SUPPORTED 0x11D
1222 #define CM_ES_DIRECTION_NOT_SUPPORTED 0x11E
1223 #define CM_ES_INVALID_OT_NET_CONN_FIX_VAR 0x11F
1224 #define CM_ES_INVALID_TO_NET_CONN_FIX_VAR 0x120
1225 #define CM_ES_INVALID_OT_NET_CONN_PRIORITY 0x121
1226 #define CM_ES_INVALID_TO_NET_CONN_PRIORITY 0x122
1227 #define CM_ES_INVALID_OT_NET_CONN_TYPE 0x123
1228 #define CM_ES_INVALID_TO_NET_CONN_TYPE 0x124
1229 #define CM_ES_INVALID_OT_NET_CONN_REDUNDANT_OWNER 0x125
1230 #define CM_ES_INVALID_CONFIGURATION_SIZE 0x126
1231 #define CM_ES_INVALID_OT_SIZE 0x127
1232 #define CM_ES_INVALID_TO_SIZE 0x128
1233 #define CM_ES_INVALID_CONFIGURATION_APP_PATH 0x129
1234 #define CM_ES_INVALID_CONSUMING_APP_PATH 0x12A
1235 #define CM_ES_INVALID_PRODUCING_APP_PATH 0x12B
1236 #define CM_ES_CONFIGURATION_SYMBOL_NOT_EXIST 0x12C
1237 #define CM_ES_CONSUMING_SYMBOL_NOT_EXIST 0x12D
1238 #define CM_ES_PRODUCING_SYMBOL_NOT_EXIST 0x12E
1239 #define CM_ES_INCONSISTENT_APP_PATH_COMBO 0x12F
1240 #define CM_ES_INCONSISTENT_CONSUME_DATA_FORMAT 0x130
1241 #define CM_ES_INCONSISTENT_PRODUCE_DATA_FORMAT 0x131
1242 #define CM_ES_NULL_FORWARD_OPEN_NOT_SUPPORTED 0x132
1243 #define CM_ES_CONNECTION_TIMED_OUT 0x203
1244 #define CM_ES_UNCONNECTED_REQUEST_TIMED_OUT 0x204
1245 #define CM_ES_PARAMETER_ERROR_IN_UNCONNECTED_REQUEST 0x205
1246 #define CM_ES_MESSAGE_TOO_LARGE_FOR_UNCONNECTED_SEND 0x206
1247 #define CM_ES_UNCONNECTED_ACK_WITHOUT_REPLY 0x207
1248 #define CM_ES_NO_BUFFER_MEMORY_AVAILABLE 0x301
1249 #define CM_ES_NETWORK_BANDWIDTH_NOT_AVAIL_FOR_DATA 0x302
1250 #define CM_ES_NO_CONSUMED_CONN_ID_FILTER_AVAILABLE 0x303
1251 #define CM_ES_NOT_CONFIGURED_TO_SEND_SCHEDULED_DATA 0x304
1252 #define CM_ES_SCHEDULE_SIGNATURE_MISMATCH 0x305
1253 #define CM_ES_SCHEDULE_SIGNATURE_VALIDATION_NOT_POSS 0x306
1254 #define CM_ES_PORT_NOT_AVAILABLE 0x311
1255 #define CM_ES_LINK_ADDRESS_NOT_VALID 0x312
1256 #define CM_ES_INVALID_SEGMENT_IN_CONN_PATH 0x315
1257 #define CM_ES_FWD_CLOSE_CONN_PATH_MISMATCH 0x316
1258 #define CM_ES_SCHEDULING_NOT_SPECIFIED 0x317
1259 #define CM_ES_LINK_ADDRESS_TO_SELF_INVALID 0x318
1260 #define CM_ES_SECONDARY_RESOURCES_UNAVAILABLE 0x319
1261 #define CM_ES_RACK_CONNECTION_ALREADY_ESTABLISHED 0x31A
1262 #define CM_ES_MODULE_CONNECTION_ALREADY_ESTABLISHED 0x31B
1263 #define CM_ES_MISCELLANEOUS 0x31C
1264 #define CM_ES_REDUNDANT_CONNECTION_MISMATCH 0x31D
1265 #define CM_ES_NO_CONSUMER_RES_AVAIL_IN_PROD_MODULE 0x31E
1266 #define CM_ES_NO_CONSUMER_RES_CONF_IN_PROD_MODULE 0x31F
1267 #define CM_ES_NETWORK_LINK_OFFLINE 0x800
1268 #define CM_ES_INCOMPATIBLE_MULTICAST_RPI 0x801
1269 #define CM_ES_INVALID_SAFETY_CONN_SIZE 0x802
1270 #define CM_ES_INVALID_SAFETY_CONN_FORMAT 0x803
1271 #define CM_ES_INVALID_TIME_CORRECTION_CONN_PARAM 0x804
1272 #define CM_ES_INVALID_PING_INTERVAL_EPI_MULTIPLIER 0x805
1273 #define CM_ES_TIME_COORDINATION_MSG_MIN_MULTIPLIER 0x806
1274 #define CM_ES_NETWORK_TIME_EXPECTATION_MULTIPLIER 0x807
1275 #define CM_ES_TIMEOUT_MULTIPLIER 0x808
1276 #define CM_ES_INVALID_MAX_CONSUMER_NUMBER 0x809
1277 #define CM_ES_INVALID_CPCRC 0x80A
1278 #define CM_ES_TIME_CORRECTION_CONN_ID_INVALID 0x80B
1279 #define CM_ES_SCID_MISMATCH 0x80C
1280 #define CM_ES_TUNID_NOT_SET 0x80D
1281 #define CM_ES_TUNID_MISMATCH 0x80E
1282 #define CM_ES_CONFIGURATION_OPERATION_NOT_ALLOWED 0x80F
1283 #define CM_ES_NO_TARGET_APP_DATA_AVAILABLE 0x810
1284 #define CM_ES_NO_ORIG_APP_DATA_AVAILABLE 0x811
1285 #define CM_ES_NODE_ADDRESS_CHANGED_AFTER_SCHEDULED 0x812
1286 #define CM_ES_NOT_CONFIGURED_MULTICAST 0x813
1287 #define CM_ES_INVALID_PROD_CONS_DATA_FORMAT 0x814
1288 #define CM_ES_EGRESS_RULE_DENY 0x916
1289 #define CM_ES_EGRESS_RULE_CIPHER_NOT_ALLOWED 0x917
1290 #define CM_ES_NO_MATCHING_INGRESS_RULE 0x918
1291 #define CM_ES_INGRESS_RULE_DENY 0x919
1292 #define CM_ES_INGRESS_RULE_DENY_NON_SECURE 0x91A
1293 #define CM_ES_NO_MATCHING_EGRESS_RULE 0x91B
1295 /* Translate function to string - CIP Extended Status codes */
1296 static const value_string cip_cm_ext_st_vals[] = {
1297 { CM_ES_DUP_FWD_OPEN, "Connection in use or duplicate Forward Open" },
1298 { CM_ES_CLASS_AND_TRIGGER, "Transport class and trigger combination not supported" },
1299 { CM_ES_OWNERSHIP_CONFLICT, "Ownership conflict" },
1300 { CM_ES_TARGET_CONN_NOT_FOUND, "Target connection not found" },
1301 { CM_ES_INVALID_NET_CONN_PARAM, "Invalid network connection parameter" },
1302 { CM_ES_INVALID_CONNECTION_SIZE, "Invalid connection size" },
1303 { CM_ES_TARGET_CONNECTION_NOT_CONFIGURED, "Target for connection not configured" },
1304 { CM_ES_RPI_NOT_SUPPORTED, "RPI not supported" },
1305 { CM_ES_RPI_NOT_ACCEPTABLE, "RPI value(s) not acceptable" },
1306 { CM_ES_OUT_OF_CONNECTIONS, "Out of connections" },
1307 { CM_ES_VENDOR_ID_OR_PRODUCT_CODE_MISMATCH, "Vendor ID or product code mismatch" },
1308 { CM_ES_DEVICE_TYPE_MISMATCH, "Device type mismatch" },
1309 { CM_ES_REVISION_MISMATCH, "Revision mismatch" },
1310 { CM_ES_INVALID_PROD_CONS_APP_PATH, "Invalid produced or consumed application path" },
1311 { CM_ES_INVALID_OR_INCONSISTENT_CONF_APP_PATH, "Invalid or inconsistent configuration application path" },
1312 { CM_ES_NON_LISTEN_ONLY_CONN_NOT_OPENED, "Non-listen only connection not opened" },
1313 { CM_ES_TARGET_OBJECT_OUT_OF_CONNECTIONS, "Target object out of connections" },
1314 { CM_ES_RPI_SMALLER_THAN_PROD_INHIBIT_TIME, "RPI is smaller than the production inhibit time" },
1315 { CM_ES_TRANSPORT_CLASS_NOT_SUPPORTED, "Transport class not supported" },
1316 { CM_ES_PRODUCTION_TRIGGER_NOT_SUPPORTED, "Production trigger not supported" },
1317 { CM_ES_DIRECTION_NOT_SUPPORTED, "Direction not supported" },
1318 { CM_ES_INVALID_OT_NET_CONN_FIX_VAR, "Invalid O->T Fixed/Variable" },
1319 { CM_ES_INVALID_TO_NET_CONN_FIX_VAR, "Invalid T->O Fixed/Variable" },
1320 { CM_ES_INVALID_OT_NET_CONN_PRIORITY, "Invalid O->T Priority" },
1321 { CM_ES_INVALID_TO_NET_CONN_PRIORITY, "Invalid T->O Priority" },
1322 { CM_ES_INVALID_OT_NET_CONN_TYPE, "Invalid O->T connection type" },
1323 { CM_ES_INVALID_TO_NET_CONN_TYPE, "Invalid T->O connection type" },
1324 { CM_ES_INVALID_OT_NET_CONN_REDUNDANT_OWNER, "Invalid O->T redundant owner" },
1325 { CM_ES_INVALID_CONFIGURATION_SIZE, "Invalid configuration size" },
1326 { CM_ES_INVALID_OT_SIZE, "Invalid O->T size" },
1327 { CM_ES_INVALID_TO_SIZE, "Invalid T->O size" },
1328 { CM_ES_INVALID_CONFIGURATION_APP_PATH, "Invalid configuration application path" },
1329 { CM_ES_INVALID_CONSUMING_APP_PATH, "Invalid consuming application path" },
1330 { CM_ES_INVALID_PRODUCING_APP_PATH, "Invalid producing application path" },
1331 { CM_ES_CONFIGURATION_SYMBOL_NOT_EXIST, "Configuration symbol does not exist" },
1332 { CM_ES_CONSUMING_SYMBOL_NOT_EXIST, "Consuming symbol does not exist" },
1333 { CM_ES_PRODUCING_SYMBOL_NOT_EXIST, "Producing symbol does not exist" },
1334 { CM_ES_INCONSISTENT_APP_PATH_COMBO, "Inconsistent application path combination" },
1335 { CM_ES_INCONSISTENT_CONSUME_DATA_FORMAT, "Inconsistent consume data format" },
1336 { CM_ES_INCONSISTENT_PRODUCE_DATA_FORMAT, "Inconsistent produce data format" },
1337 { CM_ES_NULL_FORWARD_OPEN_NOT_SUPPORTED, "NULL ForwardOpen not supported" },
1338 { CM_ES_CONNECTION_TIMED_OUT, "Connection timed out" },
1339 { CM_ES_UNCONNECTED_REQUEST_TIMED_OUT, "Unconnected request timed out" },
1340 { CM_ES_PARAMETER_ERROR_IN_UNCONNECTED_REQUEST, "Parameter error in unconnected request" },
1341 { CM_ES_MESSAGE_TOO_LARGE_FOR_UNCONNECTED_SEND, "Message too large for UnconnectedSend" },
1342 { CM_ES_UNCONNECTED_ACK_WITHOUT_REPLY, "Unconnected acknowledged without reply" },
1343 { CM_ES_NO_BUFFER_MEMORY_AVAILABLE, "No buffer memory available" },
1344 { CM_ES_NETWORK_BANDWIDTH_NOT_AVAIL_FOR_DATA, "Network bandwidth not available for data" },
1345 { CM_ES_NO_CONSUMED_CONN_ID_FILTER_AVAILABLE, "No consumed connection ID filter available" },
1346 { CM_ES_NOT_CONFIGURED_TO_SEND_SCHEDULED_DATA, "Not configured to send scheduled priority data" },
1347 { CM_ES_SCHEDULE_SIGNATURE_MISMATCH, "Schedule signature mismatch" },
1348 { CM_ES_SCHEDULE_SIGNATURE_VALIDATION_NOT_POSS, "Schedule signature validation not possible" },
1349 { CM_ES_PORT_NOT_AVAILABLE, "Port not available" },
1350 { CM_ES_LINK_ADDRESS_NOT_VALID, "Link address not valid" },
1351 { CM_ES_INVALID_SEGMENT_IN_CONN_PATH, "Invalid segment in connection path" },
1352 { CM_ES_FWD_CLOSE_CONN_PATH_MISMATCH, "ForwardClose connection path mismatch" },
1353 { CM_ES_SCHEDULING_NOT_SPECIFIED, "Scheduling not specified" },
1354 { CM_ES_LINK_ADDRESS_TO_SELF_INVALID, "Link address to self invalid" },
1355 { CM_ES_SECONDARY_RESOURCES_UNAVAILABLE, "Secondary resources unavailable" },
1356 { CM_ES_RACK_CONNECTION_ALREADY_ESTABLISHED, "Rack connection already established" },
1357 { CM_ES_MODULE_CONNECTION_ALREADY_ESTABLISHED, "Module connection already established" },
1358 { CM_ES_MISCELLANEOUS, "Miscellaneous" },
1359 { CM_ES_REDUNDANT_CONNECTION_MISMATCH, "Redundant connection mismatch" },
1360 { CM_ES_NO_CONSUMER_RES_AVAIL_IN_PROD_MODULE, "No more user configurable link consumer resources available in the producing module" },
1361 { CM_ES_NO_CONSUMER_RES_CONF_IN_PROD_MODULE, "No more user configurable link consumer resources configured in the producing module" },
1362 { CM_ES_NETWORK_LINK_OFFLINE, "Network link offline" },
1363 { CM_ES_INCOMPATIBLE_MULTICAST_RPI, "Incompatible Multicast RPI" },
1364 { CM_ES_INVALID_SAFETY_CONN_SIZE, "Invalid Safety Connection Size" },
1365 { CM_ES_INVALID_SAFETY_CONN_FORMAT, "Invalid Safety Connection Format" },
1366 { CM_ES_INVALID_TIME_CORRECTION_CONN_PARAM, "Invalid Time Correction Connection Parameters" },
1367 { CM_ES_INVALID_PING_INTERVAL_EPI_MULTIPLIER, "Invalid Ping Interval EPI Multiplier" },
1368 { CM_ES_TIME_COORDINATION_MSG_MIN_MULTIPLIER, "Time Coordination Msg Min Multiplier" },
1369 { CM_ES_NETWORK_TIME_EXPECTATION_MULTIPLIER, "Network Time Expectation Multiplier" },
1370 { CM_ES_TIMEOUT_MULTIPLIER, "Timeout Multiplier" },
1371 { CM_ES_INVALID_MAX_CONSUMER_NUMBER, "Invalid Max Consumer Number" },
1372 { CM_ES_INVALID_CPCRC, "Invalid CPCRC" },
1373 { CM_ES_TIME_CORRECTION_CONN_ID_INVALID, "Time Correction Connection ID Invalid" },
1374 { CM_ES_SCID_MISMATCH, "SCID Mismatch" },
1375 { CM_ES_TUNID_NOT_SET, "TUNID not set" },
1376 { CM_ES_TUNID_MISMATCH, "TUNID Mismatch" },
1377 { CM_ES_CONFIGURATION_OPERATION_NOT_ALLOWED, "Configuration operation not allowed" },
1378 { CM_ES_NO_TARGET_APP_DATA_AVAILABLE, "No target application data available" },
1379 { CM_ES_NO_ORIG_APP_DATA_AVAILABLE, "No originator application data available" },
1380 { CM_ES_NODE_ADDRESS_CHANGED_AFTER_SCHEDULED, "Node address has changed since the network was scheduled" },
1381 { CM_ES_NOT_CONFIGURED_MULTICAST, "Not configured for off-subnet multicast" },
1382 { CM_ES_INVALID_PROD_CONS_DATA_FORMAT, "Invalid produce/consume data format" },
1383 { CM_ES_EGRESS_RULE_DENY, "Egress Rule deny" },
1384 { CM_ES_EGRESS_RULE_CIPHER_NOT_ALLOWED, "Egress Rule Cipher not allowed" },
1385 { CM_ES_NO_MATCHING_INGRESS_RULE, "No matching Ingress Rules" },
1386 { CM_ES_INGRESS_RULE_DENY, "Ingress Rule deny" },
1387 { CM_ES_INGRESS_RULE_DENY_NON_SECURE, "Ingress Rule deny non-secure" },
1388 { CM_ES_NO_MATCHING_EGRESS_RULE, "No matching Egress Rule" },
1390 { 0, NULL }
1393 value_string_ext cip_cm_ext_st_vals_ext = VALUE_STRING_EXT_INIT(cip_cm_ext_st_vals);
1395 /* Translate function to string - PCCC Status codes */
1396 static const value_string cip_pccc_gs_st_vals[] = {
1397 { PCCC_GS_SUCCESS, "Success" },
1398 { PCCC_GS_ILLEGAL_CMD, "Illegal command or format" },
1399 { PCCC_GS_HOST_COMMS, "Host has a problem and will not communicate" },
1400 { PCCC_GS_MISSING_REMOTE_NODE, "Remote node host is missing, disconnected, or shut down" },
1401 { PCCC_GS_HARDWARE_FAULT, "Host could not complete function due to hardware fault" },
1402 { PCCC_GS_ADDRESSING_ERROR, "Addressing problem or memory protect rungs" },
1403 { PCCC_GS_CMD_PROTECTION, "Function not allowed due to command protection selection" },
1404 { PCCC_GS_PROGRAM_MODE, "Processor is in Program mode" },
1405 { PCCC_GS_MISSING_COMPATIBILITY_FILE, "Compatibility mode file missing or communication zone problem" },
1406 { PCCC_GS_BUFFER_FULL_1, "Remote node cannot buffer command" },
1407 { PCCC_GS_WAIT_ACK, "Wait ACK (1775-KA buffer full)" },
1408 { PCCC_GS_REMOTE_DOWNLOAD_ERROR, "Remote node problem due to download" },
1409 { PCCC_GS_BUFFER_FULL_2, "Wait ACK (1775-KA buffer full)" },
1410 { PCCC_GS_NOT_USED_1, "Not used" },
1411 { PCCC_GS_NOT_USED_2, "Not used" },
1412 { PCCC_GS_USE_EXTSTS, "Error code in the EXT STS byte" },
1414 { 0, NULL }
1417 static value_string_ext cip_pccc_gs_st_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_gs_st_vals);
1419 /* Translate function to string - PCCC Extended Status codes */
1420 static const value_string cip_pccc_es_st_vals[] = {
1421 { PCCC_ES_ILLEGAL_VALUE, "A field has an illegal value" },
1422 { PCCC_ES_SHORT_ADDRESS, "Less levels specified in address than minimum for any address" },
1423 { PCCC_ES_LONG_ADDRESS, "More levels specified in address than system supports" },
1424 { PCCC_ES_NOT_FOUND, "Symbol not found" },
1425 { PCCC_ES_BAD_FORMAT, "Symbol is of improper format" },
1426 { PCCC_ES_BAD_POINTER, "Address doesn't point to something usable" },
1427 { PCCC_ES_BAD_SIZE, "File is wrong size" },
1428 { PCCC_ES_SITUATION_CHANGED, "Cannot complete request, situation has changed since the start of the command" },
1429 { PCCC_ES_DATA_TOO_LARGE, "Data or file is too large" },
1430 { PCCC_ES_TRANS_TOO_LARGE, "Transaction size plus word address is too large" },
1431 { PCCC_ES_ACCESS_DENIED, "Access denied, improper privilege" },
1432 { PCCC_ES_NOT_AVAILABLE, "Condition cannot be generated - resource is not available" },
1433 { PCCC_ES_ALREADY_EXISTS, "Condition already exists - resource is already available" },
1434 { PCCC_ES_NO_EXECUTION, "Command cannot be executed" },
1435 { PCCC_ES_HIST_OVERFLOW, "Histogram overflow" },
1436 { PCCC_ES_NO_ACCESS, "No access" },
1437 { PCCC_ES_ILLEGAL_DATA_TYPE, "Illegal data type" },
1438 { PCCC_ES_INVALID_DATA, "Invalid parameter or invalid data" },
1439 { PCCC_ES_BAD_REFERENCE, "Address reference exists to deleted area" },
1440 { PCCC_ES_EXECUTION_FAILURE, "Command execution failure for unknown reason; possible PLC-3 histogram overflow" },
1441 { PCCC_ES_CONVERSION_ERROR, "Data conversion error" },
1442 { PCCC_ES_NO_COMMS, "Scanner not able to communicate with 1771 rack adapter" },
1443 { PCCC_ES_TYPE_MISMATCH, "Type mismatch" },
1444 { PCCC_ES_BAD_RESPONSE, "1771 module response was not valid" },
1445 { PCCC_ES_DUP_LABEL, "Duplicated label" },
1446 { PCCC_ES_FILE_ALREADY_OPEN, "File is open; another node owns it" },
1447 { PCCC_ES_PROGRAM_ALREADY_OWNED, "Another node is the program owner" },
1448 { PCCC_ES_RESERVED_1, "Reserved" },
1449 { PCCC_ES_RESERVED_2, "Reserved" },
1450 { PCCC_ES_PROTECTION_VIOLATION, "Data table element protection violation" },
1451 { PCCC_ES_TMP_INTERNAL_ERROR, "Temporary internal problem" },
1452 { PCCC_ES_RACK_FAULT, "Remote rack fault" },
1453 { PCCC_ES_TIMEOUT, "Timeout" },
1454 { PCCC_ES_UNKNOWN, "Unknown error" },
1456 { 0, NULL }
1459 static value_string_ext cip_pccc_es_st_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_es_st_vals);
1461 /* Translate PCCC Function Codes */
1462 static const value_string cip_pccc_fnc_06_vals[] = {
1463 { PCCC_FNC_06_00, "Echo" },
1464 { PCCC_FNC_06_01, "Read diagnostic counters" },
1465 { PCCC_FNC_06_02, "Set variables" },
1466 { PCCC_FNC_06_03, "Diagnostic status" },
1467 { PCCC_FNC_06_04, "Set timeout" },
1468 { PCCC_FNC_06_05, "Set NAKs" },
1469 { PCCC_FNC_06_06, "Set ENQs" },
1470 { PCCC_FNC_06_07, "Reset diagnostic counters" },
1471 { PCCC_FNC_06_08, "Set data table size" },
1472 { PCCC_FNC_06_09, "Read link parameters" },
1473 { PCCC_FNC_06_0A, "Set link parameters" },
1475 { 0, NULL }
1478 static value_string_ext cip_pccc_fnc_06_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_06_vals);
1480 static const value_string cip_pccc_fnc_07_vals[] = {
1481 { PCCC_FNC_07_00, "Disable outputs" },
1482 { PCCC_FNC_07_01, "Enable outputs" },
1483 { PCCC_FNC_07_03, "Enable PLC scanning" },
1484 { PCCC_FNC_07_04, "Enter download mode" },
1485 { PCCC_FNC_07_05, "Exit download/upload mode" },
1486 { PCCC_FNC_07_06, "Enter upload mode" },
1488 { 0, NULL }
1491 static value_string_ext cip_pccc_fnc_07_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_07_vals);
1493 static const value_string cip_pccc_fnc_0f_vals[] = {
1494 { PCCC_FNC_0F_00, "Word range write" },
1495 { PCCC_FNC_0F_01, "Word range read" },
1496 { PCCC_FNC_0F_02, "Bit write" },
1497 { PCCC_FNC_0F_03, "File write" },
1498 { PCCC_FNC_0F_04, "File read" },
1499 { PCCC_FNC_0F_05, "Download request" },
1500 { PCCC_FNC_0F_06, "Upload" },
1501 { PCCC_FNC_0F_07, "Shutdown" },
1502 { PCCC_FNC_0F_08, "Physical write" },
1503 { PCCC_FNC_0F_09, "Physical read" },
1504 { PCCC_FNC_0F_0A, "Restart request" },
1505 { PCCC_FNC_0F_11, "Get edit resource" },
1506 { PCCC_FNC_0F_12, "Return edit resource" },
1507 { PCCC_FNC_0F_17, "Read bytes physical" },
1508 { PCCC_FNC_0F_18, "Write bytes physical" },
1509 { PCCC_FNC_0F_26, "Read-modify-write" },
1510 { PCCC_FNC_0F_29, "Read section size" },
1511 { PCCC_FNC_0F_3A, "Set CPU mode" },
1512 { PCCC_FNC_0F_41, "Disable forces" },
1513 { PCCC_FNC_0F_50, "Download all request" },
1514 { PCCC_FNC_0F_52, "Download completed" },
1515 { PCCC_FNC_0F_53, "Upload all request (upload)" },
1516 { PCCC_FNC_0F_55, "Upload completed" },
1517 { PCCC_FNC_0F_57, "Initialize memory" },
1518 { PCCC_FNC_0F_5E, "Modify PLC-2 compatibility file" },
1519 { PCCC_FNC_0F_67, "Typed write" },
1520 { PCCC_FNC_0F_68, "Typed read" },
1521 { PCCC_FNC_0F_79, "Read-modify-write N" },
1522 { PCCC_FNC_0F_80, "Change CPU mode" },
1523 { PCCC_FNC_0F_81, "Open file" },
1524 { PCCC_FNC_0F_82, "Close file" },
1525 { PCCC_FNC_0F_88, "Execute Multiple Commands" },
1526 { PCCC_FNC_0F_8F, "Apply port configuration" },
1527 { PCCC_FNC_0F_A1, "Protected typed logical read with two address fields" },
1528 { PCCC_FNC_0F_A2, "Protected typed logical read with three address fields" },
1529 { PCCC_FNC_0F_A7, "Protected typed file read" },
1530 { PCCC_FNC_0F_A9, "Protected typed logical write with two address fields" },
1531 { PCCC_FNC_0F_AA, "Protected typed logical write with three address fields" },
1532 { PCCC_FNC_0F_AB, "Protected typed logical masked-write with three address fields" },
1533 { PCCC_FNC_0F_AF, "Protected typed file write" },
1535 { 0, NULL }
1538 static value_string_ext cip_pccc_fnc_0f_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_0f_vals);
1540 /* Translate PCCC File Types */
1541 static const value_string cip_pccc_file_types_vals[] = {
1542 { PCCC_FILE_TYPE_LOGIC, "Ladder Logic File" },
1543 { PCCC_FILE_TYPE_CHANNEL_CONFIG, "Channel Configuration File" },
1544 { PCCC_FILE_TYPE_FUNCTION_ES1, "EtherNet/IP Function File" },
1545 { PCCC_FILE_TYPE_ONLINE_EDIT, "Online Editing File" },
1546 { PCCC_FILE_TYPE_FUNCTION_IOS, "IOS Function File" },
1547 { PCCC_FILE_TYPE_DATA_OUTPUT, "Output Data File" },
1548 { PCCC_FILE_TYPE_DATA_INPUT, "Input Data File" },
1549 { PCCC_FILE_TYPE_DATA_STATUS, "Status Data File" },
1550 { PCCC_FILE_TYPE_DATA_BINARY, "Binary Data File" },
1551 { PCCC_FILE_TYPE_DATA_TIMER, "Timer Data File" },
1552 { PCCC_FILE_TYPE_DATA_COUNTER, "Counter Data File" },
1553 { PCCC_FILE_TYPE_DATA_INTEGER, "Integer Data File" },
1554 { PCCC_FILE_TYPE_DATA_FLOAT, "Float Data File" },
1555 { PCCC_FILE_TYPE_FORCE_OUTPUT, "Output Force File" },
1556 { PCCC_FILE_TYPE_FORCE_INPUT, "Input Force File" },
1557 { PCCC_FILE_TYPE_FUNCTION_ES0, "ES0 Function File" },
1558 { PCCC_FILE_TYPE_FUNCTION_STI, "STI Function File" },
1559 { PCCC_FILE_TYPE_FUNCTION_EII, "EII Function File" },
1560 { PCCC_FILE_TYPE_FUNCTION_RTC, "RTC Function File" },
1561 { PCCC_FILE_TYPE_FUNCTION_BHI, "BHI Function File" },
1562 { PCCC_FILE_TYPE_FUNCTION_MMI, "Memory Module Function File" },
1563 { PCCC_FILE_TYPE_FUNCTION_LCD, "Built-in LCD Function File" },
1564 { PCCC_FILE_TYPE_FUNCTION_PTOX, "PTOX Function File" },
1565 { PCCC_FILE_TYPE_FUNCTION_PWMX, "PWMX Function File" },
1567 { 0, NULL }
1570 static value_string_ext cip_pccc_file_type_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_file_types_vals);
1572 /* Translate PCCC CPU Modes */
1573 #if 0
1574 static const value_string cip_pccc_cpu_mode_3a_vals[] = {
1575 { PCCC_CPU_3A_PROGRAM, "Remote Program" },
1576 { PCCC_CPU_3A_RUN, "Remote Run" },
1578 { 0, NULL }
1581 value_string_ext cip_pccc_cpu_mode_3a_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_cpu_mode_3a_vals);
1582 #endif
1584 static const value_string cip_pccc_cpu_mode_80_vals[] = {
1585 { PCCC_CPU_80_PROGRAM, "Remote Program" },
1586 { PCCC_CPU_80_RUN, "Remote Run" },
1587 { PCCC_CPU_80_TEST_CONT, "Remote Test Continuous" },
1588 { PCCC_CPU_80_TEST_SINGLE, "Remote Test Single" },
1589 { PCCC_CPU_80_TEST_DEBUG, "Remote Test Debug" },
1591 { 0, NULL }
1594 static value_string_ext cip_pccc_cpu_mode_80_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_cpu_mode_80_vals);
1596 /* Translate Vendor IDs */
1597 static const value_string cip_vendor_vals[] = {
1598 { 1, "Rockwell Automation/Allen-Bradley" },
1599 { 2, "Namco Controls Corp." },
1600 { 3, "Honeywell International Inc." },
1601 { 4, "Parker Hannifin Corporation" },
1602 { 5, "Rockwell Automation/Reliance Elec." },
1603 { 6, "Reserved" },
1604 { 7, "SMC Corporation" },
1605 { 8, "Molex Incorporated" },
1606 { 9, "Western Reserve Controls Inc." },
1607 { 10, "Advanced Micro Controls Inc. (AMCI)" },
1608 { 11, "ASCO Pneumatic Controls" },
1609 { 12, "Banner Engineering Corporation" },
1610 { 13, "Belden Wire & Cable Company" },
1611 { 14, "Cooper Interconnect" },
1612 { 16, "Daniel Woodhead Co." },
1613 { 17, "Dearborn Group Inc." },
1614 { 18, "Reserved" },
1615 { 19, "Helm Instrument Company" },
1616 { 20, "Huron Net Works" },
1617 { 21, "Belden Deutschland GmbH" },
1618 { 22, "Online Development, Inc. (OLDI)" },
1619 { 23, "Vorne Industries, Inc." },
1620 { 24, "ODVA" },
1621 { 25, "Reserved" },
1622 { 26, "Festo" },
1623 { 27, "Reserved" },
1624 { 28, "Reserved" },
1625 { 30, "Unico, Inc." },
1626 { 31, "Ross Controls" },
1627 { 33, "Reserved" },
1628 { 34, "Hohner Corp." },
1629 { 35, "Micro Mo Electronics, Inc." },
1630 { 36, "MKS Instruments, Inc." },
1631 { 37, "Yaskawa Electric America formerly Magnetek Drives" },
1632 { 38, "Reserved" },
1633 { 39, "AVG Automation (Uticor)" },
1634 { 40, "WAGO Corporation" },
1635 { 41, "Celerity, Inc." },
1636 { 42, "IMI Norgren Limited" },
1637 { 43, "BALLUFF" },
1638 { 44, "Yaskawa America, Inc." },
1639 { 45, "Eurotherm by Schneider Electric" },
1640 { 46, "ABB, Inc." },
1641 { 47, "Omron Corporation" },
1642 { 48, "TURCK" },
1643 { 49, "Grayhill Inc." },
1644 { 50, "Real Time Automation" },
1645 { 51, "Reserved" },
1646 { 52, "ASCO Numatics" },
1647 { 53, "LÃœTZE" },
1648 { 54, "Reserved" },
1649 { 55, "Reserved" },
1650 { 56, "Softing" },
1651 { 57, "Pepperl+Fuchs" },
1652 { 58, "Spectrum Controls, Inc." },
1653 { 59, "D.I.P. Inc. MKS Inst." },
1654 { 60, "Applied Motion Products, Inc." },
1655 { 61, "Sencon Inc." },
1656 { 62, "High Country Tek" },
1657 { 63, "SWAC Automation Consult GmbH" },
1658 { 64, "Clippard Instrument Laboratory" },
1659 { 65, "Reserved" },
1660 { 66, "Reserved" },
1661 { 67, "Reserved" },
1662 { 68, "Eaton Electrical" },
1663 { 69, "Reserved" },
1664 { 70, "Reserved" },
1665 { 71, "Toshiba Corporation" },
1666 { 72, "Control Technology Incorporated" },
1667 { 73, "TCS (NZ) Ltd." },
1668 { 74, "Hitachi, Ltd." },
1669 { 75, "ABB Robotics" },
1670 { 76, "NKE Corporation" },
1671 { 77, "Rockwell Software, Inc." },
1672 { 78, "Escort Memory Systems (A Datalogic Group Co.)" },
1673 { 79, "Leviton" },
1674 { 80, "Industrial Devices Corporation" },
1675 { 81, "IXXAT Automation GmbH" },
1676 { 82, "Mitsubishi Electric Automation, Inc." },
1677 { 83, "OPTO 22" },
1678 { 84, "Reserved" },
1679 { 85, "Reserved" },
1680 { 86, "Horner Electric" },
1681 { 87, "Buerkert Fluid Control Systems" },
1682 { 88, "Reserved" },
1683 { 89, "Industrial Indexing Systems, Inc." },
1684 { 90, "HMS Networks" },
1685 { 91, "Robicon" },
1686 { 92, "Helix Technology (Granville-Phillips)" },
1687 { 93, "Arlington Laboratory" },
1688 { 94, "Advantech Corporation" },
1689 { 95, "Square D Company" },
1690 { 96, "Digital Electronics Corp." },
1691 { 97, "Danfoss Drives A/S" },
1692 { 98, "Reserved" },
1693 { 99, "Reserved" },
1694 { 100, "AVENTICS" },
1695 { 101, "Applied Materials, Inc." },
1696 { 102, "SWCC Showa Cable Systems Co., Ltd." },
1697 { 103, "Pacific Scientific (API Controls Inc.)" },
1698 { 104, "Sharp Manufacturing Systems Corporation" },
1699 { 105, "Olflex Wire & Cable, Inc." },
1700 { 106, "Reserved" },
1701 { 107, "Unitrode" },
1702 { 108, "Beckhoff Automation" },
1703 { 109, "National Instruments" },
1704 { 110, "Mykrolis Corporation (Millipore)" },
1705 { 111, "International Motion Controls Corp." },
1706 { 112, "Reserved" },
1707 { 113, "SEG Kempen GmbH" },
1708 { 114, "Reserved" },
1709 { 115, "Reserved" },
1710 { 116, "Temposonics, LLC" },
1711 { 117, "Krones, Inc" },
1712 { 119, "EXOR Electronic R & D" },
1713 { 120, "SIEI S.p.A." },
1714 { 121, "KUKA Deutschland GmbH" },
1715 { 122, "Reserved" },
1716 { 123, "SEC (Samsung Electronics Co., Ltd)" },
1717 { 124, "Binary Electronics Ltd" },
1718 { 125, "Flexible Machine Controls" },
1719 { 126, "Reserved" },
1720 { 127, "ABB Inc. (Entrelec)" },
1721 { 128, "MAC Valves, Inc." },
1722 { 129, "AUMA Riester GmbH & Co. KG" },
1723 { 130, "JTEKT Corporation" },
1724 { 131, "Reserved" },
1725 { 132, "Reserved" },
1726 { 133, "Balogh T.A.G., Corporation" },
1727 { 134, "TR Electronic" },
1728 { 135, "UNIPULSE Corporation" },
1729 { 136, "Reserved" },
1730 { 137, "Reserved" },
1731 { 138, "Conxall Corporation Inc." },
1732 { 139, "Reserved" },
1733 { 140, "Reserved" },
1734 { 141, "Kuramo Electric Co., Ltd." },
1735 { 142, "Creative Micro Designs" },
1736 { 143, "GE Industrial Systems" },
1737 { 144, "Leybold GmbH" },
1738 { 145, "Siemens Energy & Automation/Drives" },
1739 { 146, "Kodensha Ltd" },
1740 { 147, "Motion Engineering, Inc." },
1741 { 148, "Honda Engineering Co., Ltd" },
1742 { 149, "EIM Valve Controls" },
1743 { 150, "Melec Inc." },
1744 { 151, "Sony Manufacturing Systems Corporation" },
1745 { 152, "North American Mfg." },
1746 { 153, "Watlow" },
1747 { 154, "Japan Radio Co., Ltd" },
1748 { 155, "NADEX Co., Ltd" },
1749 { 156, "Ametek Automation & Process Technologies" },
1750 { 157, "Facts, Inc." },
1751 { 158, "KVASER AB" },
1752 { 159, "IDEC Corporation" },
1753 { 160, "Mitsubishi Heavy Industries Ltd" },
1754 { 161, "Mitsubishi Electric Corporation" },
1755 { 162, "HORIBA STEC, Co., Ltd." },
1756 { 163, "esd electronics gmbh" },
1757 { 164, "DAIHEN Corporation" },
1758 { 165, "Tyco Valves & Controls/Keystone" },
1759 { 166, "EBARA Corporation" },
1760 { 168, "Reserved" },
1761 { 169, "Hokuyo Automatic Co., Ltd." },
1762 { 170, "Pyramid Solutions, Inc." },
1763 { 171, "Denso Wave Incorporated" },
1764 { 172, "HLS Hard-Line Solutions Inc" },
1765 { 173, "Caterpillar, Inc." },
1766 { 174, "PDL Electronics Ltd." },
1767 { 175, "Reserved" },
1768 { 176, "Red Lion" },
1769 { 177, "CANON ANELVA Corporation" },
1770 { 178, "Toyo Denki Seizo KK" },
1771 { 179, "Sanyo Denki Co., Ltd." },
1772 { 180, "Hitachi Metals, Ltd. (formerly Advanced Energy Japan K.K.)" },
1773 { 181, "Pilz GmbH & Co KG" },
1774 { 182, "Marsh Bellofram-Bellofram PCD Division" },
1775 { 183, "Reserved" },
1776 { 184, "M-SYSTEM Co., Ltd." },
1777 { 185, "Nissin Electric Co., Ltd." },
1778 { 186, "Hitachi Metals Ltd." },
1779 { 187, "Oriental Motor Co., Ltd" },
1780 { 188, "A&D Company Limited" },
1781 { 189, "Phasetronics, Inc." },
1782 { 190, "Cummins Engine Company" },
1783 { 191, "Deltron Inc." },
1784 { 192, "Geneer Corporation" },
1785 { 193, "Anatol Automation, Inc." },
1786 { 194, "Reserved" },
1787 { 195, "Reserved" },
1788 { 196, "Medar, Inc." },
1789 { 197, "XP Power LLC" },
1790 { 198, "Advanced Energy Industries, Inc." },
1791 { 199, "Reserved" },
1792 { 200, "DAIDEN Co., Ltd" },
1793 { 201, "CKD Corporation" },
1794 { 202, "Toyo Electric Corporation" },
1795 { 203, "Reserved" },
1796 { 204, "AuCom Electronics Ltd" },
1797 { 205, "Sinfonia Technology Co., Ltd." },
1798 { 206, "Vector Informatik GmbH" },
1799 { 207, "Reserved" },
1800 { 208, "Moog Inc." },
1801 { 209, "Contemporary Controls" },
1802 { 210, "Tokyo Sokki Kenkyujo Co., Ltd" },
1803 { 211, "Schenck Process Group" },
1804 { 212, "The Oilgear Company" },
1805 { 213, "Reserved" },
1806 { 214, "ASM Japan K.K." },
1807 { 215, "HIRATA Corp." },
1808 { 216, "Panasonic Industrial Devices SUNX Co., Ltd." },
1809 { 217, "Meidensha Corporation" },
1810 { 218, "NIDEC SANKYO CORPORATION (Sankyo Seiki Mfg. Co., Ltd)" },
1811 { 219, "KAMRO Corp." },
1812 { 220, "NSD Co., Ltd." },
1813 { 221, "EBARA Technologies Inc." },
1814 { 222, "Reserved" },
1815 { 223, "Reserved" },
1816 { 224, "SG Co., Ltd" },
1817 { 225, "Vaasa Institute of Technology" },
1818 { 226, "MKS Instruments (ENI Technology)" },
1819 { 227, "Tateyama System Laboratory Co., Ltd." },
1820 { 228, "QLOG Corporation" },
1821 { 229, "Matric Limited Inc." },
1822 { 230, "NSD Corporation" },
1823 { 231, "Reserved" },
1824 { 232, "Sumitomo Wiring Systems, Ltd" },
1825 { 233, "Group 3 Technology Ltd" },
1826 { 234, "CTI Cryogenics" },
1827 { 235, "POLSYS CORP" },
1828 { 236, "Ampere Inc." },
1829 { 237, "Reserved" },
1830 { 238, "Simplatroll Ltd" },
1831 { 239, "Reserved" },
1832 { 240, "Reserved" },
1833 { 241, "Leading Edge Design" },
1834 { 242, "Humphrey Products" },
1835 { 243, "Schneider Electric" },
1836 { 244, "Westlock Controls Corp." },
1837 { 245, "Nihon Weidmuller Co., Ltd" },
1838 { 246, "Brooks Instrument" },
1839 { 247, "Reserved" },
1840 { 248, "Eaton Industries GmbH (formerly Moeller GmbH)" },
1841 { 249, "Varian Vacuum Products" },
1842 { 250, "Yokogawa Electric Corporation" },
1843 { 251, "Electrical Design Daiyu Co., Ltd" },
1844 { 252, "Omron Software Co., Ltd." },
1845 { 253, "EDWARDS" },
1846 { 254, "Control Technology Corporation" },
1847 { 255, "Bosch Rexroth" },
1848 { 256, "TURCK (formerly InterlinkBT)" },
1849 { 257, "Control Techniques PLC" },
1850 { 258, "Hardy Process Solutions" },
1851 { 259, "LS ELECTRIC" },
1852 { 260, "E.O.A. Systems Inc." },
1853 { 261, "Reserved" },
1854 { 262, "New Cosmos Electric Co., Ltd." },
1855 { 263, "Sense Sense Eletronica LTDA" },
1856 { 264, "Xycom, Inc." },
1857 { 265, "Baldor Electric" },
1858 { 266, "Reserved" },
1859 { 267, "Patlite Corporation" },
1860 { 268, "Reserved" },
1861 { 269, "Mogami Wire & Cable Corporation" },
1862 { 270, "Welding Technology Corporation" },
1863 { 271, "Reserved" },
1864 { 272, "Deutschmann Automation GmbH" },
1865 { 273, "ICP Panel-Tec Inc." },
1866 { 274, "Bray International, Inc" },
1867 { 275, "Reserved" },
1868 { 276, "Status Technologies" },
1869 { 277, "Trio Motion Technology ltd" },
1870 { 278, "Sherrex Systems Ltd" },
1871 { 279, "Adept Technology, Inc." },
1872 { 280, "Spang Power Electronics" },
1873 { 281, "Reserved" },
1874 { 282, "Acrosser Technology Co., Ltd" },
1875 { 283, "Hilscher GmbH" },
1876 { 284, "IMAX Corporation" },
1877 { 285, "Electronic Innovation, Inc. (Falter Engineering)" },
1878 { 286, "Netlogic Inc." },
1879 { 287, "Bosch Rexroth AG" },
1880 { 288, "Reserved" },
1881 { 289, "Reserved" },
1882 { 290, "Murata Machinery Ltd." },
1883 { 291, "MTT Company Ltd." },
1884 { 292, "Kanematsu Semiconductor Corp." },
1885 { 293, "Takebishi Electric Sales Co." },
1886 { 294, "Tokyo Electron Device Ltd" },
1887 { 295, "PFU Limited" },
1888 { 296, "Hakko Automation Co., Ltd." },
1889 { 297, "Advanet Inc." },
1890 { 298, "Tokyo Electron Software Technologies Ltd." },
1891 { 299, "Reserved" },
1892 { 300, "Shinagawa Electric Wire Co., Ltd." },
1893 { 301, "Yokogawa M&C Corporation" },
1894 { 302, "KONAN Electric Co., Ltd." },
1895 { 303, "Binar Elektronik AB" },
1896 { 304, "Furukawa Electric Co." },
1897 { 305, "Cooper Energy Services" },
1898 { 306, "Schleicher GmbH & Co." },
1899 { 307, "Hirose Electric Co., Ltd" },
1900 { 308, "Western Servo Design Inc." },
1901 { 309, "ProSoft Technology" },
1902 { 310, "Reserved" },
1903 { 311, "Towa Shoko Co., Ltd" },
1904 { 312, "Kyopal Co., Ltd" },
1905 { 313, "Extron Co." },
1906 { 314, "Wieland Electric GmbH" },
1907 { 315, "SEW Eurodrive GmbH" },
1908 { 316, "Aera Corporation" },
1909 { 317, "STA Reutlingen" },
1910 { 318, "Reserved" },
1911 { 319, "Fuji Electric Group" },
1912 { 320, "Reserved" },
1913 { 321, "Reserved" },
1914 { 322, "ifm electronic gmbh" },
1915 { 323, "Reserved" },
1916 { 324, "IDEACOD-Hohner Automation S.A." },
1917 { 325, "CommScope Inc." },
1918 { 326, "Intelligent Platforms, LLC." },
1919 { 327, "Matsushita Electric Industrial Co., Ltd" },
1920 { 328, "Okaya Electronics Corporation" },
1921 { 329, "KASHIYAMA Industries, Ltd" },
1922 { 330, "JVC" },
1923 { 331, "Interface Corporation" },
1924 { 332, "Grape Systems Inc." },
1925 { 333, "Reserved" },
1926 { 334, "Reserved" },
1927 { 335, "Toshiba IT & Control Systems Corporation" },
1928 { 336, "Sanyo Machine Works, Ltd." },
1929 { 337, "Vansco Electronics Ltd." },
1930 { 338, "Dart Container Corp." },
1931 { 339, "Livingston & Co., Inc." },
1932 { 340, "Alfa Laval LKM as" },
1933 { 341, "BF ENTRON Ltd. (British Federal)" },
1934 { 342, "Bekaert Engineering NV" },
1935 { 343, "Ferran Scientific Inc." },
1936 { 344, "KEBA Industrial Automation GmbH" },
1937 { 345, "Endress + Hauser" },
1938 { 346, "Lincoln Electric Company" },
1939 { 347, "ABB ALSTOM Power UK Ltd. (EGT)" },
1940 { 348, "Berger Lahr GmbH" },
1941 { 349, "Reserved" },
1942 { 350, "Federal Signal Corp." },
1943 { 351, "Kawasaki Robotics (USA), Inc." },
1944 { 352, "Bently Nevada Corporation" },
1945 { 354, "FRABA Posital" },
1946 { 355, "Elsag Bailey, Inc." },
1947 { 356, "FANUC Robotics America" },
1948 { 357, "Reserved" },
1949 { 358, "Surface Combustion, Inc." },
1950 { 359, "Reserved" },
1951 { 360, "AILES Electronics Ind. Co., Ltd." },
1952 { 361, "Wonderware Corporation" },
1953 { 362, "Particle Measuring Systems, Inc." },
1954 { 363, "Reserved" },
1955 { 364, "Reserved" },
1956 { 365, "BITS Co., Ltd" },
1957 { 366, "Japan Aviation Electronics Industry Ltd" },
1958 { 367, "Keyence Corporation" },
1959 { 368, "Kuroda Precision Industries Ltd." },
1960 { 369, "Mitsubishi Electric Semiconductor Application" },
1961 { 370, "Nippon Seisen Cable, Ltd." },
1962 { 371, "Omron ASO Co., Ltd" },
1963 { 372, "Seiko Seiki Co., Ltd." },
1964 { 373, "Sumitomo Heavy Industries, Ltd." },
1965 { 374, "Tango Computer Service Corporation" },
1966 { 375, "Technology Service, Inc." },
1967 { 376, "Toshiba Information Systems (Japan) Corporation" },
1968 { 377, "TOSHIBA Schneider Inverter Corporation" },
1969 { 378, "Toyooki Kogyo Co., Ltd." },
1970 { 379, "XEBEC" },
1971 { 380, "Madison Cable Corporation" },
1972 { 381, "Hitati Engineering & Services Co., Ltd" },
1973 { 382, "TEM-TECH Lab Co., Ltd" },
1974 { 383, "International Laboratory Corporation" },
1975 { 384, "Dyadic Systems Co., Ltd." },
1976 { 385, "SETO Electronics Industry Co., Ltd" },
1977 { 386, "Tokyo Electron Kyushu Limited" },
1978 { 387, "KEI System Co., Ltd" },
1979 { 388, "Reserved" },
1980 { 389, "Asahi Engineering Co., Ltd" },
1981 { 390, "Contrex Inc." },
1982 { 391, "Paradigm Controls Ltd." },
1983 { 392, "Reserved" },
1984 { 393, "Ohm Electric Co., Ltd." },
1985 { 394, "RKC Instrument Inc." },
1986 { 395, "Suzuki Motor Corporation" },
1987 { 396, "Custom Servo Motors Inc." },
1988 { 397, "PACE Control Systems" },
1989 { 398, "Selectron Systems AG" },
1990 { 399, "Reserved" },
1991 { 400, "LINTEC Co., Ltd." },
1992 { 401, "Hitachi Cable Ltd." },
1993 { 402, "BUSWARE Direct" },
1994 { 403, "Eaton Electric B.V. (former Holec Holland N.V.)" },
1995 { 404, "VAT Vacuum Valves AG" },
1996 { 405, "Omron Robotics and Safety Technologies, Inc." },
1997 { 406, "Alfa Instrumentos Eletronicos Ltda" },
1998 { 407, "TWK Elektronik GmbH" },
1999 { 408, "ABB Welding Systems AB" },
2000 { 409, "BYSTRONIC Maschinen AG" },
2001 { 410, "Kimura Electric Co., Ltd" },
2002 { 411, "Nissei Plastic Industrial Co., Ltd" },
2003 { 412, "Reserved" },
2004 { 413, "Kistler-Morse" },
2005 { 414, "Proteus Industries Inc." },
2006 { 415, "IDC Corporation" },
2007 { 416, "Nordson Corporation" },
2008 { 417, "Rapistan Systems" },
2009 { 418, "LP-Elektronik GmbH" },
2010 { 419, "GERBI & FASE S.p.A.(Fase Saldatura)" },
2011 { 420, "Phoenix Digital Corporation" },
2012 { 421, "Z-World Engineering" },
2013 { 422, "Honda R&D Co., Ltd." },
2014 { 423, "Bionics Instrument Co., Ltd." },
2015 { 424, "Teknic, Incorporated" },
2016 { 425, "R.Stahl, Inc." },
2017 { 426, "Reserved" },
2018 { 427, "Ryco Graphic Manufacturing Inc." },
2019 { 428, "Giddings & Lewis, Inc." },
2020 { 429, "Koganei Corporation" },
2021 { 430, "Reserved" },
2022 { 431, "Nichigoh Communication Electric Wire Co., Ltd." },
2023 { 433, "Fujikura Ltd." },
2024 { 434, "AD Link Technology Inc." },
2025 { 435, "Valmet Flow Control Inc (formerly StoneL)" },
2026 { 436, "Computer Optical Products, Inc." },
2027 { 437, "CONOS Inc." },
2028 { 438, "Erhardt+Leimer GmbH" },
2029 { 439, "UNIQUE Co. Ltd" },
2030 { 440, "Roboticsware, Inc." },
2031 { 441, "Nachi Fujikoshi Corporation" },
2032 { 442, "Hengstler GmbH" },
2033 { 443, "Vacon Plc" },
2034 { 444, "SUNNY GIKEN Inc." },
2035 { 445, "Lenze Drive Systems GmbH" },
2036 { 446, "CD Systems B.V." },
2037 { 447, "FMT/Aircraft Gate Support Systems AB" },
2038 { 448, "Axiomatic Technologies Corp" },
2039 { 449, "Embedded System Products, Inc." },
2040 { 450, "Reserved" },
2041 { 451, "Mencom Corporation" },
2042 { 452, "Kollmorgen" },
2043 { 453, "Panasonic Connect Co., Ltd." },
2044 { 454, "Dengensha Mfg. Co. Ltd." },
2045 { 455, "Quinn Systems Ltd." },
2046 { 456, "Tellima Technology Ltd" },
2047 { 457, "MDT, Software" },
2048 { 458, "Taiwan Keiso Co., Ltd" },
2049 { 459, "Pinnacle Systems" },
2050 { 460, "Ascom Hasler Mailing Sys" },
2051 { 461, "INSTRUMAR Limited" },
2052 { 462, "Reserved" },
2053 { 463, "Navistar International Transportation Corp" },
2054 { 464, "TRUMPF Huettinger" },
2055 { 465, "OCM Technology Inc." },
2056 { 466, "Professional Supply Inc." },
2057 { 467, "Control Solutions" },
2058 { 468, "Baumer IVO GmbH & Co. KG" },
2059 { 469, "Worcester Controls Corporation" },
2060 { 470, "Pyramid Technical Consultants, Inc." },
2061 { 471, "Eilersen Electric A/S" },
2062 { 472, "Apollo Fire Detectors Limited" },
2063 { 473, "Avtron Manufacturing, Inc." },
2064 { 474, "Reserved" },
2065 { 475, "Tokyo Keiso Co., Ltd." },
2066 { 476, "Daishowa Swiki Co., Ltd." },
2067 { 477, "Kojima Instruments Inc." },
2068 { 478, "Shimadzu Corporation" },
2069 { 479, "Tatsuta Electric Wire & Cable Co., Ltd." },
2070 { 480, "MECS Corporation" },
2071 { 481, "Tahara Electric" },
2072 { 482, "JTEKT ELECTRONICS CORPORATION" },
2073 { 483, "Clever Devices" },
2074 { 484, "GCD Hardware & Software GmbH" },
2075 { 485, "Reserved" },
2076 { 486, "Miller Electric Mfg Co." },
2077 { 487, "GEA Tuchenhagen GmbH" },
2078 { 488, "Riken Keiki Co., Ltd." },
2079 { 489, "Keisokugiken Corporation" },
2080 { 490, "Fuji Machine Mfg. Co., Ltd" },
2081 { 491, "Reserved" },
2082 { 492, "Nidec-Shimpo Corp." },
2083 { 493, "UTEC Corporation" },
2084 { 494, "Sanyo Electric Co. Ltd." },
2085 { 495, "Reserved" },
2086 { 496, "Reserved" },
2087 { 497, "Okano Electric Wire Co. Ltd" },
2088 { 498, "Shimaden Co. Ltd." },
2089 { 499, "Teddington Controls Ltd" },
2090 { 500, "Reserved" },
2091 { 501, "YASKAWA Europe (formerly VIPA GmbH)" },
2092 { 502, "Warwick Manufacturing Group" },
2093 { 503, "Danaher Controls" },
2094 { 504, "Reserved" },
2095 { 505, "Reserved" },
2096 { 506, "American Science & Engineering" },
2097 { 507, "Accutron Controls International Inc." },
2098 { 508, "Norcott Technologies Ltd" },
2099 { 509, "TB Woods, Inc" },
2100 { 510, "Proportion-Air, Inc." },
2101 { 511, "SICK Stegmann GmbH" },
2102 { 512, "Reserved" },
2103 { 513, "Edwards Signaling" },
2104 { 514, "Sumitomo Metal Industries, Ltd" },
2105 { 515, "Cosmo Instruments Co., Ltd." },
2106 { 516, "Denshosha Co., Ltd." },
2107 { 517, "Kaijo Corp." },
2108 { 518, "Michiproducts Co., Ltd." },
2109 { 519, "Miura Corporation" },
2110 { 520, "TG Information Network Co., Ltd." },
2111 { 521, "Fujikin, Inc." },
2112 { 522, "Estic Corp." },
2113 { 523, "GS Hydraulic Sales" },
2114 { 524, "Leuze Electronic GmbH & Co. KG" },
2115 { 525, "MTE Limited" },
2116 { 526, "Hyde Park Electronics, Inc." },
2117 { 527, "Pfeiffer Vacuum GmbH" },
2118 { 528, "Cyberlogic Technologies" },
2119 { 529, "OKUMA Corporation FA Systems Division" },
2120 { 530, "Reserved" },
2121 { 531, "Kokusai Electric Corporation" },
2122 { 532, "SHINKO TECHNOS" },
2123 { 533, "Itoh Denki Co., Ltd." },
2124 { 534, "Colorado Flow Tech Inc." },
2125 { 535, "Love Controls Division/Dwyer Inst." },
2126 { 536, "Alstom Drives and Controls" },
2127 { 537, "The Foxboro Company" },
2128 { 538, "Tescom Corporation" },
2129 { 539, "Reserved" },
2130 { 540, "Atlas Copco Airpower NV" },
2131 { 541, "Reserved" },
2132 { 542, "Autojet Technologies" },
2133 { 543, "Prima Electronics S.p.A." },
2134 { 544, "PMA GmbH" },
2135 { 545, "Shimafuji Electric Co., Ltd" },
2136 { 546, "Oki Electric Industry Co., Ltd" },
2137 { 547, "Kyushu Matsushita Electric Co., Ltd" },
2138 { 548, "JMACS" },
2139 { 549, "Tsuken Electric Ind Co., Ltd" },
2140 { 550, "Tamadic Co." },
2141 { 551, "MAATEL SA" },
2142 { 552, "OKUMA America" },
2143 { 553, "Control Techniques PLC-NA" },
2144 { 554, "TPC Wire & Cable" },
2145 { 555, "ATI Industrial Automation" },
2146 { 556, "Microcontrol (Australia) Pty Ltd" },
2147 { 557, "Serra Soldadura, S.A." },
2148 { 558, "Southwest Research Institute" },
2149 { 559, "Cabinplant International" },
2150 { 560, "Minebea Intec" },
2151 { 561, "Comau S.p.A." },
2152 { 562, "Phoenix Contact" },
2153 { 563, "Yokogawa MAT Corporation" },
2154 { 564, "asahi sangyo co., ltd." },
2155 { 565, "Valcom" },
2156 { 566, "Akita Myotoku Ltd." },
2157 { 567, "OBARA Corp." },
2158 { 568, "Suetron Electronic GmbH" },
2159 { 569, "Reserved" },
2160 { 570, "Serck Controls Limited" },
2161 { 571, "Fairchild Industrial Products Company" },
2162 { 572, "ARO Welding Technologies S.A.S." },
2163 { 573, "M2C GmbH" },
2164 { 574, "Shin Caterpillar Mitsubishi Ltd." },
2165 { 575, "Santest Co., Ltd." },
2166 { 576, "Cosmotechs Co., Ltd." },
2167 { 577, "Hitachi Electric Systems" },
2168 { 578, "Smartscan Ltd" },
2169 { 579, "Woodhead Software & Electronics France" },
2170 { 580, "Athena Controls, Inc." },
2171 { 581, "Norgren Automation Solutions, LLC (previously Syron Engineering & Manufacturing, Inc.)" },
2172 { 582, "Asahi Optical Co., Ltd." },
2173 { 583, "Sansha Electric Mfg. Co.,Ltd." },
2174 { 584, "CKD Nikki Denso Co,. Ltd." },
2175 { 585, "Star Micronics, Co., Ltd." },
2176 { 586, "Ecotecnia Socirtat Corp." },
2177 { 587, "Lenze" },
2178 { 588, "West Instruments Limited" },
2179 { 589, "LinMot" },
2180 { 590, "Delta Computer Systems, Inc." },
2181 { 591, "FANUC CORPORATION" },
2182 { 592, "Hearn-Gu Lee" },
2183 { 593, "ABB AG" },
2184 { 594, "Orion Machinery Co., Ltd." },
2185 { 595, "Reserved" },
2186 { 596, "Wire-Pro, Inc." },
2187 { 597, "Beijing Huakong Technology Co. Ltd." },
2188 { 598, "Yokoyama Shokai Co., Ltd." },
2189 { 599, "Toyogiken Co., Ltd." },
2190 { 600, "Coester Equipamentos Eletronicos Ltda." },
2191 { 601, "Kawasaki Robot" },
2192 { 602, "Electroplating Engineers of Japan Ltd." },
2193 { 603, "Robox S.p.a." },
2194 { 604, "Spraying Systems Company" },
2195 { 605, "Benshaw Inc." },
2196 { 606, "ZPA-DP A.S." },
2197 { 607, "Wired Rite Systems" },
2198 { 608, "Tandis Research, Inc." },
2199 { 609, "SSD Drives GmbH" },
2200 { 610, "ULVAC Japan Ltd." },
2201 { 611, "DYNAX Corporation" },
2202 { 612, "Nor-Cal Products, Inc." },
2203 { 613, "Aros Electronics AB" },
2204 { 614, "Jun-Tech Co., Ltd." },
2205 { 615, "HAN-MI Co. Ltd." },
2206 { 616, "uniNtech (formerly SungGi Internet)" },
2207 { 617, "Hae Pyung Electronics Reserch Institute" },
2208 { 618, "Milwaukee Electronics" },
2209 { 619, "OBERG Industries" },
2210 { 620, "Parker Hannifin/Compumotor Division" },
2211 { 621, "TECHNO DIGITAL CORPORATION" },
2212 { 622, "Network Supply Co., Ltd." },
2213 { 623, "Union Electronics Co., Ltd." },
2214 { 624, "Tritronics Services PM Ltd." },
2215 { 625, "Rockwell Automation/Sprecher+Schuh" },
2216 { 626, "Panasonic Corporation/Motor Company" },
2217 { 627, "Rolls-Royce Energy Systems, Inc." },
2218 { 628, "JEONGIL INTERCOM CO., LTD" },
2219 { 629, "Interroll Software & Electronics GmbH" },
2220 { 630, "Hubbell Wiring Device-Kellems (Delaware)" },
2221 { 631, "Intelligent Motion Systems" },
2222 { 632, "Reserved" },
2223 { 633, "INFICON AG" },
2224 { 634, "Hirschmann, a Belden brand" },
2225 { 635, "The Siemon Company" },
2226 { 636, "YAMAHA Motor Co. Ltd." },
2227 { 637, "aska corporation" },
2228 { 638, "Woodhead Connectivity" },
2229 { 639, "Trimble AB" },
2230 { 640, "Murrelektronik GmbH" },
2231 { 641, "Creatrix Labs, Inc." },
2232 { 642, "TopWorx" },
2233 { 643, "Kumho Industrial Co., Ltd." },
2234 { 644, "Wind River Systems, Inc." },
2235 { 645, "Bihl + Wiedemann GmbH" },
2236 { 646, "Harmonic Drive Systems Inc." },
2237 { 647, "Rikei Corporation" },
2238 { 648, "BL Autotec, Ltd." },
2239 { 649, "Hana Information & Technology Co., Ltd." },
2240 { 650, "Seoil Electric Co., Ltd." },
2241 { 651, "Fife Corporation" },
2242 { 652, "Shanghai Electrical Apparatus Research Institute" },
2243 { 653, "Detector Electronics" },
2244 { 654, "Parasense Development Centre" },
2245 { 655, "Reserved" },
2246 { 656, "Reserved" },
2247 { 657, "Six Tau S.p.A." },
2248 { 658, "Aucos GmbH" },
2249 { 659, "Rotork Controls Ltd." },
2250 { 660, "Automationdirect.com" },
2251 { 661, "Thermo BLH" },
2252 { 662, "System Controls, Ltd." },
2253 { 663, "Univer S.p.A." },
2254 { 664, "MKS-Tenta Technology" },
2255 { 665, "Lika Electronic" },
2256 { 666, "Mettler-Toledo" },
2257 { 667, "DXL USA Inc." },
2258 { 668, "Rockwell Automation/Entek IRD Intl." },
2259 { 669, "Nippon Otis Elevator Company" },
2260 { 670, "Sinano Electric, Co., Ltd." },
2261 { 671, "Sony Manufacturing Systems" },
2262 { 672, "Reserved" },
2263 { 673, "CONTEC CO., LTD." },
2264 { 674, "Automated Solutions" },
2265 { 675, "Controlweigh" },
2266 { 677, "Fincor Electronics" },
2267 { 678, "Cognex Corporation" },
2268 { 679, "Qualiflow" },
2269 { 680, "Weidmuller, Inc." },
2270 { 681, "Morinaga Milk Industry Co., Ltd." },
2271 { 682, "Takagi Industrial Co., Ltd." },
2272 { 683, "Wittenstein SE" },
2273 { 684, "Sena Technologies, Inc." },
2274 { 685, "Reserved" },
2275 { 686, "SPX Flow Technology Germany GmbH" },
2276 { 687, "Creator Teknisk Utvedkling AB" },
2277 { 688, "Reserved" },
2278 { 689, "Mibu Denki Industrial Co., Ltd." },
2279 { 690, "Takamastsu Machineer Section" },
2280 { 691, "Littelfuse" },
2281 { 692, "Reserved" },
2282 { 693, "Holjeron" },
2283 { 694, "Pfeiffer Vacuum SAS" },
2284 { 695, "Taesan LCD Co., Ltd." },
2285 { 696, "POSCON" },
2286 { 697, "VMIC" },
2287 { 698, "Matsushita Electric Works, Ltd." },
2288 { 699, "IAI Corporation" },
2289 { 700, "Horst GmbH" },
2290 { 701, "MicroControl GmbH & Co." },
2291 { 702, "Leine & Linde AB" },
2292 { 703, "Reserved" },
2293 { 704, "EC Elettronica Srl" },
2294 { 705, "VIT Software HB" },
2295 { 706, "Bronkhorst High-Tech B.V." },
2296 { 707, "Optex Co., Ltd." },
2297 { 708, "Yosio Electronic Co." },
2298 { 709, "Terasaki Electric Co., Ltd." },
2299 { 710, "Sodick Co., Ltd." },
2300 { 711, "MTS Systems Corporation-Automation Division" },
2301 { 712, "Mesa Systemtechnik" },
2302 { 713, "SHIN HO SYSTEM Co., Ltd." },
2303 { 714, "Goyo Electronics Co, Ltd." },
2304 { 715, "Loreme" },
2305 { 716, "SAB Brockskes GmbH & Co. KG" },
2306 { 717, "Trumpf Laser GmbH" },
2307 { 718, "Niigata Electronic Instruments Co., Ltd." },
2308 { 719, "Yokogawa Digital Computer Corporation" },
2309 { 720, "O.N. Electronic Co., Ltd." },
2310 { 721, "Industrial Control Communication, Inc." },
2311 { 722, "ABB, Inc." },
2312 { 723, "ElectroWave USA, Inc." },
2313 { 724, "Industrial Network Controls, LLC" },
2314 { 725, "KDT Systems Co., Ltd." },
2315 { 726, "SEFA Technology Inc." },
2316 { 727, "Nippon POP Rivets and Fasteners Ltd." },
2317 { 728, "Yamato Scale Co., Ltd." },
2318 { 729, "Zener Electric" },
2319 { 730, "GSE Scale Systems" },
2320 { 731, "ISAS (Integrated Switchgear & Sys. Pty Ltd)" },
2321 { 732, "Beta LaserMike Limited" },
2322 { 733, "TOEI Electric Co., Ltd." },
2323 { 734, "Hakko Electronics Co., Ltd" },
2324 { 735, "Reserved" },
2325 { 736, "RFID, Inc." },
2326 { 737, "Adwin Corporation" },
2327 { 738, "Osaka Vacuum, Ltd." },
2328 { 739, "A-Kyung Motion, Inc." },
2329 { 740, "Camozzi Automation spa" },
2330 { 741, "Crevis Co., LTD" },
2331 { 742, "Rice Lake Weighing Systems" },
2332 { 743, "Linux Network Services" },
2333 { 744, "KEB Automation KG" },
2334 { 745, "Hagiwara Electric Co., Ltd." },
2335 { 746, "Glass Inc. International" },
2336 { 748, "DVT Corporation" },
2337 { 749, "Woodward Governor" },
2338 { 750, "Mosaic Systems, Inc." },
2339 { 751, "Laserline GmbH" },
2340 { 752, "COM-TEC, Inc." },
2341 { 753, "Weed Instrument" },
2342 { 754, "Prof-face European Technology Center" },
2343 { 755, "Fuji Automation Co., Ltd." },
2344 { 756, "Matsutame Co., Ltd." },
2345 { 757, "Hitachi Via Mechanics, Ltd." },
2346 { 758, "Dainippon Screen Mfg. Co. Ltd." },
2347 { 759, "FLS Automation A/S" },
2348 { 760, "ABB Stotz Kontakt GmbH" },
2349 { 761, "Technical Marine Service" },
2350 { 762, "Advanced Automation Associates, Inc." },
2351 { 763, "Baumer Ident GmbH" },
2352 { 764, "Tsubakimoto Chain Co." },
2353 { 765, "Reserved" },
2354 { 766, "Furukawa Co., Ltd." },
2355 { 767, "Active Power" },
2356 { 768, "CSIRO Mining Automation" },
2357 { 769, "Matrix Integrated Systems" },
2358 { 770, "Digitronic Automationsanlagen GmbH" },
2359 { 771, "SICK STEGMANN Inc." },
2360 { 772, "TAE-Antriebstechnik GmbH" },
2361 { 773, "Electronic Solutions" },
2362 { 774, "Rocon L.L.C." },
2363 { 775, "Dijitized Communications Inc." },
2364 { 776, "Asahi Organic Chemicals Industry Co., Ltd." },
2365 { 777, "Hodensha" },
2366 { 778, "HARTING, Inc. of North America" },
2367 { 779, "Kuebler GmbH" },
2368 { 780, "Yamatake Corporation" },
2369 { 781, "JEOL" },
2370 { 782, "Yamatake Industrial Systems Co., Ltd." },
2371 { 783, "HAEHNE Elektronische Messgerate GmbH" },
2372 { 784, "Ci Technologies Pty Ltd (for Pelamos Industries)" },
2373 { 785, "N. SCHLUMBERGER & CIE" },
2374 { 786, "Teijin Seiki Co., Ltd." },
2375 { 787, "DAIKIN Industries, Ltd" },
2376 { 788, "RyuSyo Industrial Co., Ltd." },
2377 { 789, "SAGINOMIYA SEISAKUSHO, INC." },
2378 { 790, "Seishin Engineering Co., Ltd." },
2379 { 791, "Japan Support System Ltd." },
2380 { 792, "Decsys" },
2381 { 793, "Metronix Messgeraete und Elektronik GmbH" },
2382 { 794, "ROPEX Industrie - Elektronik GmbH" },
2383 { 795, "Vaccon Company, Inc." },
2384 { 796, "Siemens Industry, Inc." },
2385 { 797, "Ten X Technology, Inc." },
2386 { 798, "TE Connectivity" },
2387 { 799, "Delta Electronics, Inc." },
2388 { 800, "Denker" },
2389 { 801, "Autonics Corporation" },
2390 { 802, "JFE Electronic Engineering Pty. Ltd." },
2391 { 803, "Reserved" },
2392 { 804, "Electro-Sensors, Inc." },
2393 { 805, "Digi International, Inc." },
2394 { 806, "Texas Instruments" },
2395 { 807, "ADTEC Plasma Technology Co., Ltd" },
2396 { 808, "SICK AG" },
2397 { 809, "Ethernet Peripherals, Inc." },
2398 { 810, "Animatics Corporation" },
2399 { 811, "Reserved" },
2400 { 812, "Process Control Corporation" },
2401 { 813, "SystemV. Inc." },
2402 { 814, "Danaher Motion SRL" },
2403 { 815, "SHINKAWA Sensor Technology, Inc." },
2404 { 816, "Tesch GmbH & Co. KG" },
2405 { 817, "Reserved" },
2406 { 818, "Trend Controls Systems Ltd." },
2407 { 819, "Guangzhou ZHIYUAN Electronic Co., Ltd." },
2408 { 820, "Mykrolis Corporation" },
2409 { 821, "Bethlehem Steel Corporation" },
2410 { 822, "KK ICP" },
2411 { 823, "Takemoto Denki Corporation" },
2412 { 824, "Montalvo Corporation" },
2413 { 825, "Reserved" },
2414 { 826, "LEONI Special Cables GmbH" },
2415 { 827, "Reserved" },
2416 { 828, "ONO SOKKI CO.,LTD." },
2417 { 829, "RS Automation Co., Ltd." },
2418 { 830, "SHINDENGEN ELECTRIC MFG. CO. LTD" },
2419 { 831, "Origin Electric Co. Ltd." },
2420 { 832, "Quest Technical Solutions, Inc." },
2421 { 833, "LS Cable" },
2422 { 834, "NORD Electronic DRIVESYSTEMS GmbH" },
2423 { 835, "Northwire Inc." },
2424 { 836, "Engel Elektroantriebe GmbH" },
2425 { 837, "The Stanley Works" },
2426 { 838, "Celesco Transducer Products, Inc." },
2427 { 839, "Chugoku Electric Wire and Cable Co." },
2428 { 840, "Kongsberg Simrad AS" },
2429 { 841, "Panduit Corporation" },
2430 { 842, "Spellman High Voltage Electronics Corp." },
2431 { 843, "Kokusai Electric Alpha Co., Ltd." },
2432 { 844, "Brooks Automation, Inc." },
2433 { 845, "ANYWIRE CORPORATION" },
2434 { 846, "Honda Electronics Co. Ltd" },
2435 { 847, "REO AG" },
2436 { 848, "Heraeus Noblelight Fusion UV Inc." },
2437 { 849, "ASI Advanced Semiconductor Instruments GmbH" },
2438 { 850, "Datalogic, Inc." },
2439 { 851, "SoftPLC Corporation" },
2440 { 852, "Dynisco Instruments LLC" },
2441 { 853, "WEG" },
2442 { 854, "Teledyne LeCroy (formerly Frontline Test Equipment)" },
2443 { 855, "Tamagawa Seiki Co., Ltd." },
2444 { 856, "Multi Computing Co., Ltd." },
2445 { 857, "RVSI" },
2446 { 858, "Commercial Timesharing Inc." },
2447 { 859, "Tennessee Rand Automation LLC" },
2448 { 860, "Wacogiken Co., Ltd" },
2449 { 861, "Reflex Integration Inc." },
2450 { 862, "Siemens AG, A&D PI Flow Instruments" },
2451 { 863, "G. Bachmann Electronic GmbH" },
2452 { 864, "Entegris, Inc." },
2453 { 865, "Schweitzer Engineering Laboratories" },
2454 { 866, "ATR Industrie-Elektronik GmbH Co." },
2455 { 867, "PLASMATECH Co., Ltd" },
2456 { 868, "Reserved" },
2457 { 869, "GEMUE GmbH & Co. KG" },
2458 { 870, "Alcorn McBride Inc." },
2459 { 871, "MORI SEIKI CO., LTD" },
2460 { 872, "NodeTech Systems Ltd" },
2461 { 873, "Emhart Teknologies" },
2462 { 874, "Cervis, Inc." },
2463 { 875, "MSA Safety" },
2464 { 876, "NEDAP Power Supplies" },
2465 { 877, "Nippon Sanso Corporation" },
2466 { 878, "Mitomi Giken Co., Ltd." },
2467 { 879, "PULS GmbH" },
2468 { 880, "Reserved" },
2469 { 881, "Japan Control Engineering Ltd" },
2470 { 882, "Embedded Systems Korea (Former Zues Emtek Co Ltd.)" },
2471 { 883, "Automa SRL" },
2472 { 884, "Harms+Wende GmbH & Co KG" },
2473 { 885, "R. STAHL" },
2474 { 886, "Microwave Data Systems" },
2475 { 887, "Bernecker + Rainer Industrie-Elektronik GmbH" },
2476 { 888, "Hiprom Technologies" },
2477 { 889, "Reserved" },
2478 { 890, "Nitta Corporation" },
2479 { 891, "Kontron Modular Computers GmbH" },
2480 { 892, "Marlin Controls" },
2481 { 893, "Elcis Encoder s.r.l." },
2482 { 894, "Acromag, Inc." },
2483 { 895, "Avery Weigh-Tronix" },
2484 { 896, "Reserved" },
2485 { 897, "Reserved" },
2486 { 899, "Practicon Ltd." },
2487 { 900, "SCHUNK GmbH & Co. KG" },
2488 { 901, "MYNAH Technologies" },
2489 { 902, "Defontaine Groupe" },
2490 { 903, "Emerson Process Management Power & Water Solutions" },
2491 { 904, "F.A. Elec" },
2492 { 905, "Hottinger Baldwin Messtechnik GmbH" },
2493 { 906, "Teledyne DALSA" },
2494 { 907, "London Electronics Ltd." },
2495 { 908, "HSD SpA" },
2496 { 909, "Pepperl+Fuchs Comtrol" },
2497 { 910, "TEAM, S.A. (Tecnica Electronica de Automatismo Y Medida)" },
2498 { 911, "Regulateurs Europa Ltd" },
2499 { 912, "Reserved" },
2500 { 913, "Reserved" },
2501 { 914, "Micro Motion" },
2502 { 915, "Eckelmann AG" },
2503 { 916, "Hanyoung Nux" },
2504 { 917, "CFT Ransburg Japan KK" },
2505 { 918, "Kun Hung Electric Co. Ltd." },
2506 { 919, "Brimos wegbebakening b.v." },
2507 { 920, "NITTO SEIKO CO., LTD." },
2508 { 921, "Datasensing S.r.l." },
2509 { 922, "Yamazaki Machinery Works" },
2510 { 923, "Schmidt Technology" },
2511 { 924, "Parker Hannifin SpA (SBC Division)" },
2512 { 925, "HIMA Paul Hildebrandt GmbH" },
2513 { 926, "RivaTek, Inc." },
2514 { 927, "Misumi Corporation" },
2515 { 928, "GE Multilin" },
2516 { 929, "Measurement Computing Corporation" },
2517 { 930, "Jetter AG" },
2518 { 931, "Tokyo Electronics Systems Corporation" },
2519 { 932, "Togami Electric Mfg. Co., Ltd." },
2520 { 933, "HK Systems" },
2521 { 934, "CDA Systems Ltd." },
2522 { 935, "Aerotech Inc." },
2523 { 936, "JVL A/S" },
2524 { 937, "NovaTech Process Solutions LLC" },
2525 { 938, "Reserved" },
2526 { 939, "Cisco Systems" },
2527 { 940, "Grid Connect" },
2528 { 941, "ITW Automotive Finishing" },
2529 { 942, "HanYang System" },
2530 { 943, "ABB K.K. Technical Center" },
2531 { 944, "Taiyo Cable (Dongguan) Co., Ltd." },
2532 { 945, "Reserved" },
2533 { 946, "SEREN IPS INC" },
2534 { 947, "Belden" },
2535 { 948, "ControlNet International" },
2536 { 949, "Gefran S.P.A." },
2537 { 950, "ABB (Jokab Safety)" },
2538 { 951, "SUMITA OPTICAL GLASS, INC." },
2539 { 952, "Biffi Italia srl" },
2540 { 953, "Beck IPC GmbH" },
2541 { 954, "Copley Controls" },
2542 { 955, "Fagor Automation S. Coop." },
2543 { 956, "DARCOM" },
2544 { 957, "Frick Controls (div. of York International)" },
2545 { 958, "SymCom, Inc." },
2546 { 959, "Infranor" },
2547 { 960, "Kyosan Electric Mfg" },
2548 { 961, "Varian Vacuum Technologies" },
2549 { 962, "Messung Systems" },
2550 { 963, "Xantrex Technology, Inc." },
2551 { 964, "StarThis Inc." },
2552 { 965, "NF Chiyoda Electronics Co., Ltd." },
2553 { 966, "Flowserve Corporation" },
2554 { 967, "Spyder Controls Corp." },
2555 { 968, "IBA AG" },
2556 { 969, "SHIMOHIRA ELECTRIC MFG.CO.,LTD" },
2557 { 970, "Reserved" },
2558 { 971, "Siemens L&A" },
2559 { 972, "Eaton Automation GmbH (formerly Micro Innovation)" },
2560 { 973, "Switchgear & Instrumentation" },
2561 { 974, "Pre-Tech Co., Ltd." },
2562 { 975, "National Semiconductor" },
2563 { 976, "Invensys Operations Management" },
2564 { 977, "Ametek HDR Power Systems" },
2565 { 978, "Reserved" },
2566 { 979, "TETRA-K Corporation" },
2567 { 980, "C&M Corporation" },
2568 { 981, "Siempelkamp Maschinen" },
2569 { 982, "Reserved" },
2570 { 983, "Daifuku Co., Ltd" },
2571 { 984, "Electro-Matic Products Inc." },
2572 { 985, "BUSSAN MICROELECTRONICS CORP." },
2573 { 986, "ELAU AG" },
2574 { 987, "Hetronic USA" },
2575 { 988, "NIIGATA POWER SYSTEMS Co., Ltd." },
2576 { 989, "Software Horizons Inc." },
2577 { 990, "B3 Systems, Inc." },
2578 { 991, "Moxa, Inc." },
2579 { 992, "Reserved" },
2580 { 993, "S4 Integration" },
2581 { 994, "Elettro Stemi S.R.L." },
2582 { 995, "AquaSensors" },
2583 { 996, "Ifak System GmbH" },
2584 { 997, "SANKEI MANUFACTURING Co.,LTD." },
2585 { 998, "Emerson Network Power Co., Ltd." },
2586 { 999, "Fairmount Automation, Inc." },
2587 { 1000, "Bird Electronic Corporation" },
2588 { 1001, "Nabtesco Corporation" },
2589 { 1002, "AGM Electronics, Inc." },
2590 { 1003, "ARCX Inc." },
2591 { 1004, "DELTA I/O Co." },
2592 { 1005, "Chun IL Electric Ind. Co." },
2593 { 1006, "N-Tron Corporation, a Red Lion Company" },
2594 { 1007, "Nippon Pneumatics/Fludics System CO.,LTD." },
2595 { 1008, "DDK Ltd." },
2596 { 1009, "Seiko Epson Corporation" },
2597 { 1010, "halstrup-walcher GmbH" },
2598 { 1011, "ITT" },
2599 { 1012, "Ground Fault Systems bv" },
2600 { 1013, "Scolari Engineering S.p.A." },
2601 { 1014, "Vialis Traffic bv" },
2602 { 1015, "Weidmueller Group" },
2603 { 1016, "Shanghai Sibotech Automation Co. Ltd" },
2604 { 1017, "AEG Power Solutions GmbH" },
2605 { 1018, "Komatsu Electronics Inc." },
2606 { 1019, "Souriau" },
2607 { 1020, "Baumuller Chicago Corp." },
2608 { 1021, "J. Schmalz GmbH" },
2609 { 1022, "SEN Corporation" },
2610 { 1023, "Korenix Technology Co. Ltd" },
2611 { 1024, "Cooper Power Tools" },
2612 { 1025, "INNOBIS" },
2613 { 1026, "Shinho System" },
2614 { 1027, "Xm Services Ltd." },
2615 { 1028, "KVC Co., Ltd." },
2616 { 1029, "Sanyu Seiki Co., Ltd." },
2617 { 1030, "TuxPLC" },
2618 { 1031, "Northern Network Solutions" },
2619 { 1032, "Converteam GmbH" },
2620 { 1033, "Symbol Technologies" },
2621 { 1034, "S-TEAM Lab" },
2622 { 1035, "Maguire Products, Inc." },
2623 { 1036, "AC&T" },
2624 { 1037, "MITSUBISHI HEAVY INDUSTRIES, LTD. KOBE SHIPYARD & MACHINERY WORKS" },
2625 { 1038, "Hurletron Inc." },
2626 { 1039, "Chunichi Denshi Co., Ltd" },
2627 { 1040, "Cardinal Scale Mfg. Co." },
2628 { 1041, "METZ CONNECT USA Inc." },
2629 { 1042, "Base2" },
2630 { 1043, "ASRC Aerospace" },
2631 { 1044, "Beijing Stone Automation" },
2632 { 1045, "Changshu Switchgear Manufacture Ltd." },
2633 { 1046, "METRONIX Corp." },
2634 { 1047, "WIT" },
2635 { 1048, "ORMEC Systems Corp." },
2636 { 1049, "ASATech (China) Inc." },
2637 { 1050, "Controlled Systems Limited" },
2638 { 1051, "Mitsubishi Heavy Ind. Digital System Co., Ltd. (M.H.I.)" },
2639 { 1052, "Electrogrip" },
2640 { 1053, "TDS Automation" },
2641 { 1054, "T&C Power Conversion, Inc." },
2642 { 1055, "Robostar Co., Ltd" },
2643 { 1056, "Scancon A/S" },
2644 { 1057, "Haas Automation, Inc." },
2645 { 1058, "Eshed Technology" },
2646 { 1059, "Delta Electronic Inc." },
2647 { 1060, "Innovasic" },
2648 { 1061, "SoftDEL Systems Limited" },
2649 { 1062, "FiberFin, Inc." },
2650 { 1063, "Nicollet Technologies Corp." },
2651 { 1064, "B.F. Systems" },
2652 { 1065, "Empire Wire and Supply LLC" },
2653 { 1066, "ENDO KOGYO CO., LTD" },
2654 { 1067, "Elmo Motion Control LTD" },
2655 { 1068, "Reserved" },
2656 { 1069, "Asahi Keiki Co., Ltd." },
2657 { 1070, "Joy Mining Machinery" },
2658 { 1071, "MPM Engineering Ltd." },
2659 { 1072, "Wolke Inks & Printers GmbH" },
2660 { 1073, "Mitsubishi Electric Engineering Co., Ltd." },
2661 { 1074, "COMET AG" },
2662 { 1075, "Real Time Objects & Systems, LLC" },
2663 { 1076, "MISCO Refractometer" },
2664 { 1077, "JT Engineering Inc." },
2665 { 1078, "Automated Packing Systems" },
2666 { 1079, "Niobrara R&D Corp." },
2667 { 1080, "Garmin Ltd." },
2668 { 1081, "Japan Mobile Platform Co., Ltd" },
2669 { 1082, "Advosol Inc." },
2670 { 1083, "ABB Global Services Limited" },
2671 { 1084, "Sciemetric Instruments Inc." },
2672 { 1085, "Tata Elxsi Ltd." },
2673 { 1086, "Mechatronics Co.,Ltd" },
2674 { 1087, "Cooper Bussmann" },
2675 { 1088, "Trinite Automatisering B.V." },
2676 { 1089, "Peek Traffic B.V." },
2677 { 1090, "Acrison, Inc." },
2678 { 1091, "Applied Robotics, Inc." },
2679 { 1092, "FireBus LLC" },
2680 { 1093, "Sevenstar" },
2681 { 1094, "Magnetek" },
2682 { 1095, "Omron Microscan Systems, Inc." },
2683 { 1096, "Air Water Inc." },
2684 { 1097, "SensoPart Industriesensorik GmbH" },
2685 { 1098, "Tiefenbach Control Systems GmbH" },
2686 { 1099, "INOXPA S.A" },
2687 { 1100, "Zurich University of Applied Sciences" },
2688 { 1101, "Ethernet Direct" },
2689 { 1102, "GSI-Micro-E Systems" },
2690 { 1103, "S-Net Automation Co., Ltd." },
2691 { 1104, "Power Electronics S.L." },
2692 { 1105, "Renesas Electronics" },
2693 { 1106, "NSWCCD-SSES" },
2694 { 1107, "Porter Engineering Ltd." },
2695 { 1108, "Meggitt Airdynamics, Inc." },
2696 { 1109, "Inductive Automation" },
2697 { 1110, "Neural ID" },
2698 { 1111, "EEPod LLC" },
2699 { 1112, "Hitachi Industrial Equipment Systems Co.,Ltd." },
2700 { 1113, "Salem Automation" },
2701 { 1114, "port GmbH" },
2702 { 1115, "B & PLUS" },
2703 { 1116, "Graco Inc." },
2704 { 1117, "Altera Corporation" },
2705 { 1118, "Technology Brewing Corporation" },
2706 { 1119, "Reserved" },
2707 { 1120, "Reserved" },
2708 { 1121, "CSE Servelec" },
2709 { 1122, "Reserved" },
2710 { 1123, "Reserved" },
2711 { 1124, "Fluke Networks" },
2712 { 1125, "Tetra Pak Packaging Solutions SpA" },
2713 { 1126, "Racine Federated, Inc." },
2714 { 1127, "Pureron Japan Co., Ltd." },
2715 { 1128, "Reserved" },
2716 { 1129, "Reserved" },
2717 { 1130, "Brother Industries, Ltd." },
2718 { 1131, "Reserved" },
2719 { 1132, "Leroy Automation" },
2720 { 1133, "Reserved" },
2721 { 1134, "THK Co., Ltd." },
2722 { 1135, "Reserved" },
2723 { 1136, "Reserved" },
2724 { 1137, "TR-Electronic GmbH" },
2725 { 1138, "ASCON S.p.A." },
2726 { 1139, "Toledo do Brasil Industria de Balancas Ltda." },
2727 { 1140, "Caterpillar Global Mining Europe GmbH" },
2728 { 1141, "Emerson Process Management Valve Automation" },
2729 { 1142, "Alstom Transport" },
2730 { 1143, "Reserved" },
2731 { 1144, "Matrox Electronic Systems" },
2732 { 1145, "Littelfuse" },
2733 { 1146, "PLASMART, Inc." },
2734 { 1147, "Miyachi Corporation" },
2735 { 1148, "Reserved" },
2736 { 1149, "Reserved" },
2737 { 1150, "Promess Incorporated" },
2738 { 1151, "COPA-DATA GmbH" },
2739 { 1152, "Precision Engine Controls Corporation" },
2740 { 1153, "Alga Automacao e controle LTDA" },
2741 { 1154, "Lapp Group" },
2742 { 1155, "ICES" },
2743 { 1156, "Philips Lighting bv" },
2744 { 1157, "Aseptomag AG" },
2745 { 1158, "ARC Informatique" },
2746 { 1159, "Hesmor GmbH" },
2747 { 1160, "Kobe Steel, Ltd." },
2748 { 1161, "FLIR Systems" },
2749 { 1162, "Xcelgo A/S" },
2750 { 1163, "STRATON AUTOMATION" },
2751 { 1164, "Zypcom, Inc." },
2752 { 1165, "Swagelok" },
2753 { 1166, "Elspec" },
2754 { 1167, "ITT Water & Wastewater AB" },
2755 { 1168, "Kunbus GmbH Industrial Communication" },
2756 { 1169, "Reserved" },
2757 { 1170, "Performance Controls, Inc." },
2758 { 1171, "ACS Motion Control, Ltd." },
2759 { 1172, "Reserved" },
2760 { 1173, "IStar Technology Limited" },
2761 { 1174, "Alicat Scientific, Inc." },
2762 { 1175, "Reserved" },
2763 { 1176, "ADFweb.com SRL" },
2764 { 1177, "Tata Consultancy Services Limited" },
2765 { 1178, "CXR Ltd." },
2766 { 1179, "Vishay Nobel AB" },
2767 { 1180, "Reserved" },
2768 { 1181, "Emerson - SolaHD" },
2769 { 1182, "Endress+Hauser" },
2770 { 1183, "Bartec GmbH" },
2771 { 1184, "Reserved" },
2772 { 1185, "AccuSentry, Inc." },
2773 { 1186, "Curtiss Wright - Exlar Actuator Solutions" },
2774 { 1187, "ILS Technology" },
2775 { 1188, "Control Concepts, Inc." },
2776 { 1189, "Reserved" },
2777 { 1190, "Procon Engineering A Division of National Oilwell Varco UK Ltd" },
2778 { 1191, "Hermary" },
2779 { 1192, "Q-Lambda" },
2780 { 1193, "Reserved" },
2781 { 1194, "VAMP Ltd" },
2782 { 1195, "FlexLink" },
2783 { 1196, "Office FA.com Co., Ltd." },
2784 { 1197, "SPMC (Changzhou) Co. Ltd." },
2785 { 1198, "Anton Paar GmbH" },
2786 { 1199, "Zhuzhou CSR Times Electric Co., Ltd." },
2787 { 1200, "DeStaCo" },
2788 { 1201, "Synrad, Inc" },
2789 { 1202, "Bonfiglioli Vectron GmbH" },
2790 { 1203, "Pivotal Systems" },
2791 { 1204, "TKSCT" },
2792 { 1205, "Randy Nuernberger" },
2793 { 1206, "CENTRALP" },
2794 { 1207, "Tengen Group" },
2795 { 1208, "OES, Inc." },
2796 { 1209, "Actel Corporation" },
2797 { 1210, "Monaghan Engineering, Inc." },
2798 { 1211, "wenglor sensoric gmbh" },
2799 { 1212, "HSA Systems" },
2800 { 1213, "MKP Co., Ltd." },
2801 { 1214, "Tappan Wire and Cable" },
2802 { 1215, "Heinzmann GmbH & Co. KG" },
2803 { 1216, "Process Automation International Ltd." },
2804 { 1217, "Secure Crossing" },
2805 { 1218, "SMA Railway Technology GmbH" },
2806 { 1219, "FMS Force Measuring Systems AG" },
2807 { 1220, "ABT Endustri Enerji Sistemleri Sanayi Tic. Ltd. Sti." },
2808 { 1221, "MagneMotion Inc." },
2809 { 1222, "STS Co., Ltd." },
2810 { 1223, "Knorr-Bremse Espana, S.A. - Merak Division" },
2811 { 1224, "ABOUNDI, Inc." },
2812 { 1225, "Rosemount Inc." },
2813 { 1226, "GEA FES, Inc." },
2814 { 1227, "TMG Technologie und Engineering GmbH" },
2815 { 1228, "embeX GmbH" },
2816 { 1229, "GH Electrotermia, S.A." },
2817 { 1230, "Tolomatic" },
2818 { 1231, "Dukane" },
2819 { 1232, "Elco (Tian Jin) Electronics Co., Ltd." },
2820 { 1233, "Jacobs Automation" },
2821 { 1234, "Noda Radio Frequency Technologies Co., Ltd." },
2822 { 1235, "MSC Tuttlingen GmbH" },
2823 { 1236, "Hitachi Cable Manchester" },
2824 { 1237, "ACOREL SAS" },
2825 { 1238, "Global Engineering Solutions Co., Ltd." },
2826 { 1239, "ALTE Transportation, S.L." },
2827 { 1240, "Penko Engineering B.V." },
2828 { 1241, "Z-Tec Automation Systems Inc." },
2829 { 1242, "ENTRON Controls LLC" },
2830 { 1243, "Johannes Huebner Fabrik Elektrischer Maschinen GmbH" },
2831 { 1244, "RF IDeas, Inc." },
2832 { 1245, "Pentronic AB" },
2833 { 1246, "Atlas Copco IAS GmbH" },
2834 { 1247, "TDK-Lambda Corporation" },
2835 { 1248, "Reserved" },
2836 { 1249, "Reserved" },
2837 { 1250, "Altronic LLC" },
2838 { 1251, "Siemens AG" },
2839 { 1252, "Liebherr Transportation Systems GmbH & Co KG" },
2840 { 1253, "Reserved" },
2841 { 1254, "Reserved" },
2842 { 1255, "Reserved" },
2843 { 1256, "LMI Technologies" },
2844 { 1257, "Reserved" },
2845 { 1258, "Reserved" },
2846 { 1259, "Reserved" },
2847 { 1260, "Reserved" },
2848 { 1261, "CEPHALOS Automatisierung mbH" },
2849 { 1262, "Reserved" },
2850 { 1263, "Reserved" },
2851 { 1264, "Reserved" },
2852 { 1265, "Quabbin Wire & Cable Co., Inc." },
2853 { 1266, "Reserved" },
2854 { 1267, "Reserved" },
2855 { 1268, "HORIBA Precision Instruments (Beijing) Co.,Ltd." },
2856 { 1269, "Reserved" },
2857 { 1270, "Rovema GmbH" },
2858 { 1271, "Reserved" },
2859 { 1272, "IEP GmbH" },
2860 { 1273, "Reserved" },
2861 { 1274, "Reserved" },
2862 { 1275, "Reserved" },
2863 { 1276, "Reserved" },
2864 { 1277, "Control Chief Corporation" },
2865 { 1278, "Reserved" },
2866 { 1279, "Reserved" },
2867 { 1280, "Reserved" },
2868 { 1281, "Reserved" },
2869 { 1282, "PRIMES GmbH" },
2870 { 1283, "Branson Ultrasonics" },
2871 { 1284, "DEIF A/S" },
2872 { 1285, "CODESYS GmbH" },
2873 { 1286, "Reserved" },
2874 { 1287, "Smarteye Corporation" },
2875 { 1288, "Shibaura Machine" },
2876 { 1289, "HMS/BU Ewon" },
2877 { 1290, "OFS" },
2878 { 1291, "KROHNE" },
2879 { 1292, "Reserved" },
2880 { 1293, "Reserved" },
2881 { 1294, "Reserved" },
2882 { 1295, "Kistler Instrumente AG" },
2883 { 1296, "Reserved" },
2884 { 1297, "Reserved" },
2885 { 1298, "Reserved" },
2886 { 1299, "Reserved" },
2887 { 1300, "Reserved" },
2888 { 1301, "Xylem Analytics Germany GmbH" },
2889 { 1302, "Lenord, Bauer & Co. GmbH" },
2890 { 1303, "Carlo Gavazzi Controls" },
2891 { 1304, "Faiveley Transport" },
2892 { 1305, "Reserved" },
2893 { 1306, "Sensia LLC" },
2894 { 1307, "Kepware Technologies" },
2895 { 1308, "duagon AG" },
2896 { 1309, "Reserved" },
2897 { 1310, "Xylem Water Solutions" },
2898 { 1311, "Automation Professionals, LLC" },
2899 { 1312, "Reserved" },
2900 { 1313, "CEIA SpA" },
2901 { 1314, "Reserved" },
2902 { 1315, "Alphagate Automatisierungstechnik GmbH" },
2903 { 1316, "Mecco Partners, LLC" },
2904 { 1317, "LAP GmbH Laser Applikationen" },
2905 { 1318, "ABB S.p.A. - SACE Division" },
2906 { 1319, "Reserved" },
2907 { 1320, "Reserved" },
2908 { 1321, "C.E. Electronics, Inc." },
2909 { 1322, "Thermo Ramsey Inc., a part of Thermo Fisher Scientific" },
2910 { 1323, "Helmholz GmbH & Co. KG" },
2911 { 1324, "EUCHNER GmbH + Co. KG" },
2912 { 1325, "AMKmotion" },
2913 { 1326, "Badger Meter" },
2914 { 1327, "Reserved" },
2915 { 1328, "Fisher-Rosemount Systems, Inc. doing business as Process Systems & Solutions" },
2916 { 1329, "Conductix-Wampfler Automation GmbH" },
2917 { 1330, "Fairbanks Scales, Inc." },
2918 { 1331, "Imperx, Inc." },
2919 { 1332, "FRONIUS International GmbH" },
2920 { 1333, "Hoffman Enclosures" },
2921 { 1334, "Elecsys Corporation" },
2922 { 1335, "Reserved" },
2923 { 1336, "RACO Manufacturing and Engineering" },
2924 { 1337, "Hein Lanz Industrial Tech." },
2925 { 1338, "Codenomicon" },
2926 { 1339, "SABO Elektronik GmbH" },
2927 { 1340, "Reserved" },
2928 { 1341, "Sensirion AG" },
2929 { 1342, "SIKO GmbH" },
2930 { 1343, "Reserved" },
2931 { 1344, "GRUNDFOS" },
2932 { 1345, "Reserved" },
2933 { 1346, "Beijer Electronics Products AB" },
2934 { 1347, "Reserved" },
2935 { 1348, "AIMCO" },
2936 { 1349, "Reserved" },
2937 { 1350, "Coval" },
2938 { 1351, "Powell Industries" },
2939 { 1352, "Reserved" },
2940 { 1353, "IPDisplays" },
2941 { 1354, "SCAIME SAS" },
2942 { 1355, "Metal Work SpA" },
2943 { 1356, "Telsonic AG" },
2944 { 1357, "Reserved" },
2945 { 1358, "Hauch & Bach ApS" },
2946 { 1359, "Pago AG" },
2947 { 1360, "ULTIMATE Europe Transportation Equipment GmbH" },
2948 { 1361, "Reserved" },
2949 { 1362, "FW Murphy Production Controls, LLC" },
2950 { 1363, "Lake Cable LLC" },
2951 { 1364, "Reserved" },
2952 { 1365, "Reserved" },
2953 { 1366, "Reserved" },
2954 { 1367, "Reserved" },
2955 { 1368, "Nanotec Electronic GmbH & Co. KG" },
2956 { 1369, "SAMWON ACT Co., Ltd." },
2957 { 1370, "Aparian Inc." },
2958 { 1371, "Cosys Inc." },
2959 { 1372, "Insight Automation Inc." },
2960 { 1373, "Reserved" },
2961 { 1374, "FASTECH" },
2962 { 1375, "K.A. Schmersal GmbH & Co. KG" },
2963 { 1376, "Reserved" },
2964 { 1377, "Reserved" },
2965 { 1378, "SEIDENSHA ELECTRONICS CO., LTD" },
2966 { 1379, "Reserved" },
2967 { 1380, "Don Electronics Ltd" },
2968 { 1381, "burster gmbh & co kg" },
2969 { 1382, "Unitronics (1989) (RG) LTD" },
2970 { 1383, "OEM Technology Solutions" },
2971 { 1384, "Allied Motion" },
2972 { 1385, "Reserved" },
2973 { 1386, "DENGENSHA TOA CO., LTD" },
2974 { 1387, "Systec Systemtechnik und Industrieautomation GmbH" },
2975 { 1388, "Reserved" },
2976 { 1389, "Jenny Science AG" },
2977 { 1390, "Baumer Optronic GmbH" },
2978 { 1391, "Invertek Drives Ltd" },
2979 { 1392, "High Grade Controls Corporation" },
2980 { 1393, "Reserved" },
2981 { 1394, "Reserved" },
2982 { 1395, "Reserved" },
2983 { 1396, "Actia Systems" },
2984 { 1397, "Reserved" },
2985 { 1398, "Beijing Tianma Intelligent Control Technology Co., Ltd" },
2986 { 1399, "Universal Robots A/S" },
2987 { 1400, "Reserved" },
2988 { 1401, "Dialight" },
2989 { 1402, "E-T-A Elektrotechnische Apparate GmbH" },
2990 { 1403, "Kemppi Oy" },
2991 { 1404, "Reserved" },
2992 { 1405, "ORing Industrial Networking Corp." },
2993 { 1406, "Reserved" },
2994 { 1407, "Reserved" },
2995 { 1408, "ELAP S.R.L." },
2996 { 1409, "Applied Mining Technologies" },
2997 { 1410, "KITZ SCT Corporation" },
2998 { 1411, "VTEX Corporation" },
2999 { 1412, "ESYSE GmbH Embedded Systems Engineering" },
3000 { 1413, "Automation Controls" },
3001 { 1414, "Reserved" },
3002 { 1415, "Cincinnati Test Systems" },
3003 { 1416, "Reserved" },
3004 { 1417, "Zumbach Electronics Corp." },
3005 { 1418, "Emerson Automation Solutions" },
3006 { 1419, "CCS Inc." },
3007 { 1420, "Videojet, Inc." },
3008 { 1421, "Zebra Technologies" },
3009 { 1422, "ANRITSU CORPORATION" },
3010 { 1423, "Dimetix AG" },
3011 { 1424, "General Measure (China)" },
3012 { 1425, "Fortress Interlocks" },
3013 { 1426, "Reserved" },
3014 { 1427, "Task Force Tips" },
3015 { 1428, "SERVO-ROBOT INC." },
3016 { 1429, "Flow Devices and Systems, Inc." },
3017 { 1430, "nLIGHT, Inc." },
3018 { 1431, "Microchip Technology Inc." },
3019 { 1432, "Reserved" },
3020 { 1433, "Reserved" },
3021 { 1434, "Accutron Instruments Inc." },
3022 { 1435, "Kaeser Kompressoren SE" },
3023 { 1436, "Reserved" },
3024 { 1437, "Coherix, Inc." },
3025 { 1438, "FLSmidth A/S" },
3026 { 1439, "Reserved" },
3027 { 1440, "Cole-Parmer Instrument Company" },
3028 { 1441, "Wachendorff Automation GmbH & Co., KG" },
3029 { 1442, "SMAC Moving Coil Actuators" },
3030 { 1444, "PushCorp, Inc." },
3031 { 1445, "Fluke Process Instruments GmbH" },
3032 { 1446, "Mini Motor S.p.a" },
3033 { 1447, "I-CON Industry Tech." },
3034 { 1448, "Grace Technologies" },
3035 { 1449, "Zaxis Inc." },
3036 { 1450, "Lumasense Technologies" },
3037 { 1451, "Domino Printing" },
3038 { 1452, "Reserved" },
3039 { 1453, "Reserved" },
3040 { 1454, "Altus Sistemas de Automação S.A." },
3041 { 1455, "Reserved" },
3042 { 1456, "InterTech Development Company" },
3043 { 1457, "Reserved" },
3044 { 1458, "Perle Systems Limited" },
3045 { 1459, "Utthunga Technologies Pvt Ltd.," },
3046 { 1460, "Reserved" },
3047 { 1461, "WIPOTEC GmbH" },
3048 { 1462, "Atos spa" },
3049 { 1463, "Solartron Metrology LTD" },
3050 { 1464, "Reserved" },
3051 { 1465, "Analog Devices" },
3052 { 1466, "Power Electronics International, Inc." },
3053 { 1468, "Campbell Wrapper Corporation" },
3054 { 1469, "Herkules-Resotec Elektronik GmbH" },
3055 { 1470, "aignep spa" },
3056 { 1471, "Reserved" },
3057 { 1472, "PMV Automation AB" },
3058 { 1473, "Reserved" },
3059 { 1474, "ProTec Dynatronix LLC dba Dynatronix" },
3060 { 1475, "Reserved" },
3061 { 1476, "Bitronics, LLC." },
3062 { 1477, "Delta Tau Data Systems" },
3063 { 1478, "Reserved" },
3064 { 1479, "AUTOSOL" },
3065 { 1480, "ADB Safegate" },
3066 { 1481, "Reserved" },
3067 { 1482, "Reserved" },
3068 { 1483, "Artis GmbH" },
3069 { 1484, "REJ Co., LTD" },
3070 { 1485, "Vanderlande" },
3071 { 1486, "Packet Power" },
3072 { 1487, "ima-tec gmbh" },
3073 { 1488, "Vision Automation A/S" },
3074 { 1489, "PROCENTEC BV" },
3075 { 1490, "HETRONIK GmbH" },
3076 { 1491, "Lanmark Controls Inc." },
3077 { 1492, "Reserved" },
3078 { 1493, "flexlog GmbH" },
3079 { 1494, "YUCHANGTECH" },
3080 { 1495, "Dynapower Company" },
3081 { 1496, "TAKIKAWA ENGINEERING" },
3082 { 1497, "Ingersoll Rand" },
3083 { 1498, "ASA-RT s.r.l" },
3084 { 1499, "TRUMPF Schweiz AG" },
3085 { 1500, "Reserved" },
3086 { 1501, "Rinstrum" },
3087 { 1502, "Reserved" },
3088 { 1503, "Reserved" },
3089 { 1504, "BlueBotics SA" },
3090 { 1505, "Dynapar Corporation" },
3091 { 1506, "Blum-Novotest" },
3092 { 1507, "CIMON" },
3093 { 1508, "Dalian SeaSky Automation Co., ltd" },
3094 { 1509, "Rethink Robotics GmbH" },
3095 { 1510, "Ingeteam Power Technology S. A." },
3096 { 1511, "TOSEI ENGINEERING CORP." },
3097 { 1512, "SAMSON AG" },
3098 { 1513, "TGW Mechanics GmbH" },
3099 { 1514, "Diatrend Corporation" },
3100 { 1515, "Reserved" },
3101 { 1516, "VAHLE Automation GmbH" },
3102 { 1517, "JSL Technology Co.,Ltd." },
3103 { 1518, "NetTechnix E&P GmbH" },
3104 { 1519, "Reserved" },
3105 { 1520, "Tecweigh" },
3106 { 1521, "IVEK Corporation" },
3107 { 1522, "Reserved" },
3108 { 1523, "AQ M-TECH AB" },
3109 { 1524, "Rexnord Industries LLC" },
3110 { 1525, "Reserved" },
3111 { 1526, "OPTEX FA Co., Ltd" },
3112 { 1527, "Volktek Corporation" },
3113 { 1528, "INGENIA" },
3114 { 1529, "Reserved" },
3115 { 1530, "Analytical Technology, Inc." },
3116 { 1531, "Columbus McKinnon Corporation" },
3117 { 1532, "HBC-radiomatic GmbH" },
3118 { 1533, "Leonton Technologies" },
3119 { 1534, "Mitsubishi Electric India Pvt. Ltd." },
3120 { 1535, "FOBA Laser, ALLTEC GmbH" },
3121 { 1536, "Leakmaster Inc" },
3122 { 1537, "Buhler AG" },
3123 { 1538, "LINAK Denmark A/S" },
3124 { 1539, "Reserved" },
3125 { 1540, "SIEB & MEYER AG" },
3126 { 1541, "Reserved" },
3127 { 1542, "Watson-Marlow Ltd" },
3128 { 1543, "ABB Switzerland Ltd - Low Voltage Products" },
3129 { 1544, "Reserved" },
3130 { 1545, "adphos" },
3131 { 1546, "Hangzhou Hikrobot Technology Co., Ltd." },
3132 { 1547, "TOSS GmbH & Co. KG" },
3133 { 1548, "Solar Turbines Incorporated" },
3134 { 1549, "Reserved" },
3135 { 1550, "Reserved" },
3136 { 1551, "Carlo Gavazzi Industri" },
3137 { 1552, "Nippon Gear" },
3138 { 1553, "OSIsoft, LLC" },
3139 { 1554, "Rinco Ultrasonics AG" },
3140 { 1555, "Reserved" },
3141 { 1556, "Reserved" },
3142 { 1557, "Mitutoyo" },
3143 { 1558, "swisca" },
3144 { 1559, "Micro-Epsilon Messtechnik GmbH & Co. KG" },
3145 { 1560, "AMADA MIYACHI AMERICA" },
3146 { 1561, "Taihan Electric Wire Co., Ltd." },
3147 { 1562, "JANOME Corporation" },
3148 { 1563, "ISHIDA" },
3149 { 1564, "NAKANISHI INC." },
3150 { 1565, "Mecademic Inc." },
3151 { 1566, "Reserved" },
3152 { 1567, "Sigma (NSW) PTY LTD" },
3153 { 1568, "Hammond Power Solutions Inc.-Mesta" },
3154 { 1569, "Reserved" },
3155 { 1570, "Reserved" },
3156 { 1571, "TRIDIMEO" },
3157 { 1572, "Motortronics UK Ltd." },
3158 { 1573, "Doosan Robotics" },
3159 { 1574, "ADVANCED Motion Controls" },
3160 { 1575, "OnRobot A/S" },
3161 { 1576, "Reserved" },
3162 { 1577, "Oetiker" },
3163 { 1578, "SICK OPTEX" },
3164 { 1579, "Reserved" },
3165 { 1580, "Reserved" },
3166 { 1581, "Kahler Automation Corporation" },
3167 { 1582, "Accuenergy (Canada) Inc." },
3168 { 1583, "TCI, LLC - An Allied Motion Company" },
3169 { 1584, "Sun Automation" },
3170 { 1585, "READY Robotics Corporation" },
3171 { 1586, "PEM, Power Eng & Mfg., Inc" },
3172 { 1587, "Dürr Somac GmbH" },
3173 { 1588, "Reserved" },
3174 { 1589, "Reserved" },
3175 { 1590, "Reserved" },
3176 { 1591, "RICOH Industrial Solutions Inc." },
3177 { 1592, "Shanghai Junqian Sensing Technology Co. Ltd." },
3178 { 1593, "Knick Elektronische Messgeräte GmbH & Co. KG" },
3179 { 1594, "Magnescale. Co., Ltd." },
3180 { 1595, "Reserved" },
3181 { 1596, "Weintek Labs., Inc" },
3182 { 1597, "Sherpa, Inc." },
3183 { 1598, "Inspekto A.M.V LTD" },
3184 { 1599, "Hydronix Ltd" },
3185 { 1600, "AIOI- SYSTEMS CO. LTD." },
3186 { 1601, "Ingenieurbüro Mewes & Partner GmbH" },
3187 { 1602, "HIGHYAG Lasertechnologie GmbH" },
3188 { 1603, "Ningbo Jetron Technology Co. Ltd." },
3189 { 1604, "Myostat Motion Control" },
3190 { 1605, "A-T Controls, Inc" },
3191 { 1606, "M2M craft Co., Ltd." },
3192 { 1607, "FUTEK Advanced Sensor Technology, Inc." },
3193 { 1608, "Cetek" },
3194 { 1609, "Norgren Manufacturing Co., Ltd." },
3195 { 1610, "Bernstein AG" },
3196 { 1611, "Hitachi Industrial Products, Ltd." },
3197 { 1612, "Reserved" },
3198 { 1613, "Duplomatic MS spa" },
3199 { 1614, "Ambrit Ltd" },
3200 { 1615, "Highlight Tech Corp." },
3201 { 1616, "New Power Plasma Co. Ltd." },
3202 { 1617, "AGCO Corporation" },
3203 { 1618, "Techman Robot" },
3204 { 1619, "Nabeya Bi-tech Kaisha" },
3205 { 1620, "Reserved" },
3206 { 1621, "Panasonic Corporation / Electric Works Company" },
3207 { 1622, "Cytiva" },
3208 { 1623, "Janasi Industries Ltd." },
3209 { 1624, "Haffmans BV" },
3210 { 1625, "Reserved" },
3211 { 1626, "Omniview Pty Ltd" },
3212 { 1627, "Reserved" },
3213 { 1628, "Dover Flexo Electronics" },
3214 { 1629, "Reserved" },
3215 { 1630, "IDEM Safety Switches" },
3216 { 1631, "Sonotroagel GmbH" },
3217 { 1632, "Thermo Gamma-Metrics LLC, a part of Thermo Fisher Scientific" },
3218 { 1633, "BBH Products" },
3219 { 1634, "RSI Elektrotechnik" },
3220 { 1635, "Carlo Gavazzi Ltd" },
3221 { 1636, "KOFLOC Corp." },
3222 { 1637, "VTScada by Trihedral" },
3223 { 1638, "Hach" },
3224 { 1639, "Cogniac" },
3225 { 1640, "Toshiba Infrastructure Systems & Solutions Corporation" },
3226 { 1641, "Cannon-Automata" },
3227 { 1642, "Rosenberger" },
3228 { 1643, "Blue-White Industries" },
3229 { 1644, "Cellumation GmbH" },
3230 { 1645, "TEAC Corp." },
3231 { 1646, "AEG Identifikationssysteme GmbH" },
3232 { 1647, "MARS TOHKEN SOLUTION CO.LTD." },
3233 { 1648, "Midas Technology Corp." },
3234 { 1649, "Dinkle Enterprise Co., Ltd." },
3235 { 1650, "THALES" },
3236 { 1651, "Dunkermotoren" },
3237 { 1652, "SONOTEC GmbH" },
3238 { 1653, "Brinkmann Pumpen" },
3239 { 1654, "Rheonics" },
3240 { 1655, "Precimeter" },
3241 { 1656, "Reserved" },
3242 { 1657, "ALGO SYSTEM CO., LTD." },
3243 { 1658, "Christ Electronic Systems GmbH" },
3244 { 1659, "JFcontrol Co., Ltd." },
3245 { 1660, "Shenzhen Inovance Technology Co., Ltd" },
3246 { 1661, "Rheonik Coriolis Mass Flow Sensors" },
3247 { 1662, "Ichor Systems, Inc." },
3248 { 1663, "di-soric GmbH & Co. KG" },
3249 { 1664, "Amphenol ICC" },
3250 { 1665, "Ningbo AirTAC Automation Industrial Co., Ltd." },
3251 { 1666, "RSI" },
3252 { 1667, "Soft Robotics Inc." },
3253 { 1668, "MUSCLE CORPORATION" },
3254 { 1669, "Spotlight Systems LLC" },
3255 { 1670, "Afag Holding AG" },
3256 { 1671, "TELESIS TECHNOLOGIES INC" },
3257 { 1672, "SSI Schaefer Automation GmbH" },
3258 { 1673, "Super Systems, Inc." },
3259 { 1674, "CoreTigo LTD" },
3260 { 1675, "Inxpect SPA" },
3261 { 1676, "Kostal Industrie Elektrik GmbH" },
3262 { 1677, "JingQi (Tianjin) technology Co.,Ltd" },
3263 { 1678, "AGI Suretrack" },
3264 { 1679, "JAKA Robotics Co., Ltd." },
3265 { 1680, "Polarteknik Oy" },
3266 { 1681, "RoboteQ, Inc" },
3267 { 1682, "Uson" },
3268 { 1683, "Opt Machine Vision Tech Co., Ltd" },
3269 { 1684, "Asyril SA" },
3270 { 1685, "Georg Fischer Piping Systems" },
3271 { 1686, "Aber Instruments Ltd" },
3272 { 1687, "CodeWrights GmbH" },
3273 { 1688, "Neurala, Inc." },
3274 { 1689, "Panasonic Software Development Center Dalian Co.,Ltd." },
3275 { 1690, "Perinet GmbH" },
3276 { 1691, "MS Ultraschall Technologie GmbH" },
3277 { 1692, "PLASUS GmbH" },
3278 { 1693, "Nikon Corporation" },
3279 { 1694, "Shenzhen Hengzhiyuan Technology Corporation Ltd." },
3280 { 1695, "Kowa Optronics Co., Ltd." },
3281 { 1696, "Specialist Mechanical Engineers" },
3282 { 1697, "CMD Corporation" },
3283 { 1698, "Sanwa Engineering Corp." },
3284 { 1699, "Intellore Systems Pvt. Ltd" },
3285 { 1700, "Toledo e Souza" },
3286 { 1701, "PBS Biotech, Inc" },
3287 { 1702, "PLANET Technology Corporation" },
3288 { 1703, "Robatech AG" },
3289 { 1704, "MARKEM-IMAJE" },
3290 { 1705, "Novanta IMS" },
3291 { 1706, "Bamboo-Dynamics" },
3292 { 1707, "FACTS Engineering, LLC" },
3293 { 1708, "Digital Dynamics" },
3294 { 1709, "Fatek Automation Corporation" },
3295 { 1710, "Hanwha" },
3296 { 1711, "Fukuda" },
3297 { 1712, "Zhejiang Eternal Automation Sci-Tec Co.,Ltd" },
3298 { 1713, "KYOWA ELECTRONIC INSTRUMENTS CO.,LTD." },
3299 { 1714, "Vaisala Oyj" },
3300 { 1715, "Hennecke GmbH" },
3301 { 1716, "Encoder Products Company" },
3302 { 1717, "Converting Equipment International (dba CEI)" },
3303 { 1718, "Reserved" },
3304 { 1719, "Kinova" },
3305 { 1720, "The Poling Group, Inc." },
3306 { 1721, "plating electronic GmbH" },
3307 { 1722, "HIWIN MIKROSYSTEM CORP." },
3308 { 1723, "Wuxi Xinje Electric Co.,Ltd." },
3309 { 1724, "ViSCO Technologies Corporation" },
3310 { 1725, "MinebeaMitsumi Inc." },
3311 { 1726, "FIAtec GmbH" },
3312 { 1727, "eSOL Co.,Ltd" },
3313 { 1728, "NTN TECHNICAL SERVICE" },
3314 { 1729, "Shanghai Flexem" },
3315 { 1730, "Magswitch" },
3316 { 1731, "VEGA Grieshaber KG" },
3317 { 1732, "H.D.T. S.R.L." },
3318 { 1733, "Tool-Temp AG" },
3319 { 1734, "Hollysys Technology Group Co., Ltd" },
3320 { 1735, "Basler Electric Company" },
3321 { 1736, "Shinwa Controls Co.,Ltd" },
3322 { 1737, "Nanjing Decowell Automation Co.,Ltd." },
3323 { 1738, "Reverity Inc" },
3324 { 1739, "TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION" },
3325 { 1740, "BizLink Special Cables Germany GmbH" },
3326 { 1741, "Electronics Inc." },
3327 { 1742, "Inexbot" },
3328 { 1743, "Mujin, Inc." },
3329 { 1744, "Shanghai AYAN Industry System Co., Ltd" },
3330 { 1745, "EKE-Electronics Ltd." },
3331 { 1746, "Bizerba SE & Co. KG" },
3332 { 1747, "Astrodyne TDI" },
3333 { 9876, "ODVA" },
3335 { 0, NULL }
3338 value_string_ext cip_vendor_vals_ext = VALUE_STRING_EXT_INIT(cip_vendor_vals);
3340 /* Translate Device Profile's */
3341 static const value_string cip_devtype_vals[] = {
3342 { 0x00, "Generic Device (deprecated)" },
3343 { 0x02, "AC Drive" },
3344 { 0x03, "Motor Overload" },
3345 { 0x04, "Limit Switch" },
3346 { 0x05, "Inductive Proximity Switch" },
3347 { 0x06, "Photoelectric Sensor" },
3348 { 0x07, "General Purpose Discrete I/O" },
3349 { 0x09, "Resolver" },
3350 { 0x0C, "Communications Adapter" },
3351 { 0x0E, "Programmable Logic Controller" },
3352 { 0x10, "Position Controller", },
3353 { 0x13, "DC Drive" },
3354 { 0x15, "Contactor", },
3355 { 0x16, "Motor Starter", },
3356 { 0x17, "Soft Start", },
3357 { 0x18, "Human-Machine Interface" },
3358 { 0x1A, "Mass Flow Controller" },
3359 { 0x1B, "Pneumatic Valve" },
3360 { 0x1C, "Vacuum Pressure Gauge" },
3361 { 0x1D, "Process Control Value" },
3362 { 0x1E, "Residual Gas Analyzer" },
3363 { 0x1F, "DC Power Generator" },
3364 { 0x20, "RF Power Generator" },
3365 { 0x21, "Turbomolecular Vacuum Pump" },
3366 { 0x22, "Encoder" },
3367 { 0x23, "Safety Discrete I/O Device" },
3368 { 0x24, "Fluid Flow Controller" },
3369 { 0x25, "CIP Motion Drive" },
3370 { 0x26, "CompoNet Repeater" },
3371 { 0x27, "Mass Flow Controller, Enhanced" },
3372 { 0x28, "CIP Modbus Device" },
3373 { 0x29, "CIP Modbus Translator" },
3374 { 0x2A, "Safety Analog I/O Device" },
3375 { 0x2B, "Generic Device (keyable)" },
3376 { 0x2C, "Managed Ethernet Switch" },
3377 { 0x2D, "CIP Motion Safety Drive Device" },
3378 { 0x2E, "Safety Drive Device" },
3379 { 0x2F, "CIP Motion Encoder" },
3380 { 0x30, "CIP Motion Converter" },
3381 { 0x31, "CIP Motion I/O" },
3382 { 0x32, "ControlNet Physical Layer Component" },
3383 { 0x33, "Circuit Breaker" },
3384 { 0x34, "HART Device" },
3385 { 0x35, "CIP-HART Translator" },
3386 { 0xC8, "Embedded Component" },
3388 { 0, NULL }
3391 value_string_ext cip_devtype_vals_ext = VALUE_STRING_EXT_INIT(cip_devtype_vals);
3393 /* Translate class names */
3394 const value_string cip_class_names_vals[] = {
3395 { 0x01, "Identity" },
3396 { 0x02, "Message Router" },
3397 { 0x03, "DeviceNet" },
3398 { 0x04, "Assembly" },
3399 { 0x05, "Connection" },
3400 { 0x06, "Connection Manager" },
3401 { 0x07, "Register" },
3402 { 0x08, "Discrete Input Point" },
3403 { 0x09, "Discrete Output Point" },
3404 { 0x0A, "Analog Input Point" },
3405 { 0x0B, "Analog Output Point" },
3406 { 0x0E, "Presence Sensing" },
3407 { 0x0F, "Parameter" },
3408 { 0x10, "Parameter Group" },
3409 { 0x12, "Group" },
3410 { 0x1D, "Discrete Input Group" },
3411 { 0x1E, "Discrete Output Group" },
3412 { 0x1F, "Discrete Group" },
3413 { 0x20, "Analog Input Group" },
3414 { 0x21, "Analog Output Group" },
3415 { 0x22, "Analog Group" },
3416 { 0x23, "Position Sensor" },
3417 { 0x24, "Position Controller Supervisor" },
3418 { 0x25, "Position Controller" },
3419 { 0x26, "Block Sequencer" },
3420 { 0x27, "Command Block" },
3421 { 0x28, "Motor Data" },
3422 { 0x29, "Control Supervisor" },
3423 { 0x2A, "AC/DC Drive" },
3424 { 0x2B, "Acknowledge Handler" },
3425 { 0x2C, "Overload" },
3426 { 0x2D, "Softstart" },
3427 { 0x2E, "Selection" },
3428 { 0x30, "S-Device Supervisor" },
3429 { 0x31, "S-Analog Sensor" },
3430 { 0x32, "S-Analog Actuator" },
3431 { 0x33, "S-Single Stage Controller" },
3432 { 0x34, "S-Gas Calibration" },
3433 { 0x35, "Trip Point" },
3434 { 0x37, "File" },
3435 { 0x38, "S-Partial Pressure" },
3436 { 0x39, "Safety Supervisor" },
3437 { 0x3A, "Safety Validator" },
3438 { 0x3B, "Safety Discrete Output Point" },
3439 { 0x3C, "Safety Discrete Output Group" },
3440 { 0x3D, "Safety Discrete Input Point" },
3441 { 0x3E, "Safety Discrete Input Group" },
3442 { 0x3F, "Safety Dual Channel Output" },
3443 { 0x40, "S-Sensor Calibration" },
3444 { 0x41, "Event Log" },
3445 { 0x42, "Motion Device Axis" },
3446 { 0x43, "Time Sync" },
3447 { 0x44, "Modbus" },
3448 { 0x45, "Originator Connection List" },
3449 { 0x46, "Modbus Serial Link" },
3450 { 0x47, "Device Level Ring (DLR)" },
3451 { 0x48, "QoS" },
3452 { 0x49, "Safety Analog Input Point" },
3453 { 0x4A, "Safety Analog Input Group" },
3454 { 0x4B, "Safety Dual Channel Analog Input" },
3455 { 0x4C, "SERCOS III Link" },
3456 { 0x4D, "Target Connection List" },
3457 { 0x4E, "Base Energy" },
3458 { 0x4F, "Electrical Energy" },
3459 { 0x50, "Non-Electrical Energy" },
3460 { 0x51, "Base Switch" },
3461 { 0x52, "SNMP" },
3462 { 0x53, "Power Management" },
3463 { 0x54, "RSTP Bridge" },
3464 { 0x55, "RSTP Port" },
3465 { 0x56, "PRP/HSR Protocol" },
3466 { 0x57, "PRP/HSR Nodes Table" },
3467 { 0x58, "Safety Feedback" },
3468 { 0x59, "Safety Dual Channel Feedback" },
3469 { 0x5A, "Safety Stop Functions" },
3470 { 0x5B, "Safety Limit Functions" },
3471 { 0x5C, "Power Curtailment" },
3472 { 0x5D, "CIP Security" },
3473 { 0x5E, "EtherNet/IP Security" },
3474 { 0x5F, "Certificate Management" },
3475 { 0x60, "Authority" },
3476 { 0x61, "Password Authenticator" },
3477 { 0x62, "Certificate Authenticator" },
3478 { 0x63, "Ingress Egress" },
3479 { 0x67, "PCCC Class" },
3480 { 0xF0, "ControlNet" },
3481 { 0xF1, "ControlNet Keeper" },
3482 { 0xF2, "ControlNet Scheduling" },
3483 { 0xF3, "Connection Configuration" },
3484 { 0xF4, "Port" },
3485 { 0xF5, "TCP/IP Interface" },
3486 { 0xF6, "Ethernet Link" },
3487 { 0xF7, "CompoNet" },
3488 { 0xF8, "CompoNet Repeater" },
3489 { 0xF9, "HART Master Port" },
3490 { 0xFA, "I/O Aggregation" },
3491 { 0x100, "Protection Trip" },
3492 { 0x101, "Protection Alarm" },
3493 { 0x102, "Circuit Breaker Supervisor" },
3494 { 0x103, "Circuit Breaker Statistics" },
3495 { 0x104, "Electrical Demand" },
3496 { 0x105, "Electrical Statistics" },
3497 { 0x106, "Machine Base Data" },
3498 { 0x107, "HART Process Device" },
3499 { 0x108, "Process Device Diagnostics" },
3500 { 0x109, "LLDP Management" },
3501 { 0x10A, "LLDP Data Table" },
3502 { 0x10B, "IO-Link Service Parameter" },
3503 { 0x10C, "IO-Link Master PHY" },
3504 { 0x10D, "IO-Link Device PHY" },
3505 { 0x10E, "Pilot Light Supervisor" },
3506 { 0x10F, "Select Line Link" },
3507 { 0x110, "In-Cabinet Actual Topology" },
3508 { 0x111, "In-Cabinet Commissioning" },
3510 { 0, NULL }
3513 const value_string cip_id_state_vals[] = {
3514 { 0, "Nonexistent" },
3515 { 1, "Device Self Testing" },
3516 { 2, "Standby" },
3517 { 3, "Operational" },
3518 { 4, "Major Recoverable Fault" },
3519 { 5, "Major Unrecoverable Fault" },
3521 { 0, NULL }
3524 static const range_string cip_port_type_vals[] = {
3525 { 0, 0, "Any - no routing" },
3526 { 1, 1, "Reserved for legacy use" },
3527 { 2, 2, "ControlNet" },
3528 { 3, 3, "ControlNet with redundancy" },
3529 { 4, 4, "EtherNet/IP" },
3530 { 5, 5, "DeviceNet" },
3531 { 6, 99, "Reserved for legacy use" },
3532 { 100, 199, "Vendor Specific" },
3533 { 200, 200, "CompoNet" },
3534 { 201, 201, "Modbus/TCP" },
3535 { 202, 202, "Modbus/SL" },
3536 { 203, 203, "SERCOS III" },
3537 { 204, 65534, "Reserved for future use" },
3538 { 65535, 65535, "Any - user configurable" },
3540 { 0, 0, NULL }
3543 const value_string cip_port_number_vals[] = {
3544 { 0, "Reserved" },
3545 { 1, "Backplane" },
3547 { 0, NULL }
3550 value_string_ext cip_class_names_vals_ext = VALUE_STRING_EXT_INIT(cip_class_names_vals);
3552 /* Translate function to string - Run/Idle */
3553 static const value_string cip_run_idle_vals[] = {
3554 { 0, "Idle" },
3555 { 1, "Run" },
3557 { 0, NULL }
3560 void cip_rpi_api_fmt(char *s, uint32_t value)
3562 snprintf(s, ITEM_LABEL_LENGTH, "%.3fms", value / 1000.0);
3565 static void add_cip_class_to_info_column(packet_info *pinfo, uint32_t class_id, int display_type)
3567 cip_req_info_t *cip_req_info;
3569 /* Skip printing the top level class for certain common messages because it gets
3570 too wordy in the Info column. */
3571 cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
3572 if (cip_req_info
3573 && ((cip_req_info->bService == SC_CM_UNCON_SEND && class_id == CI_CLS_CM)
3574 || (cip_req_info->bService == SC_MULT_SERV_PACK && class_id == CI_CLS_MR)))
3576 return;
3579 // Don't show the Assembly class. It's a generic common class, and there are often multiple entries
3580 // which clutter the display.
3581 if (display_type == DISPLAY_CONNECTION_PATH && class_id == 4)
3583 return;
3586 if (display_type == DISPLAY_CONNECTION_PATH)
3588 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(class_id, cip_class_names_vals, "Class (0x%02x)"));
3590 else if (display_type == DISPLAY_REQUEST_PATH)
3592 col_append_fstr(pinfo->cinfo, COL_INFO, "%s - ", val_to_str(class_id, cip_class_names_vals, "Class (0x%02x)"));
3596 static void add_cip_symbol_to_info_column(packet_info *pinfo, char *symbol_name, int display_type)
3598 if (symbol_name == NULL)
3600 return;
3603 if (display_type == DISPLAY_CONNECTION_PATH)
3605 col_append_fstr(pinfo->cinfo, COL_INFO, " ('%s')", symbol_name);
3607 else if (display_type == DISPLAY_REQUEST_PATH)
3609 col_append_fstr(pinfo->cinfo, COL_INFO, "'%s' - ", symbol_name);
3613 void add_cip_service_to_info_column(packet_info *pinfo, uint8_t service, const value_string* service_vals)
3615 col_append_str( pinfo->cinfo, COL_INFO,
3616 val_to_str(service & CIP_SC_MASK, service_vals, "Service (0x%02x)"));
3617 col_set_fence(pinfo->cinfo, COL_INFO);
3620 static void add_cip_pccc_function_to_info_column(packet_info *pinfo, uint8_t fnc, const value_string* fnc_vals)
3622 col_append_fstr( pinfo->cinfo, COL_INFO,
3623 " - %s", val_to_str(fnc, fnc_vals, "Function (0x%02x)"));
3624 col_set_fence(pinfo->cinfo, COL_INFO);
3627 static int dissect_id_revision(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3628 int offset, int total_len)
3630 if (total_len < 2)
3632 expert_add_info(pinfo, item, &ei_mal_identity_revision);
3633 return total_len;
3636 proto_tree_add_item( tree, hf_id_major_rev, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3637 proto_tree_add_item( tree, hf_id_minor_rev, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
3638 return 2;
3641 static int dissect_id_status(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3642 int offset, int total_len)
3644 static int * const status[] = {
3645 &hf_id_status_owned,
3646 &hf_id_status_conf,
3647 &hf_id_status_extended1,
3648 &hf_id_status_minor_fault_rec,
3649 &hf_id_status_minor_fault_unrec,
3650 &hf_id_status_major_fault_rec,
3651 &hf_id_status_major_fault_unrec,
3652 &hf_id_status_extended2,
3653 NULL
3656 if (total_len < 2)
3658 expert_add_info(pinfo, item, &ei_mal_identity_status);
3659 return total_len;
3662 proto_tree_add_bitmask(tree, tvb, offset, hf_id_status, ett_id_status, status, ENC_LITTLE_ENDIAN);
3664 return 2;
3667 static int dissect_msg_rout_num_classes(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3668 int offset, int total_len)
3670 uint16_t i, num_classes;
3672 num_classes = tvb_get_letohs( tvb, offset);
3673 proto_tree_add_item( tree, hf_msg_rout_num_classes, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3675 if (total_len < (2+(num_classes*2)))
3677 expert_add_info(pinfo, item, &ei_mal_msg_rout_num_classes);
3678 return total_len;
3681 for (i = 0; i < num_classes; i++)
3682 proto_tree_add_item( tree, hf_msg_rout_classes, tvb, offset+2+(i*2), 2, ENC_LITTLE_ENDIAN);
3684 return (2+(num_classes*2));
3687 static int dissect_cm_connection_entry_list(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3688 int offset, int total_len _U_)
3690 uint32_t num_conn_entries = 0;
3691 uint32_t num_conn_entries_bytes;
3693 proto_tree_add_item_ret_uint(tree, hf_conn_mgr_num_conn_entries, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_conn_entries);
3695 num_conn_entries_bytes = (num_conn_entries+7)/8;
3696 proto_tree_add_uint(tree, hf_conn_mgr_num_conn_entries_bytes, tvb, 0, 0, num_conn_entries_bytes);
3698 for (uint32_t i = 0; i < num_conn_entries_bytes; i++)
3700 proto_tree_add_item(tree, hf_conn_mgr_conn_open_bits, tvb, offset + 2 + i, 1, ENC_LITTLE_ENDIAN);
3703 return 2 + num_conn_entries_bytes;
3706 static int dissect_time_sync_grandmaster_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3707 int offset, int total_len)
3709 if (total_len < 24)
3711 expert_add_info(pinfo, item, &ei_mal_time_sync_gm_clock);
3712 return total_len;
3715 proto_tree_add_item( tree, hf_time_sync_gm_clock_clock_id, tvb, offset, 8, ENC_NA);
3716 proto_tree_add_item( tree, hf_time_sync_gm_clock_clock_class, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3717 proto_tree_add_item( tree, hf_time_sync_gm_clock_time_accuracy, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3718 proto_tree_add_item( tree, hf_time_sync_gm_clock_offset_scaled_log_variance, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
3719 proto_tree_add_item( tree, hf_time_sync_gm_clock_current_utc_offset, tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
3721 static int* const bits[] = {
3722 &hf_time_sync_gm_clock_time_property_flags_leap61,
3723 &hf_time_sync_gm_clock_time_property_flags_leap59,
3724 &hf_time_sync_gm_clock_time_property_flags_current_utc_valid,
3725 &hf_time_sync_gm_clock_time_property_flags_ptp_timescale,
3726 &hf_time_sync_gm_clock_time_property_flags_time_traceable,
3727 &hf_time_sync_gm_clock_time_property_flags_freq_traceable,
3728 NULL
3730 proto_tree_add_bitmask(tree, tvb, offset + 16, hf_time_sync_gm_clock_time_property_flags, ett_time_sync_gm_clock_flags, bits, ENC_LITTLE_ENDIAN);
3732 proto_tree_add_item( tree, hf_time_sync_gm_clock_time_source, tvb, offset+18, 2, ENC_LITTLE_ENDIAN);
3733 proto_tree_add_item( tree, hf_time_sync_gm_clock_priority1, tvb, offset+20, 2, ENC_LITTLE_ENDIAN);
3734 proto_tree_add_item( tree, hf_time_sync_gm_clock_priority2, tvb, offset+22, 2, ENC_LITTLE_ENDIAN);
3735 return 24;
3738 static int dissect_time_sync_parent_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3739 int offset, int total_len)
3741 if (total_len < 16)
3743 expert_add_info(pinfo, item, &ei_mal_time_sync_parent_clock);
3744 return total_len;
3747 proto_tree_add_item( tree, hf_time_sync_parent_clock_clock_id, tvb, offset, 8, ENC_NA);
3748 proto_tree_add_item( tree, hf_time_sync_parent_clock_port_number, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3749 proto_tree_add_item( tree, hf_time_sync_parent_clock_observed_offset_scaled_log_variance, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3750 proto_tree_add_item( tree, hf_time_sync_parent_clock_observed_phase_change_rate, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
3751 return 16;
3754 static int dissect_time_sync_local_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3755 int offset, int total_len)
3757 if (total_len < 20)
3759 expert_add_info(pinfo, item, &ei_mal_time_sync_local_clock);
3760 return total_len;
3763 proto_tree_add_item( tree, hf_time_sync_local_clock_clock_id, tvb, offset, 8, ENC_NA);
3764 proto_tree_add_item( tree, hf_time_sync_local_clock_clock_class, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3765 proto_tree_add_item( tree, hf_time_sync_local_clock_time_accuracy, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3766 proto_tree_add_item( tree, hf_time_sync_local_clock_offset_scaled_log_variance, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
3767 proto_tree_add_item( tree, hf_time_sync_local_clock_current_utc_offset, tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
3769 static int* const bits[] = {
3770 &hf_time_sync_local_clock_time_property_flags_leap61,
3771 &hf_time_sync_local_clock_time_property_flags_leap59,
3772 &hf_time_sync_local_clock_time_property_flags_current_utc_valid,
3773 &hf_time_sync_local_clock_time_property_flags_ptp_timescale,
3774 &hf_time_sync_local_clock_time_property_flags_time_traceable,
3775 &hf_time_sync_local_clock_time_property_flags_freq_traceable,
3776 NULL
3778 proto_tree_add_bitmask(tree, tvb, offset + 16, hf_time_sync_local_clock_time_property_flags, ett_time_sync_local_clock_flags, bits, ENC_LITTLE_ENDIAN);
3780 proto_tree_add_item( tree, hf_time_sync_local_clock_time_source, tvb, offset+18, 2, ENC_LITTLE_ENDIAN);
3781 return 20;
3784 static int dissect_time_sync_port_state_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3785 int offset, int total_len)
3787 uint16_t i, num_ports;
3788 proto_tree* port_tree;
3790 if (total_len < 2)
3792 expert_add_info(pinfo, item, &ei_mal_time_sync_port_state_info);
3793 return total_len;
3796 num_ports = tvb_get_letohs( tvb, offset);
3797 proto_tree_add_item( tree, hf_time_sync_port_state_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3799 if (2+num_ports*4 > total_len)
3801 expert_add_info(pinfo, item, &ei_mal_time_sync_port_state_info_ports);
3802 return total_len;
3805 for (i = 0; i < num_ports; i++)
3807 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*4, 4, ett_time_sync_port_state_info, NULL, "Port #%d", i+1);
3808 proto_tree_add_item(port_tree, hf_time_sync_port_state_info_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3809 proto_tree_add_item(port_tree, hf_time_sync_port_state_info_port_state, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3812 return 2+num_ports*4;
3815 static int dissect_time_sync_port_enable_cfg(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3816 int offset, int total_len)
3818 uint16_t i, num_ports;
3819 proto_tree* port_tree;
3821 if (total_len < 2)
3823 expert_add_info(pinfo, item, &ei_mal_time_sync_port_enable_cfg);
3824 return total_len;
3827 num_ports = tvb_get_letohs( tvb, offset);
3828 proto_tree_add_item( tree, hf_time_sync_port_enable_cfg_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3830 if (2+num_ports*4 > total_len)
3832 expert_add_info(pinfo, item, &ei_mal_time_sync_port_enable_cfg_ports);
3833 return total_len;
3836 for (i = 0; i < num_ports; i++)
3838 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*4, 4, ett_time_sync_port_enable_cfg, NULL, "Port #%d", i+1);
3839 proto_tree_add_item(port_tree, hf_time_sync_port_enable_cfg_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3840 proto_tree_add_item(port_tree, hf_time_sync_port_enable_cfg_port_enable, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3843 return 2+num_ports*4;
3846 static int dissect_time_sync_port_log_announce(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3847 int offset, int total_len)
3849 uint16_t i, num_ports;
3850 proto_tree* port_tree;
3852 if (total_len < 2)
3854 expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_announce);
3855 return total_len;
3858 num_ports = tvb_get_letohs( tvb, offset);
3859 proto_tree_add_item( tree, hf_time_sync_port_log_announce_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3861 if (2+num_ports*4 > total_len)
3863 expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_announce_ports);
3864 return total_len;
3867 for (i = 0; i < num_ports; i++)
3869 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*4, 4, ett_time_sync_port_log_announce, NULL, "Port #%d", i+1);
3870 proto_tree_add_item(port_tree, hf_time_sync_port_log_announce_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3871 proto_tree_add_item(port_tree, hf_time_sync_port_log_announce_interval, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3874 return 2+num_ports*4;
3877 static int dissect_time_sync_port_log_sync(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3878 int offset, int total_len)
3880 uint16_t i, num_ports;
3881 proto_tree* port_tree;
3883 if (total_len < 2)
3885 expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_sync);
3886 return total_len;
3889 num_ports = tvb_get_letohs( tvb, offset);
3890 proto_tree_add_item( tree, hf_time_sync_port_log_sync_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3892 if (2+num_ports*4 > total_len)
3894 expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_sync_ports);
3895 return total_len;
3898 for (i = 0; i < num_ports; i++)
3900 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*4, 4, ett_time_sync_port_log_sync, NULL, "Port #%d", i+1);
3901 proto_tree_add_item(port_tree, hf_time_sync_port_log_sync_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3902 proto_tree_add_item(port_tree, hf_time_sync_port_log_sync_port_log_sync_interval, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3905 return 2+num_ports*4;
3908 static int dissect_time_sync_clock_type(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3909 int offset, int total_len)
3911 if (total_len < 2)
3913 expert_add_info(pinfo, item, &ei_mal_time_sync_clock_type);
3914 return total_len;
3917 static int* const bits[] = {
3918 &hf_time_sync_clock_type_management,
3919 &hf_time_sync_clock_type_end_to_end,
3920 &hf_time_sync_clock_type_boundary,
3921 &hf_time_sync_clock_type_ordinary,
3922 &hf_time_sync_clock_type_slave_only,
3923 NULL
3925 proto_tree_add_bitmask(tree, tvb, offset, hf_time_sync_clock_type, ett_time_sync_clock_type, bits, ENC_LITTLE_ENDIAN);
3927 return 2;
3930 static int dissect_time_sync_manufacture_id(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3931 int offset, int total_len)
3933 if (total_len < 4)
3935 expert_add_info(pinfo, item, &ei_mal_time_sync_manufacture_id);
3936 return total_len;
3939 proto_tree_add_item( tree, hf_time_sync_manufacture_id_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3940 proto_tree_add_item( tree, hf_time_sync_manufacture_id_reserved, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
3941 return 4;
3944 static int dissect_time_sync_prod_desc(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3945 int offset, int total_len)
3947 uint32_t size;
3949 if (total_len < 4)
3951 expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc);
3952 return total_len;
3955 proto_tree_add_item_ret_uint( tree, hf_time_sync_prod_desc_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
3957 if (size > 64)
3959 expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc_64);
3960 return total_len;
3963 if ((int)(size+4) > total_len)
3965 expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc_size);
3966 return total_len;
3969 proto_tree_add_item( tree, hf_time_sync_prod_desc_str, tvb, offset+4, size, ENC_ASCII);
3970 return size+4;
3973 static int dissect_time_sync_revision_data(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3974 int offset, int total_len)
3976 uint32_t size;
3978 if (total_len < 4)
3980 expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data);
3981 return total_len;
3984 proto_tree_add_item_ret_uint( tree, hf_time_sync_revision_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
3986 if (size > 32)
3988 expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data_32);
3989 return total_len;
3992 if ((int)(size+4) > total_len)
3994 expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data_size);
3995 return total_len;
3998 proto_tree_add_item( tree, hf_time_sync_revision_data_str, tvb, offset+4, size, ENC_ASCII);
3999 return size+4;
4002 static int dissect_time_sync_user_desc(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4003 int offset, int total_len)
4005 uint32_t size;
4007 if (total_len < 4)
4009 expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc);
4010 return total_len;
4013 proto_tree_add_item_ret_uint( tree, hf_time_sync_user_desc_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
4015 if (size > 128)
4017 expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc_128);
4018 return total_len;
4021 if ((int)(size+4) > total_len)
4023 expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc_size);
4024 return total_len;
4027 proto_tree_add_item( tree, hf_time_sync_user_desc_str, tvb, offset+4, size, ENC_ASCII);
4028 return size+4;
4031 static int dissect_time_sync_port_profile_id_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4032 int offset, int total_len)
4034 uint16_t i, num_ports;
4035 proto_tree* port_tree;
4037 if (total_len < 2)
4039 expert_add_info(pinfo, item, &ei_mal_time_sync_port_profile_id_info);
4040 return total_len;
4043 num_ports = tvb_get_letohs( tvb, offset);
4044 proto_tree_add_item( tree, hf_time_sync_port_profile_id_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4046 if (2+num_ports*10 > total_len)
4048 expert_add_info(pinfo, item, &ei_mal_time_sync_port_profile_id_info_ports);
4049 return total_len;
4052 for (i = 0; i < num_ports; i++)
4054 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*10, 10, ett_time_sync_port_profile_id_info, NULL, "Port #%d", i+1);
4055 proto_tree_add_item(port_tree, hf_time_sync_port_profile_id_info_port_num, tvb, offset+2+i*10, 2, ENC_LITTLE_ENDIAN);
4056 proto_tree_add_item(port_tree, hf_time_sync_port_profile_id_info_profile_id, tvb, offset+4+i*10, 8, ENC_NA);
4059 return 2+num_ports*10;
4062 static int dissect_time_sync_port_phys_addr_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4063 int offset, int total_len)
4065 uint16_t i, num_ports;
4066 proto_tree* port_tree;
4068 if (total_len < 2)
4070 expert_add_info(pinfo, item, &ei_mal_time_sync_port_phys_addr_info);
4071 return total_len;
4074 num_ports = tvb_get_letohs( tvb, offset);
4075 proto_tree_add_item( tree, hf_time_sync_port_phys_addr_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4077 if (2+num_ports*36 > total_len)
4079 expert_add_info(pinfo, item, &ei_mal_time_sync_port_phys_addr_info_ports);
4080 return total_len;
4083 for (i = 0; i < num_ports; i++)
4085 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*36, 36, ett_time_sync_port_phys_addr_info, NULL, "Port #%d", i+1);
4086 proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_port_num, tvb, offset+2+i*36, 2, ENC_LITTLE_ENDIAN);
4087 proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_phys_proto, tvb, offset+4+i*36, 16, ENC_ASCII);
4089 uint32_t addr_size;
4090 proto_tree_add_item_ret_uint(port_tree, hf_time_sync_port_phys_addr_info_addr_size, tvb, offset+20+i*36, 2, ENC_LITTLE_ENDIAN, &addr_size);
4092 // Field is 16 bytes, but only highlight the actual size.
4093 proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_phys_addr, tvb, offset+22+i*36, addr_size, ENC_NA);
4096 return 2+num_ports*36;
4099 static int dissect_time_sync_port_proto_addr_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4100 int offset, int total_len)
4102 uint16_t i, num_ports;
4103 proto_tree* port_tree;
4105 if (total_len < 2)
4107 expert_add_info(pinfo, item, &ei_mal_time_sync_port_proto_addr_info);
4108 return total_len;
4111 num_ports = tvb_get_letohs( tvb, offset);
4112 proto_tree_add_item( tree, hf_time_sync_port_proto_addr_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4114 if (2+num_ports*22 > total_len)
4116 expert_add_info(pinfo, item, &ei_mal_time_sync_port_proto_addr_info_ports);
4117 return total_len;
4120 for (i = 0; i < num_ports; i++)
4122 port_tree = proto_tree_add_subtree_format(tree, tvb, offset+2+i*22, 22, ett_time_sync_port_proto_addr_info, NULL, "Port #%d", i+1);
4123 proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_port_num, tvb, offset+2+i*22, 2, ENC_LITTLE_ENDIAN);
4124 proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_network_proto, tvb, offset+4+i*22, 2, ENC_LITTLE_ENDIAN);
4125 proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_addr_size, tvb, offset+6+i*22, 2, ENC_LITTLE_ENDIAN);
4126 proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_port_proto_addr, tvb, offset+8+i*22, 16, ENC_NA);
4129 return 2+num_ports*22;
4132 static int dissect_time_sync_sys_time_and_offset(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4133 int offset, int total_len)
4135 if (total_len < 16)
4137 expert_add_info(pinfo, item, &ei_mal_time_sync_sys_time_and_offset);
4138 return total_len;
4141 dissect_cip_utime(tree, tvb, offset, hf_time_sync_sys_time_and_offset_time);
4142 proto_tree_add_item( tree, hf_time_sync_sys_time_and_offset_offset, tvb, offset+8, 8, ENC_LITTLE_ENDIAN);
4144 return 16;
4147 int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4148 int offset, int total_len)
4150 uint32_t i;
4151 uint32_t num_attr = 0;
4153 proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_attr_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_attr);
4155 if (total_len < (int)(2 + num_attr * 2))
4157 expert_add_info(pinfo, item, &ei_mal_opt_attr_list);
4158 return total_len;
4161 // Look up the request data to get the CIP Class.
4162 cip_req_info_t *cip_req_info;
4163 cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
4165 for (i = 0; i < num_attr; ++i)
4167 proto_item* attr_item = proto_tree_add_item(tree, hf_attr_class_attr_num, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN);
4169 // Display attribute name.
4170 if (cip_req_info && cip_req_info->ciaData)
4172 const attribute_info_t* attr;
4173 attr = cip_get_attribute(cip_req_info->ciaData->iClass, 1, i);
4174 if (attr)
4176 proto_item_append_text(attr_item, " (%s)", attr->text);
4181 return 2 + num_attr * 2;
4184 int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4185 int offset, int total_len)
4187 uint32_t i;
4188 uint32_t num_services = 0;
4190 proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_service_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_services);
4192 if (total_len < (int)(2 + num_services * 2))
4194 expert_add_info(pinfo, item, &ei_mal_opt_service_list);
4195 return total_len;
4198 for (i = 0; i < num_services; ++i)
4200 proto_tree_add_item(tree, hf_attr_class_service_code, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN);
4203 return 2 + num_services * 2;
4206 static int dissect_port_instance_info(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
4207 int offset, int total_len)
4209 int i;
4211 for (i = 0; i < total_len; i += 4)
4213 proto_tree_add_item(tree, hf_port_type, tvb, offset + i, 2, ENC_LITTLE_ENDIAN);
4214 proto_tree_add_item(tree, hf_port_number, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
4217 return total_len;
4220 static int dissect_port_associated_comm_objects(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4221 int offset, int total_len _U_)
4223 uint32_t num_entries;
4224 proto_tree_add_item_ret_uint(tree, hf_port_num_comm_object_entries, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_entries);
4226 int parsed_len = 1;
4227 for (uint32_t i = 0; i < num_entries; ++i)
4229 parsed_len += dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset + parsed_len,
4230 tvb_reported_length_remaining(tvb, offset + parsed_len));
4233 return parsed_len;
4236 static int dissect_padded_epath_len(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4237 int offset, int total_len, bool one_byte_len)
4239 uint32_t path_size;
4240 proto_tree *epath_tree;
4241 proto_item *path_item;
4243 uint32_t path_size_len;
4244 int hf_path_len;
4245 if (one_byte_len == true)
4247 path_size_len = 1;
4248 hf_path_len = hf_path_len_usint;
4250 else
4252 path_size_len = 2;
4253 hf_path_len = hf_path_len_uint;
4256 path_item = proto_tree_add_item_ret_uint(tree, hf_path_len, tvb, offset, path_size_len, ENC_LITTLE_ENDIAN, &path_size);
4258 if (total_len < (int)(path_size * 2 + path_size_len))
4260 expert_add_info(pinfo, item, &ei_mal_padded_epath_size);
4261 return total_len;
4264 epath_tree = proto_tree_add_subtree(tree, tvb, offset + path_size_len, path_size * 2, ett_path, &path_item, "Path: ");
4265 dissect_epath(tvb, pinfo, epath_tree, path_item, offset + path_size_len, path_size * 2, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
4267 return path_size * 2 + path_size_len;
4270 /* Format: USINT (Length of EPATH in 16-bit words) + Padded EPATH */
4271 int dissect_padded_epath_len_usint(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4272 int offset, int total_len)
4274 return dissect_padded_epath_len(pinfo, tree, item, tvb, offset, total_len, true);
4277 /* Format: UINT (Length of EPATH in 16-bit words) + Padded EPATH */
4278 int dissect_padded_epath_len_uint(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4279 int offset, int total_len)
4281 return dissect_padded_epath_len(pinfo, tree, item, tvb, offset, total_len, false);
4284 static int dissect_single_segment_packed_attr(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
4285 int offset, int total_len _U_)
4287 proto_tree *subtree;
4288 proto_item *subitem;
4289 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_port_path, &subitem, "Path: ");
4291 int parsed_len = dissect_cip_segment_single(pinfo, tvb, offset, subtree, subitem, false, true, NULL, NULL, NO_DISPLAY, NULL, false);
4292 proto_item_set_len(subitem, parsed_len);
4294 return parsed_len;
4297 static int dissect_single_segment_padded_attr(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
4298 int offset, int total_len _U_)
4300 proto_tree *subtree;
4301 proto_item *subitem;
4302 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_port_path, &subitem, "Path: ");
4304 int parsed_len = dissect_cip_segment_single(pinfo, tvb, offset, subtree, subitem, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
4305 proto_item_set_len(subitem, parsed_len);
4307 return parsed_len;
4310 static int dissect_port_link_object(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
4311 int offset, int total_len)
4313 return dissect_padded_epath_len_uint(pinfo, tree, item, tvb, offset, total_len);
4316 static int dissect_port_node_range(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
4317 int offset, int total_len _U_)
4319 proto_tree_add_item(tree, hf_port_min_node_num, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4320 proto_tree_add_item(tree, hf_port_max_node_num, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4322 return 4;
4326 /// Identity - Services
4327 static int dissect_identity_reset(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb, int offset, bool request)
4329 int parsed_len = 0;
4331 if (request)
4333 if (tvb_reported_length_remaining(tvb, offset) > 0)
4335 proto_tree_add_item(tree, hf_cip_sc_reset_param, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4336 parsed_len = 1;
4339 else
4341 parsed_len = 0;
4344 return parsed_len;
4347 static const attribute_info_t cip_attribute_vals[] = {
4348 /* Identity Object (class attributes) */
4349 {0x01, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4350 {0x01, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4351 {0x01, true, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4352 {0x01, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4353 {0x01, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4354 {0x01, true, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4355 {0x01, true, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4357 /* Identity Object (instance attributes) */
4358 {0x01, false, 1, 0, "Vendor ID", cip_uint, &hf_id_vendor_id, NULL},
4359 {0x01, false, 2, 1, "Device Type", cip_uint, &hf_id_device_type, NULL},
4360 {0x01, false, 3, 2, "Product Code", cip_uint, &hf_id_product_code, NULL},
4361 {0x01, false, 4, 3, "Revision", cip_dissector_func, NULL, dissect_id_revision},
4362 {0x01, false, 5, 4, "Status", cip_dissector_func, NULL, dissect_id_status},
4363 {0x01, false, 6, 5, "Serial Number", cip_udint, &hf_id_serial_number, NULL},
4364 {0x01, false, 7, 6, "Product Name", cip_short_string, &hf_id_product_name, NULL},
4365 {0x01, false, 8, 7, "State", cip_usint, &hf_id_state, NULL},
4366 {0x01, false, 9, 8, "Configuration Consistency Value", cip_uint, &hf_id_config_value, NULL},
4367 {0x01, false, 10, 9, "Heartbeat Interval", cip_usint, &hf_id_heartbeat, NULL},
4369 /* Message Router Object (class attributes) */
4370 {0x02, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4371 {0x02, true, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4372 {0x02, true, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4373 {0x02, true, 4, 1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4374 {0x02, true, 5, 2, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4375 {0x02, true, 6, 3, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4376 {0x02, true, 7, 4, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4378 /* Message Router Object (instance attributes) */
4379 {0x02, false, 1, 0, "Object List", cip_dissector_func, NULL, dissect_msg_rout_num_classes},
4380 {0x02, false, 2, 1, "Number Available", cip_uint, &hf_msg_rout_num_available, NULL},
4381 {0x02, false, 3, 2, "Number Active", cip_uint, &hf_msg_rout_num_active, NULL},
4382 {0x02, false, 4, 3, "Active Connections", cip_uint_array, &hf_msg_rout_active_connections, NULL},
4384 /* Connection Manager Object (class attributes) */
4385 {0x06, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4386 {0x06, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4387 {0x06, true, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4388 {0x06, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4389 {0x06, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4390 {0x06, true, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4391 {0x06, true, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4393 /* Connection Manager Object (instance attributes) */
4394 {0x06, false, 1, 0, "Open Requests", cip_uint, &hf_conn_mgr_open_requests, NULL},
4395 {0x06, false, 2, 1, "Open Format Rejects", cip_uint, &hf_conn_mgr_open_format_rejects, NULL},
4396 {0x06, false, 3, 2, "Open Resource Rejects", cip_uint, &hf_conn_mgr_open_resource_rejects, NULL},
4397 {0x06, false, 4, 3, "Other Open Rejects", cip_uint, &hf_conn_mgr_other_open_rejects, NULL},
4398 {0x06, false, 5, 4, "Close Requests", cip_uint, &hf_conn_mgr_close_requests, NULL},
4399 {0x06, false, 6, 5, "Close Format Requests", cip_uint, &hf_conn_close_format_requests, NULL},
4400 {0x06, false, 7, 6, "Close Other Requests", cip_uint, &hf_conn_mgr_close_other_requests, NULL},
4401 {0x06, false, 8, 7, "Connection Timeouts", cip_uint, &hf_conn_mgr_conn_timouts, NULL},
4402 {0x06, false, 9, 8, "Connection Entry List", cip_dissector_func, NULL, dissect_cm_connection_entry_list },
4403 {0x06, false, 11, 9, "CPU Utilization", cip_uint, &hf_conn_mgr_cpu_utilization, NULL },
4404 {0x06, false, 12, 10, "Max Buff Size", cip_udint, &hf_conn_mgr_max_buff_size, NULL },
4405 {0x06, false, 13, 11, "Buff Size Remaining", cip_udint, &hf_conn_mgr_buff_size_remaining, NULL },
4407 /* File Object (instance attributes) */
4408 {0x37, false, 4, -1, "File Name", cip_stringi, &hf_file_filename, NULL },
4410 /* Time Sync Object (class attributes) */
4411 {0x43, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4412 {0x43, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4413 {0x43, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4414 {0x43, true, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4415 {0x43, true, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4416 {0x43, true, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4417 {0x43, true, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4419 /* Time Sync Object (instance attributes) */
4420 {0x43, false, 1, -1, "PTP Enable", cip_bool, &hf_time_sync_ptp_enable, NULL},
4421 {0x43, false, 2, -1, "Is Synchronized", cip_bool, &hf_time_sync_is_synchronized, NULL},
4422 {0x43, false, 3, -1, "System Time (Microseconds)", cip_utime, &hf_time_sync_sys_time_micro, NULL},
4423 {0x43, false, 4, -1, "System Time (Nanoseconds)", cip_stime, &hf_time_sync_sys_time_nano, NULL},
4424 {0x43, false, 5, -1, "Offset from Master", cip_ntime, &hf_time_sync_offset_from_master, NULL},
4425 {0x43, false, 6, -1, "Max Offset from Master", cip_ulint, &hf_time_sync_max_offset_from_master, NULL},
4426 {0x43, false, 7, -1, "Mean Path Delay To Master", cip_ntime, &hf_time_sync_mean_path_delay_to_master, NULL},
4427 {0x43, false, 8, -1, "Grand Master Clock Info", cip_dissector_func, NULL, dissect_time_sync_grandmaster_clock},
4428 {0x43, false, 9, -1, "Parent Clock Info", cip_dissector_func, NULL, dissect_time_sync_parent_clock},
4429 {0x43, false, 10, -1, "Local Clock Info", cip_dissector_func, NULL, dissect_time_sync_local_clock},
4430 {0x43, false, 11, -1, "Number of Ports", cip_uint, &hf_time_sync_num_ports, NULL},
4431 {0x43, false, 12, -1, "Port State Info", cip_dissector_func, NULL, dissect_time_sync_port_state_info},
4432 {0x43, false, 13, -1, "Port Enable Cfg", cip_dissector_func, NULL, dissect_time_sync_port_enable_cfg},
4433 {0x43, false, 14, -1, "Port Log Announcement Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_announce},
4434 {0x43, false, 15, -1, "Port Log Sync Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_sync},
4435 {0x43, false, 16, -1, "Priority1", cip_usint, &hf_time_sync_priority1, NULL},
4436 {0x43, false, 17, -1, "Priority2", cip_usint, &hf_time_sync_priority2, NULL},
4437 {0x43, false, 18, -1, "Domain number", cip_usint, &hf_time_sync_domain_number, NULL},
4438 {0x43, false, 19, -1, "Clock Type", cip_dissector_func, NULL, dissect_time_sync_clock_type},
4439 {0x43, false, 20, -1, "Manufacture Identity", cip_dissector_func, NULL, dissect_time_sync_manufacture_id},
4440 {0x43, false, 21, -1, "Product Description", cip_dissector_func, NULL, dissect_time_sync_prod_desc},
4441 {0x43, false, 22, -1, "Revision Data", cip_dissector_func, NULL, dissect_time_sync_revision_data},
4442 {0x43, false, 23, -1, "User Description", cip_dissector_func, NULL, dissect_time_sync_user_desc},
4443 {0x43, false, 24, -1, "Port Profile Identity Info", cip_dissector_func, NULL, dissect_time_sync_port_profile_id_info},
4444 {0x43, false, 25, -1, "Port Physical Address Info", cip_dissector_func, NULL, dissect_time_sync_port_phys_addr_info},
4445 {0x43, false, 26, -1, "Port Protocol Address Info", cip_dissector_func, NULL, dissect_time_sync_port_proto_addr_info},
4446 {0x43, false, 27, -1, "Steps Removed", cip_uint, &hf_time_sync_steps_removed, NULL},
4447 {0x43, false, 28, -1, "System Time and Offset", cip_dissector_func, NULL, dissect_time_sync_sys_time_and_offset},
4450 /* Connection Configuration Object (class attributes) */
4451 /* Data sizes are different than common class attributes for some items. */
4452 { 0xF3, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4453 { 0xF3, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_udint, &hf_cip_class_max_inst32, NULL },
4454 { 0xF3, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_udint, &hf_cip_class_num_inst32, NULL },
4455 { 0xF3, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4456 { 0xF3, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4457 { 0xF3, true, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4458 { 0xF3, true, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4459 { 0xF3, true, 8, 3, "Format Number", cip_uint, &hf_cip_cco_format_number, NULL },
4460 { 0xF3, true, 9, 4, "Edit Signature", cip_udint, &hf_cip_cco_edit_signature, NULL },
4462 /* Port Object (class attributes) */
4463 { 0xF4, true, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4464 { 0xF4, true, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4465 { 0xF4, true, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4466 { 0xF4, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4467 { 0xF4, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4468 { 0xF4, true, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4469 { 0xF4, true, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4470 { 0xF4, true, 8, 3, "Entry Port", cip_uint, &hf_port_entry_port, NULL },
4471 { 0xF4, true, 9, 4, "Port Instance Info", cip_dissector_func, NULL, dissect_port_instance_info },
4473 /* Port Object (instance attributes) */
4474 { 0xF4, false, 1, 0, "Port Type", cip_uint, &hf_port_type, NULL },
4475 { 0xF4, false, 2, 1, "Port Number", cip_uint, &hf_port_number, NULL },
4476 { 0xF4, false, 3, 2, "Link Object", cip_dissector_func, NULL, dissect_port_link_object },
4477 { 0xF4, false, 4, 3, "Port Name", cip_short_string, &hf_port_name, NULL },
4478 { 0xF4, false, 7, 4, "Port Number and Node Address", cip_dissector_func, NULL, dissect_single_segment_padded_attr },
4479 { 0xF4, false, 8, -1, "Port Node Range", cip_dissector_func, NULL, dissect_port_node_range },
4480 { 0xF4, false, 9, -1, "Chassis Identity", cip_dissector_func, NULL, dissect_single_segment_packed_attr },
4481 { 0xF4, false, 11, -1, "Associated Communication Objects", cip_dissector_func, NULL, dissect_port_associated_comm_objects },
4484 // Table of CIP services defined by this dissector.
4485 static cip_service_info_t cip_obj_spec_service_table[] = {
4486 { 0x1, SC_RESET, "Reset", dissect_identity_reset },
4489 // Look up a given CIP service from this dissector.
4490 static cip_service_info_t* cip_get_service_cip(uint32_t class_id, uint8_t service_id)
4492 return cip_get_service_one_table(&cip_obj_spec_service_table[0],
4493 array_length(cip_obj_spec_service_table),
4494 class_id,
4495 service_id);
4498 typedef struct attribute_val_array {
4499 size_t size;
4500 const attribute_info_t* attrs;
4501 } attribute_val_array_t;
4503 /* Each entry in this table (eg: cip_attribute_vals) is a list of:
4504 Attribute information (class_id/class_instance/attribute) to attribute property
4506 Note: If more items are added to the individual tables, it may make sense
4507 to switch to a more efficient implementation (eg: hash table).
4510 static attribute_val_array_t all_attribute_vals[] = {
4511 {array_length(cip_attribute_vals), cip_attribute_vals},
4512 {array_length(enip_attribute_vals), enip_attribute_vals},
4513 {array_length(cip_safety_attribute_vals), cip_safety_attribute_vals},
4514 {array_length(cip_motion_attribute_vals), cip_motion_attribute_vals},
4517 const attribute_info_t* cip_get_attribute(unsigned class_id, unsigned instance, unsigned attribute)
4519 size_t i, j;
4520 attribute_val_array_t* att_array;
4521 const attribute_info_t* pattr;
4523 static const attribute_info_t class_attribute_vals[] = {
4524 { 0, true, 1, -1, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
4525 { 0, true, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
4526 { 0, true, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
4527 { 0, true, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
4528 { 0, true, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
4529 { 0, true, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
4530 { 0, true, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
4533 for (i = 0; i < array_length(all_attribute_vals); i++)
4535 att_array = &all_attribute_vals[i];
4536 for (j = 0; j < att_array->size; j++)
4538 pattr = &att_array->attrs[j];
4539 if ((pattr->class_id == class_id) &&
4540 (instance != SEGMENT_VALUE_NOT_SET) &&
4541 (((instance == 0) && (pattr->class_instance == true)) || ((instance != 0) && (pattr->class_instance == false))) &&
4542 (pattr->attribute == attribute))
4544 return pattr;
4549 /* Check against common class attributes. */
4550 if (instance == 0)
4552 for (i = 0; i < array_length(class_attribute_vals); i++)
4554 pattr = &class_attribute_vals[i];
4555 if (pattr->attribute == attribute)
4557 return pattr;
4562 return NULL;
4565 // Look up a given CIP service from a table of cip_service_info_t.
4566 cip_service_info_t* cip_get_service_one_table(cip_service_info_t* services, size_t size, uint32_t class_id, uint8_t service_id)
4568 for (uint32_t i = 0; i < size; i++)
4570 cip_service_info_t* entry = &services[i];
4571 if (entry->class_id == class_id && entry->service_id == (service_id & CIP_SC_MASK))
4573 return entry;
4577 return NULL;
4580 // Look through all CIP Service tables from different dissectors, to find a definition for a given CIP service.
4581 static cip_service_info_t* cip_get_service(packet_info *pinfo, uint8_t service_id)
4583 cip_req_info_t *cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
4584 if (!cip_req_info || !cip_req_info->ciaData)
4586 return NULL;
4589 cip_service_info_t* pService = cip_get_service_cip(cip_req_info->ciaData->iClass, service_id);
4590 if (pService)
4592 return pService;
4595 pService = cip_get_service_enip(cip_req_info->ciaData->iClass, service_id);
4596 if (pService)
4598 return pService;
4601 return NULL;
4604 static const char *
4605 segment_name_format(wmem_allocator_t *scope, const char *segment_name, const char *fmt)
4606 G_GNUC_FORMAT(2);
4608 static const char *
4609 segment_name_format(wmem_allocator_t *scope, const char *segment_name, const char *fmt)
4611 wmem_strbuf_t *strbuf;
4613 strbuf = wmem_strbuf_new(scope, segment_name);
4614 wmem_strbuf_append(strbuf, fmt);
4615 return wmem_strbuf_get_str(strbuf);
4618 static int
4619 dissect_cia(tvbuff_t *tvb, int offset, unsigned char segment_type,
4620 bool generate, bool packed, packet_info *pinfo, proto_item *epath_item,
4621 proto_tree *path_tree, proto_item *path_item, proto_item ** ret_item,
4622 const char* segment_name, const value_string* vals, int* value,
4623 int hf8, int hf16, int hf32)
4625 unsigned char logical_format;
4626 int segment_len;
4627 int temp_data;
4628 int value_offset;
4629 wmem_strbuf_t *strbuf;
4630 bool extended_logical = false;
4631 uint8_t logical_seg_type = segment_type & CI_LOGICAL_SEG_TYPE_MASK;
4633 /* Extended Logical Format is slightly different than other logical formats. An extra byte is
4634 inserted after the segment type. */
4635 if (logical_seg_type == CI_LOGICAL_SEG_EXT_LOGICAL)
4637 extended_logical = true;
4639 if (generate)
4641 temp_data = tvb_get_uint8(tvb, offset + 1);
4642 *ret_item = proto_tree_add_uint(path_tree, hf_cip_ext_logical_type, tvb, 0, 0, temp_data);
4643 proto_item_set_generated(*ret_item);
4645 else
4647 *ret_item = proto_tree_add_item(path_tree, hf_cip_ext_logical_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4651 logical_format = segment_type & CI_LOGICAL_SEG_FORMAT_MASK;
4652 switch (logical_format)
4654 case CI_LOGICAL_SEG_8_BIT:
4655 value_offset = offset + 1;
4657 if (extended_logical == true)
4659 value_offset += 1;
4662 temp_data = tvb_get_uint8(tvb, value_offset);
4664 if ( generate )
4666 *ret_item = proto_tree_add_uint(path_tree, hf8, tvb, 0, 0, temp_data );
4667 proto_item_set_generated(*ret_item);
4669 else
4671 *ret_item = proto_tree_add_item(path_tree, hf8, tvb, value_offset, 1, ENC_LITTLE_ENDIAN);
4674 if (vals == NULL)
4676 if (logical_seg_type == CI_LOGICAL_SEG_ATTR_ID)
4678 proto_item_append_text(epath_item, "%s: %d", segment_name, temp_data);
4680 else
4682 proto_item_append_text(epath_item, "%s: 0x%02X", segment_name, temp_data);
4685 else
4687 proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( pinfo->pool, segment_name, ": 0x%02X" ) ) );
4690 if (value != NULL)
4691 *value = temp_data;
4693 segment_len = 2;
4694 if (extended_logical == true)
4696 if (packed)
4698 segment_len += 1;
4700 else
4702 segment_len += 2;
4705 break;
4706 case CI_LOGICAL_SEG_16_BIT:
4707 if (packed && extended_logical == false)
4709 value_offset = offset + 1;
4710 segment_len = 3;
4712 else
4714 value_offset = offset + 2;
4715 segment_len = 4;
4718 temp_data = tvb_get_letohs(tvb, value_offset);
4720 if ( generate )
4722 *ret_item = proto_tree_add_uint(path_tree, hf16, tvb, 0, 0, temp_data );
4723 proto_item_set_generated(*ret_item);
4725 else
4727 *ret_item = proto_tree_add_item(path_tree, hf16, tvb, value_offset, 2, ENC_LITTLE_ENDIAN);
4730 if (vals == NULL)
4732 if (logical_seg_type == CI_LOGICAL_SEG_ATTR_ID)
4734 proto_item_append_text(epath_item, "%s: %d", segment_name, temp_data);
4736 else
4738 proto_item_append_text(epath_item, "%s: 0x%04X", segment_name, temp_data);
4741 else
4743 strbuf = wmem_strbuf_new(pinfo->pool, segment_name);
4744 wmem_strbuf_append(strbuf, ": 0x%04X");
4746 proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( pinfo->pool, segment_name, ": 0x%04X" ) ) );
4749 if (value != NULL)
4750 *value = temp_data;
4752 break;
4753 case CI_LOGICAL_SEG_32_BIT:
4754 if (packed && extended_logical == false)
4756 value_offset = offset + 1;
4757 segment_len = 5;
4759 else
4761 value_offset = offset + 2;
4762 segment_len = 6;
4764 temp_data = tvb_get_letohl(tvb, value_offset);
4766 if ( generate )
4768 *ret_item = proto_tree_add_uint(path_tree, hf32, tvb, 0, 0, temp_data );
4769 proto_item_set_generated(*ret_item);
4771 else
4773 *ret_item = proto_tree_add_item(path_tree, hf32, tvb, value_offset, 4, ENC_LITTLE_ENDIAN);
4776 if (vals == NULL)
4778 if (logical_seg_type == CI_LOGICAL_SEG_ATTR_ID)
4780 proto_item_append_text(epath_item, "%s: %d", segment_name, temp_data);
4782 else
4784 proto_item_append_text(epath_item, "%s: 0x%08X", segment_name, temp_data);
4787 else
4789 strbuf = wmem_strbuf_new(pinfo->pool, segment_name);
4790 wmem_strbuf_append(strbuf, ": 0x%08X");
4792 proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( pinfo->pool, segment_name, ": 0x%08X" ) ) );
4795 if (value != NULL)
4796 *value = temp_data;
4798 break;
4799 default:
4800 expert_add_info(pinfo, epath_item, &ei_proto_log_seg_format);
4801 return 0;
4804 if (generate == false)
4806 proto_item_set_len(path_item, segment_len);
4809 return segment_len;
4812 /* Dissect Device ID structure */
4813 void
4814 dissect_deviceid(tvbuff_t *tvb, int offset, proto_tree *tree,
4815 int hf_vendor, int hf_devtype, int hf_prodcode,
4816 int hf_compatibility, int hf_comp_bit, int hf_majrev, int hf_minrev,
4817 bool generate, unsigned encoding)
4819 proto_item* vendor_id_item = proto_tree_add_item(tree, hf_vendor, tvb, offset, 2, encoding);
4820 proto_item* device_type_item = proto_tree_add_item(tree, hf_devtype, tvb, offset + 2, 2, encoding);
4821 proto_item* product_code_item = proto_tree_add_item(tree, hf_prodcode, tvb, offset + 4, 2, encoding);
4823 /* Major revision/Compatibility */
4824 uint8_t compatibility = tvb_get_uint8(tvb, offset + 6);
4826 /* Add Major revision/Compatibility tree */
4827 proto_item* compatibility_item = proto_tree_add_uint_format_value(tree, hf_compatibility,
4828 tvb, offset + 6, 1, compatibility, "%s, Major Revision: %d",
4829 val_to_str_const((compatibility & 0x80) >> 7, cip_com_bit_vals, ""),
4830 compatibility & 0x7F);
4831 proto_tree* compatibility_tree = proto_item_add_subtree(compatibility_item, ett_mcsc);
4833 proto_item* comp_bit_item = proto_tree_add_item(compatibility_tree, hf_comp_bit, tvb, offset + 6, 1, encoding);
4834 proto_item* major_rev_item = proto_tree_add_item(compatibility_tree, hf_majrev, tvb, offset + 6, 1, encoding);
4835 proto_item* minor_rev_item = proto_tree_add_item(tree, hf_minrev, tvb, offset + 7, 1, encoding);
4837 if (generate)
4839 proto_item_set_generated(vendor_id_item);
4840 proto_item_set_generated(device_type_item);
4841 proto_item_set_generated(product_code_item);
4842 proto_item_set_generated(compatibility_item);
4843 proto_item_set_generated(comp_bit_item);
4844 proto_item_set_generated(major_rev_item);
4845 proto_item_set_generated(minor_rev_item);
4849 static void
4850 dissect_net_param16(tvbuff_t *tvb, int offset, proto_tree *tree,
4851 int hf_net_param16, int hf_owner, int hf_type,
4852 int hf_priority, int hf_fixed_var, int hf_con_size, int ncp_ett, cip_connID_info_t* conn_info)
4854 proto_item *net_param_item;
4855 proto_tree *net_param_tree;
4857 net_param_item = proto_tree_add_item(tree, hf_net_param16, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4858 net_param_tree = proto_item_add_subtree(net_param_item, ncp_ett);
4860 /* Add the data to the tree */
4861 proto_tree_add_item(net_param_tree, hf_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4862 proto_tree_add_item_ret_uint(net_param_tree, hf_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, &conn_info->type);
4863 proto_tree_add_item(net_param_tree, hf_priority, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4864 proto_tree_add_item_ret_uint(net_param_tree, hf_fixed_var, tvb, offset, 2, ENC_LITTLE_ENDIAN, &conn_info->connection_size_type);
4865 proto_tree_add_item_ret_uint(net_param_tree, hf_con_size, tvb, offset, 2, ENC_LITTLE_ENDIAN, &conn_info->connection_size);
4868 static void
4869 dissect_net_param32(tvbuff_t *tvb, int offset, proto_tree *tree,
4870 int hf_net_param16, int hf_owner, int hf_type,
4871 int hf_priority, int hf_fixed_var, int hf_con_size, int ncp_ett, cip_connID_info_t* conn_info)
4873 proto_item *net_param_item;
4874 proto_tree *net_param_tree;
4876 net_param_item = proto_tree_add_item(tree, hf_net_param16, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4877 net_param_tree = proto_item_add_subtree(net_param_item, ncp_ett);
4879 /* Add the data to the tree */
4880 proto_tree_add_item(net_param_tree, hf_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4881 proto_tree_add_item_ret_uint(net_param_tree, hf_type, tvb, offset, 4, ENC_LITTLE_ENDIAN, &conn_info->type);
4882 proto_tree_add_item(net_param_tree, hf_priority, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4883 proto_tree_add_item_ret_uint(net_param_tree, hf_fixed_var, tvb, offset, 4, ENC_LITTLE_ENDIAN, &conn_info->connection_size_type);
4884 proto_tree_add_item_ret_uint(net_param_tree, hf_con_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &conn_info->connection_size);
4887 static void
4888 dissect_transport_type_trigger(tvbuff_t *tvb, int offset, proto_tree *tree,
4889 int hf_ttt, int hf_direction, int hf_trigger, int hf_class, int ett)
4891 int* const bits[] = {
4892 &hf_direction,
4893 &hf_trigger,
4894 &hf_class,
4895 NULL
4898 proto_tree_add_bitmask(tree, tvb, offset, hf_ttt, ett, bits, ENC_LITTLE_ENDIAN);
4901 static int dissect_segment_network_extended(packet_info *pinfo, proto_item *epath_item, tvbuff_t *tvb, int offset, bool generate, proto_tree *net_tree)
4903 int data_words;
4904 data_words = tvb_get_uint8(tvb, offset + 1);
4906 if (generate)
4908 proto_item *it;
4909 uint16_t temp_data;
4911 it = proto_tree_add_uint(net_tree, hf_cip_seg_network_size, tvb, 0, 0, data_words);
4912 proto_item_set_generated(it);
4914 temp_data = tvb_get_letohs(tvb, offset + 2);
4915 it = proto_tree_add_uint(net_tree, hf_cip_seg_network_subtype, tvb, 0, 0, temp_data);
4916 proto_item_set_generated(it);
4918 else
4920 proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4921 proto_tree_add_item(net_tree, hf_cip_seg_network_subtype, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4924 // Extended Network Subtype is included in the Number of Data words, so we must have at least 1.
4925 if (data_words < 1)
4927 expert_add_info(pinfo, epath_item, &ei_proto_ext_network);
4928 return 0;
4931 if (generate == false)
4933 /* The first word of the data is the extended segment subtype, so
4934 don't include that in the displayed data block. */
4935 int net_seg_data_offset;
4936 int net_seg_data_len;
4937 net_seg_data_offset = offset + 4;
4938 net_seg_data_len = (data_words - 1) * 2;
4940 if (tvb_reported_length_remaining(tvb, net_seg_data_offset) < net_seg_data_len)
4942 expert_add_info(pinfo, epath_item, &ei_proto_ext_network);
4943 return 0;
4946 uint16_t net_seg_subtype = tvb_get_letohs(tvb, offset + 2);
4948 int data_len_parsed = 0;
4949 switch (net_seg_subtype)
4951 case CI_CONCURRENT_EXTENDED_NETWORK_SEG:
4953 data_len_parsed = 4;
4954 data_len_parsed += dissect_concurrent_connection_network_segment(pinfo, tvb, offset + data_len_parsed, net_tree);
4955 break;
4958 default:
4960 break;
4964 if (net_seg_data_len - data_len_parsed > 0)
4966 proto_tree_add_item(net_tree, hf_cip_data, tvb, net_seg_data_offset + data_len_parsed, net_seg_data_len - data_len_parsed, ENC_NA);
4970 return data_words * 2 + 2;
4973 static int dissect_segment_network_production_inhibit_us(tvbuff_t *tvb, int offset, bool generate, proto_tree *net_tree)
4975 int data_words;
4976 uint32_t inhibit_time;
4978 data_words = tvb_get_uint8(tvb, offset + 1);
4979 inhibit_time = tvb_get_letohl(tvb, offset + 2);
4981 if (generate == true)
4983 proto_item *it;
4984 it = proto_tree_add_uint(net_tree, hf_cip_seg_network_size, tvb, 0, 0, data_words);
4985 proto_item_set_generated(it);
4987 it = proto_tree_add_uint(net_tree, hf_cip_seg_prod_inhibit_time_us, tvb, 0, 0, inhibit_time);
4988 proto_item_set_generated(it);
4990 else
4992 proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4993 proto_tree_add_item(net_tree, hf_cip_seg_prod_inhibit_time_us,
4994 tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
4997 return (data_words * 2) + 2;
5000 static int dissect_segment_symbolic(tvbuff_t *tvb, proto_tree *path_seg_tree,
5001 proto_item *path_seg_item, proto_item *epath_item,
5002 int offset, bool generate)
5004 int seg_size;
5005 proto_item *it;
5006 uint8_t symbol_size;
5008 symbol_size = tvb_get_uint8(tvb, offset) & 0x1F;
5009 if (generate)
5011 it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_size, tvb, 0, 0, symbol_size);
5012 proto_item_set_generated(it);
5014 else
5016 proto_tree_add_item(path_seg_tree, hf_cip_symbol_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5019 if (symbol_size != 0)
5021 char *symbol_name;
5022 symbol_name = tvb_format_text(wmem_packet_scope(), tvb, offset + 1, symbol_size);
5024 proto_item_append_text(path_seg_item, " (Symbolic Segment)");
5026 if (generate)
5028 it = proto_tree_add_string(path_seg_tree, hf_cip_symbol_ascii, tvb, 0, 0, symbol_name);
5029 proto_item_set_generated(it);
5031 else
5033 proto_tree_add_item(path_seg_tree, hf_cip_symbol_ascii, tvb, offset + 1, symbol_size, ENC_ASCII | ENC_NA);
5036 proto_item_append_text(epath_item, "%s", symbol_name);
5038 seg_size = symbol_size + 1;
5040 else
5042 /* Extended String */
5043 uint8_t string_format;
5044 uint8_t string_size;
5045 int data_size = 0;
5047 proto_item_append_text(path_seg_item, " (Extended String Symbolic Segment)");
5049 string_format = tvb_get_uint8(tvb, offset + 1) & CI_SYMBOL_SEG_FORMAT_MASK;
5050 string_size = tvb_get_uint8(tvb, offset + 1) & CI_SYMBOL_SEG_SIZE_MASK;
5052 if (generate)
5054 it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_extended_format, tvb, 0, 0, string_format);
5055 proto_item_set_generated(it);
5057 else
5059 proto_tree_add_item(path_seg_tree, hf_cip_symbol_extended_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5062 switch (string_format)
5064 case CI_SYMBOL_SEG_DOUBLE:
5065 data_size = string_size * 2;
5067 if (generate)
5069 it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_double_size, tvb, 0, 0, string_size);
5070 proto_item_set_generated(it);
5072 else
5074 proto_tree_add_item(path_seg_tree, hf_cip_symbol_double_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5075 proto_tree_add_item(path_seg_tree, hf_cip_data, tvb, offset + 2, data_size, ENC_NA);
5078 proto_item_append_text(epath_item, "[Data]");
5080 break;
5081 case CI_SYMBOL_SEG_TRIPLE:
5082 data_size = string_size * 3;
5084 if (generate)
5086 it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_triple_size, tvb, 0, 0, string_size);
5087 proto_item_set_generated(it);
5089 else
5091 proto_tree_add_item(path_seg_tree, hf_cip_symbol_triple_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5092 proto_tree_add_item(path_seg_tree, hf_cip_data, tvb, offset + 2, data_size, ENC_NA);
5095 proto_item_append_text(epath_item, "[Data]");
5097 break;
5098 case CI_SYMBOL_SEG_NUMERIC:
5100 uint32_t numeric_data;
5102 if (generate)
5104 it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_numeric_format, tvb, 0, 0, string_size);
5105 proto_item_set_generated(it);
5107 else
5109 proto_tree_add_item(path_seg_tree, hf_cip_symbol_numeric_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5112 if (string_size == CI_SYMBOL_NUMERIC_USINT)
5114 data_size = 1;
5115 numeric_data = tvb_get_uint8(tvb, offset + 2);
5117 if (generate)
5119 it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_usint, tvb, 0, 0, numeric_data);
5120 proto_item_set_generated(it);
5122 else
5124 proto_tree_add_item(path_seg_tree, hf_cip_numeric_usint, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
5127 else if (string_size == CI_SYMBOL_NUMERIC_UINT)
5129 data_size = 2;
5130 numeric_data = tvb_get_letohs(tvb, offset + 2);
5132 if (generate)
5134 it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_uint, tvb, 0, 0, numeric_data);
5135 proto_item_set_generated(it);
5137 else
5139 proto_tree_add_item(path_seg_tree, hf_cip_numeric_uint, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
5142 else if (string_size == CI_SYMBOL_NUMERIC_UDINT)
5144 data_size = 4;
5145 numeric_data = tvb_get_letohl(tvb, offset + 2);
5147 if (generate)
5149 it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_udint, tvb, 0, 0, numeric_data);
5150 proto_item_set_generated(it);
5152 else
5154 proto_tree_add_item(path_seg_tree, hf_cip_numeric_udint, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
5157 else
5159 /* Unknown Extended String Format. */
5160 return 0;
5163 proto_item_append_text(epath_item, "0x%x", numeric_data);
5165 break;
5167 default:
5168 /* Unknown Extended String Format. */
5169 return 0;
5172 seg_size = 2 + data_size;
5175 /* Add padding. */
5176 seg_size += seg_size % 2;
5178 return seg_size;
5181 static int dissect_segment_port(tvbuff_t* tvb, int offset, bool generate,
5182 proto_tree* path_seg_tree, proto_item* path_seg_item, proto_item* epath_item)
5184 int segment_len = 0;
5185 bool extended_port = false;
5186 int extended_port_offset = 0;
5187 uint8_t segment_type = tvb_get_uint8(tvb, offset);
5189 /* Add Extended Link Address flag & Port Identifier*/
5190 if (generate)
5192 proto_item* it = proto_tree_add_boolean(path_seg_tree, hf_cip_port_ex_link_addr, tvb, 0, 0, segment_type & CI_PORT_SEG_EX_LINK_ADDRESS);
5193 proto_item_set_generated(it);
5194 it = proto_tree_add_uint(path_seg_tree, hf_cip_port, tvb, 0, 0, (segment_type & CI_PORT_SEG_PORT_ID_MASK));
5195 proto_item_set_generated(it);
5197 else
5199 proto_tree_add_item(path_seg_tree, hf_cip_port_ex_link_addr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5200 proto_tree_add_item(path_seg_tree, hf_cip_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5203 uint8_t port_id = segment_type & CI_PORT_SEG_PORT_ID_MASK;
5204 if (port_id == 0xF)
5206 extended_port = true;
5209 proto_item_append_text(path_seg_item, " (Port Segment)");
5211 const char *port_name = try_val_to_str(port_id, cip_port_number_vals);
5212 if (port_name)
5214 proto_item_append_text(epath_item, "Port: %s", port_name);
5216 else
5218 proto_item_append_text(epath_item, "Port: %d", port_id);
5221 if (segment_type & CI_PORT_SEG_EX_LINK_ADDRESS)
5223 int offset_link_address = 2;
5225 if (extended_port == true)
5227 offset_link_address += 2;
5228 extended_port_offset = offset + 2;
5231 uint8_t opt_link_size = tvb_get_uint8(tvb, offset + 1);
5233 if (generate)
5235 /* Add size of extended link address */
5236 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_link_address_size, tvb, 0, 0, opt_link_size);
5237 proto_item_set_generated(it);
5238 /* Add extended link address */
5239 it = proto_tree_add_string(path_seg_tree, hf_cip_link_address_string, tvb, 0, 0, tvb_format_text(wmem_packet_scope(), tvb, offset + offset_link_address, opt_link_size));
5240 proto_item_set_generated(it);
5242 else
5244 proto_tree_add_item(path_seg_tree, hf_cip_link_address_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5245 proto_tree_add_item(path_seg_tree, hf_cip_link_address_string, tvb, offset + offset_link_address, opt_link_size, ENC_ASCII | ENC_NA);
5248 proto_item_append_text(epath_item, ", Address: %s", tvb_format_text(wmem_packet_scope(), tvb, offset + offset_link_address, opt_link_size));
5250 /* Pad byte */
5251 if (opt_link_size % 2)
5253 segment_len = 1 + offset_link_address + opt_link_size;
5255 else
5257 segment_len = offset_link_address + opt_link_size;
5260 else
5262 int offset_link_address = 1;
5264 segment_len = 2;
5266 if (extended_port == true)
5268 segment_len += 2;
5269 offset_link_address += 2;
5270 extended_port_offset = offset + 1;
5273 /* Add Link Address */
5274 if (generate)
5276 uint8_t link_address_byte = tvb_get_uint8(tvb, offset + offset_link_address);
5277 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_link_address_byte, tvb, 0, 0, link_address_byte);
5278 proto_item_set_generated(it);
5280 else
5282 proto_tree_add_item(path_seg_tree, hf_cip_link_address_byte, tvb, offset + offset_link_address, 1, ENC_LITTLE_ENDIAN);
5285 proto_item_append_text(epath_item, ", Address: %d", tvb_get_uint8(tvb, offset + offset_link_address));
5288 if (extended_port == true)
5290 if (generate)
5292 uint16_t port_extended = tvb_get_letohs(tvb, extended_port_offset);
5293 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_port_extended, tvb, 0, 0, port_extended);
5294 proto_item_set_generated(it);
5296 else
5298 proto_tree_add_item(path_seg_tree, hf_cip_port_extended, tvb, extended_port_offset, 2, ENC_LITTLE_ENDIAN);
5302 if (generate == false)
5304 proto_item_set_len(path_seg_item, segment_len);
5307 return segment_len;
5310 static int dissect_segment_safety(packet_info* pinfo, tvbuff_t* tvb, int offset, bool generate,
5311 proto_tree* net_tree, cip_safety_epath_info_t* safety, cip_simple_request_info_t* req_data)
5313 uint16_t seg_size = tvb_get_uint8(tvb, offset + 1) * 2;
5314 int segment_len = seg_size + 2;
5316 uint32_t safety_format;
5317 if (generate)
5319 safety_format = tvb_get_uint8(tvb, offset + 2);
5321 proto_item* it = proto_tree_add_uint(net_tree, hf_cip_seg_network_size, tvb, 0, 0, seg_size / 2);
5322 proto_item_set_generated(it);
5324 it = proto_tree_add_uint(net_tree, hf_cip_seg_safety_format, tvb, 0, 0, safety_format);
5325 proto_item_set_generated(it);
5327 /* Skip printing further information in response packets. */
5328 return segment_len;
5330 else
5332 proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5333 proto_tree_add_item_ret_uint(net_tree, hf_cip_seg_safety_format, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN, &safety_format);
5336 /* Safety Network Segment Format */
5337 if (safety_format < 3)
5339 cip_connID_info_t ignore;
5340 proto_tree* safety_tree = proto_tree_add_subtree(net_tree, tvb, offset + 3, seg_size - 1,
5341 ett_network_seg_safety, NULL, val_to_str_const(safety_format, cip_safety_segment_format_type_vals, "Reserved"));
5343 bool has_scid = false;
5344 uint32_t ntem_value = 0;
5345 switch (safety_format)
5347 case 0:
5349 has_scid = true;
5351 /* Target Format - Deprecated*/
5352 if (safety != NULL)
5353 safety->format = CIP_SAFETY_BASE_FORMAT;
5355 proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
5356 proto_tree_add_item(safety_tree, hf_cip_seg_safety_configuration_crc, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
5357 dissect_cipsafety_snn(safety_tree, tvb, pinfo, offset + 8,
5358 hf_cip_seg_safety_configuration_timestamp, hf_cip_seg_safety_configuration_date, hf_cip_seg_safety_configuration_time);
5359 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 14, 4, ENC_LITTLE_ENDIAN);
5360 dissect_net_param16(tvb, offset + 18, safety_tree,
5361 hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
5362 hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
5363 hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
5364 ett_network_seg_safety_time_correction_net_params, &ignore);
5365 proto_item* it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_tunid, tvb, offset + 20, 10, ENC_NA);
5366 dissect_unid(tvb, pinfo, offset + 20, it, "Target UNID SNN", hf_cip_seg_safety_tunid_snn_timestamp,
5367 hf_cip_seg_safety_tunid_snn_date, hf_cip_seg_safety_tunid_snn_time, hf_cip_seg_safety_tunid_nodeid,
5368 ett_cip_seg_safety_tunid, ett_cip_seg_safety_tunid_snn);
5369 it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_ounid, tvb, offset + 30, 10, ENC_NA);
5370 dissect_unid(tvb, pinfo, offset + 30, it, "Originator UNID SNN", hf_cip_seg_safety_ounid_snn_timestamp,
5371 hf_cip_seg_safety_ounid_snn_date, hf_cip_seg_safety_ounid_snn_time, hf_cip_seg_safety_ounid_nodeid,
5372 ett_cip_seg_safety_ounid, ett_cip_seg_safety_ounid_snn);
5373 proto_tree_add_item(safety_tree, hf_cip_seg_safety_ping_epi_multiplier, tvb, offset + 40, 2, ENC_LITTLE_ENDIAN);
5374 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_coord_msg_min_multiplier, tvb, offset + 42, 2, ENC_LITTLE_ENDIAN);
5375 proto_tree_add_item_ret_uint(safety_tree, hf_cip_seg_safety_network_time_expected_multiplier, tvb, offset + 44, 2, ENC_LITTLE_ENDIAN, &ntem_value);
5376 proto_tree_add_item(safety_tree, hf_cip_seg_safety_timeout_multiplier, tvb, offset + 46, 1, ENC_LITTLE_ENDIAN);
5377 proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_consumer_number, tvb, offset + 47, 1, ENC_LITTLE_ENDIAN);
5378 proto_tree_add_item(safety_tree, hf_cip_seg_safety_conn_param_crc, tvb, offset + 48, 4, ENC_LITTLE_ENDIAN);
5379 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 52, 4, ENC_LITTLE_ENDIAN);
5380 break;
5382 case 1:
5383 /* Router Format */
5384 if (safety != NULL)
5385 safety->format = CIP_SAFETY_BASE_FORMAT;
5387 proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
5388 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
5389 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN);
5390 dissect_net_param16(tvb, offset + 12, safety_tree,
5391 hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
5392 hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
5393 hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
5394 ett_network_seg_safety_time_correction_net_params, &ignore);
5395 break;
5396 case 2:
5398 has_scid = true;
5400 /* Extended Format */
5401 if (safety != NULL)
5402 safety->format = CIP_SAFETY_EXTENDED_FORMAT;
5404 proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
5405 proto_tree_add_item(safety_tree, hf_cip_seg_safety_configuration_crc, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
5406 dissect_cipsafety_snn(safety_tree, tvb, pinfo, offset + 8,
5407 hf_cip_seg_safety_configuration_timestamp, hf_cip_seg_safety_configuration_date, hf_cip_seg_safety_configuration_time);
5408 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 14, 4, ENC_LITTLE_ENDIAN);
5409 dissect_net_param16(tvb, offset + 18, safety_tree,
5410 hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
5411 hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
5412 hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
5413 ett_network_seg_safety_time_correction_net_params, &ignore);
5414 proto_item* it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_tunid, tvb, offset + 20, 10, ENC_NA);
5415 dissect_unid(tvb, pinfo, offset + 20, it, "Target UNID SNN", hf_cip_seg_safety_tunid_snn_timestamp,
5416 hf_cip_seg_safety_tunid_snn_date, hf_cip_seg_safety_tunid_snn_time, hf_cip_seg_safety_tunid_nodeid,
5417 ett_cip_seg_safety_tunid, ett_cip_seg_safety_tunid_snn);
5418 it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_ounid, tvb, offset + 30, 10, ENC_NA);
5419 dissect_unid(tvb, pinfo, offset + 30, it, "Originator UNID SNN", hf_cip_seg_safety_ounid_snn_timestamp,
5420 hf_cip_seg_safety_ounid_snn_date, hf_cip_seg_safety_ounid_snn_time, hf_cip_seg_safety_ounid_nodeid,
5421 ett_cip_seg_safety_ounid, ett_cip_seg_safety_ounid_snn);
5422 proto_tree_add_item(safety_tree, hf_cip_seg_safety_ping_epi_multiplier, tvb, offset + 40, 2, ENC_LITTLE_ENDIAN);
5423 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_coord_msg_min_multiplier, tvb, offset + 42, 2, ENC_LITTLE_ENDIAN);
5424 proto_tree_add_item_ret_uint(safety_tree, hf_cip_seg_safety_network_time_expected_multiplier, tvb, offset + 44, 2, ENC_LITTLE_ENDIAN, &ntem_value);
5425 proto_tree_add_item(safety_tree, hf_cip_seg_safety_timeout_multiplier, tvb, offset + 46, 1, ENC_LITTLE_ENDIAN);
5426 proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_consumer_number, tvb, offset + 47, 1, ENC_LITTLE_ENDIAN);
5427 proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_fault_number, tvb, offset + 48, 2, ENC_LITTLE_ENDIAN);
5428 proto_tree_add_item(safety_tree, hf_cip_seg_safety_conn_param_crc, tvb, offset + 50, 4, ENC_LITTLE_ENDIAN);
5429 proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 54, 4, ENC_LITTLE_ENDIAN);
5430 proto_tree_add_item(safety_tree, hf_cip_seg_safety_init_timestamp, tvb, offset + 58, 2, ENC_LITTLE_ENDIAN);
5431 proto_tree_add_item(safety_tree, hf_cip_seg_safety_init_rollover, tvb, offset + 60, 2, ENC_LITTLE_ENDIAN);
5432 break;
5434 } // END switch
5436 if (safety && req_data && has_scid)
5438 // Check if the SCID (SCCRC + SCTS) is all zeros.
5439 uint32_t sccrc_value = tvb_get_letohl(tvb, offset + 4);
5440 uint64_t scts_value = tvb_get_letoh48(tvb, offset + 8);
5441 bool scid_zero = (sccrc_value == 0) && (scts_value == 0);
5443 if (req_data->hasSimpleData)
5445 safety->safety_open_type = CIP_SAFETY_OPEN_TYPE1;
5447 else if (scid_zero)
5449 safety->safety_open_type = CIP_SAFETY_OPEN_TYPE2B;
5451 else
5453 safety->safety_open_type = CIP_SAFETY_OPEN_TYPE2A;
5457 if (safety)
5459 safety->nte_value_ms = ntem_value * 0.128f;
5462 else
5464 proto_tree_add_item(net_tree, hf_cip_seg_safety_data, tvb, offset + 3, seg_size - 1, ENC_NA);
5467 if (safety != NULL)
5469 safety->safety_seg = true;
5472 return segment_len;
5475 static int dissect_segment_data_simple(packet_info* pinfo, tvbuff_t* tvb, int offset, bool generate,
5476 proto_tree* path_seg_tree, proto_item* path_seg_item, cip_simple_request_info_t* req_data)
5478 if (req_data)
5480 req_data->hasSimpleData = true;
5483 uint16_t seg_size = tvb_get_uint8(tvb, offset + 1) * 2;
5484 int segment_len = seg_size + 2;
5486 if (generate)
5488 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_size_simple, tvb, 0, 0, seg_size / 2);
5489 proto_item_set_generated(it);
5491 else
5493 proto_tree_add_item(path_seg_tree, hf_cip_data_seg_size_simple, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5496 if (generate)
5498 return segment_len;
5501 /* Segment data */
5502 if (seg_size != 0)
5504 int parsed_data_len = 0;
5505 if (req_data && req_data->iClass == CI_CLS_MOTION
5506 && req_data->iConnPointA != SEGMENT_VALUE_NOT_SET
5507 && req_data->iConnPoint != SEGMENT_VALUE_NOT_SET)
5509 parsed_data_len += dissect_motion_configuration_block(tvb, pinfo, path_seg_tree, path_seg_item, offset + 2);
5512 int remaining_data_len = seg_size - parsed_data_len;
5513 if (remaining_data_len > 0)
5515 proto_tree_add_item(path_seg_tree, hf_cip_data_seg_item, tvb, offset + 2 + parsed_data_len, remaining_data_len, ENC_NA);
5519 proto_item_set_len(path_seg_item, segment_len);
5521 return segment_len;
5524 static int dissect_segment_ansi_extended_symbol(packet_info* pinfo, tvbuff_t* tvb, int offset,
5525 bool generate, proto_tree* path_seg_tree, proto_item* path_seg_item,
5526 proto_item* epath_item, int display_type,
5527 bool is_msp_item, proto_item* msp_item)
5529 /* Segment size */
5530 uint16_t seg_size = tvb_get_uint8(tvb, offset + 1);
5531 if (generate)
5533 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_size_extended, tvb, 0, 0, seg_size);
5534 proto_item_set_generated(it);
5536 else
5537 proto_tree_add_item(path_seg_tree, hf_cip_data_seg_size_extended, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5539 /* Segment data */
5540 if (seg_size != 0)
5542 char* symbol_name = tvb_format_text(pinfo->pool, tvb, offset + 2, seg_size);
5544 if (generate)
5546 proto_item* it = proto_tree_add_string(path_seg_tree, hf_cip_symbol, tvb, 0, 0, symbol_name);
5547 proto_item_set_generated(it);
5549 else
5550 proto_tree_add_item(path_seg_tree, hf_cip_symbol, tvb, offset + 2, seg_size, ENC_ASCII | ENC_NA);
5552 proto_item_append_text(epath_item, "%s", symbol_name);
5554 if (cip_enhanced_info_column == true && is_msp_item == false)
5556 add_cip_symbol_to_info_column(pinfo, symbol_name, display_type);
5559 if (msp_item != NULL)
5561 proto_item_append_text(msp_item, "'%s' - ", symbol_name);
5565 /* Check for pad byte */
5566 if (seg_size % 2)
5567 seg_size++;
5569 if (!generate)
5571 proto_item_set_len(path_seg_item, 2 + seg_size);
5574 return 2 + seg_size;
5577 // offset - Starts with the 'Key Data' section of the Electronic Key Segment Format.
5578 int dissect_electronic_key_format(tvbuff_t* tvb, int offset, proto_tree* tree, bool generate, uint8_t key_format, unsigned encoding)
5580 int key_len;
5581 if (key_format == CI_E_KEY_FORMAT_VAL)
5583 key_len = 8;
5585 else // CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL
5587 key_len = 12;
5590 if (generate)
5592 dissect_deviceid(tvb, offset, tree,
5593 hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
5594 hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, true, encoding);
5596 else
5598 dissect_deviceid(tvb, offset, tree,
5599 hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
5600 hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, false, encoding);
5602 if (key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
5604 proto_tree_add_item(tree, hf_cip_ekey_serial_number, tvb, offset + 8, 4, encoding);
5608 return key_len;
5611 static int dissect_segment_logical_special(packet_info* pinfo, tvbuff_t* tvb, int offset,
5612 bool generate, proto_tree* path_seg_tree,
5613 proto_item* path_seg_item, proto_item* epath_item)
5615 int segment_len = 0;
5617 uint8_t segment_type = tvb_get_uint8(tvb, offset);
5619 /* Logical Special ID, the only logical format specified is electronic key */
5620 if ((segment_type & CI_LOGICAL_SEG_FORMAT_MASK) == CI_LOGICAL_SEG_E_KEY)
5622 uint8_t key_format = tvb_get_uint8(tvb, offset + 1);
5623 if (key_format == CI_E_KEY_FORMAT_VAL || key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
5625 if (generate)
5627 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_ekey_format, tvb, 0, 0, key_format);
5628 proto_item_set_generated(it);
5630 else
5632 proto_tree_add_item(path_seg_tree, hf_cip_ekey_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5634 segment_len = 2;
5636 segment_len += dissect_electronic_key_format(tvb, offset + 2, path_seg_tree, generate, key_format, ENC_LITTLE_ENDIAN);
5638 proto_item_set_len(path_seg_item, segment_len);
5640 /* Add "summary" information to parent item */
5641 uint16_t vendor_id = tvb_get_letohs(tvb, offset + 2);
5642 proto_item_append_text(path_seg_tree, " (VendorID: 0x%04X", vendor_id);
5644 uint16_t device_type = tvb_get_letohs(tvb, offset + 4);
5645 proto_item_append_text(path_seg_tree, ", DevTyp: 0x%04X", device_type);
5647 uint8_t major_rev = tvb_get_uint8(tvb, offset + 8);
5648 uint8_t minor_rev = tvb_get_uint8(tvb, offset + 9);
5650 proto_item_append_text(path_seg_tree, ", %d.%d)", (major_rev & 0x7F), minor_rev);
5651 proto_item_append_text(epath_item, "[Key]");
5653 else
5655 expert_add_info(pinfo, epath_item, &ei_proto_electronic_key_format);
5658 else
5660 expert_add_info(pinfo, epath_item, &ei_proto_special_segment_format);
5663 return segment_len;
5666 static int dissect_segment_network(packet_info* pinfo, tvbuff_t* tvb, int offset,
5667 bool generate, proto_tree* path_seg_tree, proto_item* path_seg_item,
5668 proto_item* epath_item, int display_type, cip_safety_epath_info_t* safety,
5669 cip_simple_request_info_t* req_data)
5671 int segment_len = 0;
5673 uint8_t segment_type = tvb_get_uint8(tvb, offset);
5675 /* Network segment -Determine the segment sub-type */
5676 if (generate)
5678 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_network_seg_type, tvb, 0, 0, segment_type & CI_NETWORK_SEG_TYPE_MASK);
5679 proto_item_set_generated(it);
5681 else
5683 proto_tree_add_item(path_seg_tree, hf_cip_network_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5686 proto_item_append_text(path_seg_item, " (%s)", val_to_str_const((segment_type & CI_NETWORK_SEG_TYPE_MASK), cip_network_segment_type_vals, "Reserved"));
5688 switch (segment_type & CI_NETWORK_SEG_TYPE_MASK)
5690 case CI_NETWORK_SEG_SCHEDULE:
5691 if (generate)
5693 uint8_t schedule = tvb_get_uint8(tvb, offset + 1);
5694 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_schedule, tvb, 0, 0, schedule);
5695 proto_item_set_generated(it);
5697 else
5699 proto_tree_add_item(path_seg_tree, hf_cip_seg_schedule, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5702 segment_len = 2;
5703 break;
5705 case CI_NETWORK_SEG_FIXED_TAG:
5706 if (generate)
5708 uint8_t fixed_tag = tvb_get_uint8(tvb, offset + 1);
5709 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_fixed_tag, tvb, 0, 0, fixed_tag);
5710 proto_item_set_generated(it);
5712 else
5714 proto_tree_add_item(path_seg_tree, hf_cip_seg_fixed_tag, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5717 segment_len = 2;
5718 break;
5720 case CI_NETWORK_SEG_PROD_INHI:
5721 if (generate)
5723 uint8_t inhibit_time = tvb_get_uint8(tvb, offset + 1);
5724 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_prod_inhibit_time, tvb, 0, 0, inhibit_time);
5725 proto_item_set_generated(it);
5727 else
5729 proto_tree_add_item(path_seg_tree, hf_cip_seg_prod_inhibit_time, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5732 segment_len = 2;
5733 break;
5735 case CI_NETWORK_SEG_PROD_INHI_US:
5736 segment_len = dissect_segment_network_production_inhibit_us(tvb, offset, generate, path_seg_tree);
5737 break;
5739 case CI_NETWORK_SEG_EXTENDED:
5740 segment_len = dissect_segment_network_extended(pinfo, epath_item, tvb, offset, generate, path_seg_tree);
5741 proto_item_append_text(epath_item, "[Network]");
5742 break;
5744 case CI_NETWORK_SEG_SAFETY:
5745 proto_item_append_text(epath_item, "[Safety]");
5747 if (display_type == DISPLAY_CONNECTION_PATH)
5749 col_append_str(pinfo->cinfo, COL_INFO, " [Safety]");
5752 segment_len = dissect_segment_safety(pinfo, tvb, offset, generate, path_seg_tree, safety, req_data);
5753 break;
5755 default:
5756 expert_add_info(pinfo, epath_item, &ei_proto_log_sub_seg_type);
5757 segment_len = 0;
5758 break;
5759 } /* End of switch sub-type */
5761 if (generate == false)
5763 proto_item_set_len(path_seg_item, segment_len);
5766 return segment_len;
5769 static int dissect_segment_logical_service_id(packet_info* pinfo, tvbuff_t* tvb, int offset,
5770 bool generate, proto_tree* path_seg_tree, proto_item* path_seg_item, proto_item* epath_item)
5772 int segment_len = 0;
5774 uint8_t segment_type = tvb_get_uint8(tvb, offset);
5776 /* Logical Service ID - the only logical format specified is 8-bit Service ID */
5777 if ((segment_type & CI_LOGICAL_SEG_FORMAT_MASK) == CI_LOGICAL_SEG_8_BIT)
5779 uint8_t service_id = tvb_get_uint8(tvb, offset + 1);
5781 if (generate)
5783 proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_serviceid8, tvb, 0, 0, service_id);
5784 proto_item_set_generated(it);
5786 else
5788 proto_tree_add_item(path_seg_tree, hf_cip_serviceid8, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
5790 proto_item_set_len(path_seg_item, 2);
5793 proto_item_append_text(epath_item, "Service ID: 0x%x", service_id);
5795 segment_len = 2;
5797 else
5799 expert_add_info(pinfo, epath_item, &ei_proto_log_seg_type);
5802 return segment_len;
5805 int dissect_cip_segment_single(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *path_tree, proto_item *epath_item,
5806 bool generate, bool packed, cip_simple_request_info_t* req_data, cip_safety_epath_info_t* safety,
5807 int display_type, proto_item *msp_item,
5808 bool is_msp_item)
5810 int segment_len = 0;
5811 unsigned char segment_type;
5812 proto_tree *path_seg_tree;
5813 proto_item *it, *cia_ret_item;
5814 proto_item *path_seg_item;
5817 if (tvb_reported_length_remaining(tvb, offset) <= 0)
5819 expert_add_info(pinfo, epath_item, &ei_mal_incomplete_epath);
5820 return 0;
5823 /* Get segment type */
5824 segment_type = tvb_get_uint8( tvb, offset );
5826 if ( generate )
5828 path_seg_item = proto_tree_add_uint(path_tree, hf_cip_path_segment, tvb, 0, 0, segment_type );
5829 proto_item_set_generated(path_seg_item);
5830 path_seg_tree = proto_item_add_subtree( path_seg_item, ett_path_seg );
5831 it = proto_tree_add_uint(path_seg_tree, hf_cip_path_segment_type, tvb, 0, 0, segment_type&CI_SEGMENT_TYPE_MASK);
5832 proto_item_set_generated(it);
5834 else
5836 path_seg_item = proto_tree_add_item(path_tree, hf_cip_path_segment, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5837 path_seg_tree = proto_item_add_subtree( path_seg_item, ett_path_seg );
5838 proto_tree_add_item(path_seg_tree, hf_cip_path_segment_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5841 /* Determine the segment type */
5843 switch( segment_type & CI_SEGMENT_TYPE_MASK )
5845 case CI_PORT_SEGMENT:
5847 segment_len = dissect_segment_port(tvb, offset, generate, path_seg_tree, path_seg_item, epath_item);
5848 break;
5851 case CI_LOGICAL_SEGMENT:
5853 uint8_t logical_seg_type;
5854 logical_seg_type = segment_type & CI_LOGICAL_SEG_TYPE_MASK;
5856 /* Logical segment, determine the logical type */
5857 if ( generate )
5859 it = proto_tree_add_uint(path_seg_tree, hf_cip_logical_seg_type, tvb, 0, 0, logical_seg_type);
5860 proto_item_set_generated(it);
5861 if (logical_seg_type != CI_LOGICAL_SEG_SPECIAL && logical_seg_type != CI_LOGICAL_SEG_SERV_ID)
5863 it = proto_tree_add_uint(path_seg_tree, hf_cip_logical_seg_format, tvb, 0, 0, segment_type & CI_LOGICAL_SEG_FORMAT_MASK);
5864 proto_item_set_generated(it);
5867 else
5869 proto_tree_add_item(path_seg_tree, hf_cip_logical_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
5870 if (logical_seg_type != CI_LOGICAL_SEG_SPECIAL && logical_seg_type != CI_LOGICAL_SEG_SERV_ID)
5871 proto_tree_add_item(path_seg_tree, hf_cip_logical_seg_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5874 proto_item_append_text( path_seg_item, " (%s)", val_to_str_const( ((segment_type & (CI_LOGICAL_SEG_TYPE_MASK|CI_LOGICAL_SEG_FORMAT_MASK))), cip_logical_seg_vals, "Reserved"));
5876 switch (logical_seg_type)
5878 case CI_LOGICAL_SEG_CLASS_ID:
5880 uint32_t ClassID;
5881 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5882 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5883 "Class", cip_class_names_vals, &ClassID,
5884 hf_cip_class8, hf_cip_class16, hf_cip_class32);
5885 if (segment_len == 0)
5887 return 0;
5890 if (req_data)
5892 req_data->iClass = ClassID;
5894 // Save the first ClassID separately.
5895 if (req_data->iClassA == SEGMENT_VALUE_NOT_SET)
5897 req_data->iClassA = ClassID;
5901 if (req_data != NULL)
5903 if (cip_enhanced_info_column == true && is_msp_item == false)
5905 add_cip_class_to_info_column(pinfo, req_data->iClass, display_type);
5908 if (msp_item != NULL)
5910 proto_item_append_text(msp_item, "%s - ", val_to_str(req_data->iClass, cip_class_names_vals, "Class (0x%02x)"));
5914 break;
5917 case CI_LOGICAL_SEG_INST_ID:
5919 uint32_t InstanceID;
5920 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5921 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5922 "Instance", NULL, &InstanceID,
5923 hf_cip_instance8, hf_cip_instance16, hf_cip_instance32);
5924 if (segment_len == 0)
5926 return 0;
5929 if (req_data)
5931 req_data->iInstance = InstanceID;
5933 // Save the first InstanceID separately.
5934 if (req_data->iInstanceA == SEGMENT_VALUE_NOT_SET)
5936 req_data->iInstanceA = InstanceID;
5940 break;
5943 case CI_LOGICAL_SEG_MBR_ID:
5944 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5945 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5946 "Member", NULL, (req_data == NULL) ? NULL : &req_data->iMember,
5947 hf_cip_member8, hf_cip_member16, hf_cip_member32);
5948 break;
5950 case CI_LOGICAL_SEG_ATTR_ID:
5951 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5952 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5953 "Attribute", NULL, (req_data == NULL) ? NULL : &req_data->iAttribute,
5954 hf_cip_attribute8, hf_cip_attribute16, hf_cip_attribute32);
5955 if (segment_len == 0)
5957 return 0;
5960 if (req_data != NULL)
5962 const attribute_info_t* att_info = cip_get_attribute(req_data->iClass, req_data->iInstance,
5963 req_data->iAttribute);
5964 if (att_info != NULL)
5966 proto_item_append_text(cia_ret_item, " (%s)", att_info->text);
5967 proto_item_append_text(epath_item, " (%s)", att_info->text);
5970 break;
5972 case CI_LOGICAL_SEG_CON_POINT:
5974 uint32_t ConnPoint;
5975 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5976 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5977 "Connection Point", NULL, &ConnPoint,
5978 hf_cip_conpoint8, hf_cip_conpoint16, hf_cip_conpoint32);
5979 if (segment_len == 0)
5981 return 0;
5984 if (req_data)
5986 req_data->iConnPoint = ConnPoint;
5988 // Save the first ConnPoint separately.
5989 if (req_data->iConnPointA == SEGMENT_VALUE_NOT_SET)
5991 req_data->iConnPointA = ConnPoint;
5995 break;
5998 case CI_LOGICAL_SEG_SPECIAL:
5999 segment_len = dissect_segment_logical_special(pinfo, tvb, offset, generate,
6000 path_seg_tree, path_seg_item, epath_item);
6001 break;
6003 case CI_LOGICAL_SEG_SERV_ID:
6004 segment_len = dissect_segment_logical_service_id(pinfo, tvb, offset, generate,
6005 path_seg_tree, path_seg_item, epath_item);
6006 break;
6008 case CI_LOGICAL_SEG_EXT_LOGICAL:
6009 segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
6010 epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
6011 "Extended Logical", NULL, NULL,
6012 hf_cip_ext_logical8, hf_cip_ext_logical16, hf_cip_ext_logical32);
6013 break;
6015 default:
6016 expert_add_info(pinfo, epath_item, &ei_proto_log_seg_type);
6017 return 0;
6019 } /* end of switch( logical_seg_type ) */
6020 break;
6023 case CI_DATA_SEGMENT:
6025 /* Data segment, determine the logical type */
6026 if ( generate )
6028 it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_type, tvb, 0, 0, segment_type & CI_DATA_SEG_TYPE_MASK);
6029 proto_item_set_generated(it);
6031 else
6033 proto_tree_add_item(path_seg_tree, hf_cip_data_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
6036 proto_item_append_text( path_seg_item, " (%s)", val_to_str_const( (segment_type & CI_DATA_SEG_TYPE_MASK), cip_data_segment_type_vals, "Reserved"));
6038 switch( segment_type & CI_DATA_SEG_TYPE_MASK)
6040 case CI_DATA_SEG_SIMPLE:
6041 segment_len = dissect_segment_data_simple(pinfo, tvb, offset, generate, path_seg_tree, path_seg_item, req_data);
6042 proto_item_append_text(epath_item, "[Data]" );
6043 break;
6045 case CI_DATA_SEG_SYMBOL:
6046 segment_len = dissect_segment_ansi_extended_symbol(pinfo, tvb, offset, generate,
6047 path_seg_tree, path_seg_item, epath_item, display_type, is_msp_item, msp_item);
6048 break;
6050 default:
6051 expert_add_info(pinfo, epath_item, &ei_proto_log_sub_seg_type);
6052 return 0;
6054 } /* End of switch sub-type */
6056 break;
6059 case CI_NETWORK_SEGMENT:
6060 segment_len = dissect_segment_network(pinfo, tvb, offset, generate, path_seg_tree, path_seg_item, epath_item, display_type, safety, req_data);
6061 break;
6063 case CI_SYMBOLIC_SEGMENT:
6065 segment_len = dissect_segment_symbolic(tvb, path_seg_tree,
6066 path_seg_item, epath_item,
6067 offset, generate);
6069 if (segment_len == 0)
6071 expert_add_info(pinfo, epath_item, &ei_proto_ext_string_format);
6072 return 0;
6075 if (generate == false)
6077 proto_item_set_len(path_seg_item, segment_len);
6080 break;
6083 default:
6084 expert_add_info(pinfo, epath_item, &ei_proto_seg_type);
6085 return 0;
6087 } /* end of switch( segment_type & CI_SEGMENT_TYPE_MASK ) */
6090 return segment_len;
6093 void reset_cip_request_info(cip_simple_request_info_t* req_data)
6095 req_data->iClass = SEGMENT_VALUE_NOT_SET;
6096 req_data->iClassA = SEGMENT_VALUE_NOT_SET;
6098 req_data->iInstance = SEGMENT_VALUE_NOT_SET;
6099 req_data->iInstanceA = SEGMENT_VALUE_NOT_SET;
6101 req_data->iAttribute = SEGMENT_VALUE_NOT_SET;
6102 req_data->iMember = SEGMENT_VALUE_NOT_SET;
6104 req_data->iConnPoint = SEGMENT_VALUE_NOT_SET;
6105 req_data->iConnPointA = SEGMENT_VALUE_NOT_SET;
6107 req_data->hasSimpleData = false;
6110 void dissect_epath(tvbuff_t *tvb, packet_info *pinfo, proto_tree *path_tree, proto_item *epath_item, int offset, int path_length,
6111 bool generate, bool packed, cip_simple_request_info_t* req_data, cip_safety_epath_info_t* safety,
6112 int display_type, proto_item *msp_item,
6113 bool is_msp_item)
6115 int pathpos = 0;
6116 proto_item *hidden_item;
6118 if (req_data != NULL)
6120 reset_cip_request_info(req_data);
6123 if (safety != NULL)
6124 safety->safety_seg = false;
6126 if ( !generate )
6128 hidden_item = proto_tree_add_item(path_tree, hf_cip_epath,
6129 tvb, offset, path_length, ENC_NA );
6130 proto_item_set_hidden(hidden_item);
6133 while( pathpos < path_length )
6135 int segment_len;
6136 segment_len = dissect_cip_segment_single(pinfo, tvb, offset + pathpos, path_tree, epath_item, generate, packed, req_data, safety, display_type, msp_item, is_msp_item);
6137 if (segment_len == 0)
6139 break;
6142 pathpos += segment_len;
6144 /* Next path segment */
6145 if( pathpos < path_length )
6146 proto_item_append_text( epath_item, ", " );
6148 } /* end of while( pathpos < path_length ) */
6150 } /* end of dissect_epath() */
6152 #define NUM_SECONDS_PER_DAY ((uint64_t)(60 * 60 * 24))
6154 /* Number of seconds between Jan 1, 1970 00:00:00 epoch and CIP's epoch time of Jan 1, 1972 00:00:00 */
6155 #define CIP_TIMEBASE ((uint64_t)(NUM_SECONDS_PER_DAY * 365 * 2))
6157 void dissect_cip_date_and_time(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_datetime)
6159 nstime_t computed_time;
6160 uint16_t num_days_since_1972;
6161 uint32_t num_ms_today;
6163 num_days_since_1972 = tvb_get_letohs(tvb, offset+4);
6164 num_ms_today = tvb_get_letohl(tvb, offset);
6166 if ((num_days_since_1972 != 0) || (num_ms_today != 0))
6168 computed_time.secs = CIP_TIMEBASE + (uint64_t)num_days_since_1972 * NUM_SECONDS_PER_DAY;
6169 computed_time.secs += num_ms_today/1000;
6170 computed_time.nsecs = (num_ms_today%1000)*1000000;
6172 else
6174 computed_time.secs = 0;
6175 computed_time.nsecs = 0;
6178 proto_tree_add_time(tree, hf_datetime, tvb, offset, 6, &computed_time);
6181 static int dissect_cip_date(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_date)
6183 char date_str[20];
6185 uint16_t num_days_since_1972 = tvb_get_letohs(tvb, offset);
6186 /* Convert to nstime epoch */
6187 time_t computed_time = CIP_TIMEBASE + (uint64_t)num_days_since_1972 * NUM_SECONDS_PER_DAY;
6188 struct tm* date = gmtime(&computed_time);
6190 if (date != NULL)
6191 strftime(date_str, 20, "%Y-%m-%d", date);
6192 else
6193 (void) g_strlcpy(date_str, "Not representable", sizeof date_str);
6194 proto_tree_add_uint_format_value(tree, hf_date, tvb, offset, 2, num_days_since_1972, "%s", date_str);
6196 return 2;
6199 // CIP Type - STIME (nanoseconds)
6200 static int dissect_cip_stime(proto_tree* tree, tvbuff_t* tvb, int offset, int hf_datetime)
6202 nstime_t ts_nstime = { 0 };
6203 uint64_t timestamp = tvb_get_letoh64(tvb, offset);
6204 ts_nstime.secs = timestamp / 1000000000;
6205 ts_nstime.nsecs = timestamp % 1000000000;
6207 proto_tree_add_time(tree, hf_datetime, tvb, offset, 8, &ts_nstime);
6209 return 8;
6212 // CIP Type - UTIME (microseconds)
6213 int dissect_cip_utime(proto_tree* tree, tvbuff_t* tvb, int offset, int hf_datetime)
6215 nstime_t ts_nstime = { 0 };
6216 uint64_t timestamp = tvb_get_letoh64(tvb, offset);
6217 ts_nstime.secs = timestamp / 1000000;
6218 ts_nstime.nsecs = (timestamp % 1000000) * 1000;
6220 proto_tree_add_time(tree, hf_datetime, tvb, offset, 8, &ts_nstime);
6222 return 8;
6225 int dissect_cip_string_type(packet_info *pinfo, proto_tree *tree, proto_item *item,
6226 tvbuff_t *tvb, int offset, int hf_type, int string_type)
6228 uint32_t string_size_field_len;
6229 uint32_t string_size;
6230 unsigned string_encoding;
6231 int parsed_len;
6232 int total_len;
6234 total_len = tvb_reported_length_remaining(tvb, offset);
6236 switch (string_type)
6238 case CIP_SHORT_STRING_TYPE:
6239 string_size = tvb_get_uint8(tvb, offset);
6240 string_encoding = ENC_ASCII | ENC_NA;
6241 string_size_field_len = 1;
6242 break;
6244 case CIP_STRING_TYPE:
6245 string_size = tvb_get_letohs(tvb, offset);
6246 string_encoding = ENC_ASCII | ENC_NA;
6247 string_size_field_len = 2;
6248 break;
6250 case CIP_STRING2_TYPE:
6251 string_size = tvb_get_letohs(tvb, offset) * 2;
6252 string_encoding = ENC_UCS_2 | ENC_LITTLE_ENDIAN;
6253 string_size_field_len = 2;
6254 break;
6256 default:
6257 // Unsupported.
6258 return total_len;
6261 if (total_len < (int)(string_size + string_size_field_len))
6263 expert_add_info(pinfo, item, &ei_mal_missing_string_data);
6264 parsed_len = total_len;
6266 else
6268 proto_tree_add_item(tree, hf_type, tvb, offset + string_size_field_len, string_size, string_encoding);
6269 parsed_len = string_size + string_size_field_len;
6272 return parsed_len;
6275 static int dissect_cip_stringi(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset)
6277 int parsed_len = 1;
6278 uint32_t num_char = 0;
6279 proto_tree_add_item_ret_uint(tree, hf_stringi_number_char, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_char);
6281 for (uint32_t i = 0; i < num_char; ++i)
6283 proto_tree_add_item(tree, hf_stringi_language_char, tvb, offset + 1, 3, ENC_ASCII | ENC_NA);
6285 uint32_t char_string_type = 0;
6286 proto_tree_add_item_ret_uint(tree, hf_stringi_char_string_struct, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN, &char_string_type);
6287 proto_tree_add_item(tree, hf_stringi_char_set, tvb, offset + 5, 2, ENC_LITTLE_ENDIAN);
6288 parsed_len += 6;
6290 if (char_string_type != CIP_STRING_TYPE
6291 && char_string_type != CIP_SHORT_STRING_TYPE
6292 && char_string_type != CIP_STRING2_TYPE)
6294 // Unsupported type.
6295 break;
6298 parsed_len += dissect_cip_string_type(pinfo, tree, item, tvb, offset + parsed_len, hf_stringi_international_string, char_string_type);
6301 return parsed_len;
6304 int dissect_cip_attribute(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
6305 const attribute_info_t* attr, int offset, int total_len)
6307 int i, temp_data, temp_time, hour, min, sec, ms,
6308 consumed = 0;
6310 /* sanity check */
6311 if (((attr->datatype == cip_dissector_func) && (attr->pdissect == NULL)) ||
6312 ((attr->datatype != cip_dissector_func) && (attr->phf == NULL)))
6314 DISSECTOR_ASSERT(0);
6315 return total_len;
6318 switch (attr->datatype)
6320 case cip_bool:
6321 case cip_usint:
6322 case cip_sint:
6323 case cip_byte:
6324 proto_tree_add_item(tree, *(attr->phf), tvb, offset, 1, ENC_LITTLE_ENDIAN);
6325 consumed = 1;
6326 break;
6327 case cip_uint:
6328 case cip_int:
6329 case cip_word:
6330 case cip_itime:
6331 proto_tree_add_item(tree, *(attr->phf), tvb, offset, 2, ENC_LITTLE_ENDIAN);
6332 consumed = 2;
6333 break;
6334 case cip_usint_array:
6335 for (i = 0; i < total_len; i++)
6336 proto_tree_add_item(tree, *(attr->phf), tvb, offset, total_len, ENC_NA);
6337 consumed = total_len;
6338 break;
6339 case cip_uint_array:
6340 for (i = 0; i < total_len; i+=2)
6341 proto_tree_add_item(tree, *(attr->phf), tvb, offset+i, 2, ENC_LITTLE_ENDIAN);
6342 consumed = i;
6343 break;
6344 case cip_udint:
6345 case cip_dint:
6346 case cip_dword:
6347 case cip_real:
6348 case cip_time:
6349 case cip_ftime:
6350 proto_tree_add_item(tree, *(attr->phf), tvb, offset, 4, ENC_LITTLE_ENDIAN);
6351 consumed = 4;
6352 break;
6353 case cip_ulint:
6354 case cip_lint:
6355 case cip_lword:
6356 case cip_lreal:
6357 case cip_ltime:
6358 case cip_ntime:
6359 proto_tree_add_item(tree, *(attr->phf), tvb, offset, 8, ENC_LITTLE_ENDIAN);
6360 consumed = 8;
6361 break;
6362 case cip_short_string:
6363 consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_SHORT_STRING_TYPE);
6364 break;
6365 case cip_string:
6366 consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_STRING_TYPE);
6367 break;
6368 case cip_dissector_func:
6369 consumed = attr->pdissect(pinfo, tree, item, tvb, offset, total_len);
6370 if (consumed == 0)
6372 consumed = total_len;
6375 break;
6376 case cip_date_and_time:
6377 dissect_cip_date_and_time(tree, tvb, offset, *(attr->phf));
6378 consumed = 6;
6379 break;
6380 case cip_stime:
6381 consumed = dissect_cip_stime(tree, tvb, offset, *(attr->phf));
6382 break;
6383 case cip_utime:
6384 consumed = dissect_cip_utime(tree, tvb, offset, *(attr->phf));
6385 break;
6386 case cip_date:
6387 consumed = dissect_cip_date(tree, tvb, offset, *(attr->phf));
6388 break;
6389 case cip_time_of_day:
6390 temp_time = temp_data = tvb_get_letohl( tvb, offset);
6391 hour = temp_time/(60*60*1000);
6392 temp_time %= (60*60*1000);
6393 min = temp_time/(60*1000);
6394 temp_time %= (60*1000);
6395 sec = temp_time/1000;
6396 ms = temp_time%1000;
6397 proto_tree_add_uint_format_value(tree, *(attr->phf), tvb, offset, 4, temp_data, "%02d:%02d:%02d.%03d", hour, min, sec, ms);
6398 consumed = 4;
6399 break;
6400 case cip_string2:
6401 consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_STRING2_TYPE);
6402 break;
6403 case cip_stringi:
6404 consumed = dissect_cip_stringi(pinfo, tree, item, tvb, offset);
6405 break;
6406 case cip_stringN:
6407 /* CURRENTLY NOT SUPPORTED */
6408 expert_add_info(pinfo, item, &ei_proto_unsupported_datatype);
6409 consumed = total_len;
6410 break;
6413 return consumed;
6416 static int dissect_cip_service(packet_info *pinfo, tvbuff_t *tvb, int offset,
6417 proto_item *ti, proto_tree *item_tree, cip_service_info_t *service_entry, uint8_t service)
6419 int parsed_len = 0;
6421 if (service_entry != NULL && service_entry->pdissect)
6423 bool request = !(service & CIP_SC_RESPONSE_MASK);
6424 parsed_len = service_entry->pdissect(pinfo, item_tree, ti, tvb, offset, request);
6427 return parsed_len;
6430 static int dissect_cip_object_specific_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item* msp_item, cip_service_info_t *service_entry)
6432 DISSECTOR_ASSERT(service_entry != NULL);
6434 int offset = 0;
6435 uint8_t service = tvb_get_uint8(tvb, offset);
6436 uint8_t gen_status = 0;
6438 // Skip over the Request/Response header to get to the actual data.
6439 if (service & CIP_SC_RESPONSE_MASK)
6441 gen_status = tvb_get_uint8(tvb, offset + 2);
6443 uint16_t add_stat_size = tvb_get_uint8(tvb, offset + 3) * 2;
6444 offset = 4 + add_stat_size;
6446 else
6448 uint16_t req_path_size = tvb_get_uint8(tvb, offset + 1) * 2;
6449 offset = 2 + req_path_size;
6452 // Display the service name, even if there is no payload data.
6453 if (service_entry->service_name)
6455 col_append_str(pinfo->cinfo, COL_INFO, service_entry->service_name);
6456 col_set_fence(pinfo->cinfo, COL_INFO);
6458 proto_item_append_text(msp_item, "%s", service_entry->service_name);
6461 // Only dissect responses with specific response statuses.
6462 if ((service & CIP_SC_RESPONSE_MASK)
6463 && (should_dissect_cip_response(tvb, offset, gen_status) == false))
6465 return 0;
6468 proto_item *payload_item;
6469 proto_tree *payload_tree = proto_tree_add_subtree(tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), ett_cmd_data, &payload_item, "");
6471 // Add the service info to the tree item.
6472 proto_item_append_text(payload_item, "%s", service_entry->service_name);
6474 if (service & CIP_SC_RESPONSE_MASK)
6476 proto_item_append_text(payload_item, " (Response)");
6478 else
6480 proto_item_append_text(payload_item, " (Request)");
6483 // Process any known command-specific data.
6484 offset += dissect_cip_service(pinfo, tvb, offset, payload_item, payload_tree, service_entry, service);
6486 // Add any remaining data.
6487 int len_remain = tvb_reported_length_remaining(tvb, offset);
6488 if (len_remain > 0)
6490 proto_tree_add_item(payload_tree, hf_cip_data, tvb, offset, len_remain, ENC_NA);
6493 return tvb_reported_length(tvb);
6496 /************************************************
6498 * Dissector for generic CIP object
6500 ************************************************/
6502 static void
6503 dissect_cip_generic_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo, proto_item *ti )
6505 proto_tree *cmd_data_tree;
6506 int req_path_size;
6507 unsigned char add_stat_size;
6508 int cmd_data_len;
6509 int cmd_data_offset;
6510 uint8_t service = tvb_get_uint8( tvb, offset );
6512 if (service & CIP_SC_RESPONSE_MASK)
6514 /* Response message */
6515 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
6516 cmd_data_len = item_length - 4 - add_stat_size;
6517 cmd_data_offset = offset + 4 + add_stat_size;
6519 else
6521 /* Request message */
6522 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
6523 cmd_data_len = item_length - req_path_size - 2;
6524 cmd_data_offset = offset + 2 + req_path_size;
6527 /* If there is any command specific data create a sub-tree for it */
6528 if (cmd_data_len > 0)
6530 cmd_data_tree = proto_tree_add_subtree(item_tree, tvb, cmd_data_offset, cmd_data_len,
6531 ett_cmd_data, NULL, "Command Specific Data");
6532 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, cmd_data_offset, cmd_data_len, ENC_NA);
6534 else
6536 proto_item_set_hidden(ti);
6539 add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
6540 } /* End of dissect_cip_generic_data() */
6542 static int
6543 dissect_cip_class_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
6545 proto_item *ti;
6546 proto_tree *class_tree;
6548 /* Create display subtree for the protocol */
6549 ti = proto_tree_add_item(tree, proto_cip_class_generic, tvb, 0, -1, ENC_NA);
6550 class_tree = proto_item_add_subtree( ti, ett_cip_class_generic );
6552 dissect_cip_generic_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo, ti );
6554 return tvb_reported_length(tvb);
6557 static int
6558 dissect_cip_set_attribute_single_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6559 int offset, cip_simple_request_info_t* req_data)
6561 int parsed_len = 0;
6562 const attribute_info_t* attr;
6564 attr = cip_get_attribute(req_data->iClass, req_data->iInstance, req_data->iAttribute);
6565 if (attr != NULL)
6567 parsed_len = dissect_cip_attribute(pinfo, tree, item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
6570 return parsed_len;
6573 int dissect_cip_get_attribute_list_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6574 int offset, cip_simple_request_info_t* req_data)
6576 int i, att_count, att_value;
6577 const attribute_info_t* pattribute;
6578 proto_item *att_list, *att_item;
6579 proto_tree* att_tree;
6581 /* Get attribute list request */
6582 if (tvb_reported_length_remaining(tvb, offset) < 2)
6584 expert_add_info(pinfo, item, &ei_mal_serv_gal);
6585 return 0;
6588 /* Add number of attributes */
6589 att_count = tvb_get_letohs( tvb, offset);
6590 proto_tree_add_item(tree, hf_cip_sc_get_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6591 offset += 2;
6593 /* Add Attribute List */
6594 att_tree = proto_tree_add_subtree(tree, tvb, offset, att_count*2, ett_cip_get_attribute_list, &att_list, "Attribute List" );
6596 for( i=0; i < att_count; i++ )
6598 att_value = tvb_get_letohs( tvb, offset);
6599 att_item = proto_tree_add_item(att_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6600 pattribute = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
6601 if (pattribute != NULL)
6602 proto_item_append_text(att_item, " (%s)", pattribute->text);
6604 offset += 2;
6605 if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < att_count-1))
6607 expert_add_info(pinfo, att_list, &ei_mal_serv_gal_count);
6608 break;
6612 return 2 + att_count * 2;
6616 dissect_cip_set_attribute_list_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6617 int offset, cip_simple_request_info_t* req_data)
6619 int i, start_offset, att_count,
6620 att_value, att_size;
6621 const attribute_info_t* attr;
6622 proto_item *att_list, *att_item;
6623 proto_tree *att_tree, *att_list_tree;
6625 /* Get attribute list request */
6626 if (tvb_reported_length_remaining(tvb, offset) < 2)
6628 expert_add_info(pinfo, item, &ei_mal_serv_sal);
6629 return 0;
6632 /* Add number of attributes */
6633 att_count = tvb_get_letohs( tvb, offset);
6634 proto_tree_add_item(tree, hf_cip_sc_set_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6636 /* Add Attribute List */
6637 att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*2, ett_cip_set_attribute_list, &att_list, "Attribute List" );
6638 offset += 2;
6639 start_offset = offset;
6641 for( i=0; i < att_count; i++ )
6643 att_value = tvb_get_letohs( tvb, offset);
6644 att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6645 att_tree = proto_item_add_subtree( att_item, ett_cip_set_attribute_list_item);
6646 offset += 2;
6648 attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
6649 if (attr != NULL)
6651 proto_item_append_text(att_item, " (%s)", attr->text);
6652 /* provide attribute data */
6653 att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
6654 offset += att_size;
6655 proto_item_set_len(att_item, att_size+2);
6657 else
6659 /* Can't find the attribute. */
6660 break;
6663 if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < att_count-1))
6665 expert_add_info(pinfo, att_list, &ei_mal_serv_sal_count);
6666 break;
6670 proto_item_set_len(att_list, offset-start_offset );
6672 return 2 + (offset - start_offset);
6675 // NOLINTNEXTLINE(misc-no-recursion)
6676 int dissect_cip_multiple_service_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item, int offset, bool request)
6678 proto_tree *mult_serv_tree, *offset_tree;
6679 int i, num_services, serv_offset, prev_offset = 0;
6680 int parsed_len;
6681 cip_req_info_t *cip_req_info, *mr_single_req_info;
6682 mr_mult_req_info_t *mr_mult_req_info = NULL;
6684 if (tvb_reported_length_remaining(tvb, offset) < 2)
6686 expert_add_info(pinfo, item, &ei_mal_msp_missing_services);
6687 return 0;
6690 num_services = tvb_get_letohs( tvb, offset);
6691 proto_tree_add_item(tree, hf_cip_sc_mult_serv_pack_num_services, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6693 /* Ensure a rough sanity check */
6694 if (num_services*2 > tvb_reported_length_remaining(tvb, offset+2))
6696 expert_add_info(pinfo, item, &ei_mal_msp_services);
6699 offset_tree = proto_tree_add_subtree(tree, tvb, offset + 2, num_services * 2, ett_cip_msp_offset, NULL, "Offset List");
6700 for (i = 0; i < num_services; i++)
6702 proto_tree_add_item(offset_tree, hf_cip_sc_mult_serv_pack_offset, tvb, offset + 2 + i * 2, 2, ENC_LITTLE_ENDIAN);
6705 cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
6706 if ( cip_req_info )
6708 /* Only allocate memory for requests. */
6709 if (cip_req_info->pData == NULL && request == true)
6711 mr_mult_req_info = wmem_new(wmem_file_scope(), mr_mult_req_info_t);
6712 mr_mult_req_info->service = SC_MULT_SERV_PACK;
6713 mr_mult_req_info->num_services = num_services;
6714 mr_mult_req_info->requests = (cip_req_info_t *)wmem_alloc0(wmem_file_scope(), sizeof(cip_req_info_t)*num_services);
6715 cip_req_info->pData = mr_mult_req_info;
6718 mr_mult_req_info = (mr_mult_req_info_t*)cip_req_info->pData;
6720 if (mr_mult_req_info
6721 && (mr_mult_req_info->service != SC_MULT_SERV_PACK
6722 || mr_mult_req_info->num_services != num_services))
6724 mr_mult_req_info = NULL;
6728 col_append_str(pinfo->cinfo, COL_INFO, ": ");
6730 parsed_len = 2 + num_services * 2;
6731 for( i=0; i < num_services; i++ )
6733 proto_item *mult_serv_item;
6734 int serv_length;
6735 tvbuff_t *next_tvb;
6737 serv_offset = tvb_get_letohs( tvb, offset+2+(i*2) );
6739 if (tvb_reported_length_remaining(tvb, serv_offset) <= 0)
6741 expert_add_info(pinfo, item, &ei_mal_msp_inv_offset);
6742 continue;
6745 if( i == (num_services-1) )
6747 /* Last service to add */
6748 serv_length = tvb_reported_length_remaining(tvb, offset)-serv_offset;
6750 else
6752 serv_length = tvb_get_letohs( tvb, offset+2+((i+1)*2) ) - serv_offset;
6755 mult_serv_tree = proto_tree_add_subtree_format(tree, tvb, offset+serv_offset, serv_length,
6756 ett_cip_mult_service_packet, &mult_serv_item, "Service Packet #%d: ", i+1 );
6757 proto_tree_add_item(mult_serv_tree, hf_cip_sc_mult_serv_pack_offset, tvb, offset+2+(i*2) , 2, ENC_LITTLE_ENDIAN);
6759 /* Make sure the offset is valid */
6760 if ((tvb_reported_length_remaining(tvb, serv_offset) <= 0) ||
6761 (tvb_reported_length_remaining(tvb, serv_offset+serv_length) <= 0) ||
6762 (serv_length <= 0) ||
6763 (prev_offset >= serv_offset))
6765 expert_add_info(pinfo, mult_serv_item, &ei_mal_msp_inv_offset);
6766 prev_offset = serv_offset;
6767 continue;
6769 prev_offset = serv_offset;
6772 ** We call ourselves again to dissect embedded packet
6775 next_tvb = tvb_new_subset_length(tvb, offset+serv_offset, serv_length);
6777 if ( mr_mult_req_info )
6779 mr_single_req_info = mr_mult_req_info->requests + i;
6780 dissect_cip_data(mult_serv_tree, next_tvb, 0, pinfo, mr_single_req_info, mult_serv_item, true);
6782 else
6784 dissect_cip_data(mult_serv_tree, next_tvb, 0, pinfo, NULL, mult_serv_item, true);
6787 /* Add the embedded CIP service to the item. */
6788 if (mult_serv_item != NULL)
6790 uint8_t service = tvb_get_uint8(next_tvb, 0);
6791 proto_item_append_text(mult_serv_item, "%s", val_to_str(service & CIP_SC_MASK, cip_sc_vals, "Service (0x%02x)"));
6794 if (i != num_services - 1)
6796 col_append_str(pinfo->cinfo, COL_INFO, ", ");
6799 parsed_len += serv_length;
6802 return parsed_len;
6805 static int
6806 // NOLINTNEXTLINE(misc-no-recursion)
6807 dissect_cip_generic_service_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cip_simple_request_info_t* req_data)
6809 proto_item *cmd_data_item;
6810 int req_path_size,
6811 offset = 0;
6812 proto_tree *cmd_data_tree;
6813 uint8_t service = tvb_get_uint8( tvb, offset ) & CIP_SC_MASK;
6815 add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
6817 req_path_size = tvb_get_uint8(tvb, offset + 1);
6818 offset += ((req_path_size * 2) + 2);
6820 /* Create service tree */
6821 cmd_data_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cmd_data, &cmd_data_item,
6822 val_to_str(service, cip_sc_vals , "Unknown Service (0x%02x)"));
6823 proto_item_append_text(cmd_data_item, " (Request)");
6825 int parsed_len = 0;
6827 switch(service)
6829 case SC_GET_ATT_LIST:
6830 parsed_len = dissect_cip_get_attribute_list_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
6831 break;
6832 case SC_SET_ATT_LIST:
6833 parsed_len = dissect_cip_set_attribute_list_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
6834 break;
6835 case SC_MULT_SERV_PACK:
6836 parsed_len = dissect_cip_multiple_service_packet(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, true);
6837 break;
6838 case SC_SET_ATT_SINGLE:
6839 parsed_len = dissect_cip_set_attribute_single_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
6840 break;
6841 case SC_FIND_NEXT_OBJ_INST:
6842 proto_tree_add_item(cmd_data_tree, hf_cip_find_next_object_max_instance, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6843 parsed_len = 1;
6844 break;
6845 default:
6846 // No specific handling for other services.
6847 break;
6850 // Display any remaining unparsed data.
6851 int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
6852 if (remain_len > 0)
6854 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
6857 proto_item_set_len(cmd_data_item, parsed_len + remain_len);
6859 return tvb_reported_length(tvb);
6862 typedef struct cip_gaa_key {
6863 uint32_t cip_class;
6864 bool class_instance;
6865 } cip_gaa_key_t;
6867 typedef struct cip_gaa_val {
6868 wmem_list_t *attributes;
6869 } cip_gaa_val_t;
6871 static wmem_map_t *cip_gaa_hashtable;
6873 static unsigned
6874 cip_gaa_hash (const void *v)
6876 const cip_gaa_key_t *key = (const cip_gaa_key_t *)v;
6877 unsigned val;
6879 val = (unsigned)((key->cip_class << 1) & 0xFFFFFFFE);
6880 val |= (key->class_instance & 1);
6882 return val;
6885 static int
6886 cip_gaa_equal(const void *v, const void *w)
6888 const cip_gaa_key_t *v1 = (const cip_gaa_key_t *)v;
6889 const cip_gaa_key_t *v2 = (const cip_gaa_key_t *)w;
6891 if ((v1->cip_class == v2->cip_class) &&
6892 (v1->class_instance == v2->class_instance))
6893 return 1;
6895 return 0;
6898 static void build_get_attr_all_table(void)
6900 size_t i, j;
6901 attribute_val_array_t* att_array;
6902 const attribute_info_t* pattr;
6903 cip_gaa_key_t key;
6904 cip_gaa_key_t* new_key;
6905 cip_gaa_val_t *gaa_val;
6906 int last_attribute_index = -1;
6908 cip_gaa_hashtable = wmem_map_new(wmem_epan_scope(), cip_gaa_hash, cip_gaa_equal);
6910 for (i = 0; i < array_length(all_attribute_vals); i++)
6912 att_array = &all_attribute_vals[i];
6913 for (j = 0; j < att_array->size; j++)
6915 pattr = &att_array->attrs[j];
6916 key.cip_class = pattr->class_id;
6917 key.class_instance = pattr->class_instance;
6919 gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key );
6920 if (gaa_val == NULL)
6922 new_key = (cip_gaa_key_t*)wmem_memdup(wmem_epan_scope(), &key, sizeof(cip_gaa_key_t));
6923 gaa_val = wmem_new0(wmem_epan_scope(), cip_gaa_val_t);
6924 gaa_val->attributes = wmem_list_new(wmem_epan_scope());
6926 wmem_map_insert(cip_gaa_hashtable, new_key, gaa_val );
6927 last_attribute_index = -1;
6930 if ((pattr->gaa_index >= 0) && (pattr->gaa_index > last_attribute_index))
6932 wmem_list_append(gaa_val->attributes, (attribute_info_t *)pattr);
6933 last_attribute_index = pattr->gaa_index;
6939 int dissect_cip_get_attribute_all_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6940 int offset, cip_simple_request_info_t* req_data)
6942 int att_size;
6943 int len_remain;
6944 const attribute_info_t* attr;
6945 proto_item *att_item;
6946 proto_tree *att_tree;
6947 cip_gaa_key_t key;
6948 cip_gaa_val_t *gaa_val;
6949 wmem_list_frame_t* attribute_list;
6950 int parsed_len = 0;
6952 key.cip_class = req_data->iClass;
6953 key.class_instance = (req_data->iInstance == 0);
6955 gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key );
6956 if (gaa_val == NULL)
6958 return 0;
6961 for (attribute_list = wmem_list_head(gaa_val->attributes);
6962 (attribute_list != NULL);
6963 attribute_list = wmem_list_frame_next(attribute_list))
6965 attr = (const attribute_info_t *)wmem_list_frame_data(attribute_list);
6966 len_remain = tvb_reported_length_remaining(tvb, offset);
6968 /* If there are no more attributes defined or there is no data left. */
6969 if (attr == NULL || len_remain <= 0)
6970 break;
6972 att_item = proto_tree_add_uint_format_value(tree, hf_cip_attribute16, tvb, offset, 0, attr->attribute, "%d (%s)", attr->attribute, attr->text);
6973 att_tree = proto_item_add_subtree(att_item, ett_cip_get_attributes_all_item);
6975 att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, len_remain);
6976 proto_item_set_len(att_item, att_size);
6978 offset += att_size;
6979 parsed_len += att_size;
6982 return parsed_len;
6985 static int
6986 dissect_cip_get_attribute_list_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6987 int offset, cip_simple_request_info_t* req_data)
6989 int i, start_offset, att_count,
6990 att_value, att_status;
6991 unsigned att_size;
6992 const attribute_info_t* attr;
6993 proto_item *att_list, *att_item;
6994 proto_tree *att_tree, *att_list_tree;
6996 /* Get attribute list response */
6997 if (tvb_reported_length_remaining(tvb, offset) < 2)
6999 expert_add_info(pinfo, item, &ei_mal_serv_gal);
7000 return 0;
7003 /* Add number of attributes */
7004 att_count = tvb_get_letohs( tvb, offset);
7005 proto_tree_add_item(tree, hf_cip_sc_get_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7007 /* Add Attribute List */
7008 att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*4, ett_cip_get_attribute_list, &att_list, "Attribute List" );
7009 offset += 2;
7010 start_offset = offset;
7012 for( i=0; i < att_count; i++ )
7014 att_value = tvb_get_letohs( tvb, offset);
7015 att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7016 att_tree = proto_item_add_subtree( att_item, ett_cip_get_attribute_list_item);
7018 att_status = tvb_get_letohs( tvb, offset+2);
7019 proto_tree_add_item(att_tree, hf_cip_sc_get_attr_list_attr_status, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
7021 attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
7022 if (attr != NULL)
7023 proto_item_append_text(att_item, " (%s)", attr->text);
7025 offset += 4;
7026 if (att_status == 0)
7028 if (attr != NULL)
7030 /* provide attribute data */
7031 att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
7032 offset += att_size;
7033 proto_item_set_len(att_item, att_size+4);
7035 else
7037 /* Can't find the attribute */
7038 break;
7042 if ((tvb_reported_length_remaining(tvb, offset) < 4) && (i < att_count-1))
7044 expert_add_info(pinfo, att_list, &ei_mal_serv_gal_count);
7045 break;
7049 proto_item_set_len(att_list, offset-start_offset );
7050 return 2 + (offset - start_offset);
7054 dissect_cip_set_attribute_list_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
7055 int offset, cip_simple_request_info_t* req_data)
7057 int i, start_offset, att_count, att_value;
7058 const attribute_info_t* attr;
7059 proto_item *att_list, *att_item;
7060 proto_tree *att_tree, *att_list_tree;
7062 /* Get attribute list request */
7063 if (tvb_reported_length_remaining(tvb, offset) < 2)
7065 expert_add_info(pinfo, item, &ei_mal_serv_sal);
7066 return 0;
7069 /* Add number of attributes */
7070 att_count = tvb_get_letohs( tvb, offset);
7071 proto_tree_add_item(tree, hf_cip_sc_set_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7073 /* Add Attribute List */
7074 att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*4, ett_cip_get_attribute_list, &att_list, "Attribute List" );
7075 offset += 2;
7076 start_offset = offset;
7078 for( i=0; i < att_count; i++ )
7080 att_value = tvb_get_letohs( tvb, offset);
7081 att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7082 att_tree = proto_item_add_subtree( att_item, ett_cip_set_attribute_list_item);
7084 proto_tree_add_item(att_tree, hf_cip_sc_set_attr_list_attr_status, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
7086 attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
7087 if (attr != NULL)
7088 proto_item_append_text(att_item, " (%s)", attr->text);
7090 offset += 4;
7091 if ((tvb_reported_length_remaining(tvb, offset) < 4) && (i < att_count-1))
7093 expert_add_info(pinfo, att_list, &ei_mal_serv_sal_count);
7094 break;
7098 proto_item_set_len(att_list, offset-start_offset );
7099 return 2 + (offset - start_offset);
7102 static int
7103 dissect_cip_get_attribute_single_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
7104 int offset, cip_simple_request_info_t* req_data)
7106 int parsed_len = 0;
7107 int total_len;
7108 const attribute_info_t* attr;
7110 total_len = tvb_reported_length_remaining(tvb, offset);
7111 attr = cip_get_attribute(req_data->iClass, req_data->iInstance, req_data->iAttribute);
7112 if (attr != NULL)
7114 proto_item_append_text(item, " (%s)", attr->text);
7115 parsed_len = dissect_cip_attribute(pinfo, tree, item, tvb, attr, offset, total_len);
7118 return parsed_len;
7121 static int
7122 dissect_cip_find_next_object_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item, int offset)
7124 uint32_t i, num_instances;
7126 if (tvb_reported_length_remaining(tvb, offset) < 1)
7128 expert_add_info(pinfo, item, &ei_mal_serv_find_next_object);
7129 return 0;
7132 proto_tree_add_item_ret_uint(tree, hf_cip_find_next_object_num_instances, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_instances);
7133 offset += 1;
7135 for (i = 0; i < num_instances; i++)
7137 proto_tree_add_item(tree, hf_cip_find_next_object_instance_item, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7138 offset += 1;
7140 if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < num_instances-1))
7142 expert_add_info(pinfo, item, &ei_mal_serv_find_next_object_count);
7143 break;
7147 return 1 + num_instances * 2;
7150 void load_cip_request_data(packet_info *pinfo, cip_simple_request_info_t *req_data)
7152 cip_req_info_t* preq_info;
7153 preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
7155 if ((preq_info != NULL) &&
7156 (preq_info->ciaData != NULL))
7158 memcpy(req_data, preq_info->ciaData, sizeof(cip_simple_request_info_t));
7160 else
7162 reset_cip_request_info(req_data);
7166 bool should_dissect_cip_response(tvbuff_t *tvb, int offset, uint8_t gen_status)
7168 // Only parse the response if there is data left or it has a response status that allows additional data
7169 // to be returned.
7170 if ((tvb_reported_length_remaining(tvb, offset) == 0)
7171 && gen_status != CI_GRC_SUCCESS
7172 && gen_status != CI_GRC_ATTR_LIST_ERROR
7173 && gen_status != CI_GRC_SERVICE_ERROR
7174 && gen_status != CI_GRC_INVALID_LIST_STATUS)
7176 return false;
7179 return true;
7183 // NOLINTNEXTLINE(misc-no-recursion)
7184 dissect_cip_generic_service_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
7186 proto_item *cmd_data_item;
7187 proto_tree *cmd_data_tree;
7188 cip_simple_request_info_t req_data;
7189 int offset = 0;
7190 uint8_t gen_status = tvb_get_uint8(tvb, offset + 2);
7191 uint8_t service = tvb_get_uint8(tvb, offset) & CIP_SC_MASK;
7192 uint16_t add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
7194 offset = 4 + add_stat_size;
7196 add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
7198 cmd_data_tree = proto_tree_add_subtree(tree, tvb, offset, 0,
7199 ett_cmd_data, &cmd_data_item, val_to_str(service, cip_sc_vals, "Unknown Service (0x%02x)"));
7200 proto_item_append_text(cmd_data_item, " (Response)");
7202 load_cip_request_data(pinfo, &req_data);
7204 if (should_dissect_cip_response(tvb, offset, gen_status) == false)
7206 return 0;
7209 int parsed_len = 0;
7211 switch(service)
7213 case SC_GET_ATT_ALL:
7214 parsed_len = dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset, &req_data);
7215 break;
7216 case SC_GET_ATT_LIST:
7217 parsed_len = dissect_cip_get_attribute_list_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
7218 break;
7219 case SC_SET_ATT_LIST:
7220 parsed_len = dissect_cip_set_attribute_list_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
7221 break;
7222 case SC_CREATE:
7223 proto_tree_add_item(cmd_data_tree, hf_cip_sc_create_instance, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7224 parsed_len = 2;
7225 break;
7226 case SC_MULT_SERV_PACK:
7227 parsed_len = dissect_cip_multiple_service_packet(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, false);
7228 break;
7229 case SC_GET_ATT_SINGLE:
7230 parsed_len = dissect_cip_get_attribute_single_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
7231 break;
7232 case SC_FIND_NEXT_OBJ_INST:
7233 parsed_len = dissect_cip_find_next_object_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset);
7234 break;
7235 case SC_GROUP_SYNC:
7236 proto_tree_add_item(cmd_data_tree, hf_cip_sc_group_sync_is_sync, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7237 parsed_len = 1;
7238 break;
7239 default:
7240 // No specific handling for other services.
7241 break;
7244 // Display any remaining unparsed data.
7245 int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
7246 if (remain_len > 0)
7248 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
7251 proto_item_set_len(cmd_data_item, parsed_len + remain_len);
7253 return tvb_reported_length(tvb);
7256 /************************************************
7258 * Dissector for CIP Connection Manager
7260 ************************************************/
7262 static void
7263 dissect_cip_cm_timeout(proto_tree *cmd_tree, tvbuff_t *tvb, int offset)
7265 uint8_t tick, timeout_tick;
7266 int timeout;
7268 /* Display the priority/tick timer */
7269 tick = tvb_get_uint8( tvb, offset) & 0x0F;
7270 proto_tree_add_item( cmd_tree, hf_cip_cm_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7271 proto_tree_add_item( cmd_tree, hf_cip_cm_tick_time, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7273 /* Display the time-out ticks */
7274 timeout_tick = tvb_get_uint8( tvb, offset+1 );
7275 proto_tree_add_item( cmd_tree, hf_cip_cm_timeout_tick, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
7277 /* Display the actual time out */
7278 timeout = ( 1 << tick ) * timeout_tick;
7279 proto_tree_add_uint(cmd_tree, hf_cip_cm_timeout, tvb, offset, 2, timeout);
7282 static void dissect_connection_triad(tvbuff_t *tvb, int offset, proto_tree *tree,
7283 int hf_conn_serial, int hf_vendor, int hf_orig_serial,
7284 cip_connection_triad_t *triad)
7286 uint32_t ConnSerialNumber;
7287 uint32_t VendorID;
7288 uint32_t DeviceSerialNumber;
7290 proto_tree_add_item_ret_uint(tree, hf_conn_serial, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ConnSerialNumber);
7291 proto_tree_add_item_ret_uint(tree, hf_vendor, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN, &VendorID);
7292 proto_tree_add_item_ret_uint(tree, hf_orig_serial, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &DeviceSerialNumber);
7294 if (triad)
7296 triad->ConnSerialNumber = ConnSerialNumber;
7297 triad->VendorID = VendorID;
7298 triad->DeviceSerialNumber = DeviceSerialNumber;
7302 // Mark this message as belonging to a specific CIP connection index.
7303 static void mark_cip_connection(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree)
7305 cip_conn_info_t* conn_val = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
7306 if (conn_val)
7308 proto_item* pi = proto_tree_add_uint(tree, hf_cip_connection, tvb, 0, 0, conn_val->connid);
7309 proto_item_set_generated(pi);
7313 // Save the Route or Connection Path for use in the response packet.
7314 static void save_route_connection_path(packet_info* pinfo, tvbuff_t* tvb, int offset, unsigned path_size_bytes)
7316 if (pinfo->fd->visited)
7318 return;
7321 cip_req_info_t* preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
7322 if (preq_info)
7324 preq_info->pRouteConnectionPath = wmem_alloc(wmem_file_scope(), path_size_bytes);
7325 preq_info->RouteConnectionPathLen = path_size_bytes / 2;
7326 tvb_memcpy(tvb, preq_info->pRouteConnectionPath, offset, path_size_bytes);
7330 static int get_connection_timeout_multiplier(uint32_t timeout_value)
7332 uint32_t timeout_multiplier;
7333 switch (timeout_value)
7335 case 0:
7336 timeout_multiplier = 4;
7337 break;
7338 case 1:
7339 timeout_multiplier = 8;
7340 break;
7341 case 2:
7342 timeout_multiplier = 16;
7343 break;
7344 case 3:
7345 timeout_multiplier = 32;
7346 break;
7347 case 4:
7348 timeout_multiplier = 64;
7349 break;
7350 case 5:
7351 timeout_multiplier = 128;
7352 break;
7353 case 6:
7354 timeout_multiplier = 256;
7355 break;
7356 case 7:
7357 timeout_multiplier = 512;
7358 break;
7359 default:
7360 // Invalid
7361 timeout_multiplier = 0;
7362 break;
7365 return timeout_multiplier;
7368 static void fwd_open_analysis_safety_open(packet_info* pinfo, proto_item* cmd_item, cip_safety_epath_info_t* safety_fwdopen)
7370 if (safety_fwdopen->safety_seg == false)
7372 return;
7375 if (safety_fwdopen->safety_open_type == CIP_SAFETY_OPEN_TYPE1)
7377 expert_add_info(pinfo, cmd_item, &ei_cip_safety_open_type1);
7379 else if (safety_fwdopen->safety_open_type == CIP_SAFETY_OPEN_TYPE2A)
7381 expert_add_info(pinfo, cmd_item, &ei_cip_safety_open_type2a);
7383 else if (safety_fwdopen->safety_open_type == CIP_SAFETY_OPEN_TYPE2B)
7385 expert_add_info(pinfo, cmd_item, &ei_cip_safety_open_type2b);
7388 if (safety_fwdopen->originator_type == CIP_SAFETY_ORIGINATOR_PRODUCER)
7390 expert_add_info(pinfo, cmd_item, &ei_cip_safety_output);
7392 else if (safety_fwdopen->originator_type == CIP_SAFETY_ORIGINATOR_CONSUMER)
7394 expert_add_info(pinfo, cmd_item, &ei_cip_safety_input);
7398 static void fwd_open_analysis_listen_input_connection(packet_info* pinfo, proto_item* cmd_item, uint8_t TransportClass_trigger, const cip_connID_info_t* O2T_info)
7400 // Listen Only and Input Only connections must be 'Fixed'.
7401 if (O2T_info->connection_size_type != CIP_CONNECTION_SIZE_TYPE_FIXED)
7403 return;
7406 uint8_t transport_class = TransportClass_trigger & CI_TRANSPORT_CLASS_MASK;
7407 if ((transport_class == 0 && O2T_info->connection_size == 0)
7408 || (transport_class == 1 && O2T_info->connection_size == 2))
7410 expert_add_info(pinfo, cmd_item, &ei_cip_listen_input_connection);
7414 static void display_previous_route_connection_path(cip_req_info_t* preq_info, proto_tree* item_tree, tvbuff_t* tvb, packet_info* pinfo, int hf_path, int display_type);
7416 // Display all Connection Information and Analysis.
7417 static void display_connection_information_fwd_open_req(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree)
7419 cip_conn_info_t* conn_info = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
7420 if (!conn_info)
7422 return;
7425 proto_item* conn_info_item = NULL;
7426 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
7427 proto_item_set_generated(conn_info_item);
7429 mark_cip_connection(pinfo, tvb, conn_info_tree);
7431 proto_item* pi = proto_tree_add_float(conn_info_tree, hf_cip_cm_ot_timeout, tvb, 0, 0, (conn_info->O2T.rpi / 1000.0f) * conn_info->timeout_multiplier);
7432 proto_item_set_generated(pi);
7434 pi = proto_tree_add_float(conn_info_tree, hf_cip_cm_to_timeout, tvb, 0, 0, (conn_info->T2O.rpi / 1000.0f) * conn_info->timeout_multiplier);
7435 proto_item_set_generated(pi);
7437 if (conn_info->safety.safety_seg)
7439 add_safety_data_type_to_info_column(pinfo, ECIDT_O2T, &conn_info->safety);
7441 pi = proto_tree_add_float(conn_info_tree, hf_cip_safety_nte_ms, tvb, 0, 0, conn_info->safety.nte_value_ms);
7442 proto_item_set_generated(pi);
7445 if (conn_info->close_frame != 0)
7447 pi = proto_tree_add_uint(conn_info_tree, hf_cip_fwd_close_in, tvb, 0, 0, conn_info->close_frame);
7448 proto_item_set_generated(pi);
7450 else
7452 expert_add_info(pinfo, conn_info_item, &ei_cip_no_fwd_close);
7455 fwd_open_analysis_safety_open(pinfo, conn_info_item, &conn_info->safety);
7456 fwd_open_analysis_listen_input_connection(pinfo, conn_info_item, conn_info->TransportClass_trigger, &conn_info->O2T);
7459 static void display_connection_information_fwd_open_rsp(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree, cip_req_info_t* preq_info)
7461 proto_item* conn_info_item = NULL;
7462 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
7463 proto_item_set_generated(conn_info_item);
7465 mark_cip_connection(pinfo, tvb, conn_info_tree);
7467 display_previous_route_connection_path(preq_info, conn_info_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
7469 if (preq_info && preq_info->connInfo && preq_info->connInfo->safety.safety_seg)
7471 add_safety_data_type_to_info_column(pinfo, ECIDT_T2O, &preq_info->connInfo->safety);
7475 static void display_connection_information_fwd_close_req(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree)
7477 cip_conn_info_t* conn_info = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
7478 if (!conn_info)
7480 return;
7483 proto_item* conn_info_item = NULL;
7484 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
7485 proto_item_set_generated(conn_info_item);
7487 mark_cip_connection(pinfo, tvb, conn_info_tree);
7489 display_fwd_open_connection_path(conn_info, conn_info_tree, tvb, pinfo);
7491 proto_item *pi = proto_tree_add_uint(conn_info_tree, hf_cip_fwd_open_in, tvb, 0, 0, conn_info->open_req_frame);
7492 proto_item_set_generated(pi);
7494 // Show the API values
7495 pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_ot_api, tvb, 0, 0, conn_info->O2T.api);
7496 proto_item_set_generated(pi);
7498 pi = proto_tree_add_uint(conn_info_tree, hf_cip_cm_to_api, tvb, 0, 0, conn_info->T2O.api);
7499 proto_item_set_generated(pi);
7501 // Connection timeout values
7502 float ot_timeout_ms = (conn_info->O2T.rpi / 1000.0f) * conn_info->timeout_multiplier;
7503 float to_timeout_ms = (conn_info->T2O.rpi / 1000.0f) * conn_info->timeout_multiplier;
7504 proto_item* ot_timeout_item = proto_tree_add_float(conn_info_tree, hf_cip_cm_ot_timeout, tvb, 0, 0, ot_timeout_ms);
7505 proto_item_set_generated(ot_timeout_item);
7507 proto_item* to_timeout_item = proto_tree_add_float(conn_info_tree, hf_cip_cm_to_timeout, tvb, 0, 0, to_timeout_ms);
7508 proto_item_set_generated(to_timeout_item);
7510 if (conn_info->safety.safety_seg)
7512 pi = proto_tree_add_float(conn_info_tree, hf_cip_safety_nte_ms, tvb, 0, 0, conn_info->safety.nte_value_ms);
7513 proto_item_set_generated(pi);
7516 if (conn_info->safety.safety_seg)
7518 // Make it obvious that the FwdClose is Safety, to match how the FwdOpen looks.
7519 col_append_str(pinfo->cinfo, COL_INFO, " [Safety]");
7520 add_safety_data_type_to_info_column(pinfo, ECIDT_O2T, &conn_info->safety);
7525 static void display_connection_information_fwd_close_rsp(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree)
7527 cip_conn_info_t* conn_val = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
7528 if (!conn_val)
7530 return;
7533 proto_item* conn_info_item = NULL;
7534 proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
7535 proto_item_set_generated(conn_info_item);
7537 mark_cip_connection(pinfo, tvb, conn_info_tree);
7539 cip_req_info_t* preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
7540 display_previous_route_connection_path(preq_info, conn_info_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
7542 if (conn_val->safety.safety_seg)
7544 // Make it obvious that the FwdClose is Safety, to match how the FwdOpen looks.
7545 col_append_str(pinfo->cinfo, COL_INFO, " [Safety]");
7546 add_safety_data_type_to_info_column(pinfo, ECIDT_T2O, &conn_val->safety);
7550 //// Concurrent Connections
7551 static int dissect_cip_cc_hop(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* hops_tree, uint8_t hop_number)
7553 int parsed = 0;
7555 proto_item* item_hop = proto_tree_add_uint(hops_tree, hf_ext_net_seg_hop, tvb, offset, 0, hop_number);
7557 proto_tree* hop_tree = proto_item_add_subtree(item_hop, ett_cc_hop);
7558 proto_tree_add_item(hop_tree, hf_ext_net_seg_hop_egress_cip_port, tvb, offset + parsed, 1, ENC_LITTLE_ENDIAN);
7559 parsed++;
7561 proto_tree_add_item(hop_tree, hf_ext_net_seg_hop_link_adr_type, tvb, offset + parsed, 1, ENC_LITTLE_ENDIAN);
7562 proto_tree_add_item(hop_tree, hf_ext_net_seg_hop_number_of_linkadr, tvb, offset + parsed, 1, ENC_LITTLE_ENDIAN);
7563 parsed++;
7565 uint8_t link_type = tvb_get_uint8(tvb, offset + 1) >> 4;
7566 uint8_t number_of_links = tvb_get_uint8(tvb, offset + 1) & 0x0F;
7568 for (uint8_t i = 0; i < number_of_links; i++)
7570 switch (link_type)
7572 case 0: // Link addresses
7574 proto_tree_add_item(hop_tree, hf_ext_net_seg_link_address, tvb, offset + parsed, 1, ENC_LITTLE_ENDIAN);
7575 parsed++;
7576 break;
7579 case 1: // IPv4 addresses encoding
7580 proto_tree_add_item(hop_tree, hf_ext_net_seg_link_ipv4, tvb, offset + parsed, 4, ENC_LITTLE_ENDIAN);
7581 parsed += 4;
7582 break;
7584 case 2: // Host Name addresses encoding
7585 parsed += dissect_cip_string_type(pinfo, hop_tree, item_hop, tvb, offset + parsed, hf_ext_net_seg_link_hostname, CIP_STRING_TYPE);
7587 // Add pad byte when string length is odd
7588 if (parsed % 2)
7590 parsed++;
7593 break;
7595 default:
7596 break;
7600 proto_item_set_len(item_hop, parsed);
7602 return parsed;
7605 // From ODVA Volume 1
7606 static const uint32_t crc32_cc_table[256] =
7608 0x00000000U, 0x29800005U, 0x5300000AU, 0x7A80000FU,
7609 0xA6000014U, 0x8F800011U, 0xF500001EU, 0xDC80001BU,
7610 0xCC000019U, 0xE580001CU, 0x9F000013U, 0xB6800016U,
7611 0x6A00000DU, 0x43800008U, 0x39000007U, 0x10800002U,
7612 0x18000003U, 0x31800006U, 0x4B000009U, 0x6280000CU,
7613 0xBE000017U, 0x97800012U, 0xED00001DU, 0xC4800018U,
7614 0xD400001AU, 0xFD80001FU, 0x87000010U, 0xAE800015U,
7615 0x7200000EU, 0x5B80000BU, 0x21000004U, 0x08800001U,
7616 0x30000006U, 0x19800003U, 0x6300000CU, 0x4A800009U,
7617 0x96000012U, 0xBF800017U, 0xC5000018U, 0xEC80001DU,
7618 0xFC00001FU, 0xD580001AU, 0xAF000015U, 0x86800010U,
7619 0x5A00000BU, 0x7380000EU, 0x09000001U, 0x20800004U,
7620 0x28000005U, 0x01800000U, 0x7B00000FU, 0x5280000AU,
7621 0x8E000011U, 0xA7800014U, 0xDD00001BU, 0xF480001EU,
7622 0xE400001CU, 0xCD800019U, 0xB7000016U, 0x9E800013U,
7623 0x42000008U, 0x6B80000DU, 0x11000002U, 0x38800007U,
7624 0x6000000CU, 0x49800009U, 0x33000006U, 0x1A800003U,
7625 0xC6000018U, 0xEF80001DU, 0x95000012U, 0xBC800017U,
7626 0xAC000015U, 0x85800010U, 0xFF00001FU, 0xD680001AU,
7627 0x0A000001U, 0x23800004U, 0x5900000BU, 0x7080000EU,
7628 0x7800000FU, 0x5180000AU, 0x2B000005U, 0x02800000U,
7629 0xDE00001BU, 0xF780001EU, 0x8D000011U, 0xA4800014U,
7630 0xB4000016U, 0x9D800013U, 0xE700001CU, 0xCE800019U,
7631 0x12000002U, 0x3B800007U, 0x41000008U, 0x6880000DU,
7632 0x5000000AU, 0x7980000FU, 0x03000000U, 0x2A800005U,
7633 0xF600001EU, 0xDF80001BU, 0xA5000014U, 0x8C800011U,
7634 0x9C000013U, 0xB5800016U, 0xCF000019U, 0xE680001CU,
7635 0x3A000007U, 0x13800002U, 0x6900000DU, 0x40800008U,
7636 0x48000009U, 0x6180000CU, 0x1B000003U, 0x32800006U,
7637 0xEE00001DU, 0xC7800018U, 0xBD000017U, 0x94800012U,
7638 0x84000010U, 0xAD800015U, 0xD700001AU, 0xFE80001FU,
7639 0x22000004U, 0x0B800001U, 0x7100000EU, 0x5880000BU,
7640 0xC0000018U, 0xE980001DU, 0x93000012U, 0xBA800017U,
7641 0x6600000CU, 0x4F800009U, 0x35000006U, 0x1C800003U,
7642 0x0C000001U, 0x25800004U, 0x5F00000BU, 0x7680000EU,
7643 0xAA000015U, 0x83800010U, 0xF900001FU, 0xD080001AU,
7644 0xD800001BU, 0xF180001EU, 0x8B000011U, 0xA2800014U,
7645 0x7E00000FU, 0x5780000AU, 0x2D000005U, 0x04800000U,
7646 0x14000002U, 0x3D800007U, 0x47000008U, 0x6E80000DU,
7647 0xB2000016U, 0x9B800013U, 0xE100001CU, 0xC8800019U,
7648 0xF000001EU, 0xD980001BU, 0xA3000014U, 0x8A800011U,
7649 0x5600000AU, 0x7F80000FU, 0x05000000U, 0x2C800005U,
7650 0x3C000007U, 0x15800002U, 0x6F00000DU, 0x46800008U,
7651 0x9A000013U, 0xB3800016U, 0xC9000019U, 0xE080001CU,
7652 0xE800001DU, 0xC1800018U, 0xBB000017U, 0x92800012U,
7653 0x4E000009U, 0x6780000CU, 0x1D000003U, 0x34800006U,
7654 0x24000004U, 0x0D800001U, 0x7700000EU, 0x5E80000BU,
7655 0x82000010U, 0xAB800015U, 0xD100001AU, 0xF880001FU,
7656 0xA0000014U, 0x89800011U, 0xF300001EU, 0xDA80001BU,
7657 0x06000000U, 0x2F800005U, 0x5500000AU, 0x7C80000FU,
7658 0x6C00000DU, 0x45800008U, 0x3F000007U, 0x16800002U,
7659 0xCA000019U, 0xE380001CU, 0x99000013U, 0xB0800016U,
7660 0xB8000017U, 0x91800012U, 0xEB00001DU, 0xC2800018U,
7661 0x1E000003U, 0x37800006U, 0x4D000009U, 0x6480000CU,
7662 0x7400000EU, 0x5D80000BU, 0x27000004U, 0x0E800001U,
7663 0xD200001AU, 0xFB80001FU, 0x81000010U, 0xA8800015U,
7664 0x90000012U, 0xB9800017U, 0xC3000018U, 0xEA80001DU,
7665 0x36000006U, 0x1F800003U, 0x6500000CU, 0x4C800009U,
7666 0x5C00000BU, 0x7580000EU, 0x0F000001U, 0x26800004U,
7667 0xFA00001FU, 0xD380001AU, 0xA9000015U, 0x80800010U,
7668 0x88000011U, 0xA1800014U, 0xDB00001BU, 0xF280001EU,
7669 0x2E000005U, 0x07800000U, 0x7D00000FU, 0x5480000AU,
7670 0x44000008U, 0x6D80000DU, 0x17000002U, 0x3E800007U,
7671 0xE200001CU, 0xCB800019U, 0xB1000016U, 0x98800013L
7674 static uint32_t compute_crc_cc(const uint8_t* pData, size_t size)
7676 uint32_t crc = 0xFFFFFFFF;
7677 for (; size > 0; --size)
7679 crc = crc32_cc_table[*pData++ ^ (uint8_t)crc] ^ (crc >> 8);
7681 return crc;
7684 #define CC_PACKET_TYPE_MASK (0x001F)
7685 int dissect_concurrent_connection_packet(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* tree)
7687 proto_item* type_item = proto_tree_add_item(tree, proto_cc, tvb, offset, -1, ENC_NA);
7688 proto_tree* CC_tree = proto_item_add_subtree(type_item, ett_cc_header);
7690 uint16_t header_type = tvb_get_letohs(tvb, offset) & CC_PACKET_TYPE_MASK;
7692 int parsed_len = 0;
7693 if (header_type == 1)
7695 static int* const options[] = {
7696 &hf_cip_cc_packet_type,
7697 &hf_cip_cc_packet_keepalive,
7698 &hf_cip_cc_packet_keepalive_hop_count,
7699 &hf_cip_cc_packet_reserved,
7700 NULL
7703 proto_tree_add_bitmask(CC_tree, tvb, offset + parsed_len, hf_cip_cc_packet_options, ett_cc_header, options, ENC_LITTLE_ENDIAN);
7704 parsed_len += 2;
7706 uint32_t CC_frame_length;
7707 proto_tree_add_item_ret_uint(CC_tree, hf_cip_cc_packet_length, tvb, offset + parsed_len, 2, ENC_LITTLE_ENDIAN, &CC_frame_length);
7708 parsed_len += 2;
7710 uint32_t ccSeq;
7711 proto_tree_add_item_ret_uint(CC_tree, hf_cip_cc_packet_seq_number, tvb, offset + parsed_len, 4, ENC_LITTLE_ENDIAN, &ccSeq);
7712 col_append_fstr(pinfo->cinfo, COL_INFO, ", CC_SEQ=%010u", ccSeq);
7713 parsed_len += 4;
7715 const uint8_t* payloadToCRC = tvb_get_ptr(tvb, offset, CC_frame_length);
7716 uint32_t computed_cc_crc = compute_crc_cc(payloadToCRC, CC_frame_length);
7718 proto_tree_add_checksum(CC_tree, tvb, offset + CC_frame_length,
7719 hf_cip_cc_crc, hf_cip_cc_crc_status, &ei_cc_crc, pinfo,
7720 computed_cc_crc, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
7721 proto_tree_set_appendix(CC_tree, tvb, offset + CC_frame_length, CC_CRC_LENGTH);
7723 else
7725 expert_add_info(pinfo, type_item, &ei_cc_invalid_header_type);
7728 proto_item_set_len(type_item, parsed_len);
7730 return parsed_len;
7733 void proto_register_cc(void)
7735 static hf_register_info hf_cc[] =
7737 /// Concurrent Connections
7738 { &hf_cip_cm_cc_version, { "Concurrent Connections Protocol Version", "cip.cm.cc_version", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
7740 // Concurrent Connection Packet
7741 { &hf_cip_cc_packet_length,{ "Packet Length", "cip.cc.packet.length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
7742 { &hf_cip_cc_packet_type,{ "Packet Type", "cip.cc.packet_type", FT_UINT16, BASE_DEC, VALS(cc_packet_type_vals), CC_PACKET_TYPE_MASK, NULL, HFILL } },
7743 { &hf_cip_cc_packet_options, { "Packet Type and Keep-alive", "cip.cc.packet.type_and_keepalive", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
7744 { &hf_cip_cc_packet_keepalive,{ "Keep-alive Flag", "cip.cc.packet.keep_alive_flag", FT_UINT16, BASE_HEX, NULL, 0x0020, NULL, HFILL } },
7745 { &hf_cip_cc_packet_keepalive_hop_count,{ "Keep-alive Hop Count", "cip.cc.packet.keep_alive_count", FT_UINT16, BASE_DEC, NULL, 0x01C0, NULL, HFILL } },
7746 { &hf_cip_cc_packet_reserved,{ "Reserved", "cip.cc.packet.reserved", FT_UINT16, BASE_HEX, NULL, 0xFE00, NULL, HFILL } },
7747 { &hf_cip_cc_packet_seq_number,{ "Concurrent Connection Sequence Count", "cip.cc.packet.sequence_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
7748 { &hf_cip_cc_crc,{ "CRC", "cip.cc.crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
7749 { &hf_cip_cc_crc_status, { "CC CRC Status", "cip.cc.crc.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, NULL, HFILL } },
7751 // Concurrent Connection Path
7752 { &hf_ext_net_seg_hops_count,{ "Hops Count", "cip.cc.netsegment.hopsCount", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
7753 { &hf_ext_net_seg_length,{ "Length of Concurrent Connection Path", "cip.cc.netsegment.length", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
7755 // Concurrent Connection Hops
7756 { &hf_ext_net_seg_hop,{ "CC Hop", "cip.cc.netsegment.hop", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
7757 { &hf_ext_net_seg_hop_egress_cip_port,{ "Egress Port", "cip.cc.netsegment.HopEgreeCipPort", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
7758 { &hf_ext_net_seg_hop_link_adr_type,{ "Link Address Type", "cip.cc.netsegment.HopLnkAdrType", FT_UINT8, BASE_DEC, VALS(cc_link_adr_type), 0xF0, NULL, HFILL } },
7759 { &hf_ext_net_seg_hop_number_of_linkadr,{ "Number of link addresses", "cip.cc.netsegment.HopNumberOfLnkAdr", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL } },
7760 { &hf_ext_net_seg_link_address,{ "Link address", "cip.cc.netsegment.link", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
7761 { &hf_ext_net_seg_link_ipv4,{ "IPv4 address", "cip.cc.netsegment.ip", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } },
7762 { &hf_ext_net_seg_link_hostname, { "Hostname", "cip.cc.netsegment.hostname", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
7765 static ei_register_info ei_cc[] = {
7766 { &ei_cc_invalid_header_type, { "cip.cc.invalid_packet_type", PI_MALFORMED, PI_ERROR, "Invalid Concurrent Connections Packet Type", EXPFILL }},
7767 { &ei_cc_crc, { "cip.cc.crc.incorrect", PI_PROTOCOL, PI_ERROR, "CC CRC incorrect", EXPFILL }},
7770 proto_cc = proto_register_protocol("Concurrent Connection Packet",
7771 "CIPCC",
7772 "cipcc");
7774 proto_register_field_array(proto_cc, hf_cc, array_length(hf_cc));
7775 proto_register_subtree_array(ett_cc, array_length(ett_cc));
7777 expert_module_t* expert_cc = expert_register_protocol(proto_cc);
7778 expert_register_field_array(expert_cc, ei_cc, array_length(ei_cc));
7781 // Offset - Starts after the Extended Network Segment Subtype
7782 int dissect_concurrent_connection_network_segment(packet_info* pinfo, tvbuff_t* tvb, int offset, proto_tree* tree)
7784 uint32_t hops_count;
7785 proto_tree_add_item_ret_uint(tree, hf_ext_net_seg_hops_count, tvb, offset, 1, ENC_LITTLE_ENDIAN, &hops_count);
7787 proto_tree_add_item(tree, hf_ext_net_seg_length, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
7788 int parsed_len = 2;
7790 for (uint32_t i = 0; i < hops_count; i++)
7792 parsed_len += dissect_cip_cc_hop(pinfo, tvb, offset + parsed_len, tree, i + 1);
7795 // Add padding when the Network segment length is odd.
7796 if (parsed_len & 0x0001)
7798 parsed_len++;
7801 return parsed_len;
7804 static void
7805 dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, proto_item* cmd_item, tvbuff_t *tvb, int offset,
7806 bool large_fwd_open, packet_info *pinfo, bool concurrent_connection)
7808 proto_item *pi;
7809 proto_tree *epath_tree;
7810 int conn_path_size, net_param_offset = 0;
7811 uint8_t TransportClass_trigger;
7812 cip_simple_request_info_t connection_path;
7813 cip_safety_epath_info_t safety_fwdopen = {0};
7815 cip_connID_info_t O2T_info = {0};
7816 cip_connID_info_t T2O_info = {0};
7818 dissect_cip_cm_timeout(cmd_tree, tvb, offset);
7819 proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_ot_connid, tvb, offset+2, 4, ENC_LITTLE_ENDIAN, &O2T_info.connID);
7820 proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_to_connid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN, &T2O_info.connID);
7822 // Add Connection IDs as hidden items so that it's easy to find all Connection IDs in different fields.
7823 pi = proto_tree_add_item(cmd_tree, hf_cip_connid, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
7824 proto_item_set_hidden(pi);
7825 pi = proto_tree_add_item(cmd_tree, hf_cip_connid, tvb, offset + 6, 4, ENC_LITTLE_ENDIAN);
7826 proto_item_set_hidden(pi);
7828 cip_connection_triad_t conn_triad;
7829 dissect_connection_triad(tvb, offset + 10, cmd_tree,
7830 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
7831 &conn_triad);
7833 if (concurrent_connection)
7835 // For CC there is additional 1 byte containing CC Version and one reserved byte after.
7836 proto_tree_add_item(cmd_tree, hf_cip_cm_cc_version, tvb, offset + 18, 1, ENC_LITTLE_ENDIAN);
7837 offset += 2;
7840 uint32_t timeout_value;
7841 proto_tree_add_item_ret_uint(cmd_tree, hf_cip_cm_timeout_multiplier, tvb, offset+18, 1, ENC_LITTLE_ENDIAN, &timeout_value);
7842 uint32_t timeout_multiplier = get_connection_timeout_multiplier(timeout_value);
7844 proto_tree_add_item(cmd_tree, hf_cip_reserved24, tvb, offset+19, 3, ENC_LITTLE_ENDIAN);
7846 // O->T parameters
7847 proto_tree_add_item_ret_uint(cmd_tree, hf_cip_cm_ot_rpi, tvb, offset + 22, 4, ENC_LITTLE_ENDIAN, &O2T_info.rpi);
7848 if (large_fwd_open)
7850 dissect_net_param32(tvb, offset+26, cmd_tree,
7851 hf_cip_cm_ot_net_params32, hf_cip_cm_lfwo_own, hf_cip_cm_lfwo_typ,
7852 hf_cip_cm_lfwo_prio, hf_cip_cm_lfwo_fixed_var, hf_cip_cm_lfwo_con_size, ett_cm_ncp, &O2T_info);
7853 net_param_offset = 4;
7855 else
7857 dissect_net_param16(tvb, offset+26, cmd_tree,
7858 hf_cip_cm_ot_net_params16, hf_cip_cm_fwo_own, hf_cip_cm_fwo_typ,
7859 hf_cip_cm_fwo_prio, hf_cip_cm_fwo_fixed_var, hf_cip_cm_fwo_con_size, ett_cm_ncp, &O2T_info);
7860 net_param_offset = 2;
7863 // T->O parameters
7864 proto_tree_add_item_ret_uint(cmd_tree, hf_cip_cm_to_rpi, tvb, offset + 26 + net_param_offset, 4, ENC_LITTLE_ENDIAN, &T2O_info.rpi);
7865 if (large_fwd_open)
7867 dissect_net_param32(tvb, offset+26+net_param_offset+4, cmd_tree,
7868 hf_cip_cm_to_net_params32, hf_cip_cm_lfwo_own, hf_cip_cm_lfwo_typ,
7869 hf_cip_cm_lfwo_prio, hf_cip_cm_lfwo_fixed_var, hf_cip_cm_lfwo_con_size, ett_cm_ncp, &T2O_info);
7870 net_param_offset += 4;
7872 else
7874 dissect_net_param16(tvb, offset+26+net_param_offset+4, cmd_tree,
7875 hf_cip_cm_to_net_params16, hf_cip_cm_fwo_own, hf_cip_cm_fwo_typ,
7876 hf_cip_cm_fwo_prio, hf_cip_cm_fwo_fixed_var, hf_cip_cm_fwo_con_size, ett_cm_ncp, &T2O_info);
7877 net_param_offset += 2;
7880 TransportClass_trigger = tvb_get_uint8( tvb, offset+26+net_param_offset+4);
7881 dissect_transport_type_trigger(tvb, offset+26+net_param_offset+4, cmd_tree, hf_cip_cm_transport_type_trigger,
7882 hf_cip_cm_fwo_dir, hf_cip_cm_fwo_trigg, hf_cip_cm_fwo_class, ett_cm_ttt);
7884 /* Add path size */
7885 conn_path_size = tvb_get_uint8( tvb, offset+26+net_param_offset+5 )*2;
7886 proto_tree_add_item(cmd_tree, hf_cip_cm_conn_path_size, tvb, offset+26+net_param_offset+5, 1, ENC_LITTLE_ENDIAN);
7888 /* Add the epath */
7889 epath_tree = proto_tree_add_subtree(cmd_tree, tvb, offset+26+net_param_offset+6, conn_path_size, ett_path, &pi, "Connection Path: ");
7890 dissect_epath( tvb, pinfo, epath_tree, pi, offset+26+net_param_offset+6, conn_path_size, false, false, &connection_path, &safety_fwdopen, DISPLAY_CONNECTION_PATH, NULL, false);
7891 save_route_connection_path(pinfo, tvb, offset + 26 + net_param_offset + 6, conn_path_size);
7893 // Null Forward Opens are a special case, so make it obvious.
7894 if ((O2T_info.type == CONN_TYPE_NULL) && (T2O_info.type == CONN_TYPE_NULL))
7896 col_append_str(pinfo->cinfo, COL_INFO, " [Null]");
7897 expert_add_info(pinfo, cmd_item, &ei_cip_null_fwd_open);
7900 if (pinfo->fd->visited)
7902 /* "Connection" is created during ForwardOpen reply (which will be after ForwardOpen request),
7903 so ForwardOpen request can only be marked after the first pass */
7904 enip_mark_connection_triad(pinfo, &conn_triad);
7906 else
7908 if (preq_info != NULL)
7910 DISSECTOR_ASSERT(preq_info->connInfo == NULL);
7911 preq_info->connInfo = wmem_new0(wmem_file_scope(), cip_conn_info_t);
7913 preq_info->connInfo->triad = conn_triad;
7914 preq_info->connInfo->open_req_frame = pinfo->num;
7916 preq_info->connInfo->O2T = O2T_info;
7917 preq_info->connInfo->T2O = T2O_info;
7919 preq_info->connInfo->TransportClass_trigger = TransportClass_trigger;
7920 preq_info->connInfo->IsNullFwdOpen = (O2T_info.type == CONN_TYPE_NULL) && (T2O_info.type == CONN_TYPE_NULL);
7921 preq_info->connInfo->timeout_multiplier = timeout_multiplier;
7922 preq_info->connInfo->safety = safety_fwdopen;
7923 if (preq_info->connInfo->safety.safety_seg)
7925 bool server_dir = (TransportClass_trigger & CI_PRODUCTION_DIR_MASK) ? true : false;
7926 if (server_dir)
7928 preq_info->connInfo->safety.originator_type = CIP_SAFETY_ORIGINATOR_PRODUCER;
7930 else
7932 preq_info->connInfo->safety.originator_type = CIP_SAFETY_ORIGINATOR_CONSUMER;
7936 preq_info->connInfo->connection_path = connection_path;
7938 preq_info->connInfo->FwdOpenPathLenBytes = conn_path_size;
7939 preq_info->connInfo->pFwdOpenPathData = wmem_alloc(wmem_file_scope(), conn_path_size);
7940 tvb_memcpy(tvb, preq_info->connInfo->pFwdOpenPathData, offset + 26 + net_param_offset + 6, conn_path_size);
7944 display_connection_information_fwd_open_req(pinfo, tvb, cmd_tree);
7947 static void display_previous_route_connection_path(cip_req_info_t *preq_info, proto_tree *item_tree, tvbuff_t *tvb, packet_info *pinfo, int hf_path, int display_type)
7949 if (preq_info && preq_info->RouteConnectionPathLen && preq_info->pRouteConnectionPath)
7951 tvbuff_t* tvbIOI = tvb_new_real_data((const uint8_t *)preq_info->pRouteConnectionPath, preq_info->RouteConnectionPathLen * 2, preq_info->RouteConnectionPathLen * 2);
7952 if (!tvbIOI)
7954 return;
7957 proto_item* pi = proto_tree_add_uint(item_tree, hf_path, tvb, 0, 0, preq_info->RouteConnectionPathLen);
7958 proto_item_set_generated(pi);
7960 proto_tree* epath_tree = proto_tree_add_subtree(item_tree, tvb, 0, 0, ett_path, &pi, "Route/Connection Path: ");
7961 proto_item_set_generated(pi);
7963 cip_simple_request_info_t route_conn_path;
7964 dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, preq_info->RouteConnectionPathLen * 2, true, false, &route_conn_path, NULL, display_type, NULL, false);
7965 tvb_free(tvbIOI);
7967 if (preq_info->connInfo && preq_info->connInfo->IsNullFwdOpen)
7969 col_append_str(pinfo->cinfo, COL_INFO, " [Null]");
7970 expert_add_info(pinfo, item_tree, &ei_cip_null_fwd_open);
7975 typedef struct safety_application_reply_data {
7976 cip_connection_triad_t target_triad;
7977 uint16_t init_rollover_value;
7978 uint16_t init_timestamp_value;
7979 } safety_application_reply_data_t;
7981 static int dissect_fwd_open_rsp_safety_application_reply_data(cip_req_info_t* preq_info, proto_tree* tree, tvbuff_t* tvb, int offset, safety_application_reply_data_t* safety_reply_data)
7983 int reply_parsed_len = 10;
7985 proto_item* safety_item;
7986 proto_tree* safety_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cip_cm_safety, &safety_item, "");
7988 // Consumer Number and PID/CID are common to all formats.
7989 proto_tree_add_item(safety_tree, hf_cip_cm_consumer_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
7991 proto_item* pid_item;
7992 proto_tree* pid_tree = proto_tree_add_subtree(safety_tree, tvb, offset + 2, 8, ett_cip_cm_pid, &pid_item, "");
7993 bool server_dir = (preq_info->connInfo->TransportClass_trigger & CI_PRODUCTION_DIR_MASK) ? true : false;
7994 if (server_dir)
7996 proto_item_set_text(pid_item, "Consumer ID (CID)");
7998 else
8000 proto_item_set_text(pid_item, "Producer ID (PID)");
8003 proto_tree_add_item(pid_tree, hf_cip_cm_targ_vendor_id, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
8004 safety_reply_data->target_triad.VendorID = tvb_get_letohs(tvb, offset + 2);
8006 proto_tree_add_item_ret_uint(pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &(safety_reply_data->target_triad.DeviceSerialNumber));
8008 proto_tree_add_item(pid_tree, hf_cip_cm_targ_conn_serial_num, tvb, offset + 8, 2, ENC_LITTLE_ENDIAN);
8009 safety_reply_data->target_triad.ConnSerialNumber = tvb_get_letohs(tvb, offset + 8);
8011 if (preq_info->connInfo->safety.format == CIP_SAFETY_EXTENDED_FORMAT)
8013 proto_tree_add_item(safety_tree, hf_cip_cm_initial_timestamp, tvb, offset + 10, 2, ENC_LITTLE_ENDIAN);
8014 safety_reply_data->init_timestamp_value = tvb_get_letohs(tvb, offset + 10);
8016 proto_tree_add_item(safety_tree, hf_cip_cm_initial_rollover, tvb, offset + 12, 2, ENC_LITTLE_ENDIAN);
8017 safety_reply_data->init_rollover_value = tvb_get_letohs(tvb, offset + 12);
8019 reply_parsed_len += 4;
8021 proto_item_set_text(safety_item, "CIP Safety Extended Format Target Application Reply");
8023 else // CIP_SAFETY_BASE_FORMAT
8025 proto_item_set_text(safety_item, "CIP Safety Target Application Reply");
8028 proto_item_set_len(safety_item, reply_parsed_len);
8030 return reply_parsed_len;
8033 bool cip_connection_triad_match(const cip_connection_triad_t* left, const cip_connection_triad_t* right)
8035 return (left->ConnSerialNumber == right->ConnSerialNumber) &&
8036 (left->VendorID == right->VendorID) &&
8037 (left->DeviceSerialNumber == right->DeviceSerialNumber);
8040 static int
8041 dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
8043 int parsed_len = 26;
8045 /* Display originator to target connection ID */
8046 uint32_t O2TConnID;
8047 proto_tree_add_item_ret_uint(tree, hf_cip_cm_ot_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &O2TConnID);
8049 /* Display target to originator connection ID */
8050 uint32_t T2OConnID;
8051 proto_tree_add_item_ret_uint(tree, hf_cip_cm_to_connid, tvb, offset+4, 4, ENC_LITTLE_ENDIAN, &T2OConnID);
8053 // Add Connection IDs as hidden items so that it's easy to find all Connection IDs in different fields.
8054 proto_item* pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
8055 proto_item_set_hidden(pi);
8056 pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
8057 proto_item_set_hidden(pi);
8059 cip_connection_triad_t conn_triad;
8060 dissect_connection_triad(tvb, offset + 8, tree,
8061 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
8062 &conn_triad);
8064 /* Display originator to target actual packet interval */
8065 uint32_t O2TAPI;
8066 proto_tree_add_item_ret_uint(tree, hf_cip_cm_ot_api, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN, &O2TAPI);
8068 /* Display originator to target actual packet interval */
8069 uint32_t T2OAPI;
8070 proto_tree_add_item_ret_uint(tree, hf_cip_cm_to_api, tvb, offset + 20, 4, ENC_LITTLE_ENDIAN, &T2OAPI);
8072 /* Display the application reply size */
8073 uint16_t app_rep_size = tvb_get_uint8( tvb, offset+24 ) * 2;
8074 proto_tree_add_item(tree, hf_cip_cm_app_reply_size, tvb, offset+24, 1, ENC_LITTLE_ENDIAN);
8076 /* Display the Reserved byte */
8077 proto_tree_add_item(tree, hf_cip_reserved8, tvb, offset+25, 1, ENC_LITTLE_ENDIAN );
8079 // Handle the Application Reply Data.
8080 int reply_parsed_len = 0;
8081 safety_application_reply_data_t safety_reply_data = {0};
8082 if (preq_info && preq_info->connInfo && preq_info->connInfo->safety.safety_seg == true)
8084 reply_parsed_len = dissect_fwd_open_rsp_safety_application_reply_data(preq_info, tree, tvb, offset + 26, &safety_reply_data);
8087 int remaining_reply_len = app_rep_size - reply_parsed_len;
8088 if (remaining_reply_len > 0)
8090 proto_tree_add_item(tree, hf_cip_cm_app_reply_data, tvb, offset + 26 + reply_parsed_len, remaining_reply_len, ENC_NA);
8093 display_connection_information_fwd_open_rsp(pinfo, tvb, tree, preq_info);
8095 /* See if we've captured the ForwardOpen request. If so some of the conversation data has already been
8096 populated and we just need to update it. */
8097 if (pinfo->fd->visited)
8098 return parsed_len + app_rep_size;
8100 if ((preq_info != NULL) && (preq_info->connInfo != NULL))
8102 /* Ensure the connection triad matches before updating the connection IDs */
8103 if (cip_connection_triad_match(&(preq_info->connInfo->triad), &conn_triad))
8105 /* Update the connection IDs as ForwardOpen reply is allowed to update them from
8106 the ForwardOpen request */
8107 preq_info->connInfo->O2T.connID = O2TConnID;
8108 preq_info->connInfo->T2O.connID = T2OConnID;
8110 preq_info->connInfo->O2T.api = O2TAPI;
8111 preq_info->connInfo->T2O.api = T2OAPI;
8112 if (preq_info->connInfo->safety.safety_seg == true)
8114 preq_info->connInfo->safety.running_rollover_value = safety_reply_data.init_rollover_value;
8115 preq_info->connInfo->safety.running_timestamp_value = safety_reply_data.init_timestamp_value;
8116 preq_info->connInfo->safety.target_triad = safety_reply_data.target_triad;
8117 preq_info->connInfo->safety.seen_non_zero_timestamp = false;
8122 return parsed_len + app_rep_size;
8125 static void dissect_cip_cm_unconnected_send_req(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
8127 /* Display timeout fields */
8128 dissect_cip_cm_timeout(cmd_data_tree, tvb, offset);
8130 /* Message request size */
8131 uint16_t msg_req_siz = tvb_get_letohs(tvb, offset + 2);
8132 proto_tree_add_item(cmd_data_tree, hf_cip_cm_msg_req_size, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
8134 /* Message Request */
8135 proto_tree* temp_tree = proto_tree_add_subtree(cmd_data_tree, tvb, offset + 4, msg_req_siz, ett_cm_mes_req, NULL, "CIP Embedded Message Request");
8138 ** We call ourselves again to dissect embedded packet
8141 col_append_str(pinfo->cinfo, COL_INFO, ": ");
8143 tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset + 4, msg_req_siz);
8144 cip_req_info_t* preq_info = (cip_req_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8145 cip_req_info_t* pembedded_req_info = NULL;
8146 if (preq_info)
8148 if (preq_info->pData == NULL)
8150 pembedded_req_info = wmem_new0(wmem_file_scope(), cip_req_info_t);
8151 preq_info->pData = pembedded_req_info;
8153 else
8155 pembedded_req_info = (cip_req_info_t*)preq_info->pData;
8159 dissect_cip_data(temp_tree, next_tvb, 0, pinfo, pembedded_req_info, NULL, false);
8161 if (msg_req_siz % 2)
8163 /* Pad byte */
8164 proto_tree_add_item(cmd_data_tree, hf_cip_pad8, tvb, offset + 4 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
8165 msg_req_siz++; /* include the padding */
8168 /* Route Path Size */
8169 uint16_t route_path_size = tvb_get_uint8(tvb, offset + 4 + msg_req_siz) * 2;
8170 proto_tree_add_item(cmd_data_tree, hf_cip_cm_route_path_size, tvb, offset + 4 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
8172 /* Display the Reserved byte */
8173 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 5 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
8175 /* Route Path */
8176 proto_item* epath_item;
8177 proto_tree* epath_tree = proto_tree_add_subtree(cmd_data_tree, tvb, offset + 6 + msg_req_siz, route_path_size, ett_path, &epath_item, "Route Path: ");
8178 dissect_epath(tvb, pinfo, epath_tree, epath_item, offset + 6 + msg_req_siz, route_path_size, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
8180 save_route_connection_path(pinfo, tvb, offset + 6 + msg_req_siz, route_path_size);
8183 static void dissect_cip_cm_fwd_close_req(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
8185 cip_simple_request_info_t conn_path;
8187 dissect_cip_cm_timeout(cmd_data_tree, tvb, offset);
8189 cip_connection_triad_t conn_triad;
8190 dissect_connection_triad(tvb, offset + 2, cmd_data_tree,
8191 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
8192 &conn_triad);
8194 /* Add the path size */
8195 uint16_t conn_path_size = tvb_get_uint8(tvb, offset + 10) * 2;
8196 proto_tree_add_item(cmd_data_tree, hf_cip_cm_conn_path_size, tvb, offset + 10, 1, ENC_LITTLE_ENDIAN);
8198 /* Display the Reserved byte */
8199 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 11, 1, ENC_LITTLE_ENDIAN);
8201 /* Add the EPATH */
8202 proto_item *pi;
8203 proto_tree* epath_tree = proto_tree_add_subtree(cmd_data_tree, tvb, offset + 12, conn_path_size, ett_path, &pi, "Connection Path: ");
8204 dissect_epath(tvb, pinfo, epath_tree, pi, offset + 12, conn_path_size, false, false, &conn_path, NULL, DISPLAY_CONNECTION_PATH, NULL, false);
8205 save_route_connection_path(pinfo, tvb, offset + 12, conn_path_size);
8207 enip_close_cip_connection(pinfo, &conn_triad);
8208 display_connection_information_fwd_close_req(pinfo, tvb, cmd_data_tree);
8211 static int dissect_cip_cm_fwd_close_rsp_success(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo, proto_item* cmd_item)
8213 cip_connection_triad_t conn_triad;
8214 dissect_connection_triad(tvb, offset, cmd_data_tree,
8215 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
8216 &conn_triad);
8218 /* Display the application reply size */
8219 uint16_t app_rep_size = tvb_get_uint8(tvb, offset + 8) * 2;
8220 proto_tree_add_item(cmd_data_tree, hf_cip_cm_app_reply_size, tvb, offset + 8, 1, ENC_LITTLE_ENDIAN);
8222 /* Display the Reserved byte */
8223 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 9, 1, ENC_LITTLE_ENDIAN);
8224 if (app_rep_size > 0)
8226 if (tvb_reported_length_remaining(tvb, offset + 10) < app_rep_size)
8228 expert_add_info(pinfo, cmd_item, &ei_mal_fwd_close_missing_data);
8229 return 0;
8231 proto_tree_add_item(cmd_data_tree, hf_cip_cm_app_reply_data, tvb, offset + 10, app_rep_size, ENC_NA);
8234 if (!pinfo->fd->visited)
8235 enip_mark_connection_triad(pinfo, &conn_triad);
8237 display_connection_information_fwd_close_rsp(pinfo, tvb, cmd_data_tree);
8239 return 10 + app_rep_size;
8242 static void display_previous_request_path(cip_req_info_t *preq_info, proto_tree *item_tree, tvbuff_t *tvb, packet_info *pinfo, proto_item* msp_item, bool is_msp_item)
8244 if (preq_info && preq_info->IOILen && preq_info->pIOI)
8246 proto_item *pi;
8247 proto_tree *epath_tree;
8248 tvbuff_t* tvbIOI;
8250 tvbIOI = tvb_new_real_data((const uint8_t *)preq_info->pIOI, preq_info->IOILen * 2, preq_info->IOILen * 2);
8251 if (tvbIOI)
8253 pi = proto_tree_add_uint(item_tree, hf_cip_request_path_size, tvb, 0, 0, preq_info->IOILen);
8254 proto_item_set_generated(pi);
8256 /* Add the epath */
8257 epath_tree = proto_tree_add_subtree(item_tree, tvb, 0, 0, ett_path, &pi, "Request Path: ");
8258 proto_item_set_generated(pi);
8260 if (preq_info->ciaData == NULL)
8262 preq_info->ciaData = wmem_new(wmem_file_scope(), cip_simple_request_info_t);
8265 dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, preq_info->IOILen * 2, true, false, preq_info->ciaData, NULL, DISPLAY_REQUEST_PATH, msp_item, is_msp_item);
8266 tvb_free(tvbIOI);
8271 static void
8272 dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
8274 proto_item *rrsc_item, *status_item;
8275 proto_tree *rrsc_tree, *cmd_data_tree;
8276 int req_path_size;
8277 unsigned char service, gen_status, add_stat_size;
8278 unsigned short add_status;
8279 int i;
8280 cip_req_info_t *preq_info;
8282 service = tvb_get_uint8( tvb, offset );
8284 /* Special handling for Unconnected send response. If successful, embedded service code is sent.
8285 * If failed, it can be either an Unconnected send response or the embedded service code response. */
8286 preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
8287 if ( preq_info != NULL && ( service & CIP_SC_RESPONSE_MASK )
8288 && preq_info->bService == SC_CM_UNCON_SEND
8291 gen_status = tvb_get_uint8( tvb, offset+2 );
8292 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
8293 if ( add_stat_size == 2 )
8294 add_status = tvb_get_letohs( tvb, offset + 4 );
8295 else
8296 add_status = 0;
8298 if( gen_status == CI_GRC_SUCCESS
8299 || ( ( service & CIP_SC_MASK ) != SC_CM_UNCON_SEND )
8300 || !( ( gen_status == CI_GRC_FAILURE && (add_status == CM_ES_UNCONNECTED_REQUEST_TIMED_OUT ||
8301 add_status == CM_ES_PORT_NOT_AVAILABLE ||
8302 add_status == CM_ES_LINK_ADDRESS_NOT_VALID ||
8303 add_status == CM_ES_INVALID_SEGMENT_IN_CONN_PATH ||
8304 add_status == CM_ES_LINK_ADDRESS_TO_SELF_INVALID))
8305 || gen_status == CI_GRC_NO_RESOURCE
8306 || gen_status == CI_GRC_BAD_PATH
8310 cip_req_info_t* pembedded_req_info = (cip_req_info_t*)preq_info->pData;
8312 if ( pembedded_req_info )
8314 tvbuff_t *next_tvb;
8315 void *p_save_proto_data;
8316 int service_index;
8317 heur_dtbl_entry_t *hdtbl_entry;
8319 p_save_proto_data = p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
8320 p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8321 p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, pembedded_req_info );
8323 proto_item_set_generated(proto_tree_add_uint_format( item_tree, hf_cip_cm_sc, tvb, 0, 0, SC_CM_UNCON_SEND|CIP_SC_RESPONSE_MASK, "Service: Unconnected Send (Response)" ));
8324 next_tvb = tvb_new_subset_length(tvb, offset, item_length);
8326 display_previous_request_path(pembedded_req_info, item_tree, tvb, pinfo, NULL, false);
8327 display_previous_route_connection_path(preq_info, item_tree, tvb, pinfo, hf_cip_cm_route_path_size, NO_DISPLAY);
8329 /* Check to see if service is 'generic' */
8330 try_val_to_str_idx((service & CIP_SC_MASK), cip_sc_vals, &service_index);
8332 cip_service_info_t* service_entry = cip_get_service(pinfo, service);
8333 if ( pembedded_req_info && pembedded_req_info->dissector )
8335 call_dissector(pembedded_req_info->dissector, next_tvb, pinfo, item_tree );
8337 else if (service_index >= 0 && !service_entry)
8339 /* See if object dissector wants to override generic service handling */
8340 if (!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
8342 dissect_cip_generic_service_rsp(tvb, pinfo, item_tree);
8345 else if (service_entry)
8347 dissect_cip_object_specific_service(tvb, pinfo, item_tree, NULL, service_entry);
8349 else
8351 call_dissector( cip_class_generic_handle, next_tvb, pinfo, item_tree );
8354 p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8355 p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, p_save_proto_data);
8357 /* Return early because the response was only the embedded message response. */
8358 return;
8363 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP CM");
8365 /* Add Service code & Request/Response tree */
8366 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_cm_rrsc, &rrsc_item, "Service: " );
8368 /* Add Request/Response */
8369 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8371 /* watch for service collisions */
8372 proto_item_append_text( rrsc_item, "%s (%s)",
8373 val_to_str( ( service & CIP_SC_MASK ),
8374 cip_sc_vals_cm , "Unknown Service (0x%02x)"),
8375 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
8376 cip_sc_rr, "") );
8378 /* Add Service code */
8379 proto_tree_add_item(rrsc_tree, hf_cip_cm_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8380 add_cip_service_to_info_column(pinfo, service, cip_sc_vals_cm);
8382 if( service & CIP_SC_RESPONSE_MASK )
8384 /* Response message */
8385 gen_status = tvb_get_uint8( tvb, offset+2 );
8386 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
8388 if (gen_status == CI_GRC_FAILURE)
8390 /* Dissect object specific error codes */
8391 proto_tree* status_tree = proto_tree_add_subtree(item_tree, tvb, offset+2, 1, ett_status_item, &status_item, "Status: " );
8393 /* Add general status */
8394 proto_tree_add_item(status_tree, hf_cip_cm_genstat, tvb, offset+2, 1, ENC_LITTLE_ENDIAN );
8395 proto_item_append_text( status_item, "%s", val_to_str_ext( gen_status,
8396 &cip_gs_vals_ext , "Unknown Response (%x)") );
8398 /* Add additional status size */
8399 proto_tree_add_item(status_tree, hf_cip_cm_addstat_size, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
8401 if( add_stat_size )
8403 add_status = tvb_get_letohs( tvb, offset + 4 );
8404 proto_tree_add_item(status_tree, hf_cip_cm_ext_status, tvb, offset+4, 2, ENC_LITTLE_ENDIAN );
8405 proto_item_append_text(status_item, ", Extended: %s", val_to_str_ext(add_status, &cip_cm_ext_st_vals_ext, "Reserved (0x%04x)"));
8407 switch(add_status)
8409 case CM_ES_RPI_NOT_ACCEPTABLE:
8410 if (add_stat_size < 3)
8412 expert_add_info(pinfo, status_item, &ei_mal_rpi_no_data);
8414 else
8416 proto_tree_add_item(status_tree, hf_cip_cm_ext112_ot_rpi_type, tvb, offset+6, 1, ENC_LITTLE_ENDIAN );
8417 proto_tree_add_item(status_tree, hf_cip_cm_ext112_to_rpi_type, tvb, offset+7, 1, ENC_LITTLE_ENDIAN );
8418 proto_tree_add_item(status_tree, hf_cip_cm_ext112_ot_rpi, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN);
8419 proto_tree_add_item(status_tree, hf_cip_cm_ext112_to_rpi, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN);
8421 break;
8422 case CM_ES_INVALID_CONFIGURATION_SIZE:
8423 proto_tree_add_item(status_tree, hf_cip_cm_ext126_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
8424 break;
8425 case CM_ES_INVALID_OT_SIZE:
8426 proto_tree_add_item(status_tree, hf_cip_cm_ext127_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
8427 break;
8428 case CM_ES_INVALID_TO_SIZE:
8429 proto_tree_add_item(status_tree, hf_cip_cm_ext128_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
8430 break;
8431 default:
8432 /* Add additional status */
8433 if (add_stat_size > 1)
8435 proto_tree* add_status_tree = proto_tree_add_subtree( status_tree, tvb, offset+4, add_stat_size, ett_cm_add_status_item, NULL, "Additional Status" );
8437 for( i=0; i < add_stat_size-2; i += 2 )
8438 proto_tree_add_item(add_status_tree, hf_cip_cm_add_status, tvb, offset+4+i, 2, ENC_LITTLE_ENDIAN );
8444 /* If there is any command specific data create a sub-tree for it */
8445 int data_len = item_length - 4 - add_stat_size;
8446 if (data_len > 0)
8448 int parsed_len = 0;
8449 offset += (4 + add_stat_size);
8451 proto_item *cmd_item;
8452 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset, data_len,
8453 ett_cm_cmd_data, &cmd_item, "Command Specific Data" );
8455 if( gen_status == CI_GRC_SUCCESS )
8457 /* Success responses */
8458 switch (service & CIP_SC_MASK)
8460 case SC_CM_FWD_OPEN:
8461 case SC_CM_LARGE_FWD_OPEN:
8462 case SC_CM_CONCURRENT_FWD_OPEN:
8463 parsed_len = dissect_cip_cm_fwd_open_rsp_success(preq_info, cmd_data_tree, tvb, offset, pinfo);
8464 break;
8465 case SC_CM_FWD_CLOSE:
8466 case SC_CM_CONCURRENT_FWD_CLOSE:
8467 parsed_len = dissect_cip_cm_fwd_close_rsp_success(cmd_data_tree, tvb, offset, pinfo, cmd_item);
8468 break;
8469 case SC_CM_GET_CONN_OWNER:
8471 /* Get Connection owner response (Success) */
8472 proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_conn, tvb, offset, 1, ENC_LITTLE_ENDIAN);
8473 proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_coo_conn, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
8474 proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_roo_conn, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
8475 proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_last_action, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
8477 dissect_connection_triad(tvb, offset + 4, cmd_data_tree,
8478 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
8479 NULL);
8481 parsed_len = 12;
8483 break;
8484 case SC_CM_UNCON_SEND: // Unconnected send response (Success)
8485 default:
8486 parsed_len = 0;
8487 break;
8490 else
8492 /* Error responses */
8493 switch (service & CIP_SC_MASK)
8495 case SC_CM_FWD_OPEN:
8496 case SC_CM_LARGE_FWD_OPEN:
8497 case SC_CM_FWD_CLOSE:
8498 case SC_CM_CONCURRENT_FWD_OPEN:
8499 case SC_CM_CONCURRENT_FWD_CLOSE:
8501 /* Forward open and forward close error response look the same */
8502 cip_connection_triad_t conn_triad;
8503 dissect_connection_triad(tvb, offset, cmd_data_tree,
8504 hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
8505 &conn_triad);
8507 // Remaining Path Size is an optional structure.
8508 if (tvb_reported_length_remaining(tvb, offset + 8) > 0)
8510 proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset+8, 1, ENC_LITTLE_ENDIAN);
8511 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+9, 1, ENC_LITTLE_ENDIAN);
8514 /* With an error reply the connection will either never be established or it has since already closed
8515 That means the conversation should end too */
8516 enip_close_cip_connection(pinfo, &conn_triad);
8517 if (preq_info != NULL)
8519 /* Remove any connection information */
8520 preq_info->connInfo = NULL;
8524 display_previous_route_connection_path(preq_info, cmd_data_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
8526 parsed_len = 10;
8527 break;
8529 case SC_CM_UNCON_SEND:
8530 /* Unconnected send response (Unsuccess) */
8531 proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
8532 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
8533 display_previous_route_connection_path(preq_info, item_tree, tvb, pinfo, hf_cip_cm_route_path_size, NO_DISPLAY);
8534 parsed_len = 2;
8535 break;
8536 default:
8537 parsed_len = 0;
8538 break;
8540 } /* end of if-else( CI_CRC_SUCCESS ) */
8542 int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
8543 if (remain_len > 0)
8545 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
8547 } /* End of if command-specific data present */
8549 } /* End of if reply */
8550 else
8552 /* Request message */
8554 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
8556 /* If there is any command specific data creat a sub-tree for it */
8557 if( (item_length-req_path_size-2) != 0 )
8559 proto_item* cmd_data_item;
8560 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
8561 ett_cm_cmd_data, &cmd_data_item, "Command Specific Data" );
8563 /* Check what service code that received */
8564 switch (service)
8566 case SC_CM_FWD_OPEN:
8567 /* Forward open Request*/
8568 dissect_cip_cm_fwd_open_req(preq_info, cmd_data_tree, cmd_data_item, tvb, offset+2+req_path_size, false, pinfo, false);
8569 break;
8570 case SC_CM_CONCURRENT_FWD_OPEN:
8571 dissect_cip_cm_fwd_open_req(preq_info, cmd_data_tree, cmd_data_item, tvb, offset+2+req_path_size, false, pinfo, true);
8572 break;
8573 case SC_CM_LARGE_FWD_OPEN:
8574 /* Large Forward open Request*/
8575 dissect_cip_cm_fwd_open_req(preq_info, cmd_data_tree, cmd_data_item, tvb, offset+2+req_path_size, true, pinfo, false);
8576 break;
8577 case SC_CM_FWD_CLOSE:
8578 case SC_CM_CONCURRENT_FWD_CLOSE:
8579 dissect_cip_cm_fwd_close_req(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
8580 break;
8581 case SC_CM_UNCON_SEND:
8582 dissect_cip_cm_unconnected_send_req(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
8583 break;
8584 case SC_CM_GET_CONN_OWNER:
8586 /* Get Connection Owner Request */
8588 /* Display the Reserved byte */
8589 proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
8591 /* Add path size */
8592 uint16_t conn_path_size = tvb_get_uint8( tvb, offset+2+req_path_size+1 )*2;
8593 proto_tree_add_item(cmd_data_tree, hf_cip_cm_conn_path_size, tvb, offset+2+req_path_size+1, 1, ENC_LITTLE_ENDIAN);
8595 /* Add the epath */
8596 proto_item* pi;
8597 proto_tree* epath_tree = proto_tree_add_subtree(cmd_data_tree, tvb, offset+2+req_path_size+2, conn_path_size, ett_path, &pi, "Connection Path: ");
8598 dissect_epath(tvb, pinfo, epath_tree, pi, offset+2+req_path_size+2, conn_path_size, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
8599 break;
8601 default:
8602 /* Add data */
8603 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
8606 } /* End of if command-specific data present */
8608 } /* End of if-else( request ) */
8610 } /* End of dissect_cip_cm_data() */
8612 static int
8613 dissect_cip_class_cm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
8615 proto_item *ti;
8616 proto_tree *class_tree;
8618 /* Create display subtree for the protocol */
8619 ti = proto_tree_add_item(tree, proto_cip_class_cm, tvb, 0, -1, ENC_NA);
8620 class_tree = proto_item_add_subtree( ti, ett_cip_class_cm );
8622 dissect_cip_cm_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
8624 return tvb_reported_length(tvb);
8627 /************************************************
8629 * Dissector for CIP PCCC Object
8631 ************************************************/
8632 static void
8633 dissect_cip_pccc_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
8635 proto_item *rrsc_item;
8636 proto_tree *rrsc_tree, *req_id_tree, *pccc_cmd_tree, *cmd_data_tree;
8637 int req_path_size;
8638 unsigned char service;
8639 int add_status;
8641 service = tvb_get_uint8( tvb, offset );
8643 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP PCCC");
8645 /* Add Service code & Request/Response tree */
8646 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_pccc_rrsc, &rrsc_item, "Service: " );
8648 /* Add Request/Response */
8649 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8651 /* watch for service collisions */
8652 proto_item_append_text( rrsc_item, "%s (%s)",
8653 val_to_str( ( service & CIP_SC_MASK ),
8654 cip_sc_vals_pccc , "Unknown Service (0x%02x)"),
8655 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
8656 cip_sc_rr, "") );
8658 /* Add Service code */
8659 proto_tree_add_item(rrsc_tree, hf_cip_pccc_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8660 add_cip_service_to_info_column (pinfo, service, cip_sc_vals_pccc);
8662 /* There is a minimum of two bytes different between the request and response request path */
8663 /* Response message */
8664 if ( service & CIP_SC_RESPONSE_MASK )
8666 req_path_size = 2 + tvb_get_uint8( tvb, offset+2 )*2;
8668 /* Request message */
8669 else
8671 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
8674 int req_id_offset = offset+req_path_size+2;
8675 int req_id_size = tvb_get_uint8( tvb, req_id_offset );
8676 int pccc_cmd_offset = req_id_offset+req_id_size;
8678 /* Add Requestor ID tree */
8679 req_id_tree = proto_tree_add_subtree( item_tree, tvb, req_id_offset, req_id_size, ett_pccc_req_id, NULL, "Requestor ID" );
8680 /* Add Length of Requestor ID code */
8681 proto_tree_add_item(req_id_tree, hf_cip_pccc_req_id_len, tvb, req_id_offset, 1, ENC_LITTLE_ENDIAN );
8682 /* Add CIP Vendor ID */
8683 proto_tree_add_item(req_id_tree, hf_cip_pccc_cip_vend_id, tvb, req_id_offset+1, 2, ENC_LITTLE_ENDIAN );
8684 /* Add CIP Serial Number */
8685 proto_tree_add_item(req_id_tree, hf_cip_pccc_cip_serial_num, tvb, req_id_offset+3, 4, ENC_LITTLE_ENDIAN );
8687 if( service & CIP_SC_RESPONSE_MASK )
8689 /* Add PCCC Response Data tree */
8690 pccc_cmd_tree = proto_tree_add_subtree( item_tree, tvb, pccc_cmd_offset, item_length-req_path_size-2-req_id_size, ett_pccc_req_id, NULL, "PCCC Response Data" );
8692 /* Add Command Code */
8693 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_resp_code, tvb, pccc_cmd_offset, 1, ENC_LITTLE_ENDIAN );
8694 /* Add Status Code */
8695 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_sts_code, tvb, pccc_cmd_offset+1, 1, ENC_LITTLE_ENDIAN );
8696 /* Add Transaction Code */
8697 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_tns_code, tvb, pccc_cmd_offset+2, 2, ENC_LITTLE_ENDIAN );
8699 /* Check the status byte for the EXT_STS signifier - 0xF0 */
8700 add_status = tvb_get_uint8( tvb, pccc_cmd_offset+1 );
8701 // TODO: still need to test this
8702 if ( add_status == PCCC_GS_USE_EXTSTS )
8704 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_ext_sts_code, tvb, pccc_cmd_offset+4, 1, ENC_LITTLE_ENDIAN );
8706 // handle cases where data is returned in the response
8707 else if (item_length-req_path_size-2-req_id_size-4 != 0)
8709 /* Add the data tree */
8710 cmd_data_tree = proto_tree_add_subtree( pccc_cmd_tree, tvb, pccc_cmd_offset+4, item_length-req_path_size-2-req_id_size-4, ett_pccc_cmd_data, NULL, "Function Specific Response Data" );
8711 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+4, item_length-req_path_size-2-req_id_size-4, ENC_NA);
8714 } /* end of if reply */
8716 /* Request message */
8717 else
8719 /* If there is any command specific data create a sub-tree for it */
8720 if( (item_length-req_path_size-2) != 0 )
8722 uint32_t cmd_code, fnc_code;
8724 /* Add PCCC CMD Data tree */
8725 pccc_cmd_tree = proto_tree_add_subtree( item_tree, tvb, pccc_cmd_offset, item_length-req_path_size-2-req_id_size, ett_pccc_req_id, NULL, "PCCC Command Data" );
8727 /* Add Command Code */
8728 proto_tree_add_item_ret_uint(pccc_cmd_tree, hf_cip_pccc_cmd_code, tvb, pccc_cmd_offset, 1, ENC_LITTLE_ENDIAN, &cmd_code);
8729 /* Add Status Code */
8730 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_sts_code, tvb, pccc_cmd_offset+1, 1, ENC_LITTLE_ENDIAN );
8731 /* Add Transaction Code */
8732 proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_tns_code, tvb, pccc_cmd_offset+2, 2, ENC_LITTLE_ENDIAN );
8733 /* Add Function Code */
8734 switch(cmd_code)
8736 case PCCC_CMD_06:
8737 proto_tree_add_item_ret_uint(pccc_cmd_tree, hf_cip_pccc_fnc_code_06, tvb, pccc_cmd_offset+4, 1, ENC_LITTLE_ENDIAN, &fnc_code);
8738 add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_06_vals);
8739 break;
8741 case PCCC_CMD_07:
8742 proto_tree_add_item_ret_uint(pccc_cmd_tree, hf_cip_pccc_fnc_code_07, tvb, pccc_cmd_offset+4, 1, ENC_LITTLE_ENDIAN, &fnc_code);
8743 add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_07_vals);
8744 break;
8746 case PCCC_CMD_0F:
8747 proto_tree_add_item_ret_uint(pccc_cmd_tree, hf_cip_pccc_fnc_code_0f, tvb, pccc_cmd_offset+4, 1, ENC_LITTLE_ENDIAN, &fnc_code);
8748 add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_0f_vals);
8749 break;
8751 default:
8752 fnc_code = 0;
8753 break;
8756 if (item_length-req_path_size-2-req_id_size-5 != 0 )
8758 /* Add the data tree */
8759 cmd_data_tree = proto_tree_add_subtree( pccc_cmd_tree, tvb, pccc_cmd_offset+5, item_length-req_path_size-req_id_size-7,
8760 ett_pccc_cmd_data, NULL, "Function Specific Data" );
8762 int running_offset = pccc_cmd_offset+6;
8763 int num_cmds;
8764 int sub_fnc_len;
8765 proto_tree *sub_fnc_tree;
8767 /* Add in parsing of instructions that contain data beyond the FNC code */
8768 /* Instructions that end at the FNC codes are already processed */
8769 switch(cmd_code)
8771 case PCCC_CMD_0F:
8772 switch(fnc_code){
8773 /* Change CPU Mode */
8774 case PCCC_FNC_0F_80:
8775 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_cpu_mode_80, tvb, pccc_cmd_offset+5, 1, ENC_NA);
8776 break;
8777 /* Execute Multiple Commands */
8778 case PCCC_FNC_0F_88:
8779 num_cmds = tvb_get_uint8( tvb, pccc_cmd_offset+5 );
8780 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_execute_multi_count, tvb, pccc_cmd_offset+5, 1, ENC_NA);
8782 /* iterate over each of the commands and break them out */
8783 for( int i=0; i < num_cmds; i++ ){
8784 sub_fnc_len = tvb_get_uint8( tvb, running_offset);
8785 sub_fnc_tree = proto_tree_add_subtree_format(cmd_data_tree, tvb, running_offset, sub_fnc_len+1, ett_pccc_req_id, NULL, "Sub Function #%d", i+1);
8787 proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_execute_multi_len, tvb, running_offset, 1, ENC_NA);
8788 proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_execute_multi_fnc, tvb, running_offset+1, 1, ENC_NA);
8789 if( sub_fnc_len > 2 ){
8790 proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_data, tvb, running_offset+2, sub_fnc_len-1, ENC_NA);
8792 running_offset = running_offset+sub_fnc_len+1;
8794 break;
8795 /* Protected Typed Logical Read with Three Address Fields */
8796 case PCCC_FNC_0F_A2:
8797 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_byte_size, tvb, pccc_cmd_offset+5, 1, ENC_NA);
8798 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_num, tvb, pccc_cmd_offset+6, 1, ENC_NA);
8799 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_type, tvb, pccc_cmd_offset+7, 1, ENC_NA);
8800 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_element_num, tvb, pccc_cmd_offset+8, 1, ENC_NA);
8801 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_subelement_num, tvb, pccc_cmd_offset+9, 1, ENC_NA);
8802 break;
8803 /* Protected Typed Logical Write with Three Address Fields */
8804 case PCCC_FNC_0F_AA:
8805 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_byte_size, tvb, pccc_cmd_offset+5, 1, ENC_NA);
8806 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_num, tvb, pccc_cmd_offset+6, 1, ENC_NA);
8807 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_type, tvb, pccc_cmd_offset+7, 1, ENC_NA);
8808 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_element_num, tvb, pccc_cmd_offset+8, 1, ENC_NA);
8809 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_subelement_num, tvb, pccc_cmd_offset+9, 1, ENC_NA);
8810 int byte_size;
8811 byte_size = tvb_get_uint8( tvb, pccc_cmd_offset+5 );
8813 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+10, byte_size, ENC_NA);
8814 break;
8815 default: /* just print the command data if no known command code is passed */
8816 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+5, item_length-pccc_cmd_offset-5, ENC_NA);
8818 break;
8819 default: /* just print the command data if no known command code is passed */
8820 proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+5, 1, ENC_NA);
8823 } /* End of if-else( request ) */
8826 } /* End of dissect_cip_pccc_data() */
8828 static int
8829 dissect_cip_class_pccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
8831 proto_item *ti;
8832 proto_tree *class_tree;
8834 /* Create display subtree for the protocol */
8835 ti = proto_tree_add_item(tree, proto_cip_class_pccc, tvb, 0, -1, ENC_NA);
8836 class_tree = proto_item_add_subtree( ti, ett_cip_class_pccc );
8838 dissect_cip_pccc_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
8840 return tvb_reported_length(tvb);
8843 /************************************************
8845 * Dissector for CIP Modbus Object
8847 ************************************************/
8848 static void
8849 dissect_cip_mb_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
8851 proto_item *rrsc_item;
8852 proto_tree *rrsc_tree, *cmd_data_tree;
8853 tvbuff_t *next_tvb;
8854 int req_path_size;
8855 uint8_t gen_status, add_stat_size, service;
8857 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP MB");
8859 /* Add Service code & Request/Response tree */
8860 service = tvb_get_uint8( tvb, offset );
8861 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_mb_rrsc, &rrsc_item, "Service: " );
8863 /* Add Request/Response */
8864 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8866 proto_item_append_text( rrsc_item, "%s (%s)",
8867 val_to_str( ( service & CIP_SC_MASK ),
8868 cip_sc_vals_mb , "Unknown Service (0x%02x)"),
8869 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
8870 cip_sc_rr, "") );
8872 /* Add Service code */
8873 proto_tree_add_item(rrsc_tree, hf_cip_mb_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
8875 if( service & CIP_SC_RESPONSE_MASK )
8877 /* Response message */
8878 gen_status = tvb_get_uint8( tvb, offset+2 );
8879 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
8881 /* If there is any command specific data create a sub-tree for it */
8882 if( ( item_length-4-add_stat_size ) != 0 )
8884 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
8885 ett_mb_cmd_data, NULL, "Command Specific Data" );
8887 if( gen_status == CI_GRC_SUCCESS || gen_status == CI_GRC_SERVICE_ERROR )
8889 /* Success responses */
8890 switch (service & CIP_SC_MASK)
8892 case SC_MB_READ_DISCRETE_INPUTS:
8893 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_discrete_inputs_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8894 break;
8896 case SC_MB_READ_COILS:
8897 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_coils_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8898 break;
8900 case SC_MB_READ_INPUT_REGISTERS:
8901 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_input_register_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8902 break;
8904 case SC_MB_READ_HOLDING_REGISTERS:
8905 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_holding_register_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8906 break;
8908 case SC_MB_WRITE_COILS:
8909 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_start_addr, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
8910 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_outputs_forced, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
8911 break;
8913 case SC_MB_WRITE_HOLDING_REGISTERS:
8914 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_start_addr, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
8915 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_outputs_forced, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
8916 break;
8918 case SC_MB_PASSTHROUGH:
8919 /* Passthrough response (Success) */
8920 if( tvb_reported_length_remaining(tvb, offset) > 0 )
8922 modbus_data_t modbus_data;
8923 modbus_data.packet_type = RESPONSE_PACKET;
8924 modbus_data.mbtcp_transid = 0;
8925 modbus_data.unit_id = 0;
8927 /* dissect the Modbus PDU */
8928 next_tvb = tvb_new_subset_length( tvb, offset+4+add_stat_size, item_length-4-add_stat_size);
8930 /* Call Modbus Dissector */
8931 call_dissector_with_data(modbus_handle, next_tvb, pinfo, cmd_data_tree, &modbus_data);
8934 break;
8936 default:
8937 proto_tree_add_item(cmd_data_tree, hf_cip_mb_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8940 else
8942 proto_tree_add_item(cmd_data_tree, hf_cip_mb_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
8945 } /* End of if command-specific data present */
8947 } /* End of if reply */
8948 else
8950 /* Request message */
8951 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
8953 /* If there is any command specific data creat a sub-tree for it */
8954 if( (item_length-req_path_size-2) != 0 )
8956 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
8957 ett_mb_cmd_data, NULL, "Command Specific Data" );
8959 /* Check what service code that received */
8960 switch (service)
8962 case SC_MB_READ_DISCRETE_INPUTS:
8963 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_discrete_inputs_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8964 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_discrete_inputs_num_inputs, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
8965 break;
8967 case SC_MB_READ_COILS:
8968 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_coils_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8969 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_coils_num_coils, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
8970 break;
8972 case SC_MB_READ_INPUT_REGISTERS:
8973 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_input_register_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8974 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_input_register_num_registers, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
8975 break;
8977 case SC_MB_READ_HOLDING_REGISTERS:
8978 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_holding_register_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8979 proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_holding_register_num_registers, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
8980 break;
8982 case SC_MB_WRITE_COILS:
8984 uint16_t NumCoils;
8986 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8987 NumCoils = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
8988 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_num_coils, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
8989 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_data, tvb, offset+2+req_path_size+4, (NumCoils+7)/8, ENC_NA);
8991 break;
8993 case SC_MB_WRITE_HOLDING_REGISTERS:
8995 uint16_t NumRegisters;
8997 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
8998 NumRegisters = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
8999 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_num_registers, tvb, offset+2+req_path_size+2, 2, ENC_LITTLE_ENDIAN);
9000 proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_data, tvb, offset+2+req_path_size+4, NumRegisters*2, ENC_NA);
9002 break;
9004 case SC_MB_PASSTHROUGH:
9005 /* Passthrough Request */
9006 if( tvb_reported_length_remaining(tvb, offset) > 0 )
9008 modbus_data_t modbus_data;
9009 modbus_data.packet_type = QUERY_PACKET;
9010 modbus_data.mbtcp_transid = 0;
9011 modbus_data.unit_id = 0;
9013 /* dissect the Modbus PDU */
9014 next_tvb = tvb_new_subset_length( tvb, offset+2+req_path_size, item_length-req_path_size-2);
9016 /* Call Modbus Dissector */
9017 call_dissector_with_data(modbus_handle, next_tvb, pinfo, cmd_data_tree, &modbus_data);
9019 break;
9021 default:
9022 proto_tree_add_item(cmd_data_tree, hf_cip_mb_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
9025 } /* End of if command-specific data present */
9027 } /* End of if-else( request ) */
9029 add_cip_service_to_info_column(pinfo, service, cip_sc_vals_mb);
9030 } /* End of dissect_cip_mb_data() */
9032 static int
9033 dissect_cip_class_mb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
9035 proto_item *ti;
9036 proto_tree *class_tree;
9038 /* Create display subtree for the protocol */
9039 ti = proto_tree_add_item(tree, proto_cip_class_mb, tvb, 0, -1, ENC_NA);
9040 class_tree = proto_item_add_subtree( ti, ett_cip_class_mb );
9042 dissect_cip_mb_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
9044 return tvb_reported_length(tvb);
9047 /************************************************
9049 * Dissector for CIP Connection Configuration Object
9051 ************************************************/
9052 static int
9053 dissect_cip_cco_all_attribute_common( proto_tree *cmd_tree, proto_item *ti,
9054 tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo)
9056 proto_item *pi;
9057 proto_tree *tdi_tree, *iomap_tree, *epath_tree;
9058 proto_tree *ncp_tree;
9059 int conn_path_size, variable_data_size = 0, config_data_size;
9060 int iomap_size, ot_rtf, to_rtf;
9061 int temp_data;
9063 /* Connection flags */
9064 temp_data = tvb_get_letohs( tvb, offset);
9065 ot_rtf = (temp_data >> 1) & 7;
9066 to_rtf = (temp_data >> 4) & 7;
9068 static int *const connection_flags[] = {
9069 &hf_cip_cco_con_type,
9070 &hf_cip_cco_ot_rtf,
9071 &hf_cip_cco_to_rtf,
9072 NULL
9074 proto_tree_add_bitmask(cmd_tree, tvb, offset, hf_cip_cco_con_flags, ett_cco_con_flag, connection_flags, ENC_LITTLE_ENDIAN);
9076 /* Target device id */
9077 tdi_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+2, 10, ett_cco_tdi, NULL, "Target Device ID");
9079 dissect_deviceid(tvb, offset+2, tdi_tree,
9080 hf_cip_cco_tdi_vendor, hf_cip_cco_tdi_devtype, hf_cip_cco_tdi_prodcode,
9081 hf_cip_cco_tdi_compatibility, hf_cip_cco_tdi_comp_bit, hf_cip_cco_tdi_majorrev, hf_cip_cco_tdi_minorrev, false, ENC_LITTLE_ENDIAN);
9083 /* CS Data Index Number */
9084 proto_tree_add_item(cmd_tree, hf_cip_cco_cs_data_index, tvb, offset+10, 4, ENC_LITTLE_ENDIAN );
9086 /* Net Connection Parameters */
9087 ncp_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+14, 14, ett_cco_ncp, NULL, "Net Connection Parameters");
9089 /* Timeout multiplier */
9090 proto_tree_add_item(ncp_tree, hf_cip_cco_timeout_multiplier, tvb, offset+14, 1, ENC_LITTLE_ENDIAN );
9092 dissect_transport_type_trigger(tvb, offset+15, ncp_tree, hf_cip_cco_transport_type_trigger,
9093 hf_cip_cco_fwo_dir, hf_cip_cco_fwo_trigger, hf_cip_cco_fwo_class, ett_cco_ttt);
9095 proto_tree_add_item(ncp_tree, hf_cip_cco_ot_rpi, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN);
9097 /* Display O->T network connection parameters */
9098 cip_connID_info_t ignore;
9099 dissect_net_param16(tvb, offset+20, ncp_tree,
9100 hf_cip_cco_ot_net_param16, hf_cip_cco_fwo_own, hf_cip_cco_fwo_typ,
9101 hf_cip_cco_fwo_prio, hf_cip_cco_fwo_fixed_var, hf_cip_cco_fwo_con_size, ett_cco_ncp, &ignore);
9103 proto_tree_add_item(ncp_tree, hf_cip_cco_to_rpi, tvb, offset + 22, 4, ENC_LITTLE_ENDIAN);
9105 /* Display T->O network connection parameters */
9106 dissect_net_param16(tvb, offset+26, ncp_tree,
9107 hf_cip_cco_to_net_param16, hf_cip_cco_fwo_own, hf_cip_cco_fwo_typ,
9108 hf_cip_cco_fwo_prio, hf_cip_cco_fwo_fixed_var, hf_cip_cco_fwo_con_size, ett_cco_ncp, &ignore);
9110 /* Connection Path */
9111 conn_path_size = tvb_get_uint8( tvb, offset+28 )*2;
9112 proto_tree_add_item(cmd_tree, hf_cip_cco_conn_path_size, tvb, offset+28, 1, ENC_LITTLE_ENDIAN);
9114 /* Display the Reserved byte */
9115 proto_tree_add_item(cmd_tree, hf_cip_reserved8, tvb, offset+29, 1, ENC_LITTLE_ENDIAN );
9117 /* Add the epath */
9118 epath_tree = proto_tree_add_subtree(cmd_tree, tvb, offset+30, conn_path_size, ett_path, &pi, "Connection Path: ");
9119 dissect_epath(tvb, pinfo, epath_tree, pi, offset+30, conn_path_size, false, false, NULL, NULL, NO_DISPLAY, NULL, false);
9121 variable_data_size += (conn_path_size+30);
9123 /* Config #1 Data */
9124 config_data_size = tvb_get_letohs( tvb, offset+variable_data_size);
9125 proto_tree_add_item(cmd_tree, hf_cip_cco_proxy_config_size, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
9126 if (config_data_size > 0)
9127 proto_tree_add_item(cmd_tree, hf_cip_cco_proxy_config_data, tvb, offset+variable_data_size+2, config_data_size, ENC_NA);
9129 variable_data_size += (config_data_size+2);
9131 /* Config #2 Data */
9132 config_data_size = tvb_get_letohs( tvb, offset+variable_data_size);
9133 proto_tree_add_item(cmd_tree, hf_cip_cco_target_config_size, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
9134 if (config_data_size > 0)
9135 proto_tree_add_item(cmd_tree, hf_cip_cco_target_config_data, tvb, offset+variable_data_size+2, config_data_size, ENC_NA);
9137 variable_data_size += (config_data_size+2);
9139 /* Connection Name */
9140 variable_data_size += dissect_cip_string_type(pinfo, cmd_tree, ti, tvb, offset + variable_data_size, hf_cip_cco_connection_name, CIP_STRING2_TYPE);
9142 /* I/O Mapping */
9143 iomap_size = tvb_get_letohs( tvb, offset+variable_data_size+2);
9145 iomap_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, iomap_size+4, ett_cco_iomap, NULL, "I/O Mapping");
9147 proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_format_number, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
9148 proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_size, tvb, offset+variable_data_size+2, 2, ENC_LITTLE_ENDIAN);
9150 /* Attribute data */
9151 if (iomap_size > 0)
9152 proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_attribute, tvb, offset+variable_data_size+4, iomap_size, ENC_NA);
9154 variable_data_size += (iomap_size+4);
9156 /* Proxy device id */
9157 tdi_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, 8, ett_cco_pdi, NULL, "Proxy Device ID");
9159 dissect_deviceid(tvb, offset+variable_data_size, tdi_tree,
9160 hf_cip_cco_pdi_vendor, hf_cip_cco_pdi_devtype, hf_cip_cco_pdi_prodcode,
9161 hf_cip_cco_pdi_compatibility, hf_cip_cco_pdi_comp_bit, hf_cip_cco_pdi_majorrev, hf_cip_cco_pdi_minorrev, false, ENC_LITTLE_ENDIAN);
9163 /* Add in proxy device id size */
9164 variable_data_size += 8;
9166 if ((offset+variable_data_size < item_length) &&
9167 ((ot_rtf == 5) || (to_rtf == 5)))
9169 /* Safety parameters */
9170 proto_tree_add_item(cmd_tree, hf_cip_cco_safety, tvb, offset+variable_data_size, 55, ENC_NA);
9171 variable_data_size += 55;
9174 if (offset+variable_data_size < item_length)
9176 proto_tree_add_item(cmd_tree, hf_cip_cco_connection_disable, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
9177 variable_data_size++;
9180 if (offset+variable_data_size < item_length)
9182 proto_tree_add_item(cmd_tree, hf_cip_cco_net_conn_param_attr, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
9183 variable_data_size++;
9186 if (offset+variable_data_size < item_length)
9188 /* Large Net Connection Parameter */
9189 ncp_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, 18, ett_cco_ncp, NULL, "Large Net Connection Parameters");
9191 proto_tree_add_item(ncp_tree, hf_cip_cco_timeout_multiplier, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
9192 dissect_transport_type_trigger(tvb, offset+variable_data_size+1, ncp_tree, hf_cip_cco_transport_type_trigger,
9193 hf_cip_cco_fwo_dir, hf_cip_cco_fwo_trigger, hf_cip_cco_fwo_class, ett_cco_ttt);
9195 proto_tree_add_item(ncp_tree, hf_cip_cco_ot_rpi, tvb, offset + variable_data_size + 2, 4, ENC_LITTLE_ENDIAN);
9197 /* Display O->T network connection parameters */
9198 dissect_net_param32(tvb, offset+variable_data_size+6, ncp_tree,
9199 hf_cip_cco_ot_net_param32, hf_cip_cco_lfwo_own, hf_cip_cco_lfwo_typ,
9200 hf_cip_cco_lfwo_prio, hf_cip_cco_lfwo_fixed_var, hf_cip_cco_lfwo_con_size, ett_cco_ncp, &ignore);
9202 proto_tree_add_item(ncp_tree, hf_cip_cco_to_rpi, tvb, offset + variable_data_size + 10, 4, ENC_LITTLE_ENDIAN);
9204 /* Display T->O network connection parameters */
9205 dissect_net_param32(tvb, offset+variable_data_size+14, ncp_tree,
9206 hf_cip_cco_to_net_param32, hf_cip_cco_lfwo_own, hf_cip_cco_lfwo_typ,
9207 hf_cip_cco_lfwo_prio, hf_cip_cco_lfwo_fixed_var, hf_cip_cco_lfwo_con_size, ett_cco_ncp, &ignore);
9209 variable_data_size += 18;
9212 return variable_data_size;
9215 static void
9216 dissect_cip_cco_data( proto_tree *item_tree, proto_item *ti, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
9218 proto_item *rrsc_item;
9219 proto_tree *rrsc_tree, *cmd_data_tree, *con_st_tree;
9220 int req_path_size;
9221 uint8_t service, gen_status, add_stat_size;
9222 cip_simple_request_info_t req_data;
9224 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP CCO");
9226 /* Add Service code & Request/Response tree */
9227 service = tvb_get_uint8( tvb, offset );
9228 rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_cco_rrsc, &rrsc_item, "Service: " );
9230 /* Add Request/Response */
9231 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
9233 proto_item_append_text( rrsc_item, "%s (%s)",
9234 val_to_str( ( service & CIP_SC_MASK ),
9235 cip_sc_vals_cco , "Unknown Service (0x%02x)"),
9236 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
9237 cip_sc_rr, "") );
9239 /* Add Service code */
9240 proto_tree_add_item(rrsc_tree, hf_cip_cco_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
9242 load_cip_request_data(pinfo, &req_data);
9244 if(service & CIP_SC_RESPONSE_MASK )
9246 /* Response message */
9248 /* Add additional status size */
9249 gen_status = tvb_get_uint8( tvb, offset+2 );
9250 add_stat_size = tvb_get_uint8( tvb, offset+3 ) * 2;
9252 /* If there is any command specific data create a sub-tree for it */
9253 if( ( item_length-4-add_stat_size ) != 0 )
9255 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
9256 ett_cco_cmd_data, NULL, "Command Specific Data" );
9258 if( gen_status == CI_GRC_SUCCESS )
9260 /* Success responses */
9261 if (((service & CIP_SC_MASK) == SC_GET_ATT_ALL) &&
9262 (req_data.iInstance != SEGMENT_VALUE_NOT_SET))
9264 if (req_data.iInstance == 0)
9266 /* Get Attribute All (class) request */
9267 dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset + 4 + add_stat_size, &req_data);
9269 else
9271 /* Get Attribute All (instance) request */
9273 /* Connection status */
9274 con_st_tree = proto_tree_add_subtree( cmd_data_tree, tvb, offset+4+add_stat_size, 4, ett_cco_con_status, NULL, "Connection Status");
9276 proto_tree_add_item(con_st_tree, hf_cip_genstat, tvb, offset+4+add_stat_size, 1, ENC_LITTLE_ENDIAN );
9277 proto_tree_add_item(con_st_tree, hf_cip_pad8, tvb, offset+4+add_stat_size+1, 1, ENC_LITTLE_ENDIAN);
9279 /* Extended Status */
9280 proto_tree_add_item(con_st_tree, hf_cip_cco_ext_status, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
9282 dissect_cip_cco_all_attribute_common(cmd_data_tree, ti, tvb, offset+4+add_stat_size+4, item_length, pinfo);
9285 else
9287 /* Add data */
9288 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
9291 else
9293 /* Error responses */
9295 /* Add data */
9296 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
9297 } /* end of if-else( CI_CRC_SUCCESS ) */
9299 } /* End of if command-specific data present */
9301 } /* End of if reply */
9302 else
9304 /* Request message */
9305 req_path_size = tvb_get_uint8( tvb, offset+1 )*2;
9307 /* If there is any command specific data create a sub-tree for it */
9308 if( (item_length-req_path_size-2) != 0 )
9311 cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
9312 ett_cco_cmd_data, NULL, "Command Specific Data" );
9314 /* Check what service code that received */
9316 switch (service)
9318 case SC_CCO_AUDIT_CHANGE:
9319 proto_tree_add_item(cmd_data_tree, hf_cip_cco_change_type, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN );
9320 break;
9321 case SC_CCO_CHANGE_COMPLETE:
9322 proto_tree_add_item(cmd_data_tree, hf_cip_cco_change_type, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN );
9323 break;
9324 case SC_SET_ATT_ALL:
9325 if ((req_data.iInstance == 0) ||
9326 (req_data.iInstance == SEGMENT_VALUE_NOT_SET))
9328 /* Just add raw data */
9329 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
9330 break;
9333 /* Set Attribute All (instance) request */
9334 dissect_cip_cco_all_attribute_common(cmd_data_tree, ti, tvb, offset+2+req_path_size, item_length, pinfo);
9335 break;
9336 default:
9338 /* Add data */
9339 proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
9340 } /* End of check service code */
9342 } /* End of if command-specific data present */
9344 } /* End of if-else( request ) */
9346 add_cip_service_to_info_column(pinfo, service, cip_sc_vals_cco);
9347 } /* End of dissect_cip_cco_data() */
9349 static int
9350 dissect_cip_class_cco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
9352 proto_item *ti;
9353 proto_tree *class_tree;
9355 /* Create display subtree for the protocol */
9356 ti = proto_tree_add_item(tree, proto_cip_class_cco, tvb, 0, -1, ENC_NA);
9357 class_tree = proto_item_add_subtree( ti, ett_cip_class_cco );
9359 dissect_cip_cco_data( class_tree, ti, tvb, 0, tvb_reported_length(tvb), pinfo );
9361 return tvb_reported_length(tvb);
9364 static bool
9365 dissect_class_cco_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
9367 unsigned char service, service_code, ioilen, segment;
9368 cip_req_info_t* preq_info;
9369 uint32_t classid = 0;
9370 int offset = 0;
9372 service = tvb_get_uint8( tvb, offset );
9373 service_code = service & CIP_SC_MASK;
9375 /* Handle GetAttributeAll and SetAttributeAll in CCO class */
9376 if ((service_code == SC_GET_ATT_ALL) ||
9377 (service_code == SC_SET_ATT_ALL))
9379 if (service & CIP_SC_RESPONSE_MASK)
9381 /* Service response */
9382 preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
9383 if ((preq_info != NULL) &&
9384 (preq_info->dissector == dissector_get_uint_handle( subdissector_class_table, CI_CLS_CCO)))
9386 call_dissector(preq_info->dissector, tvb, pinfo, tree);
9387 return true;
9390 else
9392 /* Service request */
9393 ioilen = tvb_get_uint8( tvb, offset + 1 );
9394 if (ioilen > 1)
9396 segment = tvb_get_uint8( tvb, offset + 2 );
9397 if (((segment & CI_SEGMENT_TYPE_MASK) == CI_LOGICAL_SEGMENT) &&
9398 ((segment & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_CLASS_ID))
9400 /* Logical Class ID, do a format check */
9401 switch ( segment & CI_LOGICAL_SEG_FORMAT_MASK )
9403 case CI_LOGICAL_SEG_8_BIT:
9404 classid = tvb_get_uint8( tvb, offset + 3 );
9405 break;
9406 case CI_LOGICAL_SEG_16_BIT:
9407 if ( ioilen >= 2 )
9408 classid = tvb_get_letohs( tvb, offset + 4 );
9409 break;
9410 case CI_LOGICAL_SEG_32_BIT:
9411 if ( ioilen >= 3 )
9412 classid = tvb_get_letohl( tvb, offset + 4 );
9413 break;
9418 if (classid == CI_CLS_CCO)
9420 call_dissector(cip_class_cco_handle, tvb, pinfo, tree );
9421 return true;
9427 return false;
9430 /************************************************
9432 * Dissector for CIP Request/Response
9433 * - matches requests/responses
9434 * - calls class specific dissector
9436 ************************************************/
9438 // NOLINTNEXTLINE(misc-no-recursion)
9439 void dissect_cip_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, packet_info *pinfo, cip_req_info_t* preq_info, proto_item* msp_item, bool is_msp_item )
9441 proto_item *ti;
9442 proto_tree *cip_tree, *epath_tree;
9443 proto_item *pi, *rrsc_item, *status_item;
9444 proto_tree *rrsc_tree, *status_tree, *add_status_tree;
9445 int req_path_size;
9446 unsigned char i, gen_status;
9447 unsigned char service,ioilen,segment;
9448 void *p_save_proto_data;
9449 cip_simple_request_info_t path_info;
9450 dissector_handle_t dissector;
9451 int service_index;
9452 heur_dtbl_entry_t *hdtbl_entry;
9454 p_save_proto_data = p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
9455 p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
9456 p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, preq_info);
9458 /* Create display subtree for the protocol */
9459 ti = proto_tree_add_item(item_tree, proto_cip, tvb, 0, -1, ENC_NA);
9460 cip_tree = proto_item_add_subtree( ti, ett_cip );
9462 service = tvb_get_uint8( tvb, offset );
9464 /* Add Service code & Request/Response tree */
9465 rrsc_item = proto_tree_add_uint_format_value(cip_tree, hf_cip_service,
9466 tvb, offset, 1, service, "%s (%s)",
9467 val_to_str( ( service & CIP_SC_MASK ), cip_sc_vals , "Unknown Service (0x%02x)"),
9468 val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7, cip_sc_rr, ""));
9470 rrsc_tree = proto_item_add_subtree( rrsc_item, ett_rrsc );
9472 proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN);
9473 proto_tree_add_item(rrsc_tree, hf_cip_service_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
9475 increment_dissection_depth(pinfo);
9476 if( service & CIP_SC_RESPONSE_MASK )
9478 /* Response message */
9479 status_tree = proto_tree_add_subtree( cip_tree, tvb, offset+2, 1, ett_status_item, &status_item, "Status: " );
9481 /* Add general status */
9482 gen_status = tvb_get_uint8( tvb, offset+2 );
9483 proto_tree_add_item(status_tree, hf_cip_genstat, tvb, offset+2, 1, ENC_LITTLE_ENDIAN );
9484 proto_item_append_text( status_item, "%s: ", val_to_str_ext( gen_status,
9485 &cip_gs_vals_ext , "Unknown Response (%x)") );
9487 if (is_msp_item == false)
9489 /* Add reply status to info column */
9490 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: ",
9491 val_to_str_ext(gen_status, &cip_gs_vals_ext, "Unknown Response (%x)"));
9493 else
9495 proto_item_append_text(msp_item, "%s: ",
9496 val_to_str_ext(gen_status, &cip_gs_vals_ext, "Unknown Response (%x)"));
9499 /* Add additional status size */
9500 uint8_t add_stat_size = tvb_get_uint8( tvb, offset+3 );
9501 proto_tree_add_item(status_tree, hf_cip_addstat_size, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
9503 if( add_stat_size )
9505 /* Add additional status */
9506 add_status_tree = proto_tree_add_subtree( status_tree, tvb, offset+4, add_stat_size*2, ett_add_status_item, NULL, "Additional Status" );
9508 for( i=0; i < add_stat_size; i ++ )
9509 proto_tree_add_item(add_status_tree, hf_cip_add_stat, tvb, offset+4+(i*2), 2, ENC_LITTLE_ENDIAN );
9512 proto_item_set_len( status_item, 2 + add_stat_size*2);
9514 /* The previous packet service must be Unconnected Send, or match the current
9515 service to be a valid match. If they don't, ignore the previous data.*/
9516 if( preq_info
9517 && !( preq_info->bService == ( service & CIP_SC_MASK )
9518 || ( preq_info->bService == SC_CM_UNCON_SEND && preq_info->dissector == cip_class_cm_handle )
9521 preq_info = NULL;
9523 display_previous_request_path(preq_info, cip_tree, tvb, pinfo, msp_item, is_msp_item);
9525 /* Check to see if service is 'generic' */
9526 try_val_to_str_idx((service & CIP_SC_MASK), cip_sc_vals, &service_index);
9528 cip_service_info_t* service_entry = cip_get_service(pinfo, service);
9530 /* If the request set a dissector, then check that first. This ensures
9531 that Unconnected Send responses are properly parsed based on the
9532 embedded request. */
9533 if (preq_info && preq_info->dissector)
9535 call_dissector(preq_info->dissector, tvb, pinfo, item_tree);
9537 else if (service_index >= 0 && !service_entry)
9539 /* See if object dissector wants to override generic service handling */
9540 if(!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
9542 dissect_cip_generic_service_rsp(tvb, pinfo, cip_tree);
9545 else if (service_entry)
9547 dissect_cip_object_specific_service(tvb, pinfo, cip_tree, msp_item, service_entry);
9549 else
9551 call_dissector( cip_class_generic_handle, tvb, pinfo, item_tree );
9553 } /* End of if reply */
9554 else
9556 /* Request message */
9558 /* Add path size to tree */
9559 req_path_size = tvb_get_uint8( tvb, offset+1);
9560 proto_tree_add_item(cip_tree, hf_cip_request_path_size, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
9562 /* Add the epath */
9563 epath_tree = proto_tree_add_subtree(cip_tree, tvb, offset+2, req_path_size*2, ett_path, &pi, "Request Path: ");
9564 if (preq_info)
9566 preq_info->ciaData = wmem_new(wmem_file_scope(), cip_simple_request_info_t);
9567 dissect_epath(tvb, pinfo, epath_tree, pi, offset+2, req_path_size*2, false, false, preq_info->ciaData, NULL, DISPLAY_REQUEST_PATH, msp_item, is_msp_item);
9568 memcpy(&path_info, preq_info->ciaData, sizeof(cip_simple_request_info_t));
9570 else
9572 dissect_epath(tvb, pinfo, epath_tree, pi, offset+2, req_path_size*2, false, false, &path_info, NULL, DISPLAY_REQUEST_PATH, msp_item, is_msp_item);
9575 ioilen = tvb_get_uint8( tvb, offset + 1 );
9577 if ( preq_info )
9578 preq_info->dissector = NULL;
9579 dissector = NULL;
9581 /* The class ID should already be extracted if it's available */
9582 if (path_info.iClass != 0xFFFFFFFF)
9584 dissector = dissector_get_uint_handle( subdissector_class_table, path_info.iClass);
9586 else
9588 if ( ioilen >= 1 )
9590 segment = tvb_get_uint8( tvb, offset + 2 );
9591 if ((segment & CI_SEGMENT_TYPE_MASK) == CI_DATA_SEGMENT)
9593 dissector = dissector_get_uint_handle( subdissector_symbol_table, segment );
9598 if ( preq_info )
9600 preq_info->dissector = dissector;
9602 /* copy IOI for access by response packet */
9603 preq_info->pIOI = wmem_alloc(wmem_file_scope(), ioilen*2);
9604 preq_info->IOILen = ioilen;
9605 tvb_memcpy(tvb, preq_info->pIOI, offset+2, ioilen*2);
9607 preq_info->bService = service;
9610 /* Check to see if service is 'generic' */
9611 try_val_to_str_idx(service, cip_sc_vals, &service_index);
9613 cip_service_info_t* service_entry = cip_get_service(pinfo, service);
9614 if (service_index >= 0 && !service_entry)
9616 /* See if object dissector wants to override generic service handling */
9617 if(!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
9619 /* No need to set a custom dissector if this is just a generic service. */
9620 if (preq_info)
9622 preq_info->dissector = NULL;
9625 dissect_cip_generic_service_req(tvb, pinfo, cip_tree, &path_info);
9628 else if ( dissector )
9630 call_dissector( dissector, tvb, pinfo, item_tree );
9632 else if (service_entry)
9634 dissect_cip_object_specific_service(tvb, pinfo, cip_tree, msp_item, service_entry);
9636 else
9638 call_dissector( cip_class_generic_handle, tvb, pinfo, item_tree );
9640 } /* End of if-else( request ) */
9642 decrement_dissection_depth(pinfo);
9644 p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
9645 p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, p_save_proto_data);
9647 } /* End of dissect_cip_data() */
9649 void dissect_cip_run_idle(tvbuff_t* tvb, int offset, proto_tree* item_tree)
9651 static int * const run_idle_header[] = {
9652 &hf_32bitheader_roo,
9653 &hf_32bitheader_coo,
9654 &hf_32bitheader_run_idle,
9655 NULL
9658 proto_tree_add_bitmask(item_tree, tvb, offset, hf_32bitheader, ett_32bitheader_tree, run_idle_header, ENC_LITTLE_ENDIAN);
9661 static int
9662 dissect_cip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
9664 enip_request_info_t *enip_info;
9665 cip_req_info_t *preq_info;
9667 /* Make entries in Protocol column and Info column on summary display */
9668 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP");
9670 col_clear(pinfo->cinfo, COL_INFO);
9671 col_append_sep_str(pinfo->cinfo, COL_INFO, " | ", "");
9673 /* Each CIP request received by ENIP gets a unique ID */
9674 enip_info = (enip_request_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
9676 if ( enip_info )
9678 preq_info = enip_info->cip_info;
9679 if ( preq_info == NULL )
9681 preq_info = wmem_new0(wmem_file_scope(), cip_req_info_t);
9682 enip_info->cip_info = preq_info;
9684 dissect_cip_data( tree, tvb, 0, pinfo, enip_info->cip_info, NULL, false );
9686 else
9688 dissect_cip_data( tree, tvb, 0, pinfo, NULL, NULL, false );
9691 return tvb_reported_length(tvb);
9694 static int
9695 dissect_cip_implicit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
9697 proto_item *ti;
9698 proto_tree *cip_tree;
9700 uint32_t ClassID = GPOINTER_TO_UINT(data);
9701 int length = tvb_reported_length_remaining(tvb, 0);
9703 /* Make entries in Protocol column and Info column on summary display */
9704 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP");
9705 col_clear(pinfo->cinfo, COL_INFO);
9707 /* Create display subtree for the protocol */
9708 ti = proto_tree_add_item(tree, proto_cip, tvb, 0, length, ENC_NA);
9709 cip_tree = proto_item_add_subtree(ti, ett_cip);
9711 proto_tree_add_item(cip_tree, hf_cip_data, tvb, 0, length, ENC_NA);
9713 col_append_fstr(pinfo->cinfo, COL_INFO, "Implicit Data - %s",
9714 val_to_str(ClassID, cip_class_names_vals, "Class (0x%02x)"));
9716 return tvb_reported_length(tvb);
9720 * Protocol initialization
9723 void
9724 proto_register_cip(void)
9726 /* Setup list of header fields */
9727 static hf_register_info hf[] = {
9728 { &hf_attr_class_revision, { "Revision", "cip.class_revision", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9729 { &hf_attr_class_max_instance, { "Max Instance", "cip.max_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9730 { &hf_attr_class_num_instance, { "Number of Instances", "cip.num_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9731 { &hf_attr_class_opt_attr_num, { "Number of Attributes", "cip.num_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9732 { &hf_attr_class_attr_num, { "Attribute Number", "cip.attr_num", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9733 { &hf_attr_class_opt_service_num, { "Number of Services", "cip.num_service", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9734 { &hf_attr_class_service_code, { "Service Code", "cip.service_code", FT_UINT16, BASE_HEX, VALS(cip_sc_vals), 0, NULL, HFILL } },
9735 { &hf_attr_class_num_class_attr, { "Maximum ID Number Class Attributes", "cip.num_class_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9736 { &hf_attr_class_num_inst_attr, { "Maximum ID Number Instance Attributes", "cip.num_inst_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9738 { &hf_cip_service, { "Service", "cip.service", FT_UINT8, BASE_HEX, NULL, 0, "Service Code + Request/Response", HFILL }},
9739 { &hf_cip_reqrsp, { "Request/Response", "cip.rr", FT_UINT8, BASE_HEX, VALS(cip_sc_rr), CIP_SC_RESPONSE_MASK, "Request or Response message", HFILL }},
9740 { &hf_cip_service_code, { "Service", "cip.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals), CIP_SC_MASK, "Service Code", HFILL }},
9741 { &hf_cip_epath, { "EPath", "cip.epath", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9742 { &hf_cip_genstat, { "General Status", "cip.genstat", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
9743 { &hf_cip_addstat_size, { "Additional Status Size", "cip.addstat_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
9744 { &hf_cip_add_stat, { "Additional Status", "cip.addstat", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9745 { &hf_cip_request_path_size, { "Request Path Size", "cip.request_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
9747 { &hf_cip_path_segment, { "Path Segment", "cip.path_segment", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9748 { &hf_cip_path_segment_type, { "Path Segment Type", "cip.path_segment.type", FT_UINT8, BASE_DEC, VALS(cip_path_seg_vals), CI_SEGMENT_TYPE_MASK, NULL, HFILL }},
9749 { &hf_cip_port_ex_link_addr, { "Extended Link Address", "cip.ex_linkaddress", FT_BOOLEAN, 8, NULL, CI_PORT_SEG_EX_LINK_ADDRESS, NULL, HFILL }},
9750 { &hf_cip_port, { "Port", "cip.port", FT_UINT8, BASE_DEC, VALS(cip_port_number_vals), CI_PORT_SEG_PORT_ID_MASK, "Port Identifier", HFILL } },
9751 { &hf_cip_port_extended,{ "Port Extended", "cip.port", FT_UINT16, BASE_HEX, NULL, 0, "Port Identifier Extended", HFILL } },
9752 { &hf_cip_link_address_byte, { "Link Address", "cip.linkaddress.byte", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9753 { &hf_cip_link_address_size, { "Link Address Size", "cip.linkaddress_size", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9754 { &hf_cip_link_address_string, { "Link Address", "cip.linkaddress.string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9755 { &hf_cip_logical_seg_type, { "Logical Segment Type", "cip.logical_segment.type", FT_UINT8, BASE_DEC, VALS(cip_logical_segment_type_vals), CI_LOGICAL_SEG_TYPE_MASK, NULL, HFILL }},
9756 { &hf_cip_logical_seg_format, { "Logical Segment Format", "cip.logical_segment.format", FT_UINT8, BASE_DEC, VALS(cip_logical_segment_format_vals), CI_LOGICAL_SEG_FORMAT_MASK, NULL, HFILL }},
9757 { &hf_cip_class8, { "Class", "cip.class", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
9758 { &hf_cip_class16, { "Class", "cip.class", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
9759 { &hf_cip_class32, { "Class", "cip.class", FT_UINT32, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
9760 { &hf_cip_instance8, { "Instance", "cip.instance", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9761 { &hf_cip_instance16, { "Instance", "cip.instance", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9762 { &hf_cip_instance32, { "Instance", "cip.instance", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9763 { &hf_cip_member8, { "Member", "cip.member", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9764 { &hf_cip_member16, { "Member", "cip.member", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9765 { &hf_cip_member32, { "Member", "cip.member", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9766 { &hf_cip_attribute8, { "Attribute", "cip.attribute", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9767 { &hf_cip_attribute16, { "Attribute", "cip.attribute", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9768 { &hf_cip_attribute32, { "Attribute", "cip.attribute", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9769 { &hf_cip_conpoint8, { "Connection Point", "cip.connpoint", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9770 { &hf_cip_conpoint16, { "Connection Point", "cip.connpoint", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9771 { &hf_cip_conpoint32, { "Connection Point", "cip.connpoint", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9772 { &hf_cip_serviceid8,{ "Service ID", "cip.serviceid", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
9773 { &hf_cip_ekey_format, { "Key Format", "cip.ekey.format", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9774 { &hf_cip_ekey_vendor, { "Vendor ID", "cip.ekey.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
9775 { &hf_cip_ekey_devtype, { "Device Type", "cip.ekey.devtype", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
9776 { &hf_cip_ekey_prodcode, { "Product Code", "cip.ekey.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9777 { &hf_cip_ekey_compatibility, { "Compatibility", "cip.ekey.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9778 { &hf_cip_ekey_comp_bit, { "Compatibility", "cip.ekey.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, "EKey: Compatibility bit", HFILL }},
9779 { &hf_cip_ekey_majorrev, { "Major Revision", "cip.ekey.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, "EKey: Major Revision", HFILL }},
9780 { &hf_cip_ekey_minorrev, { "Minor Revision", "cip.ekey.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9781 { &hf_cip_ekey_serial_number, { "Serial Number", "cip.ekey.serial_number", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9782 { &hf_cip_ext_logical8,{ "Extended Logical", "cip.extlogical", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
9783 { &hf_cip_ext_logical16,{ "Extended Logical", "cip.extlogical", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
9784 { &hf_cip_ext_logical32,{ "Extended Logical", "cip.extlogical", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
9785 { &hf_cip_ext_logical_type,{ "Extended Logical Type", "cip.extlogical.type", FT_UINT8, BASE_HEX, VALS(cip_ext_logical_segment_format_vals), 0, NULL, HFILL } },
9786 { &hf_cip_data_seg_type, { "Data Segment Type", "cip.data_segment.type", FT_UINT8, BASE_DEC, VALS(cip_data_segment_type_vals), CI_DATA_SEG_TYPE_MASK, NULL, HFILL }},
9787 { &hf_cip_data_seg_size_simple, { "Data Size", "cip.data_segment.size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
9788 { &hf_cip_data_seg_size_extended, { "Data Size", "cip.data_segment.size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0, NULL, HFILL } },
9789 { &hf_cip_data_seg_item, { "Data", "cip.data_segment.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9790 { &hf_cip_symbol, { "ANSI Symbol", "cip.symbol", FT_STRING, BASE_NONE, NULL, 0, "ANSI Extended Symbol Segment", HFILL }},
9791 { &hf_cip_symbol_size, { "Symbolic Symbol Size", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
9792 { &hf_cip_symbol_ascii, { "ASCII Symbol", "cip.ascii_symbol", FT_STRING, BASE_NONE, NULL, 0, "ASCII Symbol Segment", HFILL } },
9793 { &hf_cip_symbol_extended_format,{ "Extended String Format", "cip.symbol.format", FT_UINT8, BASE_DEC, VALS(cip_symbolic_format_vals), CI_SYMBOL_SEG_FORMAT_MASK, NULL, HFILL } },
9794 { &hf_cip_symbol_numeric_format,{ "Extended String Numeric Format", "cip.symbol.numformat", FT_UINT8, BASE_DEC, VALS(cip_symbolic_numeric_format_vals), 0x1F, NULL, HFILL } },
9795 { &hf_cip_symbol_double_size, { "Double Byte Chars", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
9796 { &hf_cip_symbol_triple_size, { "Triple Byte Chars", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
9797 { &hf_cip_numeric_usint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
9798 { &hf_cip_numeric_uint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
9799 { &hf_cip_numeric_udint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
9800 { &hf_cip_network_seg_type, { "Network Segment Type", "cip.network_segment.type", FT_UINT8, BASE_DEC, VALS(cip_network_segment_type_vals), CI_NETWORK_SEG_TYPE_MASK, NULL, HFILL }},
9801 { &hf_cip_seg_schedule, { "Multiplier/Phase", "cip.network_segment.schedule", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9802 { &hf_cip_seg_fixed_tag, { "Fixed Tag", "cip.network_segment.fixed_tag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9803 { &hf_cip_seg_prod_inhibit_time, { "Production Inhibit Time (ms)", "cip.network_segment.prod_inhibit", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9804 { &hf_cip_seg_prod_inhibit_time_us, { "Production Inhibit Time (us)", "cip.network_segment.prod_inhibit", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
9805 { &hf_cip_seg_network_size, { "Network Segment Length", "cip.network_segment.length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
9806 { &hf_cip_seg_network_subtype, { "Extended Segment Subtype", "cip.network_segment.subtype", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
9807 { &hf_cip_seg_safety_format, { "Safety Format", "cip.safety_segment.format", FT_UINT8, BASE_DEC, VALS(cip_safety_segment_format_type_vals), 0, NULL, HFILL }},
9808 { &hf_cip_seg_safety_reserved, { "Reserved", "cip.safety_segment.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9809 { &hf_cip_seg_safety_configuration_crc, { "Configuration CRC (SCCRC)", "cip.safety_segment.configuration_crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9810 { &hf_cip_seg_safety_configuration_timestamp, { "Configuration Timestamp (SCTS)", "cip.safety_segment.configuration_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }},
9811 { &hf_cip_seg_safety_configuration_date, { "Configuration (Manual) Date", "cip.safety_segment.configuration_date", FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }},
9812 { &hf_cip_seg_safety_configuration_time, { "Configuration (Manual) Time", "cip.safety_segment.configuration_time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9813 { &hf_cip_seg_safety_time_correction_epi, { "Time Correction EPI", "cip.safety_segment.time_correction_epi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
9814 { &hf_cip_seg_safety_time_correction_net_params, { "Time Correction Network Connection Parameters", "cip.safety_segment.time_correction.net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9815 { &hf_cip_seg_safety_time_correction_own, { "Redundant Owner", "cip.safety_segment.time_correction.owner", FT_UINT16, BASE_DEC, VALS(cip_con_owner_vals), 0x8000, "Time Correction: Redundant owner bit", HFILL }},
9816 { &hf_cip_seg_safety_time_correction_typ, { "Connection Type", "cip.safety_segment.time_correction.type", FT_UINT16, BASE_DEC, VALS(cip_con_type_vals), 0x6000, "Time Correction: Connection type", HFILL }},
9817 { &hf_cip_seg_safety_time_correction_prio, { "Priority", "cip.safety_segment.time_correction.prio", FT_UINT16, BASE_DEC, VALS(cip_con_prio_vals), 0x0C00, "Time Correction: Connection priority", HFILL }},
9818 { &hf_cip_seg_safety_time_correction_fixed_var, { "Connection Size Type", "cip.safety_segment.time_correction.f_v", FT_UINT16, BASE_DEC, VALS(cip_con_fw_vals), 0x0200, "Time Correction: Fixed or variable connection size", HFILL }},
9819 { &hf_cip_seg_safety_time_correction_con_size, { "Connection Size", "cip.safety_segment.time_correction.consize", FT_UINT16, BASE_DEC, NULL, 0x01FF, "Time Correction: Connection size", HFILL }},
9820 { &hf_cip_seg_safety_tunid, { "Target UNID (TUNID)", "cip.safety_segment.tunid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9821 { &hf_cip_seg_safety_tunid_snn_timestamp, { "SNN Timestamp", "cip.safety_segment.tunid.snn.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }},
9822 { &hf_cip_seg_safety_tunid_snn_date, { "SNN (Manual) Date", "cip.safety_segment.tunid.snn.date", FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }},
9823 { &hf_cip_seg_safety_tunid_snn_time, { "SNN (Manual) Time", "cip.safety_segment.tunid.snn.time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9824 { &hf_cip_seg_safety_tunid_nodeid, { "Node ID", "cip.safety_segment.tunid.nodeid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9825 { &hf_cip_seg_safety_ounid, { "Originator UNID (OUNID)", "cip.safety_segment.ounid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9826 { &hf_cip_seg_safety_ounid_snn_timestamp, { "SNN Timestamp", "cip.safety_segment.ounid.snn.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }},
9827 { &hf_cip_seg_safety_ounid_snn_date, { "SNN (Manual) Date", "cip.safety_segment.ounid.snn.date", FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }},
9828 { &hf_cip_seg_safety_ounid_snn_time, { "SNN (Manual) Time", "cip.safety_segment.ounid.snn.time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9829 { &hf_cip_seg_safety_ounid_nodeid, { "Node ID", "cip.safety_segment.ounid.nodeid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9830 { &hf_cip_seg_safety_ping_epi_multiplier, { "Ping Interval EPI Multiplier", "cip.safety_segment.ping_epi_multiplier", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9831 { &hf_cip_seg_safety_time_coord_msg_min_multiplier, { "Time Coord Msg Min Multiplier", "cip.safety_segment.time_coord_msg_min_multiplier", FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }},
9832 { &hf_cip_seg_safety_network_time_expected_multiplier, { "Network Time Expectation Multiplier", "cip.safety_segment.network_time_expected_multiplier", FT_UINT16, BASE_CUSTOM, CF_FUNC(cip_safety_128us_fmt), 0, NULL, HFILL }},
9833 { &hf_cip_seg_safety_timeout_multiplier, { "Timeout Multiplier", "cip.safety_segment.timeout_multiplier", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9834 { &hf_cip_seg_safety_max_consumer_number, { "Max Consumer Number", "cip.safety_segment.max_consumer_number", FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(safety_max_consumer_numbers), 0, NULL, HFILL }},
9835 { &hf_cip_seg_safety_conn_param_crc, { "Connection Parameters CRC (CPCRC)", "cip.safety_segment.conn_param_crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9836 { &hf_cip_seg_safety_time_correction_conn_id, { "Time Correction Connection ID", "cip.safety_segment.time_correction_conn_id", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9837 { &hf_cip_seg_safety_max_fault_number, { "Max Fault Number", "cip.safety_segment.max_fault_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9838 { &hf_cip_seg_safety_init_timestamp, { "Initial Timestamp", "cip.safety_segment.init_timestamp", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9839 { &hf_cip_seg_safety_init_rollover, { "Initial Rollover Value", "cip.safety_segment.init_rollover", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9840 { &hf_cip_seg_safety_data, { "Safety Data", "cip.safety_segment.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9841 { &hf_cip_class_max_inst32, { "Max Instance", "cip.class.max_inst", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9842 { &hf_cip_class_num_inst32, { "Number of Instances", "cip.class.num_inst", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9843 { &hf_cip_reserved8, { "Reserved", "cip.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9844 { &hf_cip_reserved24, { "Reserved", "cip.reserved", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL }},
9845 { &hf_cip_pad8, { "Pad Byte", "cip.pad", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9847 { &hf_cip_sc_get_attr_list_attr_count, { "Attribute Count", "cip.getlist.attr_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9848 { &hf_cip_sc_get_attr_list_attr_status, { "Attribute Status", "cip.getlist.attr_status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
9849 { &hf_cip_sc_set_attr_list_attr_count, { "Attribute Count", "cip.setlist.attr_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9850 { &hf_cip_sc_set_attr_list_attr_status, { "Attribute Status", "cip.setlist.attr_status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
9851 { &hf_cip_sc_reset_param, { "Reset type", "cip.reset.type", FT_UINT8, BASE_DEC, VALS(cip_reset_type_vals), 0, NULL, HFILL }},
9852 { &hf_cip_sc_create_instance, { "Instance", "cip.create.instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9853 { &hf_cip_sc_mult_serv_pack_num_services, { "Number of Services", "cip.msp.num_services", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9854 { &hf_cip_sc_mult_serv_pack_offset, { "Offset", "cip.msp.offset", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9855 { &hf_cip_find_next_object_max_instance, { "Maximum ID", "cip.find_next_object.max_instance", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9856 { &hf_cip_find_next_object_num_instances, { "Number of Instances", "cip.find_next_object.num_instances", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9857 { &hf_cip_find_next_object_instance_item, { "Instance", "cip.find_next_object.instance", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9858 { &hf_cip_sc_group_sync_is_sync, { "IsSynchronized", "cip.group_sync.is_sync", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9859 { &hf_cip_data, { "Data", "cip.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9861 { &hf_id_vendor_id, { "Vendor ID", "cip.id.vendor_id", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL } },
9862 { &hf_id_device_type, { "Device Type", "cip.id.device_type", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
9863 { &hf_id_product_code, { "Product Code", "cip.id.product_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9864 { &hf_id_major_rev, { "Major Revision", "cip.id.major_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9865 { &hf_id_minor_rev, { "Minor Revision", "cip.id.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9866 { &hf_id_status, { "Status", "cip.id.status", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9867 { &hf_id_serial_number, { "Serial Number", "cip.id.serial_number", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
9868 { &hf_id_product_name, { "Product Name", "cip.id.product_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9869 { &hf_id_state, { "State", "cip.id.state", FT_UINT8, BASE_HEX, VALS(cip_id_state_vals), 0, NULL, HFILL } },
9870 { &hf_id_config_value, { "Configuration Consistency Value", "cip.id.config_value", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
9871 { &hf_id_heartbeat, { "Heartbeat Interval", "cip.id.heartbeat", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
9872 { &hf_id_status_owned, { "Owned", "cip.id.owned", FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL } },
9873 { &hf_id_status_conf, { "Configured", "cip.id.conf", FT_UINT16, BASE_DEC, NULL, 0x0004, NULL, HFILL } },
9874 { &hf_id_status_extended1, { "Extended Device Status", "cip.id.ext", FT_UINT16, BASE_HEX, NULL, 0x00F0, NULL, HFILL } },
9875 { &hf_id_status_minor_fault_rec, { "Minor Recoverable Fault", "cip.id.minor_fault1", FT_UINT16, BASE_DEC, NULL, 0x0100, NULL, HFILL } },
9876 { &hf_id_status_minor_fault_unrec, { "Minor Unrecoverable Fault", "cip.id.minor_fault2", FT_UINT16, BASE_DEC, NULL, 0x0200, NULL, HFILL } },
9877 { &hf_id_status_major_fault_rec, { "Major Recoverable Fault", "cip.id.major_fault1", FT_UINT16, BASE_DEC, NULL, 0x0400, NULL, HFILL } },
9878 { &hf_id_status_major_fault_unrec, { "Major Unrecoverable Fault", "cip.id.major_fault2", FT_UINT16, BASE_DEC, NULL, 0x0800, NULL, HFILL } },
9879 { &hf_id_status_extended2, { "Extended Device Status 2", "cip.id.ext2", FT_UINT16, BASE_HEX, NULL, 0xF000, NULL, HFILL } },
9881 { &hf_msg_rout_num_classes, { "Number of Classes", "cip.mr.num_classes", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9882 { &hf_msg_rout_classes, { "Class", "cip.mr.class", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
9883 { &hf_msg_rout_num_available, { "Number Available", "cip.mr.num_available", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9884 { &hf_msg_rout_num_active, { "Number Active", "cip.mr.num_active", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9885 { &hf_msg_rout_active_connections, { "Active Connection", "cip.mr.active_connections", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9887 { &hf_conn_mgr_open_requests, { "Open Requests", "cip.cm.open_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9888 { &hf_conn_mgr_open_format_rejects, { "Open Format Rejects", "cip.cm.open_format_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9889 { &hf_conn_mgr_open_resource_rejects, { "Open Resource Rejects", "cip.cm.open_resource_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9890 { &hf_conn_mgr_other_open_rejects, { "Other Open Rejects", "cip.cm.other_open_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9891 { &hf_conn_mgr_close_requests, { "Close Requests", "cip.cm.close_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9892 { &hf_conn_close_format_requests, { "Close Format Requests", "cip.cm.close_format_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9893 { &hf_conn_mgr_close_other_requests, { "Close Other Requests", "cip.cm.close_other_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9894 { &hf_conn_mgr_conn_timouts, { "Connection Timeouts", "cip.cm.conn_timouts", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9895 { &hf_conn_mgr_num_conn_entries, { "Number of Connection Entries (Bits)", "cip.cm.conn_entries", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9896 { &hf_conn_mgr_num_conn_entries_bytes, { "Number of Connection Entries (Bytes)", "cip.cm.conn_entries_bytes", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9897 { &hf_conn_mgr_conn_open_bits, { "Connection Open Bits", "cip.cm.conn_open_bits", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9898 { &hf_conn_mgr_cpu_utilization, { "CPU Utilization", "cip.cm.cpu_util", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9899 { &hf_conn_mgr_max_buff_size, { "Max Buff Size", "cip.cm.max_buff_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
9900 { &hf_conn_mgr_buff_size_remaining, { "Buff Size Remaining", "cip.cm.buff_remain", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
9902 { &hf_stringi_number_char, { "Number of Characters", "cip.stringi.num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
9903 { &hf_stringi_language_char, { "Language Chars", "cip.stringi.language_char", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
9904 { &hf_stringi_char_string_struct, { "Char String Struct", "cip.stringi.char_string_struct", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
9905 { &hf_stringi_char_set, { "Char Set", "cip.stringi.char_set", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9906 { &hf_stringi_international_string, { "International String", "cip.stringi.int_string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
9908 { &hf_file_filename, { "File Name", "cip.file.file_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
9910 { &hf_time_sync_ptp_enable, { "PTP Enable", "cip.time_sync.ptp_enable", FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }},
9911 { &hf_time_sync_is_synchronized, { "Is Synchronized", "cip.time_sync.is_synchronized", FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
9912 { &hf_time_sync_sys_time_micro, { "System Time (Microseconds)", "cip.time_sync.sys_time_micro", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
9913 { &hf_time_sync_sys_time_nano, { "System Time (Nanoseconds)", "cip.time_sync.sys_time_nano", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
9914 { &hf_time_sync_offset_from_master, { "Offset from Master", "cip.time_sync.offset_from_master", FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL }},
9915 { &hf_time_sync_max_offset_from_master, { "Max Offset from Master", "cip.time_sync.max_offset_from_master", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }},
9916 { &hf_time_sync_mean_path_delay_to_master, { "Mean Path Delay To Master", "cip.time_sync.mean_path_delay_to_master", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }},
9917 { &hf_time_sync_gm_clock_clock_id, { "Clock Identity", "cip.time_sync.gm_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9918 { &hf_time_sync_gm_clock_clock_class, { "Clock Class", "cip.time_sync.gm_clock.clock_class", FT_UINT16, BASE_DEC, VALS(cip_time_sync_clock_class_vals), 0, NULL, HFILL }},
9919 { &hf_time_sync_gm_clock_time_accuracy, { "Time Accuracy", "cip.time_sync.gm_clock.time_accuracy", FT_UINT16, BASE_DEC, VALS(cip_time_sync_time_accuracy_vals), 0, NULL, HFILL }},
9920 { &hf_time_sync_gm_clock_offset_scaled_log_variance, { "Offset Scaled Log Variance", "cip.time_sync.gm_clock.offset_scaled_log_variance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9921 { &hf_time_sync_gm_clock_current_utc_offset, { "Current UTC Offset", "cip.time_sync.gm_clock.current_utc_offset", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9922 { &hf_time_sync_gm_clock_time_property_flags, { "Time Property Flags", "cip.time_sync.gm_clock.time_property_flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9923 { &hf_time_sync_gm_clock_time_property_flags_leap61, { "Leap indicator 61", "cip.time_sync.gm_clock.time_property_flags.leap61", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0001, NULL, HFILL }},
9924 { &hf_time_sync_gm_clock_time_property_flags_leap59, { "Leap indicator 59", "cip.time_sync.gm_clock.time_property_flags.leap59", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0002, NULL, HFILL }},
9925 { &hf_time_sync_gm_clock_time_property_flags_current_utc_valid, { "Current UTC Offset Valid", "cip.time_sync.gm_clock.time_property_flags.current_utc_valid", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0004, NULL, HFILL }},
9926 { &hf_time_sync_gm_clock_time_property_flags_ptp_timescale, { "PTP Timescale", "cip.time_sync.gm_clock.time_property_flags.ptp_timescale", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0008, NULL, HFILL }},
9927 { &hf_time_sync_gm_clock_time_property_flags_time_traceable, { "Time traceable", "cip.time_sync.gm_clock.time_property_flags.time_traceable", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0010, NULL, HFILL }},
9928 { &hf_time_sync_gm_clock_time_property_flags_freq_traceable, { "Frequency traceable", "cip.time_sync.gm_clock.time_property_flags.freq_traceable", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0020, NULL, HFILL }},
9929 { &hf_time_sync_gm_clock_time_source, { "Time Source", "cip.time_sync.gm_clock.time_source", FT_UINT16, BASE_DEC, VALS(cip_time_sync_time_source_vals), 0, NULL, HFILL }},
9930 { &hf_time_sync_gm_clock_priority1, { "Priority1", "cip.time_sync.gm_clock.priority1", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9931 { &hf_time_sync_gm_clock_priority2, { "Priority2", "cip.time_sync.gm_clock.priority2", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9932 { &hf_time_sync_parent_clock_clock_id, { "Clock Identity", "cip.time_sync.parent_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9933 { &hf_time_sync_parent_clock_port_number, { "Port Number", "cip.time_sync.parent_clock.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9934 { &hf_time_sync_parent_clock_observed_offset_scaled_log_variance, { "Observed Offset Scaled Log Variance", "cip.time_sync.parent_clock.observed_offset_scaled_log_variance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9935 { &hf_time_sync_parent_clock_observed_phase_change_rate, { "Observed Phase Change Rate", "cip.time_sync.parent_clock.observed_phase_change_rate", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9936 { &hf_time_sync_local_clock_clock_id, { "Clock Identity", "cip.time_sync.local_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9937 { &hf_time_sync_local_clock_clock_class, { "Clock Class", "cip.time_sync.local_clock.clock_class", FT_UINT16, BASE_DEC, VALS(cip_time_sync_clock_class_vals), 0, NULL, HFILL }},
9938 { &hf_time_sync_local_clock_time_accuracy, { "Time Accuracy", "cip.time_sync.local_clock.time_accuracy", FT_UINT16, BASE_DEC, VALS(cip_time_sync_time_accuracy_vals), 0, NULL, HFILL }},
9939 { &hf_time_sync_local_clock_offset_scaled_log_variance, { "Offset Scaled Log Variance", "cip.time_sync.local_clock.offset_scaled_log_variance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9940 { &hf_time_sync_local_clock_current_utc_offset, { "Current UTC Offset", "cip.time_sync.local_clock.current_utc_offset", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9941 { &hf_time_sync_local_clock_time_property_flags, { "Time Property Flags", "cip.time_sync.local_clock.time_property_flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9942 { &hf_time_sync_local_clock_time_property_flags_leap61, { "Leap indicator 61", "cip.time_sync.local_clock.time_property_flags.leap61", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0001, NULL, HFILL }},
9943 { &hf_time_sync_local_clock_time_property_flags_leap59, { "Leap indicator 59", "cip.time_sync.local_clock.time_property_flags.leap59", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0002, NULL, HFILL }},
9944 { &hf_time_sync_local_clock_time_property_flags_current_utc_valid, { "Current UTC Offset Valid", "cip.time_sync.local_clock.time_property_flags.current_utc_valid", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0004, NULL, HFILL }},
9945 { &hf_time_sync_local_clock_time_property_flags_ptp_timescale, { "PTP Timescale", "cip.time_sync.local_clock.time_property_flags.ptp_timescale", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0008, NULL, HFILL }},
9946 { &hf_time_sync_local_clock_time_property_flags_time_traceable, { "Time traceable", "cip.time_sync.local_clock.time_property_flags.time_traceable", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0010, NULL, HFILL }},
9947 { &hf_time_sync_local_clock_time_property_flags_freq_traceable, { "Frequency traceable", "cip.time_sync.local_clock.time_property_flags.freq_traceable", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0020, NULL, HFILL }},
9948 { &hf_time_sync_local_clock_time_source, { "Time Source", "cip.time_sync.local_clock.time_source", FT_UINT16, BASE_DEC, VALS(cip_time_sync_time_source_vals), 0, NULL, HFILL }},
9949 { &hf_time_sync_num_ports, { "Port Number", "cip.time_sync.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9950 { &hf_time_sync_port_state_info_num_ports, { "Number of Ports", "cip.time_sync.port_state_info.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9951 { &hf_time_sync_port_state_info_port_num, { "Port Number", "cip.time_sync.port_state_info.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9952 { &hf_time_sync_port_state_info_port_state, { "Port State", "cip.time_sync.port_state_info.port_state", FT_UINT16, BASE_DEC, VALS(cip_time_sync_port_state_vals), 0, NULL, HFILL }},
9953 { &hf_time_sync_port_enable_cfg_num_ports, { "Number of Ports", "cip.time_sync.port_enable_cfg.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9954 { &hf_time_sync_port_enable_cfg_port_num, { "Port Number", "cip.time_sync.port_enable_cfg.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9955 { &hf_time_sync_port_enable_cfg_port_enable, { "Port Enable", "cip.time_sync.port_enable_cfg.port_enable", FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }},
9956 { &hf_time_sync_port_log_announce_num_ports, { "Number of Ports", "cip.time_sync.port_log_announce.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9957 { &hf_time_sync_port_log_announce_port_num, { "Port Number", "cip.time_sync.port_log_announce.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9958 { &hf_time_sync_port_log_announce_interval, { "Port Log Announce Interval", "cip.time_sync.port_log_announce.interval", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9959 { &hf_time_sync_port_log_sync_num_ports, { "Number of Ports", "cip.time_sync.port_log_sync.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9960 { &hf_time_sync_port_log_sync_port_num, { "Port Number", "cip.time_sync.port_log_sync.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9961 { &hf_time_sync_port_log_sync_port_log_sync_interval, { "Port Log Sync Interval", "cip.time_sync.port_log_sync.port_log_sync_interval", FT_INT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9962 { &hf_time_sync_priority1, { "Priority1", "cip.time_sync.priority1", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9963 { &hf_time_sync_priority2, { "Priority2", "cip.time_sync.priority2", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9964 { &hf_time_sync_domain_number, { "Domain number", "cip.time_sync.domain_number", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
9965 { &hf_time_sync_clock_type, { "Clock Type", "cip.time_sync.clock_type", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
9966 { &hf_time_sync_clock_type_ordinary, { "Ordinary Clock", "cip.time_sync.clock_type.ordinary", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0080, NULL, HFILL }},
9967 { &hf_time_sync_clock_type_boundary, { "Boundary Clock", "cip.time_sync.clock_type.boundary", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0040, NULL, HFILL }},
9968 { &hf_time_sync_clock_type_end_to_end, { "End-to-End Transparent Clock", "cip.time_sync.clock_type.end_to_end", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0010, NULL, HFILL }},
9969 { &hf_time_sync_clock_type_management, { "Management Node", "cip.time_sync.clock_type.management", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0008, NULL, HFILL }},
9970 { &hf_time_sync_clock_type_slave_only, { "Slave Only", "cip.time_sync.clock_type.slave_only", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0100, NULL, HFILL }},
9971 { &hf_time_sync_manufacture_id_oui, { "Manufacture Identity OUI", "cip.time_sync.manufacture_id.oui", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL }},
9972 { &hf_time_sync_manufacture_id_reserved, { "Reserved", "cip.time_sync.manufacture_id.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
9973 { &hf_time_sync_prod_desc_size, { "Product Description Size", "cip.time_sync.prod_desc_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9974 { &hf_time_sync_prod_desc_str, { "Product Description", "cip.time_sync.prod_desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9975 { &hf_time_sync_revision_data_size, { "Revision Data Size", "cip.time_sync.revision_data_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9976 { &hf_time_sync_revision_data_str, { "Revision Data", "cip.time_sync.revision_data", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9977 { &hf_time_sync_user_desc_size, { "User Description Size", "cip.time_sync.user_desc_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
9978 { &hf_time_sync_user_desc_str, { "User Description", "cip.time_sync.user_desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9979 { &hf_time_sync_port_profile_id_info_num_ports, { "Number of Ports", "cip.time_sync.port_profile_id_info.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9980 { &hf_time_sync_port_profile_id_info_port_num, { "Port Number", "cip.time_sync.port_profile_id_info.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9981 { &hf_time_sync_port_profile_id_info_profile_id, { "Port Profile Identity", "cip.time_sync.port_profile_id_info.profile_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9982 { &hf_time_sync_port_phys_addr_info_num_ports, { "Number of Ports", "cip.time_sync.port_phys_addr_info.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9983 { &hf_time_sync_port_phys_addr_info_port_num, { "Port Number", "cip.time_sync.port_phys_addr_info.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9984 { &hf_time_sync_port_phys_addr_info_phys_proto, { "Physical Protocol", "cip.time_sync.port_profile_id_info.phys_proto", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
9985 { &hf_time_sync_port_phys_addr_info_addr_size, { "Size of Address", "cip.time_sync.port_phys_addr_info.addr_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9986 { &hf_time_sync_port_phys_addr_info_phys_addr, { "Port Physical Address", "cip.time_sync.port_profile_id_info.phys_addr", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9987 { &hf_time_sync_port_proto_addr_info_num_ports, { "Number of Ports", "cip.time_sync.port_proto_addr_info.num_ports", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9988 { &hf_time_sync_port_proto_addr_info_port_num, { "Port Number", "cip.time_sync.port_proto_addr_info.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9989 { &hf_time_sync_port_proto_addr_info_network_proto, { "Network Protocol", "cip.time_sync.port_proto_addr_info.network_proto", FT_UINT16, BASE_DEC, VALS(cip_time_sync_network_protocol_vals), 0, NULL, HFILL }},
9990 { &hf_time_sync_port_proto_addr_info_addr_size, { "Size of Address", "cip.time_sync.port_proto_addr_info.addr_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9991 { &hf_time_sync_port_proto_addr_info_port_proto_addr, { "Port Protocol Address", "cip.time_sync.port_profile_id_info.port_proto_addr", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
9992 { &hf_time_sync_steps_removed, { "Steps Removed", "cip.time_sync.steps_removed", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
9993 { &hf_time_sync_sys_time_and_offset_time, { "System Time (Microseconds)", "cip.time_sync.sys_time_and_offset.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
9994 { &hf_time_sync_sys_time_and_offset_offset, { "System Offset (Microseconds)", "cip.time_sync.sys_time_and_offset.offset", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }},
9995 { &hf_port_entry_port, { "Entry Port", "cip.port.entry_port", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9996 { &hf_port_type, { "Port Type", "cip.port.type", FT_UINT16, BASE_DEC | BASE_RANGE_STRING, RVALS(cip_port_type_vals), 0, NULL, HFILL } },
9997 { &hf_port_number, { "Port Number", "cip.port.number", FT_UINT16, BASE_DEC, VALS(cip_port_number_vals), 0, NULL, HFILL } },
9998 { &hf_port_min_node_num, { "Minimum Node Number", "cip.port.min_node", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
9999 { &hf_port_max_node_num, { "Maximum Node Number", "cip.port.max_node", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
10000 { &hf_port_name, { "Port Name", "cip.port.name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
10001 { &hf_port_num_comm_object_entries, { "Number of entries", "cip.port.num_comm_object_entries", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
10002 { &hf_path_len_usint, { "Path Length", "cip.path_len", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL } },
10003 { &hf_path_len_uint, { "Path Length", "cip.path_len", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL } },
10005 { &hf_32bitheader, { "32-bit Header", "cip.32bitheader", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
10006 { &hf_32bitheader_roo, { "ROO", "cip.32bitheader.roo", FT_UINT32, BASE_HEX, NULL, 0xC, "Ready for Ownership of Outputs", HFILL } },
10007 { &hf_32bitheader_coo, { "COO", "cip.32bitheader.coo", FT_UINT32, BASE_HEX, NULL, 0x2, "Claim Output Ownership", HFILL } },
10008 { &hf_32bitheader_run_idle, { "Run/Idle", "cip.32bitheader.run_idle", FT_UINT32, BASE_HEX, VALS(cip_run_idle_vals), 0x1, NULL, HFILL } },
10010 { &hf_cip_connection, { "CIP Connection Index", "cip.connection", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
10011 { &hf_cip_fwd_open_in, { "Forward Open Request In", "cip.fwd_open_in", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
10012 { &hf_cip_fwd_close_in, { "Forward Close Request In", "cip.fwd_close_in", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
10015 static hf_register_info hf_cm[] = {
10016 { &hf_cip_cm_sc, { "Service", "cip.cm.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_cm), CIP_SC_MASK, NULL, HFILL }},
10017 { &hf_cip_cm_genstat, { "General Status", "cip.cm.genstat", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
10018 { &hf_cip_cm_addstat_size, { "Additional Status Size", "cip.cm.addstat_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10019 { &hf_cip_cm_ext_status, { "Extended Status", "cip.cm.ext_status", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_cm_ext_st_vals_ext, 0, NULL, HFILL }},
10020 { &hf_cip_cm_add_status, { "Additional Status", "cip.cm.addstat", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10021 { &hf_cip_cm_priority, { "Priority", "cip.cm.priority", FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL }},
10022 { &hf_cip_cm_tick_time, { "Tick time", "cip.cm.tick_time", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
10023 { &hf_cip_cm_timeout_tick, { "Time-out ticks", "cip.cm.timeout_tick", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
10024 { &hf_cip_cm_timeout, { "Actual Time Out", "cip.cm.timeout", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliseconds), 0, NULL, HFILL }},
10025 { &hf_cip_cm_ot_connid, { "O->T Network Connection ID", "cip.cm.ot_connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10026 { &hf_cip_cm_to_connid, { "T->O Network Connection ID", "cip.cm.to_connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10027 { &hf_cip_connid, { "Connection ID", "cip.connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10028 { &hf_cip_cm_conn_serial_num, { "Connection Serial Number", "cip.cm.conn_serial_num", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10029 { &hf_cip_cm_vendor, { "Originator Vendor ID", "cip.cm.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
10030 { &hf_cip_cm_timeout_multiplier, { "Connection Timeout Multiplier", "cip.cm.timeout_multiplier", FT_UINT8, BASE_DEC, VALS(cip_con_time_mult_vals), 0, NULL, HFILL }},
10031 { &hf_cip_cm_ot_rpi, { "O->T RPI", "cip.cm.otrpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10032 { &hf_cip_cm_ot_timeout, { "O->T Timeout Threshold", "cip.cm.ot_timeout", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_milliseconds), 0, NULL, HFILL }},
10033 { &hf_cip_cm_ot_net_params32, { "O->T Network Connection Parameters", "cip.cm.ot_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10034 { &hf_cip_cm_ot_net_params16, { "O->T Network Connection Parameters", "cip.cm.ot_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10035 { &hf_cip_cm_to_rpi, { "T->O RPI", "cip.cm.torpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10036 { &hf_cip_cm_to_timeout, { "T->O Timeout Threshold", "cip.cm.to_timeout", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_milliseconds), 0, NULL, HFILL }},
10038 { &hf_cip_safety_nte_ms, { "Network Time Expectation (Produce Timeout)", "cip.safety.nte", FT_FLOAT, BASE_NONE|BASE_UNIT_STRING, UNS(&units_milliseconds), 0, NULL, HFILL }},
10040 { &hf_cip_cm_to_net_params32, { "T->O Network Connection Parameters", "cip.cm.to_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10041 { &hf_cip_cm_to_net_params16, { "T->O Network Connection Parameters", "cip.cm.to_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10042 { &hf_cip_cm_transport_type_trigger, { "Transport Type/Trigger", "cip.cm.transport_type_trigger", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10043 { &hf_cip_cm_conn_path_size, { "Connection Path Size", "cip.cm.connpath_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10044 { &hf_cip_cm_ot_api, { "O->T API", "cip.cm.otapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10045 { &hf_cip_cm_to_api, { "T->O API", "cip.cm.toapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10046 { &hf_cip_cm_app_reply_size, { "Application Reply Size", "cip.cm.app_reply_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10047 { &hf_cip_cm_app_reply_data , { "Application Reply", "cip.cm.app_reply_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10048 { &hf_cip_cm_consumer_number, { "Consumer Number", "cip.cm.consumer_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10049 { &hf_cip_cm_targ_vendor_id, { "Target Vendor ID", "cip.cm.targ_vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
10050 { &hf_cip_cm_targ_dev_serial_num, { "Target Device Serial Number", "cip.cm.targ_dev_serial_num", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10051 { &hf_cip_cm_targ_conn_serial_num, { "Target Connection Serial Number", "cip.cm.targ_conn_serial_num", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10052 { &hf_cip_cm_initial_timestamp, { "Initial Timestamp", "cip.cm.initial_timestamp", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10053 { &hf_cip_cm_initial_rollover, { "Initial Rollover Value", "cip.cm.initial_rollover", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10054 { &hf_cip_cm_remain_path_size, { "Remaining Path Size", "cip.cm.remain_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10055 { &hf_cip_cm_msg_req_size, { "Embedded Message Request Size", "cip.cm.msg_req_size", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0, NULL, HFILL }},
10056 { &hf_cip_cm_route_path_size, { "Route Path Size", "cip.cm.route_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10057 { &hf_cip_cm_orig_serial_num, { "Originator Serial Number", "cip.cm.orig_serial_num", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10058 { &hf_cip_cm_fwo_con_size, { "Connection Size", "cip.cm.fwo.consize", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x01FF, "Fwd Open: Connection size", HFILL }},
10059 { &hf_cip_cm_lfwo_con_size, { "Connection Size", "cip.cm.fwo.consize", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0xFFFF, "Large Fwd Open: Connection size", HFILL }},
10060 { &hf_cip_cm_fwo_fixed_var, { "Connection Size Type", "cip.cm.fwo.f_v", FT_UINT16, BASE_DEC, VALS(cip_con_fw_vals), 0x0200, "Fwd Open: Fixed or variable connection size", HFILL }},
10061 { &hf_cip_cm_lfwo_fixed_var, { "Connection Size Type", "cip.cm.fwo.f_v", FT_UINT32, BASE_DEC, VALS(cip_con_fw_vals), 0x02000000, "Large Fwd Open: Fixed or variable connection size", HFILL }},
10062 { &hf_cip_cm_fwo_prio, { "Priority", "cip.cm.fwo.prio", FT_UINT16, BASE_DEC, VALS(cip_con_prio_vals), 0x0C00, "Fwd Open: Connection priority", HFILL }},
10063 { &hf_cip_cm_lfwo_prio, { "Priority", "cip.cm.fwo.prio", FT_UINT32, BASE_DEC, VALS(cip_con_prio_vals), 0x0C000000, "Large Fwd Open: Connection priority", HFILL }},
10064 { &hf_cip_cm_fwo_typ, { "Connection Type", "cip.cm.fwo.type", FT_UINT16, BASE_DEC, VALS(cip_con_type_vals), 0x6000, "Fwd Open: Connection type", HFILL }},
10065 { &hf_cip_cm_lfwo_typ, { "Connection Type", "cip.cm.fwo.type", FT_UINT32, BASE_DEC, VALS(cip_con_type_vals), 0x60000000, "Large Fwd Open: Connection type", HFILL }},
10066 { &hf_cip_cm_fwo_own, { "Redundant Owner", "cip.cm.fwo.owner", FT_UINT16, BASE_DEC, VALS(cip_con_owner_vals), 0x8000, "Fwd Open: Redundant owner bit", HFILL }},
10067 { &hf_cip_cm_lfwo_own, { "Redundant Owner", "cip.cm.fwo.owner", FT_UINT32, BASE_DEC, VALS(cip_con_owner_vals), 0x80000000, "Large Fwd Open: Redundant owner bit", HFILL }},
10068 { &hf_cip_cm_fwo_dir, { "Direction", "cip.cm.fwo.dir", FT_BOOLEAN, 8, TFS(&tfs_server_client), CI_PRODUCTION_DIR_MASK, "Fwd Open: Direction", HFILL }},
10069 { &hf_cip_cm_fwo_trigg, { "Trigger", "cip.cm.fwo.trigger", FT_UINT8, BASE_DEC, VALS(cip_con_trigg_vals), CI_PRODUCTION_TRIGGER_MASK, "Fwd Open: Production trigger", HFILL }},
10070 { &hf_cip_cm_fwo_class, { "Class", "cip.cm.fwo.transport", FT_UINT8, BASE_DEC, VALS(cip_con_class_vals), CI_TRANSPORT_CLASS_MASK, "Fwd Open: Transport Class", HFILL }},
10071 { &hf_cip_cm_gco_conn, { "Number of Connections", "cip.cm.gco.conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: Number of Connections", HFILL }},
10072 { &hf_cip_cm_gco_coo_conn, { "COO Connections", "cip.cm.gco.coo_conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: COO Connections", HFILL }},
10073 { &hf_cip_cm_gco_roo_conn, { "ROO Connections", "cip.cm.gco.roo_conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: ROO Connections", HFILL }},
10074 { &hf_cip_cm_gco_last_action, { "Last Action", "cip.cm.gco.la", FT_UINT8, BASE_DEC, VALS(cip_con_last_action_vals), 0, "GetConnOwner: Last Action", HFILL }},
10075 { &hf_cip_cm_ext112_ot_rpi_type, { "Trigger", "cip.cm.ext112otrpi_type", FT_UINT8, BASE_DEC, VALS(cip_cm_rpi_type_vals), 0, NULL, HFILL }},
10076 { &hf_cip_cm_ext112_to_rpi_type, { "Trigger", "cip.cm.ext112torpi_type", FT_UINT8, BASE_DEC, VALS(cip_cm_rpi_type_vals), 0, NULL, HFILL }},
10077 { &hf_cip_cm_ext112_ot_rpi, { "Acceptable O->T RPI", "cip.cm.ext112otrpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10078 { &hf_cip_cm_ext112_to_rpi, { "Acceptable T->O RPI", "cip.cm.ext112torpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10079 { &hf_cip_cm_ext126_size, { "Maximum Size", "cip.cm.ext126_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10080 { &hf_cip_cm_ext127_size, { "Maximum Size", "cip.cm.ext127_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10081 { &hf_cip_cm_ext128_size, { "Maximum Size", "cip.cm.ext128_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}
10084 static hf_register_info hf_pccc[] = {
10085 { &hf_cip_pccc_sc, { "Service", "cip.pccc.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_pccc), CIP_SC_MASK, NULL, HFILL }},
10086 { &hf_cip_pccc_req_id_len, { "Requestor ID Length", "cip.pccc.req.id.len", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10087 { &hf_cip_pccc_cip_vend_id, { "CIP Vendor ID", "cip.pccc.cip.vend.id", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10088 { &hf_cip_pccc_cip_serial_num, { "CIP Serial Number", "cip.pccc.cip.serial.num", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10089 { &hf_cip_pccc_cmd_code, { "Command Code", "cip.pccc.cmd.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10090 { &hf_cip_pccc_sts_code, { "Status", "cip.pccc.gs.status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_gs_st_vals_ext, 0, NULL, HFILL }},
10091 { &hf_cip_pccc_ext_sts_code, { "Extended Status", "cip.pccc.es.status", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_es_st_vals_ext, 0, NULL, HFILL }},
10092 { &hf_cip_pccc_tns_code, { "Transaction Code", "cip.pccc.tns.code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10093 { &hf_cip_pccc_fnc_code_06, { "Function Code", "cip.pccc.fnc.code_06", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_fnc_06_vals_ext, 0, NULL, HFILL }},
10094 { &hf_cip_pccc_fnc_code_07, { "Function Code", "cip.pccc.fnc.code_07", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_fnc_07_vals_ext, 0, NULL, HFILL }},
10095 { &hf_cip_pccc_fnc_code_0f, { "Function Code", "cip.pccc.fnc.code_0f", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_fnc_0f_vals_ext, 0, NULL, HFILL }},
10096 { &hf_cip_pccc_byte_size, { "Byte Size", "cip.pccc.byte.size", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10097 { &hf_cip_pccc_file_num, { "File Number", "cip.pccc.file.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10098 { &hf_cip_pccc_file_type, { "File Type", "cip.pccc.file.type", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_file_type_vals_ext, 0, NULL, HFILL }},
10099 { &hf_cip_pccc_element_num, { "Element Number", "cip.pccc.element.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10100 { &hf_cip_pccc_subelement_num, { "Sub-Element Number", "cip.pccc.subelement.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10101 #if 0
10102 { &hf_cip_pccc_cpu_mode_3a, { "CPU Mode", "cip.pccc.cpu.mode_3a", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_cpu_mode_3a_vals_ext, 0, NULL, HFILL }},
10103 #endif
10104 { &hf_cip_pccc_cpu_mode_80, { "CPU Mode", "cip.pccc.cpu.mode_80", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_pccc_cpu_mode_80_vals_ext, 0, NULL, HFILL }},
10105 { &hf_cip_pccc_resp_code, { "Response Code", "cip.pccc.resp.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10106 { &hf_cip_pccc_execute_multi_count, { "Execute Multiple Command - Number of Commands", "cip.pccc.execute.multi.count", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10107 { &hf_cip_pccc_execute_multi_len, { "Execute Multiple Command - Command Length", "cip.pccc.execute.multi.len", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10108 { &hf_cip_pccc_execute_multi_fnc, { "Execute Multiple Command - Function Code", "cip.pccc.execute.multi.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10110 { &hf_cip_pccc_data, { "Data", "cip.pccc.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
10113 static hf_register_info hf_mb[] = {
10114 { &hf_cip_mb_sc, { "Service", "cip.mb.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_mb), CIP_SC_MASK, NULL, HFILL }},
10115 { &hf_cip_mb_read_coils_start_addr, { "Starting Address", "cip.mb.read_coils.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10116 { &hf_cip_mb_read_coils_num_coils, { "Quantity of Coils", "cip.mb.read_coils.num_coils", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10117 { &hf_cip_mb_read_coils_data, { "Data", "cip.mb.read_coils.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10118 { &hf_cip_mb_read_discrete_inputs_start_addr, { "Starting Address", "cip.mb.read_discrete_inputs.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10119 { &hf_cip_mb_read_discrete_inputs_num_inputs, { "Quantity of Inputs", "cip.mb.read_discrete_inputs.num_inputs", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10120 { &hf_cip_mb_read_discrete_inputs_data, { "Data", "cip.mb.read_discrete_inputs.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10121 { &hf_cip_mb_read_holding_register_start_addr, { "Starting Address", "cip.mb.read_holding_register.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10122 { &hf_cip_mb_read_holding_register_num_registers, { "Quantity of Holding Registers", "cip.mb.read_holding_register.num_registers", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10123 { &hf_cip_mb_read_holding_register_data, { "Data", "cip.mb.read_holding_register.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10124 { &hf_cip_mb_read_input_register_start_addr, { "Starting Address", "cip.mb.read_input_register.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10125 { &hf_cip_mb_read_input_register_num_registers, { "Quantity of Input Registers", "cip.mb.read_input_register.num_registers", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10126 { &hf_cip_mb_read_input_register_data, { "Data", "cip.mb.read_input_register.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10127 { &hf_cip_mb_write_coils_start_addr, { "Starting Address", "cip.mb.write_coils.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10128 { &hf_cip_mb_write_coils_outputs_forced, { "Outputs Forced", "cip.mb.write_coils.outputs_forced", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10129 { &hf_cip_mb_write_coils_num_coils, { "Quantity of Coils", "cip.mb.write_coils.num_coils", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10130 { &hf_cip_mb_write_coils_data, { "Data", "cip.mb.write_coils.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10131 { &hf_cip_mb_write_registers_start_addr, { "Starting Address", "cip.mb.write_registers.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10132 { &hf_cip_mb_write_registers_outputs_forced, { "Outputs Forced", "cip.mb.write_registers.outputs_forced", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10133 { &hf_cip_mb_write_registers_num_registers, { "Quantity of Holding Registers", "cip.mb.write_registers.num_registers", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10134 { &hf_cip_mb_write_registers_data, { "Data", "cip.mb.write_registers.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10135 { &hf_cip_mb_data, { "Data", "cip.mb.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
10138 static hf_register_info hf_cco[] = {
10139 { &hf_cip_cco_sc, { "Service", "cip.cco.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_cco), CIP_SC_MASK, NULL, HFILL }},
10140 { &hf_cip_cco_format_number, { "Format Number", "cip.cco.format_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10141 { &hf_cip_cco_edit_signature, { "Edit Signature", "cip.cco.edit_signature", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10142 { &hf_cip_cco_con_flags, { "Connection Flags", "cip.cco.connflags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10143 { &hf_cip_cco_con_type, { "Connection O_T", "cip.cco.con", FT_UINT16, BASE_DEC, VALS(cip_con_vals), 0x0001, NULL, HFILL }},
10144 { &hf_cip_cco_ot_rtf, { "O->T real time transfer format", "cip.cco.otrtf", FT_UINT16, BASE_DEC, VALS(cip_con_rtf_vals), 0x000E, NULL, HFILL }},
10145 { &hf_cip_cco_to_rtf, { "T->O real time transfer format", "cip.cco.tortf", FT_UINT16, BASE_DEC, VALS(cip_con_rtf_vals), 0x0070, NULL, HFILL }},
10146 { &hf_cip_cco_tdi_vendor, { "Vendor ID", "cip.cco.tdi.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
10147 { &hf_cip_cco_tdi_devtype, { "Device Type", "cip.cco.tdi.devtype", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
10148 { &hf_cip_cco_tdi_prodcode, { "Product Code", "cip.cco.tdi.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10149 { &hf_cip_cco_tdi_compatibility, { "Compatibility", "cip.cco.tdi.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10150 { &hf_cip_cco_tdi_comp_bit, { "Compatibility", "cip.cco.tdi.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, NULL, HFILL }},
10151 { &hf_cip_cco_tdi_majorrev, { "Major Revision", "cip.cco.tdi.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL }},
10152 { &hf_cip_cco_tdi_minorrev, { "Minor Revision", "cip.cco.tdi.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
10153 { &hf_cip_cco_pdi_vendor, { "Vendor ID", "cip.cco.pdi.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
10154 { &hf_cip_cco_pdi_devtype, { "Device Type", "cip.cco.pdi.devtype", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
10155 { &hf_cip_cco_pdi_prodcode, { "Product Code", "cip.cco.pdi.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10156 { &hf_cip_cco_pdi_compatibility, { "Compatibility", "cip.cco.pdi.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10157 { &hf_cip_cco_pdi_comp_bit, { "Compatibility", "cip.cco.pdi.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, NULL, HFILL }},
10158 { &hf_cip_cco_pdi_majorrev, { "Major Revision", "cip.cco.pdi.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL }},
10159 { &hf_cip_cco_pdi_minorrev, { "Minor Revision", "cip.cco.pdi.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
10160 { &hf_cip_cco_cs_data_index, { "CS Data Index Number", "cip.cco.cs_data_index", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10161 { &hf_cip_cco_timeout_multiplier, { "Connection Timeout Multiplier", "cip.cco.timeout_multiplier", FT_UINT8, BASE_DEC, VALS(cip_con_time_mult_vals), 0, NULL, HFILL }},
10162 { &hf_cip_cco_ot_rpi, { "O->T RPI", "cip.cco.otrpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10163 { &hf_cip_cco_ot_net_param32, { "O->T Network Connection Parameters", "cip.cco.ot_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10164 { &hf_cip_cco_ot_net_param16, { "O->T Network Connection Parameters", "cip.cco.ot_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10165 { &hf_cip_cco_to_rpi, { "T->O RPI", "cip.cco.torpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
10166 { &hf_cip_cco_to_net_param16, { "T->O Network Connection Parameters", "cip.cco.to_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
10167 { &hf_cip_cco_to_net_param32, { "T->O Network Connection Parameters", "cip.cco.to_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
10168 { &hf_cip_cco_transport_type_trigger, { "Transport Type/Trigger", "cip.cco.transport_type_trigger", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
10169 { &hf_cip_cco_fwo_con_size, { "Connection Size", "cip.cco.consize", FT_UINT16, BASE_DEC, NULL, 0x01FF, NULL, HFILL }},
10170 { &hf_cip_cco_lfwo_con_size, { "Connection Size", "cip.cco.consize", FT_UINT32, BASE_DEC, NULL, 0xFFFF, NULL, HFILL }},
10171 { &hf_cip_cco_fwo_fixed_var, { "Connection Size Type", "cip.cco.f_v", FT_UINT16, BASE_DEC, VALS(cip_con_fw_vals), 0x0200, NULL, HFILL }},
10172 { &hf_cip_cco_lfwo_fixed_var, { "Connection Size Type", "cip.cco.f_v", FT_UINT32, BASE_DEC, VALS(cip_con_fw_vals), 0x02000000, NULL, HFILL }},
10173 { &hf_cip_cco_fwo_prio, { "Priority", "cip.cco.prio", FT_UINT16, BASE_DEC, VALS(cip_con_prio_vals), 0x0C00, NULL, HFILL }},
10174 { &hf_cip_cco_lfwo_prio, { "Priority", "cip.cco.prio", FT_UINT32, BASE_DEC, VALS(cip_con_prio_vals), 0x0C000000, NULL, HFILL }},
10175 { &hf_cip_cco_fwo_typ, { "Connection Type", "cip.cco.type", FT_UINT16, BASE_DEC, VALS(cip_con_type_vals), 0x6000, NULL, HFILL }},
10176 { &hf_cip_cco_lfwo_typ, { "Connection Type", "cip.cco.type", FT_UINT32, BASE_DEC, VALS(cip_con_type_vals), 0x60000000, NULL, HFILL }},
10177 { &hf_cip_cco_fwo_own, { "Redundant Owner", "cip.cco.owner", FT_UINT16, BASE_DEC, VALS(cip_con_owner_vals), 0x8000, NULL, HFILL }},
10178 { &hf_cip_cco_lfwo_own, { "Redundant Owner", "cip.cco.owner", FT_UINT32, BASE_DEC, VALS(cip_con_owner_vals), 0x80000000, NULL, HFILL }},
10179 { &hf_cip_cco_fwo_dir, { "Direction", "cip.cco.dir", FT_BOOLEAN, 8, TFS(&tfs_server_client), CI_PRODUCTION_DIR_MASK, NULL, HFILL }},
10180 { &hf_cip_cco_fwo_trigger, { "Trigger", "cip.cco.trigger", FT_UINT8, BASE_DEC, VALS(cip_con_trigg_vals), CI_PRODUCTION_TRIGGER_MASK, NULL, HFILL }},
10181 { &hf_cip_cco_fwo_class, { "Class", "cip.cco.transport", FT_UINT8, BASE_DEC, VALS(cip_con_class_vals), CI_TRANSPORT_CLASS_MASK, NULL, HFILL }},
10182 { &hf_cip_cco_conn_path_size, { "Connection Path Size", "cip.cco.connpath_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_word_words), 0, NULL, HFILL }},
10183 { &hf_cip_cco_proxy_config_size, { "Proxy Config Data Size", "cip.cco.proxy_config_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10184 { &hf_cip_cco_target_config_size, { "Target Config Data Size", "cip.cco.target_config_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10185 { &hf_cip_cco_iomap_format_number, { "Format number", "cip.cco.iomap_format_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
10186 { &hf_cip_cco_iomap_size, { "Mapping data size", "cip.cco.iomap_size", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0, NULL, HFILL }},
10187 { &hf_cip_cco_connection_disable, { "Connection Disable", "cip.cco.connection_disable", FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL }},
10188 { &hf_cip_cco_net_conn_param_attr, { "Net Connection Parameter Attribute Selection", "cip.cco.net_conn_param_attr", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
10189 { &hf_cip_cco_proxy_config_data, { "Proxy Config Data", "cip.cco.proxy_config_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10190 { &hf_cip_cco_target_config_data, { "Target Config Data", "cip.cco.target_config_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10191 { &hf_cip_cco_iomap_attribute, { "Attribute Data", "cip.cco.iomap", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10192 { &hf_cip_cco_safety, { "Safety Parameters", "cip.cco.safety", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
10193 { &hf_cip_cco_change_type, { "Change Type", "cip.cco.change_type", FT_UINT16, BASE_DEC, VALS(cip_cco_change_type_vals), 0, NULL, HFILL }},
10194 { &hf_cip_cco_connection_name, { "Connection Name", "cip.cco.connection_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
10195 { &hf_cip_cco_ext_status, { "Extended Status", "cip.cco.ext_status", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_cm_ext_st_vals_ext, 0, NULL, HFILL }},
10198 /* Setup protocol subtree array */
10199 static int *ett[] = {
10200 &ett_cip_class_generic,
10201 &ett_cip,
10202 &ett_path,
10203 &ett_path_seg,
10204 &ett_rrsc,
10205 &ett_mcsc,
10206 &ett_cia_path,
10207 &ett_data_seg,
10208 &ett_cmd_data,
10209 &ett_port_path,
10210 &ett_network_seg,
10211 &ett_network_seg_safety,
10212 &ett_network_seg_safety_time_correction_net_params,
10213 &ett_cip_seg_safety_tunid,
10214 &ett_cip_seg_safety_tunid_snn,
10215 &ett_cip_seg_safety_ounid,
10216 &ett_cip_seg_safety_ounid_snn,
10217 &ett_status_item,
10218 &ett_add_status_item,
10219 &ett_cip_get_attributes_all_item,
10220 &ett_cip_get_attribute_list,
10221 &ett_cip_get_attribute_list_item,
10222 &ett_cip_set_attribute_list,
10223 &ett_cip_set_attribute_list_item,
10224 &ett_cip_mult_service_packet,
10225 &ett_cip_msp_offset,
10226 &ett_time_sync_gm_clock_flags,
10227 &ett_time_sync_local_clock_flags,
10228 &ett_time_sync_port_state_info,
10229 &ett_time_sync_port_enable_cfg,
10230 &ett_time_sync_port_log_announce,
10231 &ett_time_sync_port_log_sync,
10232 &ett_time_sync_clock_type,
10233 &ett_time_sync_port_profile_id_info,
10234 &ett_time_sync_port_phys_addr_info,
10235 &ett_time_sync_port_proto_addr_info,
10236 &ett_id_status,
10237 &ett_32bitheader_tree,
10238 &ett_connection_info,
10241 static int *ett_cm[] = {
10242 &ett_cip_class_cm,
10243 &ett_cm_rrsc,
10244 &ett_cm_mes_req,
10245 &ett_cm_ncp,
10246 &ett_cm_cmd_data,
10247 &ett_cm_ttt,
10248 &ett_cm_add_status_item,
10249 &ett_cip_cm_pid,
10250 &ett_cip_cm_safety
10253 static int *ett_pccc[] = {
10254 &ett_cip_class_pccc,
10255 &ett_pccc_rrsc,
10256 &ett_pccc_req_id,
10257 &ett_pccc_cmd_data
10260 static int *ett_mb[] = {
10261 &ett_cip_class_mb,
10262 &ett_mb_rrsc,
10263 &ett_mb_cmd_data
10266 static int *ett_cco[] = {
10267 &ett_cip_class_cco,
10268 &ett_cco_iomap,
10269 &ett_cco_con_status,
10270 &ett_cco_con_flag,
10271 &ett_cco_tdi,
10272 &ett_cco_pdi,
10273 &ett_cco_ncp,
10274 &ett_cco_rrsc,
10275 &ett_cco_cmd_data,
10276 &ett_cco_ttt,
10279 static ei_register_info ei[] = {
10280 { &ei_mal_identity_revision, { "cip.malformed.id.revision", PI_MALFORMED, PI_ERROR, "Malformed Identity revision", EXPFILL }},
10281 { &ei_mal_identity_status, { "cip.malformed.id.status", PI_MALFORMED, PI_ERROR, "Malformed Identity status", EXPFILL } },
10282 { &ei_mal_msg_rout_num_classes, { "cip.malformed.msg_rout.num_classes", PI_MALFORMED, PI_ERROR, "Malformed Message Router Attribute 1", EXPFILL }},
10283 { &ei_mal_time_sync_gm_clock, { "cip.malformed.time_sync.gm_clock", PI_MALFORMED, PI_ERROR, "Malformed Grandmaster clock info", EXPFILL }},
10284 { &ei_mal_time_sync_parent_clock, { "cip.malformed.time_sync.parent_clock", PI_MALFORMED, PI_ERROR, "Malformed Parent clock info", EXPFILL }},
10285 { &ei_mal_time_sync_local_clock, { "cip.malformed.time_sync.local_clock", PI_MALFORMED, PI_ERROR, "Malformed Local clock info", EXPFILL }},
10286 { &ei_mal_time_sync_port_state_info, { "cip.malformed.time_sync.port_state_info", PI_MALFORMED, PI_ERROR, "Malformed Port State Info", EXPFILL }},
10287 { &ei_mal_time_sync_port_state_info_ports, { "cip.malformed.time_sync.port_state_info.ports", PI_MALFORMED, PI_ERROR, "Malformed Port State Info - too many ports", EXPFILL }},
10288 { &ei_mal_time_sync_port_enable_cfg, { "cip.malformed.time_sync.port_enable_cfg", PI_MALFORMED, PI_ERROR, "Malformed Port Enable Cfg", EXPFILL }},
10289 { &ei_mal_time_sync_port_enable_cfg_ports, { "cip.malformed.time_sync.port_enable_cfg.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Enable Cfg - too many ports", EXPFILL }},
10290 { &ei_mal_time_sync_port_log_announce, { "cip.malformed.time_sync.port_log_announce", PI_MALFORMED, PI_ERROR, "Malformed Port Log Announcement Interval Cfg", EXPFILL }},
10291 { &ei_mal_time_sync_port_log_announce_ports, { "cip.malformed.time_sync.port_log_announce.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Log Announcement Interval Cfg - too many ports", EXPFILL }},
10292 { &ei_mal_time_sync_port_log_sync, { "cip.malformed.time_sync.port_log_sync", PI_MALFORMED, PI_ERROR, "Malformed Port Log Sync Interval Cfg", EXPFILL }},
10293 { &ei_mal_time_sync_port_log_sync_ports, { "cip.malformed.time_sync.port_log_sync.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Log Sync Interval Cfg - too many ports", EXPFILL }},
10294 { &ei_mal_time_sync_clock_type, { "cip.malformed.time_sync.clock_type", PI_MALFORMED, PI_ERROR, "Malformed Clock Type", EXPFILL }},
10295 { &ei_mal_time_sync_manufacture_id, { "cip.malformed.time_sync.manufacture_id", PI_MALFORMED, PI_ERROR, "Malformed Manufacture Identity", EXPFILL }},
10296 { &ei_mal_time_sync_prod_desc, { "cip.malformed.time_sync.prod_desc", PI_MALFORMED, PI_ERROR, "Malformed Product Description", EXPFILL }},
10297 { &ei_mal_time_sync_prod_desc_64, { "cip.malformed.time_sync.prod_desc.limit_64", PI_PROTOCOL, PI_WARN, "Product Description limited to 64 characters", EXPFILL }},
10298 { &ei_mal_time_sync_prod_desc_size, { "cip.malformed.time_sync.prod_desc.size", PI_MALFORMED, PI_ERROR, "Malformed Product Description - invalid size", EXPFILL }},
10299 { &ei_mal_time_sync_revision_data, { "cip.malformed.time_sync.revision_data", PI_MALFORMED, PI_ERROR, "Malformed Revision Data", EXPFILL }},
10300 { &ei_mal_time_sync_revision_data_32, { "cip.malformed.time_sync.revision_data.limit_32", PI_PROTOCOL, PI_WARN, "Revision Data limited to 32 characters", EXPFILL }},
10301 { &ei_mal_time_sync_revision_data_size, { "cip.malformed.time_sync.revision_data.size", PI_MALFORMED, PI_ERROR, "Malformed Revision Data - invalid size", EXPFILL }},
10302 { &ei_mal_time_sync_user_desc, { "cip.malformed.time_sync.user_desc", PI_MALFORMED, PI_ERROR, "Malformed User Description", EXPFILL }},
10303 { &ei_mal_time_sync_user_desc_128, { "cip.malformed.time_sync.user_desc.limit_128", PI_PROTOCOL, PI_WARN, "User Description limited to 128 characters", EXPFILL }},
10304 { &ei_mal_time_sync_user_desc_size, { "cip.malformed.time_sync.user_desc.size", PI_MALFORMED, PI_ERROR, "Malformed User Description - invalid size", EXPFILL }},
10305 { &ei_mal_time_sync_port_profile_id_info, { "cip.malformed.time_sync.port_profile_id_info", PI_MALFORMED, PI_ERROR, "Malformed Port Profile Identity Info", EXPFILL }},
10306 { &ei_mal_time_sync_port_profile_id_info_ports, { "cip.malformed.time_sync.port_profile_id_info.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Profile Identity Info - too many ports", EXPFILL }},
10307 { &ei_mal_time_sync_port_phys_addr_info, { "cip.malformed.time_sync.port_phys_addr_info", PI_MALFORMED, PI_ERROR, "Malformed Port Physical Address Info", EXPFILL }},
10308 { &ei_mal_time_sync_port_phys_addr_info_ports, { "cip.malformed.time_sync.port_phys_addr_info.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Physical Address Info - too many ports", EXPFILL }},
10309 { &ei_mal_time_sync_port_proto_addr_info, { "cip.malformed.time_sync.port_proto_addr_info", PI_MALFORMED, PI_ERROR, "Malformed Port Protocol Address Info", EXPFILL }},
10310 { &ei_mal_time_sync_port_proto_addr_info_ports, { "cip.malformed.time_sync.port_proto_addr_info.ports", PI_MALFORMED, PI_ERROR, "Malformed Port Protocol Address Info - too many ports", EXPFILL }},
10311 { &ei_mal_time_sync_sys_time_and_offset, { "cip.malformed.time_sync.sys_time_and_offset", PI_MALFORMED, PI_ERROR, "Malformed System Time and Offset", EXPFILL }},
10312 { &ei_proto_log_seg_format, { "cip.unsupported.log_seg_format", PI_PROTOCOL, PI_WARN, "Unsupported Logical Segment Format", EXPFILL }},
10313 { &ei_mal_incomplete_epath, { "cip.malformed.incomplete_epath", PI_MALFORMED, PI_ERROR, "Incomplete EPATH", EXPFILL }},
10314 { &ei_proto_electronic_key_format, { "cip.unsupported.electronic_key_format", PI_PROTOCOL, PI_WARN, "Unsupported Electronic Key Format", EXPFILL }},
10315 { &ei_proto_special_segment_format, { "cip.unsupported.special_segment_format", PI_PROTOCOL, PI_WARN, "Unsupported Special Segment Format", EXPFILL }},
10316 { &ei_proto_log_seg_type, { "cip.unsupported.log_seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Logical Segment Type", EXPFILL }},
10317 { &ei_proto_log_sub_seg_type, { "cip.unsupported.log_sub_seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Sub-Segment Type", EXPFILL }},
10318 { &ei_proto_ext_string_format, { "cip.unsupported.ext_string_format", PI_PROTOCOL, PI_WARN, "Unsupported Extended String Format", EXPFILL } },
10319 { &ei_proto_ext_network, { "cip.malformed.ext_network", PI_PROTOCOL, PI_ERROR, "Malformed Extended Network Segment Format", EXPFILL } },
10320 { &ei_proto_seg_type, { "cip.unsupported.seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Segment Type", EXPFILL }},
10321 { &ei_proto_unsupported_datatype, { "cip.unsupported.datatype", PI_PROTOCOL, PI_WARN, "Unsupported Datatype", EXPFILL }},
10322 { &ei_mal_serv_gal, { "cip.malformed.get_attribute_list", PI_MALFORMED, PI_ERROR, "Malformed Get Attribute List service", EXPFILL }},
10323 { &ei_mal_serv_gal_count, { "cip.malformed.get_attribute_list.count", PI_MALFORMED, PI_ERROR, "Malformed Get Attribute List attribute list count greater than packet size", EXPFILL }},
10324 { &ei_mal_serv_sal, { "cip.malformed.set_attribute_list", PI_MALFORMED, PI_ERROR, "Malformed Set Attribute List service", EXPFILL }},
10325 { &ei_mal_serv_sal_count, { "cip.malformed.set_attribute_list.count", PI_MALFORMED, PI_ERROR, "Malformed Set Attribute List attribute list count greater than packet size", EXPFILL }},
10326 { &ei_mal_msp_services, { "cip.malformed.msp.services", PI_MALFORMED, PI_WARN, "Multiple Service Packet too many services for packet", EXPFILL }},
10327 { &ei_mal_msp_inv_offset, { "cip.malformed.msp.inv_offset", PI_MALFORMED, PI_WARN, "Multiple Service Packet service invalid offset", EXPFILL }},
10328 { &ei_mal_msp_missing_services, { "cip.malformed.msp.missing_services", PI_MALFORMED, PI_ERROR, "Multiple Service Packet service missing Number of Services field", EXPFILL }},
10329 { &ei_mal_serv_find_next_object, { "cip.malformed.find_next_object", PI_MALFORMED, PI_ERROR, "Find Next Object service missing Number of List Members field", EXPFILL }},
10330 { &ei_mal_serv_find_next_object_count, { "cip.malformed.find_next_object.count", PI_MALFORMED, PI_ERROR, "Find Next Object instance list count greater than packet size", EXPFILL }},
10331 { &ei_mal_rpi_no_data, { "cip.malformed.rpi_no_data", PI_MALFORMED, PI_WARN, "RPI not acceptable - missing extended data", EXPFILL }},
10332 { &ei_mal_fwd_close_missing_data, { "cip.malformed.fwd_close_missing_data", PI_MALFORMED, PI_ERROR, "Forward Close response missing application reply data", EXPFILL }},
10333 { &ei_mal_opt_attr_list, { "cip.malformed.opt_attr_list", PI_MALFORMED, PI_ERROR, "Optional attribute list missing data", EXPFILL }},
10334 { &ei_mal_opt_service_list, { "cip.malformed.opt_service_list", PI_MALFORMED, PI_ERROR, "Optional service list missing data", EXPFILL }},
10335 { &ei_mal_padded_epath_size, { "cip.malformed.epath.size", PI_MALFORMED, PI_ERROR, "Malformed EPATH vs Size", EXPFILL } },
10336 { &ei_mal_missing_string_data, { "cip.malformed.missing_str_data", PI_MALFORMED, PI_ERROR, "Missing string data", EXPFILL } },
10338 { &ei_cip_null_fwd_open, { "cip.analysis.null_fwd_open", PI_PROTOCOL, PI_NOTE, "Null Forward Open", EXPFILL } },
10339 { &ei_cip_safety_open_type1, { "cip.analysis.safety_open_type1", PI_PROTOCOL, PI_NOTE, "Type 1 - Safety Open with Data", EXPFILL } },
10340 { &ei_cip_safety_open_type2a, { "cip.analysis.safety_open_type2a", PI_PROTOCOL, PI_NOTE, "Type 2a - Safety Open with SCID check", EXPFILL } },
10341 { &ei_cip_safety_open_type2b, { "cip.analysis.safety_open_type2b", PI_PROTOCOL, PI_NOTE, "Type 2b - Safety Open without SCID check", EXPFILL } },
10342 { &ei_cip_safety_input, { "cip.analysis.safety_input", PI_PROTOCOL, PI_NOTE, "Safety Input Connection", EXPFILL } },
10343 { &ei_cip_safety_output, { "cip.analysis.safety_output", PI_PROTOCOL, PI_NOTE, "Safety Output Connection", EXPFILL } },
10344 { &ei_cip_listen_input_connection, { "cip.analysis.listen_input_connection", PI_PROTOCOL, PI_NOTE, "[Likely] Listen Only or Input Only Connection", EXPFILL } },
10345 { &ei_cip_no_fwd_close, { "cip.analysis.no_fwd_close", PI_PROTOCOL, PI_NOTE, "No Forward Close seen for this CIP Connection", EXPFILL } },
10348 module_t *cip_module;
10349 expert_module_t* expert_cip;
10351 /* Register the protocol name and description */
10352 proto_cip = proto_register_protocol("Common Industrial Protocol",
10353 "CIP", "cip");
10354 cip_handle = register_dissector("cip", dissect_cip, proto_cip);
10356 register_dissector("cip_implicit", dissect_cip_implicit, proto_cip);
10358 /* Required function calls to register the header fields and subtrees used */
10359 proto_register_field_array(proto_cip, hf, array_length(hf));
10360 proto_register_subtree_array(ett, array_length(ett));
10362 expert_cip = expert_register_protocol(proto_cip);
10363 expert_register_field_array(expert_cip, ei, array_length(ei));
10365 cip_module = prefs_register_protocol(proto_cip, NULL);
10366 prefs_register_bool_preference(cip_module, "enhanced_info_column",
10367 "Display enhanced Info column data",
10368 "Whether the CIP dissector should display enhanced/verbose data in the Info column for CIP explicit messages",
10369 &cip_enhanced_info_column);
10371 subdissector_class_table = register_dissector_table("cip.class.iface",
10372 "CIP Class Interface Handle", proto_cip, FT_UINT32, BASE_HEX);
10373 subdissector_symbol_table = register_dissector_table("cip.data_segment.iface",
10374 "CIP Data Segment Interface Handle", proto_cip, FT_UINT32, BASE_HEX);
10376 /* Register the protocol name and description */
10377 proto_cip_class_generic = proto_register_protocol("CIP Class Generic",
10378 "CIPCLS", "cipcls");
10379 cip_class_generic_handle = register_dissector("cipcls",
10380 dissect_cip_class_generic, proto_cip_class_generic);
10382 /* Register the protocol name and description */
10383 proto_cip_class_cm = proto_register_protocol("CIP Connection Manager",
10384 "CIPCM", "cipcm");
10385 cip_class_cm_handle = register_dissector("cipcm",
10386 dissect_cip_class_cm, proto_cip_class_cm);
10387 proto_register_field_array(proto_cip_class_cm, hf_cm, array_length(hf_cm));
10388 proto_register_subtree_array(ett_cm, array_length(ett_cm));
10390 proto_cip_class_pccc = proto_register_protocol("CIP PCCC Object",
10391 "CIPPCCC", "cippccc");
10392 cip_class_pccc_handle = register_dissector("cippccc",
10393 dissect_cip_class_pccc, proto_cip_class_pccc);
10394 proto_register_field_array(proto_cip_class_pccc, hf_pccc, array_length(hf_pccc));
10395 proto_register_subtree_array(ett_pccc, array_length(ett_pccc));
10397 proto_cip_class_mb = proto_register_protocol("CIP Modbus Object",
10398 "CIPMB", "cipmb");
10399 cip_class_mb_handle = register_dissector("cipmb",
10400 dissect_cip_class_mb, proto_cip_class_mb);
10401 proto_register_field_array(proto_cip_class_mb, hf_mb, array_length(hf_mb));
10402 proto_register_subtree_array(ett_mb, array_length(ett_mb));
10404 proto_cip_class_cco = proto_register_protocol("CIP Connection Configuration Object",
10405 "CIPCCO", "cipcco");
10406 cip_class_cco_handle = register_dissector("cipcco",
10407 dissect_cip_class_cco, proto_cip_class_cco);
10408 proto_register_field_array(proto_cip_class_cco, hf_cco, array_length(hf_cco));
10409 proto_register_subtree_array(ett_cco, array_length(ett_cco));
10411 /* Register a heuristic dissector on the service of the message so objects
10412 * can override the dissector for common services */
10413 heur_subdissector_service = register_heur_dissector_list_with_description("cip.sc", "CIP Service data", proto_cip);
10415 build_get_attr_all_table();
10416 } /* end of proto_register_cip() */
10418 void
10419 proto_reg_handoff_cip(void)
10421 /* Register for UCMM CIP data, using EtherNet/IP SendRRData service*/
10422 dissector_add_uint( "enip.srrd.iface", ENIP_CIP_INTERFACE, cip_handle );
10424 dissector_add_uint("cip.connection.class", CI_CLS_MR, cip_handle);
10426 /* Register dissector handle for generic class */
10427 dissector_add_uint( "cip.class.iface", 0, cip_class_generic_handle );
10429 /* Register dissector handle for Connection Manager */
10430 dissector_add_uint( "cip.class.iface", CI_CLS_CM, cip_class_cm_handle );
10432 /* Register dissector handle for the PCCC class */
10433 dissector_add_uint( "cip.class.iface", CI_CLS_PCCC, cip_class_pccc_handle );
10435 /* Register dissector handle for Modbus Object */
10436 dissector_add_uint( "cip.class.iface", CI_CLS_MB, cip_class_mb_handle );
10437 modbus_handle = find_dissector_add_dependency("modbus", proto_cip_class_mb);
10439 /* Register dissector handle for Connection Configuration Object */
10440 dissector_add_uint( "cip.class.iface", CI_CLS_CCO, cip_class_cco_handle );
10441 heur_dissector_add("cip.sc", dissect_class_cco_heur, "CIP Connection Configuration Object", "cco_cip", proto_cip_class_cco, HEURISTIC_ENABLE);
10443 proto_enip = proto_get_id_by_filter_name( "enip" );
10444 proto_modbus = proto_get_id_by_filter_name( "modbus" );
10446 } /* end of proto_reg_handoff_cip() */
10449 * Editor modelines
10451 * Local Variables:
10452 * c-basic-offset: 3
10453 * tab-width: 8
10454 * indent-tabs-mode: nil
10455 * End:
10457 * ex: set shiftwidth=3 tabstop=8 expandtab:
10458 * :indentSize=3:tabSize=8:noTabs=true: