2014-07-16 16:50:41 +00:00
|
|
|
/* packet-cp2179.c
|
2018-09-06 22:14:51 +00:00
|
|
|
* Routines for Communication Protocol 2179 (aka "Cooper 2179") Dissection
|
2014-07-16 16:50:41 +00:00
|
|
|
* By Qiaoyin Yang (qiaoyin[DOT]yang[AT]gmail.com
|
|
|
|
* Copyright 2014-2015,Schweitzer Engineering Laboratories
|
|
|
|
*
|
2018-09-06 22:14:51 +00:00
|
|
|
* Enhancements by Chris Bontje (cbontje<at>gmail<dot>com, Aug 2018
|
2014-07-16 16:50:41 +00:00
|
|
|
************************************************************************************************
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2018-02-12 11:23:27 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2014-07-16 16:50:41 +00:00
|
|
|
*
|
|
|
|
************************************************************************************************
|
|
|
|
CP2179 protocol is a serial based protocol. The 2179 protocol is implemented with minor variations between vendors.
|
|
|
|
The RTAC implemented the 2179 client supporting a limited function codes and command codes. The RTAC doesn't support
|
|
|
|
multiple function codes in a single request and the dissector also doesn't support decoding these or corresponding responses.
|
|
|
|
* Dissector Notes:
|
|
|
|
A brief explanation of how a request and response messages are formulated in 2179 protocol.
|
|
|
|
The CP2179 request messages will follow the pattern below:
|
|
|
|
AA AA BB CC DD DD XX XX .... XX EE EE
|
|
|
|
|
|
|
|
A = 16-bit address field. The Most significant 5 bit is the Client address, the 11 bits for RTU address.
|
|
|
|
B = 8-bit Function code
|
|
|
|
C = 8-bit Command code
|
|
|
|
D = 16-bit Number of characters in the data field.
|
|
|
|
X = data field
|
|
|
|
E = 16-bit CRC
|
|
|
|
|
|
|
|
AA AA BB CC DD EE EE XX XX ... XX FF FF
|
|
|
|
|
|
|
|
A = 16-bit address field. The Most significant 5 bit is the Client address, the 11 bits for RTU address.
|
|
|
|
B = 8-bit Function code
|
|
|
|
C = 8-bit Status
|
|
|
|
D = 8-bit Port Status
|
|
|
|
E = 16-bit Number of characters
|
|
|
|
X = data field
|
|
|
|
F = 16-bit CRC
|
|
|
|
************************************************************************************************/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/conversation.h>
|
|
|
|
#include <epan/prefs.h>
|
2016-01-25 01:10:20 +00:00
|
|
|
#include <epan/proto_data.h>
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2014-10-04 14:49:49 +00:00
|
|
|
void proto_reg_handoff_cp2179(void);
|
|
|
|
void proto_register_cp2179(void);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Message Length Constants */
|
2014-07-16 16:50:41 +00:00
|
|
|
#define CP2179_MIN_LENGTH 7
|
|
|
|
#define RESPONSE_HEADER_SIZE 7 /*includes addr, addr, function, status, port status, number of characters */
|
|
|
|
#define BASIC_SCAN_REQ_LEN 8
|
|
|
|
#define SPECIAL_CALC_REQ_ALL_LEN 8
|
|
|
|
#define SBO_OPERATE_REQ_LEN 8
|
|
|
|
#define SPECIAL_CALC_REQ_RANGE_LEN 9
|
|
|
|
#define SBO_SELECT_REQ_LEN 9
|
|
|
|
#define SBO_OPERATE_REPLY_LEN 9
|
|
|
|
#define SBO_SELECT_REPLY_LEN 10
|
|
|
|
|
|
|
|
static gboolean cp2179_telnet_clean = TRUE;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Message Types */
|
|
|
|
#define BASIC_SCAN_REQUEST 1
|
|
|
|
#define BASIC_SCAN_RESPONSE 2
|
|
|
|
#define SPECIAL_CALC_REQUEST_ALL 3
|
|
|
|
#define SPECIAL_CALC_RESPONSE_ALL 4
|
|
|
|
#define SPECIAL_CALC_REQUEST_RANGE 5
|
|
|
|
#define SPECIAL_CALC_RESPONSE_RANGE 6
|
|
|
|
#define SPECIAL_CALC_RESPONSE 7
|
|
|
|
#define SCAN_INCLUSIVE_16_ANALOG_REQUEST 8
|
|
|
|
#define SCAN_INCLUSIVE_16_ANALOG_RESPONSE 9
|
|
|
|
#define SBO_SELECT_REQUEST 10
|
|
|
|
#define SBO_SELECT_RESPONSE 11
|
|
|
|
#define SBO_OPERATE_REQUEST 12
|
|
|
|
#define SBO_OPERATE_RESPONSE 13
|
|
|
|
#define INIT_RTU_REQUEST 14
|
|
|
|
#define INIT_RTU_RESPONSE 15
|
|
|
|
#define RESET_ACC_REQUEST 16
|
|
|
|
#define RESET_ACC_RESPONSE 17
|
|
|
|
#define TIMETAG_INFO_REQUEST 18
|
|
|
|
#define TIMETAG_INFO_RESPONSE 19
|
|
|
|
#define RST_RESPONSE 20
|
|
|
|
|
|
|
|
/* Message type Lookup */
|
|
|
|
static const value_string cp2179_messagetype_vals[] = {
|
|
|
|
{BASIC_SCAN_REQUEST, "Basic Scan Request"},
|
|
|
|
{BASIC_SCAN_RESPONSE, "Basic Scan Response"},
|
2014-07-16 16:50:41 +00:00
|
|
|
{SPECIAL_CALC_REQUEST_ALL, "Special Calc Request All"},
|
|
|
|
{SPECIAL_CALC_RESPONSE_ALL, "Special Calc Response All"},
|
|
|
|
{SPECIAL_CALC_REQUEST_RANGE, "Special Calc Request a Range"},
|
|
|
|
{SPECIAL_CALC_RESPONSE_RANGE, "Special Calc Response a Range"},
|
|
|
|
{SPECIAL_CALC_RESPONSE, "Special Calc Response"},
|
|
|
|
{SCAN_INCLUSIVE_16_ANALOG_REQUEST, "Scan Inclusive Request"},
|
|
|
|
{SCAN_INCLUSIVE_16_ANALOG_RESPONSE, "Scan Inclusive Response"},
|
|
|
|
{SBO_SELECT_REQUEST, "SBO Select Request"},
|
|
|
|
{SBO_SELECT_RESPONSE, "SBO Select Response"},
|
|
|
|
{SBO_OPERATE_REQUEST, "SBO Operate Request"},
|
|
|
|
{SBO_OPERATE_RESPONSE, "SBO Operate Response"},
|
|
|
|
{INIT_RTU_REQUEST, "INIT RTU Request"},
|
|
|
|
{INIT_RTU_RESPONSE, "INIT RTU Response"},
|
|
|
|
{RESET_ACC_REQUEST, "RESET Accumulator Request"},
|
|
|
|
{RESET_ACC_RESPONSE, "RESET Accumulator Response"},
|
2018-09-06 22:14:51 +00:00
|
|
|
{TIMETAG_INFO_REQUEST, "Time-Tagged Information Request"},
|
|
|
|
{TIMETAG_INFO_RESPONSE, "Time-Tagged Information Response"},
|
|
|
|
{RST_RESPONSE, "RST Response - Out of Sequence SBO"},
|
2014-07-16 16:50:41 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
static value_string_ext cp2179_messagetype_vals_ext = VALUE_STRING_EXT_INIT(cp2179_messagetype_vals);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* List contains request data */
|
|
|
|
typedef struct {
|
2018-09-06 22:14:51 +00:00
|
|
|
wmem_list_t *request_frame_data;
|
2014-07-16 16:50:41 +00:00
|
|
|
} cp2179_conversation;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* CP2179 function codes */
|
|
|
|
#define BASIC_SCAN 0x00
|
|
|
|
#define SCAN_INCLUSIVE 0x01
|
|
|
|
#define SCAN_FOR_SPECIAL_CALC 0x03
|
|
|
|
#define RETRIEVE_TIME_TAGGED_INFO 0x04 /* not supported by the RTAC */
|
|
|
|
#define SCAN_BY_TABLE 0x0A
|
|
|
|
#define SUPERVISORY_CONTROL 0x10
|
|
|
|
#define RTU_CONFIG 0x20
|
|
|
|
#define RETURN_RTU_CONFIG 0x25
|
|
|
|
#define REPORT_EXCEPTION_DATA 0x0D
|
|
|
|
#define RST_RESPONSE_CODE 0x80
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* Function code Lookup */
|
|
|
|
static const value_string FunctionCodenames[] = {
|
|
|
|
{ BASIC_SCAN, "Basic Scan" },
|
|
|
|
{ SCAN_INCLUSIVE, "Scan Inclusive"},
|
|
|
|
{ SCAN_FOR_SPECIAL_CALC, "Scan Floating Points" },
|
2018-09-06 22:14:51 +00:00
|
|
|
{ RETRIEVE_TIME_TAGGED_INFO, "Retrieve Time Tagged Information" },
|
2014-07-16 16:50:41 +00:00
|
|
|
{ SCAN_BY_TABLE, "Scan by Table" },
|
|
|
|
{ SUPERVISORY_CONTROL, "Supervisory Control" },
|
|
|
|
{ RTU_CONFIG, "RTU Internal Control" },
|
|
|
|
{ RETURN_RTU_CONFIG, "Return RTU Config"},
|
|
|
|
{ REPORT_EXCEPTION_DATA, "Report Exception data"},
|
2018-09-06 22:14:51 +00:00
|
|
|
{ RST_RESPONSE_CODE, "RST Response"},
|
2014-07-16 16:50:41 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Function Code 0x00 (Basic Scan) Command Codes */
|
|
|
|
#define SIMPLE_STATUS_DATA 0x01
|
|
|
|
#define ALWAYS_RESERVED 0x02
|
|
|
|
#define TWO_BIT_STATUS 0x04
|
|
|
|
#define ANALOG_16_BIT 0x08
|
|
|
|
#define SS_AND_ANA16 0x09
|
|
|
|
#define ACCUMULATOR_16_BIT 0x40
|
|
|
|
|
|
|
|
/* Function Code 0x03 (Special Calc / Floating Point) Command Codes */
|
|
|
|
#define SPECIAL_CALC_ALL 0x80
|
|
|
|
#define SPECIAL_CALC_RANGE 0x00
|
|
|
|
|
|
|
|
/* Function Code 0x10 (Supervisory Control) Command Codes */
|
|
|
|
#define SBO_SELECT_OPEN 0x10
|
|
|
|
#define SBO_SELECT_CLOSE 0x11
|
|
|
|
#define SBO_OPERATE 0x20
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
static const value_string cp2179_CommandCodeNames [] = {
|
2018-09-06 22:14:51 +00:00
|
|
|
{ SPECIAL_CALC_RANGE, "Request a Range of Special Calc"},
|
2014-07-16 16:50:41 +00:00
|
|
|
{ SIMPLE_STATUS_DATA, "Simple Status" },
|
|
|
|
{ ALWAYS_RESERVED, "Reserved" },
|
|
|
|
{ TWO_BIT_STATUS, "2 Bit Data Status" },
|
|
|
|
{ ANALOG_16_BIT, "16 Bit Analog" },
|
2018-09-06 22:14:51 +00:00
|
|
|
{ SS_AND_ANA16, "Simple Status and 16-bit Analog" },
|
2014-07-16 16:50:41 +00:00
|
|
|
{ SBO_SELECT_OPEN, "SBO Open" },
|
|
|
|
{ SBO_SELECT_CLOSE, "SBO Close" },
|
|
|
|
{ SBO_OPERATE, "SBO Operate" },
|
2018-09-06 22:14:51 +00:00
|
|
|
{ ACCUMULATOR_16_BIT, "16 Bit Pulsed Accumulator" },
|
2014-07-16 16:50:41 +00:00
|
|
|
{ SPECIAL_CALC_ALL, "Request All Special Calc Data"},
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static value_string_ext cp2179_CommandCodeNames_ext = VALUE_STRING_EXT_INIT(cp2179_CommandCodeNames);
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Function Code 0x04 (Retrieve Time Tagged Information) Command Codes */
|
|
|
|
#define TIMETAG_INFO_RETRYLAST_SINGLEREC 0x00
|
|
|
|
#define TIMETAG_INFO_RETRYLAST_DUMP 0x20
|
|
|
|
#define TIMETAG_INFO_SINGLEREC 0x40
|
|
|
|
#define TIMETAG_INFO_DUMP 0x60
|
|
|
|
|
|
|
|
static const value_string cp2179_FC04_CommandCodeNames [] = {
|
|
|
|
{ TIMETAG_INFO_RETRYLAST_SINGLEREC, "Retransmit Last Single Record" },
|
|
|
|
{ TIMETAG_INFO_RETRYLAST_DUMP, "Retransmit Last Dump All Records" },
|
|
|
|
{ TIMETAG_INFO_SINGLEREC, "Return Single Record" },
|
|
|
|
{ TIMETAG_INFO_DUMP, "Dump All Records" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Function Code 0x20 (RTU Control) Command Codes */
|
|
|
|
#define INIT_RTU_CONFIGURATION 0x00
|
|
|
|
#define RESET_ACCUMULATOR 0x11
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
/* Function Code 0x20 Command Code Lookup */
|
|
|
|
static const value_string cp2179_FC20_CommandCodeNames [] = {
|
|
|
|
{ INIT_RTU_CONFIGURATION, "Initialize RTU Config" },
|
|
|
|
{ RESET_ACCUMULATOR, "Accumulator Reset" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Holds Request information required to later decode a response */
|
|
|
|
typedef struct {
|
|
|
|
guint32 fnum; /* frame number */
|
|
|
|
guint16 address_word;
|
|
|
|
guint8 function_code;
|
|
|
|
guint8 commmand_code;
|
|
|
|
guint16 numberofcharacters;
|
|
|
|
guint8 *requested_points;
|
2018-09-06 22:14:51 +00:00
|
|
|
} request_frame;
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int proto_cp2179 = -1;
|
|
|
|
|
|
|
|
/* Initialize the subtree pointers */
|
|
|
|
static gint ett_cp2179 = -1;
|
|
|
|
static gint ett_cp2179_header = -1;
|
|
|
|
static gint ett_cp2179_addr = -1;
|
|
|
|
static gint ett_cp2179_fc = -1;
|
|
|
|
static gint ett_cp2179_data = -1;
|
|
|
|
static gint ett_cp2179_subdata = -1;
|
2018-09-06 22:14:51 +00:00
|
|
|
static gint ett_cp2179_event = -1;
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* Initialize the protocol and registered fields */
|
|
|
|
static int hf_cp2179_request_frame = -1;
|
|
|
|
static int hf_cp2179_rtu_address = -1;
|
|
|
|
static int hf_cp2179_master_address = -1;
|
|
|
|
static int hf_cp2179_function_code = -1;
|
|
|
|
static int hf_cp2179_nop_flag = -1;
|
|
|
|
static int hf_cp2179_rst_flag = -1;
|
|
|
|
static int hf_cp2179_reserved = -1;
|
|
|
|
static int hf_cp2179_command_code = -1;
|
2018-09-06 22:14:51 +00:00
|
|
|
static int hf_cp2179_command_code_fc04 = -1;
|
2014-07-16 16:50:41 +00:00
|
|
|
static int hf_cp2179_command_code_fc20 = -1;
|
|
|
|
static int hf_cp2179_sbo_request_point = -1;
|
|
|
|
static int hf_cp2179_resetacc_request_point = -1;
|
|
|
|
static int hf_cp2179_speccalc_request_point = -1;
|
|
|
|
static int hf_cp2179_scaninc_startreq_point = -1;
|
|
|
|
static int hf_cp2179_scaninc_stopreq_point = -1;
|
|
|
|
static int hf_cp2179_number_characters = -1;
|
|
|
|
static int hf_cp2179_analog_16bit = -1;
|
|
|
|
static int hf_cp2179_accumulator = -1;
|
|
|
|
static int hf_cp2179_crc = -1;
|
2014-09-04 12:35:51 +00:00
|
|
|
/* static int hf_cp2179_data_field = -1; */
|
2014-07-16 16:50:41 +00:00
|
|
|
static int hf_cp2179_status_byte = -1;
|
|
|
|
static int hf_cp2179_port_status_byte = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit0 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit1 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit2 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit3 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit4 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit5 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit6 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit7 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit8 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit9 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit10 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit11 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit12 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit13 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit14 = -1;
|
|
|
|
static int hf_cp2179_simplestatusbit15 = -1;
|
|
|
|
static int hf_cp2179_specialcalc = -1;
|
|
|
|
static int hf_cp2179_2bitstatus = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg0 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg1 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg2 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg3 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg4 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg5 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg6 = -1;
|
|
|
|
static int hf_cp2179_2bitstatuschg7 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus0 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus1 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus2 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus3 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus4 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus5 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus6 = -1;
|
|
|
|
static int hf_cp2179_2bitstatusstatus7 = -1;
|
2018-09-06 22:14:51 +00:00
|
|
|
static int hf_cp2179_timetag_moredata = -1;
|
|
|
|
static int hf_cp2179_timetag_numsets = -1;
|
|
|
|
static int hf_cp2179_timetag_event_type = -1;
|
|
|
|
static int hf_cp2179_timetag_event_date_hundreds = -1;
|
|
|
|
static int hf_cp2179_timetag_event_date_tens = -1;
|
|
|
|
static int hf_cp2179_timetag_event_hour = -1;
|
|
|
|
static int hf_cp2179_timetag_event_minute = -1;
|
|
|
|
static int hf_cp2179_timetag_event_second = -1;
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2016-01-13 01:16:04 +00:00
|
|
|
static dissector_handle_t cp2179_handle;
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
static const int *cp2179_simplestatus_bits[] = {
|
|
|
|
&hf_cp2179_simplestatusbit0,
|
|
|
|
&hf_cp2179_simplestatusbit1,
|
|
|
|
&hf_cp2179_simplestatusbit2,
|
|
|
|
&hf_cp2179_simplestatusbit3,
|
|
|
|
&hf_cp2179_simplestatusbit4,
|
|
|
|
&hf_cp2179_simplestatusbit5,
|
|
|
|
&hf_cp2179_simplestatusbit6,
|
|
|
|
&hf_cp2179_simplestatusbit7,
|
|
|
|
&hf_cp2179_simplestatusbit8,
|
|
|
|
&hf_cp2179_simplestatusbit9,
|
|
|
|
&hf_cp2179_simplestatusbit10,
|
|
|
|
&hf_cp2179_simplestatusbit11,
|
|
|
|
&hf_cp2179_simplestatusbit12,
|
|
|
|
&hf_cp2179_simplestatusbit13,
|
|
|
|
&hf_cp2179_simplestatusbit14,
|
|
|
|
&hf_cp2179_simplestatusbit15,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int *cp2179_2bitstatus_bits[] = {
|
|
|
|
&hf_cp2179_2bitstatuschg0,
|
|
|
|
&hf_cp2179_2bitstatuschg1,
|
|
|
|
&hf_cp2179_2bitstatuschg2,
|
|
|
|
&hf_cp2179_2bitstatuschg3,
|
|
|
|
&hf_cp2179_2bitstatuschg4,
|
|
|
|
&hf_cp2179_2bitstatuschg5,
|
|
|
|
&hf_cp2179_2bitstatuschg6,
|
|
|
|
&hf_cp2179_2bitstatuschg7,
|
|
|
|
&hf_cp2179_2bitstatusstatus0,
|
|
|
|
&hf_cp2179_2bitstatusstatus1,
|
|
|
|
&hf_cp2179_2bitstatusstatus2,
|
|
|
|
&hf_cp2179_2bitstatusstatus3,
|
|
|
|
&hf_cp2179_2bitstatusstatus4,
|
|
|
|
&hf_cp2179_2bitstatusstatus5,
|
|
|
|
&hf_cp2179_2bitstatusstatus6,
|
|
|
|
&hf_cp2179_2bitstatusstatus7,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************************************************/
|
|
|
|
/* Clean all instances of 0xFFFF from Telnet payload to compensate for IAC control code (replace w/ 0xFF) */
|
|
|
|
/* Function Duplicated from packet-telnet.c (unescape_and_tvbuffify_telnet_option) */
|
|
|
|
/**********************************************************************************************************/
|
|
|
|
static tvbuff_t *
|
|
|
|
clean_telnet_iac(packet_info *pinfo, tvbuff_t *tvb, int offset, int len)
|
|
|
|
{
|
|
|
|
tvbuff_t *telnet_tvb;
|
|
|
|
guint8 *buf;
|
|
|
|
const guint8 *spos;
|
|
|
|
guint8 *dpos;
|
|
|
|
int skip_byte, len_remaining;
|
|
|
|
|
|
|
|
spos=tvb_get_ptr(tvb, offset, len);
|
2016-04-12 16:00:53 +00:00
|
|
|
buf = (guint8 *)wmem_alloc(pinfo->pool, len);
|
|
|
|
dpos = buf;
|
2014-07-16 16:50:41 +00:00
|
|
|
skip_byte = 0;
|
|
|
|
len_remaining = len;
|
|
|
|
while(len_remaining > 0){
|
|
|
|
|
|
|
|
/* Only analyze two sequential bytes of source tvb if we have at least two bytes left */
|
|
|
|
if (len_remaining > 1) {
|
|
|
|
/* If two sequential 0xFF's exist, increment skip_byte counter, decrement */
|
|
|
|
/* len_remaining by 2 and copy a single 0xFF to dest tvb. */
|
|
|
|
if((spos[0]==0xff) && (spos[1]==0xff)){
|
|
|
|
skip_byte++;
|
|
|
|
len_remaining -= 2;
|
2016-04-12 16:00:53 +00:00
|
|
|
*(dpos++) = 0xff;
|
|
|
|
spos += 2;
|
2014-07-16 16:50:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* If we only have a single byte left, or there were no sequential 0xFF's, copy byte from src tvb to dest tvb */
|
2016-04-12 16:00:53 +00:00
|
|
|
*(dpos++) = *(spos++);
|
2014-07-16 16:50:41 +00:00
|
|
|
len_remaining--;
|
|
|
|
}
|
|
|
|
telnet_tvb = tvb_new_child_real_data(tvb, buf, len-skip_byte, len-skip_byte);
|
|
|
|
add_new_data_source(pinfo, telnet_tvb, "Processed Telnet Data");
|
|
|
|
|
|
|
|
return telnet_tvb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Code to Dissect Request frames */
|
|
|
|
/******************************************************************************************************/
|
|
|
|
static int
|
2018-09-06 22:14:51 +00:00
|
|
|
dissect_request_frame(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, guint16 message_type )
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
/* Set up structures needed to add the protocol subtree and manage it */
|
|
|
|
proto_tree *cp2179_proto_tree = NULL;
|
|
|
|
proto_tree *cp2179_addr_tree = NULL;
|
|
|
|
proto_tree *cp2179_fc_tree = NULL;
|
|
|
|
|
|
|
|
proto_item *cp2179_proto_item = NULL;
|
|
|
|
|
|
|
|
guint8 req_command_code = 0;
|
|
|
|
guint8 function_code = 0;
|
|
|
|
|
|
|
|
guint16 address_word = -1;
|
|
|
|
guint16 requestnumberofcharacters = 0;
|
|
|
|
|
|
|
|
cp2179_proto_item = proto_tree_add_item(tree, proto_cp2179, tvb, 0, -1, ENC_NA);
|
|
|
|
cp2179_proto_tree = proto_item_add_subtree(cp2179_proto_item, ett_cp2179_header);
|
|
|
|
|
|
|
|
/* RTU & Master Address are encoded into a 16-bit word */
|
|
|
|
address_word = tvb_get_letohs(tvb, offset);
|
|
|
|
cp2179_addr_tree = proto_tree_add_subtree_format(cp2179_proto_tree, tvb, offset, 2, ett_cp2179_addr, NULL,
|
|
|
|
"RTU Address: %d, Master Address: %d", (address_word & 0x7FF), ((address_word & 0xF800) >> 11) );
|
|
|
|
|
|
|
|
proto_tree_add_item(cp2179_addr_tree, hf_cp2179_rtu_address, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_addr_tree, hf_cp2179_master_address, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
/* Report the function code */
|
|
|
|
function_code = tvb_get_guint8(tvb, offset) & 0x3f;
|
|
|
|
cp2179_fc_tree = proto_tree_add_subtree_format(cp2179_proto_tree, tvb, offset, 1, ett_cp2179_fc, NULL,
|
|
|
|
"Function Code: %s (0x%02x)", val_to_str_const(function_code, FunctionCodenames, "Unknown Function Code"), function_code);
|
|
|
|
|
|
|
|
proto_tree_add_item(cp2179_fc_tree, hf_cp2179_function_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_fc_tree, hf_cp2179_reserved, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* The command-byte interpretation is dependent on the function code. */
|
|
|
|
switch(message_type)
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
2018-09-06 22:14:51 +00:00
|
|
|
case INIT_RTU_REQUEST:
|
|
|
|
case RESET_ACC_REQUEST:
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_command_code_fc20 , tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BASIC_SCAN_REQUEST:
|
|
|
|
case SCAN_INCLUSIVE_16_ANALOG_REQUEST:
|
|
|
|
req_command_code = tvb_get_guint8(tvb, offset);
|
|
|
|
/* Update Info column with useful information of Command Code Type */
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " [ %s ]", val_to_str_ext_const(req_command_code, &cp2179_CommandCodeNames_ext, "Unknown Command Code"));
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_command_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TIMETAG_INFO_REQUEST:
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_command_code_fc04 , tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_command_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
break;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
offset += 1;
|
|
|
|
|
|
|
|
requestnumberofcharacters = tvb_get_letohs(tvb, 4);
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_number_characters, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* If request number is greater than 0, there is data field present in the request */
|
2014-07-16 16:50:41 +00:00
|
|
|
if ( requestnumberofcharacters > 0 ){
|
|
|
|
/*Depends on the packet type, the data field should be dissect differently*/
|
2018-09-06 22:14:51 +00:00
|
|
|
switch (message_type)
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
case SBO_SELECT_REQUEST:
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_sbo_request_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*Reset Accumulator request data field will always only has 1 byte. The Sequence ID of the Accumulator that it wants to reset*/
|
|
|
|
case RESET_ACC_REQUEST:
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_resetacc_request_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* A special calculation that requests for a range of points will have a list of sequence ID of the Special Calculation points */
|
|
|
|
case SPECIAL_CALC_REQUEST_RANGE:
|
|
|
|
do{
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_speccalc_request_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*Scan Inclusive will have a starting sequence ID and a ending sequence ID in the data field.*/
|
|
|
|
case SCAN_INCLUSIVE_16_ANALOG_REQUEST:
|
|
|
|
do{
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_scaninc_startreq_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_scaninc_stopreq_point, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
|
|
|
|
/* The last two bytes of the message are a 16-bit CRC */
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
return tvb_reported_length(tvb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Code to dissect Response frames */
|
|
|
|
/******************************************************************************************************/
|
|
|
|
static int
|
2018-09-06 22:14:51 +00:00
|
|
|
dissect_response_frame(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, guint16 message_type)
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
/* Set up structures needed to add the protocol subtree and manage it */
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_item *response_item = NULL;
|
2014-07-16 16:50:41 +00:00
|
|
|
proto_item *cp2179_proto_item = NULL;
|
|
|
|
proto_item *cp2179_subdata_item = NULL;
|
|
|
|
|
|
|
|
proto_tree *cp2179_proto_tree = NULL;
|
|
|
|
proto_tree *cp2179_addr_tree = NULL;
|
|
|
|
proto_tree *cp2179_fc_tree = NULL;
|
|
|
|
proto_tree *cp2179_data_tree = NULL;
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_tree *cp2179_event_tree = NULL;
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
cp2179_conversation *conv;
|
|
|
|
guint32 req_frame_num;
|
|
|
|
guint16 req_address_word;
|
|
|
|
guint8 req_command_code;
|
|
|
|
gboolean request_found = FALSE;
|
2018-09-06 22:14:51 +00:00
|
|
|
request_frame *request_data;
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
gint analogtestvalue = 0;
|
|
|
|
gint analog16_num = 0;
|
|
|
|
gint point_num = 0;
|
|
|
|
|
|
|
|
guint function_code;
|
|
|
|
guint simplestatusseq = 0x30;
|
|
|
|
|
|
|
|
guint16 address_word = 0;
|
|
|
|
guint16 numberofcharacters = -1;
|
|
|
|
|
|
|
|
gfloat specialcalvalue = 0;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
int x, y, num_records = 0, recordsize = 0, num_values = 0;
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
cp2179_proto_item = proto_tree_add_item(tree, proto_cp2179, tvb, 0, -1, ENC_NA);
|
|
|
|
cp2179_proto_tree = proto_item_add_subtree(cp2179_proto_item, ett_cp2179_header);
|
|
|
|
|
|
|
|
/* RTU & Master Address are encoded into a 16-bit word */
|
|
|
|
address_word = tvb_get_letohs(tvb, offset);
|
|
|
|
|
|
|
|
cp2179_addr_tree = proto_tree_add_subtree_format(cp2179_proto_tree, tvb, offset, 2, ett_cp2179_addr, NULL,
|
|
|
|
"RTU Address: %d, Master Address: %d", (address_word & 0x7FF), ((address_word & 0xF800) >> 11) );
|
|
|
|
|
|
|
|
proto_tree_add_item(cp2179_addr_tree, hf_cp2179_rtu_address, tvb, 0, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_addr_tree, hf_cp2179_master_address, tvb, 0, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
/*The response always echos the function code in request, except when the RTU can't perform the required function.
|
|
|
|
It may set the NOP or RST bit. Bit 0 to bit 5 is the field for function codes. Bit 6 is NOP bit. Bit 7 is RST bit. */
|
2018-09-06 22:14:51 +00:00
|
|
|
function_code = tvb_get_guint8(tvb, offset);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
cp2179_fc_tree = proto_tree_add_subtree_format(cp2179_proto_tree, tvb, offset, 1, ett_cp2179_fc, NULL,
|
|
|
|
"Function Code: %s (0x%02x)", val_to_str_const(function_code, FunctionCodenames, "Unknown Function Code"), function_code);
|
|
|
|
|
|
|
|
proto_tree_add_item(cp2179_fc_tree, hf_cp2179_function_code, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_fc_tree, hf_cp2179_nop_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_fc_tree, hf_cp2179_rst_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
|
|
|
|
offset += 1;
|
|
|
|
|
|
|
|
/* Status Byte & Port Status */
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_status_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_port_status_byte, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
|
|
|
|
/* Number of characters */
|
|
|
|
numberofcharacters = tvb_get_letohs(tvb, 5);
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_number_characters, tvb, offset, 2, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
/* get the converstation data */
|
|
|
|
conv = (cp2179_conversation *)p_get_proto_data(wmem_file_scope(), pinfo, proto_cp2179, 0);
|
|
|
|
|
|
|
|
if (conv) {
|
2018-09-06 22:14:51 +00:00
|
|
|
wmem_list_frame_t *frame = wmem_list_head(conv->request_frame_data);
|
2014-07-16 16:50:41 +00:00
|
|
|
/* Cycle through all logged instances of request frames, looking for request frame number that occurred immediately
|
|
|
|
prior to current frame number that has a matching address word */
|
|
|
|
while (frame && !request_found) {
|
2018-09-06 22:14:51 +00:00
|
|
|
request_data = (request_frame *)wmem_list_frame_data(frame);
|
2014-07-16 16:50:41 +00:00
|
|
|
req_frame_num = request_data->fnum;
|
|
|
|
req_command_code = request_data->commmand_code;
|
|
|
|
req_address_word = request_data->address_word;
|
2016-01-24 03:40:51 +00:00
|
|
|
if ((pinfo->num > req_frame_num) && (req_address_word == address_word)) {
|
2018-09-06 22:14:51 +00:00
|
|
|
response_item = proto_tree_add_uint(cp2179_proto_tree, hf_cp2179_request_frame, tvb, 0, 0, req_frame_num);
|
2019-04-03 21:32:30 +00:00
|
|
|
proto_item_set_generated(response_item);
|
2014-07-16 16:50:41 +00:00
|
|
|
request_found = TRUE;
|
|
|
|
}
|
|
|
|
frame = wmem_list_frame_next(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request_found)
|
|
|
|
{
|
2018-09-06 22:14:51 +00:00
|
|
|
switch (message_type)
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
case SBO_SELECT_RESPONSE:
|
|
|
|
case SBO_OPERATE_RESPONSE:
|
|
|
|
case RESET_ACC_RESPONSE:
|
|
|
|
case INIT_RTU_RESPONSE:
|
|
|
|
|
|
|
|
if ( numberofcharacters > 0 ){
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Based on the message type, process the next byte differently */
|
|
|
|
if ( message_type == SBO_SELECT_RESPONSE ){
|
2014-07-16 16:50:41 +00:00
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_sbo_request_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
if ( message_type == RESET_ACC_RESPONSE ){
|
2014-07-16 16:50:41 +00:00
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_resetacc_request_point, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SPECIAL_CALC_RESPONSE:
|
|
|
|
/* Based on the command code from the corresponding request, dissect the data field differently.
|
|
|
|
If required a range of Special calculation, display the requested sequence ID and corresponding
|
|
|
|
values. The requested sequence number is obtained from the previous request frame. */
|
|
|
|
cp2179_data_tree = proto_tree_add_subtree(cp2179_proto_tree, tvb, offset, numberofcharacters, ett_cp2179_data, NULL, "CP2179 Data Field");
|
|
|
|
|
|
|
|
if (req_command_code == SPECIAL_CALC_ALL ){
|
|
|
|
do{
|
|
|
|
specialcalvalue = tvb_get_letohieee_float(tvb, offset );
|
|
|
|
proto_tree_add_float_format(cp2179_data_tree, hf_cp2179_specialcalc, tvb, offset, 4, specialcalvalue,
|
|
|
|
"Special Calculation %u : %f", point_num, specialcalvalue);
|
|
|
|
point_num += 1;
|
|
|
|
offset += 4;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
}
|
|
|
|
/*If it request all the special calculation data, dissect all of them and associated a sequence ID with it.*/
|
|
|
|
else if (req_command_code == SPECIAL_CALC_RANGE ){
|
|
|
|
do{
|
|
|
|
specialcalvalue = tvb_get_letohieee_float(tvb, offset );
|
|
|
|
proto_tree_add_float_format(cp2179_data_tree, hf_cp2179_specialcalc, tvb, offset, 4, specialcalvalue,
|
|
|
|
"Special Calculation %u : %f", request_data->requested_points[point_num], specialcalvalue);
|
|
|
|
point_num += 1;
|
|
|
|
offset += 4;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCAN_INCLUSIVE_16_ANALOG_RESPONSE:
|
|
|
|
|
|
|
|
cp2179_data_tree = proto_tree_add_subtree(cp2179_proto_tree, tvb, offset, numberofcharacters, ett_cp2179_data, NULL, "CP2179 Data Field");
|
|
|
|
|
|
|
|
/* Update Info column with useful information of Command Code Type */
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " [ %s ]", val_to_str_ext_const(req_command_code, &cp2179_CommandCodeNames_ext, "Unknown Command Code"));
|
|
|
|
|
|
|
|
/*Report the values of the requested SCAN inclusive data. To figure out which sequence ID the values in the response associated with,
|
2018-09-06 22:14:51 +00:00
|
|
|
we read the request_frame information and show the corresponding sequence ID of the data in response frame.*/
|
2014-07-16 16:50:41 +00:00
|
|
|
do{
|
2018-04-10 06:06:47 +00:00
|
|
|
analogtestvalue = tvb_get_letohis(tvb, offset);
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_tree_add_int_format(cp2179_data_tree, hf_cp2179_analog_16bit, tvb, offset, 2, request_data->requested_points[point_num],
|
|
|
|
"Analog (16 bit) %u : %d", request_data->requested_points[point_num], analogtestvalue);
|
2014-07-16 16:50:41 +00:00
|
|
|
point_num += 1;
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
case BASIC_SCAN_RESPONSE:
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
cp2179_data_tree = proto_tree_add_subtree(cp2179_proto_tree, tvb, offset, numberofcharacters, ett_cp2179_data, NULL, "CP2179 Data Field");
|
|
|
|
|
|
|
|
/* Update Info column with useful information of Command Code Type */
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " [ %s ]", val_to_str_ext_const(req_command_code, &cp2179_CommandCodeNames_ext, "Unknown Command Code"));
|
|
|
|
|
|
|
|
switch (req_command_code)
|
|
|
|
{
|
|
|
|
/* Based the command code from the request frame, we dissect the response data differently.
|
|
|
|
For example, if the request packet has command byte as ANALOG_16_BIT, the
|
|
|
|
the data field in the response should be dissected as 16-bit signed integer(s). */
|
|
|
|
case ACCUMULATOR_16_BIT:
|
|
|
|
do{
|
|
|
|
analogtestvalue = tvb_get_letohs(tvb, offset);
|
|
|
|
proto_tree_add_uint_format(cp2179_data_tree, hf_cp2179_accumulator, tvb, offset, 2, analog16_num,
|
|
|
|
"Accumulator %u : %u", analog16_num, analogtestvalue);
|
|
|
|
analog16_num += 1;
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ANALOG_16_BIT:
|
|
|
|
do{
|
2018-04-10 06:06:47 +00:00
|
|
|
analogtestvalue = tvb_get_letohis(tvb, offset);
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_tree_add_int_format(cp2179_data_tree, hf_cp2179_analog_16bit, tvb, offset, 2, analog16_num,
|
2014-07-16 16:50:41 +00:00
|
|
|
"Analog (16 bit) %u : %i", analog16_num, analogtestvalue);
|
|
|
|
analog16_num += 1;
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIMPLE_STATUS_DATA:
|
|
|
|
do{
|
|
|
|
cp2179_subdata_item = proto_tree_add_bitmask(cp2179_data_tree, tvb, offset, hf_cp2179_simplestatusbit,
|
|
|
|
ett_cp2179_subdata, cp2179_simplestatus_bits, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_item_set_text(cp2179_subdata_item, "Simple Status Point 0x%x", simplestatusseq);
|
|
|
|
|
|
|
|
simplestatusseq += 1;
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TWO_BIT_STATUS:
|
|
|
|
do{
|
|
|
|
cp2179_subdata_item = proto_tree_add_bitmask(cp2179_data_tree, tvb, offset, hf_cp2179_2bitstatus,
|
|
|
|
ett_cp2179_subdata, cp2179_2bitstatus_bits, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_item_set_text(cp2179_subdata_item, "2 Bit Status Point 0x%x", simplestatusseq);
|
|
|
|
|
|
|
|
simplestatusseq += 1;
|
|
|
|
offset += 2;
|
|
|
|
}while(tvb_reported_length_remaining(tvb, offset) > 2);
|
|
|
|
|
|
|
|
break;
|
|
|
|
} /* end of command code switch */
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
break;
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
} /* end of basic scan response switch */
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
case TIMETAG_INFO_RESPONSE:
|
|
|
|
{
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_timetag_moredata, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_timetag_numsets, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
|
|
|
|
num_records = tvb_get_guint8(tvb, offset) & 0x7F;
|
|
|
|
recordsize = (numberofcharacters-1) / num_records;
|
|
|
|
num_values = (recordsize-6) / 2; /* Determine how many 16-bit analog values are present in each event record */
|
|
|
|
|
|
|
|
offset += 1;
|
|
|
|
|
|
|
|
for (x = 0; x < num_records; x++)
|
|
|
|
{
|
|
|
|
cp2179_event_tree = proto_tree_add_subtree_format(cp2179_proto_tree, tvb, offset, recordsize, ett_cp2179_event, NULL, "Event Record # %d", x+1);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_date_hundreds, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_date_tens, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_hour, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_minute, tvb, offset+4, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
proto_tree_add_item(cp2179_event_tree, hf_cp2179_timetag_event_second, tvb, offset+5, 1, ENC_LITTLE_ENDIAN);
|
|
|
|
offset += 6;
|
|
|
|
|
|
|
|
for (y = 0; y < num_values; y++)
|
|
|
|
{
|
|
|
|
analogtestvalue = tvb_get_letohis(tvb, offset);
|
|
|
|
proto_tree_add_int_format(cp2179_event_tree, hf_cp2179_analog_16bit, tvb, offset, 2, analogtestvalue,
|
|
|
|
"Analog Value (16 bit) %u : %d", y+1, analogtestvalue);
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-07-16 16:50:41 +00:00
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
} /* end of message type switch */
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_tree_add_item(cp2179_proto_tree, hf_cp2179_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
} /* request found */
|
|
|
|
|
|
|
|
} /* conversation data found */
|
|
|
|
|
|
|
|
if (!request_found) {
|
2018-09-06 22:14:51 +00:00
|
|
|
proto_item_append_text(response_item, ", No Request found");
|
2014-07-16 16:50:41 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tvb_reported_length(tvb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Load Request information into bs request struct */
|
|
|
|
/******************************************************************************************************/
|
2018-09-06 22:14:51 +00:00
|
|
|
static request_frame* copy_request_frame(tvbuff_t *tvb )
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
|
|
|
/* Set up structures needed to add the protocol request and use it for dissecting response packet */
|
|
|
|
guint offset = 0;
|
2014-09-04 11:53:52 +00:00
|
|
|
guint8 idx=0 ;
|
2018-09-06 22:14:51 +00:00
|
|
|
request_frame *frame;
|
2014-07-16 16:50:41 +00:00
|
|
|
guint16 num_objects=0;
|
|
|
|
|
|
|
|
/* get a new frame and initialize it */
|
2018-09-06 22:14:51 +00:00
|
|
|
frame = wmem_new(wmem_file_scope(), request_frame);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* update the data within the structure frame */
|
|
|
|
frame->address_word = tvb_get_letohs(tvb, offset); offset +=2;
|
|
|
|
frame->function_code = tvb_get_guint8(tvb, offset); offset +=1;
|
|
|
|
frame->commmand_code = tvb_get_guint8(tvb, offset); offset +=1;
|
|
|
|
frame->numberofcharacters = tvb_get_letohs(tvb, offset);offset +=2;
|
|
|
|
|
|
|
|
/*Keep track of the request data field in a request.
|
|
|
|
Such as SCAN INCLUSIVE request contains a Start Sequence Number and an Ending Sequence Number. */
|
|
|
|
if (frame->function_code == SCAN_INCLUSIVE) {
|
|
|
|
guint8 startpt, endpt;
|
|
|
|
startpt = tvb_get_guint8(tvb, offset);
|
|
|
|
endpt = tvb_get_guint8(tvb, offset+1);
|
|
|
|
num_objects = (endpt - startpt) + 1;
|
|
|
|
frame->requested_points = (guint8 *)wmem_alloc(wmem_file_scope(), num_objects * sizeof(guint8));
|
|
|
|
|
|
|
|
/* We have a range of 'request' points */
|
2014-09-04 11:53:52 +00:00
|
|
|
for (idx = 0; idx < num_objects; idx++) {
|
|
|
|
frame->requested_points[idx] = startpt;
|
2014-07-16 16:50:41 +00:00
|
|
|
startpt++;
|
|
|
|
}
|
|
|
|
/* offset += 2; */
|
|
|
|
}
|
|
|
|
/* Get Details for all Requested Points */
|
|
|
|
else {
|
|
|
|
num_objects = frame->numberofcharacters;
|
|
|
|
frame->requested_points = (guint8 *)wmem_alloc(wmem_file_scope(), num_objects * sizeof(guint8));
|
2014-09-04 11:53:52 +00:00
|
|
|
for (idx = 0; idx < num_objects; idx++) {
|
|
|
|
frame->requested_points[idx] = tvb_get_guint8(tvb, offset);
|
2014-07-16 16:50:41 +00:00
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Classify the different packet type */
|
|
|
|
/******************************************************************************************************/
|
|
|
|
static int
|
2018-09-06 22:14:51 +00:00
|
|
|
classify_message_type(tvbuff_t *tvb)
|
2014-07-16 16:50:41 +00:00
|
|
|
{
|
2018-09-06 22:14:51 +00:00
|
|
|
int message_type = -1;
|
2014-07-16 16:50:41 +00:00
|
|
|
guint8 function_code;
|
|
|
|
guint8 command_code;
|
|
|
|
guint16 requestnumberofcharacters = 0;
|
|
|
|
guint16 responsenumberofcharacters = 0;
|
2018-09-06 22:14:51 +00:00
|
|
|
guint16 message_length = 0;
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
message_length = tvb_reported_length(tvb);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* The response always echos the function code from the request, except when the RTU can't perform the required function.
|
|
|
|
It may set the NOP or RST bit. Bit 0 to bit 5 is the field for function codes. Bit 6 is NOP bit. Bit 7 is RST bit. */
|
2014-07-16 16:50:41 +00:00
|
|
|
function_code = tvb_get_guint8(tvb, 2);
|
|
|
|
command_code = tvb_get_guint8(tvb, 3);
|
2018-09-06 22:14:51 +00:00
|
|
|
|
|
|
|
/* We still don't know what type of message this is, request or response */
|
|
|
|
/* Get the 'number of characters' value, for both request frames (offset 4) and response frames (offset 5) */
|
2014-07-16 16:50:41 +00:00
|
|
|
requestnumberofcharacters = tvb_get_letohs(tvb, 4);
|
|
|
|
responsenumberofcharacters = tvb_get_letohs(tvb, 5);
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* 2179 protocol messages do not have a flag that tells you whether it is a request or a response.
|
|
|
|
Use various values within the message (function code, command code, message length) to determine this */
|
2014-07-16 16:50:41 +00:00
|
|
|
switch (function_code ){
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Basic Scan Operation (Function code 0x00), supported by the RTAC */
|
2014-07-16 16:50:41 +00:00
|
|
|
case BASIC_SCAN:
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Basic Scan Request Message */
|
|
|
|
if ( (requestnumberofcharacters == 0) && (message_length == BASIC_SCAN_REQ_LEN) ) {
|
|
|
|
message_type = BASIC_SCAN_REQUEST ;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Basic Scan Response Message */
|
|
|
|
else if ( (responsenumberofcharacters > 0) && (message_length > BASIC_SCAN_REQ_LEN) ) {
|
|
|
|
message_type = BASIC_SCAN_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Supervisory Control (Function code 0x10), supported by the RTAC */
|
2014-07-16 16:50:41 +00:00
|
|
|
case SUPERVISORY_CONTROL:
|
2018-09-06 22:14:51 +00:00
|
|
|
/* SBO Select Request */
|
|
|
|
if ( (requestnumberofcharacters == 1) && (message_length == SBO_SELECT_REQ_LEN) ) {
|
|
|
|
message_type = SBO_SELECT_REQUEST;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
/* SBO Select Response */
|
|
|
|
else if ( (responsenumberofcharacters == 1) && (message_length == SBO_SELECT_REPLY_LEN) ) {
|
|
|
|
message_type = SBO_SELECT_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
/* SBO Operate Request */
|
2014-07-16 16:50:41 +00:00
|
|
|
else if (requestnumberofcharacters == 0) {
|
2018-09-06 22:14:51 +00:00
|
|
|
if ( (message_length == SBO_OPERATE_REQ_LEN) && (command_code == SBO_OPERATE) ) {
|
|
|
|
message_type = SBO_OPERATE_REQUEST;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
/* SBO Operate Response */
|
2014-07-16 16:50:41 +00:00
|
|
|
else if (responsenumberofcharacters == 0) {
|
2018-09-06 22:14:51 +00:00
|
|
|
if (message_length == SBO_OPERATE_REPLY_LEN) {
|
|
|
|
message_type = SBO_OPERATE_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Scan for floating point (aka: special calculations) (Function code 0x03), supported by the RTAC */
|
2014-07-16 16:50:41 +00:00
|
|
|
case SCAN_FOR_SPECIAL_CALC:
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Special Calc Request All */
|
2014-07-16 16:50:41 +00:00
|
|
|
if ( (requestnumberofcharacters == 0) && (command_code == SPECIAL_CALC_ALL ) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = SPECIAL_CALC_REQUEST_ALL;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Special Calc Request Range */
|
2014-07-16 16:50:41 +00:00
|
|
|
else if ( (requestnumberofcharacters > 0) && (command_code == SPECIAL_CALC_RANGE ) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = SPECIAL_CALC_REQUEST_RANGE;
|
|
|
|
}
|
|
|
|
/* Special Calc Response */
|
|
|
|
else if ( (responsenumberofcharacters > 0) && (message_length == (responsenumberofcharacters + 9) ) ) {
|
|
|
|
message_type = SPECIAL_CALC_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
2018-09-06 22:14:51 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Retrieve Time-tagged information (Function code 0x04), not supported by RTAC */
|
|
|
|
case RETRIEVE_TIME_TAGGED_INFO:
|
|
|
|
|
|
|
|
if (requestnumberofcharacters == 0) {
|
|
|
|
message_type = TIMETAG_INFO_REQUEST;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
message_type = TIMETAG_INFO_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2018-09-06 22:14:51 +00:00
|
|
|
|
|
|
|
/* Scan Inclusive (Function Code 0x01), supported by the RTAC */
|
2014-07-16 16:50:41 +00:00
|
|
|
case SCAN_INCLUSIVE:
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Scan Inclusive Response */
|
2014-07-16 16:50:41 +00:00
|
|
|
if ( (responsenumberofcharacters > 0) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = SCAN_INCLUSIVE_16_ANALOG_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* Scan Inclusive Request */
|
2014-07-16 16:50:41 +00:00
|
|
|
if( (command_code == ANALOG_16_BIT) && (requestnumberofcharacters == 2) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = SCAN_INCLUSIVE_16_ANALOG_REQUEST;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/* RTU Internal Control and Configuration (Function Code 0x20) */
|
2014-07-16 16:50:41 +00:00
|
|
|
case RTU_CONFIG:
|
|
|
|
if (responsenumberofcharacters == 0) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = INIT_RTU_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
if ( (requestnumberofcharacters == 0) && (command_code == INIT_RTU_CONFIGURATION) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = INIT_RTU_REQUEST;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (responsenumberofcharacters == 1) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = RESET_ACC_RESPONSE;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
if ( (requestnumberofcharacters == 1) && (command_code == RESET_ACCUMULATOR) ) {
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = RESET_ACC_REQUEST;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-09-06 22:14:51 +00:00
|
|
|
case RST_RESPONSE_CODE:
|
|
|
|
message_type = RST_RESPONSE;
|
|
|
|
break;
|
2014-07-16 16:50:41 +00:00
|
|
|
default :
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = -99;
|
2014-07-16 16:50:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
return message_type;
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Code to dissect CP2179 protocol packets */
|
|
|
|
/******************************************************************************************************/
|
|
|
|
static int
|
|
|
|
dissect_cp2179_pdu(tvbuff_t *cp2179_tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|
|
|
{
|
|
|
|
int offset = 0;
|
2018-09-06 22:14:51 +00:00
|
|
|
gint16 message_type;
|
2014-07-16 16:50:41 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CP2179");
|
|
|
|
col_clear(pinfo->cinfo,COL_INFO);
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
message_type = classify_message_type(cp2179_tvb);
|
2014-07-16 16:50:41 +00:00
|
|
|
/* set information for Information column for CP2179 */
|
2018-09-06 22:14:51 +00:00
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext_const(message_type, &cp2179_messagetype_vals_ext, "Unknown Message Type"));
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-12-27 02:26:24 +00:00
|
|
|
if (!pinfo->fd->visited){
|
2018-09-06 22:14:51 +00:00
|
|
|
conversation_t *conversation = NULL;
|
|
|
|
cp2179_conversation *conv_data = NULL;
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* Find a conversation, create a new if no one exists */
|
|
|
|
conversation = find_or_create_conversation(pinfo);
|
2018-09-06 22:14:51 +00:00
|
|
|
conv_data = (cp2179_conversation *)conversation_get_proto_data(conversation, proto_cp2179);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
if (conv_data == NULL){
|
|
|
|
conv_data = wmem_new(wmem_file_scope(), cp2179_conversation);
|
|
|
|
conv_data->request_frame_data = wmem_list_new(wmem_file_scope());
|
|
|
|
conversation_add_proto_data(conversation, proto_cp2179, (void *)conv_data);
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
p_add_proto_data(wmem_file_scope(), pinfo, proto_cp2179, 0, conv_data);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
if ((message_type == BASIC_SCAN_REQUEST) || (message_type == SBO_SELECT_REQUEST)
|
|
|
|
||(message_type == SPECIAL_CALC_REQUEST_ALL)||(message_type == SBO_OPERATE_REQUEST)
|
|
|
|
||(message_type == SPECIAL_CALC_REQUEST_RANGE)||(message_type == INIT_RTU_REQUEST)
|
|
|
|
||(message_type == RESET_ACC_REQUEST)||(message_type == SCAN_INCLUSIVE_16_ANALOG_REQUEST)) {
|
2014-07-16 16:50:41 +00:00
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
/*fill the request frame. It holds the request information, to be used later when dissecting the response. */
|
|
|
|
request_frame *frame_ptr = NULL;
|
|
|
|
frame_ptr = copy_request_frame(cp2179_tvb);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/*also hold the current frame number*/
|
2016-01-24 03:40:51 +00:00
|
|
|
frame_ptr->fnum = pinfo->num;
|
2018-09-06 22:14:51 +00:00
|
|
|
wmem_list_prepend(conv_data->request_frame_data, frame_ptr);
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
} /* !visited */
|
|
|
|
|
|
|
|
if (tvb_reported_length_remaining(cp2179_tvb, offset) > 0){
|
2018-09-06 22:14:51 +00:00
|
|
|
switch (message_type){
|
|
|
|
case BASIC_SCAN_REQUEST:
|
|
|
|
case TIMETAG_INFO_REQUEST:
|
2014-07-16 16:50:41 +00:00
|
|
|
case SBO_SELECT_REQUEST:
|
|
|
|
case SBO_OPERATE_REQUEST:
|
|
|
|
case SPECIAL_CALC_REQUEST_ALL:
|
|
|
|
case SPECIAL_CALC_REQUEST_RANGE:
|
|
|
|
case SCAN_INCLUSIVE_16_ANALOG_REQUEST:
|
|
|
|
case RESET_ACC_REQUEST:
|
|
|
|
case INIT_RTU_REQUEST:
|
2018-09-06 22:14:51 +00:00
|
|
|
dissect_request_frame(cp2179_tvb, tree, pinfo, offset, message_type);
|
2014-07-16 16:50:41 +00:00
|
|
|
break;
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
case BASIC_SCAN_RESPONSE:
|
|
|
|
case TIMETAG_INFO_RESPONSE:
|
2014-07-16 16:50:41 +00:00
|
|
|
case SBO_SELECT_RESPONSE:
|
|
|
|
case SBO_OPERATE_RESPONSE:
|
|
|
|
case SPECIAL_CALC_RESPONSE:
|
|
|
|
case SCAN_INCLUSIVE_16_ANALOG_RESPONSE:
|
|
|
|
case INIT_RTU_RESPONSE:
|
|
|
|
case RESET_ACC_RESPONSE:
|
2018-09-06 22:14:51 +00:00
|
|
|
case RST_RESPONSE:
|
|
|
|
dissect_response_frame(cp2179_tvb, tree, pinfo, offset, message_type);
|
2014-07-16 16:50:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
} /* packet type */
|
|
|
|
} /* length remaining */
|
|
|
|
|
|
|
|
return tvb_reported_length(cp2179_tvb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************************************/
|
|
|
|
/* Dissect (and possibly Re-assemble) CP2179 protocol payload data */
|
|
|
|
/******************************************************************************************************/
|
|
|
|
static int
|
|
|
|
dissect_cp2179(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
|
|
|
{
|
|
|
|
tvbuff_t *cp2179_tvb;
|
|
|
|
gint length = tvb_reported_length(tvb);
|
|
|
|
|
|
|
|
/* Check for the packet length, a 2179 Message is at least 7 byte long*/
|
|
|
|
if(length < CP2179_MIN_LENGTH){
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((pinfo->srcport) && cp2179_telnet_clean){
|
|
|
|
cp2179_tvb = clean_telnet_iac(pinfo, tvb, 0, length);
|
|
|
|
}
|
|
|
|
else{
|
2017-01-10 06:18:49 +00:00
|
|
|
/* cp2179_tvb = tvb_new_subset_length_caplen( tvb, 0, length, length); */
|
2014-07-16 16:50:41 +00:00
|
|
|
cp2179_tvb = tvb_new_subset_length( tvb, 0, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
dissect_cp2179_pdu(cp2179_tvb, pinfo, tree, data);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_cp2179(void)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] =
|
|
|
|
{
|
|
|
|
{ &hf_cp2179_request_frame,
|
|
|
|
{ "Request Frame", "cp2179.request_frame",
|
|
|
|
FT_FRAMENUM, BASE_NONE,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_rtu_address,
|
|
|
|
{ "RTU Address", "cp2179.RTUAddress",
|
|
|
|
FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x7FF,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_master_address,
|
|
|
|
{ "Master Address", "cp2179.MasterAddress",
|
|
|
|
FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0xF800,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_function_code,
|
|
|
|
{ "Function Code", "cp2179.functioncode",
|
|
|
|
FT_UINT8, BASE_HEX,
|
|
|
|
VALS(FunctionCodenames), 0x3F,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_nop_flag,
|
|
|
|
{ "NOP Flag", "cp2179.nop_flag",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x40,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_rst_flag,
|
|
|
|
{ "RST Flag", "cp2179.rst_flag",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x80,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_reserved,
|
|
|
|
{ "Reserved Bits", "cp2179.Reserved",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0xC0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_command_code,
|
|
|
|
{ "Command Code", "cp2179.commandcode",
|
|
|
|
FT_UINT8, BASE_HEX,
|
|
|
|
VALS(cp2179_CommandCodeNames), 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
2018-09-06 22:14:51 +00:00
|
|
|
{ &hf_cp2179_command_code_fc04,
|
|
|
|
{ "Command Code (FC 0x04)", "cp2179.commandcode.fc04",
|
|
|
|
FT_UINT8, BASE_HEX,
|
|
|
|
VALS(cp2179_FC04_CommandCodeNames), 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
|
2014-07-16 16:50:41 +00:00
|
|
|
{ &hf_cp2179_command_code_fc20,
|
2018-09-06 22:14:51 +00:00
|
|
|
{ "Command Code (FC 0x20)", "cp2179.commandcode.fc20",
|
2014-07-16 16:50:41 +00:00
|
|
|
FT_UINT8, BASE_HEX,
|
|
|
|
VALS(cp2179_FC20_CommandCodeNames), 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_status_byte,
|
|
|
|
{ "RTU Status", "cp2179.rtustatus",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_port_status_byte,
|
|
|
|
{ "Port Status", "cp2179.portstatus",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_sbo_request_point,
|
|
|
|
{ "SBO Request Point", "cp2179.sbo_requestpoint",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_resetacc_request_point,
|
|
|
|
{ "Reset Accumulator Request Point", "cp2179.resetacc_requestpoint",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_speccalc_request_point,
|
|
|
|
{ "Special Calc Request Point", "cp2179.speccalc_requestpoint",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_scaninc_startreq_point,
|
|
|
|
{ "Start Request Point", "cp2179.scaninc_startreq_point",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_scaninc_stopreq_point,
|
|
|
|
{ "Stop Request Point", "cp2179.scaninc_stopreq_point",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_number_characters,
|
|
|
|
{ "Number of Characters", "cp2179.numberofcharacters",
|
|
|
|
FT_UINT16, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_crc,
|
|
|
|
{ "CRC", "cp2179.crc",
|
|
|
|
FT_UINT16, BASE_HEX,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2014-09-04 12:35:51 +00:00
|
|
|
#if 0
|
2014-07-16 16:50:41 +00:00
|
|
|
{ &hf_cp2179_data_field,
|
|
|
|
{ "Data Field", "cp2179.datafield",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
2014-09-04 12:35:51 +00:00
|
|
|
#endif
|
2014-07-16 16:50:41 +00:00
|
|
|
{ &hf_cp2179_accumulator,
|
|
|
|
{ "Accumulator", "cp2179.accumulator",
|
|
|
|
FT_UINT16, BASE_DEC,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_specialcalc,
|
|
|
|
{ "Special Calc", "cp2179.specialcalc",
|
|
|
|
FT_FLOAT, BASE_NONE,
|
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_analog_16bit,
|
|
|
|
{ "Analog 16-bit", "cp2179.analogdata",
|
2018-09-06 22:14:51 +00:00
|
|
|
FT_INT16, BASE_DEC,
|
2014-07-16 16:50:41 +00:00
|
|
|
0x0, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit,
|
|
|
|
{ "Simple Status Bit", "cp2179.simplestatusbit",
|
|
|
|
FT_UINT16, BASE_HEX,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit0,
|
|
|
|
{ "Simple Status bit 0", "cp2179.simplestatusbit0",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0001,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit1,
|
|
|
|
{ "Simple Status bit 1", "cp2179.simplestatusbit1",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0002,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit2,
|
|
|
|
{ "Simple Status bit 2", "cp2179.simplestatusbit2",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0004,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit3,
|
|
|
|
{ "Simple Status bit 3", "cp2179.simplestatusbit3",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0008,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit4,
|
|
|
|
{ "Simple Status bit 4", "cp2179.simplestatusbit4",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0010,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_simplestatusbit5,
|
|
|
|
{ "Simple Status bit 5", "cp2179.simplestatusbit5",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0020,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_simplestatusbit6,
|
|
|
|
{ "Simple Status bit 6", "cp2179.simplestatusbit6",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0040,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit7,
|
|
|
|
{ "Simple Status bit 7", "cp2179.simplestatusbit7",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0080,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit8,
|
|
|
|
{ "Simple Status bit 8", "cp2179.simplestatusbit8",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0100,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit9,
|
|
|
|
{ "Simple Status bit 9", "cp2179.simplestatusbit9",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0200,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit10,
|
|
|
|
{ "Simple Status bit 10", "cp2179.simplestatusbit10",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0400,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit11,
|
|
|
|
{ "Simple Status bit 11", "cp2179.simplestatusbit11",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0800,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit12,
|
|
|
|
{ "Simple Status bit 12", "cp2179.simplestatusbit12",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x1000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_simplestatusbit13,
|
|
|
|
{ "Simple Status bit 13", "cp2179.simplestatusbit13",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x2000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_simplestatusbit14,
|
|
|
|
{ "Simple Status bit 14", "cp2179.simplestatusbit14",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x4000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_simplestatusbit15,
|
|
|
|
{ "Simple Status bit 15", "cp2179.simplestatusbit15",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x8000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatus,
|
|
|
|
{ "2 Bit Status", "cp2179.twobitstatus",
|
|
|
|
FT_UINT16, BASE_HEX,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg0,
|
|
|
|
{ "2 Bit Status Change 0", "cp2179.twobitstatuschg0",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0001,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg1,
|
|
|
|
{ "2 Bit Status Change 1", "cp2179.twobitstatuschg1",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0002,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg2,
|
|
|
|
{ "2 Bit Status Change 2", "cp2179.twobitstatuschg2",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0004,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg3,
|
|
|
|
{ "2 Bit Status Change 3", "cp2179.twobitstatuschg3",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0008,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg4,
|
|
|
|
{ "2 Bit Status Change 4", "cp2179.twobitstatuschg4",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0010,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatuschg5,
|
|
|
|
{ "2 Bit Status Change 5", "cp2179.twobitstatuschg5",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0020,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_2bitstatuschg6,
|
|
|
|
{ "2 Bit Status Change 6", "cp2179.twobitstatuschg6",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0040,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_2bitstatuschg7,
|
|
|
|
{ "2 Bit Status Change 7", "cp2179.twobitstatuschg7",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0080,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
|
|
|
|
{ &hf_cp2179_2bitstatusstatus0,
|
|
|
|
{ "2 Bit Status bit 0", "cp2179.twobitstatusbit0",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0100,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus1,
|
|
|
|
{ "2 Bit Status bit 1", "cp2179.twobitstatusbit1",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0200,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus2,
|
|
|
|
{ "2 Bit Status bit 2", "cp2179.twobitstatusbit2",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0400,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus3,
|
|
|
|
{ "2 Bit Status bit 3", "cp2179.twobitstatusbit3",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x0800,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus4,
|
|
|
|
{ "2 Bit Status bit 4", "cp2179.twobitstatusbit4",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x1000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus5,
|
|
|
|
{ "2 Bit Status bit 5", "cp2179.twobitstatusbit5",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x2000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus6,
|
|
|
|
{ "2 Bit Status bit 6", "cp2179.twobitstatusbit6",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x4000,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_2bitstatusstatus7,
|
|
|
|
{ "2 Bit Status bit 7", "cp2179.twobitstatusbit7",
|
|
|
|
FT_BOOLEAN, 16,
|
|
|
|
NULL, 0x8000,
|
|
|
|
NULL, HFILL }
|
2018-09-06 22:14:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_moredata,
|
|
|
|
{ "Additional Records Available", "cp2179.timetag.moredata",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x80,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_numsets,
|
|
|
|
{ "Number of Sets", "cp2179.timetag.numsets",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x7F,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_type,
|
|
|
|
{ "Event Type", "cp2179.timetag.event.type",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_date_hundreds,
|
|
|
|
{ "Julian Date (Hundreds)", "cp2179.timetag.event.date.hundreds",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0F,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_date_tens,
|
|
|
|
{ "Julian Date (Tens)", "cp2179.timetag.event.date.tens",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_hour,
|
|
|
|
{ "Hour", "cp2179.timetag.event.hour",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_minute,
|
|
|
|
{ "Minute", "cp2179.timetag.event.minute",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
},
|
|
|
|
{ &hf_cp2179_timetag_event_second,
|
|
|
|
{ "Second", "cp2179.timetag.event.second",
|
|
|
|
FT_UINT8, BASE_DEC,
|
|
|
|
NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
|
|
|
}
|
2014-07-16 16:50:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Setup protocol subtree array */
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_cp2179,
|
|
|
|
&ett_cp2179_header,
|
|
|
|
&ett_cp2179_addr,
|
|
|
|
&ett_cp2179_fc,
|
|
|
|
&ett_cp2179_data,
|
2018-09-06 22:14:51 +00:00
|
|
|
&ett_cp2179_subdata,
|
|
|
|
&ett_cp2179_event
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
module_t *cp2179_module;
|
|
|
|
|
|
|
|
proto_cp2179 = proto_register_protocol ("CP2179 Protocol", "CP2179", "cp2179");
|
2016-01-13 01:16:04 +00:00
|
|
|
cp2179_handle = register_dissector("cp2179", dissect_cp2179, proto_cp2179);
|
2014-07-16 16:50:41 +00:00
|
|
|
proto_register_field_array(proto_cp2179, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
|
|
|
|
/* Register required preferences for CP2179 Encapsulated-over-TCP decoding */
|
2016-10-07 20:25:01 +00:00
|
|
|
cp2179_module = prefs_register_protocol(proto_cp2179, NULL);
|
2014-07-16 16:50:41 +00:00
|
|
|
|
|
|
|
/* Telnet protocol IAC (0xFF) processing; defaults to TRUE to allow Telnet Encapsulated Data */
|
|
|
|
prefs_register_bool_preference(cp2179_module, "telnetclean",
|
2016-09-20 21:11:29 +00:00
|
|
|
"Remove extra 0xFF (IAC) bytes from Telnet-encapsulated data",
|
2014-07-16 16:50:41 +00:00
|
|
|
"Whether the SEL Protocol dissector should automatically pre-process Telnet data to remove IAC bytes",
|
|
|
|
&cp2179_telnet_clean);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_cp2179(void)
|
|
|
|
{
|
2016-10-07 20:25:01 +00:00
|
|
|
dissector_add_for_decode_as_with_preference("tcp.port", cp2179_handle);
|
2015-04-03 15:09:17 +00:00
|
|
|
dissector_add_for_decode_as("rtacser.data", cp2179_handle);
|
2014-07-16 16:50:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|