1 /* packet-cip.c
2  * Routines for Common Industrial Protocol (CIP) dissection
3  * CIP Home: www.odva.org
4  *
5  * This dissector includes items from:
6  *    CIP Volume 1: Common Industrial Protocol, Edition 3.30
7  *    CIP Volume 5: Integration of Modbus Devices into the CIP Architecture, Edition 2.17
8  *    CIP Volume 7: CIP Safety, Edition 1.9
9  *    CIP Volume 8: CIP Security, Edition 1.11
10  *
11  * Copyright 2004
12  * Magnus Hansson <mah@hms.se>
13  * Joakim Wiberg <jow@hms.se>
14  *
15  * Added support for Connection Configuration Object
16  *   ryan wamsley * Copyright 2007
17  *
18  * Object dependend services based on IOI
19  *   Jan Bartels, Siempelkamp Maschinen- und Anlagenbau GmbH & Co. KG
20  *   Copyright 2007
21  *
22  * Improved support for CoCo, CM, MB objects
23  * Heuristic object support for common services
24  *   Michael Mann * Copyright 2011
25  *
26  * Added support for PCCC Objects
27  *   Jared Rittle - Cisco Talos
28  *   Copyright 2017
29  *
30  * Wireshark - Network traffic analyzer
31  * By Gerald Combs <gerald@wireshark.org>
32  * Copyright 1998 Gerald Combs
33  *
34  * SPDX-License-Identifier: GPL-2.0-or-later
35  */
36 
37 #include "config.h"
38 
39 #include <epan/packet.h>
40 #include <epan/expert.h>
41 #include <epan/prefs.h>
42 #include <epan/proto_data.h>
43 #include <epan/wmem_scopes.h>
44 #include "packet-cip.h"
45 #include "packet-cipmotion.h"
46 #include "packet-cipsafety.h"
47 #include "packet-mbtcp.h"
48 
49 void proto_register_cip(void);
50 void proto_reg_handoff_cip(void);
51 
52 typedef struct mr_mult_req_info {
53    guint8 service;
54    int num_services;
55    cip_req_info_t *requests;
56 } mr_mult_req_info_t;
57 
58 static dissector_handle_t cip_handle;
59 static dissector_handle_t cip_class_generic_handle;
60 static dissector_handle_t cip_class_cm_handle;
61 static dissector_handle_t cip_class_pccc_handle;
62 static dissector_handle_t modbus_handle;
63 static dissector_handle_t cip_class_cco_handle;
64 static heur_dissector_list_t  heur_subdissector_service;
65 
66 static gboolean cip_enhanced_info_column = TRUE;
67 
68 /* Initialize the protocol and registered fields */
69 static int proto_cip = -1;
70 static int proto_cip_class_generic = -1;
71 static int proto_cip_class_cm = -1;
72 static int proto_cip_class_pccc = -1;
73 static int proto_cip_class_mb = -1;
74 static int proto_cip_class_cco = -1;
75 static int proto_enip = -1;
76 static int proto_modbus = -1;
77 
78 int hf_attr_class_revision = -1;
79 int hf_attr_class_max_instance = -1;
80 int hf_attr_class_num_instance = -1;
81 int hf_attr_class_opt_attr_num = -1;
82 int hf_attr_class_attr_num = -1;
83 int hf_attr_class_opt_service_num = -1;
84 int hf_attr_class_service_code = -1;
85 int hf_attr_class_num_class_attr = -1;
86 int hf_attr_class_num_inst_attr = -1;
87 static int hf_cip_data = -1;
88 static int hf_cip_service = -1;
89 static int hf_cip_service_code = -1;
90 static int hf_cip_reqrsp = -1;
91 static int hf_cip_epath = -1;
92 static int hf_cip_genstat = -1;
93 static int hf_cip_addstat_size = -1;
94 static int hf_cip_add_stat = -1;
95 static int hf_cip_request_path_size = -1;
96 
97 static int hf_cip_cm_sc = -1;
98 static int hf_cip_cm_genstat = -1;
99 static int hf_cip_cm_addstat_size = -1;
100 static int hf_cip_cm_add_status = -1;
101 static int hf_cip_cm_ext_status = -1;
102 static int hf_cip_cm_priority = -1;
103 static int hf_cip_cm_tick_time = -1;
104 static int hf_cip_cm_timeout_tick = -1;
105 static int hf_cip_cm_timeout = -1;
106 static int hf_cip_cm_ot_connid = -1;
107 static int hf_cip_cm_to_connid = -1;
108 static int hf_cip_connid = -1;
109 static int hf_cip_cm_conn_serial_num = -1;
110 static int hf_cip_cm_orig_serial_num = -1;
111 static int hf_cip_cm_vendor = -1;
112 static int hf_cip_cm_timeout_multiplier = -1;
113 static int hf_cip_cm_ot_rpi = -1;
114 static int hf_cip_cm_ot_net_params32 = -1;
115 static int hf_cip_cm_ot_net_params16 = -1;
116 static int hf_cip_cm_to_rpi = -1;
117 static int hf_cip_cm_to_net_params32 = -1;
118 static int hf_cip_cm_to_net_params16 = -1;
119 static int hf_cip_cm_transport_type_trigger = -1;
120 static int hf_cip_cm_conn_path_size = -1;
121 static int hf_cip_cm_ot_api = -1;
122 static int hf_cip_cm_to_api = -1;
123 static int hf_cip_cm_app_reply_size = -1;
124 static int hf_cip_cm_app_reply_data = -1;
125 static int hf_cip_cm_consumer_number = -1;
126 static int hf_cip_cm_targ_vendor_id = -1;
127 static int hf_cip_cm_targ_dev_serial_num = -1;
128 static int hf_cip_cm_targ_conn_serial_num = -1;
129 static int hf_cip_cm_initial_timestamp = -1;
130 static int hf_cip_cm_initial_rollover = -1;
131 static int hf_cip_cm_remain_path_size = -1;
132 static int hf_cip_cm_msg_req_size = -1;
133 static int hf_cip_cm_route_path_size = -1;
134 static int hf_cip_cm_fwo_con_size = -1;
135 static int hf_cip_cm_lfwo_con_size = -1;
136 static int hf_cip_cm_fwo_fixed_var = -1;
137 static int hf_cip_cm_lfwo_fixed_var = -1;
138 static int hf_cip_cm_fwo_prio = -1;
139 static int hf_cip_cm_lfwo_prio = -1;
140 static int hf_cip_cm_fwo_typ = -1;
141 static int hf_cip_cm_lfwo_typ = -1;
142 static int hf_cip_cm_fwo_own = -1;
143 static int hf_cip_cm_lfwo_own = -1;
144 static int hf_cip_cm_fwo_dir = -1;
145 static int hf_cip_cm_fwo_trigg = -1;
146 static int hf_cip_cm_fwo_class = -1;
147 static int hf_cip_cm_gco_conn = -1;
148 static int hf_cip_cm_gco_coo_conn = -1;
149 static int hf_cip_cm_gco_roo_conn = -1;
150 static int hf_cip_cm_gco_last_action = -1;
151 static int hf_cip_cm_ext112_ot_rpi_type = -1;
152 static int hf_cip_cm_ext112_to_rpi_type = -1;
153 static int hf_cip_cm_ext112_ot_rpi = -1;
154 static int hf_cip_cm_ext112_to_rpi = -1;
155 static int hf_cip_cm_ext126_size = -1;
156 static int hf_cip_cm_ext127_size = -1;
157 static int hf_cip_cm_ext128_size = -1;
158 
159 static int hf_cip_pccc_sc = -1;
160 static int hf_cip_pccc_req_id_len = -1;
161 static int hf_cip_pccc_cip_vend_id = -1;
162 static int hf_cip_pccc_cip_serial_num = -1;
163 static int hf_cip_pccc_cmd_code = -1;
164 static int hf_cip_pccc_sts_code = -1;
165 static int hf_cip_pccc_ext_sts_code = -1;
166 static int hf_cip_pccc_tns_code = -1;
167 static int hf_cip_pccc_fnc_code_06 = -1;
168 static int hf_cip_pccc_fnc_code_07 = -1;
169 static int hf_cip_pccc_fnc_code_0f = -1;
170 static int hf_cip_pccc_byte_size = -1;
171 static int hf_cip_pccc_file_num = -1;
172 static int hf_cip_pccc_file_type = -1;
173 static int hf_cip_pccc_element_num = -1;
174 static int hf_cip_pccc_subelement_num = -1;
175 #if 0
176 static int hf_cip_pccc_cpu_mode_3a = -1;
177 #endif
178 static int hf_cip_pccc_cpu_mode_80 = -1;
179 static int hf_cip_pccc_resp_code = -1;
180 static int hf_cip_pccc_execute_multi_count = -1;
181 static int hf_cip_pccc_execute_multi_len = -1;
182 static int hf_cip_pccc_execute_multi_fnc = -1;
183 static int hf_cip_pccc_data = -1;
184 
185 static int hf_cip_mb_sc = -1;
186 static int hf_cip_mb_read_coils_start_addr = -1;
187 static int hf_cip_mb_read_coils_num_coils = -1;
188 static int hf_cip_mb_read_coils_data = -1;
189 static int hf_cip_mb_read_discrete_inputs_start_addr = -1;
190 static int hf_cip_mb_read_discrete_inputs_num_inputs = -1;
191 static int hf_cip_mb_read_discrete_inputs_data = -1;
192 static int hf_cip_mb_read_holding_register_start_addr = -1;
193 static int hf_cip_mb_read_holding_register_num_registers = -1;
194 static int hf_cip_mb_read_holding_register_data = -1;
195 static int hf_cip_mb_read_input_register_start_addr = -1;
196 static int hf_cip_mb_read_input_register_num_registers = -1;
197 static int hf_cip_mb_read_input_register_data = -1;
198 static int hf_cip_mb_write_coils_start_addr = -1;
199 static int hf_cip_mb_write_coils_outputs_forced = -1;
200 static int hf_cip_mb_write_coils_num_coils = -1;
201 static int hf_cip_mb_write_coils_data = -1;
202 static int hf_cip_mb_write_registers_start_addr = -1;
203 static int hf_cip_mb_write_registers_outputs_forced = -1;
204 static int hf_cip_mb_write_registers_num_registers = -1;
205 static int hf_cip_mb_write_registers_data = -1;
206 static int hf_cip_mb_data = -1;
207 
208 static int hf_cip_cco_con_type = -1;
209 static int hf_cip_cco_ot_rtf = -1;
210 static int hf_cip_cco_to_rtf = -1;
211 static int hf_cip_cco_sc = -1;
212 static int hf_cip_cco_format_number = -1;
213 static int hf_cip_cco_edit_signature = -1;
214 static int hf_cip_cco_con_flags = -1;
215 static int hf_cip_cco_tdi_vendor = -1;
216 static int hf_cip_cco_tdi_devtype = -1;
217 static int hf_cip_cco_tdi_prodcode = -1;
218 static int hf_cip_cco_tdi_compatibility = -1;
219 static int hf_cip_cco_tdi_comp_bit = -1;
220 static int hf_cip_cco_tdi_majorrev = -1;
221 static int hf_cip_cco_tdi_minorrev = -1;
222 static int hf_cip_cco_pdi_vendor = -1;
223 static int hf_cip_cco_pdi_devtype = -1;
224 static int hf_cip_cco_pdi_prodcode = -1;
225 static int hf_cip_cco_pdi_compatibility = -1;
226 static int hf_cip_cco_pdi_comp_bit = -1;
227 static int hf_cip_cco_pdi_majorrev = -1;
228 static int hf_cip_cco_pdi_minorrev = -1;
229 static int hf_cip_cco_cs_data_index = -1;
230 static int hf_cip_cco_ot_rpi = -1;
231 static int hf_cip_cco_to_rpi = -1;
232 static int hf_cip_cco_ot_net_param16 = -1;
233 static int hf_cip_cco_to_net_param16 = -1;
234 static int hf_cip_cco_fwo_own = -1;
235 static int hf_cip_cco_fwo_typ = -1;
236 static int hf_cip_cco_fwo_prio = -1;
237 static int hf_cip_cco_fwo_fixed_var = -1;
238 static int hf_cip_cco_fwo_con_size = -1;
239 static int hf_cip_cco_ot_net_param32 = -1;
240 static int hf_cip_cco_to_net_param32 = -1;
241 static int hf_cip_cco_lfwo_own = -1;
242 static int hf_cip_cco_lfwo_typ = -1;
243 static int hf_cip_cco_lfwo_prio = -1;
244 static int hf_cip_cco_lfwo_fixed_var = -1;
245 static int hf_cip_cco_lfwo_con_size = -1;
246 static int hf_cip_cco_conn_path_size = -1;
247 static int hf_cip_cco_proxy_config_size = -1;
248 static int hf_cip_cco_target_config_size = -1;
249 static int hf_cip_cco_iomap_format_number = -1;
250 static int hf_cip_cco_iomap_size = -1;
251 static int hf_cip_cco_connection_disable = -1;
252 static int hf_cip_cco_net_conn_param_attr = -1;
253 static int hf_cip_cco_timeout_multiplier = -1;
254 static int hf_cip_cco_transport_type_trigger = -1;
255 static int hf_cip_cco_fwo_dir = -1;
256 static int hf_cip_cco_fwo_trigger = -1;
257 static int hf_cip_cco_fwo_class = -1;
258 static int hf_cip_cco_proxy_config_data = -1;
259 static int hf_cip_cco_target_config_data = -1;
260 static int hf_cip_cco_iomap_attribute = -1;
261 static int hf_cip_cco_safety = -1;
262 static int hf_cip_cco_change_type = -1;
263 static int hf_cip_cco_connection_name = -1;
264 static int hf_cip_cco_ext_status = -1;
265 
266 static int hf_cip_path_segment = -1;
267 static int hf_cip_path_segment_type = -1;
268 static int hf_cip_port_ex_link_addr = -1;
269 static int hf_cip_port = -1;
270 static int hf_cip_port_extended = -1;
271 static int hf_cip_link_address_size = -1;
272 static int hf_cip_link_address_byte = -1;
273 static int hf_cip_link_address_string = -1;
274 static int hf_cip_logical_seg_type = -1;
275 static int hf_cip_logical_seg_format = -1;
276 static int hf_cip_class8 = -1;
277 static int hf_cip_class16 = -1;
278 static int hf_cip_class32 = -1;
279 static int hf_cip_instance8 = -1;
280 static int hf_cip_instance16 = -1;
281 static int hf_cip_instance32 = -1;
282 static int hf_cip_member8 = -1;
283 static int hf_cip_member16 = -1;
284 static int hf_cip_member32 = -1;
285 static int hf_cip_attribute8 = -1;
286 static int hf_cip_attribute16 = -1;
287 static int hf_cip_attribute32 = -1;
288 static int hf_cip_conpoint8 = -1;
289 static int hf_cip_conpoint16 = -1;
290 static int hf_cip_conpoint32 = -1;
291 static int hf_cip_serviceid8 = -1;
292 static int hf_cip_ekey_format = -1;
293 static int hf_cip_ekey_vendor = -1;
294 static int hf_cip_ekey_devtype = -1;
295 static int hf_cip_ekey_prodcode = -1;
296 static int hf_cip_ekey_compatibility = -1;
297 static int hf_cip_ekey_comp_bit = -1;
298 static int hf_cip_ekey_majorrev = -1;
299 static int hf_cip_ekey_minorrev = -1;
300 static int hf_cip_ekey_serial_number = -1;
301 static int hf_cip_ext_logical8 = -1;
302 static int hf_cip_ext_logical16 = -1;
303 static int hf_cip_ext_logical32 = -1;
304 static int hf_cip_ext_logical_type = -1;
305 static int hf_cip_data_seg_type = -1;
306 static int hf_cip_data_seg_size_simple = -1;
307 static int hf_cip_data_seg_size_extended = -1;
308 static int hf_cip_data_seg_item = -1;
309 static int hf_cip_symbol = -1;
310 static int hf_cip_symbol_size = -1;
311 static int hf_cip_symbol_ascii = -1;
312 static int hf_cip_symbol_extended_format = -1;
313 static int hf_cip_symbol_numeric_format = -1;
314 static int hf_cip_symbol_double_size = -1;
315 static int hf_cip_symbol_triple_size = -1;
316 static int hf_cip_numeric_usint = -1;
317 static int hf_cip_numeric_uint = -1;
318 static int hf_cip_numeric_udint = -1;
319 static int hf_cip_network_seg_type = -1;
320 static int hf_cip_seg_schedule = -1;
321 static int hf_cip_seg_fixed_tag = -1;
322 static int hf_cip_seg_prod_inhibit_time = -1;
323 static int hf_cip_seg_prod_inhibit_time_us = -1;
324 static int hf_cip_seg_network_size = -1;
325 static int hf_cip_seg_network_subtype = -1;
326 static int hf_cip_seg_safety_format = -1;
327 static int hf_cip_seg_safety_reserved = -1;
328 static int hf_cip_seg_safety_configuration_crc = -1;
329 static int hf_cip_seg_safety_configuration_timestamp = -1;
330 static int hf_cip_seg_safety_configuration_date = -1;
331 static int hf_cip_seg_safety_configuration_time = -1;
332 static int hf_cip_seg_safety_time_correction_epi = -1;
333 static int hf_cip_seg_safety_time_correction_net_params = -1;
334 static int hf_cip_seg_safety_time_correction_own = -1;
335 static int hf_cip_seg_safety_time_correction_typ = -1;
336 static int hf_cip_seg_safety_time_correction_prio = -1;
337 static int hf_cip_seg_safety_time_correction_fixed_var = -1;
338 static int hf_cip_seg_safety_time_correction_con_size = -1;
339 static int hf_cip_seg_safety_tunid = -1;
340 static int hf_cip_seg_safety_tunid_snn_timestamp = -1;
341 static int hf_cip_seg_safety_tunid_snn_date = -1;
342 static int hf_cip_seg_safety_tunid_snn_time = -1;
343 static int hf_cip_seg_safety_tunid_nodeid = -1;
344 static int hf_cip_seg_safety_ounid = -1;
345 static int hf_cip_seg_safety_ounid_snn_timestamp = -1;
346 static int hf_cip_seg_safety_ounid_snn_date = -1;
347 static int hf_cip_seg_safety_ounid_snn_time = -1;
348 static int hf_cip_seg_safety_ounid_nodeid = -1;
349 static int hf_cip_seg_safety_ping_eri_multiplier = -1;
350 static int hf_cip_seg_safety_time_coord_msg_min_multiplier = -1;
351 static int hf_cip_seg_safety_network_time_expected_multiplier = -1;
352 static int hf_cip_seg_safety_timeout_multiplier = -1;
353 static int hf_cip_seg_safety_max_consumer_number = -1;
354 static int hf_cip_seg_safety_conn_param_crc = -1;
355 static int hf_cip_seg_safety_time_correction_conn_id = -1;
356 static int hf_cip_seg_safety_max_fault_number = -1;
357 static int hf_cip_seg_safety_init_timestamp = -1;
358 static int hf_cip_seg_safety_init_rollover = -1;
359 static int hf_cip_seg_safety_data = -1;
360 static int hf_cip_class_max_inst32 = -1;
361 static int hf_cip_class_num_inst32 = -1;
362 static int hf_cip_reserved8 = -1;
363 static int hf_cip_reserved24 = -1;
364 static int hf_cip_pad8 = -1;
365 
366 static int hf_cip_sc_get_attr_list_attr_count = -1;
367 static int hf_cip_sc_get_attr_list_attr_status = -1;
368 static int hf_cip_sc_set_attr_list_attr_count = -1;
369 static int hf_cip_sc_set_attr_list_attr_status = -1;
370 static int hf_cip_sc_reset_param = -1;
371 static int hf_cip_sc_create_instance = -1;
372 static int hf_cip_sc_mult_serv_pack_num_services = -1;
373 static int hf_cip_sc_mult_serv_pack_offset = -1;
374 static int hf_cip_find_next_object_max_instance = -1;
375 static int hf_cip_find_next_object_num_instances = -1;
376 static int hf_cip_find_next_object_instance_item = -1;
377 static int hf_cip_sc_group_sync_is_sync = -1;
378 
379 /* Parsed Attributes */
380 static int hf_id_vendor_id = -1;
381 static int hf_id_device_type = -1;
382 static int hf_id_product_code = -1;
383 static int hf_id_major_rev = -1;
384 static int hf_id_minor_rev = -1;
385 static int hf_id_status = -1;
386 static int hf_id_serial_number = -1;
387 static int hf_id_product_name = -1;
388 static int hf_id_state = -1;
389 static int hf_id_config_value = -1;
390 static int hf_id_heartbeat = -1;
391 static int hf_id_status_owned = -1;
392 static int hf_id_status_conf = -1;
393 static int hf_id_status_extended1 = -1;
394 static int hf_id_status_minor_fault_rec = -1;
395 static int hf_id_status_minor_fault_unrec = -1;
396 static int hf_id_status_major_fault_rec = -1;
397 static int hf_id_status_major_fault_unrec = -1;
398 static int hf_id_status_extended2 = -1;
399 static int hf_msg_rout_num_classes = -1;
400 static int hf_msg_rout_classes = -1;
401 static int hf_msg_rout_num_available = -1;
402 static int hf_msg_rout_num_active = -1;
403 static int hf_msg_rout_active_connections = -1;
404 static int hf_conn_mgr_open_requests = -1;
405 static int hf_conn_mgr_open_format_rejects = -1;
406 static int hf_conn_mgr_open_resource_rejects = -1;
407 static int hf_conn_mgr_other_open_rejects = -1;
408 static int hf_conn_mgr_close_requests = -1;
409 static int hf_conn_close_format_requests = -1;
410 static int hf_conn_mgr_close_other_requests = -1;
411 static int hf_conn_mgr_conn_timouts = -1;
412 static int hf_conn_mgr_num_conn_entries = -1;
413 static int hf_conn_mgr_num_conn_entries_bytes = -1;
414 static int hf_conn_mgr_conn_open_bits = -1;
415 static int hf_conn_mgr_cpu_utilization = -1;
416 static int hf_conn_mgr_max_buff_size = -1;
417 static int hf_conn_mgr_buff_size_remaining = -1;
418 static int hf_stringi_number_char = -1;
419 static int hf_stringi_language_char = -1;
420 static int hf_stringi_char_string_struct = -1;
421 static int hf_stringi_char_set = -1;
422 static int hf_stringi_international_string = -1;
423 static int hf_file_filename = -1;
424 static int hf_time_sync_ptp_enable = -1;
425 static int hf_time_sync_is_synchronized = -1;
426 static int hf_time_sync_sys_time_micro = -1;
427 static int hf_time_sync_sys_time_nano = -1;
428 static int hf_time_sync_offset_from_master = -1;
429 static int hf_time_sync_max_offset_from_master = -1;
430 static int hf_time_sync_mean_path_delay_to_master = -1;
431 static int hf_time_sync_gm_clock_clock_id = -1;
432 static int hf_time_sync_gm_clock_clock_class = -1;
433 static int hf_time_sync_gm_clock_time_accuracy = -1;
434 static int hf_time_sync_gm_clock_offset_scaled_log_variance = -1;
435 static int hf_time_sync_gm_clock_current_utc_offset = -1;
436 static int hf_time_sync_gm_clock_time_property_flags = -1;
437 static int hf_time_sync_gm_clock_time_property_flags_leap61 = -1;
438 static int hf_time_sync_gm_clock_time_property_flags_leap59 = -1;
439 static int hf_time_sync_gm_clock_time_property_flags_current_utc_valid = -1;
440 static int hf_time_sync_gm_clock_time_property_flags_ptp_timescale = -1;
441 static int hf_time_sync_gm_clock_time_property_flags_time_traceable = -1;
442 static int hf_time_sync_gm_clock_time_property_flags_freq_traceable = -1;
443 static int hf_time_sync_gm_clock_time_source = -1;
444 static int hf_time_sync_gm_clock_priority1 = -1;
445 static int hf_time_sync_gm_clock_priority2 = -1;
446 static int hf_time_sync_parent_clock_clock_id = -1;
447 static int hf_time_sync_parent_clock_port_number = -1;
448 static int hf_time_sync_parent_clock_observed_offset_scaled_log_variance = -1;
449 static int hf_time_sync_parent_clock_observed_phase_change_rate = -1;
450 static int hf_time_sync_local_clock_clock_id = -1;
451 static int hf_time_sync_local_clock_clock_class = -1;
452 static int hf_time_sync_local_clock_time_accuracy = -1;
453 static int hf_time_sync_local_clock_offset_scaled_log_variance = -1;
454 static int hf_time_sync_local_clock_current_utc_offset = -1;
455 static int hf_time_sync_local_clock_time_property_flags = -1;
456 static int hf_time_sync_local_clock_time_property_flags_leap61 = -1;
457 static int hf_time_sync_local_clock_time_property_flags_leap59 = -1;
458 static int hf_time_sync_local_clock_time_property_flags_current_utc_valid = -1;
459 static int hf_time_sync_local_clock_time_property_flags_ptp_timescale = -1;
460 static int hf_time_sync_local_clock_time_property_flags_time_traceable = -1;
461 static int hf_time_sync_local_clock_time_property_flags_freq_traceable = -1;
462 static int hf_time_sync_local_clock_time_source = -1;
463 static int hf_time_sync_num_ports = -1;
464 static int hf_time_sync_port_state_info_num_ports = -1;
465 static int hf_time_sync_port_state_info_port_num = -1;
466 static int hf_time_sync_port_state_info_port_state = -1;
467 static int hf_time_sync_port_enable_cfg_num_ports = -1;
468 static int hf_time_sync_port_enable_cfg_port_num = -1;
469 static int hf_time_sync_port_enable_cfg_port_enable = -1;
470 static int hf_time_sync_port_log_announce_num_ports = -1;
471 static int hf_time_sync_port_log_announce_port_num = -1;
472 static int hf_time_sync_port_log_announce_interval = -1;
473 static int hf_time_sync_port_log_sync_num_ports = -1;
474 static int hf_time_sync_port_log_sync_port_num = -1;
475 static int hf_time_sync_port_log_sync_port_log_sync_interval = -1;
476 static int hf_time_sync_priority1 = -1;
477 static int hf_time_sync_priority2 = -1;
478 static int hf_time_sync_domain_number = -1;
479 static int hf_time_sync_clock_type = -1;
480 static int hf_time_sync_clock_type_ordinary = -1;
481 static int hf_time_sync_clock_type_boundary = -1;
482 static int hf_time_sync_clock_type_end_to_end = -1;
483 static int hf_time_sync_clock_type_management = -1;
484 static int hf_time_sync_clock_type_slave_only = -1;
485 static int hf_time_sync_manufacture_id_oui = -1;
486 static int hf_time_sync_manufacture_id_reserved = -1;
487 static int hf_time_sync_prod_desc_size = -1;
488 static int hf_time_sync_prod_desc_str = -1;
489 static int hf_time_sync_revision_data_size = -1;
490 static int hf_time_sync_revision_data_str = -1;
491 static int hf_time_sync_user_desc_size = -1;
492 static int hf_time_sync_user_desc_str = -1;
493 static int hf_time_sync_port_profile_id_info_num_ports = -1;
494 static int hf_time_sync_port_profile_id_info_port_num = -1;
495 static int hf_time_sync_port_profile_id_info_profile_id = -1;
496 static int hf_time_sync_port_phys_addr_info_num_ports = -1;
497 static int hf_time_sync_port_phys_addr_info_port_num = -1;
498 static int hf_time_sync_port_phys_addr_info_phys_proto = -1;
499 static int hf_time_sync_port_phys_addr_info_addr_size = -1;
500 static int hf_time_sync_port_phys_addr_info_phys_addr = -1;
501 static int hf_time_sync_port_proto_addr_info_num_ports = -1;
502 static int hf_time_sync_port_proto_addr_info_port_num = -1;
503 static int hf_time_sync_port_proto_addr_info_network_proto = -1;
504 static int hf_time_sync_port_proto_addr_info_addr_size = -1;
505 static int hf_time_sync_port_proto_addr_info_port_proto_addr = -1;
506 static int hf_time_sync_steps_removed = -1;
507 static int hf_time_sync_sys_time_and_offset_time = -1;
508 static int hf_time_sync_sys_time_and_offset_offset = -1;
509 static int hf_port_entry_port = -1;
510 static int hf_port_type = -1;
511 static int hf_port_number = -1;
512 static int hf_port_min_node_num = -1;
513 static int hf_port_max_node_num = -1;
514 static int hf_port_name = -1;
515 static int hf_port_num_comm_object_entries = -1;
516 static int hf_path_len_usint = -1;
517 static int hf_path_len_uint = -1;
518 
519 static int hf_32bitheader = -1;
520 static int hf_32bitheader_roo = -1;
521 static int hf_32bitheader_coo = -1;
522 static int hf_32bitheader_run_idle = -1;
523 
524 static int hf_cip_connection = -1;
525 
526 /* Initialize the subtree pointers */
527 static gint ett_cip = -1;
528 static gint ett_cip_class_generic = -1;
529 static gint ett_cip_class_cm = -1;
530 static gint ett_cip_class_pccc = -1;
531 static gint ett_cip_class_mb = -1;
532 static gint ett_cip_class_cco = -1;
533 
534 static gint ett_path = -1;
535 static gint ett_path_seg = -1;
536 static gint ett_mcsc = -1;
537 static gint ett_cia_path = -1;
538 static gint ett_data_seg = -1;
539 static gint ett_port_path = -1;
540 static gint ett_network_seg = -1;
541 static gint ett_network_seg_safety = -1;
542 static gint ett_network_seg_safety_time_correction_net_params = -1;
543 static gint ett_cip_seg_safety_tunid = -1;
544 static gint ett_cip_seg_safety_tunid_snn = -1;
545 static gint ett_cip_seg_safety_ounid = -1;
546 static gint ett_cip_seg_safety_ounid_snn = -1;
547 
548 static gint ett_rrsc = -1;
549 static gint ett_status_item = -1;
550 static gint ett_add_status_item = -1;
551 static gint ett_cmd_data = -1;
552 
553 static gint ett_cip_get_attributes_all_item = -1;
554 static gint ett_cip_get_attribute_list = -1;
555 static gint ett_cip_get_attribute_list_item = -1;
556 static gint ett_cip_set_attribute_list = -1;
557 static gint ett_cip_set_attribute_list_item = -1;
558 static gint ett_cip_mult_service_packet = -1;
559 static gint ett_cip_msp_offset = -1;
560 
561 static gint ett_cm_rrsc = -1;
562 static gint ett_cm_ncp = -1;
563 static gint ett_cm_mes_req = -1;
564 static gint ett_cm_cmd_data = -1;
565 static gint ett_cm_ttt = -1;
566 static gint ett_cm_add_status_item = -1;
567 static gint ett_cip_cm_pid = -1;
568 static gint ett_cip_cm_safety = -1;
569 
570 static gint ett_pccc_rrsc = -1;
571 static gint ett_pccc_req_id = -1;
572 static gint ett_pccc_cmd_data = -1;
573 
574 static gint ett_mb_rrsc = -1;
575 static gint ett_mb_cmd_data = -1;
576 
577 static gint ett_cco_iomap = -1;
578 static gint ett_cco_con_status = -1;
579 static gint ett_cco_con_flag = -1;
580 static gint ett_cco_tdi = -1;
581 static gint ett_cco_pdi = -1;
582 static gint ett_cco_ncp = -1;
583 static gint ett_cco_rrsc = -1;
584 static gint ett_cco_cmd_data = -1;
585 static gint ett_cco_ttt = -1;
586 
587 static gint ett_time_sync_gm_clock_flags = -1;
588 static gint ett_time_sync_local_clock_flags = -1;
589 static gint ett_time_sync_port_state_info = -1;
590 static gint ett_time_sync_port_enable_cfg = -1;
591 static gint ett_time_sync_port_log_announce = -1;
592 static gint ett_time_sync_port_log_sync = -1;
593 static gint ett_time_sync_clock_type = -1;
594 static gint ett_time_sync_port_profile_id_info = -1;
595 static gint ett_time_sync_port_phys_addr_info = -1;
596 static gint ett_time_sync_port_proto_addr_info = -1;
597 static gint ett_id_status = -1;
598 static gint ett_32bitheader_tree = -1;
599 
600 static gint ett_connection_info = -1;
601 
602 static const unit_name_string units_safety_128us = { " (128 us increment)", " (128 us increments)" };
603 
604 static expert_field ei_mal_identity_revision = EI_INIT;
605 static expert_field ei_mal_identity_status = EI_INIT;
606 static expert_field ei_mal_msg_rout_num_classes = EI_INIT;
607 static expert_field ei_mal_time_sync_gm_clock = EI_INIT;
608 static expert_field ei_mal_time_sync_parent_clock = EI_INIT;
609 static expert_field ei_mal_time_sync_local_clock = EI_INIT;
610 static expert_field ei_mal_time_sync_port_state_info = EI_INIT;
611 static expert_field ei_mal_time_sync_port_state_info_ports = EI_INIT;
612 static expert_field ei_mal_time_sync_port_enable_cfg = EI_INIT;
613 static expert_field ei_mal_time_sync_port_enable_cfg_ports = EI_INIT;
614 static expert_field ei_mal_time_sync_port_log_announce = EI_INIT;
615 static expert_field ei_mal_time_sync_port_log_announce_ports = EI_INIT;
616 static expert_field ei_mal_time_sync_port_log_sync = EI_INIT;
617 static expert_field ei_mal_time_sync_port_log_sync_ports = EI_INIT;
618 static expert_field ei_mal_time_sync_clock_type = EI_INIT;
619 static expert_field ei_mal_time_sync_manufacture_id = EI_INIT;
620 static expert_field ei_mal_time_sync_prod_desc = EI_INIT;
621 static expert_field ei_mal_time_sync_prod_desc_64 = EI_INIT;
622 static expert_field ei_mal_time_sync_prod_desc_size = EI_INIT;
623 static expert_field ei_mal_time_sync_revision_data = EI_INIT;
624 static expert_field ei_mal_time_sync_revision_data_32 = EI_INIT;
625 static expert_field ei_mal_time_sync_revision_data_size = EI_INIT;
626 static expert_field ei_mal_time_sync_user_desc = EI_INIT;
627 static expert_field ei_mal_time_sync_user_desc_128 = EI_INIT;
628 static expert_field ei_mal_time_sync_user_desc_size = EI_INIT;
629 static expert_field ei_mal_time_sync_port_profile_id_info = EI_INIT;
630 static expert_field ei_mal_time_sync_port_profile_id_info_ports = EI_INIT;
631 static expert_field ei_mal_time_sync_port_phys_addr_info = EI_INIT;
632 static expert_field ei_mal_time_sync_port_phys_addr_info_ports = EI_INIT;
633 static expert_field ei_mal_time_sync_port_proto_addr_info = EI_INIT;
634 static expert_field ei_mal_time_sync_port_proto_addr_info_ports = EI_INIT;
635 static expert_field ei_mal_time_sync_sys_time_and_offset = EI_INIT;
636 static expert_field ei_proto_log_seg_format = EI_INIT;
637 static expert_field ei_mal_incomplete_epath = EI_INIT;
638 static expert_field ei_proto_electronic_key_format = EI_INIT;
639 static expert_field ei_proto_special_segment_format = EI_INIT;
640 static expert_field ei_proto_log_seg_type = EI_INIT;
641 static expert_field ei_proto_log_sub_seg_type = EI_INIT;
642 static expert_field ei_proto_ext_string_format = EI_INIT;
643 static expert_field ei_proto_ext_network = EI_INIT;
644 static expert_field ei_proto_seg_type = EI_INIT;
645 static expert_field ei_proto_unsupported_datatype = EI_INIT;
646 static expert_field ei_mal_serv_gal = EI_INIT;
647 static expert_field ei_mal_serv_gal_count = EI_INIT;
648 static expert_field ei_mal_serv_sal = EI_INIT;
649 static expert_field ei_mal_serv_sal_count = EI_INIT;
650 static expert_field ei_mal_msp_services = EI_INIT;
651 static expert_field ei_mal_msp_inv_offset = EI_INIT;
652 static expert_field ei_mal_msp_missing_services = EI_INIT;
653 static expert_field ei_mal_serv_find_next_object = EI_INIT;
654 static expert_field ei_mal_serv_find_next_object_count = EI_INIT;
655 static expert_field ei_mal_rpi_no_data = EI_INIT;
656 static expert_field ei_mal_fwd_close_missing_data = EI_INIT;
657 static expert_field ei_mal_opt_attr_list = EI_INIT;
658 static expert_field ei_mal_opt_service_list = EI_INIT;
659 static expert_field ei_mal_padded_epath_size = EI_INIT;
660 static expert_field ei_mal_missing_string_data = EI_INIT;
661 
662 static dissector_table_t   subdissector_class_table;
663 static dissector_table_t   subdissector_symbol_table;
664 
665 /* Translate function to string - CIP Service codes */
666 static const value_string cip_sc_vals[] = {
667    GENERIC_SC_LIST
668 
669    { 0,                       NULL }
670 };
671 
672 /* Translate function to string - CIP Service codes for CM */
673 static const value_string cip_sc_vals_cm[] = {
674    GENERIC_SC_LIST
675 
676    /* Some class specific services */
677    { SC_CM_FWD_CLOSE,            "Forward Close" },
678    { SC_CM_FWD_OPEN,             "Forward Open" },
679    { SC_CM_UNCON_SEND,           "Unconnected Send" },
680    { SC_CM_LARGE_FWD_OPEN,       "Large Forward Open" },
681    { SC_CM_GET_CONN_DATA,        "Get Connection Data" },
682    { SC_CM_SEARCH_CONN_DATA,     "Search Connection Data" },
683    { SC_CM_GET_CONN_OWNER,       "Get Connection Owner" },
684 
685    { 0,                       NULL }
686 };
687 
688 /* Translate function to string - CIP Service codes for PCCC */
689 static const value_string cip_sc_vals_pccc[] = {
690    GENERIC_SC_LIST
691 
692    /* Some class specific services */
693    { SC_PCCC_EXECUTE_PCCC,     "Execute PCCC" },
694 
695    { 0,                       NULL }
696 };
697 
698 /* Translate function to string - CIP Service codes for MB */
699 static const value_string cip_sc_vals_mb[] = {
700    GENERIC_SC_LIST
701 
702    /* Some class specific services */
703    { SC_MB_READ_DISCRETE_INPUTS,    "Read Discrete" },
704    { SC_MB_READ_COILS,              "Read Coils" },
705    { SC_MB_READ_INPUT_REGISTERS,    "Read Input Registers" },
706    { SC_MB_READ_HOLDING_REGISTERS,  "Read Holding Registers" },
707    { SC_MB_WRITE_COILS,             "Write Coils" },
708    { SC_MB_WRITE_HOLDING_REGISTERS, "Write Holding Registers" },
709    { SC_MB_PASSTHROUGH,             "Modbus Passthrough" },
710 
711    { 0,                       NULL }
712 };
713 
714 /* Translate function to string - CIP Service codes for CCO */
715 static const value_string cip_sc_vals_cco[] = {
716    GENERIC_SC_LIST
717 
718    /* Some class specific services */
719    { SC_CCO_KICK_TIMER,           "Kick Timer" },
720    { SC_CCO_OPEN_CONN,            "Open Connection" },
721    { SC_CCO_CLOSE_CONN,           "Close Connection" },
722    { SC_CCO_STOP_CONN,            "Stop Connection" },
723    { SC_CCO_CHANGE_START,         "Change Start" },
724    { SC_CCO_GET_STATUS,           "Get Status" },
725    { SC_CCO_CHANGE_COMPLETE,      "Change Complete" },
726    { SC_CCO_AUDIT_CHANGE,         "Audit Changes" },
727 
728    { 0,                       NULL }
729 };
730 
731 /* Translate function to string - CIP Request/Response */
732 const value_string cip_sc_rr[] = {
733    { 0,        "Request"  },
734    { 1,        "Response" },
735 
736    { 0,        NULL }
737 };
738 
739 /* Translate function to string - Compatibility */
740 static const value_string cip_com_bit_vals[] = {
741    { 0,        "Bit Cleared" },
742    { 1,        "Bit Set"     },
743 
744    { 0,        NULL          }
745 };
746 
747 const value_string cip_reset_type_vals[] = {
748    { 0,        "Cycle Power" },
749    { 1,        "Factory Default" },
750    { 2,        "Keep Communication Parameters" },
751 
752    { 0,        NULL          }
753 };
754 
755 /* Translate function to string - Connection priority */
756 static const value_string cip_con_prio_vals[] = {
757    { 0,        "Low Priority"  },
758    { 1,        "High Priority" },
759    { 2,        "Scheduled"     },
760    { 3,        "Urgent"        },
761 
762    { 0,        NULL            }
763 };
764 
765 /* Translate function to string - Connection size fixed or variable */
766 static const value_string cip_con_fw_vals[] = {
767    { 0,        "Fixed"    },
768    { 1,        "Variable" },
769 
770    { 0,        NULL       }
771 };
772 
773 /* Translate function to string - Connection owner */
774 static const value_string cip_con_owner_vals[] = {
775    { 0,        "Non-Redundant" },
776    { 1,        "Redundant" },
777 
778    { 0,        NULL        }
779 };
780 
781 /* Translate function to string - Connection direction */
782 static const value_string cip_con_dir_vals[] = {
783    { 0,        "Client" },
784    { 1,        "Server" },
785 
786    { 0,        NULL        }
787 };
788 
789 /* Translate function to string - Connection type*/
790 static const value_string cip_con_vals[] = {
791    { 0,        "Originator" },
792    { 1,        "Target" },
793 
794    { 0,        NULL        }
795 };
796 
797 /* Translate function to string - Production trigger */
798 static const value_string cip_con_trigg_vals[] = {
799    { 0,        "Cyclic" },
800    { 1,        "Change-Of-State" },
801    { 2,        "Application Object" },
802 
803    { 0,        NULL        }
804 };
805 
806 /* Translate function to string - Transport class */
807 static const value_string cip_con_class_vals[] = {
808    { 0,        "0" },
809    { 1,        "1" },
810    { 2,        "2" },
811    { 3,        "3" },
812 
813    { 0,        NULL        }
814 };
815 
816 /* Translate function to string - Connection type */
817 static const value_string cip_con_type_vals[] = {
818    { CONN_TYPE_NULL,        "Null"           },
819    { CONN_TYPE_MULTICAST,   "Multicast"      },
820    { CONN_TYPE_P2P,         "Point to Point" },
821    { CONN_TYPE_RESERVED,    "Reserved"       },
822 
823    { 0,        NULL             }
824 };
825 
826 /* Translate function to string - Timeout Multiplier */
827 static const value_string cip_con_time_mult_vals[] = {
828    { 0,        "*4"   },
829    { 1,        "*8"   },
830    { 2,        "*16"  },
831    { 3,        "*32"  },
832    { 4,        "*64"  },
833    { 5,        "*128" },
834    { 6,        "*256" },
835    { 7,        "*512" },
836 
837    { 0,        NULL    }
838 };
839 
840 /* Translate function to string - Connection Last Action */
841 static const value_string cip_con_last_action_vals[] = {
842    { 0,        "No Owner"           },
843    { 1,        "Owner Is Idle Mode" },
844    { 2,        "Owner Is Run Mode"  },
845    { 255,      "Implementation not supported" },
846 
847    { 0,        NULL             }
848 };
849 
850 /* Translate function to string - real time transfer format type */
851 static const value_string cip_con_rtf_vals[] = {
852    { 0,        "32-bit Header"  },
853    { 1,        "Zero data length idle mode"},
854    { 2,        "Modeless"  },
855    { 3,        "Heartbeat"  },
856    { 5,        "Safety"  },
857 
858    { 0,        NULL             }
859 };
860 
861 /* Translate function to string - CCO change type */
862 static const value_string cip_cco_change_type_vals[] = {
863    { 0,        "Full"           },
864    { 1,        "Incremental"    },
865 
866    { 0,        NULL             }
867 };
868 
869 static const value_string cip_time_sync_clock_class_vals[] = {
870    { 6,        "Primary Reference"          },
871    { 7,        "Primary Reference (Hold)"   },
872    { 52,       "Degraded Reference A (Master only)"  },
873    { 187,      "Degraded Reference B (Master/Slave)" },
874    { 248,      "Default"                    },
875    { 255,      "Slave Only"                 },
876 
877    { 0,        NULL             }
878 };
879 
880 static const value_string cip_time_sync_time_accuracy_vals[] = {
881    { 0x20,   "Accurate to within 25ns"  },
882    { 0x21,   "Accurate to within 100ns" },
883    { 0x22,   "Accurate to within 250ns" },
884    { 0x23,   "Accurate to within 1us"   },
885    { 0x24,   "Accurate to within 2.5us" },
886    { 0x25,   "Accurate to within 10us"  },
887    { 0x26,   "Accurate to within 25us"  },
888    { 0x27,   "Accurate to within 100us" },
889    { 0x28,   "Accurate to within 250us" },
890    { 0x29,   "Accurate to within 1ms"   },
891    { 0x2A,   "Accurate to within 2.5ms" },
892    { 0x2B,   "Accurate to within 10ms"  },
893    { 0x2C,   "Accurate to within 25ms"  },
894    { 0x2D,   "Accurate to within 100ms" },
895    { 0x2E,   "Accurate to within 250ms" },
896    { 0x2F,   "Accurate to within 1s"    },
897    { 0x30,   "Accurate to within 10s"   },
898    { 0x31,   "Accurate to >10s"         },
899    { 0,      NULL             }
900 };
901 
902 static const value_string cip_time_sync_time_source_vals[] = {
903    { 0x10,   "Atomic Clock"        },
904    { 0x20,   "GPS"                 },
905    { 0x30,   "Terrestrial Radio"   },
906    { 0x40,   "PTP"                 },
907    { 0x50,   "NTP"                 },
908    { 0x60,   "Hand Set"            },
909    { 0x90,   "Other"               },
910    { 0xA0,   "Internal Oscillator" },
911    { 0,      NULL             }
912 };
913 
914 static const value_string cip_time_sync_port_state_vals[] = {
915    { 1,      "INITIALIZING" },
916    { 2,      "FAULTY"       },
917    { 3,      "DISABLED"     },
918    { 4,      "LISTENING"    },
919    { 5,      "PRE_MASTER"   },
920    { 6,      "MASTER"       },
921    { 7,      "PASSIVE"      },
922    { 8,      "UNCALIBRATED" },
923    { 9,      "SLAVE"        },
924    { 0,      NULL           }
925 };
926 
927 static const value_string cip_time_sync_network_protocol_vals[] = {
928    { 1,      "UDP/IPv4"     },
929    { 2,      "UDP/IPv6"     },
930    { 3,      "IEEE 802.3"   },
931    { 4,      "DeviceNet"    },
932    { 5,      "ControlNet"   },
933    { 0xFFFF, "Local or Unknown protocol"   },
934    { 0,      NULL           }
935 };
936 
937 static const value_string cip_path_seg_vals[] = {
938    { ((CI_PORT_SEGMENT>>5)&7),       "Port Segment" },
939    { ((CI_LOGICAL_SEGMENT>>5)&7),    "Logical Segment" },
940    { ((CI_NETWORK_SEGMENT>>5)&7),    "Network Segment" },
941    { ((CI_SYMBOLIC_SEGMENT>>5)&7),   "Symbolic Segment" },
942    { ((CI_DATA_SEGMENT>>5)&7),       "Data Segment" },
943    { 5,             "Constructed Data Type" },
944    { 6,             "Elementary Data Type" },
945    { 7,             "Reserved" },
946 
947    { 0,                          NULL }
948 };
949 
950 static const value_string cip_logical_segment_type_vals[] = {
951    { ((CI_LOGICAL_SEG_CLASS_ID>>2)&7),      "Class ID" },
952    { ((CI_LOGICAL_SEG_INST_ID>>2)&7),       "Instance ID" },
953    { ((CI_LOGICAL_SEG_MBR_ID>>2)&7),        "Member ID" },
954    { ((CI_LOGICAL_SEG_CON_POINT>>2)&7),     "Connection Point" },
955    { ((CI_LOGICAL_SEG_ATTR_ID>>2)&7),       "Attribute ID" },
956    { ((CI_LOGICAL_SEG_SPECIAL>>2)&7),       "Special" },
957    { ((CI_LOGICAL_SEG_SERV_ID>>2)&7),       "Service ID" },
958    { ((CI_LOGICAL_SEG_EXT_LOGICAL>>2)&7),   "Extended Logical" },
959 
960    { 0,                          NULL }
961 };
962 
963 static const value_string cip_logical_segment_format_vals[] = {
964    { CI_LOGICAL_SEG_8_BIT,           "8-bit Logical Segment" },
965    { CI_LOGICAL_SEG_16_BIT,          "16-bit Logical Segment" },
966    { CI_LOGICAL_SEG_32_BIT,          "32-bit Logical Segment" },
967    { CI_LOGICAL_SEG_RES_2,           "Reserved" },
968 
969    { 0,                          NULL }
970 };
971 
972 static const value_string cip_logical_seg_vals[] = {
973    {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Class Segment"},
974    {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Class Segment"},
975    {((CI_LOGICAL_SEG_CLASS_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Class Segment"},
976 
977    {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Instance Segment"},
978    {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Instance Segment"},
979    {((CI_LOGICAL_SEG_INST_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Instance Segment"},
980 
981    {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Member Segment"},
982    {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Member Segment"},
983    {((CI_LOGICAL_SEG_MBR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Member Segment"},
984 
985    {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Connection Point Segment"},
986    {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Connection Point Segment"},
987    {((CI_LOGICAL_SEG_CON_POINT & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Connection Point Segment"},
988 
989    {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_8_BIT), "8-Bit Attribute Segment"},
990    {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_16_BIT), "16-Bit Attribute Segment"},
991    {((CI_LOGICAL_SEG_ATTR_ID & CI_LOGICAL_SEG_TYPE_MASK)|CI_LOGICAL_SEG_32_BIT), "32-Bit Attribute Segment"},
992 
993    {((CI_LOGICAL_SEG_SERV_ID & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_8_BIT), "8-Bit Service ID Segment"},
994 
995    {CI_LOGICAL_SEG_SPECIAL, "Electronic Key Segment"},
996 
997    {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_8_BIT), "8-Bit Extended Logical Segment"},
998    {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_16_BIT), "16-Bit Extended Logical Segment"},
999    {((CI_LOGICAL_SEG_EXT_LOGICAL & CI_LOGICAL_SEG_TYPE_MASK) | CI_LOGICAL_SEG_32_BIT), "32-Bit Extended Logical Segment"},
1000 
1001    { 0,                          NULL }
1002 };
1003 
1004 static const value_string cip_ext_logical_segment_format_vals[] = {
1005     { 0,          "Reserved" },
1006     { 1,          "Array Index" },
1007     { 2,          "Indirect Array Index" },
1008     { 3,          "Bit Index" },
1009     { 4,          "Indirect Bit Index" },
1010     { 5,          "Structure Member Number" },
1011     { 6,          "Structure Member Handle" },
1012 
1013     { 0,                          NULL }
1014 };
1015 
1016 static const value_string cip_data_segment_type_vals[] = {
1017    {CI_DATA_SEG_SIMPLE, "Simple Data Segment"},
1018    {CI_DATA_SEG_SYMBOL, "ANSI Extended Symbol Segment"},
1019 
1020    { 0,                          NULL }
1021 };
1022 
1023 static const value_string cip_network_segment_type_vals[] = {
1024    {CI_NETWORK_SEG_SCHEDULE,     "Schedule Segment"},
1025    {CI_NETWORK_SEG_FIXED_TAG,    "Fixed Tag Segment"},
1026    {CI_NETWORK_SEG_PROD_INHI,    "Production Inhibit Time in Milliseconds"},
1027    {CI_NETWORK_SEG_SAFETY,       "Safety Segment"},
1028    {CI_NETWORK_SEG_PROD_INHI_US, "Production Inhibit Time in Microseconds"},
1029    {CI_NETWORK_SEG_EXTENDED,     "Extended Network Segment"},
1030 
1031    { 0,                          NULL }
1032 };
1033 
1034 static const value_string cip_symbolic_format_vals[] = {
1035     { 1,          "Double Byte Segment" },
1036     { 2,          "Triple Byte Segment" },
1037     { 6,          "Numeric Segment" },
1038 
1039     { 0,          NULL }
1040 };
1041 
1042 static const value_string cip_symbolic_numeric_format_vals[] = {
1043     { 6,          "USINT" },
1044     { 7,          "UINT" },
1045     { 8,          "UDINT" },
1046 
1047     { 0,          NULL }
1048 };
1049 
1050 static const value_string cip_safety_segment_format_type_vals[] = {
1051    {0,    "Target Format"},
1052    {1,    "Router Format"},
1053    {2,    "Extended Format"},
1054 
1055    { 0,                          NULL }
1056 };
1057 
1058 static const value_string cip_cm_rpi_type_vals[] = {
1059    {0,   "RPI acceptable"},
1060    {1,   "Unspecified"},
1061    {2,   "Minimum acceptable RPI"},
1062    {3,   "Maximum acceptable RPI"},
1063    {4,   "Required RPI to correct mismatch"},
1064 
1065    { 0,                          NULL }
1066 };
1067 
1068 /* Translate function to string - CIP General Status codes */
1069 static const value_string cip_gs_vals[] = {
1070    { CI_GRC_SUCCESS,             "Success" },
1071    { CI_GRC_FAILURE,             "Connection failure" },
1072    { CI_GRC_NO_RESOURCE,         "Resource unavailable" },
1073    { CI_GRC_BAD_DATA,            "Invalid parameter value" },
1074    { CI_GRC_BAD_PATH,            "Path segment error" },
1075    { CI_GRC_BAD_CLASS_INSTANCE,  "Path destination unknown" },
1076    { CI_GRC_PARTIAL_DATA,        "Partial transfer" },
1077    { CI_GRC_CONN_LOST,           "Connection lost" },
1078    { CI_GRC_BAD_SERVICE,         "Service not supported" },
1079    { CI_GRC_BAD_ATTR_DATA,       "Invalid attribute value" },
1080    { CI_GRC_ATTR_LIST_ERROR,     "Attribute list error" },
1081    { CI_GRC_ALREADY_IN_MODE,     "Already in requested mode/state" },
1082    { CI_GRC_BAD_OBJ_MODE,        "Object state conflict" },
1083    { CI_GRC_OBJ_ALREADY_EXISTS,  "Object already exists" },
1084    { CI_GRC_ATTR_NOT_SETTABLE,   "Attribute not settable" },
1085    { CI_GRC_PERMISSION_DENIED,   "Privilege violation" },
1086    { CI_GRC_DEV_IN_WRONG_STATE,  "Device state conflict" },
1087    { CI_GRC_REPLY_DATA_TOO_LARGE,"Reply data too large" },
1088    { CI_GRC_FRAGMENT_PRIMITIVE,  "Fragmentation of a primitive value" },
1089    { CI_GRC_CONFIG_TOO_SMALL,    "Not enough data" },
1090    { CI_GRC_UNDEFINED_ATTR,      "Attribute not supported" },
1091    { CI_GRC_CONFIG_TOO_BIG,      "Too much data" },
1092    { CI_GRC_OBJ_DOES_NOT_EXIST,  "Object does not exist" },
1093    { CI_GRC_NO_FRAGMENTATION,    "Service fragmentation sequence not in progress" },
1094    { CI_GRC_DATA_NOT_SAVED,      "No stored attribute data" },
1095    { CI_GRC_DATA_WRITE_FAILURE,  "Store operation failure" },
1096    { CI_GRC_REQUEST_TOO_LARGE,   "Routing failure, request packet too large" },
1097    { CI_GRC_RESPONSE_TOO_LARGE,  "Routing failure, response packet too large" },
1098    { CI_GRC_MISSING_LIST_DATA,   "Missing attribute list entry data" },
1099    { CI_GRC_INVALID_LIST_STATUS, "Invalid attribute value list" },
1100    { CI_GRC_SERVICE_ERROR,       "Embedded service error" },
1101    { CI_GRC_CONN_RELATED_FAILURE,"Vendor specific error" },
1102    { CI_GRC_INVALID_PARAMETER,   "Invalid parameter" },
1103    { CI_GRC_WRITE_ONCE_FAILURE,  "Write-once value or medium already written" },
1104    { CI_GRC_INVALID_REPLY,       "Invalid reply received" },
1105    { CI_GRC_BUFFER_OVERFLOW,     "Buffer overflow" },
1106    { CI_GRC_MESSAGE_FORMAT,      "Invalid message format" },
1107    { CI_GRC_BAD_KEY_IN_PATH,     "Key failure in path" },
1108    { CI_GRC_BAD_PATH_SIZE,       "Path size invalid" },
1109    { CI_GRC_UNEXPECTED_ATTR,     "Unexpected attribute in list" },
1110    { CI_GRC_INVALID_MEMBER,      "Invalid Member ID" },
1111    { CI_GRC_MEMBER_NOT_SETTABLE, "Member not settable" },
1112    { CI_GRC_G2_SERVER_FAILURE,   "Group 2 only server general failure" },
1113    { CI_GRC_UNKNOWN_MB_ERROR,    "Unknown Modbus error" },
1114    { CI_GRC_ATTRIBUTE_NOT_GET,   "Attribute not gettable" },
1115 
1116    { 0,                          NULL }
1117 };
1118 
1119 value_string_ext cip_gs_vals_ext = VALUE_STRING_EXT_INIT(cip_gs_vals);
1120 
1121 /* Connection Manager Extended Status codes */
1122 #define CM_ES_DUP_FWD_OPEN                            0x100
1123 #define CM_ES_CLASS_AND_TRIGGER                       0x103
1124 #define CM_ES_OWNERSHIP_CONFLICT                      0x106
1125 #define CM_ES_TARGET_CONN_NOT_FOUND                   0x107
1126 #define CM_ES_INVALID_NET_CONN_PARAM                  0x108
1127 #define CM_ES_INVALID_CONNECTION_SIZE                 0x109
1128 #define CM_ES_TARGET_CONNECTION_NOT_CONFIGURED        0x110
1129 #define CM_ES_RPI_NOT_SUPPORTED                       0x111
1130 #define CM_ES_RPI_NOT_ACCEPTABLE                      0x112
1131 #define CM_ES_OUT_OF_CONNECTIONS                      0x113
1132 #define CM_ES_VENDOR_ID_OR_PRODUCT_CODE_MISMATCH      0x114
1133 #define CM_ES_DEVICE_TYPE_MISMATCH                    0x115
1134 #define CM_ES_REVISION_MISMATCH                       0x116
1135 #define CM_ES_INVALID_PROD_CONS_APP_PATH              0x117
1136 #define CM_ES_INVALID_OR_INCONSISTENT_CONF_APP_PATH   0x118
1137 #define CM_ES_NON_LISTEN_ONLY_CONN_NOT_OPENED         0x119
1138 #define CM_ES_TARGET_OBJECT_OUT_OF_CONNECTIONS        0x11A
1139 #define CM_ES_RPI_SMALLER_THAN_PROD_INHIBIT_TIME      0x11B
1140 #define CM_ES_TRANSPORT_CLASS_NOT_SUPPORTED           0x11C
1141 #define CM_ES_PRODUCTION_TRIGGER_NOT_SUPPORTED        0x11D
1142 #define CM_ES_DIRECTION_NOT_SUPPORTED                 0x11E
1143 #define CM_ES_INVALID_OT_NET_CONN_FIX_VAR             0x11F
1144 #define CM_ES_INVALID_TO_NET_CONN_FIX_VAR             0x120
1145 #define CM_ES_INVALID_OT_NET_CONN_PRIORITY            0x121
1146 #define CM_ES_INVALID_TO_NET_CONN_PRIORITY            0x122
1147 #define CM_ES_INVALID_OT_NET_CONN_TYPE                0x123
1148 #define CM_ES_INVALID_TO_NET_CONN_TYPE                0x124
1149 #define CM_ES_INVALID_OT_NET_CONN_REDUNDANT_OWNER     0x125
1150 #define CM_ES_INVALID_CONFIGURATION_SIZE              0x126
1151 #define CM_ES_INVALID_OT_SIZE                         0x127
1152 #define CM_ES_INVALID_TO_SIZE                         0x128
1153 #define CM_ES_INVALID_CONFIGURATION_APP_PATH          0x129
1154 #define CM_ES_INVALID_CONSUMING_APP_PATH              0x12A
1155 #define CM_ES_INVALID_PRODUCING_APP_PATH              0x12B
1156 #define CM_ES_CONFIGURATION_SYMBOL_NOT_EXIST          0x12C
1157 #define CM_ES_CONSUMING_SYMBOL_NOT_EXIST              0x12D
1158 #define CM_ES_PRODUCING_SYMBOL_NOT_EXIST              0x12E
1159 #define CM_ES_INCONSISTENT_APP_PATH_COMBO             0x12F
1160 #define CM_ES_INCONSISTENT_CONSUME_DATA_FORMAT        0x130
1161 #define CM_ES_INCONSISTENT_PRODUCE_DATA_FORMAT        0x131
1162 #define CM_ES_NULL_FORWARD_OPEN_NOT_SUPPORTED         0x132
1163 #define CM_ES_CONNECTION_TIMED_OUT                    0x203
1164 #define CM_ES_UNCONNECTED_REQUEST_TIMED_OUT           0x204
1165 #define CM_ES_PARAMETER_ERROR_IN_UNCONNECTED_REQUEST  0x205
1166 #define CM_ES_MESSAGE_TOO_LARGE_FOR_UNCONNECTED_SEND  0x206
1167 #define CM_ES_UNCONNECTED_ACK_WITHOUT_REPLY           0x207
1168 #define CM_ES_NO_BUFFER_MEMORY_AVAILABLE              0x301
1169 #define CM_ES_NETWORK_BANDWIDTH_NOT_AVAIL_FOR_DATA    0x302
1170 #define CM_ES_NO_CONSUMED_CONN_ID_FILTER_AVAILABLE    0x303
1171 #define CM_ES_NOT_CONFIGURED_TO_SEND_SCHEDULED_DATA   0x304
1172 #define CM_ES_SCHEDULE_SIGNATURE_MISMATCH             0x305
1173 #define CM_ES_SCHEDULE_SIGNATURE_VALIDATION_NOT_POSS  0x306
1174 #define CM_ES_PORT_NOT_AVAILABLE                      0x311
1175 #define CM_ES_LINK_ADDRESS_NOT_VALID                  0x312
1176 #define CM_ES_INVALID_SEGMENT_IN_CONN_PATH            0x315
1177 #define CM_ES_FWD_CLOSE_CONN_PATH_MISMATCH            0x316
1178 #define CM_ES_SCHEDULING_NOT_SPECIFIED                0x317
1179 #define CM_ES_LINK_ADDRESS_TO_SELF_INVALID            0x318
1180 #define CM_ES_SECONDARY_RESOURCES_UNAVAILABLE         0x319
1181 #define CM_ES_RACK_CONNECTION_ALREADY_ESTABLISHED     0x31A
1182 #define CM_ES_MODULE_CONNECTION_ALREADY_ESTABLISHED   0x31B
1183 #define CM_ES_MISCELLANEOUS                           0x31C
1184 #define CM_ES_REDUNDANT_CONNECTION_MISMATCH           0x31D
1185 #define CM_ES_NO_CONSUMER_RES_AVAIL_IN_PROD_MODULE    0x31E
1186 #define CM_ES_NO_CONSUMER_RES_CONF_IN_PROD_MODULE     0x31F
1187 #define CM_ES_NETWORK_LINK_OFFLINE                    0x800
1188 #define CM_ES_INCOMPATIBLE_MULTICAST_RPI              0x801
1189 #define CM_ES_INVALID_SAFETY_CONN_SIZE                0x802
1190 #define CM_ES_INVALID_SAFETY_CONN_FORMAT              0x803
1191 #define CM_ES_INVALID_TIME_CORRECTION_CONN_PARAM      0x804
1192 #define CM_ES_INVALID_PING_INTERVAL_EPI_MULTIPLIER    0x805
1193 #define CM_ES_TIME_COORDINATION_MSG_MIN_MULTIPLIER    0x806
1194 #define CM_ES_NETWORK_TIME_EXPECTATION_MULTIPLIER     0x807
1195 #define CM_ES_TIMEOUT_MULTIPLIER                      0x808
1196 #define CM_ES_INVALID_MAX_CONSUMER_NUMBER             0x809
1197 #define CM_ES_INVALID_CPCRC                           0x80A
1198 #define CM_ES_TIME_CORRECTION_CONN_ID_INVALID         0x80B
1199 #define CM_ES_SCID_MISMATCH                           0x80C
1200 #define CM_ES_TUNID_NOT_SET                           0x80D
1201 #define CM_ES_TUNID_MISMATCH                          0x80E
1202 #define CM_ES_CONFIGURATION_OPERATION_NOT_ALLOWED     0x80F
1203 #define CM_ES_NO_TARGET_APP_DATA_AVAILABLE            0x810
1204 #define CM_ES_NO_ORIG_APP_DATA_AVAILABLE              0x811
1205 #define CM_ES_NODE_ADDRESS_CHANGED_AFTER_SCHEDULED    0x812
1206 #define CM_ES_NOT_CONFIGURED_MULTICAST                0x813
1207 #define CM_ES_INVALID_PROD_CONS_DATA_FORMAT           0x814
1208 
1209 /* Translate function to string - CIP Extended Status codes */
1210 static const value_string cip_cm_ext_st_vals[] = {
1211    { CM_ES_DUP_FWD_OPEN,                           "Connection in use or duplicate Forward Open" },
1212    { CM_ES_CLASS_AND_TRIGGER,                      "Transport class and trigger combination not supported" },
1213    { CM_ES_OWNERSHIP_CONFLICT,                     "Ownership conflict" },
1214    { CM_ES_TARGET_CONN_NOT_FOUND,                  "Target connection not found" },
1215    { CM_ES_INVALID_NET_CONN_PARAM,                 "Invalid network connection parameter" },
1216    { CM_ES_INVALID_CONNECTION_SIZE,                "Invalid connection size" },
1217    { CM_ES_TARGET_CONNECTION_NOT_CONFIGURED,       "Target for connection not configured" },
1218    { CM_ES_RPI_NOT_SUPPORTED,                      "RPI not supported" },
1219    { CM_ES_RPI_NOT_ACCEPTABLE,                     "RPI value(s) not acceptable" },
1220    { CM_ES_OUT_OF_CONNECTIONS,                     "Out of connections" },
1221    { CM_ES_VENDOR_ID_OR_PRODUCT_CODE_MISMATCH,     "Vendor ID or product code mismatch" },
1222    { CM_ES_DEVICE_TYPE_MISMATCH,                   "Device type mismatch" },
1223    { CM_ES_REVISION_MISMATCH,                      "Revision mismatch" },
1224    { CM_ES_INVALID_PROD_CONS_APP_PATH,             "Invalid produced or consumed application path" },
1225    { CM_ES_INVALID_OR_INCONSISTENT_CONF_APP_PATH,  "Invalid or inconsistent configuration application path" },
1226    { CM_ES_NON_LISTEN_ONLY_CONN_NOT_OPENED,        "Non-listen only connection not opened" },
1227    { CM_ES_TARGET_OBJECT_OUT_OF_CONNECTIONS,       "Target object out of connections" },
1228    { CM_ES_RPI_SMALLER_THAN_PROD_INHIBIT_TIME,     "RPI is smaller than the production inhibit time" },
1229    { CM_ES_TRANSPORT_CLASS_NOT_SUPPORTED,          "Transport class not supported" },
1230    { CM_ES_PRODUCTION_TRIGGER_NOT_SUPPORTED,       "Production trigger not supported" },
1231    { CM_ES_DIRECTION_NOT_SUPPORTED,                "Direction not supported" },
1232    { CM_ES_INVALID_OT_NET_CONN_FIX_VAR,            "Invalid O->T Fixed/Variable" },
1233    { CM_ES_INVALID_TO_NET_CONN_FIX_VAR,            "Invalid T->O Fixed/Variable" },
1234    { CM_ES_INVALID_OT_NET_CONN_PRIORITY,           "Invalid O->T Priority" },
1235    { CM_ES_INVALID_TO_NET_CONN_PRIORITY,           "Invalid T->O Priority" },
1236    { CM_ES_INVALID_OT_NET_CONN_TYPE,               "Invalid O->T connection type" },
1237    { CM_ES_INVALID_TO_NET_CONN_TYPE,               "Invalid T->O connection type" },
1238    { CM_ES_INVALID_OT_NET_CONN_REDUNDANT_OWNER,    "Invalid O->T redundant owner" },
1239    { CM_ES_INVALID_CONFIGURATION_SIZE,             "Invalid configuration size" },
1240    { CM_ES_INVALID_OT_SIZE,                        "Invalid O->T size" },
1241    { CM_ES_INVALID_TO_SIZE,                        "Invalid T->O size" },
1242    { CM_ES_INVALID_CONFIGURATION_APP_PATH,         "Invalid configuration application path" },
1243    { CM_ES_INVALID_CONSUMING_APP_PATH,             "Invalid consuming application path" },
1244    { CM_ES_INVALID_PRODUCING_APP_PATH,             "Invalid producing application path" },
1245    { CM_ES_CONFIGURATION_SYMBOL_NOT_EXIST,         "Configuration symbol does not exist" },
1246    { CM_ES_CONSUMING_SYMBOL_NOT_EXIST,             "Consuming symbol does not exist" },
1247    { CM_ES_PRODUCING_SYMBOL_NOT_EXIST,             "Producing symbol does not exist" },
1248    { CM_ES_INCONSISTENT_APP_PATH_COMBO,            "Inconsistent application path combination" },
1249    { CM_ES_INCONSISTENT_CONSUME_DATA_FORMAT,       "Inconsistent consume data format" },
1250    { CM_ES_INCONSISTENT_PRODUCE_DATA_FORMAT,       "Inconsistent produce data format" },
1251    { CM_ES_NULL_FORWARD_OPEN_NOT_SUPPORTED,        "NULL ForwardOpen not supported" },
1252    { CM_ES_CONNECTION_TIMED_OUT,                   "Connection timed out" },
1253    { CM_ES_UNCONNECTED_REQUEST_TIMED_OUT,          "Unconnected request timed out" },
1254    { CM_ES_PARAMETER_ERROR_IN_UNCONNECTED_REQUEST, "Parameter error in unconnected request" },
1255    { CM_ES_MESSAGE_TOO_LARGE_FOR_UNCONNECTED_SEND, "Message too large for UnconnectedSend" },
1256    { CM_ES_UNCONNECTED_ACK_WITHOUT_REPLY,          "Unconnected acknowledged without reply" },
1257    { CM_ES_NO_BUFFER_MEMORY_AVAILABLE,             "No buffer memory available" },
1258    { CM_ES_NETWORK_BANDWIDTH_NOT_AVAIL_FOR_DATA,   "Network bandwidth not available for data" },
1259    { CM_ES_NO_CONSUMED_CONN_ID_FILTER_AVAILABLE,   "No consumed connection ID filter available" },
1260    { CM_ES_NOT_CONFIGURED_TO_SEND_SCHEDULED_DATA,  "Not configured to send scheduled priority data" },
1261    { CM_ES_SCHEDULE_SIGNATURE_MISMATCH,            "Schedule signature mismatch" },
1262    { CM_ES_SCHEDULE_SIGNATURE_VALIDATION_NOT_POSS, "Schedule signature validation not possible" },
1263    { CM_ES_PORT_NOT_AVAILABLE,                     "Port not available" },
1264    { CM_ES_LINK_ADDRESS_NOT_VALID,                 "Link address not valid" },
1265    { CM_ES_INVALID_SEGMENT_IN_CONN_PATH,           "Invalid segment in connection path" },
1266    { CM_ES_FWD_CLOSE_CONN_PATH_MISMATCH,           "ForwardClose connection path mismatch" },
1267    { CM_ES_SCHEDULING_NOT_SPECIFIED,               "Scheduling not specified" },
1268    { CM_ES_LINK_ADDRESS_TO_SELF_INVALID,           "Link address to self invalid" },
1269    { CM_ES_SECONDARY_RESOURCES_UNAVAILABLE,        "Secondary resources unavailable" },
1270    { CM_ES_RACK_CONNECTION_ALREADY_ESTABLISHED,    "Rack connection already established" },
1271    { CM_ES_MODULE_CONNECTION_ALREADY_ESTABLISHED,  "Module connection already established" },
1272    { CM_ES_MISCELLANEOUS,                          "Miscellaneous" },
1273    { CM_ES_REDUNDANT_CONNECTION_MISMATCH,          "Redundant connection mismatch" },
1274    { CM_ES_NO_CONSUMER_RES_AVAIL_IN_PROD_MODULE,   "No more user configurable link consumer resources available in the producing module" },
1275    { CM_ES_NO_CONSUMER_RES_CONF_IN_PROD_MODULE,    "No more user configurable link consumer resources configured in the producing module" },
1276    { CM_ES_NETWORK_LINK_OFFLINE,                   "Network link offline" },
1277    { CM_ES_INCOMPATIBLE_MULTICAST_RPI,             "Incompatible Multicast RPI" },
1278    { CM_ES_INVALID_SAFETY_CONN_SIZE,               "Invalid Safety Connection Size" },
1279    { CM_ES_INVALID_SAFETY_CONN_FORMAT,             "Invalid Safety Connection Format" },
1280    { CM_ES_INVALID_TIME_CORRECTION_CONN_PARAM,     "Invalid Time Correction Connection Parameters" },
1281    { CM_ES_INVALID_PING_INTERVAL_EPI_MULTIPLIER,   "Invalid Ping Interval EPI Multiplier" },
1282    { CM_ES_TIME_COORDINATION_MSG_MIN_MULTIPLIER,   "Time Coordination Msg Min Multiplier" },
1283    { CM_ES_NETWORK_TIME_EXPECTATION_MULTIPLIER,    "Network Time Expectation Multiplier" },
1284    { CM_ES_TIMEOUT_MULTIPLIER,                     "Timeout Multiplier" },
1285    { CM_ES_INVALID_MAX_CONSUMER_NUMBER,            "Invalid Max Consumer Number" },
1286    { CM_ES_INVALID_CPCRC,                          "Invalid CPCRC" },
1287    { CM_ES_TIME_CORRECTION_CONN_ID_INVALID,        "Time Correction Connection ID Invalid" },
1288    { CM_ES_SCID_MISMATCH,                          "SCID Mismatch" },
1289    { CM_ES_TUNID_NOT_SET,                          "TUNID not set" },
1290    { CM_ES_TUNID_MISMATCH,                         "TUNID Mismatch" },
1291    { CM_ES_CONFIGURATION_OPERATION_NOT_ALLOWED,    "Configuration operation not allowed" },
1292    { CM_ES_NO_TARGET_APP_DATA_AVAILABLE,           "No target application data available" },
1293    { CM_ES_NO_ORIG_APP_DATA_AVAILABLE,             "No originator application data available" },
1294    { CM_ES_NODE_ADDRESS_CHANGED_AFTER_SCHEDULED,   "Node address has changed since the network was scheduled" },
1295    { CM_ES_NOT_CONFIGURED_MULTICAST,               "Not configured for off-subnet multicast" },
1296    { CM_ES_INVALID_PROD_CONS_DATA_FORMAT,          "Invalid produce/consume data format" },
1297 
1298    { 0,                          NULL }
1299 };
1300 
1301 value_string_ext cip_cm_ext_st_vals_ext = VALUE_STRING_EXT_INIT(cip_cm_ext_st_vals);
1302 
1303 /* Translate function to string - PCCC Status codes */
1304 static const value_string cip_pccc_gs_st_vals[] = {
1305    { PCCC_GS_SUCCESS,                         "Success" },
1306    { PCCC_GS_ILLEGAL_CMD,                     "Illegal command or format" },
1307    { PCCC_GS_HOST_COMMS,                      "Host has a problem and will not communicate" },
1308    { PCCC_GS_MISSING_REMOTE_NODE,             "Remote node host is missing, disconnected, or shut down" },
1309    { PCCC_GS_HARDWARE_FAULT,                  "Host could not complete function due to hardware fault" },
1310    { PCCC_GS_ADDRESSING_ERROR,                "Addressing problem or memory protect rungs" },
1311    { PCCC_GS_CMD_PROTECTION,                  "Function not allowed due to command protection selection" },
1312    { PCCC_GS_PROGRAM_MODE,                    "Processor is in Program mode" },
1313    { PCCC_GS_MISSING_COMPATABILITY_FILE,      "Compatibility mode file missing or communication zone problem" },
1314    { PCCC_GS_BUFFER_FULL_1,                   "Remote node cannot buffer command" },
1315    { PCCC_GS_WAIT_ACK,                        "Wait ACK (1775-KA buffer full)" },
1316    { PCCC_GS_REMOTE_DOWNLOAD_ERROR,           "Remote node problem due to download" },
1317    { PCCC_GS_BUFFER_FULL_2,                   "Wait ACK (1775-KA buffer full)" },
1318    { PCCC_GS_NOT_USED_1,                      "Not used" },
1319    { PCCC_GS_NOT_USED_2,                      "Not used" },
1320    { PCCC_GS_USE_EXTSTS,                      "Error code in the EXT STS byte" },
1321 
1322    { 0,                          NULL }
1323 };
1324 
1325 static value_string_ext cip_pccc_gs_st_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_gs_st_vals);
1326 
1327 /* Translate function to string - PCCC Extended Status codes */
1328 static const value_string cip_pccc_es_st_vals[] = {
1329    { PCCC_ES_ILLEGAL_VALUE,                        "A field has an illegal value" },
1330    { PCCC_ES_SHORT_ADDRESS,                        "Less levels specified in address than minimum for any address" },
1331    { PCCC_ES_LONG_ADDRESS,                         "More levels specified in address than system supports" },
1332    { PCCC_ES_NOT_FOUND,                            "Symbol not found" },
1333    { PCCC_ES_BAD_FORMAT,                           "Symbol is of improper format" },
1334    { PCCC_ES_BAD_POINTER,                          "Address doesn't point to something usable" },
1335    { PCCC_ES_BAD_SIZE,                             "File is wrong size" },
1336    { PCCC_ES_SITUATION_CHANGED,                    "Cannot complete request, situation has changed since the start of the command" },
1337    { PCCC_ES_DATA_TOO_LARGE,                       "Data or file is too large" },
1338    { PCCC_ES_TRANS_TOO_LARGE,                      "Transaction size plus word address is too large" },
1339    { PCCC_ES_ACCESS_DENIED,                        "Access denied, improper privilege" },
1340    { PCCC_ES_NOT_AVAILABLE,                        "Condition cannot be generated - resource is not available" },
1341    { PCCC_ES_ALREADY_EXISTS,                       "Condition already exists - resource is already available" },
1342    { PCCC_ES_NO_EXECUTION,                         "Command cannot be executed" },
1343    { PCCC_ES_HIST_OVERFLOW,                        "Histogram overflow" },
1344    { PCCC_ES_NO_ACCESS,                            "No access" },
1345    { PCCC_ES_ILLEGAL_DATA_TYPE,                    "Illegal data type" },
1346    { PCCC_ES_INVALID_DATA,                         "Invalid parameter or invalid data" },
1347    { PCCC_ES_BAD_REFERENCE,                        "Address reference exists to deleted area" },
1348    { PCCC_ES_EXECUTION_FAILURE,                    "Command execution failure for unknown reason; possible PLC-3 histogram overflow" },
1349    { PCCC_ES_CONVERSION_ERROR,                     "Data conversion error" },
1350    { PCCC_ES_NO_COMMS,                             "Scanner not able to communicate with 1771 rack adapter" },
1351    { PCCC_ES_TYPE_MISMATCH,                        "Type mismatch" },
1352    { PCCC_ES_BAD_RESPONSE,                         "1771 module response was not valid" },
1353    { PCCC_ES_DUP_LABEL,                            "Duplicated label" },
1354    { PCCC_ES_FILE_ALREADY_OPEN,                    "File is open; another node owns it" },
1355    { PCCC_ES_PROGRAM_ALREADY_OWNED,                "Another node is the program owner" },
1356    { PCCC_ES_RESERVED_1,                           "Reserved" },
1357    { PCCC_ES_RESERVED_2,                           "Reserved" },
1358    { PCCC_ES_PROTECTION_VIOLATION,                 "Data table element protection violation" },
1359    { PCCC_ES_TMP_INTERNAL_ERROR,                   "Temporary internal problem" },
1360    { PCCC_ES_RACK_FAULT,                           "Remote rack fault" },
1361    { PCCC_ES_TIMEOUT,                              "Timeout" },
1362    { PCCC_ES_UNKNOWN,                              "Unknown error" },
1363 
1364    { 0,                          NULL }
1365 };
1366 
1367 static value_string_ext cip_pccc_es_st_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_es_st_vals);
1368 
1369 /* Translate PCCC Function Codes */
1370 static const value_string cip_pccc_fnc_06_vals[] = {
1371     { PCCC_FNC_06_00, "Echo" },
1372     { PCCC_FNC_06_01, "Read diagnostic counters" },
1373     { PCCC_FNC_06_02, "Set variables" },
1374     { PCCC_FNC_06_03, "Diagnostic status" },
1375     { PCCC_FNC_06_04, "Set timeout" },
1376     { PCCC_FNC_06_05, "Set NAKs" },
1377     { PCCC_FNC_06_06, "Set ENQs" },
1378     { PCCC_FNC_06_07, "Reset diagnostic counters" },
1379     { PCCC_FNC_06_08, "Set data table size" },
1380     { PCCC_FNC_06_09, "Read link parameters" },
1381     { PCCC_FNC_06_0A, "Set link parameters" },
1382 
1383    { 0,                          NULL }
1384 };
1385 
1386 static value_string_ext cip_pccc_fnc_06_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_06_vals);
1387 
1388 static const value_string cip_pccc_fnc_07_vals[] = {
1389     { PCCC_FNC_07_00, "Disable outputs" },
1390     { PCCC_FNC_07_01, "Enable outputs" },
1391     { PCCC_FNC_07_03, "Enable PLC scanning" },
1392     { PCCC_FNC_07_04, "Enter download mode" },
1393     { PCCC_FNC_07_05, "Exit download/upload mode" },
1394     { PCCC_FNC_07_06, "Enter upload mode" },
1395 
1396    { 0,                          NULL }
1397 };
1398 
1399 static value_string_ext cip_pccc_fnc_07_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_07_vals);
1400 
1401 static const value_string cip_pccc_fnc_0f_vals[] = {
1402     { PCCC_FNC_0F_00, "Word range write" },
1403     { PCCC_FNC_0F_01, "Word range read" },
1404     { PCCC_FNC_0F_02, "Bit write" },
1405     { PCCC_FNC_0F_03, "File write" },
1406     { PCCC_FNC_0F_04, "File read" },
1407     { PCCC_FNC_0F_05, "Download request" },
1408     { PCCC_FNC_0F_06, "Upload" },
1409     { PCCC_FNC_0F_07, "Shutdown" },
1410     { PCCC_FNC_0F_08, "Physical write" },
1411     { PCCC_FNC_0F_09, "Physical read" },
1412     { PCCC_FNC_0F_0A, "Restart request" },
1413     { PCCC_FNC_0F_11, "Get edit resource" },
1414     { PCCC_FNC_0F_12, "Return edit resource" },
1415     { PCCC_FNC_0F_17, "Read bytes physical" },
1416     { PCCC_FNC_0F_18, "Write bytes physical" },
1417     { PCCC_FNC_0F_26, "Read-modify-write" },
1418     { PCCC_FNC_0F_29, "Read section size" },
1419     { PCCC_FNC_0F_3A, "Set CPU mode" },
1420     { PCCC_FNC_0F_41, "Disable forces" },
1421     { PCCC_FNC_0F_50, "Download all request" },
1422     { PCCC_FNC_0F_52, "Download completed" },
1423     { PCCC_FNC_0F_53, "Upload all request (upload)" },
1424     { PCCC_FNC_0F_55, "Upload completed" },
1425     { PCCC_FNC_0F_57, "Initialize memory" },
1426     { PCCC_FNC_0F_5E, "Modify PLC-2 compatibility file" },
1427     { PCCC_FNC_0F_67, "Typed write" },
1428     { PCCC_FNC_0F_68, "Typed read" },
1429     { PCCC_FNC_0F_79, "Read-modify-write N" },
1430     { PCCC_FNC_0F_80, "Change CPU mode" },
1431     { PCCC_FNC_0F_81, "Open file" },
1432     { PCCC_FNC_0F_82, "Close file" },
1433     { PCCC_FNC_0F_88, "Execute Multiple Commands" },
1434     { PCCC_FNC_0F_8F, "Apply port configuration" },
1435     { PCCC_FNC_0F_A1, "Protected typed logical read with two address fields" },
1436     { PCCC_FNC_0F_A2, "Protected typed logical read with three address fields" },
1437     { PCCC_FNC_0F_A7, "Protected typed file read" },
1438     { PCCC_FNC_0F_A9, "Protected typed logical write with two address fields" },
1439     { PCCC_FNC_0F_AA, "Protected typed logical write with three address fields" },
1440     { PCCC_FNC_0F_AB, "Protected typed logical masked-write with three address fields" },
1441     { PCCC_FNC_0F_AF, "Protected typed file write" },
1442 
1443    { 0,                          NULL }
1444 };
1445 
1446 static value_string_ext cip_pccc_fnc_0f_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_fnc_0f_vals);
1447 
1448 /* Translate PCCC File Types */
1449 static const value_string cip_pccc_file_types_vals[] = {
1450    { PCCC_FILE_TYPE_LOGIC,               "Ladder Logic File" },
1451    { PCCC_FILE_TYPE_CHANNEL_CONFIG,      "Channel Configuration File" },
1452    { PCCC_FILE_TYPE_FUNCTION_ES1,        "EtherNet/IP Function File" },
1453    { PCCC_FILE_TYPE_ONLINE_EDIT,         "Online Editing File" },
1454    { PCCC_FILE_TYPE_FUNCTION_IOS,        "IOS Function File" },
1455    { PCCC_FILE_TYPE_DATA_OUTPUT,         "Output Data File" },
1456    { PCCC_FILE_TYPE_DATA_INPUT,          "Input Data File" },
1457    { PCCC_FILE_TYPE_DATA_STATUS,         "Status Data File" },
1458    { PCCC_FILE_TYPE_DATA_BINARY,         "Binary Data File" },
1459    { PCCC_FILE_TYPE_DATA_TIMER,          "Timer Data File" },
1460    { PCCC_FILE_TYPE_DATA_COUNTER,        "Counter Data File" },
1461    { PCCC_FILE_TYPE_DATA_INTEGER,        "Integer Data File" },
1462    { PCCC_FILE_TYPE_DATA_FLOAT,          "Float Data File" },
1463    { PCCC_FILE_TYPE_FORCE_OUTPUT,        "Output Force File" },
1464    { PCCC_FILE_TYPE_FORCE_INPUT,         "Input Force File" },
1465    { PCCC_FILE_TYPE_FUNCTION_ES0,        "ES0 Function File" },
1466    { PCCC_FILE_TYPE_FUNCTION_STI,        "STI Function File" },
1467    { PCCC_FILE_TYPE_FUNCTION_EII,        "EII Function File" },
1468    { PCCC_FILE_TYPE_FUNCTION_RTC,        "RTC Function File" },
1469    { PCCC_FILE_TYPE_FUNCTION_BHI,        "BHI Function File" },
1470    { PCCC_FILE_TYPE_FUNCTION_MMI,        "Memory Module Function File" },
1471    { PCCC_FILE_TYPE_FUNCTION_LCD,        "Built-in LCD Function File" },
1472    { PCCC_FILE_TYPE_FUNCTION_PTOX,       "PTOX Function File" },
1473    { PCCC_FILE_TYPE_FUNCTION_PWMX,       "PWMX Function File" },
1474 
1475    { 0,                          NULL }
1476 };
1477 
1478 static value_string_ext cip_pccc_file_type_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_file_types_vals);
1479 
1480 /* Translate PCCC CPU Modes */
1481 #if 0
1482 static const value_string cip_pccc_cpu_mode_3a_vals[] = {
1483    { PCCC_CPU_3A_PROGRAM,           "Remote Program" },
1484    { PCCC_CPU_3A_RUN,               "Remote Run" },
1485 
1486    { 0,                          NULL }
1487 };
1488 
1489 value_string_ext cip_pccc_cpu_mode_3a_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_cpu_mode_3a_vals);
1490 #endif
1491 
1492 static const value_string cip_pccc_cpu_mode_80_vals[] = {
1493    { PCCC_CPU_80_PROGRAM,           "Remote Program" },
1494    { PCCC_CPU_80_RUN,               "Remote Run" },
1495    { PCCC_CPU_80_TEST_CONT,         "Remote Test Continuous" },
1496    { PCCC_CPU_80_TEST_SINGLE,       "Remote Test Single" },
1497    { PCCC_CPU_80_TEST_DEBUG,        "Remote Test Debug" },
1498 
1499    { 0,                          NULL }
1500 };
1501 
1502 static value_string_ext cip_pccc_cpu_mode_80_vals_ext = VALUE_STRING_EXT_INIT(cip_pccc_cpu_mode_80_vals);
1503 
1504 /* Translate Vendor IDs */
1505 static const value_string cip_vendor_vals[] = {
1506    {    0,   "Reserved" },
1507    {    1,   "Rockwell Automation/Allen-Bradley" },
1508    {    2,   "Namco Controls Corp." },
1509    {    3,   "Honeywell Inc." },
1510    {    4,   "Parker Hannifin Corp. (Veriflo Division)" },
1511    {    5,   "Rockwell Automation/Reliance Elec." },
1512    {    6,   "Reserved" },
1513    {    7,   "SMC Corporation" },
1514    {    8,   "Molex Incorporated" },
1515    {    9,   "Western Reserve Controls Corp." },
1516    {   10,   "Advanced Micro Controls Inc. (AMCI)" },
1517    {   11,   "ASCO Pneumatic Controls" },
1518    {   12,   "Banner Engineering Corp." },
1519    {   13,   "Belden Wire & Cable Company" },
1520    {   14,   "Cooper Interconnect" },
1521    {   15,   "Reserved" },
1522    {   16,   "Daniel Woodhead Co. (Woodhead Connectivity)" },
1523    {   17,   "Dearborn Group Inc." },
1524    {   18,   "Reserved" },
1525    {   19,   "Helm Instrument Company" },
1526    {   20,   "Huron Net Works" },
1527    {   21,   "Lumberg, Inc." },
1528    {   22,   "Online Development Inc.(Automation Value)" },
1529    {   23,   "Vorne Industries, Inc." },
1530    {   24,   "ODVA Special Reserve" },
1531    {   25,   "Reserved" },
1532    {   26,   "Festo Corporation" },
1533    {   27,   "Reserved" },
1534    {   28,   "Reserved" },
1535    {   29,   "Reserved" },
1536    {   30,   "Unico, Inc." },
1537    {   31,   "Ross Controls" },
1538    {   32,   "Reserved" },
1539    {   33,   "Reserved" },
1540    {   34,   "Hohner Corp." },
1541    {   35,   "Micro Mo Electronics, Inc." },
1542    {   36,   "MKS Instruments, Inc." },
1543    {   37,   "Yaskawa Electric America formerly Magnetek Drives" },
1544    {   38,   "Reserved" },
1545    {   39,   "AVG Automation (Uticor)" },
1546    {   40,   "Wago Corporation" },
1547    {   41,   "Kinetics (Unit Instruments)" },
1548    {   42,   "IMI Norgren Limited" },
1549    {   43,   "BALLUFF, Inc." },
1550    {   44,   "Yaskawa Electric America, Inc." },
1551    {   45,   "Eurotherm Controls Inc" },
1552    {   46,   "ABB Industrial Systems" },
1553    {   47,   "Omron Corporation" },
1554    {   48,   "TURCk, Inc." },
1555    {   49,   "Grayhill Inc." },
1556    {   50,   "Real Time Automation (C&ID)" },
1557    {   51,   "Reserved" },
1558    {   52,   "Numatics, Inc." },
1559    {   53,   "Lutze, Inc." },
1560    {   54,   "Reserved" },
1561    {   55,   "Reserved" },
1562    {   56,   "Softing GmbH" },
1563    {   57,   "Pepperl + Fuchs" },
1564    {   58,   "Spectrum Controls, Inc." },
1565    {   59,   "D.I.P. Inc. MKS Inst." },
1566    {   60,   "Applied Motion Products, Inc." },
1567    {   61,   "Sencon Inc." },
1568    {   62,   "High Country Tek" },
1569    {   63,   "SWAC Automation Consult GmbH" },
1570    {   64,   "Clippard Instrument Laboratory" },
1571    {   65,   "Reserved" },
1572    {   66,   "Reserved" },
1573    {   67,   "Reserved" },
1574    {   68,   "Eaton Electrical" },
1575    {   69,   "Reserved" },
1576    {   70,   "Reserved" },
1577    {   71,   "Toshiba International Corp." },
1578    {   72,   "Control Technology Incorporated" },
1579    {   73,   "TCS (NZ) Ltd." },
1580    {   74,   "Hitachi, Ltd." },
1581    {   75,   "ABB Robotics Products AB" },
1582    {   76,   "NKE Corporation" },
1583    {   77,   "Rockwell Software, Inc." },
1584    {   78,   "Escort Memory Systems (A Datalogic Group Co.)" },
1585    {   79,   "Reserved" },
1586    {   80,   "Industrial Devices Corporation" },
1587    {   81,   "IXXAT Automation GmbH" },
1588    {   82,   "Mitsubishi Electric Automation, Inc." },
1589    {   83,   "OPTO-22" },
1590    {   84,   "Reserved" },
1591    {   85,   "Reserved" },
1592    {   86,   "Horner Electric" },
1593    {   87,   "Burkert Werke GmbH & Co. KG" },
1594    {   88,   "Reserved" },
1595    {   89,   "Industrial Indexing Systems, Inc." },
1596    {   90,   "HMS Industrial Networks AB" },
1597    {   91,   "Robicon" },
1598    {   92,   "Helix Technology (Granville-Phillips)" },
1599    {   93,   "Arlington Laboratory" },
1600    {   94,   "Advantech Co. Ltd." },
1601    {   95,   "Square D Company" },
1602    {   96,   "Digital Electronics Corp." },
1603    {   97,   "Danfoss" },
1604    {   98,   "Reserved" },
1605    {   99,   "Reserved" },
1606    {  100,   "Bosch Rexroth Corporation, Pneumatics" },
1607    {  101,   "Applied Materials, Inc." },
1608    {  102,   "Showa Electric Wire & Cable Co." },
1609    {  103,   "Pacific Scientific (API Controls Inc.)" },
1610    {  104,   "Sharp Manufacturing Systems Corp." },
1611    {  105,   "Olflex Wire & Cable, Inc." },
1612    {  106,   "Reserved" },
1613    {  107,   "Unitrode" },
1614    {  108,   "Beckhoff Automation GmbH" },
1615    {  109,   "National Instruments" },
1616    {  110,   "Mykrolis Corporations (Millipore)" },
1617    {  111,   "International Motion Controls Corp." },
1618    {  112,   "Reserved" },
1619    {  113,   "SEG Kempen GmbH" },
1620    {  114,   "Reserved" },
1621    {  115,   "Reserved" },
1622    {  116,   "MTS Systems Corp." },
1623    {  117,   "Krones, Inc" },
1624    {  118,   "Reserved" },
1625    {  119,   "EXOR Electronic R & D" },
1626    {  120,   "SIEI S.p.A." },
1627    {  121,   "KUKA Roboter GmbH" },
1628    {  122,   "Reserved" },
1629    {  123,   "SEC (Samsung Electronics Co., Ltd)" },
1630    {  124,   "Binary Electronics Ltd" },
1631    {  125,   "Flexible Machine Controls" },
1632    {  126,   "Reserved" },
1633    {  127,   "ABB Inc. (Entrelec)" },
1634    {  128,   "MAC Valves, Inc." },
1635    {  129,   "Auma Actuators Inc" },
1636    {  130,   "Toyoda Machine Works, Ltd" },
1637    {  131,   "Reserved" },
1638    {  132,   "Reserved" },
1639    {  133,   "Balogh T.A.G., Corporation" },
1640    {  134,   "TR Systemtechnik GmbH" },
1641    {  135,   "UNIPULSE Corporation" },
1642    {  136,   "Reserved" },
1643    {  137,   "Reserved" },
1644    {  138,   "Conxall Corporation Inc." },
1645    {  139,   "Reserved" },
1646    {  140,   "Reserved" },
1647    {  141,   "Kuramo Electric Co., Ltd." },
1648    {  142,   "Creative Micro Designs" },
1649    {  143,   "GE Industrial Systems" },
1650    {  144,   "Leybold Vacuum GmbH" },
1651    {  145,   "Siemens Energy & Automation/Drives" },
1652    {  146,   "Kodensha Ltd" },
1653    {  147,   "Motion Engineering, Inc." },
1654    {  148,   "Honda Engineering Co., Ltd" },
1655    {  149,   "EIM Valve Controls" },
1656    {  150,   "Melec Inc." },
1657    {  151,   "Sony Manufacturing Systems Corporation" },
1658    {  152,   "North American Mfg." },
1659    {  153,   "WATLOW" },
1660    {  154,   "Japan Radio Co., Ltd" },
1661    {  155,   "NADEX Co., Ltd" },
1662    {  156,   "Ametek Automation & Process Technologies" },
1663    {  157,   "Reserved" },
1664    {  158,   "KVASER AB" },
1665    {  159,   "IDEC IZUMI Corporation" },
1666    {  160,   "Mitsubishi Heavy Industries Ltd" },
1667    {  161,   "Mitsubishi Electric Corporation" },
1668    {  162,   "Horiba-STEC Inc." },
1669    {  163,   "esd electronic system design gmbh" },
1670    {  164,   "DAIHEN Corporation" },
1671    {  165,   "Tyco Valves & Controls/Keystone" },
1672    {  166,   "EBARA Corporation" },
1673    {  167,   "Reserved" },
1674    {  168,   "Reserved" },
1675    {  169,   "Hokuyo Electric Co. Ltd" },
1676    {  170,   "Pyramid Solutions, Inc." },
1677    {  171,   "Denso Wave Incorporated" },
1678    {  172,   "HLS Hard-Line Solutions Inc" },
1679    {  173,   "Caterpillar, Inc." },
1680    {  174,   "PDL Electronics Ltd." },
1681    {  175,   "Reserved" },
1682    {  176,   "Red Lion Controls" },
1683    {  177,   "ANELVA Corporation" },
1684    {  178,   "Toyo Denki Seizo KK" },
1685    {  179,   "Sanyo Denki Co., Ltd" },
1686    {  180,   "Advanced Energy Japan K.K. (Aera Japan)" },
1687    {  181,   "Pilz GmbH & Co" },
1688    {  182,   "Marsh Bellofram-Bellofram PCD Division" },
1689    {  183,   "Reserved" },
1690    {  184,   "M-SYSTEM Co. Ltd" },
1691    {  185,   "Nissin Electric Co., Ltd" },
1692    {  186,   "Hitachi Metals Ltd." },
1693    {  187,   "Oriental Motor Company" },
1694    {  188,   "A&D Co., Ltd" },
1695    {  189,   "Phasetronics, Inc." },
1696    {  190,   "Cummins Engine Company" },
1697    {  191,   "Deltron Inc." },
1698    {  192,   "Geneer Corporation" },
1699    {  193,   "Anatol Automation, Inc." },
1700    {  194,   "Reserved" },
1701    {  195,   "Reserved" },
1702    {  196,   "Medar, Inc." },
1703    {  197,   "Comdel Inc." },
1704    {  198,   "Advanced Energy Industries, Inc" },
1705    {  199,   "Reserved" },
1706    {  200,   "DAIDEN Co., Ltd" },
1707    {  201,   "CKD Corporation" },
1708    {  202,   "Toyo Electric Corporation" },
1709    {  203,   "Reserved" },
1710    {  204,   "AuCom Electronics Ltd" },
1711    {  205,   "Shinko Electric Co., Ltd" },
1712    {  206,   "Vector Informatik GmbH" },
1713    {  207,   "Reserved" },
1714    {  208,   "Moog Inc." },
1715    {  209,   "Contemporary Controls" },
1716    {  210,   "Tokyo Sokki Kenkyujo Co., Ltd" },
1717    {  211,   "Schenck-AccuRate, Inc." },
1718    {  212,   "The Oilgear Company" },
1719    {  213,   "Reserved" },
1720    {  214,   "ASM Japan K.K." },
1721    {  215,   "HIRATA Corp." },
1722    {  216,   "SUNX Limited" },
1723    {  217,   "Meidensha Corp." },
1724    {  218,   "NIDEC SANKYO CORPORATION (Sankyo Seiki Mfg. Co., Ltd)" },
1725    {  219,   "KAMRO Corp." },
1726    {  220,   "Nippon System Development Co., Ltd" },
1727    {  221,   "EBARA Technologies Inc." },
1728    {  222,   "Reserved" },
1729    {  223,   "Reserved" },
1730    {  224,   "SG Co., Ltd" },
1731    {  225,   "Vaasa Institute of Technology" },
1732    {  226,   "MKS Instruments (ENI Technology)" },
1733    {  227,   "Tateyama System Laboratory Co., Ltd." },
1734    {  228,   "QLOG Corporation" },
1735    {  229,   "Matric Limited Inc." },
1736    {  230,   "NSD Corporation" },
1737    {  231,   "Reserved" },
1738    {  232,   "Sumitomo Wiring Systems, Ltd" },
1739    {  233,   "Group 3 Technology Ltd" },
1740    {  234,   "CTI Cryogenics" },
1741    {  235,   "POLSYS CORP" },
1742    {  236,   "Ampere Inc." },
1743    {  237,   "Reserved" },
1744    {  238,   "Simplatroll Ltd" },
1745    {  239,   "Reserved" },
1746    {  240,   "Reserved" },
1747    {  241,   "Leading Edge Design" },
1748    {  242,   "Humphrey Products" },
1749    {  243,   "Schneider Automation, Inc." },
1750    {  244,   "Westlock Controls Corp." },
1751    {  245,   "Nihon Weidmuller Co., Ltd" },
1752    {  246,   "Brooks Instrument (Div. of Emerson)" },
1753    {  247,   "Reserved" },
1754    {  248,   "Moeller GmbH" },
1755    {  249,   "Varian Vacuum Products" },
1756    {  250,   "Yokogawa Electric Corporation" },
1757    {  251,   "Electrical Design Daiyu Co., Ltd" },
1758    {  252,   "Omron Software Co., Ltd" },
1759    {  253,   "BOC Edwards" },
1760    {  254,   "Control Technology Corporation" },
1761    {  255,   "Bosch Rexroth" },
1762    {  256,   "Turck" },
1763    {  257,   "Control Techniques PLC" },
1764    {  258,   "Hardy Instruments, Inc." },
1765    {  259,   "LS Industrial Systems" },
1766    {  260,   "E.O.A. Systems Inc." },
1767    {  261,   "Reserved" },
1768    {  262,   "New Cosmos Electric Co., Ltd." },
1769    {  263,   "Sense Eletronica LTDA" },
1770    {  264,   "Xycom, Inc." },
1771    {  265,   "Baldor Electric" },
1772    {  266,   "Reserved" },
1773    {  267,   "Patlite Corporation" },
1774    {  268,   "Reserved" },
1775    {  269,   "Mogami Wire & Cable Corporation" },
1776    {  270,   "Welding Technology Corporation (WTC)" },
1777    {  271,   "Reserved" },
1778    {  272,   "Deutschmann Automation GmbH" },
1779    {  273,   "ICP Panel-Tec Inc." },
1780    {  274,   "Bray Controls USA" },
1781    {  275,   "Reserved" },
1782    {  276,   "Status Technologies" },
1783    {  277,   "Trio Motion Technology Ltd" },
1784    {  278,   "Sherrex Systems Ltd" },
1785    {  279,   "Adept Technology, Inc." },
1786    {  280,   "Spang Power Electronics" },
1787    {  281,   "Reserved" },
1788    {  282,   "Acrosser Technology Co., Ltd" },
1789    {  283,   "Hilscher GmbH" },
1790    {  284,   "IMAX Corporation" },
1791    {  285,   "Electronic Innovation, Inc. (Falter Engineering)" },
1792    {  286,   "Netlogic Inc." },
1793    {  287,   "Bosch Rexroth Corporation, Indramat" },
1794    {  288,   "Reserved" },
1795    {  289,   "Reserved" },
1796    {  290,   "Murata  Machinery Ltd." },
1797    {  291,   "MTT Company Ltd." },
1798    {  292,   "Kanematsu Semiconductor Corp." },
1799    {  293,   "Takebishi Electric Sales Co." },
1800    {  294,   "Tokyo Electron Device Ltd" },
1801    {  295,   "PFU Limited" },
1802    {  296,   "Hakko Automation Co., Ltd." },
1803    {  297,   "Advanet Inc." },
1804    {  298,   "Tokyo Electron Software Technologies Ltd." },
1805    {  299,   "Reserved" },
1806    {  300,   "Shinagawa Electric Wire Co., Ltd." },
1807    {  301,   "Yokogawa M&C Corporation" },
1808    {  302,   "KONAN Electric Co., Ltd." },
1809    {  303,   "Binar Elektronik AB" },
1810    {  304,   "Furukawa Electric Co." },
1811    {  305,   "Cooper Energy Services" },
1812    {  306,   "Schleicher GmbH & Co." },
1813    {  307,   "Hirose Electric Co., Ltd" },
1814    {  308,   "Western Servo Design Inc." },
1815    {  309,   "Prosoft Technology" },
1816    {  310,   "Reserved" },
1817    {  311,   "Towa Shoko Co., Ltd" },
1818    {  312,   "Kyopal Co., Ltd" },
1819    {  313,   "Extron Co." },
1820    {  314,   "Wieland Electric GmbH" },
1821    {  315,   "SEW Eurodrive GmbH" },
1822    {  316,   "Aera Corporation" },
1823    {  317,   "STA Reutlingen" },
1824    {  318,   "Reserved" },
1825    {  319,   "Fuji Electric Co., Ltd." },
1826    {  320,   "Reserved" },
1827    {  321,   "Reserved" },
1828    {  322,   "ifm efector, inc." },
1829    {  323,   "Reserved" },
1830    {  324,   "IDEACOD-Hohner Automation S.A." },
1831    {  325,   "CommScope Inc." },
1832    {  326,   "GE Fanuc Automation North America, Inc." },
1833    {  327,   "Matsushita Electric Industrial Co., Ltd" },
1834    {  328,   "Okaya Electronics Corporation" },
1835    {  329,   "KASHIYAMA Industries, Ltd" },
1836    {  330,   "JVC" },
1837    {  331,   "Interface Corporation" },
1838    {  332,   "Grape Systems Inc." },
1839    {  333,   "Reserved" },
1840    {  334,   "Reserved" },
1841    {  335,   "Toshiba IT & Control Systems Corporation" },
1842    {  336,   "Sanyo Machine Works, Ltd." },
1843    {  337,   "Vansco Electronics Ltd." },
1844    {  338,   "Dart Container Corp." },
1845    {  339,   "Livingston & Co., Inc." },
1846    {  340,   "Alfa Laval LKM as" },
1847    {  341,   "BF ENTRON Ltd. (British Federal)" },
1848    {  342,   "Bekaert Engineering NV" },
1849    {  343,   "Ferran  Scientific Inc." },
1850    {  344,   "KEBA AG" },
1851    {  345,   "Endress + Hauser" },
1852    {  346,   "Reserved" },
1853    {  347,   "ABB ALSTOM Power UK Ltd. (EGT)" },
1854    {  348,   "Berger Lahr GmbH" },
1855    {  349,   "Reserved" },
1856    {  350,   "Federal Signal Corp." },
1857    {  351,   "Kawasaki Robotics (USA), Inc." },
1858    {  352,   "Bently Nevada Corporation" },
1859    {  353,   "Reserved" },
1860    {  354,   "FRABA Posital GmbH" },
1861    {  355,   "Elsag Bailey, Inc." },
1862    {  356,   "Fanuc Robotics America" },
1863    {  357,   "Reserved" },
1864    {  358,   "Surface Combustion, Inc." },
1865    {  359,   "Reserved" },
1866    {  360,   "AILES Electronics Ind. Co., Ltd." },
1867    {  361,   "Wonderware Corporation" },
1868    {  362,   "Particle Measuring Systems, Inc." },
1869    {  363,   "Reserved" },
1870    {  364,   "Reserved" },
1871    {  365,   "BITS Co., Ltd" },
1872    {  366,   "Japan Aviation Electronics Industry Ltd" },
1873    {  367,   "Keyence Corporation" },
1874    {  368,   "Kuroda Precision Industries Ltd." },
1875    {  369,   "Mitsubishi Electric Semiconductor Application" },
1876    {  370,   "Nippon Seisen Cable, Ltd." },
1877    {  371,   "Omron ASO Co., Ltd" },
1878    {  372,   "Seiko Seiki Co., Ltd." },
1879    {  373,   "Sumitomo Heavy Industries, Ltd." },
1880    {  374,   "Tango Computer Service Corporation" },
1881    {  375,   "Technology Service, Inc." },
1882    {  376,   "Toshiba Information Systems (Japan) Corporation" },
1883    {  377,   "TOSHIBA Schneider Inverter Corporation" },
1884    {  378,   "Toyooki Kogyo Co., Ltd." },
1885    {  379,   "XEBEC" },
1886    {  380,   "Madison Cable Corporation" },
1887    {  381,   "Hitati Engineering & Services Co., Ltd" },
1888    {  382,   "TEM-TECH Lab Co., Ltd" },
1889    {  383,   "International Laboratory Corporation" },
1890    {  384,   "Dyadic Systems Co., Ltd." },
1891    {  385,   "SETO Electronics Industry Co., Ltd" },
1892    {  386,   "Tokyo Electron Kyushu Limited" },
1893    {  387,   "KEI System Co., Ltd" },
1894    {  388,   "Reserved" },
1895    {  389,   "Asahi Engineering Co., Ltd" },
1896    {  390,   "Contrex Inc." },
1897    {  391,   "Paradigm Controls Ltd." },
1898    {  392,   "Reserved" },
1899    {  393,   "Ohm Electric Co., Ltd." },
1900    {  394,   "RKC Instrument Inc." },
1901    {  395,   "Suzuki Motor Corporation" },
1902    {  396,   "Custom Servo Motors Inc." },
1903    {  397,   "PACE Control Systems" },
1904    {  398,   "Reserved" },
1905    {  399,   "Reserved" },
1906    {  400,   "LINTEC Co., Ltd." },
1907    {  401,   "Hitachi Cable Ltd." },
1908    {  402,   "BUSWARE Direct" },
1909    {  403,   "Eaton Electric B.V. (former Holec Holland N.V.)" },
1910    {  404,   "VAT Vakuumventile AG" },
1911    {  405,   "Scientific Technologies Incorporated" },
1912    {  406,   "Alfa Instrumentos Eletronicos Ltda" },
1913    {  407,   "TWK Elektronik GmbH" },
1914    {  408,   "ABB Welding Systems AB" },
1915    {  409,   "BYSTRONIC Maschinen AG" },
1916    {  410,   "Kimura Electric Co., Ltd" },
1917    {  411,   "Nissei Plastic Industrial Co., Ltd" },
1918    {  412,   "Reserved" },
1919    {  413,   "Kistler-Morse Corporation" },
1920    {  414,   "Proteous Industries Inc." },
1921    {  415,   "IDC Corporation" },
1922    {  416,   "Nordson Corporation" },
1923    {  417,   "Rapistan Systems" },
1924    {  418,   "LP-Elektronik GmbH" },
1925    {  419,   "GERBI & FASE S.p.A.(Fase Saldatura)" },
1926    {  420,   "Phoenix Digital Corporation" },
1927    {  421,   "Z-World Engineering" },
1928    {  422,   "Honda R&D Co., Ltd." },
1929    {  423,   "Bionics Instrument Co., Ltd." },
1930    {  424,   "Teknic, Inc." },
1931    {  425,   "R.Stahl, Inc." },
1932    {  426,   "Reserved" },
1933    {  427,   "Ryco Graphic Manufacturing Inc." },
1934    {  428,   "Giddings & Lewis, Inc." },
1935    {  429,   "Koganei Corporation" },
1936    {  430,   "Reserved" },
1937    {  431,   "Nichigoh Communication Electric Wire Co., Ltd." },
1938    {  432,   "Reserved" },
1939    {  433,   "Fujikura Ltd." },
1940    {  434,   "AD Link Technology Inc." },
1941    {  435,   "StoneL Corporation" },
1942    {  436,   "Computer Optical Products, Inc." },
1943    {  437,   "CONOS Inc." },
1944    {  438,   "Erhardt + Leimer GmbH" },
1945    {  439,   "UNIQUE Co. Ltd" },
1946    {  440,   "Roboticsware, Inc." },
1947    {  441,   "Nachi Fujikoshi Corporation" },
1948    {  442,   "Hengstler GmbH" },
1949    {  443,   "Reserved" },
1950    {  444,   "SUNNY GIKEN Inc." },
1951    {  445,   "Lenze Drive Systems GmbH" },
1952    {  446,   "CD Systems B.V." },
1953    {  447,   "FMT/Aircraft Gate Support Systems AB" },
1954    {  448,   "Axiomatic Technologies Corp" },
1955    {  449,   "Embedded System Products, Inc." },
1956    {  450,   "Reserved" },
1957    {  451,   "Mencom Corporation" },
1958    {  452,   "Reserved" },
1959    {  453,   "Matsushita Welding Systems Co., Ltd." },
1960    {  454,   "Dengensha Mfg. Co. Ltd." },
1961    {  455,   "Quinn Systems Ltd." },
1962    {  456,   "Tellima Technology Ltd" },
1963    {  457,   "MDT, Software" },
1964    {  458,   "Taiwan Keiso Co., Ltd" },
1965    {  459,   "Pinnacle Systems" },
1966    {  460,   "Ascom Hasler Mailing Sys" },
1967    {  461,   "INSTRUMAR Limited" },
1968    {  462,   "Reserved" },
1969    {  463,   "Navistar International Transportation Corp" },
1970    {  464,   "Huettinger Elektronik GmbH + Co. KG" },
1971    {  465,   "OCM Technology Inc." },
1972    {  466,   "Professional Supply Inc." },
1973    {  467,   "Control Solutions" },
1974    {  468,   "Baumer IVO GmbH & Co. KG" },
1975    {  469,   "Worcester Controls Corporation" },
1976    {  470,   "Pyramid Technical Consultants, Inc." },
1977    {  471,   "Reserved" },
1978    {  472,   "Apollo Fire Detectors Limited" },
1979    {  473,   "Avtron Manufacturing, Inc." },
1980    {  474,   "Reserved" },
1981    {  475,   "Tokyo Keiso Co., Ltd." },
1982    {  476,   "Daishowa Swiki Co., Ltd." },
1983    {  477,   "Kojima Instruments Inc." },
1984    {  478,   "Shimadzu Corporation" },
1985    {  479,   "Tatsuta Electric Wire & Cable Co., Ltd." },
1986    {  480,   "MECS Corporation" },
1987    {  481,   "Tahara Electric" },
1988    {  482,   "Koyo Electronics" },
1989    {  483,   "Clever Devices" },
1990    {  484,   "GCD Hardware & Software GmbH" },
1991    {  485,   "Reserved" },
1992    {  486,   "Miller Electric Mfg Co." },
1993    {  487,   "GEA Tuchenhagen GmbH" },
1994    {  488,   "Riken Keiki Co., LTD" },
1995    {  489,   "Keisokugiken Corporation" },
1996    {  490,   "Fuji Machine Mfg. Co., Ltd" },
1997    {  491,   "Reserved" },
1998    {  492,   "Nidec-Shimpo Corp." },
1999    {  493,   "UTEC Corporation" },
2000    {  494,   "Sanyo Electric Co. Ltd." },
2001    {  495,   "Reserved" },
2002    {  496,   "Reserved" },
2003    {  497,   "Okano Electric Wire Co. Ltd" },
2004    {  498,   "Shimaden Co. Ltd." },
2005    {  499,   "Teddington Controls Ltd" },
2006    {  500,   "Reserved" },
2007    {  501,   "VIPA GmbH" },
2008    {  502,   "Warwick Manufacturing Group" },
2009    {  503,   "Danaher Controls" },
2010    {  504,   "Reserved" },
2011    {  505,   "Reserved" },
2012    {  506,   "American Science & Engineering" },
2013    {  507,   "Accutron Controls International Inc." },
2014    {  508,   "Norcott Technologies Ltd" },
2015    {  509,   "TB Woods, Inc" },
2016    {  510,   "Proportion-Air, Inc." },
2017    {  511,   "SICK Stegmann GmbH" },
2018    {  512,   "Reserved" },
2019    {  513,   "Edwards Signaling" },
2020    {  514,   "Sumitomo Metal Industries, Ltd" },
2021    {  515,   "Cosmo Instruments Co., Ltd." },
2022    {  516,   "Denshosha Co., Ltd." },
2023    {  517,   "Kaijo Corp." },
2024    {  518,   "Michiproducts Co., Ltd." },
2025    {  519,   "Miura Corporation" },
2026    {  520,   "TG Information Network Co., Ltd." },
2027    {  521,   "Fujikin , Inc." },
2028    {  522,   "Estic Corp." },
2029    {  523,   "GS Hydraulic Sales" },
2030    {  524,   "Reserved" },
2031    {  525,   "MTE Limited" },
2032    {  526,   "Hyde Park Electronics, Inc." },
2033    {  527,   "Pfeiffer Vacuum GmbH" },
2034    {  528,   "Cyberlogic Technologies" },
2035    {  529,   "OKUMA Corporation FA Systems Division" },
2036    {  530,   "Reserved" },
2037    {  531,   "Hitachi Kokusai Electric Co., Ltd." },
2038    {  532,   "SHINKO TECHNOS Co., Ltd." },
2039    {  533,   "Itoh Electric Co., Ltd." },
2040    {  534,   "Colorado Flow Tech Inc." },
2041    {  535,   "Love Controls Division/Dwyer Inst." },
2042    {  536,   "Alstom Drives and Controls" },
2043    {  537,   "The Foxboro Company" },
2044    {  538,   "Tescom Corporation" },
2045    {  539,   "Reserved" },
2046    {  540,   "Atlas Copco Controls UK" },
2047    {  541,   "Reserved" },
2048    {  542,   "Autojet Technologies" },
2049    {  543,   "Prima Electronics S.p.A." },
2050    {  544,   "PMA GmbH" },
2051    {  545,   "Shimafuji Electric Co., Ltd" },
2052    {  546,   "Oki Electric Industry Co., Ltd" },
2053    {  547,   "Kyushu Matsushita Electric Co., Ltd" },
2054    {  548,   "Nihon Electric Wire & Cable Co., Ltd" },
2055    {  549,   "Tsuken Electric Ind Co., Ltd" },
2056    {  550,   "Tamadic Co." },
2057    {  551,   "MAATEL SA" },
2058    {  552,   "OKUMA America" },
2059    {  553,   "Control Techniques PLC-NA" },
2060    {  554,   "TPC Wire & Cable" },
2061    {  555,   "ATI Industrial Automation" },
2062    {  556,   "Microcontrol (Australia) Pty Ltd" },
2063    {  557,   "Serra Soldadura, S.A." },
2064    {  558,   "Southwest Research Institute" },
2065    {  559,   "Cabinplant International" },
2066    {  560,   "Sartorius Mechatronics T&H GmbH" },
2067    {  561,   "Comau S.p.A. Robotics & Final Assembly Division" },
2068    {  562,   "Phoenix Contact" },
2069    {  563,   "Yokogawa MAT Corporation" },
2070    {  564,   "asahi sangyo co., ltd." },
2071    {  565,   "Reserved" },
2072    {  566,   "Akita Myotoku Ltd." },
2073    {  567,   "OBARA Corp." },
2074    {  568,   "Suetron Electronic GmbH" },
2075    {  569,   "Reserved" },
2076    {  570,   "Serck Controls Limited" },
2077    {  571,   "Fairchild Industrial Products Company" },
2078    {  572,   "ARO S.A." },
2079    {  573,   "M2C GmbH" },
2080    {  574,   "Shin Caterpillar Mitsubishi Ltd." },
2081    {  575,   "Santest Co., Ltd." },
2082    {  576,   "Cosmotechs Co., Ltd." },
2083    {  577,   "Hitachi Electric Systems" },
2084    {  578,   "Smartscan Ltd" },
2085    {  579,   "Woodhead Software & Electronics France" },
2086    {  580,   "Athena Controls, Inc." },
2087    {  581,   "Syron Engineering & Manufacturing, Inc." },
2088    {  582,   "Asahi Optical Co., Ltd." },
2089    {  583,   "Sansha Electric Mfg. Co., Ltd." },
2090    {  584,   "Nikki Denso Co., Ltd." },
2091    {  585,   "Star Micronics, Co., Ltd." },
2092    {  586,   "Ecotecnia Socirtat Corp." },
2093    {  587,   "AC Technology Corp." },
2094    {  588,   "West Instruments Limited" },
2095    {  589,   "NTI Limited" },
2096    {  590,   "Delta Computer Systems, Inc." },
2097    {  591,   "FANUC Ltd." },
2098    {  592,   "Hearn-Gu Lee" },
2099    {  593,   "ABB Automation Products" },
2100    {  594,   "Orion Machinery Co., Ltd." },
2101    {  595,   "Reserved" },
2102    {  596,   "Wire-Pro, Inc." },
2103    {  597,   "Beijing Huakong Technology Co. Ltd." },
2104    {  598,   "Yokoyama Shokai Co., Ltd." },
2105    {  599,   "Toyogiken Co., Ltd." },
2106    {  600,   "Coester Equipamentos Eletronicos Ltda." },
2107    {  601,   "Reserved" },
2108    {  602,   "Electroplating Engineers of Japan Ltd." },
2109    {  603,   "ROBOX S.p.A." },
2110    {  604,   "Spraying Systems Company" },
2111    {  605,   "Benshaw Inc." },
2112    {  606,   "ZPA-DP A.S." },
2113    {  607,   "Wired Rite Systems" },
2114    {  608,   "Tandis Research, Inc." },
2115    {  609,   "SSD Drives GmbH" },
2116    {  610,   "ULVAC Japan Ltd." },
2117    {  611,   "DYNAX Corporation" },
2118    {  612,   "Nor-Cal Products, Inc." },
2119    {  613,   "Aros Electronics AB" },
2120    {  614,   "Jun-Tech Co., Ltd." },
2121    {  615,   "HAN-MI Co. Ltd." },
2122    {  616,   "uniNtech (formerly SungGi Internet)" },
2123    {  617,   "Hae Pyung Electronics Reserch Institute" },
2124    {  618,   "Milwaukee Electronics" },
2125    {  619,   "OBERG Industries" },
2126    {  620,   "Parker Hannifin/Compumotor Division" },
2127    {  621,   "TECHNO DIGITAL CORPORATION" },
2128    {  622,   "Network Supply Co., Ltd." },
2129    {  623,   "Union Electronics Co., Ltd." },
2130    {  624,   "Tritronics Services PM Ltd." },
2131    {  625,   "Rockwell Automation-Sprecher+Schuh" },
2132    {  626,   "Matsushita Electric Industrial Co., Ltd/Motor Co." },
2133    {  627,   "Rolls-Royce Energy Systems, Inc." },
2134    {  628,   "JEONGIL INTERCOM CO., LTD" },
2135    {  629,   "Interroll Corp." },
2136    {  630,   "Hubbell Wiring Device-Kellems (Delaware)" },
2137    {  631,   "Intelligent Motion Systems" },
2138    {  632,   "Reserved" },
2139    {  633,   "INFICON AG" },
2140    {  634,   "Hirschmann, Inc." },
2141    {  635,   "The Siemon Company" },
2142    {  636,   "YAMAHA Motor Co. Ltd." },
2143    {  637,   "aska corporation" },
2144    {  638,   "Woodhead Connectivity" },
2145    {  639,   "Trimble AB" },
2146    {  640,   "Murrelektronik GmbH" },
2147    {  641,   "Creatrix Labs, Inc." },
2148    {  642,   "TopWorx" },
2149    {  643,   "Kumho Industrial Co., Ltd." },
2150    {  644,   "Wind River Systems, Inc." },
2151    {  645,   "Bihl & Wiedemann GmbH" },
2152    {  646,   "Harmonic Drive Systems Inc." },
2153    {  647,   "Rikei Corporation" },
2154    {  648,   "BL Autotec, Ltd." },
2155    {  649,   "Hana Information & Technology Co., Ltd." },
2156    {  650,   "Seoil Electric Co., Ltd." },
2157    {  651,   "Fife Corporation" },
2158    {  652,   "Shanghai Electrical Apparatus Research Institute" },
2159    {  653,   "Reserved" },
2160    {  654,   "Parasense Development Centre" },
2161    {  655,   "Reserved" },
2162    {  656,   "Reserved" },
2163    {  657,   "Six Tau S.p.A." },
2164    {  658,   "Aucos GmbH" },
2165    {  659,   "Rotork Controls" },
2166    {  660,   "Automationdirect.com" },
2167    {  661,   "Thermo BLH" },
2168    {  662,   "System Controls, Ltd." },
2169    {  663,   "Univer S.p.A." },
2170    {  664,   "MKS-Tenta Technology" },
2171    {  665,   "Lika Electronic SNC" },
2172    {  666,   "Mettler-Toledo, Inc." },
2173    {  667,   "DXL USA Inc." },
2174    {  668,   "Rockwell Automation/Entek IRD Intl." },
2175    {  669,   "Nippon Otis Elevator Company" },
2176    {  670,   "Sinano Electric, Co., Ltd." },
2177    {  671,   "Sony Manufacturing Systems" },
2178    {  672,   "Reserved" },
2179    {  673,   "Contec Co., Ltd." },
2180    {  674,   "Automated Solutions" },
2181    {  675,   "Controlweigh" },
2182    {  676,   "Reserved" },
2183    {  677,   "Fincor Electronics" },
2184    {  678,   "Cognex Corporation" },
2185    {  679,   "Qualiflow" },
2186    {  680,   "Weidmuller, Inc." },
2187    {  681,   "Morinaga Milk Industry Co., Ltd." },
2188    {  682,   "Takagi Industrial Co., Ltd." },
2189    {  683,   "Wittenstein AG" },
2190    {  684,   "Sena Technologies, Inc." },
2191    {  685,   "Reserved" },
2192    {  686,   "APV Products Unna" },
2193    {  687,   "Creator Teknisk Utvedkling AB" },
2194    {  688,   "Reserved" },
2195    {  689,   "Mibu Denki Industrial Co., Ltd." },
2196    {  690,   "Takamastsu Machineer Section" },
2197    {  691,   "Startco Engineering Ltd." },
2198    {  692,   "Reserved" },
2199    {  693,   "Holjeron" },
2200    {  694,   "ALCATEL High Vacuum Technology" },
2201    {  695,   "Taesan LCD Co., Ltd." },
2202    {  696,   "POSCON" },
2203    {  697,   "VMIC" },
2204    {  698,   "Matsushita Electric Works, Ltd." },
2205    {  699,   "IAI Corporation" },
2206    {  700,   "Horst GmbH" },
2207    {  701,   "MicroControl GmbH & Co." },
2208    {  702,   "Leine & Linde AB" },
2209    {  703,   "Reserved" },
2210    {  704,   "EC Elettronica Srl" },
2211    {  705,   "VIT Software HB" },
2212    {  706,   "Bronkhorst High-Tech B.V." },
2213    {  707,   "Optex Co., Ltd." },
2214    {  708,   "Yosio Electronic Co." },
2215    {  709,   "Terasaki Electric Co., Ltd." },
2216    {  710,   "Sodick Co., Ltd." },
2217    {  711,   "MTS Systems Corporation-Automation Division" },
2218    {  712,   "Mesa Systemtechnik" },
2219    {  713,   "SHIN HO SYSTEM Co., Ltd." },
2220    {  714,   "Goyo Electronics Co, Ltd." },
2221    {  715,   "Loreme" },
2222    {  716,   "SAB Brockskes GmbH & Co. KG" },
2223    {  717,   "Trumpf Laser GmbH + Co. KG" },
2224    {  718,   "Niigata Electronic Instruments Co., Ltd." },
2225    {  719,   "Yokogawa Digital Computer Corporation" },
2226    {  720,   "O.N. Electronic Co., Ltd." },
2227    {  721,   "Industrial Control  Communication, Inc." },
2228    {  722,   "ABB, Inc." },
2229    {  723,   "ElectroWave USA, Inc." },
2230    {  724,   "Industrial Network Controls, LLC" },
2231    {  725,   "KDT Systems Co., Ltd." },
2232    {  726,   "SEFA Technology Inc." },
2233    {  727,   "Nippon POP Rivets and Fasteners Ltd." },
2234    {  728,   "Yamato Scale Co., Ltd." },
2235    {  729,   "Zener Electric" },
2236    {  730,   "GSE Scale Systems" },
2237    {  731,   "ISAS (Integrated Switchgear & Sys. Pty Ltd)" },
2238    {  732,   "Beta LaserMike Limited" },
2239    {  733,   "TOEI Electric Co., Ltd." },
2240    {  734,   "Hakko Electronics Co., Ltd" },
2241    {  735,   "Reserved" },
2242    {  736,   "RFID, Inc." },
2243    {  737,   "Adwin Corporation" },
2244    {  738,   "Osaka Vacuum, Ltd." },
2245    {  739,   "A-Kyung Motion, Inc." },
2246    {  740,   "Camozzi S.P. A." },
2247    {  741,   "Crevis Co., LTD" },
2248    {  742,   "Rice Lake Weighing Systems" },
2249    {  743,   "Linux Network Services" },
2250    {  744,   "KEB Antriebstechnik GmbH" },
2251    {  745,   "Hagiwara Electric Co., Ltd." },
2252    {  746,   "Glass Inc. International" },
2253    {  747,   "Reserved" },
2254    {  748,   "DVT Corporation" },
2255    {  749,   "Woodward Governor" },
2256    {  750,   "Mosaic Systems, Inc." },
2257    {  751,   "Laserline GmbH" },
2258    {  752,   "COM-TEC, Inc." },
2259    {  753,   "Weed Instrument" },
2260    {  754,   "Prof-face European Technology Center" },
2261    {  755,   "Fuji Automation Co., Ltd." },
2262    {  756,   "Matsutame Co., Ltd." },
2263    {  757,   "Hitachi Via Mechanics, Ltd." },
2264    {  758,   "Dainippon Screen Mfg. Co. Ltd." },
2265    {  759,   "FLS Automation A/S" },
2266    {  760,   "ABB Stotz Kontakt GmbH" },
2267    {  761,   "Technical Marine Service" },
2268    {  762,   "Advanced Automation Associates, Inc." },
2269    {  763,   "Baumer Ident GmbH" },
2270    {  764,   "Tsubakimoto Chain Co." },
2271    {  765,   "Reserved" },
2272    {  766,   "Furukawa Co., Ltd." },
2273    {  767,   "Active Power" },
2274    {  768,   "CSIRO Mining Automation" },
2275    {  769,   "Matrix Integrated Systems" },
2276    {  770,   "Digitronic Automationsanlagen GmbH" },
2277    {  771,   "SICK STEGMANN Inc." },
2278    {  772,   "TAE-Antriebstechnik GmbH" },
2279    {  773,   "Electronic Solutions" },
2280    {  774,   "Rocon L.L.C." },
2281    {  775,   "Dijitized Communications Inc." },
2282    {  776,   "Asahi Organic Chemicals Industry Co., Ltd." },
2283    {  777,   "Hodensha" },
2284    {  778,   "Harting, Inc. NA" },
2285    {  779,   "Kubler GmbH" },
2286    {  780,   "Yamatake Corporation" },
2287    {  781,   "JEOL" },
2288    {  782,   "Yamatake Industrial Systems Co., Ltd." },
2289    {  783,   "HAEHNE Elektronische Messgerate GmbH" },
2290    {  784,   "Ci Technologies Pty Ltd (for Pelamos Industries)" },
2291    {  785,   "N. SCHLUMBERGER & CIE" },
2292    {  786,   "Teijin Seiki Co., Ltd." },
2293    {  787,   "DAIKIN Industries, Ltd" },
2294    {  788,   "RyuSyo Industrial Co., Ltd." },
2295    {  789,   "SAGINOMIYA SEISAKUSHO, INC." },
2296    {  790,   "Seishin Engineering Co., Ltd." },
2297    {  791,   "Japan Support System Ltd." },
2298    {  792,   "Decsys" },
2299    {  793,   "Metronix Messgerate u. Elektronik GmbH" },
2300    {  794,   "Reserved" },
2301    {  795,   "Vaccon Company, Inc." },
2302    {  796,   "Siemens Energy & Automation, Inc." },
2303    {  797,   "Ten X Technology, Inc." },
2304    {  798,   "Tyco Electronics" },
2305    {  799,   "Delta Power Electronics Center" },
2306    {  800,   "Denker" },
2307    {  801,   "Autonics Corporation" },
2308    {  802,   "JFE Electronic Engineering Pty. Ltd." },
2309    {  803,   "Reserved" },
2310    {  804,   "Electro-Sensors, Inc." },
2311    {  805,   "Digi International, Inc." },
2312    {  806,   "Texas Instruments" },
2313    {  807,   "ADTEC Plasma Technology Co., Ltd" },
2314    {  808,   "SICK AG" },
2315    {  809,   "Ethernet Peripherals, Inc." },
2316    {  810,   "Animatics Corporation" },
2317    {  811,   "Reserved" },
2318    {  812,   "Process Control Corporation" },
2319    {  813,   "SystemV. Inc." },
2320    {  814,   "Danaher Motion SRL" },
2321    {  815,   "SHINKAWA Sensor Technology, Inc." },
2322    {  816,   "Tesch GmbH & Co. KG" },
2323    {  817,   "Reserved" },
2324    {  818,   "Trend Controls Systems Ltd." },
2325    {  819,   "Guangzhou ZHIYUAN Electronic Co., Ltd." },
2326    {  820,   "Mykrolis Corporation" },
2327    {  821,   "Bethlehem Steel Corporation" },
2328    {  822,   "KK ICP" },
2329    {  823,   "Takemoto Denki Corporation" },
2330    {  824,   "The Montalvo Corporation" },
2331    {  825,   "Reserved" },
2332    {  826,   "LEONI Special Cables GmbH" },
2333    {  827,   "Reserved" },
2334    {  828,   "ONO SOKKI CO.,LTD." },
2335    {  829,   "Rockwell Samsung Automation" },
2336    {  830,   "SHINDENGEN ELECTRIC MFG. CO. LTD" },
2337    {  831,   "Origin Electric Co. Ltd." },
2338    {  832,   "Quest Technical Solutions, Inc." },
2339    {  833,   "LS Cable, Ltd." },
2340    {  834,   "Enercon-Nord Electronic GmbH" },
2341    {  835,   "Northwire Inc." },
2342    {  836,   "Engel Elektroantriebe GmbH" },
2343    {  837,   "The Stanley Works" },
2344    {  838,   "Celesco Transducer Products, Inc." },
2345    {  839,   "Chugoku Electric Wire and Cable Co." },
2346    {  840,   "Kongsberg Simrad AS" },
2347    {  841,   "Panduit Corporation" },
2348    {  842,   "Spellman High Voltage Electronics Corp." },
2349    {  843,   "Kokusai Electric Alpha Co., Ltd." },
2350    {  844,   "Brooks Automation, Inc." },
2351    {  845,   "ANYWIRE CORPORATION" },
2352    {  846,   "Honda Electronics Co. Ltd" },
2353    {  847,   "REO Elektronik AG" },
2354    {  848,   "Fusion UV Systems, Inc." },
2355    {  849,   "ASI Advanced Semiconductor Instruments GmbH" },
2356    {  850,   "Datalogic, Inc." },
2357    {  851,   "SoftPLC Corporation" },
2358    {  852,   "Dynisco Instruments LLC" },
2359    {  853,   "WEG Industrias SA" },
2360    {  854,   "Frontline Test Equipment, Inc." },
2361    {  855,   "Tamagawa Seiki Co., Ltd." },
2362    {  856,   "Multi Computing Co., Ltd." },
2363    {  857,   "RVSI" },
2364    {  858,   "Commercial Timesharing Inc." },
2365    {  859,   "Tennessee Rand Automation LLC" },
2366    {  860,   "Wacogiken Co., Ltd" },
2367    {  861,   "Reflex Integration Inc." },
2368    {  862,   "Siemens AG, A&D PI Flow Instruments" },
2369    {  863,   "G. Bachmann Electronic GmbH" },
2370    {  864,   "NT International" },
2371    {  865,   "Schweitzer Engineering Laboratories" },
2372    {  866,   "ATR Industrie-Elektronik GmbH Co." },
2373    {  867,   "PLASMATECH Co., Ltd" },
2374    {  868,   "Reserved" },
2375    {  869,   "GEMU GmbH & Co. KG" },
2376    {  870,   "Alcorn McBride Inc." },
2377    {  871,   "MORI SEIKI CO., LTD" },
2378    {  872,   "NodeTech Systems Ltd" },
2379    {  873,   "Emhart Teknologies" },
2380    {  874,   "Cervis, Inc." },
2381    {  875,   "FieldServer Technologies (Div Sierra Monitor Corp)" },
2382    {  876,   "NEDAP Power Supplies" },
2383    {  877,   "Nippon Sanso Corporation" },
2384    {  878,   "Mitomi Giken Co., Ltd." },
2385    {  879,   "PULS GmbH" },
2386    {  880,   "Reserved" },
2387    {  881,   "Japan Control Engineering Ltd" },
2388    {  882,   "Embedded Systems Korea (Former Zues Emtek Co Ltd.)" },
2389    {  883,   "Automa SRL" },
2390    {  884,   "Harms+Wende GmbH & Co KG" },
2391    {  885,   "SAE-STAHL GmbH" },
2392    {  886,   "Microwave Data Systems" },
2393    {  887,   "B&R Industrial Automation GmbH" },
2394    {  888,   "Hiprom Technologies" },
2395    {  889,   "Reserved" },
2396    {  890,   "Nitta Corporation" },
2397    {  891,   "Kontron Modular Computers GmbH" },
2398    {  892,   "Marlin Controls" },
2399    {  893,   "ELCIS s.r.l." },
2400    {  894,   "Acromag, Inc." },
2401    {  895,   "Avery Weigh-Tronix" },
2402    {  896,   "Reserved" },
2403    {  897,   "Reserved" },
2404    {  898,   "Reserved" },
2405    {  899,   "Practicon Ltd" },
2406    {  900,   "Schunk GmbH & Co. KG" },
2407    {  901,   "MYNAH Technologies" },
2408    {  902,   "Defontaine Groupe" },
2409    {  903,   "Emerson Process Management Power & Water Solutions" },
2410    {  904,   "F.A. Elec" },
2411    {  905,   "Hottinger Baldwin Messtechnik GmbH" },
2412    {  906,   "Coreco Imaging, Inc." },
2413    {  907,   "London Electronics Ltd." },
2414    {  908,   "HSD SpA" },
2415    {  909,   "Comtrol Corporation" },
2416    {  910,   "TEAM, S.A. (Tecnica Electronica de Automatismo Y Medida)" },
2417    {  911,   "MAN B&W Diesel Ltd. Regulateurs Europa" },
2418    {  912,   "Reserved" },
2419    {  913,   "Reserved" },
2420    {  914,   "Micro Motion, Inc." },
2421    {  915,   "Eckelmann AG" },
2422    {  916,   "Hanyoung Nux" },
2423    {  917,   "Ransburg Industrial Finishing KK" },
2424    {  918,   "Kun Hung Electric Co. Ltd." },
2425    {  919,   "Brimos wegbebakening b.v." },
2426    {  920,   "Nitto Seiki Co., Ltd" },
2427    {  921,   "PPT Vision, Inc." },
2428    {  922,   "Yamazaki Machinery Works" },
2429    {  923,   "SCHMIDT Technology GmbH" },
2430    {  924,   "Parker Hannifin SpA (SBC Division)" },
2431    {  925,   "HIMA Paul Hildebrandt GmbH" },
2432    {  926,   "RivaTek, Inc." },
2433    {  927,   "Misumi Corporation" },
2434    {  928,   "GE Multilin" },
2435    {  929,   "Measurement Computing Corporation" },
2436    {  930,   "Jetter AG" },
2437    {  931,   "Tokyo Electronics Systems Corporation" },
2438    {  932,   "Togami Electric Mfg. Co., Ltd." },
2439    {  933,   "HK Systems" },
2440    {  934,   "CDA Systems Ltd." },
2441    {  935,   "Aerotech Inc." },
2442    {  936,   "JVL Industrie Elektronik A/S" },
2443    {  937,   "NovaTech Process Solutions LLC" },
2444    {  938,   "Reserved" },
2445    {  939,   "Cisco Systems" },
2446    {  940,   "Grid Connect" },
2447    {  941,   "ITW Automotive Finishing" },
2448    {  942,   "HanYang System" },
2449    {  943,   "ABB K.K. Technical Center" },
2450    {  944,   "Taiyo Electric Wire & Cable Co., Ltd." },
2451    {  945,   "Reserved" },
2452    {  946,   "SEREN IPS INC" },
2453    {  947,   "Belden CDT Electronics Division" },
2454    {  948,   "ControlNet International" },
2455    {  949,   "Gefran S.P.A." },
2456    {  950,   "Jokab Safety AB" },
2457    {  951,   "SUMITA OPTICAL GLASS, INC." },
2458    {  952,   "Biffi Italia srl" },
2459    {  953,   "Beck IPC GmbH" },
2460    {  954,   "Copley Controls Corporation" },
2461    {  955,   "Fagor Automation S. Coop." },
2462    {  956,   "DARCOM" },
2463    {  957,   "Frick Controls (div. of York International)" },
2464    {  958,   "SymCom, Inc." },
2465    {  959,   "Infranor" },
2466    {  960,   "Kyosan Cable, Ltd." },
2467    {  961,   "Varian Vacuum Technologies" },
2468    {  962,   "Messung Systems" },
2469    {  963,   "Xantrex Technology, Inc." },
2470    {  964,   "StarThis Inc." },
2471    {  965,   "Chiyoda Co., Ltd." },
2472    {  966,   "Flowserve Corporation" },
2473    {  967,   "Spyder Controls Corp." },
2474    {  968,   "IBA AG" },
2475    {  969,   "SHIMOHIRA ELECTRIC MFG.CO.,LTD" },
2476    {  970,   "Reserved" },
2477    {  971,   "Siemens L&A" },
2478    {  972,   "Micro Innovations AG" },
2479    {  973,   "Switchgear & Instrumentation" },
2480    {  974,   "PRE-TECH CO., LTD." },
2481    {  975,   "National Semiconductor" },
2482    {  976,   "Invensys Process Systems" },
2483    {  977,   "Ametek HDR Power Systems" },
2484    {  978,   "Reserved" },
2485    {  979,   "TETRA-K Corporation" },
2486    {  980,   "C & M Corporation" },
2487    {  981,   "Siempelkamp Maschinen" },
2488    {  982,   "Reserved" },
2489    {  983,   "Daifuku America Corporation" },
2490    {  984,   "Electro-Matic Products Inc." },
2491    {  985,   "BUSSAN MICROELECTRONICS CORP." },
2492    {  986,   "ELAU AG" },
2493    {  987,   "Hetronic USA" },
2494    {  988,   "NIIGATA POWER SYSTEMS Co., Ltd." },
2495    {  989,   "Software Horizons Inc." },
2496    {  990,   "B3 Systems, Inc." },
2497    {  991,   "Moxa Networking Co., Ltd." },
2498    {  992,   "Reserved" },
2499    {  993,   "S4 Integration" },
2500    {  994,   "Elettro Stemi S.R.L." },
2501    {  995,   "AquaSensors" },
2502    {  996,   "Ifak System GmbH" },
2503    {  997,   "SANKEI MANUFACTURING Co.,LTD." },
2504    {  998,   "Emerson Network Power Co., Ltd." },
2505    {  999,   "Fairmount Automation, Inc." },
2506    { 1000,   "Bird Electronic Corporation" },
2507    { 1001,   "Nabtesco Corporation" },
2508    { 1002,   "AGM Electronics, Inc." },
2509    { 1003,   "ARCX Inc." },
2510    { 1004,   "DELTA I/O Co." },
2511    { 1005,   "Chun IL Electric Ind. Co." },
2512    { 1006,   "N-Tron" },
2513    { 1007,   "Nippon Pneumatics/Fludics System CO.,LTD." },
2514    { 1008,   "DDK Ltd." },
2515    { 1009,   "Seiko Epson Corporation" },
2516    { 1010,   "Halstrup-Walcher GmbH" },
2517    { 1011,   "ITT" },
2518    { 1012,   "Ground Fault Systems bv" },
2519    { 1013,   "Scolari Engineering S.p.A." },
2520    { 1014,   "Vialis Traffic bv" },
2521    { 1015,   "Weidmueller Interface GmbH & Co. KG" },
2522    { 1016,   "Shanghai Sibotech Automation Co. Ltd" },
2523    { 1017,   "AEG Power Supply Systems GmbH" },
2524    { 1018,   "Komatsu Electronics Inc." },
2525    { 1019,   "Souriau" },
2526    { 1020,   "Baumuller Chicago Corp." },
2527    { 1021,   "J. Schmalz GmbH" },
2528    { 1022,   "SEN Corporation" },
2529    { 1023,   "Korenix Technology Co. Ltd" },
2530    { 1024,   "Cooper Power Tools" },
2531    { 1025,   "INNOBIS" },
2532    { 1026,   "Shinho System" },
2533    { 1027,   "Xm Services Ltd." },
2534    { 1028,   "KVC Co., Ltd." },
2535    { 1029,   "Sanyu Seiki Co., Ltd." },
2536    { 1030,   "TuxPLC" },
2537    { 1031,   "Northern Network Solutions" },
2538    { 1032,   "Converteam GmbH" },
2539    { 1033,   "Symbol Technologies" },
2540    { 1034,   "S-TEAM Lab" },
2541    { 1035,   "Maguire Products, Inc." },
2542    { 1036,   "AC&T" },
2543    { 1037,   "MITSUBISHI HEAVY INDUSTRIES, LTD. KOBE SHIPYARD & MACHINERY WORKS" },
2544    { 1038,   "Hurletron Inc." },
2545    { 1039,   "Chunichi Denshi Co., Ltd" },
2546    { 1040,   "Cardinal Scale Mfg. Co." },
2547    { 1041,   "BTR NETCOM via RIA Connect, Inc." },
2548    { 1042,   "Base2" },
2549    { 1043,   "ASRC Aerospace" },
2550    { 1044,   "Beijing Stone Automation" },
2551    { 1045,   "Changshu Switchgear Manufacture Ltd." },
2552    { 1046,   "METRONIX Corp." },
2553    { 1047,   "WIT" },
2554    { 1048,   "ORMEC Systems Corp." },
2555    { 1049,   "ASATech (China) Inc." },
2556    { 1050,   "Controlled Systems Limited" },
2557    { 1051,   "Mitsubishi Heavy Ind. Digital System Co., Ltd. (M.H.I.)" },
2558    { 1052,   "Electrogrip" },
2559    { 1053,   "TDS Automation" },
2560    { 1054,   "T&C Power Conversion, Inc." },
2561    { 1055,   "Robostar Co., Ltd" },
2562    { 1056,   "Scancon A/S" },
2563    { 1057,   "Haas Automation, Inc." },
2564    { 1058,   "Eshed Technology" },
2565    { 1059,   "Delta Electronic Inc." },
2566    { 1060,   "Innovasic Semiconductor" },
2567    { 1061,   "SoftDEL Systems Limited" },
2568    { 1062,   "FiberFin, Inc." },
2569    { 1063,   "Nicollet Technologies Corp." },
2570    { 1064,   "B.F. Systems" },
2571    { 1065,   "Empire Wire and Supply LLC" },
2572    { 1066,   "Reserved" },
2573    { 1067,   "Elmo Motion Control LTD" },
2574    { 1068,   "Reserved" },
2575    { 1069,   "Asahi Keiki Co., Ltd." },
2576    { 1070,   "Joy Mining Machinery" },
2577    { 1071,   "MPM Engineering Ltd" },
2578    { 1072,   "Wolke Inks & Printers GmbH" },
2579    { 1073,   "Mitsubishi Electric Engineering Co., Ltd." },
2580    { 1074,   "COMET AG" },
2581    { 1075,   "Real Time Objects & Systems, LLC" },
2582    { 1076,   "MISCO Refractometer" },
2583    { 1077,   "JT Engineering Inc." },
2584    { 1078,   "Automated Packing Systems" },
2585    { 1079,   "Niobrara R&D Corp." },
2586    { 1080,   "Garmin Ltd." },
2587    { 1081,   "Japan Mobile Platform Co., Ltd" },
2588    { 1082,   "Advosol Inc." },
2589    { 1083,   "ABB Global Services Limited" },
2590    { 1084,   "Sciemetric Instruments Inc." },
2591    { 1085,   "Tata Elxsi Ltd." },
2592    { 1086,   "TPC Mechatronics, Co., Ltd." },
2593    { 1087,   "Cooper Bussmann" },
2594    { 1088,   "Trinite Automatisering B.V." },
2595    { 1089,   "Peek Traffic B.V." },
2596    { 1090,   "Acrison, Inc" },
2597    { 1091,   "Applied Robotics, Inc." },
2598    { 1092,   "FireBus Systems, Inc." },
2599    { 1093,   "Beijing Sevenstar Huachuang Electronics" },
2600    { 1094,   "Magnetek" },
2601    { 1095,   "Microscan" },
2602    { 1096,   "Air Water Inc." },
2603    { 1097,   "Sensopart Industriesensorik GmbH" },
2604    { 1098,   "Tiefenbach Control Systems GmbH" },
2605    { 1099,   "INOXPA S.A" },
2606    { 1100,   "Zurich University of Applied Sciences" },
2607    { 1101,   "Ethernet Direct" },
2608    { 1102,   "GSI-Micro-E Systems" },
2609    { 1103,   "S-Net Automation Co., Ltd." },
2610    { 1104,   "Power Electronics S.L." },
2611    { 1105,   "Renesas Technology Corp." },
2612    { 1106,   "NSWCCD-SSES" },
2613    { 1107,   "Porter Engineering Ltd." },
2614    { 1108,   "Meggitt Airdynamics, Inc." },
2615    { 1109,   "Inductive Automation" },
2616    { 1110,   "Neural ID" },
2617    { 1111,   "EEPod LLC" },
2618    { 1112,   "Hitachi Industrial Equipment Systems Co., Ltd." },
2619    { 1113,   "Salem Automation" },
2620    { 1114,   "port GmbH" },
2621    { 1115,   "B & PLUS" },
2622    { 1116,   "Graco Inc." },
2623    { 1117,   "Altera Corporation" },
2624    { 1118,   "Technology Brewing Corporation" },
2625    { 1121,   "CSE Servelec" },
2626    { 1124,   "Fluke Networks" },
2627    { 1125,   "Tetra Pak Packaging Solutions SPA" },
2628    { 1126,   "Racine Federated, Inc." },
2629    { 1127,   "Pureron Japan Co., Ltd." },
2630    { 1130,   "Brother Industries, Ltd." },
2631    { 1132,   "Leroy Automation" },
2632    { 1134,   "THK CO., LTD." },
2633    { 1137,   "TR-Electronic GmbH" },
2634    { 1138,   "ASCON S.p.A." },
2635    { 1139,   "Toledo do Brasil Industria de Balancas Ltda." },
2636    { 1140,   "Bucyrus DBT Europe GmbH" },
2637    { 1141,   "Emerson Process Management Valve Automation" },
2638    { 1142,   "Alstom Transport" },
2639    { 1144,   "Matrox Electronic Systems" },
2640    { 1145,   "Littelfuse" },
2641    { 1146,   "PLASMART, Inc." },
2642    { 1147,   "Miyachi Corporation" },
2643    { 1150,   "Promess Incorporated" },
2644    { 1151,   "COPA-DATA GmbH" },
2645    { 1152,   "Precision Engine Controls Corporation" },
2646    { 1153,   "Alga Automacao e controle LTDA" },
2647    { 1154,   "U.I. Lapp GmbH" },
2648    { 1155,   "ICES" },
2649    { 1156,   "Philips Lighting bv" },
2650    { 1157,   "Aseptomag AG" },
2651    { 1158,   "ARC Informatique" },
2652    { 1159,   "Hesmor GmbH" },
2653    { 1160,   "Kobe Steel, Ltd." },
2654    { 1161,   "FLIR Systems" },
2655    { 1162,   "Simcon A/S" },
2656    { 1163,   "COPALP" },
2657    { 1164,   "Zypcom, Inc." },
2658    { 1165,   "Swagelok" },
2659    { 1166,   "Elspec" },
2660    { 1167,   "ITT Water & Wastewater AB" },
2661    { 1168,   "Kunbus GmbH Industrial Communication" },
2662    { 1170,   "Performance Controls, Inc." },
2663    { 1171,   "ACS Motion Control, Ltd." },
2664    { 1173,   "IStar Technology Limited" },
2665    { 1174,   "Alicat Scientific, Inc." },
2666    { 1176,   "ADFweb.com SRL" },
2667    { 1177,   "Tata Consultancy Services Limited" },
2668    { 1178,   "CXR Ltd." },
2669    { 1179,   "Vishay Nobel AB" },
2670    { 1181,   "SolaHD" },
2671    { 1182,   "Endress+Hauser" },
2672    { 1183,   "Bartec GmbH" },
2673    { 1185,   "AccuSentry, Inc." },
2674    { 1186,   "Exlar Corporation" },
2675    { 1187,   "ILS Technology" },
2676    { 1188,   "Control Concepts Inc." },
2677    { 1190,   "Procon Engineering Limited" },
2678    { 1191,   "Hermary Opto Electronics Inc." },
2679    { 1192,   "Q-Lambda" },
2680    { 1194,   "VAMP Ltd" },
2681    { 1195,   "FlexLink" },
2682    { 1196,   "Office FA.com Co., Ltd." },
2683    { 1197,   "SPMC (Changzhou) Co. Ltd." },
2684    { 1198,   "Anton Paar GmbH" },
2685    { 1199,   "Zhuzhou CSR Times Electric Co., Ltd." },
2686    { 1200,   "DeStaCo" },
2687    { 1201,   "Synrad, Inc" },
2688    { 1202,   "Bonfiglioli Vectron GmbH" },
2689    { 1203,   "Pivotal Systems" },
2690    { 1204,   "TKSCT" },
2691    { 1205,   "Randy Nuernberger" },
2692    { 1206,   "CENTRALP" },
2693    { 1207,   "Tengen Group" },
2694    { 1208,   "OES, Inc." },
2695    { 1209,   "Actel Corporation" },
2696    { 1210,   "Monaghan Engineering, Inc." },
2697    { 1211,   "wenglor sensoric gmbh" },
2698    { 1212,   "HSA Systems" },
2699    { 1213,   "MK Precision Co., Ltd." },
2700    { 1214,   "Tappan Wire and Cable" },
2701    { 1215,   "Heinzmann GmbH & Co. KG" },
2702    { 1216,   "Process Automation International Ltd." },
2703    { 1217,   "Secure Crossing" },
2704    { 1218,   "SMA Railway Technology GmbH" },
2705    { 1219,   "FMS Force Measuring Systems AG" },
2706    { 1220,   "ABT Endustri Enerji Sistemleri Sanayi Tic. Ltd. Sti." },
2707    { 1221,   "MagneMotion Inc." },
2708    { 1222,   "STS Co., Ltd." },
2709    { 1223,   "MERAK SIC, SA" },
2710    { 1224,   "ABOUNDI, Inc." },
2711    { 1225,   "Rosemount Inc." },
2712    { 1226,   "GEA FES, Inc." },
2713    { 1227,   "TMG Technologie und Engineering GmbH" },
2714    { 1228,   "embeX GmbH" },
2715    { 1229,   "GH Electrotermia, S.A." },
2716    { 1230,   "Tolomatic" },
2717    { 1231,   "Dukane" },
2718    { 1232,   "Elco (Tian Jin) Electronics Co., Ltd." },
2719    { 1233,   "Jacobs Automation" },
2720    { 1234,   "Noda Radio Frequency Technologies Co., Ltd." },
2721    { 1235,   "MSC Tuttlingen GmbH" },
2722    { 1236,   "Hitachi Cable Manchester" },
2723    { 1237,   "ACOREL SAS" },
2724    { 1238,   "Global Engineering Solutions Co., Ltd." },
2725    { 1239,   "ALTE Transportation, S.L." },
2726    { 1240,   "Penko Engineering B.V." },
2727 
2728    { 0, NULL }
2729 };
2730 
2731 value_string_ext cip_vendor_vals_ext = VALUE_STRING_EXT_INIT(cip_vendor_vals);
2732 
2733 /* Translate Device Profile's */
2734 static const value_string cip_devtype_vals[] = {
2735    { 0x00,        "Generic Device (deprecated)"         },
2736    { 0x02,        "AC Drive"                            },
2737    { 0x03,        "Motor Overload"                      },
2738    { 0x04,        "Limit Switch"                        },
2739    { 0x05,        "Inductive Proximity Switch"          },
2740    { 0x06,        "Photoelectric Sensor"                },
2741    { 0x07,        "General Purpose Discrete I/O"        },
2742    { 0x09,        "Resolver"                            },
2743    { 0x0C,        "Communications Adapter"              },
2744    { 0x0E,        "Programmable Logic Controller"       },
2745    { 0x10,        "Position Controller",                },
2746    { 0x13,        "DC Drive"                            },
2747    { 0x15,        "Contactor",                          },
2748    { 0x16,        "Motor Starter",                      },
2749    { 0x17,        "Soft Start",                         },
2750    { 0x18,        "Human-Machine Interface"             },
2751    { 0x1A,        "Mass Flow Controller"                },
2752    { 0x1B,        "Pneumatic Valve"                     },
2753    { 0x1C,        "Vacuum Pressure Gauge"               },
2754    { 0x1D,        "Process Control Value"               },
2755    { 0x1E,        "Residual Gas Analyzer"               },
2756    { 0x1F,        "DC Power Generator"                  },
2757    { 0x20,        "RF Power Generator"                  },
2758    { 0x21,        "Turbomolecular Vacuum Pump"          },
2759    { 0x22,        "Encoder"                             },
2760    { 0x23,        "Safety Discrete I/O Device"          },
2761    { 0x24,        "Fluid Flow Controller"               },
2762    { 0x25,        "CIP Motion Drive"                    },
2763    { 0x26,        "CompoNet Repeater"                   },
2764    { 0x27,        "Mass Flow Controller, Enhanced"      },
2765    { 0x28,        "CIP Modbus Device"                   },
2766    { 0x29,        "CIP Modbus Translator"               },
2767    { 0x2A,        "Safety Analog I/O Device"            },
2768    { 0x2B,        "Generic Device (keyable)"            },
2769    { 0x2C,        "Managed Ethernet Switch"             },
2770    { 0x2D,        "CIP Motion Safety Drive Device"      },
2771    { 0x2E,        "Safety Drive Device"                 },
2772    { 0x2F,        "CIP Motion Encoder"                  },
2773    { 0x30,        "CIP Motion Converter"                },
2774    { 0x31,        "CIP Motion I/O"                      },
2775    { 0x32,        "ControlNet Physical Layer Component" },
2776    { 0x33,        "Circuit Breaker"                     },
2777    { 0x34,        "HART Device"                         },
2778    { 0x35,        "CIP-HART Translator"                 },
2779    { 0xC8,        "Embedded Component"                  },
2780 
2781    { 0, NULL }
2782 };
2783 
2784 value_string_ext cip_devtype_vals_ext = VALUE_STRING_EXT_INIT(cip_devtype_vals);
2785 
2786 /* Translate class names */
2787 const value_string cip_class_names_vals[] = {
2788    { 0x01,     "Identity"                       },
2789    { 0x02,     "Message Router"                 },
2790    { 0x03,     "DeviceNet"                      },
2791    { 0x04,     "Assembly"                       },
2792    { 0x05,     "Connection"                     },
2793    { 0x06,     "Connection Manager"             },
2794    { 0x07,     "Register"                       },
2795    { 0x08,     "Discrete Input Point"           },
2796    { 0x09,     "Discrete Output Point"          },
2797    { 0x0A,     "Analog Input Point"             },
2798    { 0x0B,     "Analog Output Point"            },
2799    { 0x0E,     "Presence Sensing"               },
2800    { 0x0F,     "Parameter"                      },
2801    { 0x10,     "Parameter Group"                },
2802    { 0x12,     "Group"                          },
2803    { 0x1D,     "Discrete Input Group"           },
2804    { 0x1E,     "Discrete Output Group"          },
2805    { 0x1F,     "Discrete Group"                 },
2806    { 0x20,     "Analog Input Group"             },
2807    { 0x21,     "Analog Output Group"            },
2808    { 0x22,     "Analog Group"                   },
2809    { 0x23,     "Position Sensor"                },
2810    { 0x24,     "Position Controller Supervisor" },
2811    { 0x25,     "Position Controller"            },
2812    { 0x26,     "Block Sequencer"                },
2813    { 0x27,     "Command Block"                  },
2814    { 0x28,     "Motor Data"                     },
2815    { 0x29,     "Control Supervisor"             },
2816    { 0x2A,     "AC/DC Drive"                    },
2817    { 0x2B,     "Acknowledge Handler"            },
2818    { 0x2C,     "Overload"                       },
2819    { 0x2D,     "Softstart"                      },
2820    { 0x2E,     "Selection"                      },
2821    { 0x30,     "S-Device Supervisor"            },
2822    { 0x31,     "S-Analog Sensor"                },
2823    { 0x32,     "S-Analog Actuator"              },
2824    { 0x33,     "S-Single Stage Controller"      },
2825    { 0x34,     "S-Gas Calibration"              },
2826    { 0x35,     "Trip Point"                     },
2827    { 0x37,     "File"                           },
2828    { 0x38,     "S-Partial Pressure"             },
2829    { 0x39,     "Safety Supervisor"              },
2830    { 0x3A,     "Safety Validator"               },
2831    { 0x3B,     "Safety Discrete Output Point"   },
2832    { 0x3C,     "Safety Discrete Output Group"   },
2833    { 0x3D,     "Safety Discrete Input Point"    },
2834    { 0x3E,     "Safety Discrete Input Group"    },
2835    { 0x3F,     "Safety Dual Channel Output"     },
2836    { 0x40,     "S-Sensor Calibration"           },
2837    { 0x41,     "Event Log"                      },
2838    { 0x42,     "Motion Device Axis"             },
2839    { 0x43,     "Time Sync"                      },
2840    { 0x44,     "Modbus"                         },
2841    { 0x45,     "Originator Connection List"     },
2842    { 0x46,     "Modbus Serial Link"             },
2843    { 0x47,     "Device Level Ring (DLR)"        },
2844    { 0x48,     "QoS"                            },
2845    { 0x49,     "Safety Analog Input Point"      },
2846    { 0x4A,     "Safety Analog Input Group"      },
2847    { 0x4B,     "Safety Dual Channel Analog Input"  },
2848    { 0x4C,     "SERCOS III Link"                },
2849    { 0x4D,     "Target Connection List"         },
2850    { 0x4E,     "Base Energy"                    },
2851    { 0x4F,     "Electrical Energy"              },
2852    { 0x50,     "Non-Electrical Energy"          },
2853    { 0x51,     "Base Switch"                    },
2854    { 0x52,     "SNMP"                           },
2855    { 0x53,     "Power Management"               },
2856    { 0x54,     "RSTP Bridge"                    },
2857    { 0x55,     "RSTP Port"                      },
2858    { 0x56,     "PRP/HSR Protocol"               },
2859    { 0x57,     "PRP/HSR Nodes Table"            },
2860    { 0x58,     "Safety Feedback"                },
2861    { 0x59,     "Safety Dual Channel Feedback"   },
2862    { 0x5A,     "Safety Stop Functions"          },
2863    { 0x5B,     "Safety Limit Functions"         },
2864    { 0x5C,     "Power Curtailment"              },
2865    { 0x5D,     "CIP Security"                   },
2866    { 0x5E,     "EtherNet/IP Security"           },
2867    { 0x5F,     "Certificate Management"         },
2868    { 0x60,     "Authority"                      },
2869    { 0x61,     "Password Authenticator"         },
2870    { 0x62,     "Certificate Authenticator"      },
2871    { 0x67,     "PCCC Class"                     },
2872    { 0xF0,     "ControlNet"                     },
2873    { 0xF1,     "ControlNet Keeper"              },
2874    { 0xF2,     "ControlNet Scheduling"          },
2875    { 0xF3,     "Connection Configuration"       },
2876    { 0xF4,     "Port"                           },
2877    { 0xF5,     "TCP/IP Interface"               },
2878    { 0xF6,     "Ethernet Link"                  },
2879    { 0xF7,     "CompoNet"                       },
2880    { 0xF8,     "CompoNet Repeater"              },
2881    { 0xF9,     "HART Master Port"               },
2882    { 0xFA,     "I/O Aggregation"                },
2883    { 0x100,    "Protection Trip"                },
2884    { 0x101,    "Protection Alarm"               },
2885    { 0x102,    "Circuit Breaker Supervisor"     },
2886    { 0x103,    "Circuit Breaker Statistics"     },
2887    { 0x104,    "Electrical Demand"              },
2888    { 0x105,    "Electrical Statistics"          },
2889    { 0x106,    "Machine Base Data"              },
2890    { 0x107,    "HART Process Device"            },
2891    { 0x108,    "Process Device Diagnostics"     },
2892    { 0x109,    "LLDP Management"                },
2893    { 0x10A,    "LLDP Data Table"                },
2894    { 0x10B,    "IO-Link Service Parameter"      },
2895    { 0x10C,    "IO-Link Master PHY"             },
2896    { 0x10D,    "IO-Link Device PHY"             },
2897    { 0x10E,    "Pilot Light Supervisor"         },
2898    { 0x10F,    "Select Line Link"               },
2899    { 0x110,    "In-Cabinet Actual Topology"     },
2900    { 0x111,    "In-Cabinet Commissioning"       },
2901 
2902    { 0,        NULL                             }
2903 };
2904 
2905 static const value_string cip_id_state_vals[] = {
2906    { 0, "Nonexistent" },
2907    { 1, "Device Self Testing" },
2908    { 2, "Standby" },
2909    { 3, "Operational" },
2910    { 4, "Major Recoverable Fault" },
2911    { 5, "Major Unrecoverable Fault" },
2912 
2913    { 0, NULL }
2914 };
2915 
2916 static const range_string cip_port_type_vals[] = {
2917    { 0, 0, "Any - no routing" },
2918    { 1, 1, "Reserved for legacy use" },
2919    { 2, 2, "ControlNet" },
2920    { 3, 3, "ControlNet with redundancy" },
2921    { 4, 4, "EtherNet/IP" },
2922    { 5, 5, "DeviceNet" },
2923    { 6, 99, "Reserved for legacy use" },
2924    { 100, 199, "Vendor Specific" },
2925    { 200, 200, "CompoNet" },
2926    { 201, 201, "Modbus/TCP" },
2927    { 202, 202, "Modbus/SL" },
2928    { 203, 203, "SERCOS III" },
2929    { 204, 65534, "Reserved for future use" },
2930    { 65535, 65535, "Any - user configurable" },
2931 
2932    { 0, 0, NULL }
2933 };
2934 
2935 const value_string cip_port_number_vals[] = {
2936    { 0, "Reserved" },
2937    { 1, "Backplane" },
2938 
2939    { 0, NULL }
2940 };
2941 
2942 value_string_ext cip_class_names_vals_ext = VALUE_STRING_EXT_INIT(cip_class_names_vals);
2943 
2944 /* Translate function to string - Run/Idle */
2945 static const value_string cip_run_idle_vals[] = {
2946    { 0, "Idle" },
2947    { 1, "Run" },
2948 
2949    { 0, NULL }
2950 };
2951 
cip_rpi_api_fmt(gchar * s,guint32 value)2952 void cip_rpi_api_fmt(gchar *s, guint32 value)
2953 {
2954    g_snprintf(s, ITEM_LABEL_LENGTH, "%.3fms", value / 1000.0);
2955 }
2956 
add_cip_class_to_info_column(packet_info * pinfo,guint32 class_id,int display_type)2957 static void add_cip_class_to_info_column(packet_info *pinfo, guint32 class_id, int display_type)
2958 {
2959    cip_req_info_t *cip_req_info;
2960 
2961    /* Skip printing the top level class for certain common messages because it gets
2962       too wordy in the Info column. */
2963    cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
2964    if (cip_req_info
2965        && ((cip_req_info->bService == SC_CM_UNCON_SEND && class_id == CI_CLS_CM)
2966        || (cip_req_info->bService == SC_MULT_SERV_PACK && class_id == CI_CLS_MR)))
2967    {
2968        return;
2969    }
2970 
2971    if (display_type == DISPLAY_CONNECTION_PATH)
2972    {
2973        col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(class_id, cip_class_names_vals, "Class (0x%02x)"));
2974    }
2975    else if (display_type == DISPLAY_REQUEST_PATH)
2976    {
2977        col_append_fstr(pinfo->cinfo, COL_INFO, "%s - ", val_to_str(class_id, cip_class_names_vals, "Class (0x%02x)"));
2978    }
2979 }
2980 
add_cip_symbol_to_info_column(packet_info * pinfo,gchar * symbol_name,int display_type)2981 static void add_cip_symbol_to_info_column(packet_info *pinfo, gchar *symbol_name, int display_type)
2982 {
2983    if (symbol_name == NULL)
2984    {
2985        return;
2986    }
2987 
2988    if (display_type == DISPLAY_CONNECTION_PATH)
2989    {
2990        col_append_fstr(pinfo->cinfo, COL_INFO, " ('%s')", symbol_name);
2991    }
2992    else if (display_type == DISPLAY_REQUEST_PATH)
2993    {
2994        col_append_fstr(pinfo->cinfo, COL_INFO, "'%s' - ", symbol_name);
2995    }
2996 }
2997 
add_cip_service_to_info_column(packet_info * pinfo,guint8 service,const value_string * service_vals)2998 void add_cip_service_to_info_column(packet_info *pinfo, guint8 service, const value_string* service_vals)
2999 {
3000    col_append_str( pinfo->cinfo, COL_INFO,
3001       val_to_str(service & CIP_SC_MASK, service_vals, "Service (0x%02x)"));
3002    col_set_fence(pinfo->cinfo, COL_INFO);
3003 }
3004 
add_cip_pccc_function_to_info_column(packet_info * pinfo,guint8 fnc,const value_string * fnc_vals)3005 static void add_cip_pccc_function_to_info_column(packet_info *pinfo, guint8 fnc, const value_string* fnc_vals)
3006 {
3007    col_append_fstr( pinfo->cinfo, COL_INFO,
3008       " - %s", val_to_str(fnc, fnc_vals, "Function (0x%02x)"));
3009    col_set_fence(pinfo->cinfo, COL_INFO);
3010 }
3011 
dissect_id_revision(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3012 static int dissect_id_revision(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3013                              int offset, int total_len)
3014 {
3015    if (total_len < 2)
3016    {
3017       expert_add_info(pinfo, item, &ei_mal_identity_revision);
3018       return total_len;
3019    }
3020 
3021    proto_tree_add_item( tree, hf_id_major_rev, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3022    proto_tree_add_item( tree, hf_id_minor_rev, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
3023    return 2;
3024 }
3025 
dissect_id_status(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3026 static int dissect_id_status(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3027    int offset, int total_len)
3028 {
3029    static int * const status[] = {
3030       &hf_id_status_owned,
3031       &hf_id_status_conf,
3032       &hf_id_status_extended1,
3033       &hf_id_status_minor_fault_rec,
3034       &hf_id_status_minor_fault_unrec,
3035       &hf_id_status_major_fault_rec,
3036       &hf_id_status_major_fault_unrec,
3037       &hf_id_status_extended2,
3038       NULL
3039    };
3040 
3041    if (total_len < 2)
3042    {
3043       expert_add_info(pinfo, item, &ei_mal_identity_status);
3044       return total_len;
3045    }
3046 
3047    proto_tree_add_bitmask(tree, tvb, offset, hf_id_status, ett_id_status, status, ENC_LITTLE_ENDIAN);
3048 
3049    return 2;
3050 }
3051 
dissect_msg_rout_num_classes(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3052 static int dissect_msg_rout_num_classes(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3053                              int offset, int total_len)
3054 {
3055    guint16 i, num_classes;
3056 
3057    num_classes = tvb_get_letohs( tvb, offset);
3058    proto_tree_add_item( tree, hf_msg_rout_num_classes, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3059 
3060    if (total_len < (2+(num_classes*2)))
3061    {
3062       expert_add_info(pinfo, item, &ei_mal_msg_rout_num_classes);
3063       return total_len;
3064    }
3065 
3066    for (i = 0; i < num_classes; i++)
3067       proto_tree_add_item( tree, hf_msg_rout_classes, tvb, offset+2+(i*2), 2, ENC_LITTLE_ENDIAN);
3068 
3069    return (2+(num_classes*2));
3070 }
3071 
dissect_cm_connection_entry_list(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)3072 static int dissect_cm_connection_entry_list(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3073     int offset, int total_len _U_)
3074 {
3075     guint32 num_conn_entries = 0;
3076     guint32 num_conn_entries_bytes;
3077 
3078     proto_tree_add_item_ret_uint(tree, hf_conn_mgr_num_conn_entries, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_conn_entries);
3079 
3080     num_conn_entries_bytes = (num_conn_entries+7)/8;
3081     proto_tree_add_uint(tree, hf_conn_mgr_num_conn_entries_bytes, tvb, 0, 0, num_conn_entries_bytes);
3082 
3083     for (guint32 i = 0; i < num_conn_entries_bytes; i++)
3084     {
3085         proto_tree_add_item(tree, hf_conn_mgr_conn_open_bits, tvb, offset + 2 + i, 1, ENC_LITTLE_ENDIAN);
3086     }
3087 
3088     return 2 + num_conn_entries_bytes;
3089 }
3090 
dissect_time_sync_grandmaster_clock(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3091 static int dissect_time_sync_grandmaster_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3092                              int offset, int total_len)
3093 {
3094    if (total_len < 24)
3095    {
3096       expert_add_info(pinfo, item, &ei_mal_time_sync_gm_clock);
3097       return total_len;
3098    }
3099 
3100    proto_tree_add_item( tree, hf_time_sync_gm_clock_clock_id, tvb, offset, 8, ENC_NA);
3101    proto_tree_add_item( tree, hf_time_sync_gm_clock_clock_class, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3102    proto_tree_add_item( tree, hf_time_sync_gm_clock_time_accuracy, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3103    proto_tree_add_item( tree, hf_time_sync_gm_clock_offset_scaled_log_variance, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
3104    proto_tree_add_item( tree, hf_time_sync_gm_clock_current_utc_offset, tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
3105 
3106    static int* const bits[] = {
3107       &hf_time_sync_gm_clock_time_property_flags_leap61,
3108       &hf_time_sync_gm_clock_time_property_flags_leap59,
3109       &hf_time_sync_gm_clock_time_property_flags_current_utc_valid,
3110       &hf_time_sync_gm_clock_time_property_flags_ptp_timescale,
3111       &hf_time_sync_gm_clock_time_property_flags_time_traceable,
3112       &hf_time_sync_gm_clock_time_property_flags_freq_traceable,
3113       NULL
3114    };
3115    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);
3116 
3117    proto_tree_add_item( tree, hf_time_sync_gm_clock_time_source, tvb, offset+18, 2, ENC_LITTLE_ENDIAN);
3118    proto_tree_add_item( tree, hf_time_sync_gm_clock_priority1, tvb, offset+20, 2, ENC_LITTLE_ENDIAN);
3119    proto_tree_add_item( tree, hf_time_sync_gm_clock_priority2, tvb, offset+22, 2, ENC_LITTLE_ENDIAN);
3120    return 24;
3121 }
3122 
dissect_time_sync_parent_clock(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3123 static int dissect_time_sync_parent_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3124                              int offset, int total_len)
3125 {
3126    if (total_len < 16)
3127    {
3128       expert_add_info(pinfo, item, &ei_mal_time_sync_parent_clock);
3129       return total_len;
3130    }
3131 
3132    proto_tree_add_item( tree, hf_time_sync_parent_clock_clock_id, tvb, offset, 8, ENC_NA);
3133    proto_tree_add_item( tree, hf_time_sync_parent_clock_port_number, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3134    proto_tree_add_item( tree, hf_time_sync_parent_clock_observed_offset_scaled_log_variance, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3135    proto_tree_add_item( tree, hf_time_sync_parent_clock_observed_phase_change_rate, tvb, offset+12, 4, ENC_LITTLE_ENDIAN);
3136    return 16;
3137 }
3138 
dissect_time_sync_local_clock(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3139 static int dissect_time_sync_local_clock(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3140                              int offset, int total_len)
3141 {
3142    if (total_len < 20)
3143    {
3144       expert_add_info(pinfo, item, &ei_mal_time_sync_local_clock);
3145       return total_len;
3146    }
3147 
3148    proto_tree_add_item( tree, hf_time_sync_local_clock_clock_id, tvb, offset, 8, ENC_NA);
3149    proto_tree_add_item( tree, hf_time_sync_local_clock_clock_class, tvb, offset+8, 2, ENC_LITTLE_ENDIAN);
3150    proto_tree_add_item( tree, hf_time_sync_local_clock_time_accuracy, tvb, offset+10, 2, ENC_LITTLE_ENDIAN);
3151    proto_tree_add_item( tree, hf_time_sync_local_clock_offset_scaled_log_variance, tvb, offset+12, 2, ENC_LITTLE_ENDIAN);
3152    proto_tree_add_item( tree, hf_time_sync_local_clock_current_utc_offset, tvb, offset+14, 2, ENC_LITTLE_ENDIAN);
3153 
3154    static int* const bits[] = {
3155       &hf_time_sync_local_clock_time_property_flags_leap61,
3156       &hf_time_sync_local_clock_time_property_flags_leap59,
3157       &hf_time_sync_local_clock_time_property_flags_current_utc_valid,
3158       &hf_time_sync_local_clock_time_property_flags_ptp_timescale,
3159       &hf_time_sync_local_clock_time_property_flags_time_traceable,
3160       &hf_time_sync_local_clock_time_property_flags_freq_traceable,
3161       NULL
3162    };
3163    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);
3164 
3165    proto_tree_add_item( tree, hf_time_sync_local_clock_time_source, tvb, offset+18, 2, ENC_LITTLE_ENDIAN);
3166    return 20;
3167 }
3168 
dissect_time_sync_port_state_info(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3169 static int dissect_time_sync_port_state_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3170                              int offset, int total_len)
3171 {
3172    guint16 i, num_ports;
3173    proto_tree* port_tree;
3174 
3175    if (total_len < 2)
3176    {
3177       expert_add_info(pinfo, item, &ei_mal_time_sync_port_state_info);
3178       return total_len;
3179    }
3180 
3181    num_ports = tvb_get_letohs( tvb, offset);
3182    proto_tree_add_item( tree, hf_time_sync_port_state_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3183 
3184    if (2+num_ports*4 > total_len)
3185    {
3186       expert_add_info(pinfo, item, &ei_mal_time_sync_port_state_info_ports);
3187       return total_len;
3188    }
3189 
3190    for (i = 0; i < num_ports; i++)
3191    {
3192        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);
3193        proto_tree_add_item(port_tree, hf_time_sync_port_state_info_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3194        proto_tree_add_item(port_tree, hf_time_sync_port_state_info_port_state, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3195    }
3196 
3197    return 2+num_ports*4;
3198 }
3199 
dissect_time_sync_port_enable_cfg(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3200 static int dissect_time_sync_port_enable_cfg(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3201                              int offset, int total_len)
3202 {
3203    guint16 i, num_ports;
3204    proto_tree* port_tree;
3205 
3206    if (total_len < 2)
3207    {
3208       expert_add_info(pinfo, item, &ei_mal_time_sync_port_enable_cfg);
3209       return total_len;
3210    }
3211 
3212    num_ports = tvb_get_letohs( tvb, offset);
3213    proto_tree_add_item( tree, hf_time_sync_port_enable_cfg_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3214 
3215    if (2+num_ports*4 > total_len)
3216    {
3217       expert_add_info(pinfo, item, &ei_mal_time_sync_port_enable_cfg_ports);
3218       return total_len;
3219    }
3220 
3221    for (i = 0; i < num_ports; i++)
3222    {
3223        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);
3224        proto_tree_add_item(port_tree, hf_time_sync_port_enable_cfg_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3225        proto_tree_add_item(port_tree, hf_time_sync_port_enable_cfg_port_enable, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3226    }
3227 
3228    return 2+num_ports*4;
3229 }
3230 
dissect_time_sync_port_log_announce(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3231 static int dissect_time_sync_port_log_announce(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3232                              int offset, int total_len)
3233 {
3234    guint16 i, num_ports;
3235    proto_tree* port_tree;
3236 
3237    if (total_len < 2)
3238    {
3239       expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_announce);
3240       return total_len;
3241    }
3242 
3243    num_ports = tvb_get_letohs( tvb, offset);
3244    proto_tree_add_item( tree, hf_time_sync_port_log_announce_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3245 
3246    if (2+num_ports*4 > total_len)
3247    {
3248       expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_announce_ports);
3249       return total_len;
3250    }
3251 
3252    for (i = 0; i < num_ports; i++)
3253    {
3254        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);
3255        proto_tree_add_item(port_tree, hf_time_sync_port_log_announce_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3256        proto_tree_add_item(port_tree, hf_time_sync_port_log_announce_interval, tvb, offset+4+i*4, 2, ENC_LITTLE_ENDIAN);
3257    }
3258 
3259    return 2+num_ports*4;
3260 }
3261 
dissect_time_sync_port_log_sync(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3262 static int dissect_time_sync_port_log_sync(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3263                              int offset, int total_len)
3264 {
3265    guint16 i, num_ports;
3266    proto_tree* port_tree;
3267 
3268    if (total_len < 2)
3269    {
3270       expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_sync);
3271       return total_len;
3272    }
3273 
3274    num_ports = tvb_get_letohs( tvb, offset);
3275    proto_tree_add_item( tree, hf_time_sync_port_log_sync_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3276 
3277    if (2+num_ports*4 > total_len)
3278    {
3279       expert_add_info(pinfo, item, &ei_mal_time_sync_port_log_sync_ports);
3280       return total_len;
3281    }
3282 
3283    for (i = 0; i < num_ports; i++)
3284    {
3285        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);
3286        proto_tree_add_item(port_tree, hf_time_sync_port_log_sync_port_num, tvb, offset+2+i*4, 2, ENC_LITTLE_ENDIAN);
3287        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);
3288    }
3289 
3290    return 2+num_ports*4;
3291 }
3292 
dissect_time_sync_clock_type(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3293 static int dissect_time_sync_clock_type(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3294                              int offset, int total_len)
3295 {
3296    if (total_len < 2)
3297    {
3298       expert_add_info(pinfo, item, &ei_mal_time_sync_clock_type);
3299       return total_len;
3300    }
3301 
3302    static int* const bits[] = {
3303       &hf_time_sync_clock_type_management,
3304       &hf_time_sync_clock_type_end_to_end,
3305       &hf_time_sync_clock_type_boundary,
3306       &hf_time_sync_clock_type_ordinary,
3307       &hf_time_sync_clock_type_slave_only,
3308       NULL
3309    };
3310    proto_tree_add_bitmask(tree, tvb, offset, hf_time_sync_clock_type, ett_time_sync_clock_type, bits, ENC_LITTLE_ENDIAN);
3311 
3312    return 2;
3313 }
3314 
dissect_time_sync_manufacture_id(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3315 static int dissect_time_sync_manufacture_id(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3316                              int offset, int total_len)
3317 {
3318    if (total_len < 4)
3319    {
3320       expert_add_info(pinfo, item, &ei_mal_time_sync_manufacture_id);
3321       return total_len;
3322    }
3323 
3324    proto_tree_add_item( tree, hf_time_sync_manufacture_id_oui, tvb, offset, 3, ENC_LITTLE_ENDIAN);
3325    proto_tree_add_item( tree, hf_time_sync_manufacture_id_reserved, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
3326    return 4;
3327 }
3328 
dissect_time_sync_prod_desc(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3329 static int dissect_time_sync_prod_desc(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3330                              int offset, int total_len)
3331 {
3332    guint32 size;
3333 
3334    if (total_len < 4)
3335    {
3336       expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc);
3337       return total_len;
3338    }
3339 
3340    proto_tree_add_item_ret_uint( tree, hf_time_sync_prod_desc_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
3341 
3342    if (size > 64)
3343    {
3344       expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc_64);
3345       return total_len;
3346    }
3347 
3348    if ((int)(size+4) > total_len)
3349    {
3350       expert_add_info(pinfo, item, &ei_mal_time_sync_prod_desc_size);
3351       return total_len;
3352    }
3353 
3354    proto_tree_add_item( tree, hf_time_sync_prod_desc_str, tvb, offset+4, size, ENC_ASCII|ENC_NA);
3355    return size+4;
3356 }
3357 
dissect_time_sync_revision_data(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3358 static int dissect_time_sync_revision_data(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3359                              int offset, int total_len)
3360 {
3361    guint32 size;
3362 
3363    if (total_len < 4)
3364    {
3365       expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data);
3366       return total_len;
3367    }
3368 
3369    proto_tree_add_item_ret_uint( tree, hf_time_sync_revision_data_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
3370 
3371    if (size > 32)
3372    {
3373       expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data_32);
3374       return total_len;
3375    }
3376 
3377    if ((int)(size+4) > total_len)
3378    {
3379       expert_add_info(pinfo, item, &ei_mal_time_sync_revision_data_size);
3380       return total_len;
3381    }
3382 
3383    proto_tree_add_item( tree, hf_time_sync_revision_data_str, tvb, offset+4, size, ENC_ASCII|ENC_NA);
3384    return size+4;
3385 }
3386 
dissect_time_sync_user_desc(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3387 static int dissect_time_sync_user_desc(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3388                              int offset, int total_len)
3389 {
3390    guint32 size;
3391 
3392    if (total_len < 4)
3393    {
3394       expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc);
3395       return total_len;
3396    }
3397 
3398    proto_tree_add_item_ret_uint( tree, hf_time_sync_user_desc_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &size);
3399 
3400    if (size > 128)
3401    {
3402       expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc_128);
3403       return total_len;
3404    }
3405 
3406    if ((int)(size+4) > total_len)
3407    {
3408       expert_add_info(pinfo, item, &ei_mal_time_sync_user_desc_size);
3409       return total_len;
3410    }
3411 
3412    proto_tree_add_item( tree, hf_time_sync_user_desc_str, tvb, offset+4, size, ENC_ASCII|ENC_NA);
3413    return size+4;
3414 }
3415 
dissect_time_sync_port_profile_id_info(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3416 static int dissect_time_sync_port_profile_id_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3417                              int offset, int total_len)
3418 {
3419    guint16 i, num_ports;
3420    proto_tree* port_tree;
3421 
3422    if (total_len < 2)
3423    {
3424       expert_add_info(pinfo, item, &ei_mal_time_sync_port_profile_id_info);
3425       return total_len;
3426    }
3427 
3428    num_ports = tvb_get_letohs( tvb, offset);
3429    proto_tree_add_item( tree, hf_time_sync_port_profile_id_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3430 
3431    if (2+num_ports*10 > total_len)
3432    {
3433       expert_add_info(pinfo, item, &ei_mal_time_sync_port_profile_id_info_ports);
3434       return total_len;
3435    }
3436 
3437    for (i = 0; i < num_ports; i++)
3438    {
3439        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);
3440        proto_tree_add_item(port_tree, hf_time_sync_port_profile_id_info_port_num, tvb, offset+2+i*10, 2, ENC_LITTLE_ENDIAN);
3441        proto_tree_add_item(port_tree, hf_time_sync_port_profile_id_info_profile_id, tvb, offset+4+i*10, 8, ENC_NA);
3442    }
3443 
3444    return 2+num_ports*10;
3445 }
3446 
dissect_time_sync_port_phys_addr_info(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3447 static int dissect_time_sync_port_phys_addr_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3448                              int offset, int total_len)
3449 {
3450    guint16 i, num_ports;
3451    proto_tree* port_tree;
3452 
3453    if (total_len < 2)
3454    {
3455       expert_add_info(pinfo, item, &ei_mal_time_sync_port_phys_addr_info);
3456       return total_len;
3457    }
3458 
3459    num_ports = tvb_get_letohs( tvb, offset);
3460    proto_tree_add_item( tree, hf_time_sync_port_phys_addr_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3461 
3462    if (2+num_ports*36 > total_len)
3463    {
3464       expert_add_info(pinfo, item, &ei_mal_time_sync_port_phys_addr_info_ports);
3465       return total_len;
3466    }
3467 
3468    for (i = 0; i < num_ports; i++)
3469    {
3470        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);
3471        proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_port_num, tvb, offset+2+i*36, 2, ENC_LITTLE_ENDIAN);
3472        proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_phys_proto, tvb, offset+4+i*36, 16, ENC_ASCII|ENC_NA);
3473 
3474        guint32 addr_size;
3475        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);
3476 
3477        // Field is 16 bytes, but only highlight the actual size.
3478        proto_tree_add_item(port_tree, hf_time_sync_port_phys_addr_info_phys_addr, tvb, offset+22+i*36, addr_size, ENC_NA);
3479    }
3480 
3481    return 2+num_ports*36;
3482 }
3483 
dissect_time_sync_port_proto_addr_info(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3484 static int dissect_time_sync_port_proto_addr_info(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3485                              int offset, int total_len)
3486 {
3487    guint16 i, num_ports;
3488    proto_tree* port_tree;
3489 
3490    if (total_len < 2)
3491    {
3492       expert_add_info(pinfo, item, &ei_mal_time_sync_port_proto_addr_info);
3493       return total_len;
3494    }
3495 
3496    num_ports = tvb_get_letohs( tvb, offset);
3497    proto_tree_add_item( tree, hf_time_sync_port_proto_addr_info_num_ports, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3498 
3499    if (2+num_ports*22 > total_len)
3500    {
3501       expert_add_info(pinfo, item, &ei_mal_time_sync_port_proto_addr_info_ports);
3502       return total_len;
3503    }
3504 
3505    for (i = 0; i < num_ports; i++)
3506    {
3507        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);
3508        proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_port_num, tvb, offset+2+i*22, 2, ENC_LITTLE_ENDIAN);
3509        proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_network_proto, tvb, offset+4+i*22, 2, ENC_LITTLE_ENDIAN);
3510        proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_addr_size, tvb, offset+6+i*22, 2, ENC_LITTLE_ENDIAN);
3511        proto_tree_add_item(port_tree, hf_time_sync_port_proto_addr_info_port_proto_addr, tvb, offset+8+i*22, 16, ENC_NA);
3512    }
3513 
3514    return 2+num_ports*22;
3515 }
3516 
dissect_time_sync_sys_time_and_offset(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3517 static int dissect_time_sync_sys_time_and_offset(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3518                              int offset, int total_len)
3519 {
3520    if (total_len < 16)
3521    {
3522       expert_add_info(pinfo, item, &ei_mal_time_sync_sys_time_and_offset);
3523       return total_len;
3524    }
3525 
3526    dissect_cip_utime(tree, tvb, offset, hf_time_sync_sys_time_and_offset_time);
3527    proto_tree_add_item( tree, hf_time_sync_sys_time_and_offset_offset, tvb, offset+8, 8, ENC_LITTLE_ENDIAN);
3528 
3529    return 16;
3530 }
3531 
dissect_optional_attr_list(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3532 int dissect_optional_attr_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3533    int offset, int total_len)
3534 {
3535    guint32 i;
3536    guint32 num_attr = 0;
3537 
3538    proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_attr_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_attr);
3539 
3540    if (total_len < (int)(2 + num_attr * 2))
3541    {
3542       expert_add_info(pinfo, item, &ei_mal_opt_attr_list);
3543       return total_len;
3544    }
3545 
3546    // Look up the request data to get the CIP Class.
3547    cip_req_info_t *cip_req_info;
3548    cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
3549 
3550    for (i = 0; i < num_attr; ++i)
3551    {
3552       proto_item* attr_item = proto_tree_add_item(tree, hf_attr_class_attr_num, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN);
3553 
3554       // Display attribute name.
3555       if (cip_req_info && cip_req_info->ciaData)
3556       {
3557           attribute_info_t* attr;
3558           attr = cip_get_attribute(cip_req_info->ciaData->iClass, 1, i);
3559           if (attr)
3560           {
3561               proto_item_append_text(attr_item, " (%s)", attr->text);
3562           }
3563       }
3564    }
3565 
3566    return 2 + num_attr * 2;
3567 }
3568 
dissect_optional_service_list(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3569 int dissect_optional_service_list(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3570    int offset, int total_len)
3571 {
3572    guint32 i;
3573    guint32 num_services = 0;
3574 
3575    proto_tree_add_item_ret_uint(tree, hf_attr_class_opt_service_num, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num_services);
3576 
3577    if (total_len < (int)(2 + num_services * 2))
3578    {
3579       expert_add_info(pinfo, item, &ei_mal_opt_service_list);
3580       return total_len;
3581    }
3582 
3583    for (i = 0; i < num_services; ++i)
3584    {
3585       proto_tree_add_item(tree, hf_attr_class_service_code, tvb, offset + 2 + 2 * i, 2, ENC_LITTLE_ENDIAN);
3586    }
3587 
3588    return 2 + num_services * 2;
3589 }
3590 
dissect_port_instance_info(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len)3591 static int dissect_port_instance_info(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3592    int offset, int total_len)
3593 {
3594    int i;
3595 
3596    for (i = 0; i < total_len; i += 4)
3597    {
3598       proto_tree_add_item(tree, hf_port_type, tvb, offset + i, 2, ENC_LITTLE_ENDIAN);
3599       proto_tree_add_item(tree, hf_port_number, tvb, offset + i + 2, 2, ENC_LITTLE_ENDIAN);
3600    }
3601 
3602    return total_len;
3603 }
3604 
dissect_port_associated_comm_objects(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len _U_)3605 static int dissect_port_associated_comm_objects(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3606     int offset, int total_len _U_)
3607 {
3608     guint32 num_entries;
3609     proto_tree_add_item_ret_uint(tree, hf_port_num_comm_object_entries, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_entries);
3610 
3611     int parsed_len = 1;
3612     for (guint32 i = 0; i < num_entries; ++i)
3613     {
3614         parsed_len += dissect_padded_epath_len_usint(pinfo, tree, item, tvb, offset + parsed_len,
3615             tvb_reported_length_remaining(tvb, offset + parsed_len));
3616     }
3617 
3618     return parsed_len;
3619 }
3620 
dissect_padded_epath_len(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len,gboolean one_byte_len)3621 static int dissect_padded_epath_len(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3622    int offset, int total_len, gboolean one_byte_len)
3623 {
3624    guint32     path_size;
3625    proto_tree *epath_tree;
3626    proto_item *path_item;
3627 
3628    guint32 path_size_len;
3629    int hf_path_len;
3630    if (one_byte_len == TRUE)
3631    {
3632       path_size_len = 1;
3633       hf_path_len = hf_path_len_usint;
3634    }
3635    else
3636    {
3637       path_size_len = 2;
3638       hf_path_len = hf_path_len_uint;
3639    }
3640 
3641    path_item = proto_tree_add_item_ret_uint(tree, hf_path_len, tvb, offset, path_size_len, ENC_LITTLE_ENDIAN, &path_size);
3642 
3643    if (total_len < (int)(path_size * 2 + path_size_len))
3644    {
3645       expert_add_info(pinfo, item, &ei_mal_padded_epath_size);
3646       return total_len;
3647    }
3648 
3649    epath_tree = proto_tree_add_subtree(tree, tvb, offset + path_size_len, path_size * 2, ett_path, &path_item, "Path: ");
3650    dissect_epath(tvb, pinfo, epath_tree, path_item, offset + path_size_len, path_size * 2, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
3651 
3652    return path_size * 2 + path_size_len;
3653 }
3654 
3655 /* Format: USINT (Length of EPATH in 16-bit words) + Padded EPATH */
dissect_padded_epath_len_usint(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3656 int dissect_padded_epath_len_usint(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3657    int offset, int total_len)
3658 {
3659    return dissect_padded_epath_len(pinfo, tree, item, tvb, offset, total_len, TRUE);
3660 }
3661 
3662 /* Format: UINT (Length of EPATH in 16-bit words) + Padded EPATH */
dissect_padded_epath_len_uint(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3663 int dissect_padded_epath_len_uint(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3664    int offset, int total_len)
3665 {
3666    return dissect_padded_epath_len(pinfo, tree, item, tvb, offset, total_len, FALSE);
3667 }
3668 
dissect_single_segment_packed_attr(packet_info * pinfo,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)3669 static int dissect_single_segment_packed_attr(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3670    int offset, int total_len _U_)
3671 {
3672    proto_tree *subtree;
3673    proto_item *subitem;
3674    subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_port_path, &subitem, "Path: ");
3675 
3676    int parsed_len = dissect_cip_segment_single(pinfo, tvb, offset, subtree, subitem, FALSE, TRUE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
3677    proto_item_set_len(subitem, parsed_len);
3678 
3679    return parsed_len;
3680 }
3681 
dissect_single_segment_padded_attr(packet_info * pinfo,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)3682 static int dissect_single_segment_padded_attr(packet_info *pinfo, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3683    int offset, int total_len _U_)
3684 {
3685    proto_tree *subtree;
3686    proto_item *subitem;
3687    subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_port_path, &subitem, "Path: ");
3688 
3689    int parsed_len = dissect_cip_segment_single(pinfo, tvb, offset, subtree, subitem, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
3690    proto_item_set_len(subitem, parsed_len);
3691 
3692    return parsed_len;
3693 }
3694 
dissect_port_link_object(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int total_len)3695 static int dissect_port_link_object(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
3696    int offset, int total_len)
3697 {
3698    return dissect_padded_epath_len_uint(pinfo, tree, item, tvb, offset, total_len);
3699 }
3700 
dissect_port_node_range(packet_info * pinfo _U_,proto_tree * tree,proto_item * item _U_,tvbuff_t * tvb,int offset,int total_len _U_)3701 static int dissect_port_node_range(packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, tvbuff_t *tvb,
3702    int offset, int total_len _U_)
3703 {
3704    proto_tree_add_item(tree, hf_port_min_node_num, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3705    proto_tree_add_item(tree, hf_port_max_node_num, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
3706 
3707    return 4;
3708 }
3709 
3710 static attribute_info_t cip_attribute_vals[] = {
3711     /* Identity Object (class attributes) */
3712    {0x01, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3713    {0x01, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3714    {0x01, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3715    {0x01, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3716    {0x01, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3717    {0x01, TRUE, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3718    {0x01, TRUE, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3719 
3720     /* Identity Object (instance attributes) */
3721    {0x01, FALSE, 1, 0, "Vendor ID", cip_uint, &hf_id_vendor_id, NULL},
3722    {0x01, FALSE, 2, 1, "Device Type", cip_uint, &hf_id_device_type, NULL},
3723    {0x01, FALSE, 3, 2, "Product Code", cip_uint, &hf_id_product_code, NULL},
3724    {0x01, FALSE, 4, 3, "Revision", cip_dissector_func, NULL, dissect_id_revision},
3725    {0x01, FALSE, 5, 4, "Status", cip_dissector_func, NULL, dissect_id_status},
3726    {0x01, FALSE, 6, 5, "Serial Number", cip_udint, &hf_id_serial_number, NULL},
3727    {0x01, FALSE, 7, 6, "Product Name", cip_short_string, &hf_id_product_name, NULL},
3728    {0x01, FALSE, 8, 7, "State", cip_usint, &hf_id_state, NULL},
3729    {0x01, FALSE, 9, 8, "Configuration Consistency Value", cip_uint, &hf_id_config_value, NULL},
3730    {0x01, FALSE, 10, 9, "Heartbeat Interval", cip_usint, &hf_id_heartbeat, NULL},
3731 
3732     /* Message Router Object (class attributes) */
3733    {0x02, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3734    {0x02, TRUE, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3735    {0x02, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3736    {0x02, TRUE, 4, 1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3737    {0x02, TRUE, 5, 2, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3738    {0x02, TRUE, 6, 3, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3739    {0x02, TRUE, 7, 4, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3740 
3741     /* Message Router Object (instance attributes) */
3742    {0x02, FALSE, 1, 0, "Object List", cip_dissector_func, NULL, dissect_msg_rout_num_classes},
3743    {0x02, FALSE, 2, 1, "Number Available", cip_uint, &hf_msg_rout_num_available, NULL},
3744    {0x02, FALSE, 3, 2, "Number Active", cip_uint, &hf_msg_rout_num_active, NULL},
3745    {0x02, FALSE, 4, 3, "Active Connections", cip_uint_array, &hf_msg_rout_active_connections, NULL},
3746 
3747     /* Connection Manager Object (class attributes) */
3748    {0x06, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3749    {0x06, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3750    {0x06, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3751    {0x06, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3752    {0x06, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3753    {0x06, TRUE, 6, 2, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3754    {0x06, TRUE, 7, 3, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3755 
3756     /* Connection Manager Object (instance attributes) */
3757    {0x06, FALSE, 1, 0, "Open Requests", cip_uint, &hf_conn_mgr_open_requests, NULL},
3758    {0x06, FALSE, 2, 1, "Open Format Rejects", cip_uint, &hf_conn_mgr_open_format_rejects, NULL},
3759    {0x06, FALSE, 3, 2, "Open Resource Rejects", cip_uint, &hf_conn_mgr_open_resource_rejects, NULL},
3760    {0x06, FALSE, 4, 3, "Other Open Rejects", cip_uint, &hf_conn_mgr_other_open_rejects, NULL},
3761    {0x06, FALSE, 5, 4, "Close Requests", cip_uint, &hf_conn_mgr_close_requests, NULL},
3762    {0x06, FALSE, 6, 5, "Close Format Requests", cip_uint, &hf_conn_close_format_requests, NULL},
3763    {0x06, FALSE, 7, 6, "Close Other Requests", cip_uint, &hf_conn_mgr_close_other_requests, NULL},
3764    {0x06, FALSE, 8, 7, "Connection Timeouts", cip_uint, &hf_conn_mgr_conn_timouts, NULL},
3765    {0x06, FALSE, 9, 8, "Connection Entry List", cip_dissector_func, NULL, dissect_cm_connection_entry_list },
3766    {0x06, FALSE, 11, 9, "CPU Utilization", cip_uint, &hf_conn_mgr_cpu_utilization, NULL },
3767    {0x06, FALSE, 12, 10, "Max Buff Size", cip_udint, &hf_conn_mgr_max_buff_size, NULL },
3768    {0x06, FALSE, 13, 11, "Buff Size Remaining", cip_udint, &hf_conn_mgr_buff_size_remaining, NULL },
3769 
3770     /* File Object (instance attributes) */
3771    {0x37, FALSE, 4, -1, "File Name", cip_stringi, &hf_file_filename, NULL },
3772 
3773     /* Time Sync Object (class attributes) */
3774    {0x43, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3775    {0x43, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3776    {0x43, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3777    {0x43, TRUE, 4, 3, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3778    {0x43, TRUE, 5, 4, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3779    {0x43, TRUE, 6, 5, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3780    {0x43, TRUE, 7, 6, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3781 
3782     /* Time Sync Object (instance attributes) */
3783    {0x43, FALSE, 1, -1, "PTP Enable", cip_bool, &hf_time_sync_ptp_enable, NULL},
3784    {0x43, FALSE, 2, -1, "Is Synchronized", cip_bool, &hf_time_sync_is_synchronized, NULL},
3785    {0x43, FALSE, 3, -1, "System Time (Microseconds)", cip_utime, &hf_time_sync_sys_time_micro, NULL},
3786    {0x43, FALSE, 4, -1, "System Time (Nanoseconds)", cip_stime, &hf_time_sync_sys_time_nano, NULL},
3787    {0x43, FALSE, 5, -1, "Offset from Master", cip_ntime, &hf_time_sync_offset_from_master, NULL},
3788    {0x43, FALSE, 6, -1, "Max Offset from Master", cip_ulint, &hf_time_sync_max_offset_from_master, NULL},
3789    {0x43, FALSE, 7, -1, "Mean Path Delay To Master", cip_ntime, &hf_time_sync_mean_path_delay_to_master, NULL},
3790    {0x43, FALSE, 8, -1, "Grand Master Clock Info", cip_dissector_func, NULL, dissect_time_sync_grandmaster_clock},
3791    {0x43, FALSE, 9, -1, "Parent Clock Info", cip_dissector_func, NULL, dissect_time_sync_parent_clock},
3792    {0x43, FALSE, 10, -1, "Local Clock Info", cip_dissector_func, NULL, dissect_time_sync_local_clock},
3793    {0x43, FALSE, 11, -1, "Number of Ports", cip_uint, &hf_time_sync_num_ports, NULL},
3794    {0x43, FALSE, 12, -1, "Port State Info", cip_dissector_func, NULL, dissect_time_sync_port_state_info},
3795    {0x43, FALSE, 13, -1, "Port Enable Cfg", cip_dissector_func, NULL, dissect_time_sync_port_enable_cfg},
3796    {0x43, FALSE, 14, -1, "Port Log Announcement Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_announce},
3797    {0x43, FALSE, 15, -1, "Port Log Sync Interval Cfg", cip_dissector_func, NULL, dissect_time_sync_port_log_sync},
3798    {0x43, FALSE, 16, -1, "Priority1", cip_usint, &hf_time_sync_priority1, NULL},
3799    {0x43, FALSE, 17, -1, "Priority2", cip_usint, &hf_time_sync_priority2, NULL},
3800    {0x43, FALSE, 18, -1, "Domain number", cip_usint, &hf_time_sync_domain_number, NULL},
3801    {0x43, FALSE, 19, -1, "Clock Type", cip_dissector_func, NULL, dissect_time_sync_clock_type},
3802    {0x43, FALSE, 20, -1, "Manufacture Identity", cip_dissector_func, NULL, dissect_time_sync_manufacture_id},
3803    {0x43, FALSE, 21, -1, "Product Description", cip_dissector_func, NULL, dissect_time_sync_prod_desc},
3804    {0x43, FALSE, 22, -1, "Revision Data", cip_dissector_func, NULL, dissect_time_sync_revision_data},
3805    {0x43, FALSE, 23, -1, "User Description", cip_dissector_func, NULL, dissect_time_sync_user_desc},
3806    {0x43, FALSE, 24, -1, "Port Profile Identity Info", cip_dissector_func, NULL, dissect_time_sync_port_profile_id_info},
3807    {0x43, FALSE, 25, -1, "Port Physical Address Info", cip_dissector_func, NULL, dissect_time_sync_port_phys_addr_info},
3808    {0x43, FALSE, 26, -1, "Port Protocol Address Info", cip_dissector_func, NULL, dissect_time_sync_port_proto_addr_info},
3809    {0x43, FALSE, 27, -1, "Steps Removed", cip_uint, &hf_time_sync_steps_removed, NULL},
3810    {0x43, FALSE, 28, -1, "System Time and Offset", cip_dissector_func, NULL, dissect_time_sync_sys_time_and_offset},
3811 
3812 
3813    /* Connection Configuration Object (class attributes) */
3814    /* Data sizes are different than common class attributes for some items. */
3815    { 0xF3, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3816    { 0xF3, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_udint, &hf_cip_class_max_inst32, NULL },
3817    { 0xF3, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_udint, &hf_cip_class_num_inst32, NULL },
3818    { 0xF3, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3819    { 0xF3, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3820    { 0xF3, TRUE, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3821    { 0xF3, TRUE, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3822    { 0xF3, TRUE, 8, 3, "Format Number", cip_uint, &hf_cip_cco_format_number, NULL },
3823    { 0xF3, TRUE, 9, 4, "Edit Signature", cip_udint, &hf_cip_cco_edit_signature, NULL },
3824 
3825    /* Port Object (class attributes) */
3826    { 0xF4, TRUE, 1, 0, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3827    { 0xF4, TRUE, 2, 1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3828    { 0xF4, TRUE, 3, 2, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3829    { 0xF4, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3830    { 0xF4, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3831    { 0xF4, TRUE, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3832    { 0xF4, TRUE, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3833    { 0xF4, TRUE, 8, 3, "Entry Port", cip_uint, &hf_port_entry_port, NULL },
3834    { 0xF4, TRUE, 9, 4, "Port Instance Info", cip_dissector_func, NULL, dissect_port_instance_info },
3835 
3836    /* Port Object (instance attributes) */
3837    { 0xF4, FALSE, 1, 0, "Port Type", cip_uint, &hf_port_type, NULL },
3838    { 0xF4, FALSE, 2, 1, "Port Number", cip_uint, &hf_port_number, NULL },
3839    { 0xF4, FALSE, 3, 2, "Link Object", cip_dissector_func, NULL, dissect_port_link_object },
3840    { 0xF4, FALSE, 4, 3, "Port Name", cip_short_string, &hf_port_name, NULL },
3841    { 0xF4, FALSE, 7, 4, "Port Number and Node Address", cip_dissector_func, NULL, dissect_single_segment_padded_attr },
3842    { 0xF4, FALSE, 8, -1, "Port Node Range", cip_dissector_func, NULL, dissect_port_node_range },
3843    { 0xF4, FALSE, 9, -1, "Chassis Identity", cip_dissector_func, NULL, dissect_single_segment_packed_attr },
3844    { 0xF4, FALSE, 11, -1, "Associated Communication Objects", cip_dissector_func, NULL, dissect_port_associated_comm_objects },
3845 };
3846 
3847 typedef struct attribute_val_array {
3848    size_t size;
3849    attribute_info_t* attrs;
3850 } attribute_val_array_t;
3851 
3852 /* Each entry in this table (eg: cip_attribute_vals) is a list of:
3853     Attribute information (class_id/class_instance/attribute) to attribute property
3854 
3855     Note: If more items are added to the individual tables, it may make sense
3856       to switch to a more efficient implementation (eg: hash table).
3857 */
3858 
3859 static attribute_val_array_t all_attribute_vals[] = {
3860    {sizeof(cip_attribute_vals)/sizeof(attribute_info_t), cip_attribute_vals},
3861    {sizeof(enip_attribute_vals)/sizeof(attribute_info_t), enip_attribute_vals},
3862    {sizeof(cip_safety_attribute_vals)/sizeof(attribute_info_t), cip_safety_attribute_vals},
3863    {sizeof(cip_motion_attribute_vals)/sizeof(attribute_info_t), cip_motion_attribute_vals},
3864 };
3865 
cip_get_attribute(guint class_id,guint instance,guint attribute)3866 attribute_info_t* cip_get_attribute(guint class_id, guint instance, guint attribute)
3867 {
3868    size_t i, j;
3869    attribute_val_array_t* att_array;
3870    attribute_info_t* pattr;
3871 
3872    static attribute_info_t class_attribute_vals[] = {
3873       { 0, TRUE, 1, -1, CLASS_ATTRIBUTE_1_NAME, cip_uint, &hf_attr_class_revision, NULL },
3874       { 0, TRUE, 2, -1, CLASS_ATTRIBUTE_2_NAME, cip_uint, &hf_attr_class_max_instance, NULL },
3875       { 0, TRUE, 3, -1, CLASS_ATTRIBUTE_3_NAME, cip_uint, &hf_attr_class_num_instance, NULL },
3876       { 0, TRUE, 4, -1, CLASS_ATTRIBUTE_4_NAME, cip_dissector_func, NULL, dissect_optional_attr_list },
3877       { 0, TRUE, 5, -1, CLASS_ATTRIBUTE_5_NAME, cip_dissector_func, NULL, dissect_optional_service_list },
3878       { 0, TRUE, 6, -1, CLASS_ATTRIBUTE_6_NAME, cip_uint, &hf_attr_class_num_class_attr, NULL },
3879       { 0, TRUE, 7, -1, CLASS_ATTRIBUTE_7_NAME, cip_uint, &hf_attr_class_num_inst_attr, NULL },
3880    };
3881 
3882    for (i = 0; i < sizeof(all_attribute_vals)/sizeof(attribute_val_array_t); i++)
3883    {
3884       att_array = &all_attribute_vals[i];
3885       for (j = 0; j < att_array->size; j++)
3886       {
3887          pattr = &att_array->attrs[j];
3888          if ((pattr->class_id == class_id) &&
3889              (instance != SEGMENT_VALUE_NOT_SET) &&
3890              (((instance == 0) && (pattr->class_instance == TRUE)) || ((instance != 0) && (pattr->class_instance == FALSE))) &&
3891              (pattr->attribute == attribute))
3892          {
3893             return pattr;
3894          }
3895       }
3896    }
3897 
3898    /* Check against common class attributes. */
3899    if (instance == 0)
3900    {
3901       for (i = 0; i < sizeof(class_attribute_vals) / sizeof(attribute_info_t); i++)
3902       {
3903          pattr = &class_attribute_vals[i];
3904          if (pattr->attribute == attribute)
3905          {
3906             return pattr;
3907          }
3908       }
3909    }
3910 
3911    return NULL;
3912 }
3913 
3914 static const char *
3915 segment_name_format(const char *segment_name, const char *fmt)
3916     G_GNUC_FORMAT(2);
3917 
3918 static const char *
segment_name_format(const char * segment_name,const char * fmt)3919 segment_name_format(const char *segment_name, const char *fmt)
3920 {
3921    wmem_strbuf_t *strbuf;
3922 
3923    strbuf = wmem_strbuf_new(wmem_packet_scope(), segment_name);
3924    wmem_strbuf_append(strbuf, fmt);
3925    return wmem_strbuf_get_str(strbuf);
3926 }
3927 
3928 static int
dissect_cia(tvbuff_t * tvb,int offset,unsigned char segment_type,gboolean generate,gboolean packed,packet_info * pinfo,proto_item * epath_item,proto_tree * path_tree,proto_item * path_item,proto_item ** ret_item,const char * segment_name,const value_string * vals,int * value,int hf8,int hf16,int hf32)3929 dissect_cia(tvbuff_t *tvb, int offset, unsigned char segment_type,
3930             gboolean generate, gboolean packed, packet_info *pinfo, proto_item *epath_item,
3931             proto_tree *path_tree, proto_item *path_item, proto_item ** ret_item,
3932             const char* segment_name, const value_string* vals, int* value,
3933             int hf8, int hf16, int hf32)
3934 {
3935    unsigned char logical_format;
3936    int segment_len;
3937    int temp_data;
3938    int value_offset;
3939    wmem_strbuf_t *strbuf;
3940    gboolean extended_logical = FALSE;
3941 
3942    /* Extended Logical Format is slightly different than other logical formats. An extra byte is
3943       inserted after the segment type. */
3944    if ((segment_type & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_EXT_LOGICAL)
3945    {
3946       extended_logical = TRUE;
3947 
3948       if (generate)
3949       {
3950          temp_data = tvb_get_guint8(tvb, offset + 1);
3951          *ret_item = proto_tree_add_uint(path_tree, hf_cip_ext_logical_type, tvb, 0, 0, temp_data);
3952          proto_item_set_generated(*ret_item);
3953       }
3954       else
3955       {
3956          *ret_item = proto_tree_add_item(path_tree, hf_cip_ext_logical_type, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
3957       }
3958    }
3959 
3960    logical_format = segment_type & CI_LOGICAL_SEG_FORMAT_MASK;
3961    switch (logical_format)
3962    {
3963    case CI_LOGICAL_SEG_8_BIT:
3964       value_offset = offset + 1;
3965 
3966       if (extended_logical == TRUE)
3967       {
3968          value_offset += 1;
3969       }
3970 
3971       temp_data = tvb_get_guint8(tvb, value_offset);
3972 
3973       if ( generate )
3974       {
3975          *ret_item = proto_tree_add_uint(path_tree, hf8, tvb, 0, 0, temp_data );
3976          proto_item_set_generated(*ret_item);
3977       }
3978       else
3979       {
3980          *ret_item = proto_tree_add_item(path_tree, hf8, tvb, value_offset, 1, ENC_LITTLE_ENDIAN);
3981       }
3982 
3983       if (vals == NULL)
3984       {
3985          proto_item_append_text( epath_item, "%s: 0x%02X", segment_name,  temp_data);
3986       }
3987       else
3988       {
3989          proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( segment_name, ": 0x%02X" ) ) );
3990       }
3991 
3992       if (value != NULL)
3993          *value = temp_data;
3994 
3995       segment_len = 2;
3996       if (extended_logical == TRUE)
3997       {
3998          if (packed)
3999          {
4000             segment_len += 1;
4001          }
4002          else
4003          {
4004             segment_len += 2;
4005          }
4006       }
4007       break;
4008    case CI_LOGICAL_SEG_16_BIT:
4009       if (packed && extended_logical == FALSE)
4010       {
4011          value_offset = offset + 1;
4012          segment_len = 3;
4013       }
4014       else
4015       {
4016          value_offset = offset + 2;
4017          segment_len = 4;
4018       }
4019 
4020       temp_data = tvb_get_letohs(tvb, value_offset);
4021 
4022       if ( generate )
4023       {
4024          *ret_item = proto_tree_add_uint(path_tree, hf16, tvb, 0, 0, temp_data );
4025          proto_item_set_generated(*ret_item);
4026       }
4027       else
4028       {
4029          *ret_item = proto_tree_add_item(path_tree, hf16, tvb, value_offset, 2, ENC_LITTLE_ENDIAN);
4030       }
4031 
4032       if (vals == NULL)
4033       {
4034          proto_item_append_text( epath_item, "%s: 0x%04X", segment_name,  temp_data);
4035       }
4036       else
4037       {
4038          strbuf = wmem_strbuf_new(wmem_packet_scope(), segment_name);
4039          wmem_strbuf_append(strbuf, ": 0x%04X");
4040 
4041          proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( segment_name, ": 0x%04X" ) ) );
4042       }
4043 
4044       if (value != NULL)
4045          *value = temp_data;
4046 
4047       break;
4048    case CI_LOGICAL_SEG_32_BIT:
4049       if (packed && extended_logical == FALSE)
4050       {
4051          value_offset = offset + 1;
4052          segment_len = 5;
4053       }
4054       else
4055       {
4056          value_offset = offset + 2;
4057          segment_len = 6;
4058       }
4059       temp_data = tvb_get_letohl(tvb, value_offset);
4060 
4061       if ( generate )
4062       {
4063          *ret_item = proto_tree_add_uint(path_tree, hf32, tvb, 0, 0, temp_data );
4064          proto_item_set_generated(*ret_item);
4065       }
4066       else
4067       {
4068          *ret_item = proto_tree_add_item(path_tree, hf32, tvb, value_offset, 4, ENC_LITTLE_ENDIAN);
4069       }
4070 
4071       if (vals == NULL)
4072       {
4073          proto_item_append_text( epath_item, "%s: 0x%08X", segment_name,  temp_data);
4074       }
4075       else
4076       {
4077          strbuf = wmem_strbuf_new(wmem_packet_scope(), segment_name);
4078          wmem_strbuf_append(strbuf, ": 0x%08X");
4079 
4080          proto_item_append_text( epath_item, "%s", val_to_str( temp_data, vals, segment_name_format( segment_name, ": 0x%08X" ) ) );
4081       }
4082 
4083       if (value != NULL)
4084          *value = temp_data;
4085 
4086       break;
4087    default:
4088       expert_add_info(pinfo, epath_item, &ei_proto_log_seg_format);
4089       return 0;
4090    }
4091 
4092    if (generate == FALSE)
4093    {
4094       proto_item_set_len(path_item, segment_len);
4095    }
4096 
4097    return segment_len;
4098 }
4099 
4100 /* Dissect Device ID structure */
4101 void
dissect_deviceid(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_vendor,int hf_devtype,int hf_prodcode,int hf_compatibility,int hf_comp_bit,int hf_majrev,int hf_minrev,gboolean generate)4102 dissect_deviceid(tvbuff_t *tvb, int offset, proto_tree *tree,
4103                  int hf_vendor, int hf_devtype, int hf_prodcode,
4104                  int hf_compatibility, int hf_comp_bit, int hf_majrev, int hf_minrev,
4105                  gboolean generate)
4106 {
4107    proto_item* vendor_id_item = proto_tree_add_item(tree, hf_vendor, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4108    proto_item* device_type_item = proto_tree_add_item(tree, hf_devtype, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4109    proto_item* product_code_item = proto_tree_add_item(tree, hf_prodcode, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
4110 
4111    /* Major revision/Compatibility */
4112    guint8 compatibility = tvb_get_guint8(tvb, offset + 6);
4113 
4114    /* Add Major revision/Compatibility tree */
4115    proto_item* compatibility_item = proto_tree_add_uint_format_value(tree, hf_compatibility,
4116       tvb, offset + 6, 1, compatibility, "%s, Major Revision: %d",
4117       val_to_str_const((compatibility & 0x80) >> 7, cip_com_bit_vals, ""),
4118       compatibility & 0x7F);
4119    proto_tree* compatibility_tree = proto_item_add_subtree(compatibility_item, ett_mcsc);
4120 
4121    proto_item* comp_bit_item = proto_tree_add_item(compatibility_tree, hf_comp_bit, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
4122    proto_item* major_rev_item = proto_tree_add_item(compatibility_tree, hf_majrev, tvb, offset + 6, 1, ENC_LITTLE_ENDIAN);
4123    proto_item* minor_rev_item = proto_tree_add_item(tree, hf_minrev, tvb, offset + 7, 1, ENC_LITTLE_ENDIAN);
4124 
4125    if (generate)
4126    {
4127       proto_item_set_generated(vendor_id_item);
4128       proto_item_set_generated(device_type_item);
4129       proto_item_set_generated(product_code_item);
4130       proto_item_set_generated(compatibility_item);
4131       proto_item_set_generated(comp_bit_item);
4132       proto_item_set_generated(major_rev_item);
4133       proto_item_set_generated(minor_rev_item);
4134    }
4135 }
4136 
4137 static void
dissect_net_param16(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_net_param16,int hf_owner,int hf_type,int hf_priority,int hf_fixed_var,int hf_con_size,gint ncp_ett,cip_connID_info_t * conn_info)4138 dissect_net_param16(tvbuff_t *tvb, int offset, proto_tree *tree,
4139                  int hf_net_param16, int hf_owner, int hf_type,
4140                  int hf_priority, int hf_fixed_var, int hf_con_size, gint ncp_ett, cip_connID_info_t* conn_info)
4141 {
4142    proto_item *net_param_item;
4143    proto_tree *net_param_tree;
4144 
4145    net_param_item = proto_tree_add_item(tree, hf_net_param16, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4146    net_param_tree = proto_item_add_subtree(net_param_item, ncp_ett);
4147 
4148    /* Add the data to the tree */
4149    proto_tree_add_item(net_param_tree, hf_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4150    proto_tree_add_item_ret_uint(net_param_tree, hf_type, tvb, offset, 2, ENC_LITTLE_ENDIAN, &conn_info->type);
4151    proto_tree_add_item(net_param_tree, hf_priority, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4152    proto_tree_add_item(net_param_tree, hf_fixed_var, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4153    proto_tree_add_item(net_param_tree, hf_con_size, tvb, offset, 2, ENC_LITTLE_ENDIAN );
4154 }
4155 
4156 static void
dissect_net_param32(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_net_param16,int hf_owner,int hf_type,int hf_priority,int hf_fixed_var,int hf_con_size,gint ncp_ett,cip_connID_info_t * conn_info)4157 dissect_net_param32(tvbuff_t *tvb, int offset, proto_tree *tree,
4158                  int hf_net_param16, int hf_owner, int hf_type,
4159                  int hf_priority, int hf_fixed_var, int hf_con_size, gint ncp_ett, cip_connID_info_t* conn_info)
4160 {
4161    proto_item *net_param_item;
4162    proto_tree *net_param_tree;
4163 
4164    net_param_item = proto_tree_add_item(tree, hf_net_param16, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4165    net_param_tree = proto_item_add_subtree(net_param_item, ncp_ett);
4166 
4167    /* Add the data to the tree */
4168    proto_tree_add_item(net_param_tree, hf_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4169    proto_tree_add_item_ret_uint(net_param_tree, hf_type, tvb, offset, 4, ENC_LITTLE_ENDIAN, &conn_info->type);
4170    proto_tree_add_item(net_param_tree, hf_priority, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4171    proto_tree_add_item(net_param_tree, hf_fixed_var, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4172    proto_tree_add_item(net_param_tree, hf_con_size, tvb, offset, 4, ENC_LITTLE_ENDIAN );
4173 }
4174 
4175 static void
dissect_transport_type_trigger(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_ttt,int hf_direction,int hf_trigger,int hf_class,gint ett)4176 dissect_transport_type_trigger(tvbuff_t *tvb, int offset, proto_tree *tree,
4177                  int hf_ttt, int hf_direction, int hf_trigger, int hf_class, gint ett)
4178 {
4179    int* const bits[] = {
4180       &hf_direction,
4181       &hf_trigger,
4182       &hf_class,
4183       NULL
4184    };
4185 
4186    proto_tree_add_bitmask(tree, tvb, offset, hf_ttt, ett, bits, ENC_LITTLE_ENDIAN);
4187 }
4188 
dissect_segment_network_extended(packet_info * pinfo,proto_item * epath_item,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * net_tree)4189 static int dissect_segment_network_extended(packet_info *pinfo, proto_item *epath_item, tvbuff_t *tvb, int offset, gboolean generate, proto_tree *net_tree)
4190 {
4191    int data_words;
4192    data_words = tvb_get_guint8(tvb, offset + 1);
4193 
4194    if (generate)
4195    {
4196       proto_item *it;
4197       guint16 temp_data;
4198 
4199       it = proto_tree_add_uint(net_tree, hf_cip_seg_network_size, tvb, 0, 0, data_words);
4200       proto_item_set_generated(it);
4201 
4202       temp_data = tvb_get_letohs(tvb, offset + 2);
4203       it = proto_tree_add_uint(net_tree, hf_cip_seg_network_subtype, tvb, 0, 0, temp_data);
4204       proto_item_set_generated(it);
4205    }
4206    else
4207    {
4208       proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4209       proto_tree_add_item(net_tree, hf_cip_seg_network_subtype, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4210    }
4211 
4212    // Extended Network Subtype is included in the Number of Data words, so we must have at least 1.
4213    if (data_words < 1)
4214    {
4215       expert_add_info(pinfo, epath_item, &ei_proto_ext_network);
4216       return 0;
4217    }
4218 
4219    if (generate == FALSE)
4220    {
4221       /* The first word of the data is the extended segment subtype, so
4222          don't include that in the displayed data block. */
4223       int net_seg_data_offset;
4224       int net_seg_data_len;
4225       net_seg_data_offset = offset + 4;
4226       net_seg_data_len = (data_words - 1) * 2;
4227 
4228       if (tvb_reported_length_remaining(tvb, net_seg_data_offset) < net_seg_data_len)
4229       {
4230           expert_add_info(pinfo, epath_item, &ei_proto_ext_network);
4231           return 0;
4232       }
4233 
4234       if (net_seg_data_len > 0)
4235       {
4236           proto_tree_add_item(net_tree, hf_cip_data, tvb, net_seg_data_offset, net_seg_data_len, ENC_NA);
4237       }
4238    }
4239 
4240    return data_words * 2 + 2;
4241 }
4242 
dissect_segment_network_production_inhibit_us(tvbuff_t * tvb,int offset,gboolean generate,proto_tree * net_tree)4243 static int dissect_segment_network_production_inhibit_us(tvbuff_t *tvb, int offset, gboolean generate, proto_tree *net_tree)
4244 {
4245    int data_words;
4246    guint32 inhibit_time;
4247 
4248    data_words = tvb_get_guint8(tvb, offset + 1);
4249    inhibit_time = tvb_get_letohl(tvb, offset + 2);
4250 
4251    if (generate == TRUE)
4252    {
4253       proto_item *it;
4254       it = proto_tree_add_uint(net_tree, hf_cip_seg_network_size, tvb, 0, 0, data_words);
4255       proto_item_set_generated(it);
4256 
4257       it = proto_tree_add_uint(net_tree, hf_cip_seg_prod_inhibit_time_us, tvb, 0, 0, inhibit_time);
4258       proto_item_set_generated(it);
4259    }
4260    else
4261    {
4262       proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4263       proto_tree_add_item(net_tree, hf_cip_seg_prod_inhibit_time_us,
4264          tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
4265    }
4266 
4267    return (data_words * 2) + 2;
4268 }
4269 
dissect_segment_symbolic(tvbuff_t * tvb,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item,int offset,gboolean generate)4270 static int dissect_segment_symbolic(tvbuff_t *tvb, proto_tree *path_seg_tree,
4271    proto_item *path_seg_item, proto_item *epath_item,
4272    int offset, gboolean generate)
4273 {
4274    int seg_size;
4275    proto_item *it;
4276    guint8 symbol_size;
4277 
4278    symbol_size = tvb_get_guint8(tvb, offset) & 0x1F;
4279    if (generate)
4280    {
4281       it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_size, tvb, 0, 0, symbol_size);
4282       proto_item_set_generated(it);
4283    }
4284    else
4285    {
4286       proto_tree_add_item(path_seg_tree, hf_cip_symbol_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4287    }
4288 
4289    if (symbol_size != 0)
4290    {
4291       gchar *symbol_name;
4292       symbol_name = tvb_format_text(wmem_packet_scope(), tvb, offset + 1, symbol_size);
4293 
4294       proto_item_append_text(path_seg_item, " (Symbolic Segment)");
4295 
4296       if (generate)
4297       {
4298          it = proto_tree_add_string(path_seg_tree, hf_cip_symbol_ascii, tvb, 0, 0, symbol_name);
4299          proto_item_set_generated(it);
4300       }
4301       else
4302       {
4303          proto_tree_add_item(path_seg_tree, hf_cip_symbol_ascii, tvb, offset + 1, symbol_size, ENC_ASCII | ENC_NA);
4304       }
4305 
4306       proto_item_append_text(epath_item, "%s", symbol_name);
4307 
4308       seg_size = symbol_size + 1;
4309    }
4310    else
4311    {
4312       /* Extended String */
4313       guint8 string_format;
4314       guint8 string_size;
4315       int data_size = 0;
4316 
4317       proto_item_append_text(path_seg_item, " (Extended String Symbolic Segment)");
4318 
4319       string_format = tvb_get_guint8(tvb, offset + 1) & CI_SYMBOL_SEG_FORMAT_MASK;
4320       string_size = tvb_get_guint8(tvb, offset + 1) & CI_SYMBOL_SEG_SIZE_MASK;
4321 
4322       if (generate)
4323       {
4324          it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_extended_format, tvb, 0, 0, string_format);
4325          proto_item_set_generated(it);
4326       }
4327       else
4328       {
4329          proto_tree_add_item(path_seg_tree, hf_cip_symbol_extended_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4330       }
4331 
4332       switch (string_format)
4333       {
4334       case CI_SYMBOL_SEG_DOUBLE:
4335          data_size = string_size * 2;
4336 
4337          if (generate)
4338          {
4339             it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_double_size, tvb, 0, 0, string_size);
4340             proto_item_set_generated(it);
4341          }
4342          else
4343          {
4344             proto_tree_add_item(path_seg_tree, hf_cip_symbol_double_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4345             proto_tree_add_item(path_seg_tree, hf_cip_data, tvb, offset + 2, data_size, ENC_NA);
4346          }
4347 
4348          proto_item_append_text(epath_item, "[Data]");
4349 
4350          break;
4351       case CI_SYMBOL_SEG_TRIPLE:
4352          data_size = string_size * 3;
4353 
4354          if (generate)
4355          {
4356             it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_triple_size, tvb, 0, 0, string_size);
4357             proto_item_set_generated(it);
4358          }
4359          else
4360          {
4361             proto_tree_add_item(path_seg_tree, hf_cip_symbol_triple_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4362             proto_tree_add_item(path_seg_tree, hf_cip_data, tvb, offset + 2, data_size, ENC_NA);
4363          }
4364 
4365          proto_item_append_text(epath_item, "[Data]");
4366 
4367          break;
4368       case CI_SYMBOL_SEG_NUMERIC:
4369       {
4370          guint32 numeric_data;
4371 
4372          if (generate)
4373          {
4374             it = proto_tree_add_uint(path_seg_tree, hf_cip_symbol_numeric_format, tvb, 0, 0, string_size);
4375             proto_item_set_generated(it);
4376          }
4377          else
4378          {
4379             proto_tree_add_item(path_seg_tree, hf_cip_symbol_numeric_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4380          }
4381 
4382          if (string_size == CI_SYMBOL_NUMERIC_USINT)
4383          {
4384             data_size = 1;
4385             numeric_data = tvb_get_guint8(tvb, offset + 2);
4386 
4387             if (generate)
4388             {
4389                it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_usint, tvb, 0, 0, numeric_data);
4390                proto_item_set_generated(it);
4391             }
4392             else
4393             {
4394                proto_tree_add_item(path_seg_tree, hf_cip_numeric_usint, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN);
4395             }
4396          }
4397          else if (string_size == CI_SYMBOL_NUMERIC_UINT)
4398          {
4399             data_size = 2;
4400             numeric_data = tvb_get_letohs(tvb, offset + 2);
4401 
4402             if (generate)
4403             {
4404                it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_uint, tvb, 0, 0, numeric_data);
4405                proto_item_set_generated(it);
4406             }
4407             else
4408             {
4409                proto_tree_add_item(path_seg_tree, hf_cip_numeric_uint, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
4410             }
4411          }
4412          else if (string_size == CI_SYMBOL_NUMERIC_UDINT)
4413          {
4414             data_size = 4;
4415             numeric_data = tvb_get_letohl(tvb, offset + 2);
4416 
4417             if (generate)
4418             {
4419                it = proto_tree_add_uint(path_seg_tree, hf_cip_numeric_udint, tvb, 0, 0, numeric_data);
4420                proto_item_set_generated(it);
4421             }
4422             else
4423             {
4424                proto_tree_add_item(path_seg_tree, hf_cip_numeric_udint, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
4425             }
4426          }
4427          else
4428          {
4429             /* Unknown Extended String Format. */
4430             return 0;
4431          }
4432 
4433          proto_item_append_text(epath_item, "0x%x", numeric_data);
4434 
4435          break;
4436       }
4437       default:
4438          /* Unknown Extended String Format. */
4439          return 0;
4440       }
4441 
4442       seg_size = 2 + data_size;
4443    }
4444 
4445    /* Add padding. */
4446    seg_size += seg_size % 2;
4447 
4448    return seg_size;
4449 }
4450 
dissect_segment_port(tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item)4451 static int dissect_segment_port(tvbuff_t* tvb, int offset, gboolean generate,
4452    proto_tree* path_seg_tree, proto_item* path_seg_item, proto_item* epath_item)
4453 {
4454    int segment_len = 0;
4455    gboolean extended_port = FALSE;
4456    int extended_port_offset = 0;
4457    guint8 segment_type = tvb_get_guint8(tvb, offset);
4458 
4459    /* Add Extended Link Address flag & Port Identifier*/
4460    if (generate)
4461    {
4462       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);
4463       proto_item_set_generated(it);
4464       it = proto_tree_add_uint(path_seg_tree, hf_cip_port, tvb, 0, 0, (segment_type & CI_PORT_SEG_PORT_ID_MASK));
4465       proto_item_set_generated(it);
4466    }
4467    else
4468    {
4469       proto_tree_add_item(path_seg_tree, hf_cip_port_ex_link_addr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4470       proto_tree_add_item(path_seg_tree, hf_cip_port, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4471    }
4472 
4473    guint8 port_id = segment_type & CI_PORT_SEG_PORT_ID_MASK;
4474    if (port_id == 0xF)
4475    {
4476       extended_port = TRUE;
4477    }
4478 
4479    proto_item_append_text(path_seg_item, " (Port Segment)");
4480 
4481    const gchar *port_name = try_val_to_str(port_id, cip_port_number_vals);
4482    if (port_name)
4483    {
4484       proto_item_append_text(epath_item, "Port: %s", port_name);
4485    }
4486    else
4487    {
4488       proto_item_append_text(epath_item, "Port: %d", port_id);
4489    }
4490 
4491    if (segment_type & CI_PORT_SEG_EX_LINK_ADDRESS)
4492    {
4493       int offset_link_address = 2;
4494 
4495       if (extended_port == TRUE)
4496       {
4497          offset_link_address += 2;
4498          extended_port_offset = offset + 2;
4499       }
4500 
4501       guint8 opt_link_size = tvb_get_guint8(tvb, offset + 1);
4502 
4503       if (generate)
4504       {
4505          /* Add size of extended link address */
4506          proto_item* it = proto_tree_add_uint(path_seg_item, hf_cip_link_address_size, tvb, 0, 0, opt_link_size);
4507          proto_item_set_generated(it);
4508          /* Add extended link address */
4509          it = proto_tree_add_string(path_seg_item, hf_cip_link_address_string, tvb, 0, 0, tvb_format_text(wmem_packet_scope(), tvb, offset + offset_link_address, opt_link_size));
4510          proto_item_set_generated(it);
4511       }
4512       else
4513       {
4514          proto_tree_add_item(path_seg_item, hf_cip_link_address_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4515          proto_tree_add_item(path_seg_item, hf_cip_link_address_string, tvb, offset + offset_link_address, opt_link_size, ENC_ASCII | ENC_NA);
4516       }
4517 
4518       proto_item_append_text(epath_item, ", Address: %s", tvb_format_text(wmem_packet_scope(), tvb, offset + offset_link_address, opt_link_size));
4519 
4520       /* Pad byte */
4521       if (opt_link_size % 2)
4522       {
4523          segment_len = 1 + offset_link_address + opt_link_size;
4524       }
4525       else
4526       {
4527          segment_len = offset_link_address + opt_link_size;
4528       }
4529    }
4530    else
4531    {
4532       int offset_link_address = 1;
4533 
4534       segment_len = 2;
4535 
4536       if (extended_port == TRUE)
4537       {
4538          segment_len += 2;
4539          offset_link_address += 2;
4540          extended_port_offset = offset + 1;
4541       }
4542 
4543       /* Add Link Address */
4544       if (generate)
4545       {
4546          guint8 link_address_byte = tvb_get_guint8(tvb, offset + offset_link_address);
4547          proto_item* it = proto_tree_add_uint(path_seg_item, hf_cip_link_address_byte, tvb, 0, 0, link_address_byte);
4548          proto_item_set_generated(it);
4549       }
4550       else
4551       {
4552          proto_tree_add_item(path_seg_item, hf_cip_link_address_byte, tvb, offset + offset_link_address, 1, ENC_LITTLE_ENDIAN);
4553       }
4554 
4555       proto_item_append_text(epath_item, ", Address: %d", tvb_get_guint8(tvb, offset + offset_link_address));
4556    }
4557 
4558    if (extended_port == TRUE)
4559    {
4560       if (generate)
4561       {
4562          guint16 port_extended = tvb_get_letohs(tvb, extended_port_offset);
4563          proto_item* it = proto_tree_add_uint(path_seg_item, hf_cip_port_extended, tvb, 0, 0, port_extended);
4564          proto_item_set_generated(it);
4565       }
4566       else
4567       {
4568          proto_tree_add_item(path_seg_item, hf_cip_port_extended, tvb, extended_port_offset, 2, ENC_LITTLE_ENDIAN);
4569       }
4570    }
4571 
4572    if (generate == FALSE)
4573    {
4574       proto_item_set_len(path_seg_item, segment_len);
4575    }
4576 
4577    return segment_len;
4578 }
4579 
dissect_segment_safety(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * net_tree,cip_safety_epath_info_t * safety)4580 static int dissect_segment_safety(packet_info* pinfo, tvbuff_t* tvb, int offset, gboolean generate,
4581    proto_tree* net_tree, cip_safety_epath_info_t* safety)
4582 {
4583    guint16 seg_size = tvb_get_guint8(tvb, offset + 1) * 2;
4584    int segment_len = seg_size + 2;
4585 
4586    if (generate)
4587    {
4588       /* TODO: Skip printing information in response packets for now. Think of a better way to handle
4589          generated data that doesn't require a lot of copy-paste. */
4590       return segment_len;
4591    }
4592 
4593    /* Segment size */
4594    proto_tree_add_item(net_tree, hf_cip_seg_network_size, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4595 
4596    guint32 safety_format;
4597    proto_tree_add_item_ret_uint(net_tree, hf_cip_seg_safety_format, tvb, offset + 2, 1, ENC_LITTLE_ENDIAN, &safety_format);
4598 
4599    /* Safety Network Segment Format */
4600    if (safety_format < 3)
4601    {
4602       cip_connID_info_t ignore;
4603       proto_tree* safety_tree = proto_tree_add_subtree(net_tree, tvb, offset + 3, seg_size - 1,
4604          ett_network_seg_safety, NULL, val_to_str_const(safety_format, cip_safety_segment_format_type_vals, "Reserved"));
4605       switch (safety_format)
4606       {
4607       case 0:
4608       {
4609          /* Target Format */
4610          if (safety != NULL)
4611             safety->format = CIP_SAFETY_BASE_FORMAT;
4612 
4613          proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
4614          proto_tree_add_item(safety_tree, hf_cip_seg_safety_configuration_crc, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
4615          dissect_cipsafety_snn(safety_tree, tvb, pinfo, offset + 8,
4616             hf_cip_seg_safety_configuration_timestamp, hf_cip_seg_safety_configuration_date, hf_cip_seg_safety_configuration_time);
4617          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 14, 4, ENC_LITTLE_ENDIAN);
4618          dissect_net_param16(tvb, offset + 18, safety_tree,
4619             hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
4620             hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
4621             hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
4622             ett_network_seg_safety_time_correction_net_params, &ignore);
4623          proto_item* it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_tunid, tvb, offset + 20, 10, ENC_NA);
4624          dissect_unid(tvb, pinfo, offset + 20, it, "Target UNID SNN", hf_cip_seg_safety_tunid_snn_timestamp,
4625             hf_cip_seg_safety_tunid_snn_date, hf_cip_seg_safety_tunid_snn_time, hf_cip_seg_safety_tunid_nodeid,
4626             ett_cip_seg_safety_tunid, ett_cip_seg_safety_tunid_snn);
4627          it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_ounid, tvb, offset + 30, 10, ENC_NA);
4628          dissect_unid(tvb, pinfo, offset + 30, it, "Originator UNID SNN", hf_cip_seg_safety_ounid_snn_timestamp,
4629             hf_cip_seg_safety_ounid_snn_date, hf_cip_seg_safety_ounid_snn_time, hf_cip_seg_safety_ounid_nodeid,
4630             ett_cip_seg_safety_ounid, ett_cip_seg_safety_ounid_snn);
4631          proto_tree_add_item(safety_tree, hf_cip_seg_safety_ping_eri_multiplier, tvb, offset + 40, 2, ENC_LITTLE_ENDIAN);
4632          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_coord_msg_min_multiplier, tvb, offset + 42, 2, ENC_LITTLE_ENDIAN);
4633          proto_tree_add_item(safety_tree, hf_cip_seg_safety_network_time_expected_multiplier, tvb, offset + 44, 2, ENC_LITTLE_ENDIAN);
4634          proto_tree_add_item(safety_tree, hf_cip_seg_safety_timeout_multiplier, tvb, offset + 46, 1, ENC_LITTLE_ENDIAN);
4635          proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_consumer_number, tvb, offset + 47, 1, ENC_LITTLE_ENDIAN);
4636          proto_tree_add_item(safety_tree, hf_cip_seg_safety_conn_param_crc, tvb, offset + 48, 4, ENC_LITTLE_ENDIAN);
4637          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 52, 4, ENC_LITTLE_ENDIAN);
4638          break;
4639       }
4640       case 1:
4641          /* Router Format */
4642          if (safety != NULL)
4643             safety->format = CIP_SAFETY_BASE_FORMAT;
4644 
4645          proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
4646          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
4647          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN);
4648          dissect_net_param16(tvb, offset + 12, safety_tree,
4649             hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
4650             hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
4651             hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
4652             ett_network_seg_safety_time_correction_net_params, &ignore);
4653          break;
4654       case 2:
4655       {
4656          /* Extended Format */
4657          if (safety != NULL)
4658             safety->format = CIP_SAFETY_EXTENDED_FORMAT;
4659 
4660          proto_tree_add_item(safety_tree, hf_cip_seg_safety_reserved, tvb, offset + 3, 1, ENC_LITTLE_ENDIAN);
4661          proto_tree_add_item(safety_tree, hf_cip_seg_safety_configuration_crc, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
4662          dissect_cipsafety_snn(safety_tree, tvb, pinfo, offset + 8,
4663             hf_cip_seg_safety_configuration_timestamp, hf_cip_seg_safety_configuration_date, hf_cip_seg_safety_configuration_time);
4664          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_epi, tvb, offset + 14, 4, ENC_LITTLE_ENDIAN);
4665          dissect_net_param16(tvb, offset + 18, safety_tree,
4666             hf_cip_seg_safety_time_correction_net_params, hf_cip_seg_safety_time_correction_own,
4667             hf_cip_seg_safety_time_correction_typ, hf_cip_seg_safety_time_correction_prio,
4668             hf_cip_seg_safety_time_correction_fixed_var, hf_cip_seg_safety_time_correction_con_size,
4669             ett_network_seg_safety_time_correction_net_params, &ignore);
4670          proto_item* it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_tunid, tvb, offset + 20, 10, ENC_NA);
4671          dissect_unid(tvb, pinfo, offset + 20, it, "Target UNID SNN", hf_cip_seg_safety_tunid_snn_timestamp,
4672             hf_cip_seg_safety_tunid_snn_date, hf_cip_seg_safety_tunid_snn_time, hf_cip_seg_safety_tunid_nodeid,
4673             ett_cip_seg_safety_tunid, ett_cip_seg_safety_tunid_snn);
4674          it = proto_tree_add_item(safety_tree, hf_cip_seg_safety_ounid, tvb, offset + 30, 10, ENC_NA);
4675          dissect_unid(tvb, pinfo, offset + 30, it, "Originator UNID SNN", hf_cip_seg_safety_ounid_snn_timestamp,
4676             hf_cip_seg_safety_ounid_snn_date, hf_cip_seg_safety_ounid_snn_time, hf_cip_seg_safety_ounid_nodeid,
4677             ett_cip_seg_safety_ounid, ett_cip_seg_safety_ounid_snn);
4678          proto_tree_add_item(safety_tree, hf_cip_seg_safety_ping_eri_multiplier, tvb, offset + 40, 2, ENC_LITTLE_ENDIAN);
4679          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_coord_msg_min_multiplier, tvb, offset + 42, 2, ENC_LITTLE_ENDIAN);
4680          proto_tree_add_item(safety_tree, hf_cip_seg_safety_network_time_expected_multiplier, tvb, offset + 44, 2, ENC_LITTLE_ENDIAN);
4681          proto_tree_add_item(safety_tree, hf_cip_seg_safety_timeout_multiplier, tvb, offset + 46, 1, ENC_LITTLE_ENDIAN);
4682          proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_consumer_number, tvb, offset + 47, 1, ENC_LITTLE_ENDIAN);
4683          proto_tree_add_item(safety_tree, hf_cip_seg_safety_max_fault_number, tvb, offset + 48, 2, ENC_LITTLE_ENDIAN);
4684          proto_tree_add_item(safety_tree, hf_cip_seg_safety_conn_param_crc, tvb, offset + 50, 4, ENC_LITTLE_ENDIAN);
4685          proto_tree_add_item(safety_tree, hf_cip_seg_safety_time_correction_conn_id, tvb, offset + 54, 4, ENC_LITTLE_ENDIAN);
4686          proto_tree_add_item(safety_tree, hf_cip_seg_safety_init_timestamp, tvb, offset + 58, 2, ENC_LITTLE_ENDIAN);
4687          proto_tree_add_item(safety_tree, hf_cip_seg_safety_init_rollover, tvb, offset + 60, 2, ENC_LITTLE_ENDIAN);
4688          break;
4689       }
4690       }  // END switch
4691    }
4692    else
4693    {
4694       proto_tree_add_item(net_tree, hf_cip_seg_safety_data, tvb, offset + 3, seg_size - 1, ENC_NA);
4695    }
4696 
4697    if (safety != NULL)
4698    {
4699       safety->safety_seg = TRUE;
4700    }
4701 
4702    return segment_len;
4703 }
4704 
dissect_segment_data_simple(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,cip_simple_request_info_t * req_data)4705 static int dissect_segment_data_simple(packet_info* pinfo, tvbuff_t* tvb, int offset, gboolean generate,
4706    proto_tree* path_seg_tree, proto_item* path_seg_item, cip_simple_request_info_t* req_data)
4707 {
4708    guint16 seg_size = tvb_get_guint8(tvb, offset + 1) * 2;
4709    int segment_len = seg_size + 2;
4710 
4711    if (generate)
4712    {
4713       proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_size_simple, tvb, 0, 0, seg_size / 2);
4714       proto_item_set_generated(it);
4715    }
4716    else
4717    {
4718       proto_tree_add_item(path_seg_tree, hf_cip_data_seg_size_simple, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4719    }
4720 
4721    if (generate)
4722    {
4723       return segment_len;
4724    }
4725 
4726    /* Segment data  */
4727    if (seg_size != 0)
4728    {
4729       int parsed_data_len = 0;
4730       if (req_data && req_data->iClass == CI_CLS_MOTION
4731          && req_data->iConnPointA != SEGMENT_VALUE_NOT_SET
4732          && req_data->iConnPoint != SEGMENT_VALUE_NOT_SET)
4733       {
4734          parsed_data_len += dissect_motion_configuration_block(tvb, pinfo, path_seg_tree, path_seg_item, offset + 2);
4735       }
4736 
4737       int remaining_data_len = seg_size - parsed_data_len;
4738       if (remaining_data_len > 0)
4739       {
4740          proto_tree_add_item(path_seg_tree, hf_cip_data_seg_item, tvb, offset + 2 + parsed_data_len, remaining_data_len, ENC_NA);
4741       }
4742    }
4743 
4744    proto_item_set_len(path_seg_item, segment_len);
4745 
4746    return segment_len;
4747 }
4748 
dissect_segment_ansi_extended_symbol(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item,int display_type,gboolean is_msp_item,proto_item * msp_item)4749 static int dissect_segment_ansi_extended_symbol(packet_info* pinfo, tvbuff_t* tvb, int offset,
4750    gboolean generate, proto_tree* path_seg_tree, proto_item* path_seg_item,
4751    proto_item* epath_item, int display_type,
4752    gboolean is_msp_item, proto_item* msp_item)
4753 {
4754    /* Segment size */
4755    guint16 seg_size = tvb_get_guint8(tvb, offset + 1);
4756    if (generate)
4757    {
4758       proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_size_extended, tvb, 0, 0, seg_size);
4759       proto_item_set_generated(it);
4760    }
4761    else
4762       proto_tree_add_item(path_seg_tree, hf_cip_data_seg_size_extended, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4763 
4764    /* Segment data  */
4765    if (seg_size != 0)
4766    {
4767       gchar* symbol_name = tvb_format_text(pinfo->pool, tvb, offset + 2, seg_size);
4768 
4769       if (generate)
4770       {
4771          proto_item* it = proto_tree_add_string(path_seg_tree, hf_cip_symbol, tvb, 0, 0, symbol_name);
4772          proto_item_set_generated(it);
4773       }
4774       else
4775          proto_tree_add_item(path_seg_tree, hf_cip_symbol, tvb, offset + 2, seg_size, ENC_ASCII | ENC_NA);
4776 
4777       proto_item_append_text(epath_item, "%s", symbol_name);
4778 
4779       if (cip_enhanced_info_column == TRUE && is_msp_item == FALSE)
4780       {
4781          add_cip_symbol_to_info_column(pinfo, symbol_name, display_type);
4782       }
4783 
4784       if (msp_item != NULL)
4785       {
4786          proto_item_append_text(msp_item, "'%s' - ", symbol_name);
4787       }
4788    }
4789 
4790    /* Check for pad byte */
4791    if (seg_size % 2)
4792       seg_size++;
4793 
4794    if (!generate)
4795    {
4796       proto_item_set_len(path_seg_item, 2 + seg_size);
4797    }
4798 
4799    return 2 + seg_size;
4800 }
4801 
dissect_segment_logical_special(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item)4802 static int dissect_segment_logical_special(packet_info* pinfo, tvbuff_t* tvb, int offset,
4803    gboolean generate, proto_tree* path_seg_tree,
4804    proto_item* path_seg_item, proto_item* epath_item)
4805 {
4806    int segment_len = 0;
4807 
4808    guint8 segment_type = tvb_get_guint8(tvb, offset);
4809 
4810    /* Logical Special ID, the only logical format specified is electronic key */
4811    if ((segment_type & CI_LOGICAL_SEG_FORMAT_MASK) == CI_LOGICAL_SEG_E_KEY)
4812    {
4813       guint8 key_format = tvb_get_guint8(tvb, offset + 1);
4814       if (key_format == CI_E_KEY_FORMAT_VAL || key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
4815       {
4816          if (key_format == CI_E_KEY_FORMAT_VAL)
4817          {
4818             segment_len = 10;
4819          }
4820          else  // CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL
4821          {
4822             segment_len = 14;
4823          }
4824 
4825          if (generate)
4826          {
4827             proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_ekey_format, tvb, 0, 0, key_format);
4828             proto_item_set_generated(it);
4829 
4830             dissect_deviceid(tvb, offset + 2, path_seg_tree,
4831                hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
4832                hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, TRUE);
4833          }
4834          else
4835          {
4836             proto_tree_add_item(path_seg_tree, hf_cip_ekey_format, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4837 
4838             /* dissect the device ID */
4839             dissect_deviceid(tvb, offset + 2, path_seg_tree,
4840                hf_cip_ekey_vendor, hf_cip_ekey_devtype, hf_cip_ekey_prodcode,
4841                hf_cip_ekey_compatibility, hf_cip_ekey_comp_bit, hf_cip_ekey_majorrev, hf_cip_ekey_minorrev, FALSE);
4842 
4843             if (key_format == CI_E_SERIAL_NUMBER_KEY_FORMAT_VAL)
4844             {
4845                proto_tree_add_item(path_seg_tree, hf_cip_ekey_serial_number, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN);
4846             }
4847 
4848             proto_item_set_len(path_seg_item, segment_len);
4849          }
4850 
4851          /* Add "summary" information to parent item */
4852          guint16 vendor_id = tvb_get_letohs(tvb, offset + 2);
4853          proto_item_append_text(path_seg_tree, " (VendorID: 0x%04X", vendor_id);
4854 
4855          guint16 device_type = tvb_get_letohs(tvb, offset + 4);
4856          proto_item_append_text(path_seg_tree, ", DevTyp: 0x%04X", device_type);
4857 
4858          guint8 major_rev = tvb_get_guint8(tvb, offset + 8);
4859          guint8 minor_rev = tvb_get_guint8(tvb, offset + 9);
4860 
4861          proto_item_append_text(path_seg_tree, ", %d.%d)", (major_rev & 0x7F), minor_rev);
4862          proto_item_append_text(epath_item, "[Key]");
4863       }
4864       else
4865       {
4866          expert_add_info(pinfo, epath_item, &ei_proto_electronic_key_format);
4867       }
4868    }
4869    else
4870    {
4871       expert_add_info(pinfo, epath_item, &ei_proto_special_segment_format);
4872    }
4873 
4874    return segment_len;
4875 }
4876 
dissect_segment_network(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item,int display_type,cip_safety_epath_info_t * safety)4877 static int dissect_segment_network(packet_info* pinfo, tvbuff_t* tvb, int offset,
4878    gboolean generate, proto_tree* path_seg_tree, proto_item* path_seg_item,
4879    proto_item* epath_item, int display_type, cip_safety_epath_info_t* safety)
4880 {
4881    int segment_len = 0;
4882 
4883    guint8 segment_type = tvb_get_guint8(tvb, offset);
4884 
4885    /* Network segment -Determine the segment sub-type */
4886    if (generate)
4887    {
4888       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);
4889       proto_item_set_generated(it);
4890    }
4891    else
4892    {
4893       proto_tree_add_item(path_seg_tree, hf_cip_network_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4894    }
4895 
4896    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"));
4897 
4898    switch (segment_type & CI_NETWORK_SEG_TYPE_MASK)
4899    {
4900    case CI_NETWORK_SEG_SCHEDULE:
4901       if (generate)
4902       {
4903          guint8 schedule = tvb_get_guint8(tvb, offset + 1);
4904          proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_schedule, tvb, 0, 0, schedule);
4905          proto_item_set_generated(it);
4906       }
4907       else
4908       {
4909          proto_tree_add_item(path_seg_tree, hf_cip_seg_schedule, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4910       }
4911 
4912       segment_len = 2;
4913       break;
4914 
4915    case CI_NETWORK_SEG_FIXED_TAG:
4916       if (generate)
4917       {
4918          guint8 fixed_tag = tvb_get_guint8(tvb, offset + 1);
4919          proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_fixed_tag, tvb, 0, 0, fixed_tag);
4920          proto_item_set_generated(it);
4921       }
4922       else
4923       {
4924          proto_tree_add_item(path_seg_tree, hf_cip_seg_fixed_tag, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4925       }
4926 
4927       segment_len = 2;
4928       break;
4929 
4930    case CI_NETWORK_SEG_PROD_INHI:
4931       if (generate)
4932       {
4933          guint8 inhibit_time = tvb_get_guint8(tvb, offset + 1);
4934          proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_seg_prod_inhibit_time, tvb, 0, 0, inhibit_time);
4935          proto_item_set_generated(it);
4936       }
4937       else
4938       {
4939          proto_tree_add_item(path_seg_tree, hf_cip_seg_prod_inhibit_time, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4940       }
4941 
4942       segment_len = 2;
4943       break;
4944 
4945    case CI_NETWORK_SEG_PROD_INHI_US:
4946       segment_len = dissect_segment_network_production_inhibit_us(tvb, offset, generate, path_seg_tree);
4947       break;
4948 
4949    case CI_NETWORK_SEG_EXTENDED:
4950       segment_len = dissect_segment_network_extended(pinfo, epath_item, tvb, offset, generate, path_seg_tree);
4951       proto_item_append_text(epath_item, "[Network]");
4952       break;
4953 
4954    case CI_NETWORK_SEG_SAFETY:
4955       proto_item_append_text(epath_item, "[Safety]");
4956 
4957       if (display_type == DISPLAY_CONNECTION_PATH)
4958       {
4959          col_append_str(pinfo->cinfo, COL_INFO, " [Safety]");
4960       }
4961 
4962       segment_len = dissect_segment_safety(pinfo, tvb, offset, generate, path_seg_tree, safety);
4963       break;
4964 
4965    default:
4966       expert_add_info(pinfo, epath_item, &ei_proto_log_sub_seg_type);
4967       segment_len = 0;
4968       break;
4969    } /* End of switch sub-type */
4970 
4971    if (generate == FALSE)
4972    {
4973       proto_item_set_len(path_seg_item, segment_len);
4974    }
4975 
4976    return segment_len;
4977 }
4978 
dissect_segment_logical_service_id(packet_info * pinfo,tvbuff_t * tvb,int offset,gboolean generate,proto_tree * path_seg_tree,proto_item * path_seg_item,proto_item * epath_item)4979 static int dissect_segment_logical_service_id(packet_info* pinfo, tvbuff_t* tvb, int offset,
4980    gboolean generate, proto_tree* path_seg_tree, proto_item* path_seg_item, proto_item* epath_item)
4981 {
4982    int segment_len = 0;
4983 
4984    guint8 segment_type = tvb_get_guint8(tvb, offset);
4985 
4986    /* Logical Service ID - the only logical format specified is 8-bit Service ID */
4987    if ((segment_type & CI_LOGICAL_SEG_FORMAT_MASK) == CI_LOGICAL_SEG_8_BIT)
4988    {
4989       guint8 service_id = tvb_get_guint8(tvb, offset + 1);
4990 
4991       if (generate)
4992       {
4993          proto_item* it = proto_tree_add_uint(path_seg_tree, hf_cip_serviceid8, tvb, 0, 0, service_id);
4994          proto_item_set_generated(it);
4995       }
4996       else
4997       {
4998          proto_tree_add_item(path_seg_tree, hf_cip_serviceid8, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
4999 
5000          proto_item_set_len(path_seg_item, 2);
5001       }
5002 
5003       proto_item_append_text(epath_item, "Service ID: 0x%x", service_id);
5004 
5005       segment_len = 2;
5006    }
5007    else
5008    {
5009       expert_add_info(pinfo, epath_item, &ei_proto_log_seg_type);
5010    }
5011 
5012    return segment_len;
5013 }
5014 
dissect_cip_segment_single(packet_info * pinfo,tvbuff_t * tvb,int offset,proto_tree * path_tree,proto_item * epath_item,gboolean generate,gboolean packed,cip_simple_request_info_t * req_data,cip_safety_epath_info_t * safety,int display_type,proto_item * msp_item,gboolean is_msp_item)5015 int dissect_cip_segment_single(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *path_tree, proto_item *epath_item,
5016                     gboolean generate, gboolean packed, cip_simple_request_info_t* req_data, cip_safety_epath_info_t* safety,
5017                     int display_type, proto_item *msp_item,
5018                     gboolean is_msp_item)
5019 {
5020    int segment_len = 0;
5021    unsigned char segment_type;
5022    proto_tree *path_seg_tree;
5023    proto_item *it, *cia_ret_item;
5024    proto_item *path_seg_item;
5025 
5026    {
5027       if (tvb_reported_length_remaining(tvb, offset) <= 0)
5028       {
5029          expert_add_info(pinfo, epath_item, &ei_mal_incomplete_epath);
5030          return 0;
5031       }
5032 
5033       /* Get segment type */
5034       segment_type = tvb_get_guint8( tvb, offset );
5035 
5036       if ( generate )
5037       {
5038          path_seg_item = proto_tree_add_uint(path_tree, hf_cip_path_segment, tvb, 0, 0, segment_type );
5039          proto_item_set_generated(path_seg_item);
5040          path_seg_tree = proto_item_add_subtree( path_seg_item, ett_path_seg );
5041          it = proto_tree_add_uint(path_seg_tree, hf_cip_path_segment_type, tvb, 0, 0, segment_type&CI_SEGMENT_TYPE_MASK);
5042          proto_item_set_generated(it);
5043       }
5044       else
5045       {
5046          path_seg_item = proto_tree_add_item(path_tree, hf_cip_path_segment, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5047          path_seg_tree = proto_item_add_subtree( path_seg_item, ett_path_seg );
5048          proto_tree_add_item(path_seg_tree, hf_cip_path_segment_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5049       }
5050 
5051       /* Determine the segment type */
5052 
5053       switch( segment_type & CI_SEGMENT_TYPE_MASK )
5054       {
5055          case CI_PORT_SEGMENT:
5056          {
5057             segment_len = dissect_segment_port(tvb, offset, generate, path_seg_tree, path_seg_item, epath_item);
5058             break;
5059          }
5060 
5061          case CI_LOGICAL_SEGMENT:
5062          {
5063             guint8 logical_seg_type;
5064             logical_seg_type = segment_type & CI_LOGICAL_SEG_TYPE_MASK;
5065 
5066             /* Logical segment, determine the logical type */
5067             if ( generate )
5068             {
5069                it = proto_tree_add_uint(path_seg_tree, hf_cip_logical_seg_type, tvb, 0, 0, logical_seg_type);
5070                proto_item_set_generated(it);
5071                if (logical_seg_type != CI_LOGICAL_SEG_SPECIAL && logical_seg_type != CI_LOGICAL_SEG_SERV_ID)
5072                {
5073                   it = proto_tree_add_uint(path_seg_tree, hf_cip_logical_seg_format, tvb, 0, 0, segment_type & CI_LOGICAL_SEG_FORMAT_MASK);
5074                   proto_item_set_generated(it);
5075                }
5076             }
5077             else
5078             {
5079                proto_tree_add_item(path_seg_tree, hf_cip_logical_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
5080                if (logical_seg_type != CI_LOGICAL_SEG_SPECIAL && logical_seg_type != CI_LOGICAL_SEG_SERV_ID)
5081                   proto_tree_add_item(path_seg_tree, hf_cip_logical_seg_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5082             }
5083 
5084             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"));
5085 
5086             switch (logical_seg_type)
5087             {
5088                case CI_LOGICAL_SEG_CLASS_ID:
5089                {
5090                   guint32 ClassID;
5091                   segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5092                        epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5093                        "Class", cip_class_names_vals, &ClassID,
5094                        hf_cip_class8, hf_cip_class16, hf_cip_class32);
5095                   if (segment_len == 0)
5096                   {
5097                      return 0;
5098                   }
5099 
5100                   if (req_data)
5101                   {
5102                      req_data->iClass = ClassID;
5103 
5104                      // Save the first ClassID separately.
5105                      if (req_data->iClassA == SEGMENT_VALUE_NOT_SET)
5106                      {
5107                         req_data->iClassA = ClassID;
5108                      }
5109                   }
5110 
5111                   if (req_data != NULL)
5112                   {
5113                      if (cip_enhanced_info_column == TRUE && is_msp_item == FALSE)
5114                      {
5115                         add_cip_class_to_info_column(pinfo, req_data->iClass, display_type);
5116                      }
5117 
5118                      if (msp_item != NULL)
5119                      {
5120                         proto_item_append_text(msp_item, "%s - ", val_to_str(req_data->iClass, cip_class_names_vals, "Class (0x%02x)"));
5121                      }
5122                   }
5123 
5124                   break;
5125                }
5126 
5127                case CI_LOGICAL_SEG_INST_ID:
5128                {
5129                   guint32 InstanceID;
5130                   segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5131                        epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5132                        "Instance", NULL, &InstanceID,
5133                        hf_cip_instance8, hf_cip_instance16, hf_cip_instance32);
5134                   if (segment_len == 0)
5135                   {
5136                      return 0;
5137                   }
5138 
5139                   if (req_data)
5140                   {
5141                      req_data->iInstance = InstanceID;
5142 
5143                      // Save the first InstanceID separately.
5144                      if (req_data->iInstanceA == SEGMENT_VALUE_NOT_SET)
5145                      {
5146                         req_data->iInstanceA = InstanceID;
5147                      }
5148                   }
5149 
5150                   break;
5151                }
5152 
5153                case CI_LOGICAL_SEG_MBR_ID:
5154                   segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5155                        epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5156                        "Member", NULL, (req_data == NULL) ? NULL : &req_data->iMember,
5157                        hf_cip_member8, hf_cip_member16, hf_cip_member32);
5158                   break;
5159 
5160                case CI_LOGICAL_SEG_ATTR_ID:
5161                   segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5162                        epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5163                        "Attribute", NULL, (req_data == NULL) ? NULL : &req_data->iAttribute,
5164                        hf_cip_attribute8, hf_cip_attribute16, hf_cip_attribute32);
5165                   if (segment_len == 0)
5166                   {
5167                      return 0;
5168                   }
5169 
5170                   if (req_data != NULL)
5171                   {
5172                      attribute_info_t* att_info = cip_get_attribute(req_data->iClass, req_data->iInstance,
5173                                                   req_data->iAttribute);
5174                      if (att_info != NULL)
5175                      {
5176                         proto_item_append_text(cia_ret_item, " (%s)", att_info->text);
5177                         proto_item_append_text(epath_item, " (%s)", att_info->text);
5178                      }
5179                   }
5180                   break;
5181 
5182                case CI_LOGICAL_SEG_CON_POINT:
5183                {
5184                   guint32 ConnPoint;
5185                   segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5186                      epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5187                      "Connection Point", NULL, &ConnPoint,
5188                      hf_cip_conpoint8, hf_cip_conpoint16, hf_cip_conpoint32);
5189                   if (segment_len == 0)
5190                   {
5191                      return 0;
5192                   }
5193 
5194                   if (req_data)
5195                   {
5196                      req_data->iConnPoint = ConnPoint;
5197 
5198                      // Save the first ConnPoint separately.
5199                      if (req_data->iConnPointA == SEGMENT_VALUE_NOT_SET)
5200                      {
5201                         req_data->iConnPointA = ConnPoint;
5202                      }
5203                   }
5204 
5205                   break;
5206                }
5207 
5208                case CI_LOGICAL_SEG_SPECIAL:
5209                    segment_len = dissect_segment_logical_special(pinfo, tvb, offset, generate,
5210                       path_seg_tree, path_seg_item, epath_item);
5211                    break;
5212 
5213                case CI_LOGICAL_SEG_SERV_ID:
5214                    segment_len = dissect_segment_logical_service_id(pinfo, tvb, offset, generate,
5215                       path_seg_tree, path_seg_item, epath_item);
5216                    break;
5217 
5218                case CI_LOGICAL_SEG_EXT_LOGICAL:
5219                    segment_len = dissect_cia(tvb, offset, segment_type, generate, packed, pinfo,
5220                        epath_item, path_seg_tree, path_seg_item, &cia_ret_item,
5221                        "Extended Logical", NULL, NULL,
5222                        hf_cip_ext_logical8, hf_cip_ext_logical16, hf_cip_ext_logical32);
5223                    break;
5224 
5225                default:
5226                   expert_add_info(pinfo, epath_item, &ei_proto_log_seg_type);
5227                   return 0;
5228 
5229             } /* end of switch( logical_seg_type ) */
5230             break;
5231          }
5232 
5233          case CI_DATA_SEGMENT:
5234          {
5235             /* Data segment, determine the logical type */
5236             if ( generate )
5237             {
5238                it = proto_tree_add_uint(path_seg_tree, hf_cip_data_seg_type, tvb, 0, 0, segment_type & CI_DATA_SEG_TYPE_MASK);
5239                proto_item_set_generated(it);
5240             }
5241             else
5242             {
5243                proto_tree_add_item(path_seg_tree, hf_cip_data_seg_type, tvb, offset, 1, ENC_LITTLE_ENDIAN );
5244             }
5245 
5246             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"));
5247 
5248             switch( segment_type & CI_DATA_SEG_TYPE_MASK)
5249             {
5250                case CI_DATA_SEG_SIMPLE:
5251                   segment_len = dissect_segment_data_simple(pinfo, tvb, offset, generate, path_seg_tree, path_seg_item, req_data);
5252                   proto_item_append_text(epath_item, "[Data]" );
5253                   break;
5254 
5255                case CI_DATA_SEG_SYMBOL:
5256                   segment_len = dissect_segment_ansi_extended_symbol(pinfo, tvb, offset, generate,
5257                      path_seg_tree, path_seg_item, epath_item, display_type, is_msp_item, msp_item);
5258                   break;
5259 
5260                default:
5261                   expert_add_info(pinfo, epath_item, &ei_proto_log_sub_seg_type);
5262                   return 0;
5263 
5264             } /* End of switch sub-type */
5265 
5266             break;
5267          }
5268 
5269          case CI_NETWORK_SEGMENT:
5270             segment_len = dissect_segment_network(pinfo, tvb, offset, generate, path_seg_tree, path_seg_item, epath_item, display_type, safety);
5271             break;
5272 
5273          case CI_SYMBOLIC_SEGMENT:
5274          {
5275              segment_len = dissect_segment_symbolic(tvb, path_seg_tree,
5276                  path_seg_item, epath_item,
5277                  offset, generate);
5278 
5279              if (segment_len == 0)
5280              {
5281                  expert_add_info(pinfo, epath_item, &ei_proto_ext_string_format);
5282                  return 0;
5283              }
5284 
5285              if (generate == FALSE)
5286              {
5287                  proto_item_set_len(path_seg_item, segment_len);
5288              }
5289 
5290              break;
5291          }
5292 
5293          default:
5294             expert_add_info(pinfo, epath_item, &ei_proto_seg_type);
5295             return 0;
5296 
5297       } /* end of switch( segment_type & CI_SEGMENT_TYPE_MASK ) */
5298    }
5299 
5300    return segment_len;
5301 }
5302 
reset_cip_request_info(cip_simple_request_info_t * req_data)5303 void reset_cip_request_info(cip_simple_request_info_t* req_data)
5304 {
5305    req_data->iClass = SEGMENT_VALUE_NOT_SET;
5306    req_data->iClassA = SEGMENT_VALUE_NOT_SET;
5307 
5308    req_data->iInstance = SEGMENT_VALUE_NOT_SET;
5309    req_data->iInstanceA = SEGMENT_VALUE_NOT_SET;
5310 
5311    req_data->iAttribute = SEGMENT_VALUE_NOT_SET;
5312    req_data->iMember = SEGMENT_VALUE_NOT_SET;
5313 
5314    req_data->iConnPoint = SEGMENT_VALUE_NOT_SET;
5315    req_data->iConnPointA = SEGMENT_VALUE_NOT_SET;
5316 }
5317 
dissect_epath(tvbuff_t * tvb,packet_info * pinfo,proto_tree * path_tree,proto_item * epath_item,int offset,int path_length,gboolean generate,gboolean packed,cip_simple_request_info_t * req_data,cip_safety_epath_info_t * safety,int display_type,proto_item * msp_item,gboolean is_msp_item)5318 void dissect_epath(tvbuff_t *tvb, packet_info *pinfo, proto_tree *path_tree, proto_item *epath_item, int offset, int path_length,
5319                     gboolean generate, gboolean packed, cip_simple_request_info_t* req_data, cip_safety_epath_info_t* safety,
5320                     int display_type, proto_item *msp_item,
5321                     gboolean is_msp_item)
5322 {
5323    int pathpos = 0;
5324    proto_item *hidden_item;
5325 
5326    if (req_data != NULL)
5327    {
5328       reset_cip_request_info(req_data);
5329    }
5330 
5331    if (safety != NULL)
5332       safety->safety_seg = FALSE;
5333 
5334    if ( !generate )
5335    {
5336       hidden_item = proto_tree_add_item(path_tree, hf_cip_epath,
5337                                         tvb, offset, path_length, ENC_NA );
5338       proto_item_set_hidden(hidden_item);
5339    }
5340 
5341   while( pathpos < path_length )
5342   {
5343       int segment_len;
5344       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);
5345       if (segment_len == 0)
5346       {
5347           break;
5348       }
5349 
5350       pathpos += segment_len;
5351 
5352       /* Next path segment */
5353       if( pathpos < path_length )
5354          proto_item_append_text( epath_item, ", " );
5355 
5356    } /* end of while( pathpos < path_length ) */
5357 
5358 } /* end of dissect_epath() */
5359 
5360 /* Number of seconds between Jan 1, 1970 00:00:00 epoch and CIP's epoch time of Jan 1, 1972 00:00:00 */
5361 #define CIP_TIMEBASE 63003600
5362 
dissect_cip_date_and_time(proto_tree * tree,tvbuff_t * tvb,int offset,int hf_datetime)5363 void dissect_cip_date_and_time(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_datetime)
5364 {
5365    nstime_t computed_time;
5366    guint16 num_days_since_1972;
5367    guint32 num_ms_today;
5368 
5369    num_days_since_1972 = tvb_get_letohs(tvb, offset+4);
5370    num_ms_today = tvb_get_letohl(tvb, offset);
5371 
5372    if ((num_days_since_1972 != 0) || (num_ms_today != 0))
5373    {
5374       computed_time.secs = CIP_TIMEBASE+(num_days_since_1972*60*60*24);
5375       computed_time.secs += num_ms_today/1000;
5376       computed_time.nsecs = (num_ms_today%1000)*1000000;
5377    }
5378    else
5379    {
5380       computed_time.secs = 0;
5381       computed_time.nsecs = 0;
5382    }
5383 
5384    proto_tree_add_time(tree, hf_datetime, tvb, offset, 6, &computed_time);
5385 }
5386 
5387 // CIP Type - STIME (nanoseconds)
dissect_cip_stime(proto_tree * tree,tvbuff_t * tvb,int offset,int hf_datetime)5388 static int dissect_cip_stime(proto_tree* tree, tvbuff_t* tvb, int offset, int hf_datetime)
5389 {
5390    nstime_t ts_nstime = { 0 };
5391    guint64 timestamp = tvb_get_letoh64(tvb, offset);
5392    ts_nstime.secs = timestamp / 1000000000;
5393    ts_nstime.nsecs = timestamp % 1000000000;
5394 
5395    proto_tree_add_time(tree, hf_datetime, tvb, offset, 8, &ts_nstime);
5396 
5397    return 8;
5398 }
5399 
5400 // CIP Type - UTIME (microseconds)
dissect_cip_utime(proto_tree * tree,tvbuff_t * tvb,int offset,int hf_datetime)5401 int dissect_cip_utime(proto_tree* tree, tvbuff_t* tvb, int offset, int hf_datetime)
5402 {
5403    nstime_t ts_nstime = { 0 };
5404    guint64 timestamp = tvb_get_letoh64(tvb, offset);
5405    ts_nstime.secs = timestamp / 1000000;
5406    ts_nstime.nsecs = timestamp % 1000000;
5407 
5408    proto_tree_add_time(tree, hf_datetime, tvb, offset, 8, &ts_nstime);
5409 
5410    return 8;
5411 }
5412 
dissect_cip_string_type(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset,int hf_type,int string_type)5413 int dissect_cip_string_type(packet_info *pinfo, proto_tree *tree, proto_item *item,
5414     tvbuff_t *tvb, int offset, int hf_type, int string_type)
5415 {
5416     guint32 string_size_field_len;
5417     guint32 string_size;
5418     guint string_encoding;
5419     int parsed_len;
5420     int total_len;
5421 
5422     total_len = tvb_reported_length_remaining(tvb, offset);
5423 
5424     switch (string_type)
5425     {
5426     case CIP_SHORT_STRING_TYPE:
5427         string_size = tvb_get_guint8(tvb, offset);
5428         string_encoding = ENC_ASCII | ENC_NA;
5429         string_size_field_len = 1;
5430         break;
5431 
5432     case CIP_STRING_TYPE:
5433         string_size = tvb_get_letohs(tvb, offset);
5434         string_encoding = ENC_ASCII | ENC_NA;
5435         string_size_field_len = 2;
5436         break;
5437 
5438     case CIP_STRING2_TYPE:
5439         string_size = tvb_get_letohs(tvb, offset) * 2;
5440         string_encoding = ENC_UCS_2 | ENC_LITTLE_ENDIAN;
5441         string_size_field_len = 2;
5442         break;
5443 
5444     default:
5445         // Unsupported.
5446         return total_len;
5447         break;
5448     }
5449 
5450     if (total_len < (int)(string_size + string_size_field_len))
5451     {
5452         expert_add_info(pinfo, item, &ei_mal_missing_string_data);
5453         parsed_len = total_len;
5454     }
5455     else
5456     {
5457         proto_tree_add_item(tree, hf_type, tvb, offset + string_size_field_len, string_size, string_encoding);
5458         parsed_len = string_size + string_size_field_len;
5459     }
5460 
5461     return parsed_len;
5462 }
5463 
dissect_cip_stringi(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,int offset)5464 static int dissect_cip_stringi(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int offset)
5465 {
5466     int parsed_len = 1;
5467     guint32 num_char = 0;
5468     proto_tree_add_item_ret_uint(tree, hf_stringi_number_char, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_char);
5469 
5470     for (guint32 i = 0; i < num_char; ++i)
5471     {
5472         proto_tree_add_item(tree, hf_stringi_language_char, tvb, offset + 1, 3, ENC_ASCII | ENC_NA);
5473 
5474         guint32 char_string_type = 0;
5475         proto_tree_add_item_ret_uint(tree, hf_stringi_char_string_struct, tvb, offset + 4, 1, ENC_LITTLE_ENDIAN, &char_string_type);
5476         proto_tree_add_item(tree, hf_stringi_char_set, tvb, offset + 5, 2, ENC_LITTLE_ENDIAN);
5477         parsed_len += 6;
5478 
5479         if (char_string_type != CIP_STRING_TYPE
5480             && char_string_type != CIP_SHORT_STRING_TYPE
5481             && char_string_type != CIP_STRING2_TYPE)
5482         {
5483             // Unsupported type.
5484             break;
5485         }
5486 
5487         parsed_len += dissect_cip_string_type(pinfo, tree, item, tvb, offset + parsed_len, hf_stringi_international_string, char_string_type);
5488     }
5489 
5490     return parsed_len;
5491 }
5492 
dissect_cip_attribute(packet_info * pinfo,proto_tree * tree,proto_item * item,tvbuff_t * tvb,attribute_info_t * attr,int offset,int total_len)5493 int dissect_cip_attribute(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb,
5494                          attribute_info_t* attr, int offset, int total_len)
5495 {
5496    int i, temp_data, temp_time, hour, min, sec, ms,
5497       consumed = 0;
5498    time_t computed_time;
5499    struct tm* date;
5500    char date_str[20];
5501 
5502    /* sanity check */
5503    if (((attr->datatype == cip_dissector_func) && (attr->pdissect == NULL)) ||
5504        ((attr->datatype != cip_dissector_func) && (attr->phf == NULL)))
5505    {
5506       DISSECTOR_ASSERT(0);
5507       return total_len;
5508    }
5509 
5510    switch (attr->datatype)
5511    {
5512    case cip_bool:
5513    case cip_usint:
5514    case cip_sint:
5515    case cip_byte:
5516       proto_tree_add_item(tree, *(attr->phf), tvb, offset, 1, ENC_LITTLE_ENDIAN);
5517       consumed = 1;
5518       break;
5519    case cip_uint:
5520    case cip_int:
5521    case cip_word:
5522    case cip_itime:
5523       proto_tree_add_item(tree, *(attr->phf), tvb, offset, 2, ENC_LITTLE_ENDIAN);
5524       consumed = 2;
5525       break;
5526    case cip_usint_array:
5527       for (i = 0; i < total_len; i++)
5528          proto_tree_add_item(tree, *(attr->phf), tvb, offset, total_len, ENC_NA);
5529       consumed = total_len;
5530       break;
5531    case cip_uint_array:
5532       for (i = 0; i < total_len; i+=2)
5533          proto_tree_add_item(tree, *(attr->phf), tvb, offset+i, 2, ENC_LITTLE_ENDIAN);
5534       consumed = i;
5535       break;
5536    case cip_udint:
5537    case cip_dint:
5538    case cip_dword:
5539    case cip_real:
5540    case cip_time:
5541    case cip_ftime:
5542       proto_tree_add_item(tree, *(attr->phf), tvb, offset, 4, ENC_LITTLE_ENDIAN);
5543       consumed = 4;
5544       break;
5545    case cip_ulint:
5546    case cip_lint:
5547    case cip_lword:
5548    case cip_lreal:
5549    case cip_ltime:
5550    case cip_ntime:
5551       proto_tree_add_item(tree, *(attr->phf), tvb, offset, 8, ENC_LITTLE_ENDIAN);
5552       consumed = 8;
5553       break;
5554    case cip_short_string:
5555       consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_SHORT_STRING_TYPE);
5556       break;
5557    case cip_string:
5558       consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_STRING_TYPE);
5559       break;
5560    case cip_dissector_func:
5561       consumed = attr->pdissect(pinfo, tree, item, tvb, offset, total_len);
5562       if (consumed == 0)
5563       {
5564          consumed = total_len;
5565       }
5566 
5567       break;
5568    case cip_date_and_time:
5569       dissect_cip_date_and_time(tree, tvb, offset, *(attr->phf));
5570       consumed = 6;
5571       break;
5572    case cip_stime:
5573       consumed = dissect_cip_stime(tree, tvb, offset, *(attr->phf));
5574       break;
5575    case cip_utime:
5576       consumed = dissect_cip_utime(tree, tvb, offset, *(attr->phf));
5577       break;
5578    case cip_date:
5579       temp_data = tvb_get_letohs( tvb, offset);
5580       /* Convert to nstime epoch */
5581       computed_time = CIP_TIMEBASE+(temp_data*60*60*24);
5582       date = gmtime(&computed_time);
5583       if (date != NULL)
5584           strftime(date_str, 20, "%b %d, %Y", date);
5585       else
5586           (void) g_strlcpy(date_str, "Not representable", sizeof date_str);
5587       proto_tree_add_uint_format_value(tree, *(attr->phf), tvb, offset, 2, temp_data, "%s", date_str);
5588       consumed = 2;
5589       break;
5590    case cip_time_of_day:
5591       temp_time = temp_data = tvb_get_letohl( tvb, offset);
5592       hour = temp_time/(60*60*1000);
5593       temp_time %= (60*60*1000);
5594       min = temp_time/(60*1000);
5595       temp_time %= (60*1000);
5596       sec = temp_time/1000;
5597       ms = temp_time%1000;
5598       proto_tree_add_uint_format_value(tree, *(attr->phf), tvb, offset, 4, temp_data, "%02d:%02d:%02d.%03d", hour, min, sec, ms);
5599       consumed = 4;
5600       break;
5601    case cip_string2:
5602       consumed = dissect_cip_string_type(pinfo, tree, item, tvb, offset, *(attr->phf), CIP_STRING2_TYPE);
5603       break;
5604    case cip_stringi:
5605       consumed = dissect_cip_stringi(pinfo, tree, item, tvb, offset);
5606       break;
5607    case cip_stringN:
5608       /* CURRENTLY NOT SUPPORTED */
5609       expert_add_info(pinfo, item, &ei_proto_unsupported_datatype);
5610       consumed = total_len;
5611       break;
5612    }
5613 
5614    return consumed;
5615 }
5616 
5617 /************************************************
5618  *
5619  * Dissector for generic CIP object
5620  *
5621  ************************************************/
5622 
5623 static void
dissect_cip_generic_data(proto_tree * item_tree,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo,proto_item * ti)5624 dissect_cip_generic_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo, proto_item *ti )
5625 {
5626    proto_tree *cmd_data_tree;
5627    int req_path_size;
5628    unsigned char add_stat_size;
5629    int cmd_data_len;
5630    int cmd_data_offset;
5631    guint8 service = tvb_get_guint8( tvb, offset );
5632 
5633    if (service & CIP_SC_RESPONSE_MASK)
5634    {
5635       /* Response message */
5636       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
5637       cmd_data_len = item_length - 4 - add_stat_size;
5638       cmd_data_offset = offset + 4 + add_stat_size;
5639    }
5640    else
5641    {
5642       /* Request message */
5643       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
5644       cmd_data_len = item_length - req_path_size - 2;
5645       cmd_data_offset = offset + 2 + req_path_size;
5646    }
5647 
5648    /* If there is any command specific data create a sub-tree for it */
5649    if (cmd_data_len > 0)
5650    {
5651       cmd_data_tree = proto_tree_add_subtree(item_tree, tvb, cmd_data_offset, cmd_data_len,
5652          ett_cmd_data, NULL, "Command Specific Data");
5653       proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, cmd_data_offset, cmd_data_len, ENC_NA);
5654    }
5655    else
5656    {
5657       proto_item_set_hidden(ti);
5658    }
5659 
5660    add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
5661 } /* End of dissect_cip_generic_data() */
5662 
5663 static int
dissect_cip_class_generic(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)5664 dissect_cip_class_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
5665 {
5666    proto_item *ti;
5667    proto_tree *class_tree;
5668 
5669    /* Create display subtree for the protocol */
5670    ti = proto_tree_add_item(tree, proto_cip_class_generic, tvb, 0, -1, ENC_NA);
5671    class_tree = proto_item_add_subtree( ti, ett_cip_class_generic );
5672 
5673    dissect_cip_generic_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo, ti );
5674 
5675    return tvb_reported_length(tvb);
5676 }
5677 
5678 static int
dissect_cip_set_attribute_single_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)5679 dissect_cip_set_attribute_single_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
5680                                   int offset, cip_simple_request_info_t* req_data)
5681 {
5682    int parsed_len = 0;
5683    attribute_info_t* attr;
5684 
5685    attr = cip_get_attribute(req_data->iClass, req_data->iInstance, req_data->iAttribute);
5686    if (attr != NULL)
5687    {
5688       parsed_len = dissect_cip_attribute(pinfo, tree, item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
5689    }
5690 
5691    return parsed_len;
5692 }
5693 
dissect_cip_get_attribute_list_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)5694 int dissect_cip_get_attribute_list_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
5695                                   int offset, cip_simple_request_info_t* req_data)
5696 {
5697    int i, att_count, att_value;
5698    attribute_info_t* pattribute;
5699    proto_item *att_list, *att_item;
5700    proto_tree* att_tree;
5701 
5702    /* Get attribute list request */
5703    if (tvb_reported_length_remaining(tvb, offset) < 2)
5704    {
5705       expert_add_info(pinfo, item, &ei_mal_serv_gal);
5706       return 0;
5707    }
5708 
5709    /* Add number of attributes */
5710    att_count = tvb_get_letohs( tvb, offset);
5711    proto_tree_add_item(tree, hf_cip_sc_get_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5712    offset += 2;
5713 
5714    /* Add Attribute List */
5715    att_tree = proto_tree_add_subtree(tree, tvb, offset, att_count*2, ett_cip_get_attribute_list, &att_list, "Attribute List" );
5716 
5717    for( i=0; i < att_count; i++ )
5718    {
5719       att_value = tvb_get_letohs( tvb, offset);
5720       att_item = proto_tree_add_item(att_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5721       pattribute = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
5722       if (pattribute != NULL)
5723          proto_item_append_text(att_item, " (%s)", pattribute->text);
5724 
5725       offset += 2;
5726       if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < att_count-1))
5727       {
5728          expert_add_info(pinfo, att_list, &ei_mal_serv_gal_count);
5729          break;
5730       }
5731    }
5732 
5733    return 2 + att_count * 2;
5734 }
5735 
5736 int
dissect_cip_set_attribute_list_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)5737 dissect_cip_set_attribute_list_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
5738                                   int offset, cip_simple_request_info_t* req_data)
5739 {
5740    int i, start_offset, att_count,
5741        att_value, att_size;
5742    attribute_info_t* attr;
5743    proto_item *att_list, *att_item;
5744    proto_tree *att_tree, *att_list_tree;
5745 
5746    /* Get attribute list request */
5747    if (tvb_reported_length_remaining(tvb, offset) < 2)
5748    {
5749       expert_add_info(pinfo, item, &ei_mal_serv_sal);
5750       return 0;
5751    }
5752 
5753    /* Add number of attributes */
5754    att_count = tvb_get_letohs( tvb, offset);
5755    proto_tree_add_item(tree, hf_cip_sc_set_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5756 
5757    /* Add Attribute List */
5758    att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*2, ett_cip_set_attribute_list, &att_list, "Attribute List" );
5759    offset += 2;
5760    start_offset = offset;
5761 
5762    for( i=0; i < att_count; i++ )
5763    {
5764       att_value = tvb_get_letohs( tvb, offset);
5765       att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5766       att_tree = proto_item_add_subtree( att_item, ett_cip_set_attribute_list_item);
5767       offset += 2;
5768 
5769       attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
5770       if (attr != NULL)
5771       {
5772          proto_item_append_text(att_item, " (%s)", attr->text);
5773          /* provide attribute data */
5774          att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
5775          offset += att_size;
5776          proto_item_set_len(att_item, att_size+2);
5777       }
5778       else
5779       {
5780          /* Can't find the attribute. */
5781          break;
5782       }
5783 
5784       if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < att_count-1))
5785       {
5786          expert_add_info(pinfo, att_list, &ei_mal_serv_sal_count);
5787          break;
5788       }
5789    }
5790 
5791    proto_item_set_len(att_list, offset-start_offset );
5792 
5793    return 2 + (offset - start_offset);
5794 }
5795 
dissect_cip_multiple_service_packet(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,gboolean request)5796 int dissect_cip_multiple_service_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item, int offset, gboolean request)
5797 {
5798    proto_tree *mult_serv_tree, *offset_tree;
5799    int i, num_services, serv_offset, prev_offset = 0;
5800    int parsed_len;
5801    cip_req_info_t *cip_req_info, *mr_single_req_info;
5802    mr_mult_req_info_t *mr_mult_req_info = NULL;
5803 
5804    if (tvb_reported_length_remaining(tvb, offset) < 2)
5805    {
5806       expert_add_info(pinfo, item, &ei_mal_msp_missing_services);
5807       return 0;
5808    }
5809 
5810    num_services = tvb_get_letohs( tvb, offset);
5811    proto_tree_add_item(tree, hf_cip_sc_mult_serv_pack_num_services, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5812 
5813    /* Ensure a rough sanity check */
5814    if (num_services*2 > tvb_reported_length_remaining(tvb, offset+2))
5815    {
5816       expert_add_info(pinfo, item, &ei_mal_msp_services);
5817    }
5818 
5819    offset_tree = proto_tree_add_subtree(tree, tvb, offset + 2, num_services * 2, ett_cip_msp_offset, NULL, "Offset List");
5820    for (i = 0; i < num_services; i++)
5821    {
5822       proto_tree_add_item(offset_tree, hf_cip_sc_mult_serv_pack_offset, tvb, offset + 2 + i * 2, 2, ENC_LITTLE_ENDIAN);
5823    }
5824 
5825    cip_req_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
5826    if ( cip_req_info )
5827    {
5828       /* Only allocate memory for requests. */
5829       if (cip_req_info->pData == NULL && request == TRUE)
5830       {
5831          mr_mult_req_info = wmem_new(wmem_file_scope(), mr_mult_req_info_t);
5832          mr_mult_req_info->service = SC_MULT_SERV_PACK;
5833          mr_mult_req_info->num_services = num_services;
5834          mr_mult_req_info->requests = (cip_req_info_t *)wmem_alloc0(wmem_file_scope(), sizeof(cip_req_info_t)*num_services);
5835          cip_req_info->pData = mr_mult_req_info;
5836       }
5837 
5838       mr_mult_req_info = (mr_mult_req_info_t*)cip_req_info->pData;
5839 
5840       if (mr_mult_req_info
5841          && (mr_mult_req_info->service != SC_MULT_SERV_PACK
5842          || mr_mult_req_info->num_services != num_services))
5843       {
5844          mr_mult_req_info = NULL;
5845       }
5846    }
5847 
5848    col_append_str(pinfo->cinfo, COL_INFO, ": ");
5849 
5850    parsed_len = 2 + num_services * 2;
5851    for( i=0; i < num_services; i++ )
5852    {
5853       proto_item *mult_serv_item;
5854       int serv_length;
5855       tvbuff_t *next_tvb;
5856 
5857       serv_offset = tvb_get_letohs( tvb, offset+2+(i*2) );
5858 
5859       if (tvb_reported_length_remaining(tvb, serv_offset) <= 0)
5860       {
5861          expert_add_info(pinfo, item, &ei_mal_msp_inv_offset);
5862          continue;
5863       }
5864 
5865       if( i == (num_services-1) )
5866       {
5867          /* Last service to add */
5868          serv_length = tvb_reported_length_remaining(tvb, offset)-serv_offset;
5869       }
5870       else
5871       {
5872          serv_length = tvb_get_letohs( tvb, offset+2+((i+1)*2) ) - serv_offset;
5873       }
5874 
5875       mult_serv_tree = proto_tree_add_subtree_format(tree, tvb, offset+serv_offset, serv_length,
5876                     ett_cip_mult_service_packet, &mult_serv_item, "Service Packet #%d: ", i+1 );
5877       proto_tree_add_item(mult_serv_tree, hf_cip_sc_mult_serv_pack_offset, tvb, offset+2+(i*2) , 2, ENC_LITTLE_ENDIAN);
5878 
5879       /* Make sure the offset is valid */
5880       if ((tvb_reported_length_remaining(tvb, serv_offset) <= 0) ||
5881           (tvb_reported_length_remaining(tvb, serv_offset+serv_length) <= 0) ||
5882           (serv_length <= 0) ||
5883           (prev_offset >= serv_offset))
5884       {
5885          expert_add_info(pinfo, mult_serv_item, &ei_mal_msp_inv_offset);
5886          prev_offset = serv_offset;
5887          continue;
5888       }
5889       prev_offset = serv_offset;
5890 
5891       /*
5892       ** We call ourselves again to dissect embedded packet
5893       */
5894 
5895       next_tvb = tvb_new_subset_length(tvb, offset+serv_offset, serv_length);
5896 
5897       if ( mr_mult_req_info )
5898       {
5899          mr_single_req_info = mr_mult_req_info->requests + i;
5900          dissect_cip_data(mult_serv_tree, next_tvb, 0, pinfo, mr_single_req_info, mult_serv_item, TRUE);
5901       }
5902       else
5903       {
5904          dissect_cip_data(mult_serv_tree, next_tvb, 0, pinfo, NULL, mult_serv_item, TRUE);
5905       }
5906 
5907       /* Add the embedded CIP service to the item. */
5908       if (mult_serv_item != NULL)
5909       {
5910          guint8 service = tvb_get_guint8(next_tvb, 0);
5911          proto_item_append_text(mult_serv_item, "%s", val_to_str(service & CIP_SC_MASK, cip_sc_vals, "Service (0x%02x)"));
5912       }
5913 
5914       if (i != num_services - 1)
5915       {
5916           col_append_str(pinfo->cinfo, COL_INFO, ", ");
5917       }
5918 
5919       parsed_len += serv_length;
5920    }
5921 
5922    return parsed_len;
5923 }
5924 
5925 static int
dissect_cip_generic_service_req(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,cip_simple_request_info_t * req_data)5926 dissect_cip_generic_service_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cip_simple_request_info_t* req_data)
5927 {
5928    proto_item *cmd_data_item;
5929    int req_path_size,
5930        offset = 0;
5931    proto_tree *cmd_data_tree;
5932    guint8 service = tvb_get_guint8( tvb, offset ) & CIP_SC_MASK;
5933 
5934    add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
5935 
5936    req_path_size = tvb_get_guint8(tvb, offset + 1);
5937    offset += ((req_path_size * 2) + 2);
5938 
5939    /* Create service tree */
5940    cmd_data_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cmd_data, &cmd_data_item,
5941                         val_to_str(service, cip_sc_vals , "Unknown Service (0x%02x)"));
5942    proto_item_append_text(cmd_data_item, " (Request)");
5943 
5944    int parsed_len = 0;
5945 
5946    switch(service)
5947    {
5948    case SC_GET_ATT_LIST:
5949       parsed_len = dissect_cip_get_attribute_list_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
5950       break;
5951    case SC_SET_ATT_LIST:
5952       parsed_len = dissect_cip_set_attribute_list_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
5953       break;
5954    case SC_RESET:
5955       // Parameter to reset is optional.
5956       if (tvb_reported_length_remaining(tvb, offset) > 0)
5957       {
5958          proto_tree_add_item(cmd_data_tree, hf_cip_sc_reset_param, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5959          parsed_len = 1;
5960       }
5961       break;
5962    case SC_MULT_SERV_PACK:
5963       parsed_len = dissect_cip_multiple_service_packet(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, TRUE);
5964       break;
5965    case SC_SET_ATT_SINGLE:
5966       parsed_len = dissect_cip_set_attribute_single_req(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, req_data);
5967       break;
5968    case SC_FIND_NEXT_OBJ_INST:
5969       proto_tree_add_item(cmd_data_tree, hf_cip_find_next_object_max_instance, tvb, offset, 1, ENC_LITTLE_ENDIAN);
5970       parsed_len = 1;
5971       break;
5972    default:
5973       // No specific handling for other services.
5974       break;
5975    }
5976 
5977    // Display any remaining unparsed data.
5978    int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
5979    if (remain_len > 0)
5980    {
5981        proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
5982    }
5983 
5984    proto_item_set_len(cmd_data_item, parsed_len + remain_len);
5985 
5986    return tvb_reported_length(tvb);
5987 }
5988 
5989 typedef struct cip_gaa_key {
5990    guint32 cip_class;
5991    gboolean class_instance;
5992 } cip_gaa_key_t;
5993 
5994 typedef struct cip_gaa_val {
5995    wmem_list_t *attributes;
5996 } cip_gaa_val_t;
5997 
5998 static wmem_map_t *cip_gaa_hashtable = NULL;
5999 
6000 static guint
cip_gaa_hash(gconstpointer v)6001 cip_gaa_hash (gconstpointer v)
6002 {
6003    const cip_gaa_key_t *key = (const cip_gaa_key_t *)v;
6004    guint val;
6005 
6006    val = (guint)((key->cip_class << 1) & 0xFFFFFFFE);
6007    val |= (key->class_instance & 1);
6008 
6009    return val;
6010 }
6011 
6012 static gint
cip_gaa_equal(gconstpointer v,gconstpointer w)6013 cip_gaa_equal(gconstpointer v, gconstpointer w)
6014 {
6015    const cip_gaa_key_t *v1 = (const cip_gaa_key_t *)v;
6016    const cip_gaa_key_t *v2 = (const cip_gaa_key_t *)w;
6017 
6018    if ((v1->cip_class == v2->cip_class) &&
6019        (v1->class_instance == v2->class_instance))
6020        return 1;
6021 
6022    return 0;
6023 }
6024 
build_get_attr_all_table(void)6025 static void build_get_attr_all_table(void)
6026 {
6027    size_t i, j;
6028    attribute_val_array_t* att_array;
6029    attribute_info_t* pattr;
6030    cip_gaa_key_t key;
6031    cip_gaa_key_t* new_key;
6032    cip_gaa_val_t *gaa_val;
6033    int last_attribute_index = -1;
6034 
6035    cip_gaa_hashtable = wmem_map_new(wmem_epan_scope(), cip_gaa_hash, cip_gaa_equal);
6036 
6037    for (i = 0; i < sizeof(all_attribute_vals)/sizeof(attribute_val_array_t); i++)
6038    {
6039       att_array = &all_attribute_vals[i];
6040       for (j = 0; j < att_array->size; j++)
6041       {
6042          pattr = &att_array->attrs[j];
6043          key.cip_class = pattr->class_id;
6044          key.class_instance = pattr->class_instance;
6045 
6046          gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key );
6047          if (gaa_val == NULL)
6048          {
6049             new_key = (cip_gaa_key_t*)wmem_memdup(wmem_epan_scope(), &key, sizeof(cip_gaa_key_t));
6050             gaa_val = wmem_new0(wmem_epan_scope(), cip_gaa_val_t);
6051             gaa_val->attributes = wmem_list_new(wmem_epan_scope());
6052 
6053             wmem_map_insert(cip_gaa_hashtable, new_key, gaa_val );
6054             last_attribute_index = -1;
6055          }
6056 
6057          if ((pattr->gaa_index >= 0) && (pattr->gaa_index > last_attribute_index))
6058          {
6059              wmem_list_append(gaa_val->attributes, pattr);
6060              last_attribute_index = pattr->gaa_index;
6061          }
6062       }
6063    }
6064 }
6065 
dissect_cip_get_attribute_all_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,cip_simple_request_info_t * req_data)6066 int dissect_cip_get_attribute_all_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6067     int offset, cip_simple_request_info_t* req_data)
6068 {
6069    int att_size;
6070    gint len_remain;
6071    attribute_info_t* attr;
6072    proto_item *att_item;
6073    proto_tree *att_tree;
6074    cip_gaa_key_t key;
6075    cip_gaa_val_t *gaa_val;
6076    wmem_list_frame_t* attribute_list;
6077    int parsed_len = 0;
6078 
6079    key.cip_class = req_data->iClass;
6080    key.class_instance = (req_data->iInstance == 0);
6081 
6082    gaa_val = (cip_gaa_val_t *)wmem_map_lookup( cip_gaa_hashtable, &key );
6083    if (gaa_val == NULL)
6084    {
6085       return 0;
6086    }
6087 
6088    for (attribute_list = wmem_list_head(gaa_val->attributes);
6089        (attribute_list != NULL);
6090         attribute_list = wmem_list_frame_next(attribute_list))
6091    {
6092       attr = (attribute_info_t *)wmem_list_frame_data(attribute_list);
6093       len_remain = tvb_reported_length_remaining(tvb, offset);
6094 
6095       /* If there are no more attributes defined or there is no data left. */
6096       if (attr == NULL || len_remain <= 0)
6097          break;
6098 
6099       att_item = proto_tree_add_uint_format_value(tree, hf_cip_attribute16, tvb, offset, 0, attr->attribute, "%d (%s)", attr->attribute, attr->text);
6100       att_tree = proto_item_add_subtree(att_item, ett_cip_get_attributes_all_item);
6101 
6102       att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, len_remain);
6103       proto_item_set_len(att_item, att_size);
6104 
6105       offset += att_size;
6106       parsed_len += att_size;
6107    }
6108 
6109    return parsed_len;
6110 }
6111 
6112 static int
dissect_cip_get_attribute_list_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)6113 dissect_cip_get_attribute_list_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6114                                   int offset, cip_simple_request_info_t* req_data)
6115 {
6116    int i, start_offset, att_count,
6117        att_value, att_status;
6118    guint att_size;
6119    attribute_info_t* attr;
6120    proto_item *att_list, *att_item;
6121    proto_tree *att_tree, *att_list_tree;
6122 
6123    /* Get attribute list response */
6124    if (tvb_reported_length_remaining(tvb, offset) < 2)
6125    {
6126       expert_add_info(pinfo, item, &ei_mal_serv_gal);
6127       return 0;
6128    }
6129 
6130    /* Add number of attributes */
6131    att_count = tvb_get_letohs( tvb, offset);
6132    proto_tree_add_item(tree, hf_cip_sc_get_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6133 
6134    /* Add Attribute List */
6135    att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*4, ett_cip_get_attribute_list, &att_list, "Attribute List" );
6136    offset += 2;
6137    start_offset = offset;
6138 
6139    for( i=0; i < att_count; i++ )
6140    {
6141       att_value = tvb_get_letohs( tvb, offset);
6142       att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6143       att_tree = proto_item_add_subtree( att_item, ett_cip_get_attribute_list_item);
6144 
6145       att_status = tvb_get_letohs( tvb, offset+2);
6146       proto_tree_add_item(att_tree, hf_cip_sc_get_attr_list_attr_status, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
6147 
6148       attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
6149       if (attr != NULL)
6150          proto_item_append_text(att_item, " (%s)", attr->text);
6151 
6152       offset += 4;
6153       if (att_status == 0)
6154       {
6155          if (attr != NULL)
6156          {
6157             /* provide attribute data */
6158             att_size = dissect_cip_attribute(pinfo, att_tree, att_item, tvb, attr, offset, tvb_reported_length_remaining(tvb, offset));
6159             offset += att_size;
6160             proto_item_set_len(att_item, att_size+4);
6161          }
6162          else
6163          {
6164             /* Can't find the attribute */
6165             break;
6166          }
6167       }
6168 
6169       if ((tvb_reported_length_remaining(tvb, offset) < 4) && (i < att_count-1))
6170       {
6171          expert_add_info(pinfo, att_list, &ei_mal_serv_gal_count);
6172          break;
6173       }
6174    }
6175 
6176    proto_item_set_len(att_list, offset-start_offset );
6177    return 2 + (offset - start_offset);
6178 }
6179 
6180 int
dissect_cip_set_attribute_list_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)6181 dissect_cip_set_attribute_list_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6182                                   int offset, cip_simple_request_info_t* req_data)
6183 {
6184    int i, start_offset, att_count, att_value;
6185    attribute_info_t* attr;
6186    proto_item *att_list, *att_item;
6187    proto_tree *att_tree, *att_list_tree;
6188 
6189    /* Get attribute list request */
6190    if (tvb_reported_length_remaining(tvb, offset) < 2)
6191    {
6192       expert_add_info(pinfo, item, &ei_mal_serv_sal);
6193       return 0;
6194    }
6195 
6196    /* Add number of attributes */
6197    att_count = tvb_get_letohs( tvb, offset);
6198    proto_tree_add_item(tree, hf_cip_sc_set_attr_list_attr_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6199 
6200    /* Add Attribute List */
6201    att_list_tree = proto_tree_add_subtree(tree, tvb, offset+2, att_count*4, ett_cip_get_attribute_list, &att_list, "Attribute List" );
6202    offset += 2;
6203    start_offset = offset;
6204 
6205    for( i=0; i < att_count; i++ )
6206    {
6207       att_value = tvb_get_letohs( tvb, offset);
6208       att_item = proto_tree_add_item(att_list_tree, hf_cip_attribute16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6209       att_tree = proto_item_add_subtree( att_item, ett_cip_set_attribute_list_item);
6210 
6211       proto_tree_add_item(att_tree, hf_cip_sc_set_attr_list_attr_status, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
6212 
6213       attr = cip_get_attribute(req_data->iClass, req_data->iInstance, att_value);
6214       if (attr != NULL)
6215          proto_item_append_text(att_item, " (%s)", attr->text);
6216 
6217       offset += 4;
6218       if ((tvb_reported_length_remaining(tvb, offset) < 4) && (i < att_count-1))
6219       {
6220          expert_add_info(pinfo, att_list, &ei_mal_serv_sal_count);
6221          break;
6222       }
6223    }
6224 
6225    proto_item_set_len(att_list, offset-start_offset );
6226    return 2 + (offset - start_offset);
6227 }
6228 
6229 static int
dissect_cip_get_attribute_single_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset,cip_simple_request_info_t * req_data)6230 dissect_cip_get_attribute_single_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item,
6231                                   int offset, cip_simple_request_info_t* req_data)
6232 {
6233    int parsed_len = 0;
6234    int total_len;
6235    attribute_info_t* attr;
6236 
6237    total_len = tvb_reported_length_remaining(tvb, offset);
6238    attr = cip_get_attribute(req_data->iClass, req_data->iInstance, req_data->iAttribute);
6239    if (attr != NULL)
6240    {
6241       proto_item_append_text(item, " (%s)", attr->text);
6242       parsed_len = dissect_cip_attribute(pinfo, tree, item, tvb, attr, offset, total_len);
6243    }
6244 
6245    return parsed_len;
6246 }
6247 
6248 static int
dissect_cip_find_next_object_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * item,int offset)6249 dissect_cip_find_next_object_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item * item, int offset)
6250 {
6251    guint32 i, num_instances;
6252 
6253    if (tvb_reported_length_remaining(tvb, offset) < 1)
6254    {
6255       expert_add_info(pinfo, item, &ei_mal_serv_find_next_object);
6256       return 0;
6257    }
6258 
6259    proto_tree_add_item_ret_uint(tree, hf_cip_find_next_object_num_instances, tvb, offset, 1, ENC_LITTLE_ENDIAN, &num_instances);
6260    offset += 1;
6261 
6262    for (i = 0; i < num_instances; i++)
6263    {
6264       proto_tree_add_item(tree, hf_cip_find_next_object_instance_item, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6265       offset += 1;
6266 
6267       if ((tvb_reported_length_remaining(tvb, offset) < 2) && (i < num_instances-1))
6268       {
6269          expert_add_info(pinfo, item, &ei_mal_serv_find_next_object_count);
6270          break;
6271       }
6272    }
6273 
6274    return 1 + num_instances * 2;
6275 }
6276 
load_cip_request_data(packet_info * pinfo,cip_simple_request_info_t * req_data)6277 void load_cip_request_data(packet_info *pinfo, cip_simple_request_info_t *req_data)
6278 {
6279     cip_req_info_t* preq_info;
6280     preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6281 
6282     if ((preq_info != NULL) &&
6283         (preq_info->ciaData != NULL))
6284     {
6285         memcpy(req_data, preq_info->ciaData, sizeof(cip_simple_request_info_t));
6286     }
6287     else
6288     {
6289         reset_cip_request_info(req_data);
6290     }
6291 }
6292 
should_dissect_cip_response(tvbuff_t * tvb,int offset,guint8 gen_status)6293 gboolean should_dissect_cip_response(tvbuff_t *tvb, int offset, guint8 gen_status)
6294 {
6295     // Only parse the response if there is data left or it has a response status that allows additional data
6296     //   to be returned.
6297     if ((tvb_reported_length_remaining(tvb, offset) == 0)
6298         && gen_status != CI_GRC_SUCCESS
6299         && gen_status != CI_GRC_ATTR_LIST_ERROR
6300         && gen_status != CI_GRC_SERVICE_ERROR
6301         && gen_status != CI_GRC_INVALID_LIST_STATUS)
6302     {
6303         return FALSE;
6304     }
6305 
6306     return TRUE;
6307 }
6308 
6309 static int
dissect_cip_generic_service_rsp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)6310 dissect_cip_generic_service_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
6311 {
6312    proto_item *cmd_data_item;
6313    proto_tree *cmd_data_tree;
6314    cip_simple_request_info_t req_data;
6315    int offset = 0;
6316    guint8 gen_status = tvb_get_guint8(tvb, offset + 2);
6317    guint8 service = tvb_get_guint8(tvb, offset) & CIP_SC_MASK;
6318    guint16 add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
6319 
6320    offset = 4 + add_stat_size;
6321 
6322    add_cip_service_to_info_column(pinfo, service, cip_sc_vals);
6323 
6324    cmd_data_tree = proto_tree_add_subtree(tree, tvb, offset, 0,
6325        ett_cmd_data, &cmd_data_item, val_to_str(service, cip_sc_vals, "Unknown Service (0x%02x)"));
6326    proto_item_append_text(cmd_data_item, " (Response)");
6327 
6328    load_cip_request_data(pinfo, &req_data);
6329 
6330    if (should_dissect_cip_response(tvb, offset, gen_status) == FALSE)
6331    {
6332       return 0;
6333    }
6334 
6335    int parsed_len = 0;
6336 
6337    switch(service)
6338    {
6339    case SC_GET_ATT_ALL:
6340       parsed_len = dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset, &req_data);
6341       break;
6342    case SC_GET_ATT_LIST:
6343       parsed_len = dissect_cip_get_attribute_list_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
6344       break;
6345    case SC_SET_ATT_LIST:
6346       parsed_len = dissect_cip_set_attribute_list_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
6347       break;
6348    case SC_CREATE:
6349       proto_tree_add_item(cmd_data_tree, hf_cip_sc_create_instance, tvb, offset, 2, ENC_LITTLE_ENDIAN);
6350       parsed_len = 2;
6351       break;
6352    case SC_MULT_SERV_PACK:
6353       parsed_len = dissect_cip_multiple_service_packet(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, FALSE);
6354       break;
6355    case SC_GET_ATT_SINGLE:
6356       parsed_len = dissect_cip_get_attribute_single_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset, &req_data);
6357       break;
6358    case SC_FIND_NEXT_OBJ_INST:
6359       parsed_len = dissect_cip_find_next_object_rsp(tvb, pinfo, cmd_data_tree, cmd_data_item, offset);
6360       break;
6361    case SC_GROUP_SYNC:
6362       proto_tree_add_item(cmd_data_tree, hf_cip_sc_group_sync_is_sync, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6363       parsed_len = 1;
6364       break;
6365    default:
6366       // No specific handling for other services.
6367       break;
6368    }
6369 
6370    // Display any remaining unparsed data.
6371    int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
6372    if (remain_len > 0)
6373    {
6374        proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
6375    }
6376 
6377    proto_item_set_len(cmd_data_item, parsed_len + remain_len);
6378 
6379    return tvb_reported_length(tvb);
6380 }
6381 
6382 /************************************************
6383  *
6384  * Dissector for CIP Connection Manager
6385  *
6386  ************************************************/
6387 
6388 static void
dissect_cip_cm_timeout(proto_tree * cmd_tree,tvbuff_t * tvb,int offset)6389 dissect_cip_cm_timeout(proto_tree *cmd_tree, tvbuff_t *tvb, int offset)
6390 {
6391    guint8 tick, timeout_tick;
6392    int timeout;
6393 
6394    /* Display the priority/tick timer */
6395    tick = tvb_get_guint8( tvb, offset) & 0x0F;
6396    proto_tree_add_item( cmd_tree, hf_cip_cm_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6397    proto_tree_add_item( cmd_tree, hf_cip_cm_tick_time, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6398 
6399    /* Display the time-out ticks */
6400    timeout_tick = tvb_get_guint8( tvb, offset+1 );
6401    proto_tree_add_item( cmd_tree, hf_cip_cm_timeout_tick, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
6402 
6403    /* Display the actual time out */
6404    timeout = ( 1 << tick ) * timeout_tick;
6405    proto_tree_add_uint(cmd_tree, hf_cip_cm_timeout, tvb, offset, 2, timeout);
6406 }
6407 
dissect_connection_triad(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_conn_serial,int hf_vendor,int hf_orig_serial,cip_connection_triad_t * triad)6408 static void dissect_connection_triad(tvbuff_t *tvb, int offset, proto_tree *tree,
6409    int hf_conn_serial, int hf_vendor, int hf_orig_serial,
6410    cip_connection_triad_t *triad)
6411 {
6412    guint32 ConnSerialNumber;
6413    guint32 VendorID;
6414    guint32 DeviceSerialNumber;
6415 
6416    proto_tree_add_item_ret_uint(tree, hf_conn_serial, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ConnSerialNumber);
6417    proto_tree_add_item_ret_uint(tree, hf_vendor, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN, &VendorID);
6418    proto_tree_add_item_ret_uint(tree, hf_orig_serial, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN, &DeviceSerialNumber);
6419 
6420    if (triad)
6421    {
6422       triad->ConnSerialNumber = ConnSerialNumber;
6423       triad->VendorID = VendorID;
6424       triad->DeviceSerialNumber = DeviceSerialNumber;
6425    }
6426 }
6427 
6428 // Mark this message as belonging to a specific CIP connection index.
mark_cip_connection(packet_info * pinfo,tvbuff_t * tvb,proto_tree * tree)6429 static void mark_cip_connection(packet_info* pinfo, tvbuff_t* tvb, proto_tree* tree)
6430 {
6431     cip_conn_info_t* conn_val = (cip_conn_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_CONNECTION_INFO);
6432     if (conn_val)
6433     {
6434         proto_item* pi = proto_tree_add_uint(tree, hf_cip_connection, tvb, 0, 0, conn_val->connid);
6435         proto_item_set_generated(pi);
6436     }
6437 }
6438 
6439 // Save the Route or Connection Path for use in the response packet.
save_route_connection_path(packet_info * pinfo,tvbuff_t * tvb,int offset,guint path_size_bytes)6440 static void save_route_connection_path(packet_info* pinfo, tvbuff_t* tvb, int offset, guint path_size_bytes)
6441 {
6442    if (pinfo->fd->visited)
6443    {
6444       return;
6445    }
6446 
6447    cip_req_info_t* preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6448    if (preq_info)
6449    {
6450       preq_info->pRouteConnectionPath = wmem_alloc(wmem_file_scope(), path_size_bytes);
6451       preq_info->RouteConnectionPathLen = path_size_bytes / 2;
6452       tvb_memcpy(tvb, preq_info->pRouteConnectionPath, offset, path_size_bytes);
6453    }
6454 }
6455 
6456 static void
dissect_cip_cm_fwd_open_req(cip_req_info_t * preq_info,proto_tree * cmd_tree,tvbuff_t * tvb,int offset,gboolean large_fwd_open,packet_info * pinfo)6457 dissect_cip_cm_fwd_open_req(cip_req_info_t *preq_info, proto_tree *cmd_tree, tvbuff_t *tvb, int offset, gboolean large_fwd_open, packet_info *pinfo)
6458 {
6459    proto_item *pi;
6460    proto_tree *epath_tree;
6461    int conn_path_size, net_param_offset = 0;
6462    guint8 TransportClass_trigger;
6463    cip_simple_request_info_t connection_path;
6464    cip_safety_epath_info_t safety_fwdopen = {0};
6465 
6466    cip_connID_info_t O2T_info = {0};
6467    cip_connID_info_t T2O_info = {0};
6468 
6469    dissect_cip_cm_timeout(cmd_tree, tvb, offset);
6470    proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_ot_connid, tvb, offset+2, 4, ENC_LITTLE_ENDIAN, &O2T_info.connID);
6471    proto_tree_add_item_ret_uint( cmd_tree, hf_cip_cm_to_connid, tvb, offset+6, 4, ENC_LITTLE_ENDIAN, &T2O_info.connID);
6472 
6473    // Add Connection IDs as hidden items so that it's easy to find all Connection IDs in different fields.
6474    pi = proto_tree_add_item(cmd_tree, hf_cip_connid, tvb, offset + 2, 4, ENC_LITTLE_ENDIAN);
6475    proto_item_set_hidden(pi);
6476    pi = proto_tree_add_item(cmd_tree, hf_cip_connid, tvb, offset + 6, 4, ENC_LITTLE_ENDIAN);
6477    proto_item_set_hidden(pi);
6478 
6479    cip_connection_triad_t conn_triad;
6480    dissect_connection_triad(tvb, offset + 10, cmd_tree,
6481       hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
6482       &conn_triad);
6483 
6484    proto_tree_add_item(cmd_tree, hf_cip_cm_timeout_multiplier, tvb, offset+18, 1, ENC_LITTLE_ENDIAN);
6485    proto_tree_add_item(cmd_tree, hf_cip_reserved24, tvb, offset+19, 3, ENC_LITTLE_ENDIAN);
6486 
6487    // O->T parameters
6488    proto_tree_add_item(cmd_tree, hf_cip_cm_ot_rpi, tvb, offset + 22, 4, ENC_LITTLE_ENDIAN);
6489    if (large_fwd_open)
6490    {
6491       dissect_net_param32(tvb, offset+26, cmd_tree,
6492                  hf_cip_cm_ot_net_params32, hf_cip_cm_lfwo_own, hf_cip_cm_lfwo_typ,
6493                  hf_cip_cm_lfwo_prio, hf_cip_cm_lfwo_fixed_var, hf_cip_cm_lfwo_con_size, ett_cm_ncp, &O2T_info);
6494       net_param_offset = 4;
6495    }
6496    else
6497    {
6498       dissect_net_param16(tvb, offset+26, cmd_tree,
6499                  hf_cip_cm_ot_net_params16, hf_cip_cm_fwo_own, hf_cip_cm_fwo_typ,
6500                  hf_cip_cm_fwo_prio, hf_cip_cm_fwo_fixed_var, hf_cip_cm_fwo_con_size, ett_cm_ncp, &O2T_info);
6501       net_param_offset = 2;
6502    }
6503 
6504    // T->O parameters
6505    proto_tree_add_item(cmd_tree, hf_cip_cm_to_rpi, tvb, offset + 26 + net_param_offset, 4, ENC_LITTLE_ENDIAN);
6506    if (large_fwd_open)
6507    {
6508       dissect_net_param32(tvb, offset+26+net_param_offset+4, cmd_tree,
6509                  hf_cip_cm_to_net_params32, hf_cip_cm_lfwo_own, hf_cip_cm_lfwo_typ,
6510                  hf_cip_cm_lfwo_prio, hf_cip_cm_lfwo_fixed_var, hf_cip_cm_lfwo_con_size, ett_cm_ncp, &T2O_info);
6511       net_param_offset += 4;
6512    }
6513    else
6514    {
6515       dissect_net_param16(tvb, offset+26+net_param_offset+4, cmd_tree,
6516                  hf_cip_cm_to_net_params16, hf_cip_cm_fwo_own, hf_cip_cm_fwo_typ,
6517                  hf_cip_cm_fwo_prio, hf_cip_cm_fwo_fixed_var, hf_cip_cm_fwo_con_size, ett_cm_ncp, &T2O_info);
6518       net_param_offset += 2;
6519    }
6520 
6521    TransportClass_trigger = tvb_get_guint8( tvb, offset+26+net_param_offset+4);
6522    dissect_transport_type_trigger(tvb, offset+26+net_param_offset+4, cmd_tree, hf_cip_cm_transport_type_trigger,
6523                                   hf_cip_cm_fwo_dir, hf_cip_cm_fwo_trigg, hf_cip_cm_fwo_class, ett_cm_ttt);
6524 
6525    /* Add path size */
6526    conn_path_size = tvb_get_guint8( tvb, offset+26+net_param_offset+5 )*2;
6527    proto_tree_add_item(cmd_tree, hf_cip_cm_conn_path_size, tvb, offset+26+net_param_offset+5, 1, ENC_LITTLE_ENDIAN);
6528 
6529    /* Add the epath */
6530    epath_tree = proto_tree_add_subtree(cmd_tree, tvb, offset+26+net_param_offset+6, conn_path_size, ett_path, &pi, "Connection Path: ");
6531    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);
6532    save_route_connection_path(pinfo, tvb, offset + 26 + net_param_offset + 6, conn_path_size);
6533 
6534    if (pinfo->fd->visited)
6535    {
6536        /* "Connection" is created during ForwardOpen reply (which will be after ForwardOpen request),
6537           so ForwardOpen request can only be marked after the first pass */
6538        enip_mark_connection_triad(pinfo, &conn_triad);
6539    }
6540    else
6541    {
6542       if (preq_info != NULL)
6543       {
6544          DISSECTOR_ASSERT(preq_info->connInfo == NULL);
6545          preq_info->connInfo = wmem_new0(wmem_file_scope(), cip_conn_info_t);
6546 
6547          preq_info->connInfo->triad = conn_triad;
6548          preq_info->connInfo->open_req_frame = pinfo->num;
6549 
6550          preq_info->connInfo->O2T = O2T_info;
6551          preq_info->connInfo->T2O = T2O_info;
6552 
6553          preq_info->connInfo->TransportClass_trigger = TransportClass_trigger;
6554          preq_info->connInfo->safety = safety_fwdopen;
6555          preq_info->connInfo->ClassID = connection_path.iClass;
6556          preq_info->connInfo->ConnPoint = connection_path.iConnPoint;
6557 
6558          preq_info->connInfo->FwdOpenPathLenBytes = conn_path_size;
6559          preq_info->connInfo->pFwdOpenPathData = wmem_alloc(wmem_file_scope(), conn_path_size);
6560          tvb_memcpy(tvb, preq_info->connInfo->pFwdOpenPathData, offset + 26 + net_param_offset + 6, conn_path_size);
6561       }
6562    }
6563 
6564    mark_cip_connection(pinfo, tvb, cmd_tree);
6565 }
6566 
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)6567 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)
6568 {
6569    if (preq_info && preq_info->RouteConnectionPathLen && preq_info->pRouteConnectionPath)
6570    {
6571       tvbuff_t* tvbIOI = tvb_new_real_data((const guint8 *)preq_info->pRouteConnectionPath, preq_info->RouteConnectionPathLen * 2, preq_info->RouteConnectionPathLen * 2);
6572       if (!tvbIOI)
6573       {
6574          return;
6575       }
6576 
6577       proto_item* pi = proto_tree_add_uint(item_tree, hf_path, tvb, 0, 0, preq_info->RouteConnectionPathLen);
6578       proto_item_set_generated(pi);
6579 
6580       proto_tree* epath_tree = proto_tree_add_subtree(item_tree, tvb, 0, 0, ett_path, &pi, "Route/Connection Path: ");
6581       proto_item_set_generated(pi);
6582 
6583       cip_simple_request_info_t route_conn_path;
6584       dissect_epath(tvbIOI, pinfo, epath_tree, pi, 0, preq_info->RouteConnectionPathLen * 2, TRUE, FALSE, &route_conn_path, NULL, display_type, NULL, FALSE);
6585       tvb_free(tvbIOI);
6586    }
6587 }
6588 
6589 static int
dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t * preq_info,proto_tree * tree,tvbuff_t * tvb,int offset,packet_info * pinfo)6590 dissect_cip_cm_fwd_open_rsp_success(cip_req_info_t *preq_info, proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
6591 {
6592    int parsed_len = 26;
6593 
6594    unsigned char app_rep_size;
6595    guint32 O2TConnID, T2OConnID;
6596    guint16 init_rollover_value = 0, init_timestamp_value = 0;
6597    proto_tree *pid_tree, *safety_tree;
6598    cip_connection_triad_t target_triad = {0};
6599 
6600    /* Display originator to target connection ID */
6601    O2TConnID = tvb_get_letohl( tvb, offset );
6602    proto_tree_add_item( tree, hf_cip_cm_ot_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
6603 
6604    /* Display target to originator connection ID */
6605    T2OConnID = tvb_get_letohl( tvb, offset+4 );
6606    proto_tree_add_item( tree, hf_cip_cm_to_connid, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
6607 
6608    // Add Connection IDs as hidden items so that it's easy to find all Connection IDs in different fields.
6609    proto_item* pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
6610    proto_item_set_hidden(pi);
6611    pi = proto_tree_add_item(tree, hf_cip_connid, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
6612    proto_item_set_hidden(pi);
6613 
6614    cip_connection_triad_t conn_triad;
6615    dissect_connection_triad(tvb, offset + 8, tree,
6616       hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
6617       &conn_triad);
6618 
6619    /* Display originator to target actual packet interval */
6620    guint32 O2TAPI = tvb_get_letohl( tvb, offset+16 );
6621    proto_tree_add_item(tree, hf_cip_cm_ot_api, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN);
6622 
6623    /* Display originator to target actual packet interval */
6624    guint32 T2OAPI = tvb_get_letohl( tvb, offset+20 );
6625    proto_tree_add_item(tree, hf_cip_cm_to_api, tvb, offset + 20, 4, ENC_LITTLE_ENDIAN);
6626 
6627    /* Display the application reply size */
6628    app_rep_size = tvb_get_guint8( tvb, offset+24 ) * 2;
6629    proto_tree_add_item(tree, hf_cip_cm_app_reply_size, tvb, offset+24, 1, ENC_LITTLE_ENDIAN);
6630 
6631    /* Display the Reserved byte */
6632    proto_tree_add_item(tree, hf_cip_reserved8, tvb, offset+25, 1, ENC_LITTLE_ENDIAN );
6633    if (app_rep_size > 0)
6634    {
6635       if ((preq_info == NULL) || (preq_info->connInfo == NULL) ||
6636           (preq_info->connInfo->safety.safety_seg == FALSE))
6637       {
6638          proto_tree_add_item(tree, hf_cip_cm_app_reply_data, tvb, offset+26, app_rep_size, ENC_NA );
6639       }
6640       else if (preq_info->connInfo->safety.format == CIP_SAFETY_BASE_FORMAT)
6641       {
6642          safety_tree = proto_tree_add_subtree( tree, tvb, offset+26, 10, ett_cip_cm_safety, NULL, "Safety Application Reply Data");
6643          proto_tree_add_item( safety_tree, hf_cip_cm_consumer_number, tvb, offset+26, 2, ENC_LITTLE_ENDIAN);
6644          pid_tree = proto_tree_add_subtree( safety_tree, tvb, offset+28, 8, ett_cip_cm_pid, NULL, "PID/CID");
6645          proto_tree_add_item( pid_tree, hf_cip_cm_targ_vendor_id, tvb, offset+28, 2, ENC_LITTLE_ENDIAN);
6646          target_triad.VendorID = tvb_get_letohs(tvb, offset+28);
6647 
6648          proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_triad.DeviceSerialNumber);
6649 
6650          proto_tree_add_item( pid_tree, hf_cip_cm_targ_conn_serial_num, tvb, offset+34, 2, ENC_LITTLE_ENDIAN);
6651          target_triad.ConnSerialNumber = tvb_get_letohs(tvb, offset+34);
6652 
6653          if (app_rep_size > 10)
6654             proto_tree_add_item(tree, hf_cip_cm_app_reply_data, tvb, offset+36, app_rep_size-10, ENC_NA );
6655       }
6656       else if (preq_info->connInfo->safety.format == CIP_SAFETY_EXTENDED_FORMAT)
6657       {
6658          safety_tree = proto_tree_add_subtree( tree, tvb, offset+26, 14, ett_cip_cm_safety, NULL, "Safety Application Reply Data");
6659          proto_tree_add_item( safety_tree, hf_cip_cm_consumer_number, tvb, offset+26, 2, ENC_LITTLE_ENDIAN);
6660          pid_tree = proto_tree_add_subtree( safety_tree, tvb, offset+28, 12, ett_cip_cm_pid, NULL, "PID/CID");
6661          proto_tree_add_item( pid_tree, hf_cip_cm_targ_vendor_id, tvb, offset+28, 2, ENC_LITTLE_ENDIAN);
6662          target_triad.VendorID = tvb_get_letohs(tvb, offset+28);
6663 
6664          proto_tree_add_item_ret_uint( pid_tree, hf_cip_cm_targ_dev_serial_num, tvb, offset+30, 4, ENC_LITTLE_ENDIAN, &target_triad.DeviceSerialNumber);
6665 
6666          proto_tree_add_item( pid_tree, hf_cip_cm_targ_conn_serial_num, tvb, offset+34, 2, ENC_LITTLE_ENDIAN);
6667          target_triad.ConnSerialNumber = tvb_get_letohs(tvb, offset+34);
6668 
6669          proto_tree_add_item( pid_tree, hf_cip_cm_initial_timestamp, tvb, offset+36, 2, ENC_LITTLE_ENDIAN);
6670          init_timestamp_value = tvb_get_letohs(tvb, offset+36);
6671          proto_tree_add_item( pid_tree, hf_cip_cm_initial_rollover, tvb, offset+38, 2, ENC_LITTLE_ENDIAN);
6672          init_rollover_value = tvb_get_letohs(tvb, offset+38);
6673 
6674          if (app_rep_size > 14)
6675             proto_tree_add_item(tree, hf_cip_cm_app_reply_data, tvb, offset+40, app_rep_size-14, ENC_NA );
6676       }
6677    }
6678 
6679    proto_item* conn_info_item = NULL;
6680    proto_tree* conn_info_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
6681    proto_item_set_generated(conn_info_item);
6682 
6683    mark_cip_connection(pinfo, tvb, conn_info_tree);
6684    display_previous_route_connection_path(preq_info, conn_info_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
6685 
6686    /* See if we've captured the ForwardOpen request.  If so some of the conversation data has already been
6687       populated and we just need to update it. */
6688    if (pinfo->fd->visited)
6689       return parsed_len + app_rep_size;
6690 
6691    if ((preq_info != NULL) && (preq_info->connInfo != NULL))
6692    {
6693       /* Ensure the connection triad matches before updating the connection IDs */
6694       if ((preq_info->connInfo->triad.ConnSerialNumber == conn_triad.ConnSerialNumber) &&
6695           (preq_info->connInfo->triad.VendorID == conn_triad.VendorID) &&
6696           (preq_info->connInfo->triad.DeviceSerialNumber == conn_triad.DeviceSerialNumber))
6697       {
6698          /* Update the connection IDs as ForwardOpen reply is allowed to update them from
6699             the ForwardOpen request */
6700          preq_info->connInfo->O2T.connID = O2TConnID;
6701          preq_info->connInfo->T2O.connID = T2OConnID;
6702 
6703          preq_info->connInfo->O2T.api = O2TAPI;
6704          preq_info->connInfo->T2O.api = T2OAPI;
6705          if (preq_info->connInfo->safety.safety_seg == TRUE)
6706          {
6707              preq_info->connInfo->safety.running_rollover_value = init_rollover_value;
6708              preq_info->connInfo->safety.running_timestamp_value = init_timestamp_value;
6709              preq_info->connInfo->safety.target_triad = target_triad;
6710          }
6711       }
6712    }
6713 
6714    return parsed_len + app_rep_size;
6715 }
6716 
dissect_cip_cm_unconnected_send_req(proto_tree * cmd_data_tree,tvbuff_t * tvb,int offset,packet_info * pinfo)6717 static void dissect_cip_cm_unconnected_send_req(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
6718 {
6719    /* Display timeout fields */
6720    dissect_cip_cm_timeout(cmd_data_tree, tvb, offset);
6721 
6722    /* Message request size */
6723    guint16 msg_req_siz = tvb_get_letohs(tvb, offset + 2);
6724    proto_tree_add_item(cmd_data_tree, hf_cip_cm_msg_req_size, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
6725 
6726    /* Message Request */
6727    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");
6728 
6729    /*
6730    ** We call ourselves again to dissect embedded packet
6731    */
6732 
6733    col_append_str(pinfo->cinfo, COL_INFO, ": ");
6734 
6735    tvbuff_t* next_tvb = tvb_new_subset_length(tvb, offset + 4, msg_req_siz);
6736    cip_req_info_t* preq_info = (cip_req_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6737    cip_req_info_t* pembedded_req_info = NULL;
6738    if (preq_info)
6739    {
6740       if (preq_info->pData == NULL)
6741       {
6742          pembedded_req_info = wmem_new0(wmem_file_scope(), cip_req_info_t);
6743          preq_info->pData = pembedded_req_info;
6744       }
6745       else
6746       {
6747          pembedded_req_info = (cip_req_info_t*)preq_info->pData;
6748       }
6749    }
6750 
6751    dissect_cip_data(temp_tree, next_tvb, 0, pinfo, pembedded_req_info, NULL, FALSE);
6752 
6753    if (msg_req_siz % 2)
6754    {
6755       /* Pad byte */
6756       proto_tree_add_item(cmd_data_tree, hf_cip_pad8, tvb, offset + 4 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
6757       msg_req_siz++;  /* include the padding */
6758    }
6759 
6760    /* Route Path Size */
6761    guint16 route_path_size = tvb_get_guint8(tvb, offset + 4 + msg_req_siz) * 2;
6762    proto_tree_add_item(cmd_data_tree, hf_cip_cm_route_path_size, tvb, offset + 4 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
6763 
6764    /* Display the Reserved byte */
6765    proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 5 + msg_req_siz, 1, ENC_LITTLE_ENDIAN);
6766 
6767    /* Route Path */
6768    proto_item* epath_item;
6769    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: ");
6770    dissect_epath(tvb, pinfo, epath_tree, epath_item, offset + 6 + msg_req_siz, route_path_size, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
6771 
6772    save_route_connection_path(pinfo, tvb, offset + 6 + msg_req_siz, route_path_size);
6773 }
6774 
dissect_cip_cm_fwd_close_req(proto_tree * cmd_data_tree,tvbuff_t * tvb,int offset,packet_info * pinfo)6775 static void dissect_cip_cm_fwd_close_req(proto_tree* cmd_data_tree, tvbuff_t* tvb, int offset, packet_info* pinfo)
6776 {
6777    cip_simple_request_info_t conn_path;
6778 
6779    dissect_cip_cm_timeout(cmd_data_tree, tvb, offset);
6780 
6781    cip_connection_triad_t conn_triad;
6782    dissect_connection_triad(tvb, offset + 2, cmd_data_tree,
6783       hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
6784       &conn_triad);
6785 
6786    if (!pinfo->fd->visited)
6787       enip_mark_connection_triad(pinfo, &conn_triad);
6788 
6789    /* Add the path size */
6790    guint16 conn_path_size = tvb_get_guint8(tvb, offset + 10) * 2;
6791    proto_tree_add_item(cmd_data_tree, hf_cip_cm_conn_path_size, tvb, offset + 10, 1, ENC_LITTLE_ENDIAN);
6792 
6793    /* Display the Reserved byte */
6794    proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 11, 1, ENC_LITTLE_ENDIAN);
6795 
6796    /* Add the EPATH */
6797    proto_item *pi;
6798    proto_tree* epath_tree = proto_tree_add_subtree(cmd_data_tree, tvb, offset + 12, conn_path_size, ett_path, &pi, "Connection Path: ");
6799    dissect_epath(tvb, pinfo, epath_tree, pi, offset + 12, conn_path_size, FALSE, FALSE, &conn_path, NULL, DISPLAY_CONNECTION_PATH, NULL, FALSE);
6800    save_route_connection_path(pinfo, tvb, offset + 12, conn_path_size);
6801 
6802    mark_cip_connection(pinfo, tvb, cmd_data_tree);
6803 }
6804 
dissect_cip_cm_fwd_close_rsp_success(proto_tree * cmd_data_tree,tvbuff_t * tvb,int offset,packet_info * pinfo,proto_item * cmd_item)6805 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)
6806 {
6807    cip_connection_triad_t conn_triad;
6808    dissect_connection_triad(tvb, offset, cmd_data_tree,
6809       hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
6810       &conn_triad);
6811 
6812    /* Display the application reply size */
6813    guint16 app_rep_size = tvb_get_guint8(tvb, offset + 8) * 2;
6814    proto_tree_add_item(cmd_data_tree, hf_cip_cm_app_reply_size, tvb, offset + 8, 1, ENC_LITTLE_ENDIAN);
6815 
6816    /* Display the Reserved byte */
6817    proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset + 9, 1, ENC_LITTLE_ENDIAN);
6818    if (app_rep_size > 0)
6819    {
6820       if (tvb_reported_length_remaining(tvb, offset + 10) < app_rep_size)
6821       {
6822          expert_add_info(pinfo, cmd_item, &ei_mal_fwd_close_missing_data);
6823          return 0;
6824       }
6825       proto_tree_add_item(cmd_data_tree, hf_cip_cm_app_reply_data, tvb, offset + 10, app_rep_size, ENC_NA);
6826    }
6827 
6828    enip_close_cip_connection(pinfo, &conn_triad);
6829 
6830    proto_item* conn_info_item = NULL;
6831    proto_tree* conn_info_tree = proto_tree_add_subtree(cmd_data_tree, tvb, 0, 0, ett_connection_info, &conn_info_item, "Connection Information");
6832    proto_item_set_generated(conn_info_item);
6833 
6834    mark_cip_connection(pinfo, tvb, conn_info_tree);
6835 
6836    cip_req_info_t* preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6837    display_previous_route_connection_path(preq_info, conn_info_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
6838 
6839    return 10 + app_rep_size;
6840 }
6841 
display_previous_request_path(cip_req_info_t * preq_info,proto_tree * item_tree,tvbuff_t * tvb,packet_info * pinfo,proto_item * msp_item,gboolean is_msp_item)6842 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, gboolean is_msp_item)
6843 {
6844    if (preq_info && preq_info->IOILen && preq_info->pIOI)
6845    {
6846       proto_item *pi;
6847       proto_tree *epath_tree;
6848       tvbuff_t* tvbIOI;
6849 
6850       tvbIOI = tvb_new_real_data((const guint8 *)preq_info->pIOI, preq_info->IOILen * 2, preq_info->IOILen * 2);
6851       if (tvbIOI)
6852       {
6853          pi = proto_tree_add_uint(item_tree, hf_cip_request_path_size, tvb, 0, 0, preq_info->IOILen);
6854          proto_item_set_generated(pi);
6855 
6856          /* Add the epath */
6857          epath_tree = proto_tree_add_subtree(item_tree, tvb, 0, 0, ett_path, &pi, "Request Path: ");
6858          proto_item_set_generated(pi);
6859 
6860          if (preq_info->ciaData == NULL)
6861          {
6862             preq_info->ciaData = wmem_new(wmem_file_scope(), cip_simple_request_info_t);
6863          }
6864 
6865          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);
6866          tvb_free(tvbIOI);
6867       }
6868    }
6869 }
6870 
6871 static void
dissect_cip_cm_data(proto_tree * item_tree,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo)6872 dissect_cip_cm_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
6873 {
6874    proto_item *rrsc_item, *status_item;
6875    proto_tree *rrsc_tree, *cmd_data_tree;
6876    int req_path_size;
6877    unsigned char service, gen_status, add_stat_size;
6878    unsigned short add_status;
6879    int i;
6880    cip_req_info_t *preq_info;
6881 
6882    service = tvb_get_guint8( tvb, offset );
6883 
6884    /* Special handling for Unconnected send response. If successful, embedded service code is sent.
6885     * If failed, it can be either an Unconnected send response or the embedded service code response. */
6886    preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
6887    if (  preq_info != NULL && ( service & CIP_SC_RESPONSE_MASK )
6888       && preq_info->bService == SC_CM_UNCON_SEND
6889       )
6890    {
6891       gen_status = tvb_get_guint8( tvb, offset+2 );
6892       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
6893       if ( add_stat_size == 2 )
6894          add_status = tvb_get_letohs( tvb, offset + 4 );
6895       else
6896          add_status = 0;
6897 
6898       if(   gen_status == CI_GRC_SUCCESS
6899          || ( ( service & CIP_SC_MASK ) != SC_CM_UNCON_SEND )
6900          || !(  ( gen_status == CI_GRC_FAILURE && (add_status == CM_ES_UNCONNECTED_REQUEST_TIMED_OUT ||
6901                                                    add_status == CM_ES_PORT_NOT_AVAILABLE ||
6902                                                    add_status == CM_ES_LINK_ADDRESS_NOT_VALID ||
6903                                                    add_status == CM_ES_INVALID_SEGMENT_IN_CONN_PATH ||
6904                                                    add_status == CM_ES_LINK_ADDRESS_TO_SELF_INVALID))
6905              || gen_status == CI_GRC_NO_RESOURCE
6906              || gen_status == CI_GRC_BAD_PATH
6907              )
6908          )
6909       {
6910          cip_req_info_t* pembedded_req_info = (cip_req_info_t*)preq_info->pData;
6911 
6912          if ( pembedded_req_info )
6913          {
6914             tvbuff_t *next_tvb;
6915             void *p_save_proto_data;
6916             gint service_index;
6917             heur_dtbl_entry_t *hdtbl_entry;
6918 
6919             p_save_proto_data = p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0 );
6920             p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6921             p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, pembedded_req_info );
6922 
6923             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)" ));
6924             next_tvb = tvb_new_subset_length(tvb, offset, item_length);
6925 
6926             display_previous_request_path(pembedded_req_info, item_tree, tvb, pinfo, NULL, FALSE);
6927             display_previous_route_connection_path(preq_info, item_tree, tvb, pinfo, hf_cip_cm_route_path_size, NO_DISPLAY);
6928 
6929             /* Check to see if service is 'generic' */
6930             try_val_to_str_idx((service & CIP_SC_MASK), cip_sc_vals, &service_index);
6931 
6932             if ( pembedded_req_info && pembedded_req_info->dissector )
6933             {
6934                call_dissector(pembedded_req_info->dissector, next_tvb, pinfo, item_tree );
6935             }
6936             else if (service_index >= 0)
6937             {
6938                /* See if object dissector wants to override generic service handling */
6939                if (!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
6940                {
6941                    dissect_cip_generic_service_rsp(tvb, pinfo, item_tree);
6942                }
6943             }
6944             else
6945             {
6946                call_dissector( cip_class_generic_handle, next_tvb, pinfo, item_tree );
6947             }
6948 
6949             p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
6950             p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, p_save_proto_data);
6951 
6952             /* Return early because the response was only the embedded message response. */
6953             return;
6954          }
6955       }
6956    }
6957 
6958    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP CM");
6959 
6960    /* Add Service code & Request/Response tree */
6961    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_cm_rrsc, &rrsc_item, "Service: " );
6962 
6963    /* Add Request/Response */
6964    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
6965 
6966    /* watch for service collisions */
6967    proto_item_append_text( rrsc_item, "%s (%s)",
6968                val_to_str( ( service & CIP_SC_MASK ),
6969                   cip_sc_vals_cm , "Unknown Service (0x%02x)"),
6970                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
6971                   cip_sc_rr, "") );
6972 
6973    /* Add Service code */
6974    proto_tree_add_item(rrsc_tree, hf_cip_cm_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
6975    add_cip_service_to_info_column(pinfo, service, cip_sc_vals_cm);
6976 
6977    if( service & CIP_SC_RESPONSE_MASK )
6978    {
6979       /* Response message */
6980       gen_status = tvb_get_guint8( tvb, offset+2 );
6981       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
6982 
6983       if (gen_status == CI_GRC_FAILURE)
6984       {
6985          /* Dissect object specific error codes */
6986          proto_tree* status_tree = proto_tree_add_subtree(item_tree, tvb, offset+2, 1, ett_status_item, &status_item, "Status: " );
6987 
6988          /* Add general status */
6989          proto_tree_add_item(status_tree, hf_cip_cm_genstat, tvb, offset+2, 1, ENC_LITTLE_ENDIAN );
6990          proto_item_append_text( status_item, "%s", val_to_str_ext( gen_status,
6991                         &cip_gs_vals_ext , "Unknown Response (%x)")   );
6992 
6993          /* Add additional status size */
6994          proto_tree_add_item(status_tree, hf_cip_cm_addstat_size, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
6995 
6996          if( add_stat_size )
6997          {
6998             add_status = tvb_get_letohs( tvb, offset + 4 );
6999             proto_tree_add_item(status_tree, hf_cip_cm_ext_status, tvb, offset+4, 2, ENC_LITTLE_ENDIAN );
7000             proto_item_append_text(status_item, ", Extended: %s", val_to_str_ext(add_status, &cip_cm_ext_st_vals_ext, "Reserved (0x%04x)"));
7001 
7002             switch(add_status)
7003             {
7004             case CM_ES_RPI_NOT_ACCEPTABLE:
7005                if (add_stat_size < 3)
7006                {
7007                   expert_add_info(pinfo, status_item, &ei_mal_rpi_no_data);
7008                }
7009                else
7010                {
7011                   proto_tree_add_item(status_tree, hf_cip_cm_ext112_ot_rpi_type, tvb, offset+6, 1, ENC_LITTLE_ENDIAN );
7012                   proto_tree_add_item(status_tree, hf_cip_cm_ext112_to_rpi_type, tvb, offset+7, 1, ENC_LITTLE_ENDIAN );
7013                   proto_tree_add_item(status_tree, hf_cip_cm_ext112_ot_rpi, tvb, offset + 8, 4, ENC_LITTLE_ENDIAN);
7014                   proto_tree_add_item(status_tree, hf_cip_cm_ext112_to_rpi, tvb, offset + 12, 4, ENC_LITTLE_ENDIAN);
7015                }
7016                break;
7017             case CM_ES_INVALID_CONFIGURATION_SIZE:
7018                proto_tree_add_item(status_tree, hf_cip_cm_ext126_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
7019                break;
7020             case CM_ES_INVALID_OT_SIZE:
7021                proto_tree_add_item(status_tree, hf_cip_cm_ext127_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
7022                break;
7023             case CM_ES_INVALID_TO_SIZE:
7024                proto_tree_add_item(status_tree, hf_cip_cm_ext128_size, tvb, offset+6, 2, ENC_LITTLE_ENDIAN );
7025                break;
7026             default:
7027                /* Add additional status */
7028                if (add_stat_size > 1)
7029                {
7030                   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" );
7031 
7032                   for( i=0; i < add_stat_size-2; i += 2 )
7033                      proto_tree_add_item(add_status_tree, hf_cip_cm_add_status, tvb, offset+4+i, 2, ENC_LITTLE_ENDIAN );
7034                }
7035             }
7036          }
7037       }
7038 
7039       /* If there is any command specific data create a sub-tree for it */
7040       int data_len = item_length - 4 - add_stat_size;
7041       if (data_len > 0)
7042       {
7043          int parsed_len = 0;
7044          offset += (4 + add_stat_size);
7045 
7046          proto_item *cmd_item;
7047          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset, data_len,
7048                                                  ett_cm_cmd_data, &cmd_item, "Command Specific Data" );
7049 
7050          if( gen_status == CI_GRC_SUCCESS )
7051          {
7052            /* Success responses */
7053            switch (service & CIP_SC_MASK)
7054            {
7055            case SC_CM_FWD_OPEN:
7056            case SC_CM_LARGE_FWD_OPEN:
7057               parsed_len = dissect_cip_cm_fwd_open_rsp_success(preq_info, cmd_data_tree, tvb, offset, pinfo);
7058               break;
7059            case SC_CM_FWD_CLOSE:
7060               parsed_len = dissect_cip_cm_fwd_close_rsp_success(cmd_data_tree, tvb, offset, pinfo, cmd_item);
7061               break;
7062             case SC_CM_GET_CONN_OWNER:
7063             {
7064                /* Get Connection owner response (Success) */
7065                proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_conn, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7066                proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_coo_conn, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
7067                proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_roo_conn, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
7068                proto_tree_add_item( cmd_data_tree, hf_cip_cm_gco_last_action, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
7069 
7070                dissect_connection_triad(tvb, offset + 4, cmd_data_tree,
7071                   hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
7072                   NULL);
7073 
7074                parsed_len = 12;
7075             }
7076             break;
7077             case SC_CM_UNCON_SEND:  // Unconnected send response (Success)
7078             default:
7079                parsed_len = 0;
7080                break;
7081             }
7082          }
7083          else
7084          {
7085             /* Error responses */
7086             switch (service & CIP_SC_MASK)
7087             {
7088             case SC_CM_FWD_OPEN:
7089             case SC_CM_LARGE_FWD_OPEN:
7090             case SC_CM_FWD_CLOSE:
7091             {
7092                /* Forward open and forward close error response look the same */
7093                cip_connection_triad_t conn_triad;
7094                dissect_connection_triad(tvb, offset, cmd_data_tree,
7095                   hf_cip_cm_conn_serial_num, hf_cip_cm_vendor, hf_cip_cm_orig_serial_num,
7096                   &conn_triad);
7097 
7098                proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset+8, 1, ENC_LITTLE_ENDIAN);
7099                proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+9, 1, ENC_LITTLE_ENDIAN);
7100 
7101                /* With an error reply the connection will either never be established or it has since already closed
7102                   That means the conversation should end too */
7103                enip_close_cip_connection(pinfo, &conn_triad);
7104                if (preq_info != NULL)
7105                {
7106                   /* Remove any connection information */
7107                   preq_info->connInfo = NULL;
7108                }
7109 
7110 
7111                display_previous_route_connection_path(preq_info, cmd_data_tree, tvb, pinfo, hf_cip_cm_conn_path_size, DISPLAY_CONNECTION_PATH);
7112 
7113                parsed_len = 10;
7114                break;
7115             }
7116             case SC_CM_UNCON_SEND:
7117                /* Unconnected send response (Unsuccess) */
7118                proto_tree_add_item(cmd_data_tree, hf_cip_cm_remain_path_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
7119                proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
7120                display_previous_route_connection_path(preq_info, item_tree, tvb, pinfo, hf_cip_cm_route_path_size, NO_DISPLAY);
7121                parsed_len = 2;
7122                break;
7123             default:
7124                parsed_len = 0;
7125                break;
7126             }
7127          } /* end of if-else( CI_CRC_SUCCESS ) */
7128 
7129          int remain_len = tvb_reported_length_remaining(tvb, offset + parsed_len);
7130          if (remain_len > 0)
7131          {
7132             proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset + parsed_len, remain_len, ENC_NA);
7133          }
7134       } /* End of if command-specific data present */
7135 
7136    } /* End of if reply */
7137    else
7138    {
7139       /* Request message */
7140 
7141       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
7142 
7143       /* If there is any command specific data creat a sub-tree for it */
7144       if( (item_length-req_path_size-2) != 0 )
7145       {
7146 
7147          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
7148                                                  ett_cm_cmd_data, NULL, "Command Specific Data" );
7149 
7150          /* Check what service code that received */
7151          switch (service)
7152          {
7153          case SC_CM_FWD_OPEN:
7154             /* Forward open Request*/
7155             dissect_cip_cm_fwd_open_req(preq_info, cmd_data_tree, tvb, offset+2+req_path_size, FALSE, pinfo);
7156             break;
7157          case SC_CM_LARGE_FWD_OPEN:
7158             /* Large Forward open Request*/
7159             dissect_cip_cm_fwd_open_req(preq_info, cmd_data_tree, tvb, offset+2+req_path_size, TRUE, pinfo);
7160             break;
7161          case SC_CM_FWD_CLOSE:
7162             dissect_cip_cm_fwd_close_req(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
7163             break;
7164          case SC_CM_UNCON_SEND:
7165             dissect_cip_cm_unconnected_send_req(cmd_data_tree, tvb, offset + 2 + req_path_size, pinfo);
7166             break;
7167          case SC_CM_GET_CONN_OWNER:
7168          {
7169             /* Get Connection Owner Request */
7170 
7171             /* Display the Reserved byte */
7172             proto_tree_add_item(cmd_data_tree, hf_cip_reserved8, tvb, offset+2+req_path_size, 1, ENC_LITTLE_ENDIAN);
7173 
7174             /* Add path size */
7175             guint16 conn_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+1 )*2;
7176             proto_tree_add_item(cmd_data_tree, hf_cip_cm_conn_path_size, tvb, offset+2+req_path_size+1, 1, ENC_LITTLE_ENDIAN);
7177 
7178             /* Add the epath */
7179             proto_item* pi;
7180             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: ");
7181             dissect_epath(tvb, pinfo, epath_tree, pi, offset+2+req_path_size+2, conn_path_size, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
7182             break;
7183          }
7184          default:
7185             /* Add data */
7186             proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
7187          }
7188 
7189       } /* End of if command-specific data present */
7190 
7191    } /* End of if-else( request ) */
7192 
7193 } /* End of dissect_cip_cm_data() */
7194 
7195 static int
dissect_cip_class_cm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)7196 dissect_cip_class_cm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
7197 {
7198    proto_item *ti;
7199    proto_tree *class_tree;
7200 
7201    /* Create display subtree for the protocol */
7202    ti = proto_tree_add_item(tree, proto_cip_class_cm, tvb, 0, -1, ENC_NA);
7203    class_tree = proto_item_add_subtree( ti, ett_cip_class_cm );
7204 
7205    dissect_cip_cm_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
7206 
7207    return tvb_reported_length(tvb);
7208 }
7209 
7210 /************************************************
7211  *
7212  * Dissector for CIP PCCC Object
7213  *
7214  ************************************************/
7215 static void
dissect_cip_pccc_data(proto_tree * item_tree,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo)7216 dissect_cip_pccc_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
7217 {
7218    proto_item *rrsc_item;
7219    proto_tree *rrsc_tree, *req_id_tree, *pccc_cmd_tree, *cmd_data_tree;
7220    int req_path_size;
7221    unsigned char service;
7222    int add_status;
7223 
7224    service = tvb_get_guint8( tvb, offset );
7225 
7226    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP PCCC");
7227 
7228    /* Add Service code & Request/Response tree */
7229    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_pccc_rrsc, &rrsc_item, "Service: " );
7230 
7231    /* Add Request/Response */
7232    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7233 
7234    /* watch for service collisions */
7235    proto_item_append_text( rrsc_item, "%s (%s)",
7236                val_to_str( ( service & CIP_SC_MASK ),
7237                   cip_sc_vals_pccc , "Unknown Service (0x%02x)"),
7238                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
7239                   cip_sc_rr, "") );
7240 
7241    /* Add Service code */
7242    proto_tree_add_item(rrsc_tree, hf_cip_pccc_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7243    add_cip_service_to_info_column (pinfo, service, cip_sc_vals_pccc);
7244 
7245    /* There is a minimum of two bytes different between the request and response request path */
7246    /* Response message */
7247    if ( service & CIP_SC_RESPONSE_MASK )
7248    {
7249        req_path_size = 2 + tvb_get_guint8( tvb, offset+2 )*2;
7250    }
7251    /* Request message */
7252    else
7253    {
7254        req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
7255    }
7256 
7257    int req_id_offset = offset+req_path_size+2;
7258    int req_id_size = tvb_get_guint8( tvb, req_id_offset );
7259    int pccc_cmd_offset = req_id_offset+req_id_size;
7260 
7261    /* Add Requestor ID tree */
7262    req_id_tree = proto_tree_add_subtree( item_tree, tvb, req_id_offset, req_id_size, ett_pccc_req_id, NULL, "Requestor ID" );
7263    /* Add Length of Requestor ID code */
7264    proto_tree_add_item(req_id_tree, hf_cip_pccc_req_id_len, tvb, req_id_offset, 1, ENC_LITTLE_ENDIAN );
7265    /* Add CIP Vendor ID */
7266    proto_tree_add_item(req_id_tree, hf_cip_pccc_cip_vend_id, tvb, req_id_offset+1, 2, ENC_LITTLE_ENDIAN );
7267    /* Add CIP Serial Number */
7268    proto_tree_add_item(req_id_tree, hf_cip_pccc_cip_serial_num, tvb, req_id_offset+3, 4, ENC_LITTLE_ENDIAN );
7269 
7270    if( service & CIP_SC_RESPONSE_MASK )
7271    {
7272         /* Add PCCC Response Data tree */
7273          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" );
7274 
7275          /* Add Command Code */
7276          proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_resp_code, tvb, pccc_cmd_offset, 1, ENC_LITTLE_ENDIAN );
7277          /* Add Status Code */
7278          proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_sts_code, tvb, pccc_cmd_offset+1, 1, ENC_LITTLE_ENDIAN );
7279          /* Add Transaction Code */
7280          proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_tns_code, tvb, pccc_cmd_offset+2, 2, ENC_LITTLE_ENDIAN );
7281 
7282          /* Check the status byte for the EXT_STS signifier - 0xF0 */
7283          add_status = tvb_get_guint8( tvb, pccc_cmd_offset+1 );
7284          // TODO: still need to test this
7285          if ( add_status == PCCC_GS_USE_EXTSTS )
7286          {
7287              proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_ext_sts_code, tvb, pccc_cmd_offset+4, 1, ENC_LITTLE_ENDIAN );
7288          }
7289          // handle cases where data is returned in the response
7290          else if (item_length-req_path_size-2-req_id_size-4 != 0)
7291          {
7292             /* Add the data tree */
7293             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" );
7294             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);
7295          }
7296 
7297    } /* end of if reply */
7298 
7299   /* Request message */
7300    else
7301    {
7302       /* If there is any command specific data create a sub-tree for it */
7303       if( (item_length-req_path_size-2) != 0 )
7304       {
7305          guint32 cmd_code, fnc_code;
7306 
7307          /* Add PCCC CMD Data tree */
7308          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" );
7309 
7310          /* Add Command Code */
7311          proto_tree_add_item_ret_uint(pccc_cmd_tree, hf_cip_pccc_cmd_code, tvb, pccc_cmd_offset, 1, ENC_LITTLE_ENDIAN, &cmd_code);
7312          /* Add Status Code */
7313          proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_sts_code, tvb, pccc_cmd_offset+1, 1, ENC_LITTLE_ENDIAN );
7314          /* Add Transaction Code */
7315          proto_tree_add_item(pccc_cmd_tree, hf_cip_pccc_tns_code, tvb, pccc_cmd_offset+2, 2, ENC_LITTLE_ENDIAN );
7316          /* Add Function Code */
7317          switch(cmd_code)
7318          {
7319              case PCCC_CMD_06:
7320                  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);
7321                  add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_06_vals);
7322              break;
7323 
7324              case PCCC_CMD_07:
7325                  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);
7326                  add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_07_vals);
7327              break;
7328 
7329              case PCCC_CMD_0F:
7330                  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);
7331                  add_cip_pccc_function_to_info_column(pinfo, fnc_code, cip_pccc_fnc_0f_vals);
7332              break;
7333 
7334              default:
7335                  fnc_code = 0;
7336              break;
7337          }
7338 
7339          if (item_length-req_path_size-2-req_id_size-5 != 0 )
7340          {
7341                      /* Add the data tree */
7342             cmd_data_tree = proto_tree_add_subtree( pccc_cmd_tree, tvb, pccc_cmd_offset+5, item_length-req_path_size-req_id_size-7,
7343                                         ett_pccc_cmd_data, NULL, "Function Specific Data" );
7344 
7345             int running_offset = pccc_cmd_offset+6;
7346             int num_cmds;
7347             int sub_fnc_len;
7348             proto_tree *sub_fnc_tree;
7349 
7350             /* Add in parsing of instructions that contain data beyond the FNC code */
7351             /* Instructions that end at the FNC codes are already processed */
7352             switch(cmd_code)
7353             {
7354                 case PCCC_CMD_0F:
7355                     switch(fnc_code){
7356                         /* Change CPU Mode */
7357                         case PCCC_FNC_0F_80:
7358                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_cpu_mode_80, tvb, pccc_cmd_offset+5, 1, ENC_NA);
7359                         break;
7360                         /* Execute Multiple Commands */
7361                         case PCCC_FNC_0F_88:
7362                             num_cmds = tvb_get_guint8( tvb, pccc_cmd_offset+5 );
7363                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_execute_multi_count, tvb, pccc_cmd_offset+5, 1, ENC_NA);
7364 
7365                             /* iterate over each of the commands and break them out */
7366                             for( int i=0; i < num_cmds; i++ ){
7367                                 sub_fnc_len = tvb_get_guint8( tvb, running_offset);
7368                                 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);
7369 
7370                                 proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_execute_multi_len, tvb, running_offset, 1, ENC_NA);
7371                                 proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_execute_multi_fnc, tvb, running_offset+1, 1, ENC_NA);
7372                                 if( sub_fnc_len > 2 ){
7373                                     proto_tree_add_item(sub_fnc_tree, hf_cip_pccc_data, tvb, running_offset+2, sub_fnc_len-1, ENC_NA);
7374                                 }
7375                                 running_offset = running_offset+sub_fnc_len+1;
7376                             }
7377                         break;
7378                         /* Protected Typed Logical Read with Three Address Fields */
7379                         case PCCC_FNC_0F_A2:
7380                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_byte_size, tvb, pccc_cmd_offset+5, 1, ENC_NA);
7381                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_num, tvb, pccc_cmd_offset+6, 1, ENC_NA);
7382                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_type, tvb, pccc_cmd_offset+7, 1, ENC_NA);
7383                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_element_num, tvb, pccc_cmd_offset+8, 1, ENC_NA);
7384                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_subelement_num, tvb, pccc_cmd_offset+9, 1, ENC_NA);
7385                         break;
7386                         /* Protected Typed Logical Write with Three Address Fields */
7387                         case PCCC_FNC_0F_AA:
7388                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_byte_size, tvb, pccc_cmd_offset+5, 1, ENC_NA);
7389                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_num, tvb, pccc_cmd_offset+6, 1, ENC_NA);
7390                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_file_type, tvb, pccc_cmd_offset+7, 1, ENC_NA);
7391                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_element_num, tvb, pccc_cmd_offset+8, 1, ENC_NA);
7392                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_subelement_num, tvb, pccc_cmd_offset+9, 1, ENC_NA);
7393                             int byte_size;
7394                             byte_size = tvb_get_guint8( tvb, pccc_cmd_offset+5 );
7395 
7396                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+10, byte_size, ENC_NA);
7397                         break;
7398                         default: /* just print the command data if no known command code is passed */
7399                             proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+5, item_length-pccc_cmd_offset-5, ENC_NA);
7400                     }
7401                 break;
7402                 default: /* just print the command data if no known command code is passed */
7403                     proto_tree_add_item(cmd_data_tree, hf_cip_pccc_data, tvb, pccc_cmd_offset+5, 1, ENC_NA);
7404             }
7405         }
7406        } /* End of if-else( request ) */
7407     }
7408 
7409 } /* End of dissect_cip_pccc_data() */
7410 
7411 static int
dissect_cip_class_pccc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)7412 dissect_cip_class_pccc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
7413 {
7414    proto_item *ti;
7415    proto_tree *class_tree;
7416 
7417    /* Create display subtree for the protocol */
7418    ti = proto_tree_add_item(tree, proto_cip_class_pccc, tvb, 0, -1, ENC_NA);
7419    class_tree = proto_item_add_subtree( ti, ett_cip_class_pccc );
7420 
7421    dissect_cip_pccc_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
7422 
7423    return tvb_reported_length(tvb);
7424 }
7425 
7426 /************************************************
7427  *
7428  * Dissector for CIP Modbus Object
7429  *
7430  ************************************************/
7431 static void
dissect_cip_mb_data(proto_tree * item_tree,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo)7432 dissect_cip_mb_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
7433 {
7434    proto_item *rrsc_item;
7435    proto_tree *rrsc_tree, *cmd_data_tree;
7436    tvbuff_t *next_tvb;
7437    int req_path_size;
7438    guint8 gen_status, add_stat_size, service;
7439 
7440    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP MB");
7441 
7442    /* Add Service code & Request/Response tree */
7443    service = tvb_get_guint8( tvb, offset );
7444    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_mb_rrsc, &rrsc_item, "Service: " );
7445 
7446    /* Add Request/Response */
7447    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7448 
7449    proto_item_append_text( rrsc_item, "%s (%s)",
7450                val_to_str( ( service & CIP_SC_MASK ),
7451                   cip_sc_vals_mb , "Unknown Service (0x%02x)"),
7452                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
7453                   cip_sc_rr, "") );
7454 
7455    /* Add Service code */
7456    proto_tree_add_item(rrsc_tree, hf_cip_mb_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7457 
7458    if( service & CIP_SC_RESPONSE_MASK )
7459    {
7460       /* Response message */
7461       gen_status = tvb_get_guint8( tvb, offset+2 );
7462       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
7463 
7464       /* If there is any command specific data create a sub-tree for it */
7465       if( ( item_length-4-add_stat_size ) != 0 )
7466       {
7467          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
7468                                                  ett_mb_cmd_data, NULL, "Command Specific Data" );
7469 
7470          if( gen_status == CI_GRC_SUCCESS || gen_status == CI_GRC_SERVICE_ERROR )
7471          {
7472             /* Success responses */
7473             switch (service & CIP_SC_MASK)
7474             {
7475             case SC_MB_READ_DISCRETE_INPUTS:
7476                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);
7477                break;
7478 
7479             case SC_MB_READ_COILS:
7480                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);
7481                break;
7482 
7483             case SC_MB_READ_INPUT_REGISTERS:
7484                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);
7485                break;
7486 
7487             case SC_MB_READ_HOLDING_REGISTERS:
7488                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);
7489                break;
7490 
7491             case SC_MB_WRITE_COILS:
7492                proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_start_addr, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
7493                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);
7494                break;
7495 
7496             case SC_MB_WRITE_HOLDING_REGISTERS:
7497                proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_start_addr, tvb, offset+4+add_stat_size, 2, ENC_LITTLE_ENDIAN);
7498                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);
7499                break;
7500 
7501             case SC_MB_PASSTHROUGH:
7502                /* Passthrough response (Success) */
7503                if( tvb_reported_length_remaining(tvb, offset) > 0 )
7504                {
7505                   modbus_data_t modbus_data;
7506                   modbus_data.packet_type = RESPONSE_PACKET;
7507                   modbus_data.mbtcp_transid = 0;
7508                   modbus_data.unit_id = 0;
7509 
7510                   /* dissect the Modbus PDU */
7511                   next_tvb = tvb_new_subset_length( tvb, offset+4+add_stat_size, item_length-4-add_stat_size);
7512 
7513                   /* Call Modbus Dissector */
7514                   call_dissector_with_data(modbus_handle, next_tvb, pinfo, cmd_data_tree, &modbus_data);
7515 
7516                }
7517                break;
7518 
7519             default:
7520                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);
7521             }
7522          }
7523          else
7524          {
7525             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);
7526          }
7527 
7528       } /* End of if command-specific data present */
7529 
7530    } /* End of if reply */
7531    else
7532    {
7533       /* Request message */
7534       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
7535 
7536       /* If there is any command specific data creat a sub-tree for it */
7537       if( (item_length-req_path_size-2) != 0 )
7538       {
7539          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
7540                                                 ett_mb_cmd_data, NULL, "Command Specific Data" );
7541 
7542          /* Check what service code that received */
7543          switch (service)
7544          {
7545          case SC_MB_READ_DISCRETE_INPUTS:
7546             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);
7547             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);
7548             break;
7549 
7550          case SC_MB_READ_COILS:
7551             proto_tree_add_item(cmd_data_tree, hf_cip_mb_read_coils_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
7552             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);
7553             break;
7554 
7555          case SC_MB_READ_INPUT_REGISTERS:
7556             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);
7557             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);
7558             break;
7559 
7560          case SC_MB_READ_HOLDING_REGISTERS:
7561             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);
7562             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);
7563             break;
7564 
7565          case SC_MB_WRITE_COILS:
7566             {
7567             guint16 NumCoils;
7568 
7569             proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_coils_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
7570             NumCoils = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
7571             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);
7572             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);
7573             }
7574             break;
7575 
7576          case SC_MB_WRITE_HOLDING_REGISTERS:
7577             {
7578             guint16 NumRegisters;
7579 
7580             proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_start_addr, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN);
7581             NumRegisters = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
7582             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);
7583             proto_tree_add_item(cmd_data_tree, hf_cip_mb_write_registers_data, tvb, offset+2+req_path_size+4, NumRegisters*2, ENC_NA);
7584             }
7585             break;
7586 
7587          case SC_MB_PASSTHROUGH:
7588             /* Passthrough Request */
7589             if( tvb_reported_length_remaining(tvb, offset) > 0 )
7590             {
7591                modbus_data_t modbus_data;
7592                modbus_data.packet_type = QUERY_PACKET;
7593                modbus_data.mbtcp_transid = 0;
7594                modbus_data.unit_id = 0;
7595 
7596                /* dissect the Modbus PDU */
7597                next_tvb = tvb_new_subset_length( tvb, offset+2+req_path_size, item_length-req_path_size-2);
7598 
7599                /* Call Modbus Dissector */
7600                call_dissector_with_data(modbus_handle, next_tvb, pinfo, cmd_data_tree, &modbus_data);
7601             }
7602             break;
7603 
7604          default:
7605             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);
7606          }
7607 
7608       } /* End of if command-specific data present */
7609 
7610    } /* End of if-else( request ) */
7611 
7612    add_cip_service_to_info_column(pinfo, service, cip_sc_vals_mb);
7613 } /* End of dissect_cip_mb_data() */
7614 
7615 static int
dissect_cip_class_mb(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)7616 dissect_cip_class_mb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
7617 {
7618    proto_item *ti;
7619    proto_tree *class_tree;
7620 
7621    /* Create display subtree for the protocol */
7622    ti = proto_tree_add_item(tree, proto_cip_class_mb, tvb, 0, -1, ENC_NA);
7623    class_tree = proto_item_add_subtree( ti, ett_cip_class_mb );
7624 
7625    dissect_cip_mb_data( class_tree, tvb, 0, tvb_reported_length(tvb), pinfo );
7626 
7627    return tvb_reported_length(tvb);
7628 }
7629 
7630 /************************************************
7631  *
7632  * Dissector for CIP Connection Configuration Object
7633  *
7634  ************************************************/
7635 static int
dissect_cip_cco_all_attribute_common(proto_tree * cmd_tree,proto_item * ti,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo)7636 dissect_cip_cco_all_attribute_common( proto_tree *cmd_tree, proto_item *ti,
7637     tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo)
7638 {
7639    proto_item *pi;
7640    proto_tree *tdi_tree, *iomap_tree, *epath_tree;
7641    proto_tree *ncp_tree;
7642    int conn_path_size, variable_data_size = 0, config_data_size;
7643    int iomap_size, ot_rtf, to_rtf;
7644    int temp_data;
7645 
7646    /* Connection flags */
7647    temp_data = tvb_get_letohs( tvb, offset);
7648    ot_rtf = (temp_data >> 1) & 7;
7649    to_rtf = (temp_data >> 4) & 7;
7650 
7651    static int *const connection_flags[] = {
7652       &hf_cip_cco_con_type,
7653       &hf_cip_cco_ot_rtf,
7654       &hf_cip_cco_to_rtf,
7655       NULL
7656    };
7657    proto_tree_add_bitmask(cmd_tree, tvb, offset, hf_cip_cco_con_flags, ett_cco_con_flag, connection_flags, ENC_LITTLE_ENDIAN);
7658 
7659    /* Target device id */
7660    tdi_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+2, 10, ett_cco_tdi, NULL, "Target Device ID");
7661 
7662    dissect_deviceid(tvb, offset+2, tdi_tree,
7663       hf_cip_cco_tdi_vendor, hf_cip_cco_tdi_devtype, hf_cip_cco_tdi_prodcode,
7664       hf_cip_cco_tdi_compatibility, hf_cip_cco_tdi_comp_bit, hf_cip_cco_tdi_majorrev, hf_cip_cco_tdi_minorrev, FALSE);
7665 
7666    /* CS Data Index Number */
7667    proto_tree_add_item(cmd_tree, hf_cip_cco_cs_data_index, tvb, offset+10, 4, ENC_LITTLE_ENDIAN );
7668 
7669    /* Net Connection Parameters */
7670    ncp_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+14, 14, ett_cco_ncp, NULL, "Net Connection Parameters");
7671 
7672    /* Timeout multiplier */
7673    proto_tree_add_item(ncp_tree, hf_cip_cco_timeout_multiplier, tvb, offset+14, 1, ENC_LITTLE_ENDIAN );
7674 
7675    dissect_transport_type_trigger(tvb, offset+15, ncp_tree, hf_cip_cco_transport_type_trigger,
7676                                   hf_cip_cco_fwo_dir, hf_cip_cco_fwo_trigger, hf_cip_cco_fwo_class, ett_cco_ttt);
7677 
7678    proto_tree_add_item(ncp_tree, hf_cip_cco_ot_rpi, tvb, offset + 16, 4, ENC_LITTLE_ENDIAN);
7679 
7680    /* Display O->T network connection parameters */
7681    cip_connID_info_t ignore;
7682    dissect_net_param16(tvb, offset+20, ncp_tree,
7683               hf_cip_cco_ot_net_param16, hf_cip_cco_fwo_own, hf_cip_cco_fwo_typ,
7684               hf_cip_cco_fwo_prio, hf_cip_cco_fwo_fixed_var, hf_cip_cco_fwo_con_size, ett_cco_ncp, &ignore);
7685 
7686    proto_tree_add_item(ncp_tree, hf_cip_cco_to_rpi, tvb, offset + 22, 4, ENC_LITTLE_ENDIAN);
7687 
7688    /* Display T->O network connection parameters */
7689    dissect_net_param16(tvb, offset+26, ncp_tree,
7690               hf_cip_cco_to_net_param16, hf_cip_cco_fwo_own, hf_cip_cco_fwo_typ,
7691               hf_cip_cco_fwo_prio, hf_cip_cco_fwo_fixed_var, hf_cip_cco_fwo_con_size, ett_cco_ncp, &ignore);
7692 
7693    /* Connection Path */
7694    conn_path_size = tvb_get_guint8( tvb, offset+28 )*2;
7695    proto_tree_add_item(cmd_tree, hf_cip_cco_conn_path_size, tvb, offset+28, 1, ENC_LITTLE_ENDIAN);
7696 
7697    /* Display the Reserved byte */
7698    proto_tree_add_item(cmd_tree, hf_cip_reserved8, tvb, offset+29, 1, ENC_LITTLE_ENDIAN );
7699 
7700    /* Add the epath */
7701    epath_tree = proto_tree_add_subtree(cmd_tree, tvb, offset+30, conn_path_size, ett_path, &pi, "Connection Path: ");
7702    dissect_epath(tvb, pinfo, epath_tree, pi, offset+30, conn_path_size, FALSE, FALSE, NULL, NULL, NO_DISPLAY, NULL, FALSE);
7703 
7704    variable_data_size += (conn_path_size+30);
7705 
7706    /* Config #1 Data */
7707    config_data_size = tvb_get_letohs( tvb, offset+variable_data_size);
7708    proto_tree_add_item(cmd_tree, hf_cip_cco_proxy_config_size, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
7709    if (config_data_size > 0)
7710       proto_tree_add_item(cmd_tree, hf_cip_cco_proxy_config_data, tvb, offset+variable_data_size+2, config_data_size, ENC_NA);
7711 
7712    variable_data_size += (config_data_size+2);
7713 
7714    /* Config #2 Data */
7715    config_data_size = tvb_get_letohs( tvb, offset+variable_data_size);
7716    proto_tree_add_item(cmd_tree, hf_cip_cco_target_config_size, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
7717    if (config_data_size > 0)
7718       proto_tree_add_item(cmd_tree, hf_cip_cco_target_config_data, tvb, offset+variable_data_size+2, config_data_size, ENC_NA);
7719 
7720    variable_data_size += (config_data_size+2);
7721 
7722    /* Connection Name */
7723    variable_data_size += dissect_cip_string_type(pinfo, cmd_tree, ti, tvb, offset + variable_data_size, hf_cip_cco_connection_name, CIP_STRING2_TYPE);
7724 
7725    /* I/O Mapping */
7726    iomap_size = tvb_get_letohs( tvb, offset+variable_data_size+2);
7727 
7728    iomap_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, iomap_size+4, ett_cco_iomap, NULL, "I/O Mapping");
7729 
7730    proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_format_number, tvb, offset+variable_data_size, 2, ENC_LITTLE_ENDIAN );
7731    proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_size, tvb, offset+variable_data_size+2, 2, ENC_LITTLE_ENDIAN);
7732 
7733    /* Attribute data */
7734    if (iomap_size > 0)
7735       proto_tree_add_item(iomap_tree, hf_cip_cco_iomap_attribute, tvb, offset+variable_data_size+4, iomap_size, ENC_NA);
7736 
7737    variable_data_size += (iomap_size+4);
7738 
7739    /* Proxy device id */
7740    tdi_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, 8, ett_cco_pdi, NULL, "Proxy Device ID");
7741 
7742    dissect_deviceid(tvb, offset+variable_data_size, tdi_tree,
7743       hf_cip_cco_pdi_vendor, hf_cip_cco_pdi_devtype, hf_cip_cco_pdi_prodcode,
7744       hf_cip_cco_pdi_compatibility, hf_cip_cco_pdi_comp_bit, hf_cip_cco_pdi_majorrev, hf_cip_cco_pdi_minorrev, FALSE);
7745 
7746    /* Add in proxy device id size */
7747    variable_data_size += 8;
7748 
7749    if ((offset+variable_data_size < item_length) &&
7750        ((ot_rtf == 5) || (to_rtf == 5)))
7751    {
7752       /* Safety parameters */
7753       proto_tree_add_item(cmd_tree, hf_cip_cco_safety, tvb, offset+variable_data_size, 55, ENC_NA);
7754       variable_data_size += 55;
7755    }
7756 
7757    if (offset+variable_data_size < item_length)
7758    {
7759       proto_tree_add_item(cmd_tree, hf_cip_cco_connection_disable, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
7760       variable_data_size++;
7761    }
7762 
7763    if (offset+variable_data_size < item_length)
7764    {
7765       proto_tree_add_item(cmd_tree, hf_cip_cco_net_conn_param_attr, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
7766       variable_data_size++;
7767    }
7768 
7769    if (offset+variable_data_size < item_length)
7770    {
7771       /* Large Net Connection Parameter */
7772       ncp_tree = proto_tree_add_subtree( cmd_tree, tvb, offset+variable_data_size, 18, ett_cco_ncp, NULL, "Large Net Connection Parameters");
7773 
7774       proto_tree_add_item(ncp_tree, hf_cip_cco_timeout_multiplier, tvb, offset+variable_data_size, 1, ENC_LITTLE_ENDIAN );
7775       dissect_transport_type_trigger(tvb, offset+variable_data_size+1, ncp_tree, hf_cip_cco_transport_type_trigger,
7776                                   hf_cip_cco_fwo_dir, hf_cip_cco_fwo_trigger, hf_cip_cco_fwo_class, ett_cco_ttt);
7777 
7778       proto_tree_add_item(ncp_tree, hf_cip_cco_ot_rpi, tvb, offset + variable_data_size + 2, 4, ENC_LITTLE_ENDIAN);
7779 
7780       /* Display O->T network connection parameters */
7781       dissect_net_param32(tvb, offset+variable_data_size+6, ncp_tree,
7782                  hf_cip_cco_ot_net_param32, hf_cip_cco_lfwo_own, hf_cip_cco_lfwo_typ,
7783                  hf_cip_cco_lfwo_prio, hf_cip_cco_lfwo_fixed_var, hf_cip_cco_lfwo_con_size, ett_cco_ncp, &ignore);
7784 
7785       proto_tree_add_item(ncp_tree, hf_cip_cco_to_rpi, tvb, offset + variable_data_size + 10, 4, ENC_LITTLE_ENDIAN);
7786 
7787       /* Display T->O network connection parameters */
7788       dissect_net_param32(tvb, offset+variable_data_size+14, ncp_tree,
7789                  hf_cip_cco_to_net_param32, hf_cip_cco_lfwo_own, hf_cip_cco_lfwo_typ,
7790                  hf_cip_cco_lfwo_prio, hf_cip_cco_lfwo_fixed_var, hf_cip_cco_lfwo_con_size, ett_cco_ncp, &ignore);
7791 
7792       variable_data_size += 18;
7793    }
7794 
7795    return variable_data_size;
7796 }
7797 
7798 static void
dissect_cip_cco_data(proto_tree * item_tree,proto_item * ti,tvbuff_t * tvb,int offset,int item_length,packet_info * pinfo)7799 dissect_cip_cco_data( proto_tree *item_tree, proto_item *ti, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
7800 {
7801    proto_item *rrsc_item;
7802    proto_tree *rrsc_tree, *cmd_data_tree, *con_st_tree;
7803    int req_path_size;
7804    guint8 service, gen_status, add_stat_size;
7805    cip_simple_request_info_t req_data;
7806 
7807    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP CCO");
7808 
7809    /* Add Service code & Request/Response tree */
7810    service = tvb_get_guint8( tvb, offset );
7811    rrsc_tree = proto_tree_add_subtree( item_tree, tvb, offset, 1, ett_cco_rrsc, &rrsc_item, "Service: " );
7812 
7813    /* Add Request/Response */
7814    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7815 
7816    proto_item_append_text( rrsc_item, "%s (%s)",
7817                val_to_str( ( service & CIP_SC_MASK ),
7818                   cip_sc_vals_cco , "Unknown Service (0x%02x)"),
7819                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7,
7820                   cip_sc_rr, "") );
7821 
7822    /* Add Service code */
7823    proto_tree_add_item(rrsc_tree, hf_cip_cco_sc, tvb, offset, 1, ENC_LITTLE_ENDIAN );
7824 
7825    load_cip_request_data(pinfo, &req_data);
7826 
7827    if(service & CIP_SC_RESPONSE_MASK )
7828    {
7829       /* Response message */
7830 
7831       /* Add additional status size */
7832       gen_status = tvb_get_guint8( tvb, offset+2 );
7833       add_stat_size = tvb_get_guint8( tvb, offset+3 ) * 2;
7834 
7835       /* If there is any command specific data create a sub-tree for it */
7836       if( ( item_length-4-add_stat_size ) != 0 )
7837       {
7838          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size,
7839                                                  ett_cco_cmd_data, NULL, "Command Specific Data" );
7840 
7841          if( gen_status == CI_GRC_SUCCESS )
7842          {
7843             /* Success responses */
7844             if (((service & CIP_SC_MASK) == SC_GET_ATT_ALL) &&
7845                 (req_data.iInstance != SEGMENT_VALUE_NOT_SET))
7846             {
7847                if (req_data.iInstance == 0)
7848                {
7849                   /* Get Attribute All (class) request */
7850                   dissect_cip_get_attribute_all_rsp(tvb, pinfo, cmd_data_tree, offset + 4 + add_stat_size, &req_data);
7851                }
7852                else
7853                {
7854                   /* Get Attribute All (instance) request */
7855 
7856                   /* Connection status */
7857                   con_st_tree = proto_tree_add_subtree( cmd_data_tree, tvb, offset+4+add_stat_size, 4, ett_cco_con_status, NULL, "Connection Status");
7858 
7859                   proto_tree_add_item(con_st_tree, hf_cip_genstat, tvb, offset+4+add_stat_size, 1, ENC_LITTLE_ENDIAN );
7860                   proto_tree_add_item(con_st_tree, hf_cip_pad8, tvb, offset+4+add_stat_size+1, 1, ENC_LITTLE_ENDIAN);
7861 
7862                   /* Extended Status */
7863                   proto_tree_add_item(con_st_tree, hf_cip_cco_ext_status, tvb, offset+4+add_stat_size+2, 2, ENC_LITTLE_ENDIAN);
7864 
7865                   dissect_cip_cco_all_attribute_common(cmd_data_tree, ti, tvb, offset+4+add_stat_size+4, item_length, pinfo);
7866                }
7867             }
7868             else
7869             {
7870                /* Add data */
7871                proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
7872             }
7873          }
7874          else
7875          {
7876             /* Error responses */
7877 
7878             /* Add data */
7879             proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, ENC_NA);
7880          } /* end of if-else( CI_CRC_SUCCESS ) */
7881 
7882       } /* End of if command-specific data present */
7883 
7884    } /* End of if reply */
7885    else
7886    {
7887       /* Request message */
7888       req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
7889 
7890       /* If there is any command specific data create a sub-tree for it */
7891       if( (item_length-req_path_size-2) != 0 )
7892       {
7893 
7894          cmd_data_tree = proto_tree_add_subtree( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2,
7895                                                  ett_cco_cmd_data, NULL, "Command Specific Data" );
7896 
7897          /* Check what service code that received */
7898 
7899          switch (service)
7900          {
7901          case SC_CCO_AUDIT_CHANGE:
7902             proto_tree_add_item(cmd_data_tree, hf_cip_cco_change_type, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN );
7903             break;
7904          case SC_CCO_CHANGE_COMPLETE:
7905             proto_tree_add_item(cmd_data_tree, hf_cip_cco_change_type, tvb, offset+2+req_path_size, 2, ENC_LITTLE_ENDIAN );
7906             break;
7907          case SC_SET_ATT_ALL:
7908             if ((req_data.iInstance == 0) ||
7909                 (req_data.iInstance == SEGMENT_VALUE_NOT_SET))
7910             {
7911                /* Just add raw data */
7912                proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
7913                break;
7914             }
7915 
7916             /* Set Attribute All (instance) request */
7917             dissect_cip_cco_all_attribute_common(cmd_data_tree, ti, tvb, offset+2+req_path_size, item_length, pinfo);
7918             break;
7919          default:
7920 
7921             /* Add data */
7922             proto_tree_add_item(cmd_data_tree, hf_cip_data, tvb, offset+2+req_path_size, item_length-req_path_size-2, ENC_NA);
7923          } /* End of check service code */
7924 
7925       } /* End of if command-specific data present */
7926 
7927    } /* End of if-else( request ) */
7928 
7929    add_cip_service_to_info_column(pinfo, service, cip_sc_vals_cco);
7930 } /* End of dissect_cip_cco_data() */
7931 
7932 static int
dissect_cip_class_cco(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)7933 dissect_cip_class_cco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
7934 {
7935    proto_item *ti;
7936    proto_tree *class_tree;
7937 
7938    /* Create display subtree for the protocol */
7939    ti = proto_tree_add_item(tree, proto_cip_class_cco, tvb, 0, -1, ENC_NA);
7940    class_tree = proto_item_add_subtree( ti, ett_cip_class_cco );
7941 
7942    dissect_cip_cco_data( class_tree, ti, tvb, 0, tvb_reported_length(tvb), pinfo );
7943 
7944    return tvb_reported_length(tvb);
7945 }
7946 
7947 static gboolean
dissect_class_cco_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)7948 dissect_class_cco_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
7949 {
7950    unsigned char service, service_code, ioilen, segment;
7951    cip_req_info_t* preq_info;
7952    guint32 classid = 0;
7953    int offset = 0;
7954 
7955    service = tvb_get_guint8( tvb, offset );
7956    service_code = service & CIP_SC_MASK;
7957 
7958    /* Handle GetAttributeAll and SetAttributeAll in CCO class */
7959    if ((service_code == SC_GET_ATT_ALL) ||
7960        (service_code == SC_SET_ATT_ALL))
7961    {
7962       if (service & CIP_SC_RESPONSE_MASK)
7963       {
7964          /* Service response */
7965          preq_info = (cip_req_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
7966          if ((preq_info != NULL) &&
7967              (preq_info->dissector == dissector_get_uint_handle( subdissector_class_table, CI_CLS_CCO)))
7968          {
7969             call_dissector(preq_info->dissector, tvb, pinfo, tree);
7970             return TRUE;
7971          }
7972       }
7973       else
7974       {
7975          /* Service request */
7976          ioilen = tvb_get_guint8( tvb, offset + 1 );
7977          if (ioilen > 1)
7978          {
7979             segment = tvb_get_guint8( tvb, offset + 2 );
7980             if (((segment & CI_SEGMENT_TYPE_MASK) == CI_LOGICAL_SEGMENT) &&
7981                 ((segment & CI_LOGICAL_SEG_TYPE_MASK) == CI_LOGICAL_SEG_CLASS_ID))
7982             {
7983                /* Logical Class ID, do a format check */
7984                switch ( segment & CI_LOGICAL_SEG_FORMAT_MASK )
7985                {
7986                case CI_LOGICAL_SEG_8_BIT:
7987                   classid = tvb_get_guint8( tvb, offset + 3 );
7988                   break;
7989                case CI_LOGICAL_SEG_16_BIT:
7990                   if ( ioilen >= 2 )
7991                      classid = tvb_get_letohs( tvb, offset + 4 );
7992                   break;
7993                case CI_LOGICAL_SEG_32_BIT:
7994                   if ( ioilen >= 3 )
7995                      classid = tvb_get_letohl( tvb, offset + 4 );
7996                   break;
7997                }
7998             }
7999          }
8000 
8001          if (classid == CI_CLS_CCO)
8002          {
8003             call_dissector(cip_class_cco_handle, tvb, pinfo, tree );
8004             return TRUE;
8005          }
8006 
8007       }
8008    }
8009 
8010    return FALSE;
8011 }
8012 
8013 /************************************************
8014  *
8015  * Dissector for CIP Request/Response
8016  * - matches requests/responses
8017  * - calls class specific dissector
8018  *
8019  ************************************************/
8020 
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,gboolean is_msp_item)8021 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, gboolean is_msp_item )
8022 {
8023    proto_item *ti;
8024    proto_tree *cip_tree, *epath_tree;
8025    proto_item *pi, *rrsc_item, *status_item;
8026    proto_tree *rrsc_tree, *status_tree, *add_status_tree;
8027    int req_path_size;
8028    unsigned char i, gen_status;
8029    unsigned char service,ioilen,segment;
8030    void *p_save_proto_data;
8031    cip_simple_request_info_t path_info;
8032    dissector_handle_t dissector;
8033    gint service_index;
8034    heur_dtbl_entry_t *hdtbl_entry;
8035 
8036    p_save_proto_data = p_get_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8037    p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8038    p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, preq_info);
8039 
8040    /* Create display subtree for the protocol */
8041    ti = proto_tree_add_item(item_tree, proto_cip, tvb, 0, -1, ENC_NA);
8042    cip_tree = proto_item_add_subtree( ti, ett_cip );
8043 
8044    service = tvb_get_guint8( tvb, offset );
8045 
8046    /* Add Service code & Request/Response tree */
8047    rrsc_item = proto_tree_add_uint_format_value(cip_tree, hf_cip_service,
8048                                tvb, offset, 1, service, "%s (%s)",
8049                                val_to_str( ( service & CIP_SC_MASK ), cip_sc_vals , "Unknown Service (0x%02x)"),
8050                                val_to_str_const( ( service & CIP_SC_RESPONSE_MASK )>>7, cip_sc_rr, ""));
8051 
8052    rrsc_tree = proto_item_add_subtree( rrsc_item, ett_rrsc );
8053 
8054    proto_tree_add_item( rrsc_tree, hf_cip_reqrsp, tvb, offset, 1, ENC_LITTLE_ENDIAN);
8055    proto_tree_add_item(rrsc_tree, hf_cip_service_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
8056 
8057    if( service & CIP_SC_RESPONSE_MASK )
8058    {
8059       /* Response message */
8060       status_tree = proto_tree_add_subtree( cip_tree, tvb, offset+2, 1, ett_status_item, &status_item, "Status: " );
8061 
8062       /* Add general status */
8063       gen_status = tvb_get_guint8( tvb, offset+2 );
8064       proto_tree_add_item(status_tree, hf_cip_genstat, tvb, offset+2, 1, ENC_LITTLE_ENDIAN );
8065       proto_item_append_text( status_item, "%s: ", val_to_str_ext( gen_status,
8066                      &cip_gs_vals_ext , "Unknown Response (%x)")   );
8067 
8068       if (is_msp_item == FALSE)
8069       {
8070           /* Add reply status to info column */
8071           col_append_fstr(pinfo->cinfo, COL_INFO, "%s: ",
8072               val_to_str_ext(gen_status, &cip_gs_vals_ext, "Unknown Response (%x)"));
8073       }
8074       else
8075       {
8076           proto_item_append_text(msp_item, "%s: ",
8077               val_to_str_ext(gen_status, &cip_gs_vals_ext, "Unknown Response (%x)"));
8078       }
8079 
8080       /* Add additional status size */
8081       guint8 add_stat_size = tvb_get_guint8( tvb, offset+3 );
8082       proto_tree_add_item(status_tree, hf_cip_addstat_size, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
8083 
8084       if( add_stat_size )
8085       {
8086          /* Add additional status */
8087          add_status_tree = proto_tree_add_subtree( status_tree, tvb, offset+4, add_stat_size*2, ett_add_status_item, NULL, "Additional Status" );
8088 
8089          for( i=0; i < add_stat_size; i ++ )
8090             proto_tree_add_item(add_status_tree, hf_cip_add_stat, tvb, offset+4+(i*2), 2, ENC_LITTLE_ENDIAN );
8091       }
8092 
8093       proto_item_set_len( status_item, 2 + add_stat_size*2);
8094 
8095       /* The previous packet service must be Unconnected Send, or match the current
8096          service to be a valid match. If they don't, ignore the previous data.*/
8097       if(  preq_info
8098         && !(  preq_info->bService == ( service & CIP_SC_MASK )
8099             || ( preq_info->bService == SC_CM_UNCON_SEND && preq_info->dissector == cip_class_cm_handle )
8100             )
8101         )
8102          preq_info = NULL;
8103 
8104       display_previous_request_path(preq_info, cip_tree, tvb, pinfo, msp_item, is_msp_item);
8105 
8106       /* Check to see if service is 'generic' */
8107       try_val_to_str_idx((service & CIP_SC_MASK), cip_sc_vals, &service_index);
8108 
8109       /* If the request set a dissector, then check that first. This ensures
8110          that Unconnected Send responses are properly parsed based on the
8111          embedded request. */
8112       if (preq_info && preq_info->dissector)
8113       {
8114          call_dissector(preq_info->dissector, tvb, pinfo, item_tree);
8115       }
8116       else if (service_index >= 0)
8117       {
8118          /* See if object dissector wants to override generic service handling */
8119          if(!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
8120          {
8121            dissect_cip_generic_service_rsp(tvb, pinfo, cip_tree);
8122          }
8123       }
8124       else
8125       {
8126          call_dissector( cip_class_generic_handle, tvb, pinfo, item_tree );
8127       }
8128    } /* End of if reply */
8129    else
8130    {
8131       /* Request message */
8132 
8133       /* Add path size to tree */
8134       req_path_size = tvb_get_guint8( tvb, offset+1);
8135       proto_tree_add_item(cip_tree, hf_cip_request_path_size, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
8136 
8137       /* Add the epath */
8138       epath_tree = proto_tree_add_subtree(cip_tree, tvb, offset+2, req_path_size*2, ett_path, &pi, "Request Path: ");
8139       if (preq_info)
8140       {
8141          preq_info->ciaData = wmem_new(wmem_file_scope(), cip_simple_request_info_t);
8142          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);
8143          memcpy(&path_info, preq_info->ciaData, sizeof(cip_simple_request_info_t));
8144       }
8145       else
8146       {
8147          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);
8148       }
8149 
8150       ioilen = tvb_get_guint8( tvb, offset + 1 );
8151 
8152       if ( preq_info )
8153          preq_info->dissector = NULL;
8154       dissector = NULL;
8155 
8156       /* The class ID should already be extracted if it's available */
8157       if (path_info.iClass != 0xFFFFFFFF)
8158       {
8159          dissector = dissector_get_uint_handle( subdissector_class_table, path_info.iClass);
8160       }
8161       else
8162       {
8163          if ( ioilen >= 1 )
8164          {
8165             segment = tvb_get_guint8( tvb, offset + 2 );
8166             if ((segment & CI_SEGMENT_TYPE_MASK) == CI_DATA_SEGMENT)
8167             {
8168                dissector = dissector_get_uint_handle( subdissector_symbol_table, segment );
8169             }
8170          }
8171       }
8172 
8173       if ( preq_info )
8174       {
8175          preq_info->dissector = dissector;
8176 
8177          /* copy IOI for access by response packet */
8178          preq_info->pIOI = wmem_alloc(wmem_file_scope(), ioilen*2);
8179          preq_info->IOILen = ioilen;
8180          tvb_memcpy(tvb, preq_info->pIOI, offset+2, ioilen*2);
8181 
8182          preq_info->bService = service;
8183       }
8184 
8185       /* Check to see if service is 'generic' */
8186       try_val_to_str_idx(service, cip_sc_vals, &service_index);
8187       if (service_index >= 0)
8188       {
8189           /* See if object dissector wants to override generic service handling */
8190           if(!dissector_try_heuristic(heur_subdissector_service, tvb, pinfo, item_tree, &hdtbl_entry, NULL))
8191           {
8192              /* No need to set a custom dissector if this is just a generic service. */
8193              if (preq_info)
8194              {
8195                 preq_info->dissector = NULL;
8196              }
8197 
8198              dissect_cip_generic_service_req(tvb, pinfo, cip_tree, &path_info);
8199           }
8200       }
8201       else if ( dissector )
8202       {
8203          call_dissector( dissector, tvb, pinfo, item_tree );
8204       }
8205       else
8206       {
8207          call_dissector( cip_class_generic_handle, tvb, pinfo, item_tree );
8208       }
8209    } /* End of if-else( request ) */
8210 
8211    p_remove_proto_data(wmem_file_scope(), pinfo, proto_cip, 0);
8212    p_add_proto_data(wmem_file_scope(), pinfo, proto_cip, 0, p_save_proto_data);
8213 
8214 } /* End of dissect_cip_data() */
8215 
dissect_cip_run_idle(tvbuff_t * tvb,int offset,proto_tree * item_tree)8216 void dissect_cip_run_idle(tvbuff_t* tvb, int offset, proto_tree* item_tree)
8217 {
8218    static int * const run_idle_header[] = {
8219       &hf_32bitheader_roo,
8220       &hf_32bitheader_coo,
8221       &hf_32bitheader_run_idle,
8222       NULL
8223    };
8224 
8225    proto_tree_add_bitmask(item_tree, tvb, offset, hf_32bitheader, ett_32bitheader_tree, run_idle_header, ENC_LITTLE_ENDIAN);
8226 }
8227 
8228 static int
dissect_cip(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)8229 dissect_cip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
8230 {
8231    enip_request_info_t *enip_info;
8232    cip_req_info_t *preq_info;
8233 
8234    /* Make entries in Protocol column and Info column on summary display */
8235    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP");
8236 
8237    col_clear(pinfo->cinfo, COL_INFO);
8238    col_append_sep_str(pinfo->cinfo, COL_INFO, " | ", "");
8239 
8240    /* Each CIP request received by ENIP gets a unique ID */
8241    enip_info = (enip_request_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_enip, ENIP_REQUEST_INFO);
8242 
8243    if ( enip_info )
8244    {
8245       preq_info = enip_info->cip_info;
8246       if ( preq_info == NULL )
8247       {
8248          preq_info = wmem_new0(wmem_file_scope(), cip_req_info_t);
8249          enip_info->cip_info = preq_info;
8250       }
8251       dissect_cip_data( tree, tvb, 0, pinfo, enip_info->cip_info, NULL, FALSE );
8252    }
8253    else
8254    {
8255       dissect_cip_data( tree, tvb, 0, pinfo, NULL, NULL, FALSE );
8256    }
8257 
8258    return tvb_reported_length(tvb);
8259 }
8260 
8261 static int
dissect_cip_implicit(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)8262 dissect_cip_implicit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
8263 {
8264    proto_item *ti;
8265    proto_tree *cip_tree;
8266 
8267    guint32 ClassID = GPOINTER_TO_UINT(data);
8268    int length = tvb_reported_length_remaining(tvb, 0);
8269 
8270    /* Make entries in Protocol column and Info column on summary display */
8271    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CIP");
8272    col_clear(pinfo->cinfo, COL_INFO);
8273 
8274    /* Create display subtree for the protocol */
8275    ti = proto_tree_add_item(tree, proto_cip, tvb, 0, length, ENC_NA);
8276    cip_tree = proto_item_add_subtree(ti, ett_cip);
8277 
8278    proto_tree_add_item(cip_tree, hf_cip_data, tvb, 0, length, ENC_NA);
8279 
8280    col_append_fstr(pinfo->cinfo, COL_INFO, "Implicit Data - %s",
8281         val_to_str(ClassID, cip_class_names_vals, "Class (0x%02x)"));
8282 
8283    return tvb_reported_length(tvb);
8284 }
8285 
8286 /*
8287  * Protocol initialization
8288  */
8289 
8290 void
proto_register_cip(void)8291 proto_register_cip(void)
8292 {
8293    /* Setup list of header fields */
8294    static hf_register_info hf[] = {
8295       { &hf_attr_class_revision, { "Revision", "cip.class_revision", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8296       { &hf_attr_class_max_instance, { "Max Instance", "cip.max_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8297       { &hf_attr_class_num_instance, { "Number of Instances", "cip.num_instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8298       { &hf_attr_class_opt_attr_num, { "Number of Attributes", "cip.num_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8299       { &hf_attr_class_attr_num, { "Attribute Number", "cip.attr_num", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8300       { &hf_attr_class_opt_service_num, { "Number of Services", "cip.num_service", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8301       { &hf_attr_class_service_code, { "Service Code", "cip.service_code", FT_UINT16, BASE_HEX, VALS(cip_sc_vals), 0, NULL, HFILL } },
8302       { &hf_attr_class_num_class_attr, { "Maximum ID Number Class Attributes", "cip.num_class_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8303       { &hf_attr_class_num_inst_attr, { "Maximum ID Number Instance Attributes", "cip.num_inst_attr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8304 
8305       { &hf_cip_service, { "Service", "cip.service", FT_UINT8, BASE_HEX, NULL, 0, "Service Code + Request/Response", HFILL }},
8306       { &hf_cip_reqrsp, { "Request/Response", "cip.rr", FT_UINT8, BASE_HEX, VALS(cip_sc_rr), CIP_SC_RESPONSE_MASK, "Request or Response message", HFILL }},
8307       { &hf_cip_service_code, { "Service", "cip.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals), CIP_SC_MASK, "Service Code", HFILL }},
8308       { &hf_cip_epath, { "EPath", "cip.epath", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8309       { &hf_cip_genstat, { "General Status", "cip.genstat", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
8310       { &hf_cip_addstat_size, { "Additional Status Size", "cip.addstat_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8311       { &hf_cip_add_stat, { "Additional Status", "cip.addstat", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8312       { &hf_cip_request_path_size, { "Request Path Size", "cip.request_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8313 
8314       { &hf_cip_path_segment, { "Path Segment", "cip.path_segment", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8315       { &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 }},
8316       { &hf_cip_port_ex_link_addr, { "Extended Link Address", "cip.ex_linkaddress", FT_BOOLEAN, 8, TFS(&tfs_true_false), CI_PORT_SEG_EX_LINK_ADDRESS, NULL, HFILL }},
8317       { &hf_cip_port, { "Port", "cip.port", FT_UINT8, BASE_DEC, VALS(cip_port_number_vals), CI_PORT_SEG_PORT_ID_MASK, "Port Identifier", HFILL } },
8318       { &hf_cip_port_extended,{ "Port Extended", "cip.port", FT_UINT16, BASE_HEX, NULL, 0, "Port Identifier Extended", HFILL } },
8319       { &hf_cip_link_address_byte, { "Link Address", "cip.linkaddress.byte", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8320       { &hf_cip_link_address_size, { "Link Address Size", "cip.linkaddress_size", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8321       { &hf_cip_link_address_string, { "Link Address", "cip.linkaddress.string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8322       { &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 }},
8323       { &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 }},
8324       { &hf_cip_class8, { "Class", "cip.class", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
8325       { &hf_cip_class16, { "Class", "cip.class", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
8326       { &hf_cip_class32, { "Class", "cip.class", FT_UINT32, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
8327       { &hf_cip_instance8, { "Instance", "cip.instance", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8328       { &hf_cip_instance16, { "Instance", "cip.instance", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8329       { &hf_cip_instance32, { "Instance", "cip.instance", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8330       { &hf_cip_member8, { "Member", "cip.member", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8331       { &hf_cip_member16, { "Member", "cip.member", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8332       { &hf_cip_member32, { "Member", "cip.member", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8333       { &hf_cip_attribute8, { "Attribute", "cip.attribute", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8334       { &hf_cip_attribute16, { "Attribute", "cip.attribute", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8335       { &hf_cip_attribute32, { "Attribute", "cip.attribute", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8336       { &hf_cip_conpoint8, { "Connection Point", "cip.connpoint", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8337       { &hf_cip_conpoint16, { "Connection Point", "cip.connpoint", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8338       { &hf_cip_conpoint32, { "Connection Point", "cip.connpoint", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8339       { &hf_cip_serviceid8,{ "Service ID", "cip.serviceid", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
8340       { &hf_cip_ekey_format, { "Key Format", "cip.ekey.format", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8341       { &hf_cip_ekey_vendor, { "Vendor ID", "cip.ekey.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
8342       { &hf_cip_ekey_devtype, { "Device Type", "cip.ekey.devtype", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
8343       { &hf_cip_ekey_prodcode, { "Product Code", "cip.ekey.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8344       { &hf_cip_ekey_compatibility, { "Compatibility", "cip.ekey.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8345       { &hf_cip_ekey_comp_bit, { "Compatibility", "cip.ekey.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, "EKey: Compatibility bit", HFILL }},
8346       { &hf_cip_ekey_majorrev, { "Major Revision", "cip.ekey.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, "EKey: Major Revision", HFILL }},
8347       { &hf_cip_ekey_minorrev, { "Minor Revision", "cip.ekey.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8348       { &hf_cip_ekey_serial_number, { "Serial Number", "cip.ekey.serial_number", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8349       { &hf_cip_ext_logical8,{ "Extended Logical", "cip.extlogical", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
8350       { &hf_cip_ext_logical16,{ "Extended Logical", "cip.extlogical", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
8351       { &hf_cip_ext_logical32,{ "Extended Logical", "cip.extlogical", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
8352       { &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 } },
8353       { &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 }},
8354       { &hf_cip_data_seg_size_simple, { "Data Size", "cip.data_segment.size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8355       { &hf_cip_data_seg_size_extended, { "Data Size", "cip.data_segment.size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0, NULL, HFILL } },
8356       { &hf_cip_data_seg_item, { "Data", "cip.data_segment.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8357       { &hf_cip_symbol, { "ANSI Symbol", "cip.symbol", FT_STRING, BASE_NONE, NULL, 0, "ANSI Extended Symbol Segment", HFILL }},
8358       { &hf_cip_symbol_size, { "Symbolic Symbol Size", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
8359       { &hf_cip_symbol_ascii, { "ASCII Symbol", "cip.ascii_symbol", FT_STRING, BASE_NONE, NULL, 0, "ASCII Symbol Segment", HFILL } },
8360       { &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 } },
8361       { &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 } },
8362       { &hf_cip_symbol_double_size, { "Double Byte Chars", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
8363       { &hf_cip_symbol_triple_size, { "Triple Byte Chars", "cip.symbol.size", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } },
8364       { &hf_cip_numeric_usint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
8365       { &hf_cip_numeric_uint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
8366       { &hf_cip_numeric_udint,{ "Numeric Symbol", "cip.numeric_symbol", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
8367       { &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 }},
8368       { &hf_cip_seg_schedule, { "Multiplier/Phase", "cip.network_segment.schedule", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8369       { &hf_cip_seg_fixed_tag, { "Fixed Tag", "cip.network_segment.fixed_tag", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8370       { &hf_cip_seg_prod_inhibit_time, { "Production Inhibit Time (ms)", "cip.network_segment.prod_inhibit", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8371       { &hf_cip_seg_prod_inhibit_time_us, { "Production Inhibit Time (us)", "cip.network_segment.prod_inhibit", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
8372       { &hf_cip_seg_network_size, { "Network Segment Length", "cip.network_segment.length", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8373       { &hf_cip_seg_network_subtype, { "Extended Segment Subtype", "cip.network_segment.subtype", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
8374       { &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 }},
8375       { &hf_cip_seg_safety_reserved, { "Reserved", "cip.safety_segment.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8376       { &hf_cip_seg_safety_configuration_crc, { "Configuration CRC (SCCRC)", "cip.safety_segment.configuration_crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8377       { &hf_cip_seg_safety_configuration_timestamp, { "Configuration Timestamp (SCTS)", "cip.safety_segment.configuration_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }},
8378       { &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 }},
8379       { &hf_cip_seg_safety_configuration_time, { "Configuration (Manual) Time", "cip.safety_segment.configuration_time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8380       { &hf_cip_seg_safety_time_correction_epi, { "Time Correction EPI", "cip.safety_segment.time_correction_eri", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8381       { &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 }},
8382       { &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 }},
8383       { &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 }},
8384       { &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 }},
8385       { &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 }},
8386       { &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 }},
8387       { &hf_cip_seg_safety_tunid, { "Target UNID", "cip.safety_segment.tunid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8388       { &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 }},
8389       { &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 }},
8390       { &hf_cip_seg_safety_tunid_snn_time, { "SNN (Manual) Time", "cip.safety_segment.tunid.snn.time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8391       { &hf_cip_seg_safety_tunid_nodeid, { "Node ID", "cip.safety_segment.tunid.nodeid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8392       { &hf_cip_seg_safety_ounid, { "Originator UNID", "cip.safety_segment.ounid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8393       { &hf_cip_seg_safety_ounid_snn_timestamp, { "SNN Timestamp", "cip.safety_segment.tunid.snn.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0, NULL, HFILL }},
8394       { &hf_cip_seg_safety_ounid_snn_date, { "SNN (Manual) Date", "cip.safety_segment.tunid.snn.date", FT_UINT16, BASE_HEX, VALS(cipsafety_snn_date_vals), 0, NULL, HFILL }},
8395       { &hf_cip_seg_safety_ounid_snn_time, { "SNN (Manual) Time", "cip.safety_segment.tunid.snn.time", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8396       { &hf_cip_seg_safety_ounid_nodeid, { "Node ID", "cip.safety_segment.ounid.nodeid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8397       { &hf_cip_seg_safety_ping_eri_multiplier, { "Ping Interval EPI Multiplier", "cip.safety_segment.ping_eri_multiplier", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8398       { &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_DEC, NULL, 0, NULL, HFILL }},
8399       { &hf_cip_seg_safety_network_time_expected_multiplier, { "Network Time Expectation Multiplier", "cip.safety_segment.network_time_expected_multiplier", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_safety_128us, 0, NULL, HFILL }},
8400       { &hf_cip_seg_safety_timeout_multiplier, { "Timeout Multiplier", "cip.safety_segment.timeout_multiplier", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8401       { &hf_cip_seg_safety_max_consumer_number, { "Max Consumer Number", "cip.safety_segment.max_consumer_number", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8402       { &hf_cip_seg_safety_conn_param_crc, { "Connection Param CRC (CPCRC)", "cip.safety_segment.conn_param_crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8403       { &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 }},
8404       { &hf_cip_seg_safety_max_fault_number, { "Max Fault Number", "cip.safety_segment.max_fault_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8405       { &hf_cip_seg_safety_init_timestamp, { "Initial Timestamp", "cip.safety_segment.init_timestamp", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8406       { &hf_cip_seg_safety_init_rollover, { "Initial Rollover Value", "cip.safety_segment.init_rollover", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8407       { &hf_cip_seg_safety_data, { "Safety Data", "cip.safety_segment.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8408       { &hf_cip_class_max_inst32, { "Max Instance", "cip.class.max_inst", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8409       { &hf_cip_class_num_inst32, { "Number of Instances", "cip.class.num_inst", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8410       { &hf_cip_reserved8, { "Reserved", "cip.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8411       { &hf_cip_reserved24, { "Reserved", "cip.reserved", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL }},
8412       { &hf_cip_pad8, { "Pad Byte", "cip.pad", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8413 
8414       { &hf_cip_sc_get_attr_list_attr_count, { "Attribute Count", "cip.getlist.attr_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8415       { &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 }},
8416       { &hf_cip_sc_set_attr_list_attr_count, { "Attribute Count", "cip.setlist.attr_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8417       { &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 }},
8418       { &hf_cip_sc_reset_param, { "Reset type", "cip.reset.type", FT_UINT8, BASE_DEC, VALS(cip_reset_type_vals), 0, NULL, HFILL }},
8419       { &hf_cip_sc_create_instance, { "Instance", "cip.create.instance", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8420       { &hf_cip_sc_mult_serv_pack_num_services, { "Number of Services", "cip.msp.num_services", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8421       { &hf_cip_sc_mult_serv_pack_offset, { "Offset", "cip.msp.offset", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8422       { &hf_cip_find_next_object_max_instance, { "Maximum ID", "cip.find_next_object.max_instance", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8423       { &hf_cip_find_next_object_num_instances, { "Number of Instances", "cip.find_next_object.num_instances", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8424       { &hf_cip_find_next_object_instance_item, { "Instance", "cip.find_next_object.instance", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8425       { &hf_cip_sc_group_sync_is_sync, { "IsSynchronized", "cip.group_sync.is_sync", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8426       { &hf_cip_data, { "Data", "cip.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8427 
8428       { &hf_id_vendor_id, { "Vendor ID", "cip.id.vendor_id", FT_UINT16, BASE_HEX | BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL } },
8429       { &hf_id_device_type, { "Device Type", "cip.id.device_type", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_devtype_vals_ext, 0, NULL, HFILL }},
8430       { &hf_id_product_code, { "Product Code", "cip.id.product_code", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8431       { &hf_id_major_rev, { "Major Revision", "cip.id.major_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8432       { &hf_id_minor_rev, { "Minor Revision", "cip.id.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8433       { &hf_id_status, { "Status", "cip.id.status", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8434       { &hf_id_serial_number, { "Serial Number", "cip.id.serial_number", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8435       { &hf_id_product_name, { "Product Name", "cip.id.product_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8436       { &hf_id_state, { "State", "cip.id.state", FT_UINT8, BASE_HEX, VALS(cip_id_state_vals), 0, NULL, HFILL } },
8437       { &hf_id_config_value, { "Configuration Consistency Value", "cip.id.config_value", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
8438       { &hf_id_heartbeat, { "Heartbeat Interval", "cip.id.heartbeat", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
8439       { &hf_id_status_owned, { "Owned", "cip.id.owned", FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL } },
8440       { &hf_id_status_conf, { "Configured", "cip.id.conf", FT_UINT16, BASE_DEC, NULL, 0x0004, NULL, HFILL } },
8441       { &hf_id_status_extended1, { "Extended Device Status", "cip.id.ext", FT_UINT16, BASE_HEX, NULL, 0x00F0, NULL, HFILL } },
8442       { &hf_id_status_minor_fault_rec, { "Minor Recoverable Fault", "cip.id.minor_fault1", FT_UINT16, BASE_DEC, NULL, 0x0100, NULL, HFILL } },
8443       { &hf_id_status_minor_fault_unrec, { "Minor Unrecoverable Fault", "cip.id.minor_fault2", FT_UINT16, BASE_DEC, NULL, 0x0200, NULL, HFILL } },
8444       { &hf_id_status_major_fault_rec, { "Major Recoverable Fault", "cip.id.major_fault1", FT_UINT16, BASE_DEC, NULL, 0x0400, NULL, HFILL } },
8445       { &hf_id_status_major_fault_unrec, { "Major Unrecoverable Fault", "cip.id.major_fault2", FT_UINT16, BASE_DEC, NULL, 0x0800, NULL, HFILL } },
8446       { &hf_id_status_extended2, { "Extended Device Status 2", "cip.id.ext2", FT_UINT16, BASE_HEX, NULL, 0xF000, NULL, HFILL } },
8447 
8448       { &hf_msg_rout_num_classes, { "Number of Classes", "cip.mr.num_classes", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8449       { &hf_msg_rout_classes, { "Class", "cip.mr.class", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_class_names_vals_ext, 0, NULL, HFILL }},
8450       { &hf_msg_rout_num_available, { "Number Available", "cip.mr.num_available", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8451       { &hf_msg_rout_num_active, { "Number Active", "cip.mr.num_active", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8452       { &hf_msg_rout_active_connections, { "Active Connection", "cip.mr.active_connections", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8453 
8454       { &hf_conn_mgr_open_requests, { "Open Requests", "cip.cm.open_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8455       { &hf_conn_mgr_open_format_rejects, { "Open Format Rejects", "cip.cm.open_format_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8456       { &hf_conn_mgr_open_resource_rejects, { "Open Resource Rejects", "cip.cm.open_resource_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8457       { &hf_conn_mgr_other_open_rejects, { "Other Open Rejects", "cip.cm.other_open_rejects", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8458       { &hf_conn_mgr_close_requests, { "Close Requests", "cip.cm.close_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8459       { &hf_conn_close_format_requests, { "Close Format Requests", "cip.cm.close_format_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8460       { &hf_conn_mgr_close_other_requests, { "Close Other Requests", "cip.cm.close_other_requests", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8461       { &hf_conn_mgr_conn_timouts, { "Connection Timeouts", "cip.cm.conn_timouts", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8462       { &hf_conn_mgr_num_conn_entries, { "Number of Connection Entries (Bits)", "cip.cm.conn_entries", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8463       { &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 }},
8464       { &hf_conn_mgr_conn_open_bits, { "Connection Open Bits", "cip.cm.conn_open_bits", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8465       { &hf_conn_mgr_cpu_utilization, { "CPU Utilization", "cip.cm.cpu_util", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8466       { &hf_conn_mgr_max_buff_size, { "Max Buff Size", "cip.cm.max_buff_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
8467       { &hf_conn_mgr_buff_size_remaining, { "Buff Size Remaining", "cip.cm.buff_remain", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
8468 
8469       { &hf_stringi_number_char, { "Number of Characters", "cip.stringi.num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
8470       { &hf_stringi_language_char, { "Language Chars", "cip.stringi.language_char", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
8471       { &hf_stringi_char_string_struct, { "Char String Struct", "cip.stringi.char_string_struct", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
8472       { &hf_stringi_char_set, { "Char Set", "cip.stringi.char_set", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8473       { &hf_stringi_international_string, { "International String", "cip.stringi.int_string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
8474 
8475       { &hf_file_filename, { "File Name", "cip.file.file_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
8476 
8477       { &hf_time_sync_ptp_enable, { "PTP Enable", "cip.time_sync.ptp_enable", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }},
8478       { &hf_time_sync_is_synchronized, { "Is Synchronized", "cip.time_sync.is_synchronized", FT_BOOLEAN, 8, TFS(&tfs_true_false), 0, NULL, HFILL }},
8479       { &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 }},
8480       { &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 }},
8481       { &hf_time_sync_offset_from_master, { "Offset from Master", "cip.time_sync.offset_from_master", FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL }},
8482       { &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 }},
8483       { &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 }},
8484       { &hf_time_sync_gm_clock_clock_id, { "Clock Identity", "cip.time_sync.gm_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8485       { &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 }},
8486       { &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 }},
8487       { &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 }},
8488       { &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 }},
8489       { &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 }},
8490       { &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), 0x01, NULL, HFILL }},
8491       { &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), 0x02, NULL, HFILL }},
8492       { &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), 0x04, NULL, HFILL }},
8493       { &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), 0x08, NULL, HFILL }},
8494       { &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), 0x10, NULL, HFILL }},
8495       { &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), 0x20, NULL, HFILL }},
8496       { &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 }},
8497       { &hf_time_sync_gm_clock_priority1, { "Priority1", "cip.time_sync.gm_clock.priority1", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8498       { &hf_time_sync_gm_clock_priority2, { "Priority2", "cip.time_sync.gm_clock.priority2", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8499       { &hf_time_sync_parent_clock_clock_id, { "Clock Identity", "cip.time_sync.parent_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8500       { &hf_time_sync_parent_clock_port_number, { "Port Number", "cip.time_sync.parent_clock.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8501       { &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 }},
8502       { &hf_time_sync_parent_clock_observed_phase_change_rate, { "Observed Phase Change Rate", "cip.time_sync.parent_clock.observed_phase_change_rate", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8503       { &hf_time_sync_local_clock_clock_id, { "Clock Identity", "cip.time_sync.local_clock.clock_id", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8504       { &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 }},
8505       { &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 }},
8506       { &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 }},
8507       { &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 }},
8508       { &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 }},
8509       { &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), 0x01, NULL, HFILL }},
8510       { &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), 0x02, NULL, HFILL }},
8511       { &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), 0x04, NULL, HFILL }},
8512       { &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), 0x08, NULL, HFILL }},
8513       { &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), 0x10, NULL, HFILL }},
8514       { &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), 0x20, NULL, HFILL }},
8515       { &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 }},
8516       { &hf_time_sync_num_ports, { "Port Number", "cip.time_sync.port_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8517       { &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 }},
8518       { &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 }},
8519       { &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 }},
8520       { &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 }},
8521       { &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 }},
8522       { &hf_time_sync_port_enable_cfg_port_enable, { "Port Enable", "cip.time_sync.port_enable_cfg.port_enable", FT_BOOLEAN, 16, TFS(&tfs_enabled_disabled), 0, NULL, HFILL }},
8523       { &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 }},
8524       { &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 }},
8525       { &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 }},
8526       { &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 }},
8527       { &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 }},
8528       { &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 }},
8529       { &hf_time_sync_priority1, { "Priority1", "cip.time_sync.priority1", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8530       { &hf_time_sync_priority2, { "Priority2", "cip.time_sync.priority2", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8531       { &hf_time_sync_domain_number, { "Domain number", "cip.time_sync.domain_number", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8532       { &hf_time_sync_clock_type, { "Clock Type", "cip.time_sync.clock_type", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8533       { &hf_time_sync_clock_type_ordinary, { "Ordinary Clock", "cip.time_sync.clock_type.ordinary", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0080, NULL, HFILL }},
8534       { &hf_time_sync_clock_type_boundary, { "Boundary Clock", "cip.time_sync.clock_type.boundary", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0040, NULL, HFILL }},
8535       { &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 }},
8536       { &hf_time_sync_clock_type_management, { "Management Node", "cip.time_sync.clock_type.management", FT_BOOLEAN, 16, TFS(&tfs_set_notset), 0x0008, NULL, HFILL }},
8537       { &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 }},
8538       { &hf_time_sync_manufacture_id_oui, { "Manufacture Identity OUI", "cip.time_sync.manufacture_id.oui", FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL }},
8539       { &hf_time_sync_manufacture_id_reserved, { "Reserved", "cip.time_sync.manufacture_id.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8540       { &hf_time_sync_prod_desc_size, { "Product Description Size", "cip.time_sync.prod_desc_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8541       { &hf_time_sync_prod_desc_str, { "Product Description", "cip.time_sync.prod_desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8542       { &hf_time_sync_revision_data_size, { "Revision Data Size", "cip.time_sync.revision_data_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8543       { &hf_time_sync_revision_data_str, { "Revision Data", "cip.time_sync.revision_data", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8544       { &hf_time_sync_user_desc_size, { "User Description Size", "cip.time_sync.user_desc_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
8545       { &hf_time_sync_user_desc_str, { "User Description", "cip.time_sync.user_desc", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8546       { &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 }},
8547       { &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 }},
8548       { &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 }},
8549       { &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 }},
8550       { &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 }},
8551       { &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 }},
8552       { &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 }},
8553       { &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 }},
8554       { &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 }},
8555       { &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 }},
8556       { &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 }},
8557       { &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 }},
8558       { &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 }},
8559       { &hf_time_sync_steps_removed, { "Steps Removed", "cip.time_sync.steps_removed", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8560       { &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 }},
8561       { &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 }},
8562       { &hf_port_entry_port, { "Entry Port", "cip.port.entry_port", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8563       { &hf_port_type, { "Port Type", "cip.port.type", FT_UINT16, BASE_DEC | BASE_RANGE_STRING, RVALS(cip_port_type_vals), 0, NULL, HFILL } },
8564       { &hf_port_number, { "Port Number", "cip.port.number", FT_UINT16, BASE_DEC, VALS(cip_port_number_vals), 0, NULL, HFILL } },
8565       { &hf_port_min_node_num, { "Minimum Node Number", "cip.port.min_node", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8566       { &hf_port_max_node_num, { "Maximum Node Number", "cip.port.max_node", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
8567       { &hf_port_name, { "Port Name", "cip.port.name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
8568       { &hf_port_num_comm_object_entries, { "Number of entries", "cip.port.num_comm_object_entries", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
8569       { &hf_path_len_usint, { "Path Length", "cip.path_len", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL } },
8570       { &hf_path_len_uint, { "Path Length", "cip.path_len", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL } },
8571 
8572       { &hf_32bitheader, { "32-bit Header", "cip.32bitheader", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } },
8573       { &hf_32bitheader_roo, { "ROO", "cip.32bitheader.roo", FT_UINT32, BASE_HEX, NULL, 0xC, "Ready for Ownership of Outputs", HFILL } },
8574       { &hf_32bitheader_coo, { "COO", "cip.32bitheader.coo", FT_UINT32, BASE_HEX, NULL, 0x2, "Claim Output Ownership", HFILL } },
8575       { &hf_32bitheader_run_idle, { "Run/Idle", "cip.32bitheader.run_idle", FT_UINT32, BASE_HEX, VALS(cip_run_idle_vals), 0x1, NULL, HFILL } },
8576 
8577       { &hf_cip_connection, { "CIP Connection Index", "cip.connection", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
8578    };
8579 
8580    static hf_register_info hf_cm[] = {
8581       { &hf_cip_cm_sc, { "Service", "cip.cm.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_cm), CIP_SC_MASK, NULL, HFILL }},
8582       { &hf_cip_cm_genstat, { "General Status", "cip.cm.genstat", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &cip_gs_vals_ext, 0, NULL, HFILL }},
8583       { &hf_cip_cm_addstat_size, { "Additional Status Size", "cip.cm.addstat_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8584       { &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 }},
8585       { &hf_cip_cm_add_status, { "Additional Status", "cip.cm.addstat", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8586       { &hf_cip_cm_priority, { "Priority", "cip.cm.priority", FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL }},
8587       { &hf_cip_cm_tick_time, { "Tick time", "cip.cm.tick_time", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
8588       { &hf_cip_cm_timeout_tick, { "Time-out ticks", "cip.cm.timeout_tick", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8589       { &hf_cip_cm_timeout, { "Actual Time Out", "cip.cm.timeout", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0, NULL, HFILL }},
8590       { &hf_cip_cm_ot_connid, { "O->T Network Connection ID", "cip.cm.ot_connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8591       { &hf_cip_cm_to_connid, { "T->O Network Connection ID", "cip.cm.to_connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8592       { &hf_cip_connid, { "Connection ID", "cip.connid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8593       { &hf_cip_cm_conn_serial_num, { "Connection Serial Number", "cip.cm.conn_serial_num", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8594       { &hf_cip_cm_vendor, { "Originator Vendor ID", "cip.cm.vendor", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &cip_vendor_vals_ext, 0, NULL, HFILL }},
8595       { &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 }},
8596       { &hf_cip_cm_ot_rpi, { "O->T RPI", "cip.cm.otrpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8597       { &hf_cip_cm_ot_net_params32, { "O->T Network Connection Parameters", "cip.cm.ot_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8598       { &hf_cip_cm_ot_net_params16, { "O->T Network Connection Parameters", "cip.cm.ot_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8599       { &hf_cip_cm_to_rpi, { "T->O RPI", "cip.cm.torpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8600       { &hf_cip_cm_to_net_params32, { "T->O Network Connection Parameters", "cip.cm.to_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8601       { &hf_cip_cm_to_net_params16, { "T->O Network Connection Parameters", "cip.cm.to_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8602       { &hf_cip_cm_transport_type_trigger, { "Transport Type/Trigger", "cip.cm.transport_type_trigger", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8603       { &hf_cip_cm_conn_path_size, { "Connection Path Size", "cip.cm.connpath_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8604       { &hf_cip_cm_ot_api, { "O->T API", "cip.cm.otapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8605       { &hf_cip_cm_to_api, { "T->O API", "cip.cm.toapi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8606       { &hf_cip_cm_app_reply_size, { "Application Reply Size", "cip.cm.app_reply_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8607       { &hf_cip_cm_app_reply_data , { "Application Reply", "cip.cm.app_reply_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8608       { &hf_cip_cm_consumer_number, { "Consumer Number", "cip.cm.consumer_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8609       { &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 }},
8610       { &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 }},
8611       { &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 }},
8612       { &hf_cip_cm_initial_timestamp, { "Initial Timestamp", "cip.cm.initial_timestamp", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8613       { &hf_cip_cm_initial_rollover, { "Initial Rollover Value", "cip.cm.initial_rollover", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8614       { &hf_cip_cm_remain_path_size, { "Remaining Path Size", "cip.cm.remain_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8615       { &hf_cip_cm_msg_req_size, { "Embedded Message Request Size", "cip.cm.msg_req_size", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0, NULL, HFILL }},
8616       { &hf_cip_cm_route_path_size, { "Route Path Size", "cip.cm.route_path_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8617       { &hf_cip_cm_orig_serial_num, { "Originator Serial Number", "cip.cm.orig_serial_num", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8618       { &hf_cip_cm_fwo_con_size, { "Connection Size", "cip.cm.fwo.consize", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0x01FF, "Fwd Open: Connection size", HFILL }},
8619       { &hf_cip_cm_lfwo_con_size, { "Connection Size", "cip.cm.fwo.consize", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0xFFFF, "Large Fwd Open: Connection size", HFILL }},
8620       { &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 }},
8621       { &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 }},
8622       { &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 }},
8623       { &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 }},
8624       { &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 }},
8625       { &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 }},
8626       { &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 }},
8627       { &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 }},
8628       { &hf_cip_cm_fwo_dir, { "Direction", "cip.cm.fwo.dir", FT_UINT8, BASE_DEC, VALS(cip_con_dir_vals), CI_PRODUCTION_DIR_MASK, "Fwd Open: Direction", HFILL }},
8629       { &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 }},
8630       { &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 }},
8631       { &hf_cip_cm_gco_conn, { "Number of Connections", "cip.cm.gco.conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: Number of Connections", HFILL }},
8632       { &hf_cip_cm_gco_coo_conn, { "COO Connections", "cip.cm.gco.coo_conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: COO Connections", HFILL }},
8633       { &hf_cip_cm_gco_roo_conn, { "ROO Connections", "cip.cm.gco.roo_conn", FT_UINT8, BASE_DEC, NULL, 0, "GetConnOwner: ROO Connections", HFILL }},
8634       { &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 }},
8635       { &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 }},
8636       { &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 }},
8637       { &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 }},
8638       { &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 }},
8639       { &hf_cip_cm_ext126_size, { "Maximum Size", "cip.cm.ext126_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8640       { &hf_cip_cm_ext127_size, { "Maximum Size", "cip.cm.ext127_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8641       { &hf_cip_cm_ext128_size, { "Maximum Size", "cip.cm.ext128_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}
8642    };
8643 
8644   static hf_register_info hf_pccc[] = {
8645       { &hf_cip_pccc_sc, { "Service", "cip.pccc.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_pccc), CIP_SC_MASK, NULL, HFILL }},
8646       { &hf_cip_pccc_req_id_len, { "Requestor ID Length", "cip.pccc.req.id.len", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8647       { &hf_cip_pccc_cip_vend_id, { "CIP Vendor ID", "cip.pccc.cip.vend.id", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8648       { &hf_cip_pccc_cip_serial_num, { "CIP Serial Number", "cip.pccc.cip.serial.num", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8649       { &hf_cip_pccc_cmd_code, { "Command Code", "cip.pccc.cmd.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8650       { &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 }},
8651       { &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 }},
8652       { &hf_cip_pccc_tns_code, { "Transaction Code", "cip.pccc.tns.code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8653       { &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 }},
8654       { &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 }},
8655       { &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 }},
8656       { &hf_cip_pccc_byte_size, { "Byte Size", "cip.pccc.byte.size", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8657       { &hf_cip_pccc_file_num, { "File Number", "cip.pccc.file.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8658       { &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 }},
8659       { &hf_cip_pccc_element_num, { "Element Number", "cip.pccc.element.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8660       { &hf_cip_pccc_subelement_num, { "Sub-Element Number", "cip.pccc.subelement.num", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8661 #if 0
8662       { &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 }},
8663 #endif
8664       { &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 }},
8665       { &hf_cip_pccc_resp_code, { "Response Code", "cip.pccc.resp.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8666       { &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 }},
8667       { &hf_cip_pccc_execute_multi_len, { "Execute Multiple Command - Command Length", "cip.pccc.execute.multi.len", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8668       { &hf_cip_pccc_execute_multi_fnc, { "Execute Multiple Command - Function Code", "cip.pccc.execute.multi.code", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8669 
8670       { &hf_cip_pccc_data, { "Data", "cip.pccc.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
8671    };
8672 
8673    static hf_register_info hf_mb[] = {
8674       { &hf_cip_mb_sc, { "Service", "cip.mb.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_mb), CIP_SC_MASK, NULL, HFILL }},
8675       { &hf_cip_mb_read_coils_start_addr, { "Starting Address", "cip.mb.read_coils.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8676       { &hf_cip_mb_read_coils_num_coils, { "Quantity of Coils", "cip.mb.read_coils.num_coils", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8677       { &hf_cip_mb_read_coils_data, { "Data", "cip.mb.read_coils.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8678       { &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 }},
8679       { &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 }},
8680       { &hf_cip_mb_read_discrete_inputs_data, { "Data", "cip.mb.read_discrete_inputs.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8681       { &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 }},
8682       { &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 }},
8683       { &hf_cip_mb_read_holding_register_data, { "Data", "cip.mb.read_holding_register.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8684       { &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 }},
8685       { &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 }},
8686       { &hf_cip_mb_read_input_register_data, { "Data", "cip.mb.read_input_register.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8687       { &hf_cip_mb_write_coils_start_addr, { "Starting Address", "cip.mb.write_coils.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8688       { &hf_cip_mb_write_coils_outputs_forced, { "Outputs Forced", "cip.mb.write_coils.outputs_forced", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8689       { &hf_cip_mb_write_coils_num_coils, { "Quantity of Coils", "cip.mb.write_coils.num_coils", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8690       { &hf_cip_mb_write_coils_data, { "Data", "cip.mb.write_coils.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8691       { &hf_cip_mb_write_registers_start_addr, { "Starting Address", "cip.mb.write_registers.start_addr", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8692       { &hf_cip_mb_write_registers_outputs_forced, { "Outputs Forced", "cip.mb.write_registers.outputs_forced", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8693       { &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 }},
8694       { &hf_cip_mb_write_registers_data, { "Data", "cip.mb.write_registers.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8695       { &hf_cip_mb_data, { "Data", "cip.mb.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}
8696    };
8697 
8698    static hf_register_info hf_cco[] = {
8699       { &hf_cip_cco_sc, { "Service", "cip.cco.sc", FT_UINT8, BASE_HEX, VALS(cip_sc_vals_cco), CIP_SC_MASK, NULL, HFILL }},
8700       { &hf_cip_cco_format_number, { "Format Number", "cip.cco.format_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8701       { &hf_cip_cco_edit_signature, { "Edit Signature", "cip.cco.edit_signature", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8702       { &hf_cip_cco_con_flags, { "Connection Flags", "cip.cco.connflags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8703       { &hf_cip_cco_con_type, { "Connection O_T", "cip.cco.con", FT_UINT16, BASE_DEC, VALS(cip_con_vals), 0x0001, NULL, HFILL }},
8704       { &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 }},
8705       { &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 }},
8706       { &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 }},
8707       { &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 }},
8708       { &hf_cip_cco_tdi_prodcode, { "Product Code", "cip.cco.tdi.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8709       { &hf_cip_cco_tdi_compatibility, { "Compatibility", "cip.cco.tdi.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8710       { &hf_cip_cco_tdi_comp_bit, { "Compatibility", "cip.cco.tdi.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, NULL, HFILL }},
8711       { &hf_cip_cco_tdi_majorrev, { "Major Revision", "cip.cco.tdi.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL }},
8712       { &hf_cip_cco_tdi_minorrev, { "Minor Revision", "cip.cco.tdi.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8713       { &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 }},
8714       { &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 }},
8715       { &hf_cip_cco_pdi_prodcode, { "Product Code", "cip.cco.pdi.product_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8716       { &hf_cip_cco_pdi_compatibility, { "Compatibility", "cip.cco.pdi.compatibility", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8717       { &hf_cip_cco_pdi_comp_bit, { "Compatibility", "cip.cco.pdi.comp_bit", FT_UINT8, BASE_HEX, VALS(cip_com_bit_vals), 0x80, NULL, HFILL }},
8718       { &hf_cip_cco_pdi_majorrev, { "Major Revision", "cip.cco.pdi.major_rev", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL }},
8719       { &hf_cip_cco_pdi_minorrev, { "Minor Revision", "cip.cco.pdi.minor_rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
8720       { &hf_cip_cco_cs_data_index, { "CS Data Index Number", "cip.cco.cs_data_index", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8721       { &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 }},
8722       { &hf_cip_cco_ot_rpi, { "O->T RPI", "cip.cco.otrpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8723       { &hf_cip_cco_ot_net_param32, { "O->T Network Connection Parameters", "cip.cco.ot_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8724       { &hf_cip_cco_ot_net_param16, { "O->T Network Connection Parameters", "cip.cco.ot_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8725       { &hf_cip_cco_to_rpi, { "T->O RPI", "cip.cco.torpi", FT_UINT32, BASE_CUSTOM, CF_FUNC(cip_rpi_api_fmt), 0, NULL, HFILL }},
8726       { &hf_cip_cco_to_net_param16, { "T->O Network Connection Parameters", "cip.cco.to_net_params", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
8727       { &hf_cip_cco_to_net_param32, { "T->O Network Connection Parameters", "cip.cco.to_net_params", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
8728       { &hf_cip_cco_transport_type_trigger, { "Transport Type/Trigger", "cip.cco.transport_type_trigger", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
8729       { &hf_cip_cco_fwo_con_size, { "Connection Size", "cip.cco.consize", FT_UINT16, BASE_DEC, NULL, 0x01FF, NULL, HFILL }},
8730       { &hf_cip_cco_lfwo_con_size, { "Connection Size", "cip.cco.consize", FT_UINT32, BASE_DEC, NULL, 0xFFFF, NULL, HFILL }},
8731       { &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 }},
8732       { &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 }},
8733       { &hf_cip_cco_fwo_prio, { "Priority", "cip.cco.prio", FT_UINT16, BASE_DEC, VALS(cip_con_prio_vals), 0x0C00, NULL, HFILL }},
8734       { &hf_cip_cco_lfwo_prio, { "Priority", "cip.cco.prio", FT_UINT32, BASE_DEC, VALS(cip_con_prio_vals), 0x0C000000, NULL, HFILL }},
8735       { &hf_cip_cco_fwo_typ, { "Connection Type", "cip.cco.type", FT_UINT16, BASE_DEC, VALS(cip_con_type_vals), 0x6000, NULL, HFILL }},
8736       { &hf_cip_cco_lfwo_typ, { "Connection Type", "cip.cco.type", FT_UINT32, BASE_DEC, VALS(cip_con_type_vals), 0x60000000, NULL, HFILL }},
8737       { &hf_cip_cco_fwo_own, { "Redundant Owner", "cip.cco.owner", FT_UINT16, BASE_DEC, VALS(cip_con_owner_vals), 0x8000, NULL, HFILL }},
8738       { &hf_cip_cco_lfwo_own, { "Redundant Owner", "cip.cco.owner", FT_UINT32, BASE_DEC, VALS(cip_con_owner_vals), 0x80000000, NULL, HFILL }},
8739       { &hf_cip_cco_fwo_dir, { "Direction", "cip.cco.dir", FT_UINT8, BASE_DEC, VALS(cip_con_dir_vals), CI_PRODUCTION_DIR_MASK, NULL, HFILL }},
8740       { &hf_cip_cco_fwo_trigger, { "Trigger", "cip.cco.trigger", FT_UINT8, BASE_DEC, VALS(cip_con_trigg_vals), CI_PRODUCTION_TRIGGER_MASK, NULL, HFILL }},
8741       { &hf_cip_cco_fwo_class, { "Class", "cip.cco.transport", FT_UINT8, BASE_DEC, VALS(cip_con_class_vals), CI_TRANSPORT_CLASS_MASK, NULL, HFILL }},
8742       { &hf_cip_cco_conn_path_size, { "Connection Path Size", "cip.cco.connpath_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_word_words, 0, NULL, HFILL }},
8743       { &hf_cip_cco_proxy_config_size, { "Proxy Config Data Size", "cip.cco.proxy_config_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8744       { &hf_cip_cco_target_config_size, { "Target Config Data Size", "cip.cco.target_config_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8745       { &hf_cip_cco_iomap_format_number, { "Format number", "cip.cco.iomap_format_number", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
8746       { &hf_cip_cco_iomap_size, { "Mapping data size", "cip.cco.iomap_size", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0, NULL, HFILL }},
8747       { &hf_cip_cco_connection_disable, { "Connection Disable", "cip.cco.connection_disable", FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL }},
8748       { &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 }},
8749       { &hf_cip_cco_proxy_config_data, { "Proxy Config Data", "cip.cco.proxy_config_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8750       { &hf_cip_cco_target_config_data, { "Target Config Data", "cip.cco.target_config_data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8751       { &hf_cip_cco_iomap_attribute, { "Attribute Data", "cip.cco.iomap", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8752       { &hf_cip_cco_safety, { "Safety Parameters", "cip.cco.safety", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
8753       { &hf_cip_cco_change_type, { "Change Type", "cip.cco.change_type", FT_UINT16, BASE_DEC, VALS(cip_cco_change_type_vals), 0, NULL, HFILL }},
8754       { &hf_cip_cco_connection_name, { "Connection Name", "cip.cco.connection_name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
8755       { &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 }},
8756    };
8757 
8758    /* Setup protocol subtree array */
8759    static gint *ett[] = {
8760       &ett_cip_class_generic,
8761       &ett_cip,
8762       &ett_path,
8763       &ett_path_seg,
8764       &ett_rrsc,
8765       &ett_mcsc,
8766       &ett_cia_path,
8767       &ett_data_seg,
8768       &ett_cmd_data,
8769       &ett_port_path,
8770       &ett_network_seg,
8771       &ett_network_seg_safety,
8772       &ett_network_seg_safety_time_correction_net_params,
8773       &ett_cip_seg_safety_tunid,
8774       &ett_cip_seg_safety_tunid_snn,
8775       &ett_cip_seg_safety_ounid,
8776       &ett_cip_seg_safety_ounid_snn,
8777       &ett_status_item,
8778       &ett_add_status_item,
8779       &ett_cip_get_attributes_all_item,
8780       &ett_cip_get_attribute_list,
8781       &ett_cip_get_attribute_list_item,
8782       &ett_cip_set_attribute_list,
8783       &ett_cip_set_attribute_list_item,
8784       &ett_cip_mult_service_packet,
8785       &ett_cip_msp_offset,
8786       &ett_time_sync_gm_clock_flags,
8787       &ett_time_sync_local_clock_flags,
8788       &ett_time_sync_port_state_info,
8789       &ett_time_sync_port_enable_cfg,
8790       &ett_time_sync_port_log_announce,
8791       &ett_time_sync_port_log_sync,
8792       &ett_time_sync_clock_type,
8793       &ett_time_sync_port_profile_id_info,
8794       &ett_time_sync_port_phys_addr_info,
8795       &ett_time_sync_port_proto_addr_info,
8796       &ett_id_status,
8797       &ett_32bitheader_tree,
8798       &ett_connection_info,
8799    };
8800 
8801    static gint *ett_cm[] = {
8802       &ett_cip_class_cm,
8803       &ett_cm_rrsc,
8804       &ett_cm_mes_req,
8805       &ett_cm_ncp,
8806       &ett_cm_cmd_data,
8807       &ett_cm_ttt,
8808       &ett_cm_add_status_item,
8809       &ett_cip_cm_pid,
8810       &ett_cip_cm_safety
8811    };
8812 
8813    static gint *ett_pccc[] = {
8814       &ett_cip_class_pccc,
8815       &ett_pccc_rrsc,
8816       &ett_pccc_req_id,
8817       &ett_pccc_cmd_data
8818     };
8819 
8820    static gint *ett_mb[] = {
8821       &ett_cip_class_mb,
8822       &ett_mb_rrsc,
8823       &ett_mb_cmd_data
8824     };
8825 
8826    static gint *ett_cco[] = {
8827       &ett_cip_class_cco,
8828       &ett_cco_iomap,
8829       &ett_cco_con_status,
8830       &ett_cco_con_flag,
8831       &ett_cco_tdi,
8832       &ett_cco_pdi,
8833       &ett_cco_ncp,
8834       &ett_cco_rrsc,
8835       &ett_cco_cmd_data,
8836       &ett_cco_ttt,
8837     };
8838 
8839    static ei_register_info ei[] = {
8840       { &ei_mal_identity_revision, { "cip.malformed.id.revision", PI_MALFORMED, PI_ERROR, "Malformed Identity revision", EXPFILL }},
8841       { &ei_mal_identity_status, { "cip.malformed.id.status", PI_MALFORMED, PI_ERROR, "Malformed Identity status", EXPFILL } },
8842       { &ei_mal_msg_rout_num_classes, { "cip.malformed.msg_rout.num_classes", PI_MALFORMED, PI_ERROR, "Malformed Message Router Attribute 1", EXPFILL }},
8843       { &ei_mal_time_sync_gm_clock, { "cip.malformed.time_sync.gm_clock", PI_MALFORMED, PI_ERROR, "Malformed Grandmaster clock info", EXPFILL }},
8844       { &ei_mal_time_sync_parent_clock, { "cip.malformed.time_sync.parent_clock", PI_MALFORMED, PI_ERROR, "Malformed Parent clock info", EXPFILL }},
8845       { &ei_mal_time_sync_local_clock, { "cip.malformed.time_sync.local_clock", PI_MALFORMED, PI_ERROR, "Malformed Local clock info", EXPFILL }},
8846       { &ei_mal_time_sync_port_state_info, { "cip.malformed.time_sync.port_state_info", PI_MALFORMED, PI_ERROR, "Malformed Port State Info", EXPFILL }},
8847       { &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 }},
8848       { &ei_mal_time_sync_port_enable_cfg, { "cip.malformed.time_sync.port_enable_cfg", PI_MALFORMED, PI_ERROR, "Malformed Port Enable Cfg", EXPFILL }},
8849       { &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 }},
8850       { &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 }},
8851       { &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 }},
8852       { &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 }},
8853       { &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 }},
8854       { &ei_mal_time_sync_clock_type, { "cip.malformed.time_sync.clock_type", PI_MALFORMED, PI_ERROR, "Malformed Clock Type", EXPFILL }},
8855       { &ei_mal_time_sync_manufacture_id, { "cip.malformed.time_sync.manufacture_id", PI_MALFORMED, PI_ERROR, "Malformed Manufacture Identity", EXPFILL }},
8856       { &ei_mal_time_sync_prod_desc, { "cip.malformed.time_sync.prod_desc", PI_MALFORMED, PI_ERROR, "Malformed Product Description", EXPFILL }},
8857       { &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 }},
8858       { &ei_mal_time_sync_prod_desc_size, { "cip.malformed.time_sync.prod_desc.size", PI_MALFORMED, PI_ERROR, "Malformed Product Description - invalid size", EXPFILL }},
8859       { &ei_mal_time_sync_revision_data, { "cip.malformed.time_sync.revision_data", PI_MALFORMED, PI_ERROR, "Malformed Revision Data", EXPFILL }},
8860       { &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 }},
8861       { &ei_mal_time_sync_revision_data_size, { "cip.malformed.time_sync.revision_data.size", PI_MALFORMED, PI_ERROR, "Malformed Revision Data - invalid size", EXPFILL }},
8862       { &ei_mal_time_sync_user_desc, { "cip.malformed.time_sync.user_desc", PI_MALFORMED, PI_ERROR, "Malformed User Description", EXPFILL }},
8863       { &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 }},
8864       { &ei_mal_time_sync_user_desc_size, { "cip.malformed.time_sync.user_desc.size", PI_MALFORMED, PI_ERROR, "Malformed User Description - invalid size", EXPFILL }},
8865       { &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 }},
8866       { &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 }},
8867       { &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 }},
8868       { &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 }},
8869       { &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 }},
8870       { &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 }},
8871       { &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 }},
8872       { &ei_proto_log_seg_format, { "cip.unsupported.log_seg_format", PI_PROTOCOL, PI_WARN, "Unsupported Logical Segment Format", EXPFILL }},
8873       { &ei_mal_incomplete_epath, { "cip.malformed.incomplete_epath", PI_MALFORMED, PI_ERROR, "Incomplete EPATH", EXPFILL }},
8874       { &ei_proto_electronic_key_format, { "cip.unsupported.electronic_key_format", PI_PROTOCOL, PI_WARN, "Unsupported Electronic Key Format", EXPFILL }},
8875       { &ei_proto_special_segment_format, { "cip.unsupported.special_segment_format", PI_PROTOCOL, PI_WARN, "Unsupported Special Segment Format", EXPFILL }},
8876       { &ei_proto_log_seg_type, { "cip.unsupported.log_seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Logical Segment Type", EXPFILL }},
8877       { &ei_proto_log_sub_seg_type, { "cip.unsupported.log_sub_seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Sub-Segment Type", EXPFILL }},
8878       { &ei_proto_ext_string_format, { "cip.unsupported.ext_string_format", PI_PROTOCOL, PI_WARN, "Unsupported Extended String Format", EXPFILL } },
8879       { &ei_proto_ext_network, { "cip.malformed.ext_network", PI_PROTOCOL, PI_ERROR, "Malformed Extended Network Segment Format", EXPFILL } },
8880       { &ei_proto_seg_type, { "cip.unsupported.seg_type", PI_PROTOCOL, PI_WARN, "Unsupported Segment Type", EXPFILL }},
8881       { &ei_proto_unsupported_datatype, { "cip.unsupported.datatype", PI_PROTOCOL, PI_WARN, "Unsupported Datatype", EXPFILL }},
8882       { &ei_mal_serv_gal, { "cip.malformed.get_attribute_list", PI_MALFORMED, PI_ERROR, "Malformed Get Attribute List service", EXPFILL }},
8883       { &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 }},
8884       { &ei_mal_serv_sal, { "cip.malformed.set_attribute_list", PI_MALFORMED, PI_ERROR, "Malformed Set Attribute List service", EXPFILL }},
8885       { &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 }},
8886       { &ei_mal_msp_services, { "cip.malformed.msp.services", PI_MALFORMED, PI_WARN, "Multiple Service Packet too many services for packet", EXPFILL }},
8887       { &ei_mal_msp_inv_offset, { "cip.malformed.msp.inv_offset", PI_MALFORMED, PI_WARN, "Multiple Service Packet service invalid offset", EXPFILL }},
8888       { &ei_mal_msp_missing_services, { "cip.malformed.msp.missing_services", PI_MALFORMED, PI_ERROR, "Multiple Service Packet service missing Number of Services field", EXPFILL }},
8889       { &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 }},
8890       { &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 }},
8891       { &ei_mal_rpi_no_data, { "cip.malformed.rpi_no_data", PI_MALFORMED, PI_WARN, "RPI not acceptable - missing extended data", EXPFILL }},
8892       { &ei_mal_fwd_close_missing_data, { "cip.malformed.fwd_close_missing_data", PI_MALFORMED, PI_ERROR, "Forward Close response missing application reply data", EXPFILL }},
8893       { &ei_mal_opt_attr_list, { "cip.malformed.opt_attr_list", PI_MALFORMED, PI_ERROR, "Optional attribute list missing data", EXPFILL }},
8894       { &ei_mal_opt_service_list, { "cip.malformed.opt_service_list", PI_MALFORMED, PI_ERROR, "Optional service list missing data", EXPFILL }},
8895       { &ei_mal_padded_epath_size, { "cip.malformed.epath.size", PI_MALFORMED, PI_ERROR, "Malformed EPATH vs Size", EXPFILL } },
8896       { &ei_mal_missing_string_data, { "cip.malformed.missing_str_data", PI_MALFORMED, PI_ERROR, "Missing string data", EXPFILL } },
8897    };
8898 
8899    module_t *cip_module;
8900    expert_module_t* expert_cip;
8901 
8902    /* Register the protocol name and description */
8903    proto_cip = proto_register_protocol("Common Industrial Protocol",
8904        "CIP", "cip");
8905    cip_handle = register_dissector("cip", dissect_cip, proto_cip);
8906 
8907    register_dissector("cip_implicit", dissect_cip_implicit, proto_cip);
8908 
8909    /* Required function calls to register the header fields and subtrees used */
8910    proto_register_field_array(proto_cip, hf, array_length(hf));
8911    proto_register_subtree_array(ett, array_length(ett));
8912 
8913    expert_cip = expert_register_protocol(proto_cip);
8914    expert_register_field_array(expert_cip, ei, array_length(ei));
8915 
8916    cip_module = prefs_register_protocol(proto_cip, NULL);
8917    prefs_register_bool_preference(cip_module, "enhanced_info_column",
8918       "Display enhanced Info column data",
8919       "Whether the CIP dissector should display enhanced/verbose data in the Info column for CIP explicit messages",
8920       &cip_enhanced_info_column);
8921 
8922    subdissector_class_table = register_dissector_table("cip.class.iface",
8923       "CIP Class Interface Handle", proto_cip, FT_UINT32, BASE_HEX);
8924    subdissector_symbol_table = register_dissector_table("cip.data_segment.iface",
8925       "CIP Data Segment Interface Handle", proto_cip, FT_UINT32, BASE_HEX);
8926 
8927    /* Register the protocol name and description */
8928    proto_cip_class_generic = proto_register_protocol("CIP Class Generic",
8929        "CIPCLS", "cipcls");
8930 
8931    /* Register the protocol name and description */
8932    proto_cip_class_cm = proto_register_protocol("CIP Connection Manager",
8933        "CIPCM", "cipcm");
8934    proto_register_field_array(proto_cip_class_cm, hf_cm, array_length(hf_cm));
8935    proto_register_subtree_array(ett_cm, array_length(ett_cm));
8936 
8937    proto_cip_class_pccc = proto_register_protocol("CIP PCCC Object",
8938        "CIPPCCC", "cippccc");
8939    proto_register_field_array(proto_cip_class_pccc, hf_pccc, array_length(hf_pccc));
8940    proto_register_subtree_array(ett_pccc, array_length(ett_pccc));
8941 
8942    proto_cip_class_mb = proto_register_protocol("CIP Modbus Object",
8943        "CIPMB", "cipmb");
8944    proto_register_field_array(proto_cip_class_mb, hf_mb, array_length(hf_mb));
8945    proto_register_subtree_array(ett_mb, array_length(ett_mb));
8946 
8947    proto_cip_class_cco = proto_register_protocol("CIP Connection Configuration Object",
8948        "CIPCCO", "cipcco");
8949    proto_register_field_array(proto_cip_class_cco, hf_cco, array_length(hf_cco));
8950    proto_register_subtree_array(ett_cco, array_length(ett_cco));
8951 
8952    /* Register a heuristic dissector on the service of the message so objects
8953     * can override the dissector for common services */
8954    heur_subdissector_service = register_heur_dissector_list("cip.sc", proto_cip);
8955 
8956    build_get_attr_all_table();
8957 } /* end of proto_register_cip() */
8958 
8959 void
proto_reg_handoff_cip(void)8960 proto_reg_handoff_cip(void)
8961 {
8962    dissector_handle_t cip_class_mb_handle;
8963 
8964    /* Create dissector handles */
8965    /* Register for UCMM CIP data, using EtherNet/IP SendRRData service*/
8966    dissector_add_uint( "enip.srrd.iface", ENIP_CIP_INTERFACE, cip_handle );
8967 
8968    dissector_add_uint("cip.connection.class", CI_CLS_MR, cip_handle);
8969 
8970    /* Create and register dissector handle for generic class */
8971    cip_class_generic_handle = create_dissector_handle( dissect_cip_class_generic, proto_cip_class_generic );
8972    dissector_add_uint( "cip.class.iface", 0, cip_class_generic_handle );
8973 
8974    /* Create and register dissector handle for Connection Manager */
8975    cip_class_cm_handle = create_dissector_handle( dissect_cip_class_cm, proto_cip_class_cm );
8976    dissector_add_uint( "cip.class.iface", CI_CLS_CM, cip_class_cm_handle );
8977 
8978    /* Create and register dissector handle for the PCCC class */
8979    cip_class_pccc_handle = create_dissector_handle( dissect_cip_class_pccc, proto_cip_class_pccc );
8980    dissector_add_uint( "cip.class.iface", CI_CLS_PCCC, cip_class_pccc_handle );
8981 
8982    /* Create and register dissector handle for Modbus Object */
8983    cip_class_mb_handle = create_dissector_handle( dissect_cip_class_mb, proto_cip_class_mb );
8984    dissector_add_uint( "cip.class.iface", CI_CLS_MB, cip_class_mb_handle );
8985    modbus_handle = find_dissector_add_dependency("modbus", proto_cip_class_mb);
8986 
8987    /* Create and register dissector handle for Connection Configuration Object */
8988    cip_class_cco_handle = create_dissector_handle( dissect_cip_class_cco, proto_cip_class_cco );
8989    dissector_add_uint( "cip.class.iface", CI_CLS_CCO, cip_class_cco_handle );
8990    heur_dissector_add("cip.sc", dissect_class_cco_heur, "CIP Connection Configuration Object", "cco_cip", proto_cip_class_cco, HEURISTIC_ENABLE);
8991 
8992    proto_enip = proto_get_id_by_filter_name( "enip" );
8993    proto_modbus = proto_get_id_by_filter_name( "modbus" );
8994 
8995 } /* end of proto_reg_handoff_cip() */
8996 
8997 /*
8998  * Editor modelines
8999  *
9000  * Local Variables:
9001  * c-basic-offset: 3
9002  * tab-width: 8
9003  * indent-tabs-mode: nil
9004  * End:
9005  *
9006  * ex: set shiftwidth=3 tabstop=8 expandtab:
9007  * :indentSize=3:tabSize=8:noTabs=true:
9008  */
9009