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 2952 void cip_rpi_api_fmt(gchar *s, guint32 value) 2953 { 2954 g_snprintf(s, ITEM_LABEL_LENGTH, "%.3fms", value / 1000.0); 2955 } 2956 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) 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) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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