b087ed4b6e
replace dissect_ndr_uuid_t by dissect_dcerpc_uuid_t, as this is the correct function to use and will prevent a problem with access to non existing private_data in dissect_ndr_uuid_t svn path=/trunk/; revision=14506
2387 lines
88 KiB
C
2387 lines
88 KiB
C
/* packet-dcerpc-pn-io.c
|
|
* Routines for PROFINET IO dissection.
|
|
*
|
|
* $Id$
|
|
*
|
|
* Ethereal - Network traffic analyzer
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* The PN-IO protocol is a field bus protocol related to decentralized
|
|
* periphery and is developed by the PROFIBUS Nutzerorganisation e.V. (PNO),
|
|
* see: www.profibus.com
|
|
*
|
|
*
|
|
* PN-IO is based on the common DCE-RPC and the "lightweight" PN-RT
|
|
* (ethernet type 0x8892) protocols.
|
|
*
|
|
* The context manager (CM) part is handling context information
|
|
* (like establishing, ...) and is using DCE-RPC as it's underlying
|
|
* protocol.
|
|
*
|
|
* The actual cyclic data transfer and acyclic notification uses the
|
|
* "lightweight" PN-RT protocol.
|
|
*
|
|
* There are some other related PROFINET protocols (e.g. PN-DCP, which is
|
|
* handling addressing topics).
|
|
*
|
|
* Please note: the PROFINET CBA protocol is independant of the PN-IO protocol!
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
#include <epan/packet.h>
|
|
#include <epan/dissectors/packet-dcerpc.h>
|
|
|
|
|
|
|
|
static int proto_pn_io = -1;
|
|
|
|
static int hf_pn_io_opnum = -1;
|
|
static int hf_pn_io_reserved16 = -1;
|
|
|
|
static int hf_pn_io_array = -1;
|
|
static int hf_pn_io_status = -1;
|
|
static int hf_pn_io_args_max = -1;
|
|
static int hf_pn_io_args_len = -1;
|
|
static int hf_pn_io_array_max_count = -1;
|
|
static int hf_pn_io_array_offset = -1;
|
|
static int hf_pn_io_array_act_count = -1;
|
|
|
|
static int hf_pn_io_data = -1;
|
|
|
|
static int hf_pn_io_ar_type = -1;
|
|
static int hf_pn_io_cminitiator_macadd = -1;
|
|
static int hf_pn_io_cminitiator_objectuuid = -1;
|
|
static int hf_pn_io_ar_properties = -1;
|
|
static int hf_pn_io_cminitiator_activitytimeoutfactor = -1;
|
|
static int hf_pn_io_cminitiator_udprtport = -1;
|
|
static int hf_pn_io_station_name_length = -1;
|
|
static int hf_pn_io_cminitiator_station_name = -1;
|
|
|
|
static int hf_pn_io_cmresponder_macadd = -1;
|
|
static int hf_pn_io_cmresponder_udprtport = -1;
|
|
|
|
static int hf_pn_io_iocr_type = -1;
|
|
static int hf_pn_io_iocr_reference = -1;
|
|
static int hf_pn_io_lt = -1;
|
|
static int hf_pn_io_iocr_properties = -1;
|
|
static int hf_pn_io_data_length = -1;
|
|
static int hf_pn_io_frame_id = -1;
|
|
static int hf_pn_io_send_clock_factor = -1;
|
|
static int hf_pn_io_reduction_ratio = -1;
|
|
static int hf_pn_io_phase = -1;
|
|
static int hf_pn_io_sequence = -1;
|
|
static int hf_pn_io_frame_send_offset = -1;
|
|
static int hf_pn_io_watchdog_factor = -1;
|
|
static int hf_pn_io_data_hold_factor = -1;
|
|
static int hf_pn_io_iocr_tag_header = -1;
|
|
static int hf_pn_io_iocr_multicast_mac_add = -1;
|
|
static int hf_pn_io_number_of_apis = -1;
|
|
static int hf_pn_io_number_of_io_data_objects = -1;
|
|
static int hf_pn_io_io_data_object_frame_offset = -1;
|
|
static int hf_pn_io_number_of_iocs = -1;
|
|
static int hf_pn_io_iocs_frame_offset = -1;
|
|
|
|
static int hf_pn_io_alarmcr_type = -1;
|
|
static int hf_pn_io_alarmcr_properties = -1;
|
|
static int hf_pn_io_rta_timeoutfactor = -1;
|
|
static int hf_pn_io_rta_retries = -1;
|
|
static int hf_pn_io_localalarmref = -1;
|
|
static int hf_pn_io_maxalarmdatalength = -1;
|
|
static int hf_pn_io_alarmcr_tagheaderhigh = -1;
|
|
static int hf_pn_io_alarmcr_tagheaderlow = -1;
|
|
|
|
static int hf_pn_io_ar_uuid = -1;
|
|
static int hf_pn_io_api_tree = -1;
|
|
static int hf_pn_io_module_tree = -1;
|
|
static int hf_pn_io_submodule_tree = -1;
|
|
static int hf_pn_io_io_data_object = -1;
|
|
static int hf_pn_io_io_cs = -1;
|
|
static int hf_pn_io_api = -1;
|
|
static int hf_pn_io_slot_nr = -1;
|
|
static int hf_pn_io_subslot_nr = -1;
|
|
static int hf_pn_io_index = -1;
|
|
static int hf_pn_io_seq_number = -1;
|
|
static int hf_pn_io_record_data_length = -1;
|
|
static int hf_pn_io_padding = -1;
|
|
static int hf_pn_io_add_val1 = -1;
|
|
static int hf_pn_io_add_val2 = -1;
|
|
|
|
static int hf_pn_io_block = -1;
|
|
static int hf_pn_io_block_header = -1;
|
|
static int hf_pn_io_block_type = -1;
|
|
static int hf_pn_io_block_length = -1;
|
|
static int hf_pn_io_block_version_high = -1;
|
|
static int hf_pn_io_block_version_low = -1;
|
|
|
|
static int hf_pn_io_sessionkey = -1;
|
|
static int hf_pn_io_control_command = -1;
|
|
static int hf_pn_io_control_command_prmend = -1;
|
|
static int hf_pn_io_control_command_applready = -1;
|
|
static int hf_pn_io_control_command_release = -1;
|
|
static int hf_pn_io_control_command_done = -1;
|
|
static int hf_pn_io_control_block_properties = -1;
|
|
|
|
static int hf_pn_io_error_code = -1;
|
|
static int hf_pn_io_error_decode = -1;
|
|
static int hf_pn_io_error_code1 = -1;
|
|
static int hf_pn_io_error_code2 = -1;
|
|
static int hf_pn_io_error_code1_pniorw = -1;
|
|
static int hf_pn_io_error_code1_pnio = -1;
|
|
|
|
static int hf_pn_io_alarm_type = -1;
|
|
static int hf_pn_io_alarm_specifier = -1;
|
|
static int hf_pn_io_alarm_specifier_sequence = -1;
|
|
static int hf_pn_io_alarm_specifier_channel = -1;
|
|
static int hf_pn_io_alarm_specifier_manufacturer = -1;
|
|
static int hf_pn_io_alarm_specifier_submodule = -1;
|
|
static int hf_pn_io_alarm_specifier_ardiagnosis = -1;
|
|
|
|
static int hf_pn_io_alarm_dst_endpoint = -1;
|
|
static int hf_pn_io_alarm_src_endpoint = -1;
|
|
static int hf_pn_io_pdu_type = -1;
|
|
static int hf_pn_io_pdu_type_type = -1;
|
|
static int hf_pn_io_pdu_type_version = -1;
|
|
static int hf_pn_io_add_flags = -1;
|
|
static int hf_pn_io_window_size = -1;
|
|
static int hf_pn_io_tack = -1;
|
|
static int hf_pn_io_send_seq_num = -1;
|
|
static int hf_pn_io_ack_seq_num = -1;
|
|
static int hf_pn_io_var_part_len = -1;
|
|
|
|
static int hf_pn_io_number_of_modules = -1;
|
|
static int hf_pn_io_module_ident_number = -1;
|
|
static int hf_pn_io_module_properties = -1;
|
|
static int hf_pn_io_module_state = -1;
|
|
static int hf_pn_io_number_of_submodules = -1;
|
|
static int hf_pn_io_submodule_ident_number = -1;
|
|
static int hf_pn_io_submodule_properties = -1;
|
|
static int hf_pn_io_submodule_state = -1;
|
|
static int hf_pn_io_data_description_tree = -1;
|
|
static int hf_pn_io_data_description = -1;
|
|
static int hf_pn_io_submodule_data_length = -1;
|
|
static int hf_pn_io_length_iocs = -1;
|
|
static int hf_pn_io_length_iops = -1;
|
|
|
|
static int hf_pn_io_ioxs = -1;
|
|
static int hf_pn_io_ioxs_extension = -1;
|
|
static int hf_pn_io_ioxs_res14 = -1;
|
|
static int hf_pn_io_ioxs_instance = -1;
|
|
static int hf_pn_io_ioxs_datastate = -1;
|
|
|
|
static int hf_pn_io_address_resolution_properties = -1;
|
|
static int hf_pn_io_mci_timeout_factor = -1;
|
|
static int hf_pn_io_provider_station_name = -1;
|
|
|
|
|
|
static gint ett_pn_io = -1;
|
|
static gint ett_pn_io_block = -1;
|
|
static gint ett_pn_io_block_header = -1;
|
|
static gint ett_pn_io_status = -1;
|
|
static gint ett_pn_io_rtc = -1;
|
|
static gint ett_pn_io_rta = -1;
|
|
static gint ett_pn_io_pdu_type = -1;
|
|
static gint ett_pn_io_add_flags = -1;
|
|
static gint ett_pn_io_control_command = -1;
|
|
static gint ett_pn_io_ioxs = -1;
|
|
static gint ett_pn_io_api = -1;
|
|
static gint ett_pn_io_data_description = -1;
|
|
static gint ett_pn_io_module = -1;
|
|
static gint ett_pn_io_submodule = -1;
|
|
static gint ett_pn_io_io_data_object = -1;
|
|
static gint ett_pn_io_io_cs = -1;
|
|
|
|
static e_uuid_t uuid_pn_io_device = { 0xDEA00001, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
|
|
static guint16 ver_pn_io_device = 1;
|
|
|
|
static e_uuid_t uuid_pn_io_controller = { 0xDEA00002, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
|
|
static guint16 ver_pn_io_controller = 1;
|
|
|
|
static e_uuid_t uuid_pn_io_supervisor = { 0xDEA00003, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
|
|
static guint16 ver_pn_io_supervisor = 1;
|
|
|
|
static e_uuid_t uuid_pn_io_parameterserver = { 0xDEA00004, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } };
|
|
static guint16 ver_pn_io_parameterserver = 1;
|
|
|
|
|
|
static const value_string pn_io_block_type[] = {
|
|
{ 0x0000, "Reserved" },
|
|
{ 0x0001, "Alarm Notification High"},
|
|
{ 0x0002, "Alarm Notification Low"},
|
|
{ 0x0008, "WriteRecordReq"},
|
|
{ 0x8008, "WriteRecordRes"},
|
|
{ 0x0009, "ReadRecordReq"},
|
|
{ 0x8009, "ReadRecordRes"},
|
|
{ 0x0010, "ManufacturerSpecificDiagnosisBlock"},
|
|
{ 0x0011, "ChannelDiagnosisBlock"},
|
|
{ 0x0012, "ExpectedIdentificationDataBlock"},
|
|
{ 0x0014, "SubstituteValue RecordDataRead"},
|
|
{ 0x0015, "RecordInputDataObjectElement"},
|
|
{ 0x0016, "RecordOutputDataObjectElement"},
|
|
{ 0x0017, "RecordOutputDataSubstituteObjectElement"},
|
|
{ 0x0018, "ARData"},
|
|
{ 0x0019, "LogData"},
|
|
{ 0x001A, "APIData"},
|
|
{ 0x0020, "I&M0"},
|
|
{ 0x0021, "I&M1"},
|
|
{ 0x0022, "I&M2"},
|
|
{ 0x0023, "I&M3"},
|
|
{ 0x0024, "I&M4"},
|
|
{ 0x8001, "Alarm Ack High"},
|
|
{ 0x8002, "Alarm Ack Low"},
|
|
{ 0x0101, "ARBlockReq"},
|
|
{ 0x8101, "ARBlockRes"},
|
|
{ 0x0102, "IOCRBlockReq"},
|
|
{ 0x8102, "IOCRBlockRes"},
|
|
{ 0x0103, "AlarmCRBlockReq"},
|
|
{ 0x8103, "AlarmCRBlockRes"},
|
|
{ 0x0104, "ExpectedSubmoduleBlockReq"},
|
|
{ 0x8104, "ModuleDiffBlock"},
|
|
{ 0x0105, "PrmServerBlockReq"},
|
|
{ 0x8105, "PrmServerBlockRes"},
|
|
{ 0x0106, "MCRBlockReq"},
|
|
{ 0x0110, "IODBlockReq"},
|
|
{ 0x8110, "IODBlockRes"},
|
|
{ 0x0111, "IODBlockReq"},
|
|
{ 0x8111, "IODBlockRes"},
|
|
{ 0x0112, "IOXBlockReq"},
|
|
{ 0x8112, "IOXBlockRes"},
|
|
{ 0x0113, "IOXBlockReq"},
|
|
{ 0x8113, "IOXBlockRes"},
|
|
{ 0x0114, "ReleaseBlockReq"},
|
|
{ 0x8114, "ReleaseBlockRes"},
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_alarm_type[] = {
|
|
{ 0x0000, "Reserved" },
|
|
{ 0x0001, "Diagnosis" },
|
|
{ 0x0002, "Process" },
|
|
{ 0x0003, "Pull" },
|
|
{ 0x0004, "Plug" },
|
|
{ 0x0005, "Status" },
|
|
{ 0x0006, "Update" },
|
|
{ 0x0007, "Redundancy" },
|
|
{ 0x0008, "Controlled by supervisor" },
|
|
{ 0x0009, "Released by supervisor" },
|
|
{ 0x000A, "Plug wrong submodule" },
|
|
{ 0x000B, "Return of submodule" },
|
|
/* 0x000C - 0x001F reserved */
|
|
/* 0x0020 - 0x007F manufacturer specific */
|
|
/* 0x0080 - 0x00FF reserved for profiles */
|
|
/* 0x0100 - 0xFFFF reserved */
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_pdu_type[] = {
|
|
{ 0x01, "Data-RTA-PDU" },
|
|
{ 0x02, "NACK-RTA-PDU" },
|
|
{ 0x03, "ACK-RTA-PDU" },
|
|
{ 0x04, "ERR-RTA-PDU" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_error_code[] = {
|
|
{ 0x00, "OK" },
|
|
{ 0x81, "PNIO" },
|
|
{ 0xCF, "RTA error" },
|
|
{ 0xDA, "AlarmAck" },
|
|
{ 0xDB, "IODConnectRes" },
|
|
{ 0xDC, "IODReleaseRes" },
|
|
{ 0xDD, "IODControlRes" },
|
|
{ 0xDE, "IODReadRes" },
|
|
{ 0xDF, "IODWriteRes" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_error_decode[] = {
|
|
{ 0x00, "OK" },
|
|
{ 0x80, "PNIORW" },
|
|
{ 0x81, "PNIO" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/*
|
|
XXX: the next 2 are dependant on error_code and error_decode
|
|
|
|
e.g.: CL-RPC error:
|
|
error_code .. see above
|
|
error_decode .. 0x81
|
|
error_code1 .. 0x69
|
|
error_code2 ..
|
|
1 RPC_ERR_REJECTED
|
|
2 RPC_ERR_FAULTED
|
|
3 RPC_ERR_TIMEOUT
|
|
4 RPC_ERR_IN_ARGS
|
|
5 RPC_ERR_OUT_ARGS
|
|
6 RPC_ERR_DECODE
|
|
7 RPC_ERR_PNIO_OUT_ARGS
|
|
8 Application Timeout
|
|
*/
|
|
|
|
/* XXX: add some more error codes here */
|
|
static const value_string pn_io_error_code1[] = {
|
|
{ 0x00, "OK" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/* XXX: add some more error codes here */
|
|
static const value_string pn_io_error_code2[] = {
|
|
{ 0x00, "OK" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_error_code1_pniorw[] = {
|
|
{ 0x0a /* 10*/, "application" },
|
|
{ 0x0b /* 11*/, "access" },
|
|
{ 0x0c /* 12*/, "resource" },
|
|
{ 0x0d /* 13*/, "user specific(13)" },
|
|
{ 0x0e /* 14*/, "user specific(14)" },
|
|
{ 0x0f /* 15*/, "user specific(15)" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_error_code1_pnio[] = {
|
|
{ 0x00 /* 0*/, "Reserved" },
|
|
{ 0x01 /* 1*/, "Connect: Faulty ARBlockReq" },
|
|
{ 0x02 /* 2*/, "Connect: Faulty IOCRBlockReq" },
|
|
{ 0x03 /* 3*/, "Connect: Faulty ExpectedSubmoduleBlockReq" },
|
|
{ 0x04 /* 4*/, "Connect: Faulty AlarmCRBlockReq" },
|
|
{ 0x05 /* 5*/, "Connect: Faulty PrmServerBlockReq" },
|
|
|
|
{ 0x14 /* 20*/, "IODControl: Faulty ControlBlockConnect" },
|
|
{ 0x15 /* 21*/, "IODControl: Faulty ControlBlockPlug" },
|
|
{ 0x16 /* 22*/, "IOXControl: Faulty ControlBlock after a connect est." },
|
|
{ 0x17 /* 23*/, "IOXControl: Faulty ControlBlock a plug alarm" },
|
|
|
|
{ 0x28 /* 40*/, "Release: Faulty ReleaseBlock" },
|
|
|
|
{ 0x3c /* 60*/, "AlarmAck Error Codes" },
|
|
{ 0x3d /* 61*/, "CMDEV" },
|
|
{ 0x3e /* 62*/, "CMCTL" },
|
|
{ 0x3f /* 63*/, "NRPM" },
|
|
{ 0x40 /* 64*/, "RMPM" },
|
|
{ 0x41 /* 65*/, "ALPMI" },
|
|
{ 0x42 /* 66*/, "ALPMR" },
|
|
{ 0x43 /* 67*/, "LMPM" },
|
|
{ 0x44 /* 68*/, "MMAC" },
|
|
{ 0x45 /* 69*/, "RPC" },
|
|
{ 0x46 /* 70*/, "APMR" },
|
|
{ 0x47 /* 71*/, "APMS" },
|
|
{ 0x48 /* 72*/, "CPM" },
|
|
{ 0x49 /* 73*/, "PPM" },
|
|
{ 0x4a /* 74*/, "DCPUCS" },
|
|
{ 0x4b /* 75*/, "DCPUCR" },
|
|
{ 0x4c /* 76*/, "DCPMCS" },
|
|
{ 0x4d /* 77*/, "DCPMCR" },
|
|
{ 0x4e /* 78*/, "FSPM" },
|
|
{ 0xfd /*253*/, "RTA_ERR_CLS_PROTOCOL" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_ioxs[] = {
|
|
{ 0x00 /* 0*/, "detected by subslot" },
|
|
{ 0x01 /* 1*/, "detected by slot" },
|
|
{ 0x02 /* 2*/, "detected by IO device" },
|
|
{ 0x03 /* 3*/, "detected by IO controller" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
static const value_string pn_io_ar_type[] = {
|
|
{ 0x0000, "reserved" },
|
|
{ 0x0001, "IOCARSingle" },
|
|
{ 0x0002, "reserved" },
|
|
{ 0x0003, "IOCARCIR" },
|
|
{ 0x0004, "IOCAR_IOControllerRedundant" },
|
|
{ 0x0005, "IOCAR_IODeviceRedundant" },
|
|
{ 0x0006, "IOSAR" },
|
|
/*0x0007 - 0xFFFF reserved */
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const value_string pn_io_iocr_type[] = {
|
|
{ 0x0000, "reserved" },
|
|
{ 0x0001, "Input CR" },
|
|
{ 0x0002, "Output CR" },
|
|
{ 0x0003, "Multicast Provider CR" },
|
|
{ 0x0004, "Multicast Consumer CR" },
|
|
/*0x0005 - 0xFFFF reserved */
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
static const value_string pn_io_data_description[] = {
|
|
{ 0x0000, "reserved" },
|
|
{ 0x0001, "Input" },
|
|
{ 0x0002, "Output" },
|
|
{ 0x0003, "reserved" },
|
|
/*0x0004 - 0xFFFF reserved */
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
|
|
static const value_string pn_io_module_state[] = {
|
|
{ 0x0000, "no module" },
|
|
{ 0x0001, "wrong module" },
|
|
{ 0x0002, "proper module" },
|
|
{ 0x0003, "substitute" },
|
|
/*0x0004 - 0xFFFF reserved */
|
|
{ 0, NULL }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* dissect a 6 byte MAC address */
|
|
int
|
|
dissect_MAC(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
|
|
proto_tree *tree, int hfindex, guint8 *pdata)
|
|
{
|
|
guint8 data[6];
|
|
|
|
tvb_memcpy(tvb, data, offset, 6);
|
|
if(tree)
|
|
proto_tree_add_ether(tree, hfindex, tvb, offset, 6, data);
|
|
|
|
if (pdata)
|
|
memcpy(pdata, data, 6);
|
|
|
|
return offset + 6;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* dissect the four status (error) fields */
|
|
static int
|
|
dissect_PNIO_status(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint8 u8ErrorCode;
|
|
guint8 u8ErrorDecode;
|
|
guint8 u8ErrorCode1;
|
|
guint8 u8ErrorCode2;
|
|
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
int bytemask = (drep[0] & 0x10) ? 3 : 0;
|
|
const value_string *error_code1_vals;
|
|
|
|
|
|
|
|
/* status */
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_status, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_status);
|
|
u32SubStart = offset;
|
|
|
|
/* the PNIOStatus field is existing in both the RPC and the application data,
|
|
* depending on the current PDU.
|
|
* As the byte representation of these layers are different, this has to be handled
|
|
* in a somewhat different way than elsewhere. */
|
|
|
|
dissect_dcerpc_uint8(tvb, offset+(0^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_code, &u8ErrorCode);
|
|
dissect_dcerpc_uint8(tvb, offset+(1^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_decode, &u8ErrorDecode);
|
|
|
|
switch(u8ErrorDecode) {
|
|
case(0x80): /* PNIORW */
|
|
dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_code1_pniorw, &u8ErrorCode1);
|
|
error_code1_vals = pn_io_error_code1_pniorw;
|
|
break;
|
|
case(0x81): /* PNIO */
|
|
dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_code1_pnio, &u8ErrorCode1);
|
|
error_code1_vals = pn_io_error_code1_pnio;
|
|
break;
|
|
default:
|
|
dissect_dcerpc_uint8(tvb, offset+(2^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_code1, &u8ErrorCode1);
|
|
error_code1_vals = pn_io_error_code1;
|
|
}
|
|
|
|
/* XXX - this has to be decode specific too */
|
|
dissect_dcerpc_uint8(tvb, offset+(3^bytemask), pinfo, sub_tree, drep,
|
|
hf_pn_io_error_code2, &u8ErrorCode2);
|
|
|
|
offset +=4;
|
|
|
|
if(u8ErrorCode == 0 && u8ErrorDecode == 0 && u8ErrorCode1 == 0 && u8ErrorCode2 == 0) {
|
|
proto_item_append_text(sub_item, ": OK");
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", OK");
|
|
} else {
|
|
proto_item_append_text(sub_item, ": Error Code: \"%s\", Decode: \"%s\", Code1: \"%s\" Code2: 0x%x",
|
|
val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"),
|
|
val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"),
|
|
val_to_str(u8ErrorCode1, error_code1_vals, "(0x%x)"),
|
|
u8ErrorCode2);
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Error Code: %s, Decode: %s, Code1: 0x%x Code2: 0x%x",
|
|
val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"),
|
|
val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"),
|
|
u8ErrorCode1,
|
|
u8ErrorCode2);
|
|
}
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the alarm specifier */
|
|
static int
|
|
dissect_Alarm_specifier(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16AlarmSpecifierSequence;
|
|
guint16 u16AlarmSpecifierChannel;
|
|
guint16 u16AlarmSpecifierManufacturer;
|
|
guint16 u16AlarmSpecifierSubmodule;
|
|
guint16 u16AlarmSpecifierAR;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
|
|
/* alarm specifier */
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_alarm_specifier, tvb, offset, 2, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type);
|
|
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_alarm_specifier_sequence, &u16AlarmSpecifierSequence);
|
|
u16AlarmSpecifierSequence &= 0x07FF;
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_alarm_specifier_channel, &u16AlarmSpecifierChannel);
|
|
u16AlarmSpecifierChannel = (u16AlarmSpecifierChannel &0x0800) >> 11;
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_alarm_specifier_manufacturer, &u16AlarmSpecifierManufacturer);
|
|
u16AlarmSpecifierManufacturer = (u16AlarmSpecifierManufacturer &0x1000) >> 12;
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_alarm_specifier_submodule, &u16AlarmSpecifierSubmodule);
|
|
u16AlarmSpecifierSubmodule = (u16AlarmSpecifierSubmodule & 0x2000) >> 13;
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_alarm_specifier_ardiagnosis, &u16AlarmSpecifierAR);
|
|
u16AlarmSpecifierAR = (u16AlarmSpecifierAR & 0x8000) >> 15;
|
|
|
|
|
|
proto_item_append_text(sub_item, ", Sequence: %u, Channel: %u, Manuf: %u, Submodule: %u AR: %u",
|
|
u16AlarmSpecifierSequence, u16AlarmSpecifierChannel,
|
|
u16AlarmSpecifierManufacturer, u16AlarmSpecifierSubmodule, u16AlarmSpecifierAR);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the alarm header */
|
|
static int
|
|
dissect_Alarm_header(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16AlarmType;
|
|
guint32 u32Api;
|
|
guint16 u16SlotNr;
|
|
guint16 u16SubslotNr;
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarm_type, &u16AlarmType);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_api, &u32Api);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Slot: 0x%x/0x%x",
|
|
val_to_str(u16AlarmType, pn_io_alarm_type, "Unknown"),
|
|
u16SlotNr, u16SubslotNr);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the alarm note block */
|
|
static int
|
|
dissect_Alarm_note_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 body_length)
|
|
{
|
|
guint32 u32ModuleIdentNumber;
|
|
guint32 u32SubmoduleIdentNumber;
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", Alarm Notification");
|
|
|
|
offset = dissect_Alarm_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
|
|
|
|
offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* XXX - dissect AlarmItem */
|
|
body_length -= 20;
|
|
proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, body_length, "data",
|
|
"Alarm Item Data: %u bytes", body_length);
|
|
offset += body_length;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the alarm acknowledge block */
|
|
static int
|
|
dissect_Alarm_ack_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", Alarm Ack");
|
|
|
|
offset = dissect_Alarm_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep);
|
|
|
|
offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the read/write header */
|
|
static int
|
|
dissect_ReadWrite_header(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index)
|
|
{
|
|
e_uuid_t uuid;
|
|
guint32 u32Api;
|
|
guint16 u16SlotNr;
|
|
guint16 u16SubslotNr;
|
|
guint16 u16SeqNr;
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_seq_number, &u16SeqNr);
|
|
|
|
offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_uuid, &uuid);
|
|
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_api, &u32Api);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
proto_tree_add_string_format(tree, hf_pn_io_padding, tvb, offset, 2, "padding", "Padding: 2 bytes");
|
|
offset += 2;
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_index, u16Index);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: 0x%x, Slot: 0x%x/0x%x",
|
|
u32Api, u16SlotNr, u16SubslotNr);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the read/write request block */
|
|
static int
|
|
dissect_ReadWrite_rqst_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen)
|
|
{
|
|
|
|
offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, drep, u16Index);
|
|
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_record_data_length, u32RecDataLen);
|
|
/* XXX: don't know how to handle the optional TargetARUUID */
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes",
|
|
*u32RecDataLen);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the read/write response block */
|
|
static int
|
|
dissect_ReadWrite_resp_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index)
|
|
{
|
|
guint32 u32RecDataLen;
|
|
guint16 u16AddVal1;
|
|
guint16 u16AddVal2;
|
|
|
|
|
|
offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, drep, u16Index);
|
|
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_record_data_length, &u32RecDataLen);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_add_val1, &u16AddVal1);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_add_val2, &u16AddVal2);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes",
|
|
u32RecDataLen);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the control/connect block */
|
|
static int
|
|
dissect_ControlConnect_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
e_uuid_t ar_uuid;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint16 u16PrmEnd;
|
|
guint16 u16ApplReady;
|
|
guint16 u16Release;
|
|
guint16 u16CmdDone;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_reserved16, NULL);
|
|
|
|
offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_uuid, &ar_uuid);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_sessionkey, NULL);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_reserved16, NULL);
|
|
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_control_command, tvb, offset, 2, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_control_command);
|
|
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_control_command_prmend, &u16PrmEnd);
|
|
if(u16PrmEnd & 0x0001) {
|
|
proto_item_append_text(sub_item, ", Parameter End");
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Parameter End\"");
|
|
}
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_control_command_applready, &u16ApplReady);
|
|
if((u16ApplReady >> 1) & 0x0001) {
|
|
proto_item_append_text(sub_item, ", Application Ready");
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Application Ready\"");
|
|
}
|
|
dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_control_command_release, &u16Release);
|
|
if((u16Release >> 2) & 0x0001) {
|
|
proto_item_append_text(sub_item, ", Release");
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Release\"");
|
|
}
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_control_command_done, &u16CmdDone);
|
|
if((u16CmdDone >> 3) & 0x0001) {
|
|
proto_item_append_text(sub_item, ", Done");
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: \"Done\"");
|
|
}
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_control_block_properties, NULL);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the ARBlockReq */
|
|
static int
|
|
dissect_ARBlockReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16ARType;
|
|
e_uuid_t uuid;
|
|
guint16 u16SessionKey;
|
|
guint8 mac[6];
|
|
guint32 u32ARProperties;
|
|
guint16 u16TimeoutFactor;
|
|
guint16 u16UDPRTPort;
|
|
guint16 u16NameLength;
|
|
guint8 *pu8StationName;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_type, &u16ARType);
|
|
offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_uuid, &uuid);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_sessionkey, &u16SessionKey);
|
|
offset = dissect_MAC(tvb, offset, pinfo, tree,
|
|
hf_pn_io_cminitiator_macadd, mac);
|
|
offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_cminitiator_objectuuid, &uuid);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_properties, &u32ARProperties);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_cminitiator_activitytimeoutfactor, &u16TimeoutFactor); /* XXX - special values */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_cminitiator_udprtport, &u16UDPRTPort); /* XXX - special values */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_station_name_length, &u16NameLength);
|
|
|
|
pu8StationName = g_malloc(u16NameLength+1);
|
|
tvb_memcpy(tvb, pu8StationName, offset, u16NameLength);
|
|
pu8StationName[u16NameLength] = '\0';
|
|
proto_tree_add_string (tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, pu8StationName);
|
|
g_free(pu8StationName);
|
|
offset += u16NameLength;
|
|
|
|
/*if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: %u, Slot: %u/%u",
|
|
u32Api, u16SlotNr, u16SubslotNr);*/
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the ARBlockRes */
|
|
static int
|
|
dissect_ARBlockRes(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16ARType;
|
|
e_uuid_t uuid;
|
|
guint16 u16SessionKey;
|
|
guint8 mac[6];
|
|
guint16 u16UDPRTPort;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_type, &u16ARType);
|
|
offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_ar_uuid, &uuid);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_sessionkey, &u16SessionKey);
|
|
offset = dissect_MAC(tvb, offset, pinfo, tree,
|
|
hf_pn_io_cmresponder_macadd, mac);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_cmresponder_udprtport, &u16UDPRTPort); /* XXX - special values */
|
|
|
|
/*if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Api: %u, Slot: %u/%u",
|
|
u32Api, u16SlotNr, u16SubslotNr);*/
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the IOCRBlockReq */
|
|
static int
|
|
dissect_IOCRBlockReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16IOCRType;
|
|
guint16 u16IOCRReference;
|
|
guint16 u16LT;
|
|
guint32 u32IOCRProperties;
|
|
guint16 u16DataLength;
|
|
guint16 u16FrameID;
|
|
guint16 u16SendClockFactor;
|
|
guint16 u16ReductionRatio;
|
|
guint16 u16Phase;
|
|
guint16 u16Sequence;
|
|
guint32 u32FrameSendOffset;
|
|
guint16 u16WatchdogFactor;
|
|
guint16 u16DataHoldFactor;
|
|
guint16 u16IOCRTagHeader;
|
|
guint8 mac[6];
|
|
guint16 u16NumberOfAPIs;
|
|
guint32 u32Api;
|
|
guint16 u16NumberOfIODataObjects;
|
|
guint16 u16SlotNr;
|
|
guint16 u16SubslotNr;
|
|
guint16 u16IODataObjectFrameOffset;
|
|
guint16 u16NumberOfIOCS;
|
|
guint16 u16IOCSFrameOffset;
|
|
proto_item *api_item;
|
|
proto_tree *api_tree;
|
|
guint32 u32ApiStart;
|
|
guint16 u16Tmp;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_type, &u16IOCRType);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_reference, &u16IOCRReference);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_lt, &u16LT);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_properties, &u32IOCRProperties);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_data_length, &u16DataLength);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_frame_id, &u16FrameID);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_send_clock_factor, &u16SendClockFactor);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_reduction_ratio, &u16ReductionRatio);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_phase, &u16Phase);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_sequence, &u16Sequence);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_frame_send_offset, &u32FrameSendOffset);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_watchdog_factor, &u16WatchdogFactor);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_data_hold_factor, &u16DataHoldFactor);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_tag_header, &u16IOCRTagHeader);
|
|
offset = dissect_MAC(tvb, offset, pinfo, tree,
|
|
hf_pn_io_iocr_multicast_mac_add, mac);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_number_of_apis, &u16NumberOfAPIs);
|
|
while(u16NumberOfAPIs--) {
|
|
api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
|
|
api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
|
|
u32ApiStart = offset;
|
|
|
|
/* API */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_api, &u32Api);
|
|
/* NumberOfIODataObjects */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_number_of_io_data_objects, &u16NumberOfIODataObjects);
|
|
|
|
u16Tmp = u16NumberOfIODataObjects;
|
|
while(u16Tmp--) {
|
|
sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_data_object, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_data_object);
|
|
u32SubStart = offset;
|
|
|
|
/* SlotNumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
/* Subslotnumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
/* IODataObjectFrameOffset */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_io_data_object_frame_offset, &u16IODataObjectFrameOffset);
|
|
|
|
proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u",
|
|
u16SlotNr, u16SubslotNr, u16IODataObjectFrameOffset);
|
|
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
}
|
|
/* NumberOfIOCS */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_number_of_iocs, &u16NumberOfIOCS);
|
|
|
|
u16Tmp = u16NumberOfIOCS;
|
|
while(u16Tmp--) {
|
|
sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_cs, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_cs);
|
|
u32SubStart = offset;
|
|
|
|
/* SlotNumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
/* Subslotnumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
/* IOCSFrameOffset */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_iocs_frame_offset, &u16IOCSFrameOffset);
|
|
|
|
proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u",
|
|
u16SlotNr, u16SubslotNr, u16IOCSFrameOffset);
|
|
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
}
|
|
|
|
proto_item_append_text(api_item, ": %u, NumberOfIODataObjects: %u NumberOfIOCS: %u",
|
|
u32Api, u16NumberOfIODataObjects, u16NumberOfIOCS);
|
|
|
|
proto_item_set_len(api_item, offset - u32ApiStart);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the AlarmCRBlockReq */
|
|
static int
|
|
dissect_AlarmCRBlockReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16AlarmCRType;
|
|
guint16 u16LT;
|
|
guint32 u32AlarmCRProperties;
|
|
guint16 u16RTATimeoutFactor;
|
|
guint16 u16RTARetries;
|
|
guint16 u16LocalAlarmReference;
|
|
guint16 u16MaxAlarmDataLength;
|
|
guint16 u16AlarmCRTagHeaderHigh;
|
|
guint16 u16AlarmCRTagHeaderLow;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarmcr_type, &u16AlarmCRType);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_lt, &u16LT);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarmcr_properties, &u32AlarmCRProperties);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_rta_timeoutfactor, &u16RTATimeoutFactor);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_rta_retries, &u16RTARetries);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_localalarmref, &u16LocalAlarmReference);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarmcr_tagheaderhigh, &u16AlarmCRTagHeaderHigh);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarmcr_tagheaderlow, &u16AlarmCRTagHeaderLow);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the AlarmCRBlockRes */
|
|
static int
|
|
dissect_AlarmCRBlockRes(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16AlarmCRType;
|
|
guint16 u16LocalAlarmReference;
|
|
guint16 u16MaxAlarmDataLength;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_alarmcr_type, &u16AlarmCRType);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_localalarmref, &u16LocalAlarmReference);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
|
|
/* dissect the IOCRBlockRes */
|
|
static int
|
|
dissect_IOCRBlockRes(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16IOCRType;
|
|
guint16 u16IOCRReference;
|
|
guint16 u16FrameID;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_type, &u16IOCRType);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_reference, &u16IOCRReference);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_frame_id, &u16FrameID);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
|
|
/* dissect the MCRBlockReq */
|
|
static int
|
|
dissect_MCRBlockReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16IOCRReference;
|
|
guint32 u32AddressResolutionProperties;
|
|
guint16 u16MCITimeoutFactor;
|
|
guint16 u16NameLength;
|
|
guint8 *pu8StationName;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_iocr_reference, &u16IOCRReference);
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_address_resolution_properties, &u32AddressResolutionProperties);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_mci_timeout_factor, &u16MCITimeoutFactor);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_station_name_length, &u16NameLength);
|
|
|
|
pu8StationName = g_malloc(u16NameLength+1);
|
|
tvb_memcpy(tvb, pu8StationName, offset, u16NameLength);
|
|
pu8StationName[u16NameLength] = '\0';
|
|
proto_tree_add_string (tree, hf_pn_io_provider_station_name, tvb, offset, u16NameLength, pu8StationName);
|
|
g_free(pu8StationName);
|
|
offset += u16NameLength;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
|
|
/* dissect the DataDescription */
|
|
static int
|
|
dissect_DataDescription(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16DataDescription;
|
|
guint16 u16SubmoduleDataLength;
|
|
guint8 u8LengthIOCS;
|
|
guint8 u8LengthIOPS;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_data_description_tree, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_data_description);
|
|
u32SubStart = offset;
|
|
|
|
/* DataDescription */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_data_description, &u16DataDescription);
|
|
/* SubmoduleDataLength */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_submodule_data_length, &u16SubmoduleDataLength);
|
|
/* LengthIOCS */
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_length_iocs, &u8LengthIOCS);
|
|
/* LengthIOPS */
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_length_iops, &u8LengthIOPS);
|
|
|
|
proto_item_append_text(sub_item, ": %s, SubmoduleDataLength: %u, LengthIOCS: %u, u8LengthIOPS: %u",
|
|
val_to_str(u16DataDescription, pn_io_data_description, "(0x%x)"),
|
|
u16SubmoduleDataLength, u8LengthIOCS, u8LengthIOPS);
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the ExpectedSubmoduleBlockReq */
|
|
static int
|
|
dissect_ExpectedSubmoduleBlockReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16NumberOfAPIs;
|
|
guint32 u32Api;
|
|
guint16 u16SlotNr;
|
|
guint32 u32ModuleIdentNumber;
|
|
guint16 u16ModuleProperties;
|
|
guint16 u16NumberOfSubmodules;
|
|
guint16 u16SubslotNr;
|
|
guint32 u32SubmoduleIdentNumber;
|
|
guint16 u16SubmoduleProperties;
|
|
proto_item *api_item;
|
|
proto_tree *api_tree;
|
|
guint32 u32ApiStart;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_number_of_apis, &u16NumberOfAPIs);
|
|
while(u16NumberOfAPIs--) {
|
|
api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
|
|
api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
|
|
u32ApiStart = offset;
|
|
|
|
/* API */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_api, &u32Api);
|
|
/* SlotNumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
/* ModuleIdentNumber */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
|
|
/* ModuleProperties */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_module_properties, &u16ModuleProperties);
|
|
/* NumberOfSubmodules */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_number_of_submodules, &u16NumberOfSubmodules);
|
|
|
|
proto_item_append_text(api_item, ": %u, Slot: 0x%x, ModuleIdentNumber: 0x%x ModuleProperties: 0x%x NumberOfSubmodules: %u",
|
|
u32Api, u16SlotNr, u32ModuleIdentNumber, u16ModuleProperties, u16NumberOfSubmodules);
|
|
|
|
while(u16NumberOfSubmodules--) {
|
|
sub_item = proto_tree_add_item(api_tree, hf_pn_io_submodule_tree, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule);
|
|
u32SubStart = offset;
|
|
|
|
/* Subslotnumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
/* SubmoduleIdentNumber */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
|
|
/* SubmoduleProperties */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_submodule_properties, &u16SubmoduleProperties);
|
|
|
|
switch(u16SubmoduleProperties & 0x03) {
|
|
case(0x00): /* no input and no output data (one Input DataDescription Block follows) */
|
|
offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x01): /* input data (one Input DataDescription Block follows) */
|
|
offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x02): /* output data (one Output DataDescription Block follows) */
|
|
offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x03): /* input and output data (one Input and one Output DataDescription Block follows) */
|
|
offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
|
|
offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
}
|
|
|
|
proto_item_append_text(sub_item, ": Subslot: 0x%x, SubmoduleIdent: 0x%x SubmoduleProperties: 0x%x",
|
|
u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleProperties);
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
}
|
|
|
|
proto_item_set_len(api_item, offset - u32ApiStart);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the ModuleDiffBlock */
|
|
static int
|
|
dissect_ModuleDiffBlock(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16NumberOfAPIs;
|
|
guint32 u32Api;
|
|
guint16 u16NumberOfModules;
|
|
guint16 u16SlotNr;
|
|
guint32 u32ModuleIdentNumber;
|
|
guint16 u16ModuleState;
|
|
guint16 u16NumberOfSubmodules;
|
|
guint16 u16SubslotNr;
|
|
guint32 u32SubmoduleIdentNumber;
|
|
guint16 u16SubmoduleState;
|
|
proto_item *api_item;
|
|
proto_tree *api_tree;
|
|
guint32 u32ApiStart;
|
|
proto_item *module_item;
|
|
proto_tree *module_tree;
|
|
guint32 u32ModuleStart;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
/* NumberOfAPIs */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_number_of_apis, &u16NumberOfAPIs);
|
|
while(u16NumberOfAPIs--) {
|
|
api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, FALSE);
|
|
api_tree = proto_item_add_subtree(api_item, ett_pn_io_api);
|
|
u32ApiStart = offset;
|
|
|
|
/* API */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_api, &u32Api);
|
|
/* NumberOfModules */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep,
|
|
hf_pn_io_number_of_modules, &u16NumberOfModules);
|
|
|
|
proto_item_append_text(api_item, ": %u, NumberOfModules: %u",
|
|
u32Api, u16NumberOfModules);
|
|
|
|
while(u16NumberOfModules--) {
|
|
module_item = proto_tree_add_item(api_tree, hf_pn_io_module_tree, tvb, offset, 0, FALSE);
|
|
module_tree = proto_item_add_subtree(module_item, ett_pn_io_module);
|
|
u32ModuleStart = offset;
|
|
|
|
/* SlotNumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep,
|
|
hf_pn_io_slot_nr, &u16SlotNr);
|
|
/* ModuleIdentNumber */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, module_tree, drep,
|
|
hf_pn_io_module_ident_number, &u32ModuleIdentNumber);
|
|
/* ModuleState */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep,
|
|
hf_pn_io_module_state, &u16ModuleState);
|
|
/* NumberOfSubmodules */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep,
|
|
hf_pn_io_number_of_submodules, &u16NumberOfSubmodules);
|
|
|
|
proto_item_append_text(module_item, ": Slot 0x%x, ModuleIdent: 0x%x ModuleState: %s NumberOfSubmodules: %u",
|
|
u16SlotNr, u32ModuleIdentNumber,
|
|
val_to_str(u16ModuleState, pn_io_module_state, "(0x%x)"),
|
|
u16NumberOfSubmodules);
|
|
|
|
while(u16NumberOfSubmodules--) {
|
|
sub_item = proto_tree_add_item(module_tree, hf_pn_io_submodule_tree, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule);
|
|
u32SubStart = offset;
|
|
|
|
/* Subslotnumber */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_subslot_nr, &u16SubslotNr);
|
|
/* SubmoduleIdentNumber */
|
|
offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber);
|
|
/* SubmoduleState */
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_submodule_state, &u16SubmoduleState);
|
|
|
|
proto_item_append_text(sub_item, ": Subslot 0x%x, SubmoduleIdentNumber: 0x%x, SubmoduleState: 0x%x",
|
|
u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleState);
|
|
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
} /* NumberOfSubmodules */
|
|
|
|
proto_item_set_len(module_item, offset - u32ModuleStart);
|
|
}
|
|
|
|
proto_item_set_len(api_item, offset - u32ApiStart);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect one PN-IO block (depending on the block type) */
|
|
static int
|
|
dissect_block(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen)
|
|
{
|
|
guint16 u16BlockType;
|
|
guint16 u16BlockLength;
|
|
guint8 u8BlockVersionHigh;
|
|
guint8 u8BlockVersionLow;
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
guint16 u16BodyLength;
|
|
proto_item *header_item;
|
|
proto_tree *header_tree;
|
|
|
|
|
|
/* from here, we only have big endian (network byte ordering)!!! */
|
|
drep[0] &= ~0x10;
|
|
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_block, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_block);
|
|
u32SubStart = offset;
|
|
|
|
header_item = proto_tree_add_item(sub_tree, hf_pn_io_block_header, tvb, offset, 6, FALSE);
|
|
header_tree = proto_item_add_subtree(header_item, ett_pn_io_block_header);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep,
|
|
hf_pn_io_block_type, &u16BlockType);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep,
|
|
hf_pn_io_block_length, &u16BlockLength);
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep,
|
|
hf_pn_io_block_version_high, &u8BlockVersionHigh);
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep,
|
|
hf_pn_io_block_version_low, &u8BlockVersionLow);
|
|
|
|
/* XXX - append block_header data to header_item */
|
|
|
|
/* block length is without type and length fields, but with version field */
|
|
/* as it's already dissected, remove it */
|
|
u16BodyLength = u16BlockLength - 2;
|
|
tvb_ensure_bytes_exist(tvb, offset, u16BodyLength);
|
|
|
|
switch(u16BlockType) {
|
|
case(0x0001):
|
|
case(0x0002):
|
|
dissect_Alarm_note_block(tvb, offset, pinfo, sub_tree, drep, u16BodyLength);
|
|
break;
|
|
case(0x0101):
|
|
dissect_ARBlockReq(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0102):
|
|
dissect_IOCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0103):
|
|
dissect_AlarmCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0104):
|
|
dissect_ExpectedSubmoduleBlockReq(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0106):
|
|
dissect_MCRBlockReq(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0110):
|
|
case(0x0112):
|
|
case(0x0114):
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
|
val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
|
|
dissect_ControlConnect_block(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x0008):
|
|
case(0x0009):
|
|
dissect_ReadWrite_rqst_block(tvb, offset, pinfo, sub_tree, drep, u16Index, u32RecDataLen);
|
|
break;
|
|
case(0x8001):
|
|
case(0x8002):
|
|
dissect_Alarm_ack_block(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x8008):
|
|
case(0x8009):
|
|
dissect_ReadWrite_resp_block(tvb, offset, pinfo, sub_tree, drep, u16Index);
|
|
break;
|
|
case(0x8101):
|
|
dissect_ARBlockRes(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x8102):
|
|
dissect_IOCRBlockRes(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x8103):
|
|
dissect_AlarmCRBlockRes(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x8104):
|
|
dissect_ModuleDiffBlock(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
case(0x8110):
|
|
case(0x8112):
|
|
case(0x8114):
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
|
val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
|
|
dissect_ControlConnect_block(tvb, offset, pinfo, sub_tree, drep);
|
|
break;
|
|
default:
|
|
if (check_col(pinfo->cinfo, COL_INFO) && *u16Index < 3)
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
|
val_to_str(u16BlockType, pn_io_block_type, "Unknown"));
|
|
proto_tree_add_string_format(sub_tree, hf_pn_io_data, tvb, offset, u16BodyLength, "undecoded", "Undecoded Data: %d bytes", u16BodyLength);
|
|
}
|
|
offset += u16BodyLength;
|
|
|
|
proto_item_append_text(sub_item, "[%u]: Type=\"%s\" (0x%04x), Length=%u(+4), Version=%u.%u",
|
|
*u16Index, val_to_str(u16BlockType, pn_io_block_type, "Unknown"), u16BlockType,
|
|
u16BlockLength, u8BlockVersionHigh, u8BlockVersionLow);
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect any number of PN-IO blocks */
|
|
static int
|
|
dissect_blocks(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
|
|
while(tvb_length(tvb) > (guint) offset) {
|
|
offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
|
|
u16Index++;
|
|
}
|
|
|
|
/* we don't want to have too many blocks in the info column */
|
|
if(u16Index > 3) {
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", ... (%u blocks)",
|
|
u16Index);
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO (DCE-RPC) request header */
|
|
static int
|
|
dissect_IPNIO_rqst_header(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint32 u32ArgsMax;
|
|
guint32 u32ArgsLen;
|
|
guint32 u32MaxCount;
|
|
guint32 u32Offset;
|
|
guint32 u32ArraySize;
|
|
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM");
|
|
|
|
/* args_max */
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_args_max, &u32ArgsMax);
|
|
/* args_len */
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_args_len, &u32ArgsLen);
|
|
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io);
|
|
u32SubStart = offset;
|
|
|
|
/* RPC array header */
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_max_count, &u32MaxCount);
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_offset, &u32Offset);
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_act_count, &u32ArraySize);
|
|
|
|
proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u",
|
|
u32MaxCount, u32Offset, u32ArraySize);
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO (DCE-RPC) response header */
|
|
static int
|
|
dissect_IPNIO_resp_header(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint32 u32ArgsLen;
|
|
guint32 u32MaxCount;
|
|
guint32 u32Offset;
|
|
guint32 u32ArraySize;
|
|
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
guint32 u32SubStart;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM");
|
|
|
|
offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* args_len */
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
|
|
hf_pn_io_args_len, &u32ArgsLen);
|
|
|
|
sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io);
|
|
u32SubStart = offset;
|
|
|
|
/* RPC array header */
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_max_count, &u32MaxCount);
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_offset, &u32Offset);
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_array_act_count, &u32ArraySize);
|
|
|
|
proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u",
|
|
u32MaxCount, u32Offset, u32ArraySize);
|
|
proto_item_set_len(sub_item, offset - u32SubStart);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO connect request */
|
|
static int
|
|
dissect_IPNIO_Connect_rqst(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODConnectReq */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO connect response */
|
|
static int
|
|
dissect_IPNIO_Connect_resp(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODConnectRes */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO release request */
|
|
static int
|
|
dissect_IPNIO_Release_rqst(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODReleaseReq */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO release response */
|
|
static int
|
|
dissect_IPNIO_Release_resp(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODReleaseRes */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO control request */
|
|
static int
|
|
dissect_IPNIO_Control_rqst(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODControlReq */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO control response */
|
|
static int
|
|
dissect_IPNIO_Control_resp(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
|
|
offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODControlRes */
|
|
offset = dissect_blocks(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO read request */
|
|
static int
|
|
dissect_IPNIO_Read_rqst(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODReadReq */
|
|
offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO read response */
|
|
static int
|
|
dissect_IPNIO_Read_resp(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
gint remain;
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
/* IODReadHeader */
|
|
offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
|
|
|
|
/* XXX - RecordDataRead: dissection not yet implemented */
|
|
remain = tvb_length_remaining(tvb, offset);
|
|
proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, remain, "data", "User Data: %d bytes", remain);
|
|
offset += remain;
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
static int
|
|
dissect_IODWriteReq(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
gint remain;
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
|
|
/* IODWriteHeader */
|
|
offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
|
|
|
|
|
|
/* IODWriteMultipleReq? */
|
|
if(u16Index == 0xe040) {
|
|
while((remain = tvb_length_remaining(tvb, offset)) > 0) {
|
|
offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep);
|
|
}
|
|
} else {
|
|
/* RecordDataWrite */
|
|
/* XXX - dissection not yet implemented */
|
|
proto_tree_add_string_format(tree, hf_pn_io_data, tvb, offset, u32RecDataLen, "data", "RecordDataWrite: %d bytes", u32RecDataLen);
|
|
offset += u32RecDataLen;
|
|
|
|
/* XXX - add padding (required with IODWriteMultipleReq) */
|
|
switch(offset % 4) {
|
|
case(3):
|
|
offset += 1;
|
|
break;
|
|
case(2):
|
|
offset += 2;
|
|
break;
|
|
case(1):
|
|
offset += 3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/* dissect a PN-IO write request */
|
|
static int
|
|
dissect_IPNIO_Write_rqst(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
dissect_IODWriteRes(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
gint remain;
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
|
|
/* IODWriteResHeader */
|
|
offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen);
|
|
|
|
/* IODWriteMultipleRes? */
|
|
if(u16Index == 0xe040) {
|
|
while((remain = tvb_length_remaining(tvb, offset)) > 0) {
|
|
offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
|
|
}
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO write response */
|
|
static int
|
|
dissect_IPNIO_Write_resp(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16Index = 0;
|
|
|
|
offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, drep);
|
|
|
|
offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect the IOxS (IOCS, IOPS) field */
|
|
static int
|
|
dissect_PNIO_IOxS(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_)
|
|
{
|
|
guint8 u8IOxS;
|
|
proto_item *ioxs_item = NULL;
|
|
proto_tree *ioxs_tree = NULL;
|
|
|
|
|
|
u8IOxS = tvb_get_guint8(tvb, offset);
|
|
|
|
/* add ioxs subtree */
|
|
ioxs_item = proto_tree_add_uint_format(tree, hf_pn_io_ioxs,
|
|
tvb, offset, 1, u8IOxS,
|
|
"IOxS: 0x%02x (%s%s)",
|
|
u8IOxS,
|
|
(u8IOxS & 0x01) ? "another IOxS follows " : "",
|
|
(u8IOxS & 0x80) ? "good" : "bad");
|
|
ioxs_tree = proto_item_add_subtree(ioxs_item, ett_pn_io_ioxs);
|
|
|
|
proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_extension, tvb, offset, 1, u8IOxS);
|
|
proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_res14, tvb, offset, 1, u8IOxS);
|
|
proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_instance, tvb, offset, 1, u8IOxS);
|
|
proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_datastate, tvb, offset, 1, u8IOxS);
|
|
|
|
return offset + 1;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO Cyclic Service Data Unit (on top of PN-RT protocol) */
|
|
static int
|
|
dissect_PNIO_C_SDU(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
proto_item *data_item;
|
|
proto_tree *data_tree;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO");
|
|
|
|
if(tree) {
|
|
data_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_length(tvb),
|
|
"PROFINET IO Cyclic Service Data Unit: %u bytes", tvb_length(tvb));
|
|
data_tree = proto_item_add_subtree(data_item, ett_pn_io_rtc);
|
|
|
|
offset = dissect_PNIO_IOxS(tvb, offset, pinfo, data_tree, drep);
|
|
|
|
/* XXX - dissect the remaining data */
|
|
/* this will be one or more DataItems followed by an optional GAP and RTCPadding */
|
|
/* as we don't have the required context information to dissect the specific DataItems, this will be tricky :-( */
|
|
data_item = proto_tree_add_protocol_format(data_tree, proto_pn_io, tvb, offset, tvb_length_remaining(tvb, offset),
|
|
"Data: %u bytes (including GAP and RTCPadding)", tvb_length_remaining(tvb, offset));
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* dissect a PN-IO RTA PDU (on top of PN-RT protocol) */
|
|
static int
|
|
dissect_PNIO_RTA(tvbuff_t *tvb, int offset,
|
|
packet_info *pinfo, proto_tree *tree, guint8 *drep)
|
|
{
|
|
guint16 u16AlarmDstEndpoint;
|
|
guint16 u16AlarmSrcEndpoint;
|
|
guint8 u8PDUType;
|
|
guint8 u8PDUVersion;
|
|
guint8 u8WindowSize;
|
|
guint8 u8Tack;
|
|
guint16 u16SendSeqNum;
|
|
guint16 u16AckSeqNum;
|
|
guint16 u16VarPartLen;
|
|
int start_offset = offset;
|
|
guint16 u16Index = 0;
|
|
guint32 u32RecDataLen;
|
|
|
|
|
|
proto_item *rta_item;
|
|
proto_tree *rta_tree;
|
|
|
|
proto_item *sub_item;
|
|
proto_tree *sub_tree;
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_add_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-AL");
|
|
|
|
rta_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_length(tvb),
|
|
"PROFINET IO Alarm");
|
|
rta_tree = proto_item_add_subtree(rta_item, ett_pn_io_rta);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
|
|
hf_pn_io_alarm_dst_endpoint, &u16AlarmDstEndpoint);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
|
|
hf_pn_io_alarm_src_endpoint, &u16AlarmSrcEndpoint);
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: 0x%x, Dst: 0x%x",
|
|
u16AlarmSrcEndpoint, u16AlarmDstEndpoint);
|
|
|
|
/* PDU type */
|
|
sub_item = proto_tree_add_item(rta_tree, hf_pn_io_pdu_type, tvb, offset, 1, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type);
|
|
dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_pdu_type_type, &u8PDUType);
|
|
u8PDUType &= 0x0F;
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_pdu_type_version, &u8PDUVersion);
|
|
u8PDUVersion >>= 4;
|
|
proto_item_append_text(sub_item, ", Type: %s, Version: %u",
|
|
val_to_str(u8PDUType, pn_io_pdu_type, "Unknown"),
|
|
u8PDUVersion);
|
|
|
|
/* additional flags */
|
|
sub_item = proto_tree_add_item(rta_tree, hf_pn_io_add_flags, tvb, offset, 1, FALSE);
|
|
sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_add_flags);
|
|
dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_window_size, &u8WindowSize);
|
|
u8WindowSize &= 0x0F;
|
|
offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep,
|
|
hf_pn_io_tack, &u8Tack);
|
|
u8Tack >>= 4;
|
|
proto_item_append_text(sub_item, ", Window Size: %u, Tack: %u",
|
|
u8WindowSize, u8Tack);
|
|
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
|
|
hf_pn_io_send_seq_num, &u16SendSeqNum);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
|
|
hf_pn_io_ack_seq_num, &u16AckSeqNum);
|
|
offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep,
|
|
hf_pn_io_var_part_len, &u16VarPartLen);
|
|
|
|
switch(u8PDUType & 0x0F) {
|
|
case(1): /* Data-RTA */
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", Data-RTA");
|
|
offset = dissect_block(tvb, offset, pinfo, rta_tree, drep, &u16Index, &u32RecDataLen);
|
|
break;
|
|
case(2): /* NACK-RTA */
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", NACK-RTA");
|
|
/* no additional data */
|
|
break;
|
|
case(3): /* ACK-RTA */
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", ACK-RTA");
|
|
/* no additional data */
|
|
break;
|
|
case(4): /* ERR-RTA */
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", ERR-RTA");
|
|
offset = dissect_PNIO_status(tvb, offset, pinfo, rta_tree, drep);
|
|
break;
|
|
default:
|
|
proto_tree_add_string_format(tree, hf_pn_io_data, tvb, 0, tvb_length(tvb), "data",
|
|
"PN-IO Alarm: unknown PDU type 0x%x", u8PDUType);
|
|
}
|
|
|
|
proto_item_set_len(rta_item, offset - start_offset);
|
|
|
|
return offset;
|
|
}
|
|
|
|
|
|
/* possibly dissect a PN-IO related PN-RT packet */
|
|
static gboolean
|
|
dissect_PNIO_heur(tvbuff_t *tvb,
|
|
packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
guint8 drep_data = 0;
|
|
guint8 *drep = &drep_data;
|
|
guint8 u8CBAVersion;
|
|
guint16 u16FrameID;
|
|
|
|
|
|
/* the sub tvb will NOT contain the frame_id here! */
|
|
u16FrameID = GPOINTER_TO_UINT(pinfo->private_data);
|
|
|
|
u8CBAVersion = tvb_get_guint8 (tvb, 0);
|
|
|
|
/* is this a PNIO class 2 data packet? */
|
|
/* frame id must be in valid range (cyclic Real-Time, class=2) */
|
|
if (u16FrameID >= 0x8000 && u16FrameID < 0xbf00) {
|
|
dissect_PNIO_C_SDU(tvb, 0, pinfo, tree, drep);
|
|
return TRUE;
|
|
}
|
|
|
|
/* is this a PNIO class 1 data packet? */
|
|
/* frame id must be in valid range (cyclic Real-Time, class=1) and
|
|
* first byte (CBA version field) has to be != 0x11 */
|
|
if (u16FrameID >= 0xc000 && u16FrameID < 0xfb00 && u8CBAVersion != 0x11) {
|
|
dissect_PNIO_C_SDU(tvb, 0, pinfo, tree, drep);
|
|
return TRUE;
|
|
}
|
|
|
|
/* is this a PNIO high priority alarm packet? */
|
|
if(u16FrameID == 0xfc01) {
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_add_str(pinfo->cinfo, COL_INFO, "Alarm High");
|
|
|
|
dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep);
|
|
return TRUE;
|
|
}
|
|
|
|
/* is this a PNIO low priority alarm packet? */
|
|
if(u16FrameID == 0xfe01) {
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
col_add_str(pinfo->cinfo, COL_INFO, "Alarm Low");
|
|
|
|
dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep);
|
|
return TRUE;
|
|
}
|
|
|
|
/* this PN-RT packet doesn't seem to be PNIO specific */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/* the PNIO dcerpc interface table */
|
|
static dcerpc_sub_dissector pn_io_dissectors[] = {
|
|
{ 0, "Connect", dissect_IPNIO_Connect_rqst, dissect_IPNIO_Connect_resp },
|
|
{ 1, "Release", dissect_IPNIO_Release_rqst, dissect_IPNIO_Release_resp },
|
|
{ 2, "Read", dissect_IPNIO_Read_rqst, dissect_IPNIO_Read_resp },
|
|
{ 3, "Write", dissect_IPNIO_Write_rqst, dissect_IPNIO_Write_resp },
|
|
{ 4, "Control", dissect_IPNIO_Control_rqst, dissect_IPNIO_Control_resp },
|
|
{ 0, NULL, NULL, NULL }
|
|
};
|
|
|
|
|
|
void
|
|
proto_register_pn_io (void)
|
|
{
|
|
static hf_register_info hf[] = {
|
|
{ &hf_pn_io_opnum,
|
|
{ "Operation", "pn_io.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_reserved16,
|
|
{ "Reserved", "pn_io.reserved16", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_array,
|
|
{ "Array", "pn_io.array", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_status,
|
|
{ "Status", "pn_io.status", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_args_max,
|
|
{ "ArgsMaximum", "pn_io.args_max", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_args_len,
|
|
{ "ArgsLength", "pn_io.args_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_array_max_count,
|
|
{ "MaximumCount", "pn_io.array_max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_array_offset,
|
|
{ "Offset", "pn_io.array_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_array_act_count,
|
|
{ "ActualCount", "pn_io.array_act_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_ar_type,
|
|
{ "ARType", "pn_io.ar_type", FT_UINT16, BASE_HEX, VALS(pn_io_ar_type), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_cminitiator_macadd,
|
|
{ "CMInitiatorMacAdd", "pn_io.cminitiator_mac_add", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_cminitiator_objectuuid,
|
|
{ "CMInitiatorObjectUUID", "pn_io.cminitiator_uuid", FT_STRING, BASE_DEC, 0x0, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_ar_properties,
|
|
{ "ARProperties", "pn_io.ar_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - 32 bitfield! */
|
|
{ &hf_pn_io_cminitiator_activitytimeoutfactor,
|
|
{ "CMInitiatorActivityTimeoutFactor", "pn_io.cminitiator_activitytimeoutfactor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_cminitiator_udprtport,
|
|
{ "CMInitiatorUDPRTPort", "pn_io.cminitiator_udprtport", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_station_name_length,
|
|
{ "StationNameLength", "pn_io.station_name_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_cminitiator_station_name,
|
|
{ "CMInitiatorStationName", "pn_io.cminitiator_station_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_cmresponder_macadd,
|
|
{ "CMResponderMacAdd", "pn_io.cmresponder_macadd", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_cmresponder_udprtport,
|
|
{ "CMResponderUDPRTPort", "pn_io.cmresponder_udprtport", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
|
|
{ &hf_pn_io_iocr_type,
|
|
{ "IOCRType", "pn_io.iocr_type", FT_UINT16, BASE_HEX, VALS(pn_io_iocr_type), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_iocr_reference,
|
|
{ "IOCRReference", "pn_io.iocr_reference", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_lt,
|
|
{ "LT", "pn_io.lt", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_iocr_properties,
|
|
{ "IOCRProperties", "pn_io.iocr_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - 32 bitfield! */
|
|
{ &hf_pn_io_data_length,
|
|
{ "DataLength", "pn_io.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_frame_id,
|
|
{ "FrameID", "pn_io.frame_id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_send_clock_factor,
|
|
{ "SendClockFactor", "pn_io.send_clock_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_reduction_ratio,
|
|
{ "ReductionRatio", "pn_io.reduction_ratio", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_phase,
|
|
{ "Phase", "pn_io.phase", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_sequence,
|
|
{ "Sequence", "pn_io.sequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_frame_send_offset,
|
|
{ "FrameSendOffset", "pn_io.frame_send_offset", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_watchdog_factor,
|
|
{ "WatchdogFactor", "pn_io.watchdog_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_data_hold_factor,
|
|
{ "DataHoldFactor", "pn_io.data_hold_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_iocr_tag_header,
|
|
{ "IOCRTagHeader", "pn_io.iocr_tag_header", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_iocr_multicast_mac_add,
|
|
{ "IOCRMulticastMACAdd", "pn_io.iocr_multicast_mac_add", FT_ETHER, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_number_of_apis,
|
|
{ "NumberOfAPIs", "pn_io.number_of_apis", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_number_of_io_data_objects,
|
|
{ "NumberOfIODataObjects", "pn_io.number_of_io_data_objects", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_io_data_object_frame_offset,
|
|
{ "IODataObjectFrameOffset", "pn_io.io_data_object_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_number_of_iocs,
|
|
{ "NumberOfIOCS", "pn_io.number_of_iocs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_iocs_frame_offset,
|
|
{ "IOCSFrameOffset", "pn_io.iocs_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_alarmcr_type,
|
|
{ "AlarmCRType", "pn_io.alarmcr_type", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_alarmcr_properties,
|
|
{ "AlarmCRProperties", "pn_io.alarmcr_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - 32 bitfield! */
|
|
{ &hf_pn_io_rta_timeoutfactor,
|
|
{ "RTATimeoutFactor", "pn_io.rta_timeoutfactor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_rta_retries,
|
|
{ "RTARetries", "pn_io.rta_retries", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - only values 3 - 15 allowed */
|
|
{ &hf_pn_io_localalarmref,
|
|
{ "LocalAlarmReference", "pn_io.localalarmref", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - special values */
|
|
{ &hf_pn_io_maxalarmdatalength,
|
|
{ "MaxAlarmDataLength", "pn_io.maxalarmdatalength", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, /* XXX - only values 200 - 1432 allowed */
|
|
{ &hf_pn_io_alarmcr_tagheaderhigh,
|
|
{ "AlarmCRTagHeaderHigh", "pn_io.alarmcr_tagheaderhigh", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - 16 bitfield! */
|
|
{ &hf_pn_io_alarmcr_tagheaderlow,
|
|
{ "AlarmCRTagHeaderLow", "pn_io.alarmcr_tagheaderlow", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}, /* XXX - 16 bitfield!*/
|
|
|
|
{ &hf_pn_io_api_tree,
|
|
{ "API", "pn_io.api", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_module_tree,
|
|
{ "Module", "pn_io.module", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_submodule_tree,
|
|
{ "Submodule", "pn_io.submodule", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_io_data_object,
|
|
{ "IODataObject", "pn_io.io_data_object", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_io_cs,
|
|
{ "IOCS", "pn_io.io_cs", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_ar_uuid,
|
|
{ "ARUUID", "pn_io.ar_uuid", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_api,
|
|
{ "API", "pn_io.api", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_slot_nr,
|
|
{ "SlotNumber", "pn_io.slot_nr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_subslot_nr,
|
|
{ "SubslotNumber", "pn_io.subslot_nr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_index,
|
|
{ "Index", "pn_io.index", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_seq_number,
|
|
{ "SeqNumber", "pn_io.seq_number", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_record_data_length,
|
|
{ "RecordDataLength", "pn_io.record_data_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_padding,
|
|
{ "Padding", "pn_io.padding", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_add_val1,
|
|
{ "AdditionalValue1", "pn_io.add_val1", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_add_val2,
|
|
{ "AdditionalValue2", "pn_io.add_val2", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block_header,
|
|
{ "BlockHeader", "pn_io.block_header", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block_type,
|
|
{ "BlockType", "pn_io.block_type", FT_UINT16, BASE_HEX, VALS(pn_io_block_type), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block_length,
|
|
{ "BlockLength", "pn_io.block_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block_version_high,
|
|
{ "BlockVersionHigh", "pn_io.block_version_high", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block_version_low,
|
|
{ "BlockVersionLow", "pn_io.block_version_low", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_sessionkey,
|
|
{ "SessionKey", "pn_io.session_key", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_control_command,
|
|
{ "ControlCommand", "pn_io.control_command", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_control_command_prmend,
|
|
{ "PrmEnd", "pn_io.control_command.prmend", FT_UINT16, BASE_DEC, NULL, 0x0001, "", HFILL }},
|
|
{ &hf_pn_io_control_command_applready,
|
|
{ "ApplicationReady", "pn_io.control_command.applready", FT_UINT16, BASE_DEC, NULL, 0x0002, "", HFILL }},
|
|
{ &hf_pn_io_control_command_release,
|
|
{ "Release", "pn_io.control_command.release", FT_UINT16, BASE_DEC, NULL, 0x0004, "", HFILL }},
|
|
{ &hf_pn_io_control_command_done,
|
|
{ "Done", "pn_io.control_command.done", FT_UINT16, BASE_DEC, NULL, 0x0008, "", HFILL }},
|
|
{ &hf_pn_io_control_block_properties,
|
|
{ "ControlBlockProperties", "pn_io.control_block_properties", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_error_code,
|
|
{ "ErrorCode", "pn_io.error_code", FT_UINT8, BASE_HEX, VALS(pn_io_error_code), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_error_decode,
|
|
{ "ErrorDecode", "pn_io.error_decode", FT_UINT8, BASE_HEX, VALS(pn_io_error_decode), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_error_code1,
|
|
{ "ErrorCode1", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_error_code2,
|
|
{ "ErrorCode2", "pn_io.error_code2", FT_UINT8, BASE_HEX, VALS(pn_io_error_code2), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_error_code1_pniorw,
|
|
{ "ErrorCode1 (PNIORW)", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1_pniorw), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_error_code1_pnio,
|
|
{ "ErrorCode1 (PNIO)", "pn_io.error_code1", FT_UINT8, BASE_HEX, VALS(pn_io_error_code1_pnio), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_block,
|
|
{ "Block", "pn_io.block", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_data,
|
|
{ "Undecoded Data", "pn_io.data", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_alarm_type,
|
|
{ "AlarmType", "pn_io.alarm_type", FT_UINT16, BASE_HEX, VALS(pn_io_alarm_type), 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_alarm_specifier,
|
|
{ "AlarmSpecifier", "pn_io.alarm_specifier", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_alarm_specifier_sequence,
|
|
{ "SequenceNumber", "pn_io.alarm_specifier.sequence", FT_UINT16, BASE_HEX, NULL, 0x07FF, "", HFILL }},
|
|
{ &hf_pn_io_alarm_specifier_channel,
|
|
{ "ChannelDiagnosis", "pn_io.alarm_specifier.channel", FT_UINT16, BASE_HEX, NULL, 0x0800, "", HFILL }},
|
|
{ &hf_pn_io_alarm_specifier_manufacturer,
|
|
{ "ManufacturerSpecificDiagnosis", "pn_io.alarm_specifier.manufacturer", FT_UINT16, BASE_HEX, NULL, 0x1000, "", HFILL }},
|
|
{ &hf_pn_io_alarm_specifier_submodule,
|
|
{ "SubmoduleDiagnosisState", "pn_io.alarm_specifier.submodule", FT_UINT16, BASE_HEX, NULL, 0x2000, "", HFILL }},
|
|
{ &hf_pn_io_alarm_specifier_ardiagnosis,
|
|
{ "ARDiagnosisState", "pn_io.alarm_specifier.ardiagnosis", FT_UINT16, BASE_HEX, NULL, 0x8000, "", HFILL }},
|
|
|
|
{ &hf_pn_io_alarm_dst_endpoint,
|
|
{ "AlarmDstEndpoint", "pn_io.alarm_dst_endpoint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_alarm_src_endpoint,
|
|
{ "AlarmSrcEndpoint", "pn_io.alarm_src_endpoint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_pdu_type,
|
|
{ "PDUType", "pn_io.pdu_type", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_pdu_type_type,
|
|
{ "Type", "pn_io.pdu_type.type", FT_UINT8, BASE_HEX, VALS(pn_io_pdu_type), 0x0F, "", HFILL }},
|
|
{ &hf_pn_io_pdu_type_version,
|
|
{ "Version", "pn_io.pdu_type.version", FT_UINT8, BASE_HEX, NULL, 0xF0, "", HFILL }},
|
|
{ &hf_pn_io_add_flags,
|
|
{ "AddFlags", "pn_io.add_flags", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_window_size,
|
|
{ "WindowSize", "pn_io.window_size", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }},
|
|
{ &hf_pn_io_tack,
|
|
{ "TACK", "pn_io.tack", FT_UINT8, BASE_HEX, NULL, 0xF0, "", HFILL }},
|
|
{ &hf_pn_io_send_seq_num,
|
|
{ "SendSeqNum", "pn_io.send_seq_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_ack_seq_num,
|
|
{ "AckSeqNum", "pn_io.ack_seq_num", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_var_part_len,
|
|
{ "VarPartLen", "pn_io.var_part_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_module_ident_number,
|
|
{ "ModuleIdentNumber", "pn_io.module_ident_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_submodule_ident_number,
|
|
{ "SubmoduleIdentNumber", "pn_io.submodule_ident_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_number_of_modules,
|
|
{ "NumberOfModules", "pn_io.number_of_modules", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_module_properties,
|
|
{ "ModuleProperties", "pn_io.module_properties", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_module_state,
|
|
{ "ModuleState", "pn_io.module_state", FT_UINT16, BASE_HEX, VALS(pn_io_module_state), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_number_of_submodules,
|
|
{ "NumberOfSubmodules", "pn_io.number_of_submodules", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_submodule_properties,
|
|
{ "SubmoduleProperties", "pn_io.submodule_properties", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_submodule_state,
|
|
{ "SubmoduleState", "pn_io.submodule_state", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_data_description_tree,
|
|
{ "DataDescription", "pn_io.data_description", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_data_description,
|
|
{ "DataDescription", "pn_io.data_description", FT_UINT16, BASE_HEX, VALS(pn_io_data_description), 0x0, "", HFILL }},
|
|
{ &hf_pn_io_submodule_data_length,
|
|
{ "SubmoduleDataLength", "pn_io.submodule_data_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_length_iocs,
|
|
{ "LengthIOCS", "pn_io.length_iocs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_length_iops,
|
|
{ "LengthIOPS", "pn_io.length_iops", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
|
|
{ &hf_pn_io_ioxs,
|
|
{ "IOxS", "pn_io.ioxs", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_ioxs_extension,
|
|
{ "Extension (1:another IOxS follows/0:no IOxS follows)", "pn_io.ioxs.extension", FT_UINT8, BASE_HEX, NULL, 0x01, "", HFILL }},
|
|
{ &hf_pn_io_ioxs_res14,
|
|
{ "Reserved (should be zero)", "pn_io.ioxs.res14", FT_UINT8, BASE_HEX, NULL, 0x1E, "", HFILL }},
|
|
{ &hf_pn_io_ioxs_instance,
|
|
{ "Instance (only valid, if DataState is bad)", "pn_io.ioxs.instance", FT_UINT8, BASE_HEX, VALS(pn_io_ioxs), 0x60, "", HFILL }},
|
|
{ &hf_pn_io_ioxs_datastate,
|
|
{ "DataState (1:good/0:bad)", "pn_io.ioxs.datastate", FT_UINT8, BASE_HEX, NULL, 0x80, "", HFILL }},
|
|
|
|
{ &hf_pn_io_address_resolution_properties,
|
|
{ "AddressResolutionProperties", "pn_io.address_resolution_properties", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_mci_timeout_factor,
|
|
{ "MCITimeoutFactor", "pn_io.mci_timeout_factor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
|
|
{ &hf_pn_io_provider_station_name,
|
|
{ "ProviderStationName", "pn_io.provider_station_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}
|
|
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
&ett_pn_io,
|
|
&ett_pn_io_block,
|
|
&ett_pn_io_block_header,
|
|
&ett_pn_io_status,
|
|
&ett_pn_io_rtc,
|
|
&ett_pn_io_rta,
|
|
&ett_pn_io_pdu_type,
|
|
&ett_pn_io_add_flags,
|
|
&ett_pn_io_control_command,
|
|
&ett_pn_io_ioxs,
|
|
&ett_pn_io_api,
|
|
&ett_pn_io_data_description,
|
|
&ett_pn_io_module,
|
|
&ett_pn_io_submodule,
|
|
&ett_pn_io_io_data_object,
|
|
&ett_pn_io_io_cs
|
|
};
|
|
|
|
proto_pn_io = proto_register_protocol ("PROFINET IO", "PNIO", "pn_io");
|
|
proto_register_field_array (proto_pn_io, hf, array_length (hf));
|
|
proto_register_subtree_array (ett, array_length (ett));
|
|
}
|
|
|
|
void
|
|
proto_reg_handoff_pn_io (void)
|
|
{
|
|
/* Register the protocols as dcerpc */
|
|
dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_device, ver_pn_io_device, pn_io_dissectors, hf_pn_io_opnum);
|
|
dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_controller, ver_pn_io_controller, pn_io_dissectors, hf_pn_io_opnum);
|
|
dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_supervisor, ver_pn_io_supervisor, pn_io_dissectors, hf_pn_io_opnum);
|
|
dcerpc_init_uuid (proto_pn_io, ett_pn_io, &uuid_pn_io_parameterserver, ver_pn_io_parameterserver, pn_io_dissectors, hf_pn_io_opnum);
|
|
|
|
heur_dissector_add("pn_rt", dissect_PNIO_heur, proto_pn_io);
|
|
}
|