2015-12-02 00:03:27 +00:00
/* packet-ecmp.c
*
* Copyright 2014 , James Lynch < lynch007 @ gmail . com > , Control Techniques
* Copyright 2015 , Luke Orehawa < lukeorehawa @ gmail . com > , Control Techniques
*
* Revisions :
* - James Lynch 2014 - 07 - 22
* - Initial plugin development
* - Luke Orehawa 2015 - 11 - 26
* - Removed commands not yet in released specification
* - All commands implemented are as V0 .26 of ECMP Specification
* - Modifications of code to meet Wireshark coding style and current APIs
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* 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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include "config.h"
# include <glib.h>
# include <epan/packet.h>
# include <epan/expert.h>
# include "packet-mbtcp.h"
# define PROTO_TAG_ECMP "ECMP"
void proto_reg_handoff_ecmp ( void ) ;
void proto_register_ecmp ( void ) ;
/* Wireshark ID of the ECMP protocol */
static int proto_ecmp = - 1 ;
/* Used to set Modbus protocol data */
static int proto_modbus = - 1 ;
/* These are the handles of our subdissectors */
static dissector_handle_t modbus_handle = NULL ;
/*stores the port number for our protocol (ECMP)*/
static const guint16 global_ecmp_port = 6160 ;
/*smallest size of a packet, number of bytes*/
static const gint ecmp_min_packet_size = 6 ;
/* ECMP request codes */
# define ECMP_COMMAND_IDENTIFY 0x00
2015-12-04 09:40:44 +00:00
# define ECMP_COMMAND_INFO 0x01
2015-12-02 00:03:27 +00:00
# define ECMP_COMMAND_INTERROGATE 0x02
2015-12-04 09:40:44 +00:00
# define ECMP_COMMAND_READ 0x10
2015-12-02 00:03:27 +00:00
# define ECMP_COMMAND_READWITHTYPE 0x11
2015-12-04 09:40:44 +00:00
# define ECMP_COMMAND_WRITE 0x12
2015-12-02 00:03:27 +00:00
# define ECMP_COMMAND_OBJECTINFO 0x13
# define ECMP_COMMAND_GETNEXTOBJECTS 0x14
# define ECMP_COMMAND_FILEOPEN 0x20
# define ECMP_COMMAND_FILEREAD 0x21
# define ECMP_COMMAND_FILEWRITE 0x22
# define ECMP_COMMAND_FILECLOSE 0x23
# define ECMP_COMMAND_FILEINFO 0x24
# define ECMP_COMMAND_FILEDELETE 0x25
# define ECMP_COMMAND_FILESTATE 0x26
# define ECMP_COMMAND_FILEPOS 0x27
# define ECMP_COMMAND_FILELIST 0x28
# define ECMP_COMMAND_FILEEXISTS 0x2a
# define ECMP_COMMAND_CYCLICLINK 0x31
# define ECMP_COMMAND_PROGRAMCONTROL 0x60
# define ECMP_COMMAND_PROGRAMSTATUS 0x61
# define ECMP_COMMAND_CYCLICFRAME 0x70
# define ECMP_COMMAND_TUNNELFRAME 0x73
# define ECMP_COMMAND_MODBUSPDU 0x74
/* cyclic display formats */
static const guint8 cyclic_display_byte_format = 0 ;
static const guint8 cyclic_display_word_format = 1 ;
static const guint8 cyclic_display_long_format = 2 ;
/* Addressing scheme Structure */
static const value_string address_scheme [ ] = {
{ 0 , " No Route " } ,
{ 1 , " Intercept " } ,
{ 2 , " Default Route " } ,
{ 3 , " Diagnostics " } ,
{ 4 , " Named " } ,
{ 0 , NULL }
/*other commands to be added */
} ;
/* Address Structure */
static const value_string diagnostic [ ] = {
{ 0 , " Status " } ,
{ 1 , " Alarm " } ,
{ 2 , " Network " } ,
{ 3 , " Application " } ,
{ 0 , NULL }
/*other commands to be added*/
} ;
/* Command Structure*/
static const value_string command_vals [ ] = {
{ 0x00 , " Identify " } ,
{ 0x01 , " Info " } ,
{ 0x02 , " Interrogate " } ,
{ 0x10 , " Read " } ,
{ 0x11 , " ReadWithType " } ,
{ 0x12 , " Write " } ,
{ 0x13 , " ObjectInfo " } ,
{ 0x14 , " GetNextObjects " } ,
{ 0x20 , " FileOpen " } ,
{ 0x21 , " FileRead " } ,
{ 0x22 , " FileWrite " } ,
{ 0x23 , " FileClose " } ,
{ 0x24 , " FileInfo " } ,
{ 0x25 , " FileDelete " } ,
{ 0x26 , " FileState " } ,
{ 0x27 , " FilePos " } ,
{ 0x28 , " FileList " } ,
{ 0x2A , " FileExists " } ,
{ 0x31 , " CyclicSetup " } ,
{ 0x60 , " ProgramControl " } ,
{ 0x61 , " ProgramStatus " } ,
{ 0x70 , " CyclicFrame " } ,
{ 0x73 , " TunnelFrame " } ,
{ 0x74 , " ModbusPDU " } ,
{ 0 , NULL }
/*other commands to be added*/
} ;
/* Command Structure for request/response */
static const value_string type_rr [ ] = {
{ 0 , " Request " } ,
{ 1 , " Response " } ,
{ 0 , NULL }
/*other commands to be added*/
} ;
/* Option Code structure*/
static const value_string option_code [ ] = {
{ 0 , " End of Options " } ,
{ 1 , " Dummy " } ,
{ 2 , " Process At " } ,
{ 3 , " Route to Custom Target " } ,
{ 0 , NULL }
/* other - "Unknown" */
} ;
/* Attribute type Structure */
static const value_string attribute [ ] = {
{ 0 , " Manufacturer Name " } ,
{ 1 , " Product Family " } ,
{ 2 , " Product Model " } ,
{ 3 , " Serial Number " } ,
{ 4 , " Order Number " } ,
{ 5 , " Date Code " } ,
{ 6 , " Device Name " } ,
{ 7 , " Version Summary " } ,
{ 8 , " Colour Codes " } ,
{ 0 , NULL }
/* other - Unknown*/
} ;
/* Status type Structure */
static const value_string status [ ] = {
{ 0 , " OK (no errors detected in request) " } ,
{ 1 , " OK, chunks follow " } ,
{ 2 , " Processing Request " } ,
{ - 1 , " Error - Slave not ready " } ,
{ - 2 , " Error - Request Too Long " } ,
{ - 3 , " Error - Chunking Error " } ,
{ 0 , NULL }
/* other - Unknown*/
} ;
/* Category (device) structure*/
static const value_string category [ ] = {
{ 0 , " Drive " } ,
{ 1 , " Option Module " } ,
{ 0 , NULL }
} ;
/* Cyclic data alignment */
static const value_string cyclic_align [ ] = {
{ 0 , " 8bit " } ,
{ 1 , " 8bit " } ,
{ 2 , " 16bit " } ,
{ 4 , " 32bit " } ,
{ 8 , " 64bit " } ,
{ 0 , NULL }
} ;
/* Cyclic data scheme */
static const value_string cyclic_scheme [ ] = {
{ 0 , " Standard " } ,
{ 1 , " Synchronised " } ,
{ 0 , NULL }
} ;
/* Parameter addressing scheme */
static const value_string parameter_address_scheme [ ] = {
{ 0 , " Standard " } ,
{ 1 , " Slot Specific " } ,
{ 3 , " Variable " } ,
{ 0 , NULL }
} ;
2015-12-02 01:35:23 +00:00
#if 0
2015-12-02 00:03:27 +00:00
static const value_string route_address_scheme [ ] = {
{ 1 , " Intercept " } ,
{ 2 , " DefaultRoute " } ,
{ 0 , NULL }
} ;
2015-12-02 01:35:23 +00:00
# endif
2015-12-02 00:03:27 +00:00
/* Parameter access status */
static const value_string parameter_access_status [ ] = {
{ 0 , " OK " } ,
{ 1 , " OK - Converted " } ,
{ 2 , " OK - Clamped " } ,
{ - 1 , " ERROR - Address Type " } ,
{ - 2 , " ERROR - Timeout " } ,
{ - 3 , " ERROR - Access Denied " } ,
{ - 4 , " ERROR - Does not exist " } ,
{ - 5 , " ERROR - Data Type " } ,
{ - 6 , " ERROR - Failed Read " } ,
{ - 7 , " ERROR - Failed Write " } ,
{ - 8 , " ERROR - Not Readable " } ,
{ - 9 , " ERROR - Not Writeable " } ,
{ - 10 , " ERROR - Over Range " } ,
{ - 11 , " ERROR - Request Invalid " } ,
{ - 12 , " ERROR - Response Too Big " } ,
{ - 13 , " ERROR - Decimal Place " } ,
{ 0 , NULL }
} ;
/* Parameter data types */
static const value_string parameter_data_types [ ] = {
{ 0 , " Boolean " } ,
{ 1 , " INT8 " } ,
{ 2 , " UINT8 " } ,
{ 3 , " INT16 " } ,
{ 4 , " UINT16 " } ,
{ 5 , " INT32 " } ,
{ 6 , " UINT32 " } ,
{ 7 , " INT64 " } ,
{ 8 , " UINT64 " } ,
{ 9 , " INT128 " } ,
{ 10 , " UINT128 " } ,
{ 20 , " SINGLE " } ,
{ 21 , " DOUBLE " } ,
{ 30 , " String ID " } ,
{ 31 , " String " } ,
{ 0 , NULL }
} ;
/* Info types */
static const value_string info_type [ ] = {
{ 0 , " No Information " } ,
{ 1 , " Lowest Numbered Parameter in Menu " } ,
{ 2 , " Highest Numbered Parameter in Menu " } ,
{ 3 , " Parameter Format " } ,
{ 4 , " Minimum Value allowed for Parameter " } ,
{ 5 , " Maximum Value allowed for Parameter " } ,
{ 6 , " Object Unit Information " } ,
{ 7 , " Data Type of Parameter " } ,
{ 0 , NULL }
} ;
/* Display formats */
static const value_string display_format [ ] = {
{ 0 , " Standard format " } ,
{ 1 , " Date format (xx,yy,zz) " } ,
{ 2 , " Time with seconds format (xx.yy.zz) " } ,
{ 3 , " Character format " } ,
{ 4 , " Binary format " } ,
{ 5 , " IP address format (www.xxx.yyy.zzz) " } ,
{ 6 , " MAC address format (AA:BB:CC:DD:EE:FF) " } ,
{ 7 , " Version number (ww.xx.yy.zz) " } ,
{ 8 , " Slot menu parameter format (x,yy,zzz) " } ,
{ 0 , NULL }
} ;
/* Format units */
static const value_string format_units [ ] = {
{ 0 , " No units " } ,
{ 1 , " Custom units " } ,
{ 2 , " Millimetres (mm) " } ,
{ 3 , " Metres (m) " } ,
{ 4 , " User units (UU) " } ,
{ 5 , " Revolutions (revs) " } ,
{ 6 , " Degrees (') " } ,
/* { 7, ""}, */
{ 8 , " General position unit " } ,
{ 9 , " Millimetres per second (mm/s) " } ,
{ 10 , " User units per millisecond (UU/ms) " } ,
{ 11 , " Revolutions per minute (Rpm) " } ,
{ 12 , " Hertz (Hz) " } ,
{ 13 , " Kilohertz (kHz) " } ,
{ 14 , " Megahertz (MHz) " } ,
{ 15 , " General speed unit (Hz, rpm, mm/s) " } ,
{ 16 , " Closed loop speed unit (rpm, mm/s) " } ,
{ 17 , " Seconds per one thousand millimetres per seconds (s/m/s) " } ,
{ 18 , " User units per millimetre per second (UU/mm/s) " } ,
{ 19 , " Seconds per one thousand revolution per minute (s/1000rpm) " } ,
{ 20 , " Seconds per one hundred hertz (s/100Hz) " } ,
{ 21 , " General acceleration unit " } ,
{ 22 , " Closed loop acceleration unit " } ,
{ 23 , " Seconds squared per one thousand millimetres per second (s^2/1000ms/s) " } ,
{ 24 , " Seconds squared per user units per millisecond (s^2/UU/ms " } ,
{ 25 , " Seconds squared per one thousand revolutions per minute (s^2/1000rpm) " } ,
{ 26 , " Seconds squared per one hundred hertz (s^2/100Hz) " } ,
{ 27 , " General jerk unit " } ,
{ 28 , " Closed loop jerk unit " } ,
{ 29 , " Messages per second (Msg/s) " } ,
{ 30 , " Hours (Hours) " } ,
{ 31 , " Minutes (Mins) " } ,
{ 32 , " Seconds (s) " } ,
{ 33 , " Milliseconds (ms) " } ,
{ 34 , " Microseconds (us) " } ,
{ 35 , " Nanoseconds (ns) " } ,
{ 36 , " Volts (V) " } ,
{ 37 , " Amperes (A) " } ,
{ 38 , " Ohms (Ohms) " } ,
{ 39 , " Millihenrys (mH) " } ,
{ 40 , " Kilowatts (kW) " } ,
{ 41 , " Kilo-Volt-Amps-Reactive (kVAr) " } ,
{ 42 , " Megawatt hours (MWh) " } ,
{ 43 , " Kilowatt hours (kWh) " } ,
{ 44 , " Degrees Celcius ('C) " } ,
{ 45 , " Reciprocal of degrees celcius (/'C) " } ,
{ 46 , " Kilogram-metres squared (kgm^2) " } ,
{ 47 , " Newton metres (Nm) " } ,
{ 48 , " Newton metres per ampere (Nm/A) " } ,
{ 49 , " open-circuit volts per 1000rpm (V/1000rpm) " } ,
{ 50 , " Bits (Bits) " } ,
{ 51 , " Bytes (Bytes) " } ,
{ 52 , " Kilobytes (kB) " } ,
{ 53 , " Megabytes (MB) " } ,
{ 54 , " Bits per second (Bit/s) " } ,
{ 55 , " Baud (Baud) " } ,
{ 56 , " Kilobaud (kBaud) " } ,
{ 57 , " Megabaud (MBaud) " } ,
{ 58 , " Poles (Poles) " } ,
{ 59 , " Percent (%) " } ,
{ 60 , " Volts per millisecond (V/ms) " } ,
{ 0 , NULL }
} ;
/* File status */
static const value_string file_status [ ] = {
{ 0 , " Processing " } ,
{ 1 , " OK " } ,
{ 2 , " OK - More Data " } ,
{ 3 , " OK - EOF " } ,
{ - 1 , " ERROR - File Handle " } ,
{ - 2 , " ERROR - Blocked " } ,
{ - 3 , " ERROR - Blocking Mode " } ,
{ - 4 , " ERROR - Not in Progress " } ,
{ - 5 , " ERROR - Not Found " } ,
{ - 6 , " ERROR - Read Only " } ,
{ - 7 , " ERROR - Write Only " } ,
{ - 8 , " ERROR - Not Created " } ,
{ - 9 , " ERROR - No Data " } ,
{ - 10 , " ERROR - Wrong Mode " } ,
{ - 11 , " ERROR - Too Big " } ,
{ - 12 , " ERROR - Protected " } ,
{ - 13 , " ERROR - CRC " } ,
{ - 14 , " ERROR - Length " } ,
{ - 15 , " ERROR - Too Many Open " } ,
{ - 16 , " ERROR - Invalid File " } ,
{ - 17 , " ERROR - Invalid Request " } ,
{ - 18 , " ERROR - No Append " } ,
{ - 19 , " ERROR - Invalid State " } ,
{ - 20 , " ERROR - Incompatible " } ,
{ - 21 , " ERROR - Uninitialized " } ,
{ 0 , NULL }
} ;
/* File status mode */
static const value_string file_status_mode [ ] = {
{ 0 , " Information " } ,
{ 1 , " Read " } ,
{ 2 , " Create " } ,
{ 3 , " Append " } ,
{ 4 , " New Directory " } ,
{ 0 , NULL }
} ;
/* File attributes */
static const value_string file_attributes [ ] = {
{ 0 , " File Length " } ,
{ 1 , " File Integrity " } ,
{ 2 , " Calculate CRC32 " } ,
{ 3 , " File Attributes " } ,
{ 4 , " Creation Date and Time " } ,
{ 5 , " Modification Date and Time " } ,
{ 0 , NULL }
} ;
/* File reference position */
static const value_string file_ref_point [ ] = {
{ 0 , " SoF - Start of file " } ,
{ 1 , " EoF - End of file " } ,
{ 2 , " Current - Use current file pointer " } ,
{ 0 , NULL }
} ;
static const value_string cyclic_setup_mode [ ] = {
{ 0 , " Create " } ,
{ 1 , " Edit " } ,
{ 2 , " Finalise " } ,
{ 3 , " Delete " } ,
{ 4 , " Exist " } ,
{ 5 , " List " } ,
{ 6 , " Info " } ,
{ 10 , " Set " } ,
{ 11 , " Get " } ,
{ 12 , " Get mappings " } ,
{ 0 , NULL }
} ;
static const value_string cyclic_attributes [ ] = {
{ 0 , " State " } ,
{ 1 , " Rx/Tx " } ,
{ 2 , " Synchronised " } ,
{ 3 , " MEC Offset " } ,
{ 4 , " Sample Period " } ,
{ 5 , " MEC Delay " } ,
{ 6 , " Data Change " } ,
{ 7 , " Rx Timeout Handler " } ,
{ 8 , " Rx Data Late Handler " } ,
{ 9 , " Transport Address " } ,
{ 10 , " Max Mappings " } ,
{ 11 , " Number Of Mappings " } ,
{ 12 , " Mapping Item " } ,
{ 13 , " Saveable " } ,
{ 128 , " Max RX Links " } ,
{ 129 , " Max TX Links " } ,
{ 130 , " Max Mappings Per Link " } ,
{ 131 , " Max Sync RX Links " } ,
{ 132 , " Max Sync TX Links " } ,
{ 133 , " Max Mappings Per Sync Link " } ,
{ 134 , " 'Process At' Queue Depth " } ,
{ 135 , " MEC Period " } ,
{ 0 , NULL }
} ;
static const value_string cyclic_setup_link_dir [ ] = {
{ 0 , " Rx " } ,
{ 1 , " Tx " } ,
{ 0 , NULL }
} ;
static const value_string cyclic_setup_link_exists [ ] = {
{ 0 , " Does not exist " } ,
{ 1 , " Exists " } ,
{ 0 , NULL }
} ;
static const value_string cyclic_link_req_resp [ ] = {
{ 0 , " Request " } ,
{ 1 , " Response " } ,
{ 0 , NULL }
} ;
static const value_string additional_scheme_vals [ ] = {
{ 0 , " None " } ,
{ 1 , " Generic " } ,
{ 0 , NULL }
} ;
/* Program Control - command codes */
static const value_string command_code_list [ ] = {
{ 0 , " Stop " } ,
{ 1 , " Start " } ,
{ 2 , " Reset " } ,
{ 0 , NULL }
/*other commands to be added*/
} ;
/* Program Control - sub command codes */
static const value_string sub_command_code_list [ ] = {
{ 0 , " Default " } ,
{ 1 , " User1 " } ,
{ 2 , " User2 " } ,
{ 0 , NULL }
/*other sub commands to be added*/
} ;
/* Program Control - status codes */
static const value_string status_list [ ] = {
{ 0 , " OK " } ,
{ - 1 , " Error " } ,
{ 0 , NULL }
/*other status to be added*/
} ;
/* Program Status - running state codes */
static const value_string running_state_list [ ] = {
{ 0 , " Stopped " } ,
{ 1 , " Running " } ,
{ 2 , " Exception " } ,
{ 3 , " None (no program found in device) " } ,
{ 0 , NULL }
/*other status to be added*/
} ;
/* Interrogate - command support states */
static const value_string Interrogate_support_state [ ] = {
{ 0 , " Not Supported " } ,
{ 1 , " Supported " } ,
{ 0 , NULL }
/*other status to be added*/
} ;
/* Interrogate - command / option states */
static const value_string Interrogate_command_option_state [ ] = {
{ 0 , " Command " } ,
{ 1 , " Option " } ,
{ 0 , NULL }
/*other status to be added*/
} ;
static const value_string item_type_vals [ ] = {
{ 0 , " File " } ,
{ 1 , " Directory " } ,
{ 0 , NULL }
} ;
static const value_string file_integrity_vals [ ] = {
{ 0 , " Error " } ,
{ 1 , " OK " } ,
{ 0 , NULL }
} ;
2015-12-02 01:35:23 +00:00
#if 0
2015-12-02 00:03:27 +00:00
static const true_false_string tfs_not_expected_expected = { " Odd " , " Even " } ;
2015-12-02 01:35:23 +00:00
# endif
2015-12-02 00:03:27 +00:00
/* The following hf_* variables are used to hold the Wireshark IDs of
* our header fields ; they are filled out when we call
* proto_register_field_array ( ) in proto_register_ecmp ( )
*/
static gint hf_ecmp_command = - 1 ;
static gint hf_ecmp_destination_address = - 1 ;
static gint hf_ecmp_source_address = - 1 ;
static gint hf_ecmp_diagnostic = - 1 ;
static gint hf_ecmp_type_rr = - 1 ;
static gint hf_ecmp_chunking = - 1 ;
static gint hf_ecmp_max_response_size = - 1 ;
static gint hf_ecmp_category = - 1 ;
static gint hf_ecmp_option = - 1 ;
static gint hf_ecmp_attribute = - 1 ;
static gint hf_ecmp_no_of_attributes = - 1 ;
static gint hf_ecmp_chunk_id = - 1 ;
static gint hf_ecmp_transaction_id = - 1 ;
static gint hf_ecmp_status = - 1 ;
static gint hf_ecmp_drive_type = - 1 ;
static gint hf_ecmp_drive_derivative = - 1 ;
static gint hf_ecmp_drive_factory_fit_category_id = - 1 ;
static gint hf_ecmp_category_id = - 1 ;
static gint hf_ecmp_attribute_string = - 1 ;
static gint hf_ecmp_file_name = - 1 ;
static gint hf_ecmp_info_command = - 1 ;
static gint hf_ecmp_directory = - 1 ;
static gint hf_ecmp_names_scheme = - 1 ;
static gint hf_ecmp_variable_name = - 1 ;
static gint hf_ecmp_unit_id_string = - 1 ;
static gint hf_ecmp_ecmp_string = - 1 ;
static gint hf_ecmp_process_time = - 1 ;
static gint hf_ecmp_cyclic_frame_time = - 1 ;
static gint hf_ecmp_grandmaster = - 1 ;
static gint hf_ecmp_data = - 1 ;
static gint hf_ecmp_response_data = - 1 ;
static gint hf_ecmp_cyclic_link_num = - 1 ;
static gint hf_ecmp_cyclic_align = - 1 ;
static gint hf_ecmp_cyclic_scheme = - 1 ;
static gint hf_ecmp_cyclic_link_number_display = - 1 ;
/* Cyclic setup */
static gint hf_ecmp_cyclic_setup_mode = - 1 ;
static gint hf_ecmp_cyclic_setup_linkno = - 1 ;
static gint hf_ecmp_cyclic_setup_dir = - 1 ;
static gint hf_ecmp_cyclic_setup_attrib_count = - 1 ;
static gint hf_ecmp_cyclic_setup_rsp_status = - 1 ;
static gint hf_ecmp_cyclic_setup_rsp_err_idx = - 1 ;
static gint hf_ecmp_cyclic_setup_attrib = - 1 ;
static gint hf_ecmp_cyclic_setup_link_exists = - 1 ;
static gint hf_ecmp_cyclic_link_req_resp = - 1 ;
/*for info command */
static gint hf_ecmp_buffer_size = - 1 ;
static gint hf_ecmp_max_response = - 1 ;
static gint hf_ecmp_max_handle = - 1 ;
static gint hf_ecmp_info_address = - 1 ;
/*for parameter access commands*/
static gint hf_ecmp_parameter_address = - 1 ;
static gint hf_ecmp_number_of_parameter_definitions = - 1 ;
static gint hf_ecmp_number_of_parameter_responses = - 1 ;
static gint hf_ecmp_parameter_status = - 1 ;
static gint hf_ecmp_data_type = - 1 ;
static gint hf_ecmp_info_type = - 1 ;
/* for file access commands */
static gint hf_ecmp_file_status = - 1 ;
static gint hf_ecmp_file_handle = - 1 ;
static gint hf_ecmp_file_attributes = - 1 ;
static gint hf_ecmp_file_ref_point = - 1 ;
/* for tunnel frame command */
# define TUNNEL_START_FLAG 0x01
2015-12-04 09:40:44 +00:00
# define TUNNEL_END_FLAG 0x02
# define TUNNEL_CHECK_OUTPUT_FLAG 0x04
2015-12-02 00:03:27 +00:00
static gint hf_ecmp_tunnel_control = - 1 ;
static gint hf_ecmp_tunnel_start_flag = - 1 ;
static gint hf_ecmp_tunnel_end_flag = - 1 ;
static gint hf_ecmp_tunnel_check_output_flag = - 1 ;
static gint hf_ecmp_tunnel_size = - 1 ;
/* Generated from convert_proto_tree_add_text.pl */
static int hf_ecmp_physical_address = - 1 ;
static int hf_ecmp_logical_address = - 1 ;
static int hf_ecmp_primary_colour = - 1 ;
static int hf_ecmp_secondary_colour = - 1 ;
static int hf_ecmp_number_of_subsequent_object_requests = - 1 ;
static int hf_ecmp_number_of_decimal_places = - 1 ;
static int hf_ecmp_no_information_available = - 1 ;
static int hf_ecmp_param_format_bit_default_unipolar = - 1 ;
static int hf_ecmp_param_format_write_allowed = - 1 ;
static int hf_ecmp_param_format_read_not_allowed = - 1 ;
static int hf_ecmp_param_format_protected_from_destinations = - 1 ;
static int hf_ecmp_param_format_parameter_not_visible = - 1 ;
static int hf_ecmp_param_format_not_clonable = - 1 ;
static int hf_ecmp_param_format_voltage_or_current_rating_dependant = - 1 ;
static int hf_ecmp_param_format_parameter_has_no_default = - 1 ;
static int hf_ecmp_param_format_number_of_decimal_places = - 1 ;
static int hf_ecmp_param_format_variable_maximum_and_minimum = - 1 ;
static int hf_ecmp_param_format_string_parameter = - 1 ;
static int hf_ecmp_param_format_desitination_set_up_parameter = - 1 ;
static int hf_ecmp_param_format_filtered_when_displayed = - 1 ;
static int hf_ecmp_param_format_pseudo_read_only = - 1 ;
static int hf_ecmp_param_format_display_format = - 1 ;
static int hf_ecmp_param_format_floating_point_value = - 1 ;
static int hf_ecmp_param_format_units = - 1 ;
static int hf_ecmp_string_id = - 1 ;
static int hf_ecmp_address_scheme_menu = - 1 ;
static int hf_ecmp_address_scheme_parameter = - 1 ;
static int hf_ecmp_address_scheme_slot = - 1 ;
static int hf_ecmp_address_scheme_null_byte_size = - 1 ;
static int hf_ecmp_display_unit_id = - 1 ;
static int hf_ecmp_data_boolean = - 1 ;
static int hf_ecmp_data_int8 = - 1 ;
static int hf_ecmp_data_uint8 = - 1 ;
static int hf_ecmp_data_int16 = - 1 ;
static int hf_ecmp_data_uint16 = - 1 ;
static int hf_ecmp_data_int32 = - 1 ;
static int hf_ecmp_data_uint32 = - 1 ;
static int hf_ecmp_data_int64 = - 1 ;
static int hf_ecmp_data_uint64 = - 1 ;
static int hf_ecmp_data_float = - 1 ;
static int hf_ecmp_data_double = - 1 ;
static int hf_ecmp_access_mode = - 1 ;
static int hf_ecmp_open_in_non_blocking_mode = - 1 ;
static int hf_ecmp_open_file_relative_to_specified_directory_handle = - 1 ;
static int hf_ecmp_file_access_mode = - 1 ;
static int hf_ecmp_additional_scheme = - 1 ;
static int hf_ecmp_scheme_data_length = - 1 ;
static int hf_ecmp_number_of_requested_bytes = - 1 ;
static int hf_ecmp_number_of_bytes_transferred = - 1 ;
static int hf_ecmp_crc = - 1 ;
static int hf_ecmp_ref_offset = - 1 ;
static int hf_ecmp_number_of_files_to_list = - 1 ;
static int hf_ecmp_file_hash = - 1 ;
static int hf_ecmp_item_type = - 1 ;
static int hf_ecmp_file_integrity = - 1 ;
static int hf_ecmp_display_attr_read_only = - 1 ;
static int hf_ecmp_display_attr_hidden = - 1 ;
static int hf_ecmp_display_attr_system = - 1 ;
static int hf_ecmp_display_attr_volume_label = - 1 ;
static int hf_ecmp_display_attr_subdirectory = - 1 ;
static int hf_ecmp_display_attr_archive = - 1 ;
static int hf_ecmp_display_creation = - 1 ;
static int hf_ecmp_display_modification = - 1 ;
static int hf_ecmp_interrogate_item_type = - 1 ;
static int hf_ecmp_interrogate_count = - 1 ;
static int hf_ecmp_modbus_pdu_size = - 1 ;
/* static int hf_ecmp_destination_scheme = -1; */
static int hf_ecmp_program_control_target = - 1 ;
static int hf_ecmp_program_control_command = - 1 ;
static int hf_ecmp_program_control_sub_command = - 1 ;
static int hf_ecmp_program_control_status = - 1 ;
static int hf_ecmp_program_status_target = - 1 ;
static int hf_ecmp_program_status_status = - 1 ;
static int hf_ecmp_program_status_additional_items = - 1 ;
static int hf_ecmp_cyclic_setup_max_mappings = - 1 ;
static int hf_ecmp_cyclic_setup_start_offset = - 1 ;
static int hf_ecmp_cyclic_setup_tx_count = - 1 ;
static int hf_ecmp_cyclic_setup_rx_count = - 1 ;
static int hf_ecmp_udp_alignment = - 1 ;
static int hf_ecmp_udp_scheme = - 1 ;
static int hf_ecmp_cyclic_data = - 1 ;
static int hf_ecmp_version_summary = - 1 ;
static int hf_ecmp_min_param_menu = - 1 ;
static int hf_ecmp_max_param_menu = - 1 ;
static int hf_ecmp_file_length = - 1 ;
static int hf_ecmp_mec_offset = - 1 ;
static int hf_ecmp_sample_period = - 1 ;
static int hf_ecmp_rx_timeout = - 1 ;
static int hf_ecmp_rx_action = - 1 ;
static int hf_ecmp_rx_event_destination = - 1 ;
static int hf_ecmp_rx_event = - 1 ;
static int hf_ecmp_rx_late_handler_action = - 1 ;
static int hf_ecmp_rx_late_handler_event_destination = - 1 ;
static int hf_ecmp_rx_late_handler_event = - 1 ;
static int hf_ecmp_transport_addr_scheme = - 1 ;
static int hf_ecmp_transport_addr = - 1 ;
static int hf_ecmp_mapping_item_offset = - 1 ;
static int hf_ecmp_mapping_item_scheme = - 1 ;
static int hf_ecmp_setup_attribute = - 1 ;
static int hf_ecmp_mec_period = - 1 ;
static int hf_ecmp_interrogate_command = - 1 ;
/************************************************************/
/* These are the ids of the subtrees that we may be creating */
static gint ett_ecmp = - 1 ;
static gint ett_ecmp_address = - 1 ;
static gint ett_ecmp_response_size = - 1 ;
static gint ett_ecmp_command = - 1 ;
static gint ett_ecmp_category = - 1 ;
static gint ett_ecmp_option = - 1 ;
static gint ett_ecmp_option_data = - 1 ;
static gint ett_ecmp_attribute = - 1 ;
static gint ett_ecmp_attribute_data = - 1 ;
static gint ett_ecmp_cyclic_scheme = - 1 ;
static gint ett_ecmp_info_type = - 1 ;
2015-12-04 09:40:44 +00:00
static gint ett_ecmp_info_count = - 1 ;
2015-12-02 00:03:27 +00:00
static gint ett_ecmp_interrogate_message = - 1 ;
static gint ett_ecmp_param_address = - 1 ;
static gint ett_ecmp_access_mode = - 1 ;
static gint ett_ecmp_access_file = - 1 ;
static gint ett_ecmp_file_read = - 1 ;
static gint ett_ecmp_file_write = - 1 ;
static gint ett_ecmp_file_info = - 1 ;
static gint ett_ecmp_file_info_att = - 1 ;
static gint ett_ecmp_file_position = - 1 ;
static gint ett_ecmp_file_list_no = - 1 ;
static gint ett_ecmp_file_list = - 1 ;
static gint ett_ecmp_tunnel_3s_goodframe = - 1 ;
static gint ett_ecmp_tunnel_3s_size = - 1 ;
static gint ett_ecmp_tunnel_3s_service = - 1 ;
static gint ett_cyclic_setup_attribs = - 1 ;
static gint ett_cyclic_setup_attrib_item = - 1 ;
static gint ett_cyclic_setup_transport_addr = - 1 ;
static gint ett_ecmp_cyclic_data_32_bit_display = - 1 ;
static gint ett_ecmp_cyclic_data_16_bit_display = - 1 ;
static gint ett_ecmp_cyclic_data_8_bit_display = - 1 ;
static gint ett_ecmp_modbus_pdu_message = - 1 ;
static gint ett_ecmp_program_control_message = - 1 ;
static gint ett_ecmp_program_status_message = - 1 ;
static expert_field ei_ecmp_unknown_command = EI_INIT ;
static expert_field ei_ecmp_color = EI_INIT ;
static expert_field ei_ecmp_option = EI_INIT ;
static expert_field ei_ecmp_item_type = EI_INIT ;
static expert_field ei_ecmp_options_not_implemented = EI_INIT ;
static expert_field ei_ecmp_info_type = EI_INIT ;
static expert_field ei_ecmp_attribute_type = EI_INIT ;
static expert_field ei_ecmp_parameter_addressing_scheme = EI_INIT ;
static expert_field ei_ecmp_data_type = EI_INIT ;
/*--------------------------------------------------------------------*/
/* General Commands and Framing Dissectors */
/*--------------------------------------------------------------------*/
/*a function to add the initial information about the transport layer (the first bits)*/
static int add_transport_layer_frame ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree , int addr_type )
{
proto_item * ecmp_address_item = NULL ;
proto_tree * ecmp_address_tree = NULL ;
guint8 byte_test ;
ecmp_address_item = proto_tree_add_item ( ecmp_tree , addr_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
byte_test = tvb_get_guint8 ( tvb , offset ) ;
if ( ( byte_test ! = 0 ) & & ( byte_test ! = 1 ) ) {
/* tree to display the data in the address*/
ecmp_address_tree = proto_item_add_subtree ( ecmp_address_item , ett_ecmp_address ) ;
switch ( byte_test )
{
case 2 : /* default route scheme*/
offset + + ;
/* displays the values of the addresses*/
proto_tree_add_item ( ecmp_address_tree , hf_ecmp_physical_address , tvb , offset , 1 , ENC_NA ) ;
proto_tree_add_item ( ecmp_address_tree , hf_ecmp_logical_address , tvb , offset , 1 , ENC_NA ) ;
break ;
case 3 : /* diagnostic scheme*/
proto_tree_add_item ( ecmp_address_tree , hf_ecmp_diagnostic , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
break ;
case 4 : /* Names scheme */
/* Calls a function to display the UTF-8 string data*/
proto_tree_add_item ( ecmp_address_tree , hf_ecmp_names_scheme , tvb , offset , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset ) + 2 ) ;
break ;
}
}
offset + + ;
return offset ;
}
/* a function to display option codes */
static int add_option_codes ( int offset , packet_info * pinfo , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_option_number_item = NULL ;
proto_item * ecmp_option_item ;
proto_tree * ecmp_option_tree ;
proto_tree * ecmp_option_data_tree = NULL ;
guint8 option_code_display = 0 ;
guint16 count = 0 ; /* number of times the loop iterates*/
int start_offset ;
gboolean more_options = TRUE ;
offset + + ;
start_offset = offset ;
ecmp_option_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 1 , ett_ecmp_option , & ecmp_option_number_item , " Options " ) ;
/* Loop to display all options */
while ( more_options ) /* loops until option code is 0*/
{
option_code_display = tvb_get_guint8 ( tvb , offset ) ;
ecmp_option_item = proto_tree_add_item ( ecmp_option_tree , hf_ecmp_option , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
switch ( option_code_display )
{
case 0 : /* end of options*/
proto_item_append_text ( ecmp_option_number_item , " : %d " , count ) ;
proto_item_set_len ( ecmp_option_number_item , offset - start_offset ) ;
more_options = FALSE ;
break ;
case 1 : /* dummy - 0 bytes of data */
break ;
case 2 : /* process at - 8 bytes of data */
ecmp_option_data_tree = proto_item_add_subtree ( ecmp_option_item , ett_ecmp_option_data ) ;
proto_tree_add_item ( ecmp_option_data_tree , hf_ecmp_process_time , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
break ;
default : /* Option that is not recognised*/
proto_item_append_text ( ecmp_option_number_item , " %d " , count ) ;
expert_add_info ( pinfo , ecmp_option_number_item , & ei_ecmp_option ) ;
break ;
}
count + + ;
}
return offset ;
}
/* a function to display attributes */
static void add_attributes ( packet_info * pinfo , int offset , tvbuff_t * tvb , proto_tree * ecmp_tree , gboolean request )
{
proto_item * ecmp_attribute_number_item = NULL ;
proto_item * ecmp_attribute_item = NULL , * color_item ;
proto_tree * ecmp_attribute_tree = NULL ;
proto_tree * ecmp_attribute_data_tree = NULL ;
guint8 no_of_attributes = 0 ;
guint8 a = 0 ; /*values used for looping*/
guint8 b = 0 ;
guint8 c = 0 ;
guint8 check = 0 ;
guint16 att_length = 0 ;
guint32 color ;
gchar * pStr = NULL ; /*char array for version string output*/
int start_offset = offset ;
/*display the number of attributes*/
ecmp_attribute_number_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_no_of_attributes , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_attribute_tree = proto_item_add_subtree ( ecmp_attribute_number_item , ett_ecmp_attribute ) ;
no_of_attributes = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
for ( a = 0 ; a < no_of_attributes ; a + + , offset + + ) {
/*attribute header*/
ecmp_attribute_item = proto_tree_add_item ( ecmp_attribute_tree , hf_ecmp_attribute , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_attribute_data_tree = proto_item_add_subtree ( ecmp_attribute_item , ett_ecmp_attribute_data ) ;
if ( ! request ) {
/*code for dissecting the colour codes attribute*/
switch ( tvb_get_guint8 ( tvb , offset ) )
{
case 8 :
offset + = 1 ;
/*get length of attribute for error checking*/
offset + = 2 ;
/*output primary colour codes- the two bytes representing each colour are output as integers*/
color = tvb_get_ntohl ( tvb , offset ) ;
color_item = proto_tree_add_uint_format_value ( ecmp_attribute_data_tree , hf_ecmp_primary_colour , tvb , offset , 4 , color , " (red) %d (green) %d (blue) %d " , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) , tvb_get_guint8 ( tvb , offset + 3 ) ) ;
if ( ( color & 0xFF000000 ) ! = 0 ) {
/*error check for correct colour code format */
expert_add_info ( pinfo , color_item , & ei_ecmp_color ) ;
}
offset + = 4 ;
/*output secondary colour codes- the two bytes representing each colour are output as integers*/
color = tvb_get_ntohl ( tvb , offset ) ;
color_item = proto_tree_add_uint_format_value ( ecmp_attribute_data_tree , hf_ecmp_secondary_colour , tvb , offset , 4 , color , " (red) %d (green) %d (blue) %d " , tvb_get_guint8 ( tvb , offset + 1 ) , tvb_get_guint8 ( tvb , offset + 2 ) , tvb_get_guint8 ( tvb , offset + 3 ) ) ;
if ( ( color & 0xFF000000 ) ! = 0 ) {
/*error check for correct colour code format */
expert_add_info ( pinfo , color_item , & ei_ecmp_color ) ;
}
offset + = 4 ;
break ;
/*code for dissecting the version summary attribute*/
case 7 :
offset + + ;
att_length = tvb_get_ntohs ( tvb , offset ) ;
pStr = ( gchar * ) wmem_alloc ( wmem_packet_scope ( ) , att_length + 1 ) ; /* 100 char buffer */
b = 0 ;
offset + = 2 ;
if ( pStr ! = NULL ) {
for ( c = 0 ; c < att_length ; c + + , offset + + ) {
check = tvb_get_guint8 ( tvb , offset ) ;
if ( ( check = = ' V ' ) | | ( check = = ' # ' ) | | ( check = = ' @ ' ) ) {
pStr [ b ] = ' ' ;
b + + ;
} else if ( tvb_get_guint8 ( tvb , offset ) = = ( ' ; ' ) ) {
pStr [ b ] = 0 ;
/*display version summary parameter, e.g 'FW', 'BL', 'HW'*/
proto_tree_add_string ( ecmp_attribute_data_tree , hf_ecmp_version_summary , tvb , offset - b , b , pStr ) ;
b = 0 ;
} else {
pStr [ b ] = ( gchar ) tvb_get_guint8 ( tvb , offset ) ;
b + + ;
}
}
pStr [ b ] = 0 ;
/*display last version summary parameter, e.g 'FW', 'BL', 'HW' as no deliminator to check for, just prints out rest of version string*/
proto_tree_add_string ( ecmp_attribute_data_tree , hf_ecmp_version_summary , tvb , offset - b , b , pStr ) ;
offset - = 1 ;
}
break ;
default :
/* displays the data inside the attribute*/
proto_tree_add_item ( ecmp_attribute_data_tree , hf_ecmp_attribute_string , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset + 1 ) + 2 ) ;
break ;
}
}
}
proto_item_set_len ( ecmp_attribute_number_item , offset - start_offset ) ;
}
/* a function to display the category codes */
static int add_category_codes ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_category_item = NULL ;
proto_tree * ecmp_category_tree = NULL ;
guint8 category_size = 0 ;
int start_offset = offset ;
guint8 category_value = tvb_get_guint8 ( tvb , offset ) ;
2015-12-04 09:40:44 +00:00
/* displays the category and creates a tree to display further data*/
2015-12-02 00:03:27 +00:00
ecmp_category_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_category , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-04 09:40:44 +00:00
ecmp_category_tree = proto_item_add_subtree ( ecmp_category_item , ett_ecmp_category ) ;
offset + + ;
2015-12-02 00:03:27 +00:00
2015-12-04 09:40:44 +00:00
category_size = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
2015-12-02 00:03:27 +00:00
if ( category_size = = 2 & & category_value = = 1 ) {
/*display "option module" and its ID*/
proto_tree_add_item ( ecmp_category_tree , hf_ecmp_category_id , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = category_size ;
} else if ( category_size = = 4 & & category_value = = 0 ) {
/*display "drive" and its data (product type, drive derivative and ID*/
proto_tree_add_item ( ecmp_category_tree , hf_ecmp_drive_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_category_tree , hf_ecmp_drive_derivative , tvb , offset + 1 , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_category_tree , hf_ecmp_drive_factory_fit_category_id , tvb , offset + 2 , 2 , ENC_BIG_ENDIAN ) ;
offset + = category_size ;
} else {
/* Display unknown and its hex data */
proto_tree_add_item ( ecmp_category_tree , hf_ecmp_data , tvb , offset , category_size , ENC_NA ) ;
offset + = category_size ;
}
proto_item_set_len ( ecmp_category_item , offset - start_offset ) ;
return offset ;
}
/* a function to display response size data */
static int get_response_size ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_max_response_item = NULL ;
proto_tree * ecmp_response_size_tree = NULL ;
guint8 chunks = 0 ;
guint16 max_response_size = 0 ;
/*get values for number of chunks and max response size*/
chunks = tvb_get_guint8 ( tvb , offset ) > > 4 & 0x0F ;
max_response_size = tvb_get_ntohs ( tvb , offset ) & 0x0FFF ;
/*display response subtree */
2015-12-04 09:40:44 +00:00
ecmp_response_size_tree = proto_tree_add_subtree_format ( ecmp_tree , tvb , offset , 2 , ett_ecmp_response_size , & ecmp_max_response_item , " Response Size: %X, %X (%d) " , chunks , max_response_size , max_response_size ) ;
2015-12-02 00:03:27 +00:00
/*display chunks and max response size in response subtree*/
proto_tree_add_item ( ecmp_response_size_tree , hf_ecmp_chunking , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
proto_tree_add_uint_format_value ( ecmp_response_size_tree , hf_ecmp_max_response_size , tvb , offset , 2 , max_response_size , " %d bytes " , max_response_size ) ;
offset + = 2 ;
return offset ;
}
/* a function to display the command code and type (request/response) */
static int add_command_codes ( packet_info * pinfo , int offset , tvbuff_t * tvb , proto_tree * ecmp_tree , guint8 transaction_id_value , guint8 * command_value )
{
proto_tree * ecmp_command_tree ;
const gchar * command_str ;
guint8 command ;
command = tvb_get_guint8 ( tvb , offset ) ;
* command_value = command & 0x7F ;
command_str = val_to_str ( * command_value , command_vals , " Unknown Type (0x%02x) " ) ;
/*display command subtree*/
ecmp_command_tree = proto_tree_add_subtree_format ( ecmp_tree , tvb , offset , 1 , ett_ecmp_command , NULL , " Request Response Code: %s " , command_str ) ;
/* Displays the command */
proto_tree_add_item ( ecmp_command_tree , hf_ecmp_command , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
/* Displays the type (request/response) */
proto_tree_add_item ( ecmp_command_tree , hf_ecmp_type_rr , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
/* Information displayed in the Info column*/
col_add_fstr ( pinfo - > cinfo , COL_INFO , " %s, %s. Transaction ID: %d " ,
command_str , val_to_str ( ( ( command & 0x80 ) > > 7 ) , type_rr , " Unknown Type (0x%02x) " ) , transaction_id_value ) ;
return offset ;
}
/* a function to add a cyclic frame query */
static int add_cyclic_frame_query ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
/* display the cyclic link number */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_link_num , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
return offset ;
}
/* a function to add a cyclic frame */
static int add_cyclic_frame ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
guint8 scheme ;
proto_item * ecmp_scheme_item = NULL ;
proto_tree * ecmp_scheme_tree = NULL ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_link_num , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_align , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* get scheme */
scheme = tvb_get_guint8 ( tvb , offset ) ;
ecmp_scheme_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_scheme , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
if ( scheme = = 1 ) {
/* Create a new sub tree spawning off the scheme byte for the synchronisation scheme data to be placed. */
ecmp_scheme_tree = proto_item_add_subtree ( ecmp_scheme_item , ett_ecmp_cyclic_scheme ) ;
/* grandmaster */
proto_tree_add_item ( ecmp_scheme_tree , hf_ecmp_grandmaster , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
proto_tree_add_item ( ecmp_scheme_tree , hf_ecmp_cyclic_frame_time , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
}
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset , - 1 , ENC_NA ) ;
return tvb_reported_length ( tvb ) ;
}
/* a function to display cyclic tvb data in byte (8-bit), word (16-bit), and long (32-bit) unsigned formats */
static int display_raw_cyclic_data ( guint8 display , int offset , guint16 buffer_size , tvbuff_t * tvb , proto_tree * ecmp_current_tree )
{
/****************************************************************************************/
/* */
/* display_raw_cyclic_data - display the cyclic data in various formats. */
/* */
/* Parameters: display = selects desired display format. */
/* 0 = BYTE_FORMAT (8-bits 1F 20 37 BC ... */
/* 1 = WORD_FORMAT (16-bits 1F20 37BC 77F1 ... */
/* 2 = LONG_FORMAT (32-bits 1F2037BC 0013F5CD ... */
2015-12-04 09:40:44 +00:00
/* */
2015-12-02 00:03:27 +00:00
/* offset = offset within tvb buffer where this data starts. */
/* */
/* buffer_size = number of bytes to be converted and displayed. */
/* */
/* tvb = buffer structure within Wireshark holding this frame. */
/* */
/* ecmp_current_tree = the tree where the data is to be displayed. */
/* */
/* */
/* Notes: we only display so many elements on a line (before continuing on next line) */
/* */
/* 16 elements per line for byte (8-bit) and word (16-bit) */
/* 8 elements per line for long (32-bit) */
/* */
/* Programmer: Jim Lynch */
/****************************************************************************************/
/* bail out if the buffer size is zero */
if ( buffer_size = = 0 ) {
proto_tree_add_bytes_format_value ( ecmp_current_tree , hf_ecmp_cyclic_data , tvb , offset - 1 , 0 , NULL , " No data " ) ;
} else {
/* define some variables */
2015-12-04 09:40:44 +00:00
gchar * pdata = NULL ; /* pointer to array that stores the formatted data string */
guint16 idx = 0 ; /* counts through formatted string array */
guint8 value8 = 0 ; /* placeholder for extracted 8-bit data */
guint16 value16 = 0 ; /* placeholder for extracted 16-bit data */
guint32 value32 = 0 ; /* placeholder for extracted 32-bit data */
guint16 num_elements_total = 0 ; /* contains total number of elements (byte/word/long) to be processed */
const guint16 num_byte_elements_per_line = 16 ; /* number of byte (8-bit) elements per line e.g. "1B " (3 chars per element) */
const guint16 num_word_elements_per_line = 16 ; /* number of word (16-bit) elements per line e.g. "A81B " (5 chars per element) */
const guint16 num_long_elements_per_line = 8 ; /* number of long (32-bit) elements per line e.g. "01F4A81B " (9 chars per element) */
guint16 num_elements_per_line = 8 ; /* counts the current number of elements per line */
guint16 num_elements = 0 ; /* counts the number of elements in the format string */
guint16 format_string_size = 0 ; /* size of dynamic array to hold the formatted string */
guint16 a = 0 ; /* value used for looping */
int start_offset , line_offset ;
/* calculate format string array size and other stuff */
/* */
/* Note: format string does require a nul-terminator (the + 1 in the equations) */
/* */
/* display = 0: (byte format "1D 24 3F ... A3 " */
/* format_string_size = (num_byte_elements_per_line * 3) + 1 */
/* */
/* display = 1: (word format "1D24 3F84 120B ... 1FA3 " */
/* format_string_size = (num_word_elements_per_line * 5) + 1 */
/* */
/* display = 2: (byte format "1D243F84 9BC08F20 ... 28BB1FA3 " */
/* format_string_size = (num_long_elements_per_line * 9) + 1 */
/* */
2015-12-02 00:03:27 +00:00
if ( display = = cyclic_display_byte_format ) {
2015-12-04 09:40:44 +00:00
format_string_size = ( num_byte_elements_per_line * 3 ) + 1 ; /* format_string_size = 49 */
num_elements_per_line = num_byte_elements_per_line ; /* num_elements_per_line = 16 */
2015-12-02 00:03:27 +00:00
num_elements_total = buffer_size ;
} else if ( display = = cyclic_display_word_format ) {
2015-12-04 09:40:44 +00:00
format_string_size = ( num_word_elements_per_line * 5 ) + 1 ; /* format_string_size = 81 */
num_elements_per_line = num_word_elements_per_line ; /* num_elements_per_line = 16 */
2015-12-02 00:03:27 +00:00
num_elements_total = buffer_size > > 1 ;
} else if ( display = = cyclic_display_long_format ) {
2015-12-04 09:40:44 +00:00
format_string_size = ( num_long_elements_per_line * 9 ) + 1 ; /* format_string_size = 73 */
num_elements_per_line = num_long_elements_per_line ; /* num_elements_per_line = 8 */
2015-12-02 00:03:27 +00:00
num_elements_total = buffer_size > > 2 ;
} else {
2015-12-04 09:40:44 +00:00
format_string_size = ( num_byte_elements_per_line * 3 ) + 1 ; /* format_string_size = 49 */
num_elements_per_line = num_byte_elements_per_line ; /* num_elements_per_line = 16 */
2015-12-02 00:03:27 +00:00
num_elements_total = buffer_size ;
}
/* allocate dynamic memory for one line */
pdata = ( gchar * ) wmem_alloc ( wmem_packet_scope ( ) , format_string_size ) ;
/* OK, let's get started */
idx = 0 ;
num_elements = 0 ;
line_offset = start_offset = offset ;
/* work through the display elements, 1 byte\word\long at a time */
for ( a = 0 ; a < num_elements_total ; a + + )
{
/* use Wireshark accessor function to get the next byte, word, or long data */
if ( display = = cyclic_display_byte_format ) {
value8 = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
} else if ( display = = cyclic_display_word_format ) {
value16 = tvb_get_ntohs ( tvb , offset ) ;
offset + = 2 ;
} else if ( display = = cyclic_display_long_format ) {
value32 = tvb_get_ntohl ( tvb , offset ) ;
offset + = 4 ;
}
/* increment the num_elements we've done on the current line */
num_elements + + ;
/* check if we hit the max number of byte elements per line */
if ( num_elements > = num_elements_per_line ) {
/* we hit end of the current line */
/* add final value to string */
if ( display = = cyclic_display_byte_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %02x " , value8 ) ;
} else if ( display = = cyclic_display_word_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %04x " , value16 ) ;
} else if ( display = = cyclic_display_long_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %08x " , value32 ) ;
}
/* display the completed line in the sub-tree */
proto_tree_add_bytes_format ( ecmp_current_tree , hf_ecmp_cyclic_data , tvb , offset , offset - line_offset , NULL , " %s " , pdata ) ;
/* start the line over */
idx = 0 ;
num_elements = 0 ;
2015-12-04 09:40:44 +00:00
line_offset = offset ;
2015-12-02 00:03:27 +00:00
} else {
/* we're still adding to the current line */
/* add current value to string */
if ( display = = cyclic_display_byte_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %02x " , value8 ) ;
idx + = 3 ;
} else if ( display = = cyclic_display_word_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %04x " , value16 ) ;
idx + = 5 ;
} else if ( display = = cyclic_display_long_format ) {
g_snprintf ( & pdata [ idx ] , 32 , " %08x " , value32 ) ;
idx + = 9 ;
}
}
2015-12-04 09:40:44 +00:00
}
2015-12-02 00:03:27 +00:00
/* if we exited the loop, see if there's a partial line to display */
if ( num_elements > 0 ) {
/* add null-terminator to partial line */
pdata [ idx ] = 0x00 ;
/* display the partial line in the sub-tree */
proto_tree_add_bytes_format ( ecmp_current_tree , hf_ecmp_cyclic_data , tvb , start_offset , offset - start_offset , NULL , " %s " , pdata ) ;
}
}
return offset ;
}
/* a function returning the information requested by the 'info' command */
static void add_info_response ( int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_info_address_item = NULL ;
proto_tree * ecmp_info_tree = NULL ;
proto_tree * ecmp_info_address_tree = NULL , * address_tree ;
guint16 length = 0 ;
guint8 no_of_address = 0 ;
guint8 i = 0 ; /*for counting */
length = tvb_reported_length ( tvb ) ;
/*display info response tree */
ecmp_info_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 6 , ett_ecmp_info_type , NULL , " Response Information " ) ;
/*display buffer size */
proto_tree_add_item ( ecmp_info_tree , hf_ecmp_buffer_size , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display max response time */
proto_tree_add_item ( ecmp_info_tree , hf_ecmp_max_response , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display max handle period */
proto_tree_add_item ( ecmp_info_tree , hf_ecmp_max_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
if ( length > offset ) {
/*display count of default server addresses */
ecmp_info_address_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_info_address , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_info_address_tree = proto_item_add_subtree ( ecmp_info_address_item , ett_ecmp_info_count ) ;
no_of_address = tvb_get_guint8 ( tvb , offset ) ;
if ( no_of_address > 0 ) {
/*do code to display address data */
for ( i = 0 ; i < no_of_address ; i + + ) {
address_tree = proto_tree_add_subtree_format ( ecmp_info_address_tree , tvb , offset , 1 , ett_ecmp_address , NULL , " Address %d " , i + 1 ) ;
proto_tree_add_item ( address_tree , hf_ecmp_physical_address , tvb , offset , 1 , ENC_NA ) ;
proto_tree_add_item ( address_tree , hf_ecmp_logical_address , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
}
}
}
}
/*--------------------------------------------------------------------*/
/* Parameter Access Commands */
/*--------------------------------------------------------------------*/
/* a function to display data given data_type */
static int get_data_type ( packet_info * pinfo , int offset , guint8 data_type , tvbuff_t * tvb , proto_tree * ecmp_current_tree )
{
/*switch to decide correct data_type dissection*/
switch ( data_type )
{
case 0 : /*display boolean*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_boolean , tvb , offset , 1 , ENC_NA ) ;
break ;
case 1 : /*display INT8*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_int8 , tvb , offset , 1 , ENC_NA ) ;
break ;
case 2 : /*display UINT8*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_uint8 , tvb , offset , 1 , ENC_NA ) ;
break ;
case 3 : /*display INT16*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_int16 , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 1 ;
break ;
case 4 : /*display UINT16*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_uint16 , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 1 ;
break ;
case 5 : /*display INT32*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_int32 , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
break ;
case 6 : /*display UINT32*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_uint32 , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
break ;
case 7 : /*display INT64*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_int64 , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 7 ;
break ;
case 8 : /*display UINT64*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_uint64 , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 7 ;
break ;
case 9 : /*display INT128*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data , tvb , offset , 16 , ENC_NA ) ;
offset + = 15 ;
break ;
case 10 : /*display UINT128*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data , tvb , offset , 16 , ENC_NA ) ;
offset + = 15 ;
break ;
case 20 : /*display single float*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_float , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
break ;
case 21 : /*display double float*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data_double , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 7 ;
break ;
case 30 : /*display string ID*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_string_id , tvb , offset , 2 , ENC_NA | ENC_ASCII ) ;
offset + + ;
break ;
case 32 : /*display (ECMP) string*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_ecmp_string , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset + 1 ) + 2 ) ;
break ;
default : /*display untyped size*/
if ( data_type < 128 ) {
proto_tree_add_expert ( ecmp_current_tree , pinfo , & ei_ecmp_data_type , tvb , 0 , - 1 ) ;
} else {
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_data , tvb , offset , ( data_type - 127 ) , ENC_NA ) ;
offset + = ( data_type - 128 ) ;
}
break ;
}
return offset ;
}
/* a function to add the parameter address schemes for 'read' command */
static int get_address_scheme ( packet_info * pinfo , int offset , guint8 scheme , tvbuff_t * tvb , proto_tree * ecmp_parameter_tree )
{
/*if address scheme is standard*/
switch ( scheme )
{
case 0 :
/*display Menu no. */
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_menu , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display parameter no. */
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_parameter , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + + ;
break ;
case 1 : /*if address scheme is slot specific*/
/*display slot number*/
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_slot , tvb , offset , 1 , ENC_NA ) ;
offset + + ;
/*display Menu no. */
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_menu , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display parameter no. */
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_parameter , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + + ;
break ;
case 3 : /*if address scheme is variable*/
/*display variable name */
offset - - ;
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_variable_name , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset + 1 ) + 2 ) ;
break ;
case 4 : /*if address scheme is NULL*/
/*null size*/
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_address_scheme_null_byte_size , tvb , offset , 1 , ENC_NA ) ;
offset + + ;
break ;
default :
proto_tree_add_expert ( ecmp_parameter_tree , pinfo , & ei_ecmp_parameter_addressing_scheme , tvb , offset , 1 ) ;
}
return offset ;
}
/* a function to display an array of the read address schemes */
static void get_parameter_definitions ( packet_info * pinfo , int offset , guint8 command_value , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_parameter_item = NULL ;
proto_tree * ecmp_parameter_number_tree = NULL ;
proto_tree * ecmp_parameter_tree = NULL ;
guint8 count = 0 ;
guint8 a = 0 ;
guint8 data_type = 0 ;
gint8 dec = 0 ;
guint8 scheme = 0 ;
guint16 n = 0 ;
scheme = tvb_get_guint8 ( tvb , offset ) ;
ecmp_parameter_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_parameter_address , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_parameter_tree = proto_item_add_subtree ( ecmp_parameter_item , ett_ecmp_param_address ) ;
offset + + ;
/* if "GetNextObjects" command */
if ( command_value = = ECMP_COMMAND_GETNEXTOBJECTS )
{
offset = get_address_scheme ( pinfo , offset , scheme , tvb , ecmp_parameter_tree ) ;
offset + + ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_subsequent_object_requests , tvb , offset , 1 , ENC_NA ) ;
} else
{
/*display tree with count of definitions */
ecmp_parameter_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_parameter_definitions , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_parameter_number_tree = proto_item_add_subtree ( ecmp_parameter_item , ett_ecmp_param_address ) ;
count = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
switch ( scheme ) /*sets n so that the tree highlights bytes in scheme specific data*/
{
case 0 :
n = 4 ;
break ;
case 1 :
n = 5 ;
break ;
case 3 :
n = 1 + ( ( tvb_get_guint8 ( tvb , offset + 1 ) < < 8 ) | ( tvb_get_guint8 ( tvb , offset + 2 ) ) ) ;
break ;
default :
n = 0 ;
break ;
}
if ( command_value = = ECMP_COMMAND_OBJECTINFO ) {
n + = 1 ;
}
for ( a = 0 ; a < count ; a + + ) {
ecmp_parameter_tree = proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , n , ett_ecmp_param_address , NULL , " Parameter Definition %d: " , ( a + 1 ) ) ;
if ( command_value = = ECMP_COMMAND_OBJECTINFO ) {
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_info_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
offset = get_address_scheme ( pinfo , offset , scheme , tvb , ecmp_parameter_tree ) ;
offset + + ;
} else {
/*output the address schemes of the parameter requests */
offset = get_address_scheme ( pinfo , offset , scheme , tvb , ecmp_parameter_tree ) ;
offset + + ;
if ( command_value = = ECMP_COMMAND_WRITE ) {
data_type = tvb_get_guint8 ( tvb , offset ) ;
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_parameter_tree , hf_ecmp_data_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
dec = ( gint8 ) tvb_get_guint8 ( tvb , offset ) ;
if ( dec ! = - 1 ) {
proto_tree_add_int ( ecmp_parameter_tree , hf_ecmp_number_of_decimal_places , tvb , offset , 1 , dec ) ;
} else {
proto_tree_add_int_format_value ( ecmp_parameter_tree , hf_ecmp_number_of_decimal_places , tvb , offset , 1 , dec , " 0 (Invalid type) " ) ;
}
offset + + ;
offset = get_data_type ( pinfo , offset , data_type , tvb , ecmp_parameter_tree ) ;
offset + + ;
}
}
}
}
}
/* a function to show the "objectinfo" command response */
static void get_object_info_response ( packet_info * pinfo , int offset , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_response_item = NULL ;
proto_tree * ecmp_parameter_number_tree = NULL ;
proto_tree * ecmp_parameter_response_tree = NULL ;
2015-12-04 09:40:44 +00:00
guint8 count = 0 ; /*stores number of parameter read responses */
guint8 a = 0 ; /*counting varables */
2015-12-02 00:03:27 +00:00
guint8 n = 0 ;
guint8 info_type0 = 0 ;
guint16 length = 0 ;
guint8 data_type = 0 ;
length = tvb_reported_length ( tvb ) ;
ecmp_response_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_parameter_responses , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_parameter_number_tree = proto_item_add_subtree ( ecmp_response_item , ett_ecmp_param_address ) ;
count = tvb_get_guint8 ( tvb , offset ) ;
if ( count = = 0 ) {
offset + + ;
proto_tree_add_item ( ecmp_parameter_number_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
} else {
/*display info data response */
for ( a = 0 ; a < count ; a + + ) {
if ( a = = 0 ) {
n = ( length - offset ) / count ;
}
offset + + ;
/*display response header */
2015-12-04 09:58:38 +00:00
proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , n , ett_ecmp_command , NULL , " Response %d: " , ( a + 1 ) ) ;
2015-12-02 00:03:27 +00:00
/*display response status */
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
/*display response data */
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_info_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
info_type0 = tvb_get_guint8 ( tvb , offset ) ;
switch ( info_type0 )
{
case 0 :
/*no information available */
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_no_information_available , tvb , offset , 1 , ENC_NA ) ;
break ;
case 1 :
/*display min parameter in menu */
offset + + ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_min_param_menu , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + + ;
break ;
case 2 :
/*display max parameter in menu */
offset + + ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_max_param_menu , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + + ;
break ;
case 3 :
{
static const int * fields [ ] = {
& hf_ecmp_param_format_bit_default_unipolar ,
& hf_ecmp_param_format_write_allowed ,
& hf_ecmp_param_format_read_not_allowed ,
& hf_ecmp_param_format_protected_from_destinations ,
& hf_ecmp_param_format_parameter_not_visible ,
& hf_ecmp_param_format_not_clonable ,
& hf_ecmp_param_format_voltage_or_current_rating_dependant ,
& hf_ecmp_param_format_parameter_has_no_default ,
& hf_ecmp_param_format_number_of_decimal_places ,
& hf_ecmp_param_format_variable_maximum_and_minimum ,
& hf_ecmp_param_format_string_parameter ,
& hf_ecmp_param_format_desitination_set_up_parameter ,
& hf_ecmp_param_format_filtered_when_displayed ,
& hf_ecmp_param_format_pseudo_read_only ,
& hf_ecmp_param_format_display_format ,
& hf_ecmp_param_format_floating_point_value ,
& hf_ecmp_param_format_units ,
NULL
} ;
/*display data for parameter format- UNITS and Display Format need dissecting? */
offset + + ;
proto_tree_add_bitmask_list ( ecmp_parameter_response_tree , tvb , offset , 4 , fields , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
}
break ;
case 4 :
/*display minimum allowed value*/
offset + + ;
data_type = tvb_get_guint8 ( tvb , offset ) ;
ecmp_response_item = proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_data_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
offset = get_data_type ( pinfo , offset , data_type , tvb , ecmp_parameter_response_tree ) ;
break ;
case 5 :
/*display maximum allowed value*/
offset + + ;
data_type = tvb_get_guint8 ( tvb , offset ) ;
ecmp_response_item = proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_data_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
offset = get_data_type ( pinfo , offset , data_type , tvb , ecmp_parameter_response_tree ) ;
break ;
case 6 :
/*display Units- ID string */
offset + + ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_string_id , tvb , offset , 2 , ENC_NA | ENC_ASCII ) ;
offset + + ;
break ;
case 7 :
/*display data type */
offset + + ;
ecmp_response_item = proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_data_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
break ;
default :
expert_add_info ( pinfo , ecmp_response_item , & ei_ecmp_info_type ) ;
break ;
}
}
}
}
/* a function to display an array of the read responses */
static int get_parameter_responses ( packet_info * pinfo , int offset , guint8 command_value , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_response_item = NULL ;
proto_tree * ecmp_parameter_number_tree = NULL ;
proto_tree * ecmp_parameter_response_tree = NULL ;
2015-12-04 09:40:44 +00:00
guint8 count = 0 ; /*stores number of parameter read responses */
guint8 a = 0 ; /*counting varables */
2015-12-02 00:03:27 +00:00
guint8 data_type = 0 ;
guint8 unit_id = 0 ;
gint8 dec = 0 ;
guint16 n = 0 ;
guint8 st_error = 0 ;
guint16 length = 0 ;
guint8 scheme = 0 ;
int start_offset ;
scheme = tvb_get_guint8 ( tvb , offset ) ;
length = tvb_reported_length ( tvb ) ;
if ( command_value = = ECMP_COMMAND_GETNEXTOBJECTS ) {
/*display addressing scheme*/
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_tree , hf_ecmp_parameter_address , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
}
/*display number of responses*/
ecmp_response_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_parameter_responses , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_parameter_number_tree = proto_item_add_subtree ( ecmp_response_item , ett_ecmp_param_address ) ;
count = tvb_get_guint8 ( tvb , offset ) ;
if ( count = = 0 ) {
offset + + ;
if ( command_value ! = ECMP_COMMAND_GETNEXTOBJECTS ) {
/*display parameter status*/
proto_tree_add_item ( ecmp_parameter_number_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
}
} else {
/*loop for outputting parameter data responses*/
for ( a = 0 ; a < count ; a + + ) {
if ( command_value = = ECMP_COMMAND_WRITE ) {
if ( a = = 0 ) {
n = ( length - offset ) / count ; /*set byte highlighting*/
}
offset + + ;
/*display response: (a+1)*/
ecmp_parameter_response_tree = proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , n , ett_ecmp_command , NULL , " Response %d: " , ( a + 1 ) ) ;
ecmp_response_item = proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
} else if ( command_value = = ECMP_COMMAND_GETNEXTOBJECTS ) {
if ( a = = 0 ) {
n = ( length - offset ) / count ;
}
offset + + ;
/*display response: (a+1)*/
ecmp_parameter_response_tree = proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , n , ett_ecmp_command , NULL , " Response %d: " , ( a + 1 ) ) ;
offset = get_address_scheme ( pinfo , offset , scheme , tvb , ecmp_parameter_response_tree ) ;
} else {
/*if status is error */
if ( ( gint8 ) tvb_get_guint8 ( tvb , offset + 1 ) < 0 ) {
/*output status*/
st_error = 1 ;
offset + + ;
ecmp_parameter_response_tree = proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , 1 , ett_ecmp_command , NULL , " Response %d: " , ( a + 1 ) ) ;
ecmp_response_item = proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( ( a + 1 ) ! = count ) {
/*loop to move to next data_type (skips bytes == 0)*/
while ( 1 ) {
if ( tvb_get_guint8 ( tvb , offset + 1 ) = = 0 ) {
offset + + ;
} else {
break ;
}
}
}
} else {
offset + + ;
/*display reponse data_byte*/
start_offset = offset ;
ecmp_parameter_response_tree = proto_tree_add_subtree_format ( ecmp_parameter_number_tree , tvb , offset , 0 , ett_ecmp_command , & ecmp_response_item , " Response %d: " , ( a + 1 ) ) ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_parameter_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_data_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
data_type = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
offset = get_data_type ( pinfo , offset , data_type , tvb , ecmp_parameter_response_tree ) ;
/*if "ReadWithType" */
if ( ( command_value = = ECMP_COMMAND_READWITHTYPE ) & & ( st_error ! = 1 ) ) {
offset + + ;
/*display decimal places*/
dec = ( gint8 ) tvb_get_guint8 ( tvb , offset ) ;
if ( dec ! = - 1 ) {
proto_tree_add_int ( ecmp_parameter_response_tree , hf_ecmp_number_of_decimal_places , tvb , offset , 1 , dec ) ;
} else {
proto_tree_add_int_format_value ( ecmp_parameter_response_tree , hf_ecmp_number_of_decimal_places , tvb , offset , 1 , dec , " 0 (Invalid type) " ) ;
}
offset + + ;
/*display unit ID*/
unit_id = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_display_unit_id , tvb , offset , 1 , ENC_NA ) ;
if ( unit_id = = 255 ) {
offset + + ;
proto_tree_add_item ( ecmp_parameter_response_tree , hf_ecmp_unit_id_string , tvb , offset , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset ) + 2 ) ;
}
}
proto_item_set_len ( ecmp_response_item , offset - start_offset ) ;
}
}
}
}
return offset ;
}
/*--------------------------------------------------------------------*/
/* File Access Commands */
/*--------------------------------------------------------------------*/
/* a function to dissect "FileOpen" command */
static void file_open ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_tree * ecmp_scheme_data_tree = NULL ;
guint8 additional_scheme = 0 ;
guint8 relative = 0 ;
if ( request ) {
static const int * fields [ ] = {
& hf_ecmp_open_in_non_blocking_mode ,
& hf_ecmp_open_file_relative_to_specified_directory_handle ,
& hf_ecmp_file_access_mode ,
NULL
} ;
proto_tree_add_bitmask ( ecmp_tree , tvb , offset , hf_ecmp_access_mode , ett_ecmp_access_mode , fields , ENC_BIG_ENDIAN ) ;
offset + + ;
/*display additional scheme*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_additional_scheme , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
additional_scheme = tvb_get_guint8 ( tvb , offset ) ;
/*display file name*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_name , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
offset + = ( tvb_get_ntohs ( tvb , offset + 1 ) + 2 ) ;
/*only show file handle in relative mode*/
if ( relative = = 1 ) {
offset + + ;
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
}
if ( additional_scheme = = 1 ) {
/*display additional data*/
offset + = 2 ;
ecmp_scheme_data_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , - 1 , ett_ecmp_access_file , NULL , " Additional scheme data " ) ;
proto_tree_add_item ( ecmp_scheme_data_tree , hf_ecmp_scheme_data_length , tvb , offset , 1 , ENC_NA ) ;
offset + + ;
proto_tree_add_item ( ecmp_scheme_data_tree , hf_ecmp_data , tvb , offset , - 1 , ENC_NA ) ;
}
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( ( gint8 ) tvb_get_guint8 ( tvb , offset ) > = 0 ) {
offset + + ;
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
}
}
}
/* a function to dissect "FileRead" command */
static void file_read ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
guint16 req_bytes = 0 ;
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display requested bytes*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_requested_bytes , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( ( gint8 ) tvb_get_guint8 ( tvb , offset ) > = 0 ) {
offset + + ;
/*display bytes for reading*/
req_bytes = tvb_get_ntohs ( tvb , offset ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_response_data , tvb , offset , req_bytes + 2 , ENC_NA ) ;
2015-12-04 09:58:38 +00:00
/*offset += (2+req_bytes);*/
2015-12-02 00:03:27 +00:00
}
}
}
/* a function to dissect "FileWrite" command */
static void file_write ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
guint16 req_bytes ;
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display bytes for writing*/
req_bytes = tvb_get_ntohs ( tvb , offset ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset + 2 , req_bytes , ENC_NA ) ;
2015-12-04 09:58:38 +00:00
/*offset += (2+req_bytes);*/
2015-12-02 00:03:27 +00:00
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-04 09:58:38 +00:00
/*offset++;*/
2015-12-02 00:03:27 +00:00
}
}
/*a function to dissect "FileClose" command*/
static void file_close ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display number of data bytes transferred*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_bytes_transferred , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 4 ;
/*display CRC value*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_crc , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
}
}
/*a function to display file attributes*/
static int get_file_attribute ( packet_info * pinfo , int offset , guint8 attribute0 , tvbuff_t * tvb , proto_tree * ecmp_current_tree )
{
nstime_t ts ;
switch ( attribute0 )
{
case 0 : /*display length of file*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_file_length , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
break ;
case 1 : /*display integrity*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_file_integrity , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
break ;
case 2 : /*display CRC*/
proto_tree_add_item ( ecmp_current_tree , hf_ecmp_crc , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 3 ;
break ;
case 3 : /*display attrib*/
{
static const int * fields [ ] = {
& hf_ecmp_display_attr_read_only ,
& hf_ecmp_display_attr_hidden ,
& hf_ecmp_display_attr_system ,
& hf_ecmp_display_attr_volume_label ,
& hf_ecmp_display_attr_subdirectory ,
& hf_ecmp_display_attr_archive ,
NULL
} ;
proto_tree_add_bitmask_list ( ecmp_current_tree , tvb , offset , 1 , fields , ENC_BIG_ENDIAN ) ;
}
break ;
case 4 : /*display creation date*/
ts . secs = tvb_get_ntohl ( tvb , offset ) ;
ts . nsecs = 0 ;
proto_tree_add_time ( ecmp_current_tree , hf_ecmp_display_creation , tvb , offset , 4 , & ts ) ;
offset + = 3 ;
break ;
case 5 : /*display modification date*/
ts . secs = tvb_get_ntohl ( tvb , offset ) ;
ts . nsecs = 0 ;
proto_tree_add_time ( ecmp_current_tree , hf_ecmp_display_modification , tvb , offset , 4 , & ts ) ;
offset + = 3 ;
break ;
default : /*display incorrect attribute type error*/
proto_tree_add_expert ( ecmp_current_tree , pinfo , & ei_ecmp_attribute_type , tvb , offset , 1 ) ;
break ;
}
return offset ;
}
/*a function to dissect "FileInfo" command*/
static void file_info ( packet_info * pinfo , int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_file_info_item = NULL ;
proto_tree * ecmp_file_info_tree = NULL ;
proto_tree * ecmp_file_info_att_tree = NULL ;
guint8 no_of_att = 0 ;
guint8 attribute0 = 0 ;
guint8 a = 0 ;
int start_offset ;
if ( request ) {
/*display file handle*/
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + = 2 ;
/*display number of attributes*/
no_of_att = tvb_get_guint8 ( tvb , offset ) ;
ecmp_file_info_item = proto_tree_add_uint ( ecmp_tree , hf_ecmp_no_of_attributes , tvb , offset , 1 , no_of_att ) ;
ecmp_file_info_tree = proto_item_add_subtree ( ecmp_file_info_item , ett_ecmp_file_info ) ;
offset + + ;
/*display attributes*/
for ( a = 0 ; a < no_of_att ; a + + ) {
ecmp_file_info_item = proto_tree_add_item ( ecmp_file_info_tree , hf_ecmp_file_attributes , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_file_info_att_tree = proto_item_add_subtree ( ecmp_file_info_item , ett_ecmp_file_info_att ) ;
attribute0 = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
2015-12-04 09:58:38 +00:00
offset = get_file_attribute ( pinfo , offset , attribute0 , tvb , ecmp_file_info_att_tree ) ;
2015-12-02 00:03:27 +00:00
}
proto_item_set_len ( ecmp_file_info_item , no_of_att ) ;
} else {
/*display file status*/
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
/*display number of attributes*/
no_of_att = tvb_get_guint8 ( tvb , offset ) ;
ecmp_file_info_item = proto_tree_add_uint ( ecmp_tree , hf_ecmp_no_of_attributes , tvb , offset , 1 , no_of_att ) ;
ecmp_file_info_tree = proto_item_add_subtree ( ecmp_file_info_item , ett_ecmp_file_info ) ;
start_offset = offset ;
/*display attributes*/
for ( a = 0 ; a < no_of_att ; a + + ) {
offset + + ;
ecmp_file_info_item = proto_tree_add_item ( ecmp_file_info_tree , hf_ecmp_file_attributes , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
ecmp_file_info_att_tree = proto_item_add_subtree ( ecmp_file_info_item , ett_ecmp_file_info_att ) ;
attribute0 = tvb_get_guint8 ( tvb , offset ) ;
offset + + ;
offset = get_file_attribute ( pinfo , offset , attribute0 , tvb , ecmp_file_info_att_tree ) ;
}
proto_item_set_len ( ecmp_file_info_item , offset - start_offset ) ;
}
}
/*a function to dissect "FileStatus"/"FileDelete" commands*/
static void file_state_delete ( guint16 offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
}
}
/*a function to dissect "FilePos" command*/
static void file_pos ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_tree * ecmp_file_position_tree = NULL ;
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display "position" header*/
ecmp_file_position_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 5 , ett_ecmp_file_position , NULL , " Position " ) ;
/*display reference point*/
proto_tree_add_item ( ecmp_file_position_tree , hf_ecmp_file_ref_point , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + + ;
/*display offset from ref point*/
proto_tree_add_item ( ecmp_file_position_tree , hf_ecmp_ref_offset , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( ( gint8 ) tvb_get_guint8 ( tvb , offset ) > = 0 ) {
offset + + ;
/*display offset from ref point*/
proto_tree_add_item ( ecmp_file_position_tree , hf_ecmp_ref_offset , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
}
}
}
/*a function to dissect "FileList" command*/
static void file_list ( packet_info * pinfo , int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * ecmp_file_list_item , * ecmp_file_list_item2 , * item_type_item ;
proto_tree * ecmp_file_list_no_tree = NULL ;
proto_tree * ecmp_file_list_tree = NULL ;
guint8 no_of_items = 0 ;
guint8 item_type = 0 ;
guint8 a = 0 ;
guint16 n = 0 ;
int start_offset , start_offset2 ;
if ( request ) {
/*display file handle*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_handle , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/*display number of files to list*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_files_to_list , tvb , offset , 1 , ENC_NA ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( ( gint8 ) tvb_get_guint8 ( tvb , offset ) > = 0 ) {
offset + + ;
/*display number of files to list*/
no_of_items = tvb_get_guint8 ( tvb , offset ) ;
2016-02-08 09:14:56 +00:00
proto_tree_add_item ( ecmp_tree , hf_ecmp_number_of_files_to_list , tvb , offset , 1 , ENC_NA ) ;
2015-12-02 00:03:27 +00:00
offset + + ;
/*display hash value (dissection TBD)*/
ecmp_file_list_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_file_hash , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + + ;
/*display subtree for files*/
start_offset = offset + 1 ;
ecmp_file_list_no_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset + 1 , no_of_items , ett_ecmp_file_list_no , & ecmp_file_list_item , " Files " ) ;
/*display list of file names*/
for ( a = 0 ; a < no_of_items ; a + + ) {
start_offset2 = offset ;
offset + + ;
item_type = tvb_get_guint8 ( tvb , offset ) ;
n = tvb_get_ntohs ( tvb , offset + 1 ) ;
ecmp_file_list_tree = proto_tree_add_subtree_format ( ecmp_file_list_no_tree , tvb , offset , n + 2 , ett_ecmp_file_list , & ecmp_file_list_item2 , " File %d: " , a + 1 ) ;
item_type_item = proto_tree_add_item ( ecmp_file_list_tree , hf_ecmp_item_type , tvb , offset , 1 , ENC_NA ) ;
switch ( item_type )
{
case 0 : /*if item type is "file"*/
proto_tree_add_item ( ecmp_file_list_tree , hf_ecmp_file_name , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
break ;
case 1 : /*if item type is "directory"*/
proto_tree_add_item ( ecmp_file_list_tree , hf_ecmp_directory , tvb , offset + 1 , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
break ;
default : /*if item type is not "file" or "directory"*/
expert_add_info ( pinfo , item_type_item , & ei_ecmp_item_type ) ;
break ;
}
offset + = n ;
proto_item_set_len ( ecmp_file_list_item2 , offset - start_offset2 ) ;
}
proto_item_set_len ( ecmp_file_list_item , ( offset + 1 ) - start_offset ) ;
}
}
}
/*a function to dissect "FileExists" command*/
static void file_exists ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
if ( request ) {
/*display filename*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_name , tvb , offset , 2 , ENC_BIG_ENDIAN | ENC_ASCII ) ;
} else {
/*display file status*/
proto_tree_add_item ( ecmp_tree , hf_ecmp_file_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
}
}
static int add_cyclic_setup_attributes ( packet_info * pinfo , int offset , guint16 length , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_item * cyclic_setup_attributes_root = NULL ;
proto_item * cyclic_setup_attributes = NULL ;
proto_item * cyclic_setup_attrib_item_root = NULL ;
proto_tree * cyclic_setup_attrib_item = NULL ;
guint8 attrib ;
/* num attribs */
cyclic_setup_attributes_root = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_attrib_count , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* attrib list */
cyclic_setup_attributes = proto_item_add_subtree ( cyclic_setup_attributes_root , ett_cyclic_setup_attribs ) ;
while ( offset < length ) {
attrib = tvb_get_guint8 ( tvb , offset ) ;
cyclic_setup_attrib_item_root = proto_tree_add_item ( cyclic_setup_attributes , hf_ecmp_cyclic_setup_attrib , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
cyclic_setup_attrib_item = proto_item_add_subtree ( cyclic_setup_attrib_item_root , ett_cyclic_setup_attrib_item ) ;
switch ( attrib ) {
case 3 : /* mec offset */
{
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_mec_offset , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 4 ;
}
break ;
case 4 : /* sample period */
case 5 : /* mec delay */
{
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_sample_period , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
}
break ;
case 7 : /* rx timeout */
{
guint32 val ;
/* tout */
val = tvb_get_ntohl ( tvb , offset ) ;
proto_tree_add_uint_format_value ( cyclic_setup_attrib_item , hf_ecmp_rx_timeout , tvb , offset , 4 , val , " %dus " , val ) ;
offset + = 4 ;
/* action */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_action , tvb , offset + + , 1 , ENC_NA ) ;
/* event dest */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_event_destination , tvb , offset + + , 1 , ENC_NA ) ;
/* event */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_event , tvb , offset + + , 1 , ENC_NA ) ;
}
break ;
case 8 : /* rx late handler */
{
/* action */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_late_handler_action , tvb , offset + + , 1 , ENC_NA ) ;
/* event dest */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_late_handler_event_destination , tvb , offset + + , 1 , ENC_NA ) ;
/* event */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_rx_late_handler_event , tvb , offset + + , 1 , ENC_NA ) ;
}
break ;
case 9 : /* transport addr */
{
/* scheme */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_transport_addr_scheme , tvb , offset + + , 1 , ENC_NA ) ;
/* todo - make this check the scheme is actually 0! */
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_transport_addr , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 4 ;
}
break ;
case 12 : /* mapping item */
{
guint8 addrScheme ;
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_mapping_item_offset , tvb , offset + + , 1 , ENC_NA ) ;
addrScheme = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_mapping_item_scheme , tvb , offset + + , 1 , ENC_NA ) ;
offset = get_address_scheme ( pinfo , offset , addrScheme , tvb , cyclic_setup_attrib_item ) ;
/* todo - should this be done in the last function itself??? */
offset + + ;
}
break ;
case 0 : /* state */
case 1 : /* rx/tx */
case 2 : /* synchronised */
case 6 : /* data change */
case 10 : /* max mappings */
case 11 : /* num mappings */
case 13 : /* saveable */
case 128 : /* max rx links */
case 129 : /* max tx links */
case 130 : /* max mappings per link */
case 131 : /* max sync rx links */
case 132 : /* max sync tx links */
case 133 : /* max mappings per sync link */
case 134 : /* process at queue depth */
{
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_setup_attribute , tvb , offset + + , 1 , ENC_NA ) ;
}
break ;
case 135 : /* mec period */
{
proto_tree_add_item ( cyclic_setup_attrib_item , hf_ecmp_mec_period , tvb , offset , 4 , ENC_BIG_ENDIAN ) ;
offset + = 4 ;
}
break ;
default :
break ;
2015-12-04 09:40:44 +00:00
} /* attribute switch */
2015-12-02 00:03:27 +00:00
} /* loop through list */
return offset ;
}
static void cyclic_setup ( packet_info * pinfo , guint16 offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
guint16 length = 0 ;
proto_item * cyclic_setup_attributes_root = NULL ;
proto_item * cyclic_setup_attributes = NULL ;
guint8 Mode ;
length = tvb_reported_length ( tvb ) ;
/* if a request add the check output flag */
if ( request ) {
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_linkno , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
Mode = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( ecmp_tree , hf_ecmp_cyclic_setup_mode , tvb , offset + + , 1 , Mode ) ;
switch ( Mode ) {
case 0 : /* create */
case 10 : /* set */
{
/* link direction */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_dir , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* add the attributesd as a tree */
add_cyclic_setup_attributes ( pinfo , offset , length , tvb , ecmp_tree ) ;
}
break ;
case 1 : /* edit */
case 2 : /* finalise */
case 3 : /* delete */
case 4 : /* exist */
/* link direction */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_dir , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
break ;
case 5 : /* list */
/* tx/rx bits */
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , ENC_NA ) ;
break ;
case 11 : /* get */
case 6 : /* info */
{
if ( Mode = = 11 ) {
/* link dir */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_dir , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
}
/* num attribs */
cyclic_setup_attributes_root = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_attrib_count , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* attrib list */
cyclic_setup_attributes = proto_item_add_subtree ( cyclic_setup_attributes_root , ett_cyclic_setup_attribs ) ;
while ( offset < length ) {
proto_tree_add_item ( cyclic_setup_attributes , hf_ecmp_cyclic_setup_attrib , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
}
}
break ;
case 12 : /* get mappings */
{
/* link dir */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_dir , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* max mappings */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_max_mappings , tvb , offset + + , 1 , ENC_NA ) ;
/* start offset */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_start_offset , tvb , offset + + , 1 , ENC_NA ) ;
}
break ;
default :
/* display payload as hex bytes */
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , ENC_NA ) ;
break ;
}
} else {
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_rsp_status , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_rsp_err_idx , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
Mode = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( ecmp_tree , hf_ecmp_cyclic_setup_mode , tvb , offset + + , 1 , Mode ) ;
switch ( Mode ) {
case 0 : /* create */
case 1 : /* edit */
case 2 : /* finalise */
case 3 : /* delete */
2016-01-06 00:58:42 +00:00
/* no mode specific data */
2015-12-02 00:03:27 +00:00
break ;
case 4 : /* exist */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_link_exists , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
break ;
case 5 : /* list */
{
guint8 txCount , rxCount , linkno ;
/* num attribs */
txCount = tvb_get_guint8 ( tvb , offset ) ;
cyclic_setup_attributes_root = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_tx_count , tvb , offset + + , 1 , ENC_NA ) ;
/* link list */
cyclic_setup_attributes = proto_item_add_subtree ( cyclic_setup_attributes_root , ett_cyclic_setup_attribs ) ;
while ( txCount > 0 ) {
linkno = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( cyclic_setup_attributes , hf_ecmp_cyclic_setup_linkno , tvb , offset + + , 1 , linkno ) ;
txCount - - ;
}
rxCount = tvb_get_guint8 ( tvb , offset ) ;
cyclic_setup_attributes_root = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_rx_count , tvb , offset + + , 1 , ENC_NA ) ;
/* link list */
cyclic_setup_attributes = proto_item_add_subtree ( cyclic_setup_attributes_root , ett_cyclic_setup_attribs ) ;
while ( rxCount > 0 ) {
linkno = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( cyclic_setup_attributes , hf_ecmp_cyclic_setup_linkno , tvb , offset + + , 1 , linkno ) ;
rxCount - - ;
}
}
break ;
case 10 : /* set */
{
/* num attribs */
cyclic_setup_attributes_root = proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_setup_attrib_count , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
/* attrib list */
cyclic_setup_attributes = proto_item_add_subtree ( cyclic_setup_attributes_root , ett_cyclic_setup_attribs ) ;
while ( offset < length ) {
proto_tree_add_item ( cyclic_setup_attributes , hf_ecmp_cyclic_setup_attrib , tvb , offset + + , 1 , ENC_BIG_ENDIAN ) ;
}
}
break ;
case 11 : /* get */
case 12 : /* get mappings */
case 6 : /* info */
/* add the attributesd as a tree */
add_cyclic_setup_attributes ( pinfo , offset , length , tvb , ecmp_tree ) ;
break ;
default :
/* display payload as hex bytes */
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , ENC_NA ) ;
break ;
}
}
}
/*a function to dissect "ProgramStatus" command */
static void program_status ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
/* Description:function to dissect Program Status command */
/* */
2015-12-04 09:40:44 +00:00
/* Inputs: */
2015-12-02 00:03:27 +00:00
/* offset - current offset of pointer within the ECMP frame */
/* command_value - function code of ECMP message */
2015-12-04 09:40:44 +00:00
/* request - (1 = query, 0 = response) */
2015-12-02 00:03:27 +00:00
/* tvb - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* ecmp_tree - Wireshark protocol tree */
2015-12-02 00:03:27 +00:00
/* tree - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* */
2015-12-02 00:03:27 +00:00
/* Returns: nothing */
2015-12-04 09:40:44 +00:00
/* */
/* Notes: for queries, the "offset" points to the "target". */
2015-12-02 00:03:27 +00:00
/* for responses, the "offset" points to the "status". */
2015-12-04 09:40:44 +00:00
/* */
/* sample ECMP Request Frame */
/* 0x61 - request code (program control) */
/* 0x00 - option terminator */
/* 0x00 - target (0 = default program) <======== offset */
/* */
/* sample ECMP Response Frame */
/* 0xE1 - response code (program control) */
/* 0x00 - option terminator */
2015-12-02 00:03:27 +00:00
/* 0x01 - running state (0=Stopped, 1=Running ... ) <======== offset */
2015-12-04 09:40:44 +00:00
/* 0x00 - additional items */
2015-12-02 00:03:27 +00:00
proto_item * ecmp_program_status_message_tree = NULL ;
/* differentiate between ECMP query and response */
if ( request ) {
/*display the program control details sub-tree */
ecmp_program_status_message_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 1 , ett_ecmp_program_status_message , NULL , " Program Status: (Query) " ) ;
/* read the target */
proto_tree_add_item ( ecmp_program_status_message_tree , hf_ecmp_program_status_target , tvb , offset , 1 , ENC_NA ) ;
} else {
/*display the program status details sub-tree */
ecmp_program_status_message_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_program_status_message , NULL , " Program Status: (Response) " ) ;
/* read and display the Status */
proto_tree_add_item ( ecmp_program_status_message_tree , hf_ecmp_program_status_status , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
/* read and display the Additional Items */
proto_tree_add_item ( ecmp_program_status_message_tree , hf_ecmp_program_status_additional_items , tvb , offset , 1 , ENC_NA ) ;
}
}
/*a function to dissect "ProgramControl" command */
static void program_control ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
/* Description:function to dissect Program Control command */
/* */
2015-12-04 09:40:44 +00:00
/* Inputs: */
2015-12-02 00:03:27 +00:00
/* offset - current offset of pointer within the ECMP frame */
/* command_value - function code of ECMP message */
2015-12-04 09:40:44 +00:00
/* request - (1 = query, 0 = response) */
2015-12-02 00:03:27 +00:00
/* tvb - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* ecmp_tree - Wireshark protocol tree */
2015-12-02 00:03:27 +00:00
/* tree - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* */
2015-12-02 00:03:27 +00:00
/* Returns: nothing */
2015-12-04 09:40:44 +00:00
/* */
2016-01-06 00:58:42 +00:00
/* Notes: for queries, the "offset" points to the "target". */
2015-12-02 00:03:27 +00:00
/* for responses, the "offset" points to the "status". */
2015-12-04 09:40:44 +00:00
/* */
/* sample ECMP Request Frame */
/* 0x60 - request code (program control) */
/* 0x00 - option terminator */
/* 0x00 - target (0 = default program) <======== offset */
/* 0x01 - command (1 = start the program) */
/* 0x00 - sub command */
/* */
/* sample ECMP Response Frame */
/* 0xE0 - response code (program control) */
/* 0x00 - option terminator */
/* 0x00 - status (0 = OK) <======== offset */
/* */
2015-12-02 00:03:27 +00:00
proto_item * ecmp_program_control_message_tree = NULL ;
/* differentiate between ECMP query and response */
if ( request ) {
/*display the program control details sub-tree */
ecmp_program_control_message_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 3 , ett_ecmp_program_control_message , NULL , " Program Control: (Query) " ) ;
/* read the target */
proto_tree_add_item ( ecmp_program_control_message_tree , hf_ecmp_program_control_target , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
/* read the command */
proto_tree_add_item ( ecmp_program_control_message_tree , hf_ecmp_program_control_command , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
/* read the subcommand */
proto_tree_add_item ( ecmp_program_control_message_tree , hf_ecmp_program_control_sub_command , tvb , offset , 1 , ENC_NA ) ;
} else {
/*display the program control details sub-tree */
ecmp_program_control_message_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 1 , ett_ecmp_program_control_message , NULL , " Program Control: (Response) " ) ;
/* read and display the Status */
proto_tree_add_item ( ecmp_program_control_message_tree , hf_ecmp_program_control_status , tvb , offset , 1 , ENC_NA ) ;
}
}
/*a function to dissect "ModbusPDU" command */
static void modbus_pdu ( int offset , gboolean request , tvbuff_t * tvb , packet_info * pinfo , proto_tree * ecmp_tree )
{
/* Description:function to dissect Modbus PDU ECMP transactions */
/* */
2015-12-04 09:40:44 +00:00
/* Inputs: */
2015-12-02 00:03:27 +00:00
/* offset - current offset of pointer within the ECMP frame */
/* command_value - function code of ECMP message */
2015-12-04 09:40:44 +00:00
/* request - (1 = query, 0 = response) */
2015-12-02 00:03:27 +00:00
/* tvb - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* ecmp-tree - Wireshark protocol tree */
2015-12-02 00:03:27 +00:00
/* tree - Wireshark protocol tree */
2015-12-04 09:40:44 +00:00
/* */
2015-12-02 00:03:27 +00:00
/* Returns: nothing */
2015-12-04 09:40:44 +00:00
/* */
2016-01-06 00:58:42 +00:00
/* Notes: for queries, the "offset" points to the "size". */
2015-12-02 00:03:27 +00:00
/* for responses, the "offset" points to the size. */
2015-12-04 09:40:44 +00:00
/* */
/* sample ECMP Request Frame (Read Holding Registers) */
/* 0x74 - request code (ModbusMaster) */
/* 0x00 - option terminator */
/* 0x00 - size msb <======== offset */
/* 0x05 - size lsb */
/* 0x03 - function code - read hold reg */
/* 0x07 - register address (#20.021) msb */
/* 0xE4 - register address lsb */
/* 0x00 - number registers msb */
/* 0x03 - number registers lsb */
/* */
/* sample ECMP Response Frame */
/* 0xF4 - response code (ModbusMaster) */
/* 0x00 - option terminator */
/* 0x00 - size msb <======== offset */
/* 0x08 - size lsb */
/* 0x03 - function code - read hold reg */
/* 0x06 - byte count */
/* 0x30 - register #2021 value 12345 msb */
/* 0x39 - register #2021 value lsb */
/* 0x03 - register #2022 value 787 msb */
/* 0x13 - register #2022 value lsb */
/* 0x00 - register #2023 value 100 msb */
/* 0x64 - register #2023 value lsb */
2015-12-02 00:03:27 +00:00
tvbuff_t * next_tvb ;
2015-12-04 09:40:44 +00:00
guint16 size = 0 ; /* from Modbus TCP/IP spec: number of bytes that follow */
2015-12-02 00:03:27 +00:00
int packet_type ;
/* differentiate between ECMP query and response */
if ( request ) {
/* read and display the Size */
size = tvb_get_ntohs ( tvb , offset ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_modbus_pdu_size , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
/* keep packet context */
packet_type = QUERY_PACKET ;
next_tvb = tvb_new_subset_length ( tvb , offset , size ) ;
call_dissector_with_data ( modbus_handle , next_tvb , pinfo , ecmp_tree , & packet_type ) ;
} else {
/* read and display the Size */
size = tvb_get_ntohs ( tvb , offset ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_modbus_pdu_size , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
packet_type = RESPONSE_PACKET ;
next_tvb = tvb_new_subset_length ( tvb , offset , size ) ;
call_dissector_with_data ( modbus_handle , next_tvb , pinfo , ecmp_tree , & packet_type ) ;
}
}
/*a function to dissect "Interrogate" command */
static void interrogate ( packet_info * pinfo , int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
/* Description: function to dissect Interrogate command */
/* */
2015-12-04 09:40:44 +00:00
/* Inputs: */
2015-12-02 00:03:27 +00:00
/* offset - current offset of pointer within the ECMP frame */
2015-12-04 09:40:44 +00:00
/* request - (1 = query, 0 = response) */
2015-12-02 00:03:27 +00:00
/* tvb - rather complex structure that has the frame data */
2015-12-04 09:40:44 +00:00
/* ecmp-tree - Wireshark protocol tree */
/* */
2015-12-02 00:03:27 +00:00
/* Returns: nothing */
2015-12-04 09:40:44 +00:00
/* */
2016-01-06 00:58:42 +00:00
/* Notes: for queries, the "offset" points to the "item type". */
2015-12-02 00:03:27 +00:00
/* for responses, the "offset" points to the "item type". */
2015-12-04 09:40:44 +00:00
/* */
/* sample ECMP Request Frame */
/* 0x02 - request code (interrogate) */
/* 0x00 - option terminator */
2015-12-02 00:03:27 +00:00
/* 0x00 - item type (0=ECMP command, 1=ECMP option) <==== offset */
/* 0x05 - count (number of commands/options to follow) */
2015-12-04 09:40:44 +00:00
/* 0x10 - item code #1 ECMP Read command */
/* 0x11 - item code #2 ECMP ReadWithType command */
2015-12-02 00:03:27 +00:00
/* 0x12 - item code #3 ECMP Write command */
2015-12-04 09:40:44 +00:00
/* 0x13 - item code #4 ECMP ObjectInfo command */
/* 0x14 - item code #5 ECMP GetNextObject command */
/* */
/* sample ECMP Response Frame */
/* 0x82 - response code (program control) */
/* 0x00 - option terminator */
2015-12-02 00:03:27 +00:00
/* 0x00 - item type (0=ECMP command, 1=ECMP option) <==== offset */
/* 0x05 - count (number of commands/options to follow) */
2015-12-04 09:40:44 +00:00
/* 0x10 - item code #1 */
2015-12-02 00:03:27 +00:00
/* 0x01 - supported (ECMP Read command) */
/* 0x11 - item code #2 */
/* 0x01 - supported (ECMP ReadWithType command) */
/* 0x12 - item code #3 */
/* 0x01 - supported (ECMP Write command) */
2015-12-04 09:40:44 +00:00
/* 0x13 - item code #4 */
2015-12-02 00:03:27 +00:00
/* 0x01 - supported (ECMP ObjectInfo command) */
2015-12-04 09:40:44 +00:00
/* 0x14 - item code #5 */
2015-12-02 00:03:27 +00:00
/* 0x01 - supported (ECMP GetNextObject command) */
2015-12-04 09:40:44 +00:00
/* */
/* */
2015-12-02 00:03:27 +00:00
/* Item Type: 0 = ECMP command */
/* 1 = ECMP option (not currently implemented) */
/* */
/* Item Code: 0 .. 0x7F for commands */
/* 0 .. 2 for options */
/* */
/* Item Support: 0 = not supported */
/* 1 = supported */
2015-12-04 09:40:44 +00:00
/* */
2015-12-02 00:03:27 +00:00
const guint8 interrogate_type_command = 0 ;
proto_tree * ecmp_interrogate_message_tree = NULL , * ecmp_interrogate_tree ;
proto_item * ecmp_interrogate_message_item = NULL ;
2015-12-04 09:40:44 +00:00
guint8 item_type = 0 ; /* 0=ECMP command, 1=ECMP option */
guint8 command_req = 0 ; /* ECMP command */
guint8 supported = 0 ; /* ECMP command support status: 1=supported, 0=not supported */
guint32 count = 0 ; /* number of ECMP commands to be checked */
guint32 j ; /* loop counter */
2015-12-02 00:03:27 +00:00
/* differentiate between ECMP query and response */
if ( request ) {
/* identify the ECMP command we're dissecting */
ecmp_interrogate_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_interrogate_message , NULL , " Interrogate: (Query) " ) ;
/* read the item_type (command/option setting) */
item_type = tvb_get_guint8 ( tvb , offset ) ;
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_interrogate_tree , hf_ecmp_interrogate_item_type , tvb , offset , 1 , ENC_NA ) ;
2015-12-02 00:03:27 +00:00
offset + = 1 ;
/* read the count */
count = tvb_get_guint8 ( tvb , offset ) ;
2015-12-04 09:58:38 +00:00
proto_tree_add_item ( ecmp_interrogate_tree , hf_ecmp_interrogate_count , tvb , offset , 1 , ENC_NA ) ;
2015-12-02 00:03:27 +00:00
offset + = 1 ;
/*create the interrogate details sub-tree */
2015-12-04 09:58:38 +00:00
ecmp_interrogate_message_tree = proto_tree_add_subtree ( ecmp_interrogate_tree , tvb , offset , count , ett_ecmp_interrogate_message , & ecmp_interrogate_message_item , " ECMP Commands to be Checked " ) ;
2015-12-02 00:03:27 +00:00
/* display the item_codes (commands to be checked) */
if ( item_type = = interrogate_type_command ) {
/* loop on the commands */
for ( j = 0 ; j < count ; j + + ) {
/* display the commands to be checked */
proto_tree_add_item ( ecmp_interrogate_message_tree , hf_ecmp_interrogate_command , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
}
proto_item_set_len ( ecmp_interrogate_message_item , count ) ;
} else {
expert_add_info ( pinfo , ecmp_interrogate_message_item , & ei_ecmp_options_not_implemented ) ;
}
} else {
/* identify the ECMP command we're dissecting */
ecmp_interrogate_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_interrogate_message , NULL , " Interrogate: (Response) " ) ;
/* read the item_type (command/option setting) */
item_type = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
/* read the count */
count = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
/* display the item_codes (commands to be checked) */
if ( item_type = = interrogate_type_command ) {
/*create the interrogate details sub-tree */
ecmp_interrogate_message_tree = proto_tree_add_subtree ( ecmp_interrogate_tree , tvb , offset , 1 , ett_ecmp_interrogate_message , & ecmp_interrogate_message_item , " ECMP Commands Supported " ) ;
/* loop on the commands */
for ( j = 0 ; j < count ; j + + ) {
/* get the command code */
command_req = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
/* get the support status */
supported = tvb_get_guint8 ( tvb , offset ) ;
offset + = 1 ;
/* display if the command is supported */
proto_tree_add_uint_format ( ecmp_interrogate_message_tree , hf_ecmp_interrogate_command , tvb , offset , 1 , command_req , " %s: %s " ,
try_val_to_str ( command_req , command_vals ) ,
try_val_to_str ( supported , Interrogate_support_state ) ) ;
}
} else {
expert_add_info ( pinfo , ecmp_interrogate_message_item , & ei_ecmp_options_not_implemented ) ;
}
}
}
static void tunnel_frame ( int offset , gboolean request , tvbuff_t * tvb , proto_tree * ecmp_tree )
{
proto_tree_add_item ( ecmp_tree , hf_ecmp_tunnel_control , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_tunnel_start_flag , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_tunnel_end_flag , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
/* if a request add the check output flag */
if ( request ) {
proto_tree_add_item ( ecmp_tree , hf_ecmp_tunnel_check_output_flag , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
}
offset + = 1 ;
/* Payload length */
proto_tree_add_item ( ecmp_tree , hf_ecmp_tunnel_size , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
offset + = 2 ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_data , tvb , offset , tvb_reported_length_remaining ( tvb , offset ) , ENC_NA ) ;
2015-12-04 09:58:38 +00:00
/*offset = tvb_reported_length(tvb);*/
2015-12-02 00:03:27 +00:00
}
2015-12-04 09:40:44 +00:00
/* dissect_ecmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2015-12-02 00:03:27 +00:00
*
2015-12-04 09:40:44 +00:00
* Purpose : Wireshark dissector for Emerson Control Techniques ECMP protocol
2015-12-02 00:03:27 +00:00
*
*
2015-12-04 09:40:44 +00:00
* Inputs : tvbuff_t * tvb - complex buffer structure holding the packet ' s bytes
* packet_info * pinfo - structure holding information about the packet
* proto_tree * tree - pointer to top - level tree ( print lines )
2015-12-02 00:03:27 +00:00
*
2015-12-04 09:40:44 +00:00
* Outputs : none
2015-12-02 00:03:27 +00:00
*
*
2015-12-04 09:40:44 +00:00
* Notes : if tree = NULL , packet capture is running and dissector will only write into the Summary Line ( Info Field )
2015-12-02 00:03:27 +00:00
*
2015-12-04 09:40:44 +00:00
* if tree is non - NULL , packet capture has stopped because a packet has been selected ( clicked )
* In this case , we will display quite a bit of additional information about the packet .
2015-12-02 00:03:27 +00:00
*
*
2015-12-04 09:40:44 +00:00
* To inspect the frame buffer ( very difficult using the * tvb pointer ) , it ' s best to add this little debug
2015-12-02 00:03:27 +00:00
* code snippet at the top of the program to copy the frame buffer into an array that you can inspect .
*
2015-12-04 09:40:44 +00:00
* static guint8 jimbuf [ 512 ] ; // temp buffer for current frame data
* static gint lenframe = 0 ; // num bytes in the frame
* static gint j = 0 ; // loop counter
* static gint16 saved_offset = 0 ; // saves offset for later restoration
2015-12-02 00:03:27 +00:00
*
2015-12-04 09:40:44 +00:00
* lenframe = tvb_captured_length ( tvb ) ; // get the length of the frame
* saved_offset = offset ; // temporarily save the "offset"
2015-12-02 00:03:27 +00:00
*
2015-12-04 09:40:44 +00:00
* for ( j = 0 ; j < lenframe ; j + + ) { // loop to copy the frame buffer
* jimbuf [ j ] = tvb_get_guint8 ( tvb , offset ) ; // Wireshark function to read the frame buffer
* offset + = 1 ;
* }
* offset = saved_offset ; // restore the offset
2015-12-02 00:03:27 +00:00
*
*
2015-12-04 09:40:44 +00:00
* Authors : Sarah Bouremoum , Jim Lynch , Luke Orehawa , Others
2015-12-02 00:03:27 +00:00
*/
static int dissect_ecmp_tcp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
/* Initialize the items and trees*/
proto_item * ecmp_item = NULL ;
proto_item * ecmp_transaction_id_item = NULL ;
proto_item * ecmp_chunk_id_item = NULL ;
proto_tree * ecmp_tree = NULL ;
/*initialise the values to be used */
guint8 command_value = 0 ;
gboolean request ;
guint8 transaction_id_value = 0 ;
2015-12-04 09:40:44 +00:00
int offset = 0 ; /* index used to read data from the buffer*/
gint framelen = 0 ; /* number of bytes in the frame */
2015-12-02 00:03:27 +00:00
/* note length of the UDP frame */
framelen = tvb_reported_length ( tvb ) ;
if ( framelen < ecmp_min_packet_size ) {
return 0 ;
}
/* this code block processes ECMP TCP messages (most of them) */
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , PROTO_TAG_ECMP ) ;
col_clear ( pinfo - > cinfo , COL_INFO ) ;
/*declaration of variables*/
offset = 4 ;
/*display the first line of the tree (ECMP data)*/
ecmp_item = proto_tree_add_item ( tree , proto_ecmp , tvb , 0 , - 1 , ENC_NA ) ;
ecmp_tree = proto_item_add_subtree ( ecmp_item , ett_ecmp ) ;
/* display the information for the destination address */
offset = add_transport_layer_frame ( offset , tvb , ecmp_tree , hf_ecmp_destination_address ) ;
/* display the information for the source address */
offset = add_transport_layer_frame ( offset , tvb , ecmp_tree , hf_ecmp_source_address ) ;
/*display the transaction ID*/
ecmp_transaction_id_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_transaction_id , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
transaction_id_value = tvb_get_guint8 ( tvb , offset ) ;
if ( transaction_id_value = = 0 ) {
proto_item_append_text ( ecmp_transaction_id_item , " %s " , " -> Not initiated by Request " ) ;
}
offset + + ;
request = ( ( tvb_get_guint8 ( tvb , offset + 2 ) & 0x80 ) = = 0 ) ;
if ( request ) {
/* Calls the function to display the Response size */
offset = get_response_size ( offset , tvb , ecmp_tree ) ;
/* Calls the function to display the command and request/response */
offset = add_command_codes ( pinfo , offset , tvb , ecmp_tree , transaction_id_value , & command_value ) ;
/* Calls the function to display the option codes and its data */
offset = add_option_codes ( offset , pinfo , tvb , ecmp_tree ) ;
/* up til here all code for the request should be the same */
switch ( command_value )
{
case ECMP_COMMAND_IDENTIFY :
/*Calls a method to display the attributes and its data */
add_attributes ( pinfo , offset , tvb , ecmp_tree , request ) ;
break ;
case ECMP_COMMAND_INFO :
/* Info command is just the request code, nothing else to display */
proto_tree_add_item ( ecmp_tree , hf_ecmp_info_command , tvb , 0 , - 1 , ENC_NA ) ;
/*do nothing, no more data is present */
break ;
case ECMP_COMMAND_INTERROGATE :
interrogate ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_READ :
get_parameter_definitions ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_READWITHTYPE :
get_parameter_definitions ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_WRITE :
get_parameter_definitions ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_OBJECTINFO :
get_parameter_definitions ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_GETNEXTOBJECTS :
get_parameter_definitions ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEOPEN :
file_open ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEREAD :
file_read ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEWRITE :
file_write ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILECLOSE :
file_close ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEINFO :
file_info ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEDELETE :
file_state_delete ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILESTATE :
file_state_delete ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEPOS :
file_pos ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILELIST :
file_list ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEEXISTS :
file_exists ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_CYCLICLINK :
cyclic_setup ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_PROGRAMCONTROL :
program_control ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_PROGRAMSTATUS :
program_status ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_CYCLICFRAME :
2015-12-04 09:58:38 +00:00
add_cyclic_frame_query ( offset , tvb , ecmp_tree ) ;
2015-12-02 00:03:27 +00:00
break ;
case ECMP_COMMAND_TUNNELFRAME :
tunnel_frame ( offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_MODBUSPDU :
modbus_pdu ( offset , request , tvb , pinfo , ecmp_tree ) ;
break ;
default :
proto_tree_add_expert ( ecmp_tree , pinfo , & ei_ecmp_unknown_command , tvb , 0 , - 1 ) ;
break ;
}
/* END of code to be modified */
} else {
guint8 chunk_id_value = 0 ;
gint8 status_value = 0 ;
status_value = ( gint8 ) tvb_get_guint8 ( tvb , offset ) ; /*stores a signed value for status */
proto_tree_add_item ( ecmp_tree , hf_ecmp_status , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( status_value > = 0 ) {
offset + + ;
chunk_id_value = tvb_get_guint8 ( tvb , offset ) ;
ecmp_chunk_id_item = proto_tree_add_item ( ecmp_tree , hf_ecmp_chunk_id , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
if ( chunk_id_value = = 0 ) {
proto_item_append_text ( ecmp_chunk_id_item , " %s " , " -> Response is NOT Chunked " ) ;
}
offset + + ;
/* Calls the function to display the option codes */
offset = add_command_codes ( pinfo , offset , tvb , ecmp_tree , transaction_id_value , & command_value ) ;
if ( ( status_value = = 0 ) | | ( status_value = = 1 ) ) {
/* Calls a method to display option codes */
offset = add_option_codes ( offset , pinfo , tvb , ecmp_tree ) ;
/* up til here all code for the response should be the same */
switch ( command_value )
{
case ECMP_COMMAND_IDENTIFY :
/*Call a method to add category data */
offset = add_category_codes ( offset , tvb , ecmp_tree ) ;
/*Call a method to add attributes */
add_attributes ( pinfo , offset , tvb , ecmp_tree , request ) ;
break ;
case ECMP_COMMAND_INFO :
add_info_response ( offset , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_INTERROGATE :
interrogate ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_READ :
get_parameter_responses ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_READWITHTYPE :
get_parameter_responses ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_WRITE :
get_parameter_responses ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_OBJECTINFO :
get_object_info_response ( pinfo , offset , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_GETNEXTOBJECTS :
get_parameter_responses ( pinfo , offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEOPEN :
file_open ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEREAD :
file_read ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEWRITE :
file_write ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILECLOSE :
file_close ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEINFO :
file_info ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEDELETE :
file_state_delete ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILESTATE :
file_state_delete ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEPOS :
file_pos ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILELIST :
file_list ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_FILEEXISTS :
file_exists ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_CYCLICLINK :
cyclic_setup ( pinfo , offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_PROGRAMCONTROL :
program_control ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_PROGRAMSTATUS :
program_status ( offset , request , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_CYCLICFRAME :
2015-12-04 09:58:38 +00:00
add_cyclic_frame ( offset , tvb , ecmp_tree ) ;
2015-12-02 00:03:27 +00:00
break ;
case ECMP_COMMAND_TUNNELFRAME :
tunnel_frame ( offset , command_value , tvb , ecmp_tree ) ;
break ;
case ECMP_COMMAND_MODBUSPDU :
modbus_pdu ( offset , request , tvb , pinfo , ecmp_tree ) ;
break ;
default :
proto_tree_add_expert ( ecmp_tree , pinfo , & ei_ecmp_unknown_command , tvb , 0 , - 1 ) ;
break ;
}
/********************************* END of code to be modified ***********************************/
}
}
}
return framelen ;
}
/* this code block processes ECMP UDP messages (cyclic data) */
static int dissect_ecmp_udp ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
{
proto_item * ecmp_item = NULL ;
proto_tree * ecmp_tree = NULL ;
proto_tree * ecmp_cyclic_data_32_bit_display_tree = NULL ;
proto_tree * ecmp_cyclic_data_16_bit_display_tree = NULL ;
proto_tree * ecmp_cyclic_data_8_bit_display_tree = NULL ;
guint8 command_value = 0 ;
guint8 type_value = 0 ;
guint8 transaction_id_value = 0 ;
2015-12-04 09:40:44 +00:00
guint16 offset = 0 ; /* index used to read data from the buffer*/
gint framelen = 0 ; /* number of bytes in the frame */
guint8 scheme = 0 ; /* 0=no scheme, 1=grandmaster setup */
2015-12-02 00:03:27 +00:00
/* note length of the UDP frame */
framelen = tvb_reported_length ( tvb ) ;
if ( framelen < ecmp_min_packet_size ) {
return 0 ;
}
/* display the "ECMP" protocol indication in the PROTOCOL field */
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , PROTO_TAG_ECMP ) ;
/* Clear out stuff in the info column */
col_clear ( pinfo - > cinfo , COL_INFO ) ;
/* adjust offset to point at transaction ID */
offset + = 2 ;
/*getting the information from the buffer*/
transaction_id_value = tvb_get_guint8 ( tvb , offset ) ;
/* adjust offset to point at ECMP query/response code */
offset + = 3 ;
/* calculate if it's a query or response (type_r_r) */
type_value = tvb_get_guint8 ( tvb , offset ) ;
/* determine the ECMP command code */
command_value = type_value & 0x7f ;
/* update offset to point to cyclic link number */
offset + = 2 ;
/* Information displayed in the Info column*/
col_add_fstr ( pinfo - > cinfo , COL_INFO , " %s, %s. Transaction ID: %d " ,
val_to_str ( command_value , command_vals , " Unknown Type:0x%02x " ) ,
val_to_str ( ( type_value & 0x80 ) > > 7 , type_rr , " Unknown Type:0x%02x " ) , transaction_id_value ) ;
/*display the first line of the tree (ECMP data)*/
2015-12-04 09:40:44 +00:00
ecmp_item = proto_tree_add_item ( tree , proto_ecmp , tvb , 0 , - 1 , ENC_NA ) ; /*item created*/
ecmp_tree = proto_item_add_subtree ( ecmp_item , ett_ecmp ) ; /*tree created*/
2015-12-02 00:03:27 +00:00
/* indicate cyclic link message */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_link_req_resp , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
/* display the cyclic link number */
proto_tree_add_item ( ecmp_tree , hf_ecmp_cyclic_link_number_display , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
offset + = 1 ;
if ( type_value & 0x80 ) {
/* response data handled here */
/* display the alignment */
proto_tree_add_item ( ecmp_tree , hf_ecmp_udp_alignment , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
/* display the scheme */
scheme = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_udp_scheme , tvb , offset , 1 , ENC_NA ) ;
offset + = 1 ;
/* if the scheme is 1, there is grandmaster data to be printed */
if ( scheme = = 1 ) {
proto_tree_add_item ( ecmp_tree , hf_ecmp_grandmaster , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
proto_tree_add_item ( ecmp_tree , hf_ecmp_process_time , tvb , offset , 8 , ENC_BIG_ENDIAN ) ;
offset + = 8 ;
}
/* create the Cyclic Data Display (guint32 format) sub-tree */
ecmp_cyclic_data_32_bit_display_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_cyclic_data_32_bit_display , NULL ,
" Cyclic Data (32-bit hex unsigned format): " ) ;
/* display the raw hex data for the cyclic data in a 32-bit format */
display_raw_cyclic_data ( cyclic_display_long_format , offset , framelen - offset , tvb , ecmp_cyclic_data_32_bit_display_tree ) ;
/* create the Cyclic Data Display (guint16 format) sub-tree */
ecmp_cyclic_data_16_bit_display_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_cyclic_data_16_bit_display , NULL ,
" Cyclic Data (16-bit hex unsigned format): " ) ;
/* display the raw hex data for the cyclic data in a 16-bit format */
display_raw_cyclic_data ( cyclic_display_word_format , offset , framelen - offset , tvb , ecmp_cyclic_data_16_bit_display_tree ) ;
/* display the raw hex data for the cyclic data in a guint8 format */
ecmp_cyclic_data_8_bit_display_tree = proto_tree_add_subtree ( ecmp_tree , tvb , offset , 2 , ett_ecmp_cyclic_data_8_bit_display , NULL ,
" Cyclic Data (8-bit hex unsigned format): " ) ;
/* display the raw hex data for the cyclic data in 8-bit format */
display_raw_cyclic_data ( cyclic_display_byte_format , offset , framelen - offset , tvb , ecmp_cyclic_data_8_bit_display_tree ) ;
}
return tvb_reported_length ( tvb ) ;
}
/* Function to register the protcol*/
/* Wireshark literally scans this file (packet-ecmp.c) to find this function */
/* note: this function MUST start in column 1, due to the scanning mentioned above */
void proto_register_ecmp ( void )
{
/* A header field is something you can search/filter on.
*
* We create a structure to register our fields . It consists of an
* array of hf_register_info structures , each of which are of the format
* { & ( field id ) , { name , abbrev , type , display , strings , bitmask , blurb , HFILL } } .
*/
static hf_register_info hf [ ] = {
{ & hf_ecmp_destination_address ,
{ " Destination Address scheme " , " ecmp.destination_address " , FT_UINT8 , BASE_DEC , VALS ( address_scheme ) , 0 , NULL , HFILL } } ,
{ & hf_ecmp_source_address ,
{ " Source Address scheme " , " ecmp.source_address " , FT_UINT8 , BASE_DEC , VALS ( address_scheme ) , 0 , NULL , HFILL } } ,
{ & hf_ecmp_diagnostic ,
{ " Diagnostic group " , " ecmp.diagnostic " , FT_UINT8 , BASE_DEC , VALS ( diagnostic ) , 0 , NULL , HFILL } } ,
{ & hf_ecmp_command ,
{ " Command " , " ecmp.command " , FT_UINT8 , BASE_DEC , VALS ( command_vals ) , 0x7F , NULL , HFILL } } ,
{ & hf_ecmp_option ,
{ " Option " , " ecmp.option " , FT_UINT8 , BASE_DEC , VALS ( option_code ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_type_rr ,
{ " Type " , " ecmp.type " , FT_UINT8 , BASE_DEC , VALS ( type_rr ) , 0x80 , " ECMP Type (request/response) " , HFILL } } ,
{ & hf_ecmp_chunking ,
{ " Chunks allowed " , " ecmp.chunking " , FT_UINT16 , BASE_DEC , NULL , 0xF000 , " ECMP number of chunks allowed " , HFILL } } ,
{ & hf_ecmp_max_response_size ,
{ " Maximum Response Size " , " ecmp.response_size " , FT_UINT16 , BASE_DEC , NULL , 0x0FFF , NULL , HFILL } } ,
{ & hf_ecmp_category ,
{ " Device " , " ecmp.category " , FT_UINT8 , BASE_DEC , VALS ( category ) , 0x0 , " ECMP Category (drive or option module) " , HFILL } } ,
{ & hf_ecmp_attribute ,
{ " Attribute " , " ecmp.attribute " , FT_UINT8 , BASE_DEC , VALS ( attribute ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_no_of_attributes ,
{ " Number of attributes " , " ecmp.attribute_number " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_status ,
{ " Status " , " ecmp.status " , FT_INT8 , BASE_DEC , VALS ( status ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_chunk_id ,
{ " Chunk ID " , " ecmp.chunkID " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_transaction_id ,
{ " Transaction ID " , " ecmp.transactionID " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_drive_type ,
{ " Product Type " , " ecmp.drive_type " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_drive_derivative ,
{ " Drive Derivative " , " ecmp.drive_derivative " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_drive_factory_fit_category_id ,
{ " Factory Fitted Option ID " , " ecmp.drive_factory_fit_category_id " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_category_id ,
{ " Option ID " , " ecmp.category_id " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_link_num ,
{ " Cyclic Link Number " , " ecmp.link_num " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_align ,
{ " Alignment " , " ecmp.cyclic_align " , FT_UINT8 , BASE_DEC , VALS ( cyclic_align ) , 0x0 , " ECMP Cyclic Data Alignment " , HFILL } } ,
{ & hf_ecmp_cyclic_scheme ,
{ " Scheme " , " ecmp.cyclic_scheme " , FT_UINT8 , BASE_DEC , VALS ( cyclic_scheme ) , 0x0 , " ECMP Cyclic Scheme " , HFILL } } ,
{ & hf_ecmp_cyclic_link_number_display ,
{ " Cyclic Link Number Display " , " ecmp.link_num_display " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_buffer_size ,
{ " Buffer Size " , " ecmp.buffer_size " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_max_response ,
{ " Maximum Response Time " , " ecmp.max_response " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_max_handle ,
{ " Maximum Handle Period " , " ecmp.max_handle " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_info_address ,
{ " Number of Default Route Addresses " , " ecmp.count " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_parameter_address ,
{ " Parameter Addressing Scheme " , " ecmp.parameter.address " , FT_UINT8 , BASE_DEC , VALS ( parameter_address_scheme ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_parameter_definitions ,
{ " Number of Parameter Definitions " , " ecmp.parameter.definitions " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_parameter_responses ,
{ " Number of Parameter Responses " , " ecmp.parameter.response " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_parameter_status ,
{ " Parameter Status " , " ecmp.parameter.status " , FT_INT8 , BASE_DEC , VALS ( parameter_access_status ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_type ,
{ " Parameter Data Type " , " ecmp.parameter.data_type " , FT_UINT8 , BASE_DEC , VALS ( parameter_data_types ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_info_type ,
{ " Info Type " , " ecmp.info_type " , FT_UINT8 , BASE_DEC , VALS ( info_type ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_status ,
{ " File Status " , " ecmp.file.status " , FT_INT8 , BASE_DEC , VALS ( file_status ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_handle ,
{ " File Handle " , " ecmp.file.handle " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_attributes ,
{ " Attribute " , " ecmp.file.attribute " , FT_UINT8 , BASE_DEC , VALS ( file_attributes ) , 0x0 , " File attributes " , HFILL } } ,
{ & hf_ecmp_file_ref_point ,
{ " Reference Point " , " ecmp.file.reference " , FT_UINT8 , BASE_DEC , VALS ( file_ref_point ) , 0x0 , " File reference points " , HFILL } } ,
{ & hf_ecmp_tunnel_control ,
{ " Control " , " ecmp.tunnel_control " , FT_UINT8 , BASE_DEC , NULL , 0x0 , " Tunnel frame control field " , HFILL } } ,
{ & hf_ecmp_tunnel_start_flag ,
{ " Start " , " ecmp.tunnel_control.start " , FT_BOOLEAN , 8 , NULL , TUNNEL_START_FLAG , " Tunnel frame control field start flag " , HFILL } } ,
{ & hf_ecmp_tunnel_end_flag ,
{ " End " , " ecmp.tunnel_control.end " , FT_BOOLEAN , 8 , NULL , TUNNEL_END_FLAG , " Tunnel frame control field end flag " , HFILL } } ,
{ & hf_ecmp_tunnel_check_output_flag ,
{ " Check Output " , " ecmp.tunnel_control.check " , FT_BOOLEAN , 8 , NULL , TUNNEL_CHECK_OUTPUT_FLAG , " Tunnel frame control field check output flag " , HFILL } } ,
{ & hf_ecmp_tunnel_size ,
{ " Size " , " ecmp.tunnel_size " , FT_UINT16 , BASE_DEC , NULL , 0x0 , " Tunnel frame payload size " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_mode ,
{ " Mode " , " ecmp.cyclic_setup.mode " , FT_UINT8 , BASE_DEC , VALS ( cyclic_setup_mode ) , 0x0 , " Cyclic setup mode " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_linkno ,
{ " Link No " , " ecmp.cyclic_setup.linkno " , FT_UINT8 , BASE_DEC , NULL , 0x0 , " Cyclic setup link no " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_dir ,
{ " Direction " , " ecmp.cyclic_setup.direction " , FT_UINT8 , BASE_DEC , VALS ( cyclic_setup_link_dir ) , 0x0 , " Cyclic setup link direction " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_attrib_count ,
{ " Count " , " ecmp.cyclic_setup.attrib_count " , FT_UINT8 , BASE_DEC , NULL , 0x0 , " Cyclic setup attribute count " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_attrib ,
{ " Attribute " , " ecmp.cyclic_setup.attrib " , FT_UINT8 , BASE_DEC , VALS ( cyclic_attributes ) , 0x0 , " Cyclic setup attribute " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_rsp_status ,
{ " Status " , " ecmp.cyclic_setup.rsp_status " , FT_INT8 , BASE_DEC , NULL , 0x0 , " Cyclic setup status " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_rsp_err_idx ,
{ " Error Index " , " ecmp.cyclic_setup.rsp_err_idx " , FT_UINT8 , BASE_DEC , NULL , 0x0 , " Cyclic setup error index " , HFILL } } ,
{ & hf_ecmp_cyclic_setup_link_exists ,
{ " Existence State " , " ecmp.cyclic_setup.exists.state " , FT_UINT8 , BASE_DEC , VALS ( cyclic_setup_link_exists ) , 0x0 , " Cyclic setup exists state " , HFILL } } ,
{ & hf_ecmp_cyclic_link_req_resp ,
{ " Cyclic Link - Request-Response " , " ecmp.cyclic_link.request.response " , FT_UINT8 , BASE_DEC , VALS ( cyclic_link_req_resp ) , 0x0 , " Cyclic link request - response " , HFILL } } ,
{ & hf_ecmp_attribute_string ,
{ " Attribute string " , " ecmp.attribute_string " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_name ,
{ " File name " , " ecmp.file_name " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_directory ,
{ " Directory " , " ecmp.directory " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_names_scheme ,
{ " Names Scheme " , " ecmp.names_scheme " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_variable_name ,
{ " Variable name " , " ecmp.variable_name " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_unit_id_string ,
{ " Unit ID String " , " ecmp.unit_id_string " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_ecmp_string ,
{ " ECMP string " , " ecmp.ecmp_string " , FT_UINT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_info_command ,
{ " Info command data " , " ecmp.info_command " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_process_time ,
{ " ProcessAt time " , " ecmp.processat_time " , FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_frame_time ,
{ " Cyclic frame time " , " ecmp.cyclic_frame_time " , FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_grandmaster ,
{ " Grandmaster " , " ecmp.grandmaster " , FT_EUI64 , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data ,
{ " Data " , " ecmp.data " , FT_BYTES , SEP_SPACE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_response_data ,
{ " Response Data " , " ecmp.response_data " , FT_BYTES , SEP_SPACE , NULL , 0x0 , NULL , HFILL } } ,
/* Generated from convert_proto_tree_add_text.pl */
{ & hf_ecmp_physical_address , { " Physical address " , " ecmp.physical_address " , FT_UINT8 , BASE_DEC , NULL , 0x0F , NULL , HFILL } } ,
{ & hf_ecmp_logical_address , { " Logical address " , " ecmp.logical_address " , FT_UINT8 , BASE_DEC , NULL , 0xF0 , NULL , HFILL } } ,
{ & hf_ecmp_primary_colour , { " Primary Colour " , " ecmp.primary_colour " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_secondary_colour , { " Secondary Colour " , " ecmp.secondary_colour " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_subsequent_object_requests , { " Number of subsequent object requests " , " ecmp.number_of_subsequent_object_requests " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_decimal_places , { " Number of decimal places " , " ecmp.number_of_decimal_places " , FT_INT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_no_information_available , { " No Information available " , " ecmp.no_information_available " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_bit_default_unipolar , { " BU- Bit default/Unipolar " , " ecmp.param_format.bit_default_unipolar " , FT_UINT32 , BASE_DEC , NULL , 0x00000001 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_write_allowed , { " W- Write allowed " , " ecmp.param_format.write_allowed " , FT_UINT32 , BASE_DEC , NULL , 0x00000002 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_read_not_allowed , { " NR- Read not allowed " , " ecmp.param_format.read_not_allowed " , FT_UINT32 , BASE_DEC , NULL , 0x00000004 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_protected_from_destinations , { " PT- Protected from destinations " , " ecmp.param_format.protected_from_destinations " , FT_UINT32 , BASE_DEC , NULL , 0x00000008 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_parameter_not_visible , { " NV- Parameter not visible " , " ecmp.param_format.parameter_not_visible " , FT_UINT32 , BASE_DEC , NULL , 0x00000010 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_not_clonable , { " NC- Not clonable " , " ecmp.param_format.not_clonable " , FT_UINT32 , BASE_DEC , NULL , 0x00000020 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_voltage_or_current_rating_dependant , { " RA- Voltage or current rating dependant " , " ecmp.param_format.voltage_or_current_rating_dependant " , FT_UINT32 , BASE_DEC , NULL , 0x00000040 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_parameter_has_no_default , { " ND- Parameter has no default " , " ecmp.param_format.parameter_has_no_default " , FT_UINT32 , BASE_DEC , NULL , 0x00000080 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_number_of_decimal_places , { " DP- Number of Decimal places " , " ecmp.param_format.number_of_decimal_places " , FT_UINT32 , BASE_DEC , NULL , 0x00000F00 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_variable_maximum_and_minimum , { " VM- Variable maximum and minimum " , " ecmp.param_format.variable_maximum_and_minimum " , FT_UINT32 , BASE_DEC , NULL , 0x00001000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_string_parameter , { " TE- String parameter " , " ecmp.param_format.string_parameter " , FT_UINT32 , BASE_DEC , NULL , 0x00002000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_desitination_set_up_parameter , { " DE- Desitination set-up parameter " , " ecmp.param_format.desitination_set_up_parameter " , FT_UINT32 , BASE_DEC , NULL , 0x00004000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_filtered_when_displayed , { " FI- Filtered when displayed " , " ecmp.param_format.filtered_when_displayed " , FT_UINT32 , BASE_DEC , NULL , 0x00008000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_pseudo_read_only , { " PR- Pseudo read only " , " ecmp.param_format.pseudo_read_only " , FT_UINT32 , BASE_DEC , NULL , 0x00010000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_display_format , { " DF- Display Format " , " ecmp.param_format.display_format " , FT_UINT32 , BASE_DEC , VALS ( display_format ) , 0x001E0000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_floating_point_value , { " FL- Floating point value " , " ecmp.param_format.floating_point_value " , FT_UINT32 , BASE_DEC , NULL , 0x00200000 , NULL , HFILL } } ,
{ & hf_ecmp_param_format_units , { " UNITS " , " ecmp.param_format.units " , FT_UINT32 , BASE_DEC , VALS ( format_units ) , 0x0FC00000 , NULL , HFILL } } ,
{ & hf_ecmp_string_id , { " String ID " , " ecmp.string_id " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_address_scheme_menu , { " Menu " , " ecmp.address_scheme.menu " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_address_scheme_parameter , { " Parameter " , " ecmp.address_scheme.parameter " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_address_scheme_slot , { " Slot " , " ecmp.address_scheme.slot " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_address_scheme_null_byte_size , { " NULL byte size " , " ecmp.address_scheme.null_byte_size " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_display_unit_id , { " Unit ID " , " ecmp.display_unit_id " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_boolean , { " Data " , " ecmp.data.boolean " , FT_UINT8 , BASE_DEC , NULL , 0x01 , NULL , HFILL } } ,
{ & hf_ecmp_data_int8 , { " Data " , " ecmp.data.int8 " , FT_INT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_uint8 , { " Data " , " ecmp.data.uint8 " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_int16 , { " Data " , " ecmp.data.int16 " , FT_INT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_uint16 , { " Data " , " ecmp.data.uint16 " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_int32 , { " Data " , " ecmp.data.int32 " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_uint32 , { " Data " , " ecmp.data.uint32 " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_int64 , { " Data " , " ecmp.data.int64 " , FT_INT64 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_uint64 , { " Data " , " ecmp.data.uint64 " , FT_UINT64 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_float , { " Data " , " ecmp.data.float " , FT_FLOAT , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_data_double , { " Data " , " ecmp.data.double " , FT_DOUBLE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_access_mode , { " Access Mode " , " ecmp.access_mode " , FT_UINT8 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_open_in_non_blocking_mode , { " Open in non-blocking mode " , " ecmp.open_in_non_blocking_mode " , FT_BOOLEAN , 8 , NULL , 0x80 , NULL , HFILL } } ,
{ & hf_ecmp_open_file_relative_to_specified_directory_handle , { " Open file relative to specified directory handle " , " ecmp.open_file_relative_to_specified_directory_handle " , FT_BOOLEAN , 8 , NULL , 0x40 , NULL , HFILL } } ,
{ & hf_ecmp_file_access_mode , { " File Access Mode " , " ecmp.file_access_mode " , FT_UINT8 , BASE_DEC , VALS ( file_status_mode ) , 0x0F , NULL , HFILL } } ,
{ & hf_ecmp_additional_scheme , { " Additional Scheme " , " ecmp.additional_scheme " , FT_UINT8 , BASE_DEC , VALS ( additional_scheme_vals ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_scheme_data_length , { " Length " , " ecmp.scheme_data_length " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_requested_bytes , { " Number of requested bytes " , " ecmp.number_of_requested_bytes " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_bytes_transferred , { " Number of bytes transferred " , " ecmp.number_of_bytes_transferred " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_crc , { " CRC " , " ecmp.crc " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_ref_offset , { " Offset " , " ecmp.ref_offset " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_number_of_files_to_list , { " Number of files to list " , " ecmp.number_of_files_to_list " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_hash , { " Hash " , " ecmp.file_hash " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_item_type , { " Item type " , " ecmp.item_type " , FT_UINT8 , BASE_DEC , VALS ( item_type_vals ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_integrity , { " File Integrity " , " ecmp.file_integrity " , FT_UINT8 , BASE_DEC , VALS ( file_integrity_vals ) , 0x01 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_read_only , { " Read Only " , " ecmp.display_attr.read_only " , FT_BOOLEAN , 8 , NULL , 0x01 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_hidden , { " Hidden " , " ecmp.display_attr.hidden " , FT_BOOLEAN , 8 , NULL , 0x02 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_system , { " System " , " ecmp.display_attr.system " , FT_BOOLEAN , 8 , NULL , 0x04 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_volume_label , { " Volume Label " , " ecmp.display_attr.volume_label " , FT_BOOLEAN , 8 , NULL , 0x08 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_subdirectory , { " Subdirectory " , " ecmp.display_attr.subdirectory " , FT_BOOLEAN , 8 , NULL , 0x10 , NULL , HFILL } } ,
{ & hf_ecmp_display_attr_archive , { " Archive " , " ecmp.display_attr.archive " , FT_BOOLEAN , 8 , NULL , 0x20 , NULL , HFILL } } ,
{ & hf_ecmp_display_creation , { " Display creation " , " ecmp.display_creation " , FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_display_modification , { " Display modification " , " ecmp.display_modification " , FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_interrogate_item_type , { " Item Type " , " ecmp.interrogate_item_type " , FT_UINT8 , BASE_DEC , VALS ( Interrogate_command_option_state ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_interrogate_count , { " Count " , " ecmp.interrogate_count " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_modbus_pdu_size , { " Size " , " ecmp.modbus_pdu_size " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
#if 0
{ & hf_ecmp_destination_scheme , { " Destination Scheme " , " ecmp.destination_scheme " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
# endif
{ & hf_ecmp_program_control_target , { " Target " , " ecmp.program_control_target " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_control_command , { " Command " , " ecmp.program_control_command " , FT_UINT8 , BASE_DEC , VALS ( command_code_list ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_control_sub_command , { " Sub-Command " , " ecmp.program_control_sub_command " , FT_UINT8 , BASE_DEC , VALS ( sub_command_code_list ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_control_status , { " Status " , " ecmp.program_control_status " , FT_UINT8 , BASE_DEC , VALS ( status_list ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_status_target , { " Target " , " ecmp.program_status_target " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_status_status , { " Status " , " ecmp.program_status_status " , FT_UINT8 , BASE_DEC , VALS ( running_state_list ) , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_program_status_additional_items , { " Additional Items " , " ecmp.program_status_additional_items " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_setup_max_mappings , { " Max Mappings " , " ecmp.cyclic_setup.max_mappings " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_setup_start_offset , { " Start Offset " , " ecmp.cyclic_setup.start_offset " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_setup_tx_count , { " Tx Count " , " ecmp.cyclic_setup.tx_count " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_setup_rx_count , { " Rx Count " , " ecmp.cyclic_setup.rx_count " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_udp_alignment , { " Alignment " , " ecmp.udp_alignment " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_udp_scheme , { " Scheme " , " ecmp.udp_scheme " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_cyclic_data , { " Cyclic Data " , " ecmp.cyclic_data " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_version_summary , { " Version summary " , " ecmp.version_summary " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_min_param_menu , { " Min parameter in menu " , " ecmp.min_param_menu " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_max_param_menu , { " Max parameter in menu " , " ecmp.max_param_menu " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_file_length , { " File length " , " ecmp.file_length " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_mec_offset , { " mec_offset " , " ecmp.mec_offset " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_sample_period , { " Sample period " , " ecmp.sample_period " , FT_RELATIVE_TIME , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_timeout , { " RX Timeout " , " ecmp.rx_timeout " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_action , { " Action " , " ecmp.rx_action " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_event_destination , { " Event Destination " , " ecmp.rx_event_destination " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_event , { " Event " , " ecmp.rx_event " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_late_handler_action , { " Action " , " ecmp.rx_late_handler_action " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_late_handler_event_destination , { " Event Destination " , " ecmp.rx_late_handler_event_destination " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_rx_late_handler_event , { " Event " , " ecmp.rx_late_handler_event " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_transport_addr_scheme , { " Scheme " , " ecmp.transport_addr_scheme " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_transport_addr , { " Transport address " , " ecmp.transport_addr " , FT_IPv4 , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_mapping_item_offset , { " Offset " , " ecmp.mapping_item_offset " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_mapping_item_scheme , { " Scheme " , " ecmp.mapping_item_scheme " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_setup_attribute , { " Attribute " , " ecmp.setup_attribute " , FT_UINT8 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_mec_period , { " mec period " , " ecmp.mec_period " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_ecmp_interrogate_command , { " Command " , " ecmp.interrogate_command " , FT_UINT8 , BASE_DEC , VALS ( command_vals ) , 0x0 , NULL , HFILL } }
} ;
/* array to store pointers to the ids of the subtrees that we may be creating */
static gint * ett [ ] = {
& ett_ecmp ,
& ett_ecmp_address ,
& ett_ecmp_response_size ,
& ett_ecmp_command ,
& ett_ecmp_category ,
& ett_ecmp_option ,
& ett_ecmp_option_data ,
& ett_ecmp_attribute ,
& ett_ecmp_attribute_data ,
& ett_ecmp_cyclic_scheme ,
& ett_ecmp_interrogate_message ,
& ett_ecmp_info_type ,
& ett_ecmp_info_count ,
& ett_ecmp_param_address ,
& ett_ecmp_access_mode ,
& ett_ecmp_access_file ,
& ett_ecmp_file_read ,
& ett_ecmp_file_write ,
& ett_ecmp_file_info ,
& ett_ecmp_file_info_att ,
& ett_ecmp_file_position ,
& ett_ecmp_file_list_no ,
& ett_ecmp_file_list ,
& ett_ecmp_tunnel_3s_goodframe ,
& ett_ecmp_tunnel_3s_size ,
& ett_ecmp_tunnel_3s_service ,
& ett_cyclic_setup_attribs ,
& ett_cyclic_setup_transport_addr ,
& ett_cyclic_setup_attrib_item ,
& ett_ecmp_cyclic_data_32_bit_display ,
& ett_ecmp_cyclic_data_16_bit_display ,
& ett_ecmp_cyclic_data_8_bit_display ,
& ett_ecmp_modbus_pdu_message ,
& ett_ecmp_program_control_message ,
& ett_ecmp_program_status_message
} ;
static ei_register_info ei [ ] = {
{ & ei_ecmp_unknown_command , { " ecmp.unknown_command " , PI_PROTOCOL , PI_WARN , " Unknown Command " , EXPFILL } } ,
{ & ei_ecmp_color , { " ecmp.color_invalid " , PI_PROTOCOL , PI_WARN , " Invalid color data value " , EXPFILL } } ,
{ & ei_ecmp_option , { " ecmp.ecmp_option.unknown " , PI_PROTOCOL , PI_WARN , " ERROR - Unrecognised Option Code " , EXPFILL } } ,
{ & ei_ecmp_data_type , { " ecmp.data_type.unknown " , PI_PROTOCOL , PI_WARN , " Unknown Data Type " , EXPFILL } } ,
{ & ei_ecmp_parameter_addressing_scheme , { " ecmp.incorrect_parameter_addressing_scheme " , PI_PROTOCOL , PI_WARN , " Incorrect parameter addressing scheme " , EXPFILL } } ,
{ & ei_ecmp_info_type , { " ecmp.info_type.unknown " , PI_PROTOCOL , PI_WARN , " Unknown info type " , EXPFILL } } ,
{ & ei_ecmp_attribute_type , { " ecmp.attribute_type.unknown " , PI_PROTOCOL , PI_WARN , " Wrong attribute type " , EXPFILL } } ,
{ & ei_ecmp_item_type , { " ecmp.item_type.unknown " , PI_PROTOCOL , PI_WARN , " Unknown item type " , EXPFILL } } ,
{ & ei_ecmp_options_not_implemented , { " ecmp.options_not_implemented " , PI_UNDECODED , PI_WARN , " ECMP Options Not Implemented " , EXPFILL } }
} ;
expert_module_t * expert_ecmp ;
proto_ecmp = proto_register_protocol ( " ECMP " , PROTO_TAG_ECMP , " ecmp " ) ;
/* full name short name and abbreviation (display filter name)*/
proto_register_field_array ( proto_ecmp , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
expert_ecmp = expert_register_protocol ( proto_ecmp ) ;
expert_register_field_array ( expert_ecmp , ei , array_length ( ei ) ) ;
}
/* Function to initialise the dissector*/
/* Wireshark literally scans this file (packet-ecmp.c) to find this function */
void proto_reg_handoff_ecmp ( void )
{
static gboolean initialized = FALSE ;
static dissector_handle_t ecmp_tcp_handle , ecmp_udp_handle ;
if ( ! initialized ) {
2015-12-09 03:49:44 +00:00
ecmp_tcp_handle = create_dissector_handle ( dissect_ecmp_tcp , proto_ecmp ) ;
ecmp_udp_handle = create_dissector_handle ( dissect_ecmp_udp , proto_ecmp ) ;
2015-12-02 00:03:27 +00:00
/* Cyclic frames are over UDP and non-cyclic are over TCP */
dissector_add_uint ( " udp.port " , global_ecmp_port , ecmp_udp_handle ) ;
dissector_add_uint ( " tcp.port " , global_ecmp_port , ecmp_tcp_handle ) ;
2015-12-04 09:40:44 +00:00
initialized = TRUE ;
2015-12-02 00:03:27 +00:00
}
2015-12-04 09:40:44 +00:00
/* Modbus dissector hooks */
2016-03-16 13:02:52 +00:00
modbus_handle = find_dissector_add_dependency ( " modbus " , proto_ecmp ) ;
2015-12-02 00:03:27 +00:00
proto_modbus = proto_get_id_by_filter_name ( " modbus " ) ;
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 8
* tab - width : 8
* indent - tabs - mode : t
* End :
*
* vi : set shiftwidth = 8 tabstop = 8 noexpandtab :
* : indentSize = 8 : tabSize = 8 : noTabs = false :
*/