wireshark/epan/dissectors/packet-hsms.c
Michael Mann 268841f3e0 Combine Decode As and port preferences for tcp.port dissector table.
This patch introduces new APIs to allow dissectors to have a preference for
a (TCP) port, but the underlying data is actually part of Decode As functionality.
For now the APIs are intentionally separate from the regular APIs that register a
dissector within a dissector table.  It may be possible to eventually combine the
two so that all dissectors that register with a dissector table have an opportunity
to "automatically" have a preference to adjust the "table value" through the
preferences dialog.

The tcp.port dissector table was used as the guinea pig.  This will eventually be
expanded to other dissector tables as well (most notably UDP ports).  Some
dissectors that "shared" a TCP/UDP port preference were also converted. It also
removed the need for some preference callback functions (mostly when the callback
function was the proto_reg_handoff function) so there is cleanup around that.

Dissectors that has a port preference whose default was 0 were switched to using
the dissector_add_for_decode_as_with_preference API rather than dissector_add_uint_with_preference

Also added comments for TCP ports used that aren't IANA registered.

Change-Id: I99604f95d426ad345f4b494598d94178b886eb67
Reviewed-on: https://code.wireshark.org/review/17724
Reviewed-by: Michael Mann <mmann78@netscape.net>
2016-10-08 02:44:53 +00:00

784 lines
27 KiB
C

/* packet-hsms.c
* Routines for High-speed SECS message service dissection
* Copyright 2016, Benjamin Parzella <bparzella@gmail.com>
*
* 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.
*/
/*
* HSMS - High-speed SECS message service (SEMI-E37)
* SECS - SEMI equipment communications standard (SEMI-E5)
*
* TCP based protocol for semiconductor factory automation
* defined by SEMI (http://www.semi.org)
*
* Usual TCP port: 5000
*/
#include <config.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/dissectors/packet-tcp.h>
#include <epan/expert.h>
#define PTYPE_SECS 0
#define STYPE_SECS_DATA 0
#define STYPE_SELECT_REQ 1
#define STYPE_SELECT_RSP 2
#define STYPE_DESELECT_REQ 3
#define STYPE_DESELECT_RSP 4
#define STYPE_LINKTEST_REQ 5
#define STYPE_LINKTEST_RSP 6
#define STYPE_REJECT_REQ 7
#define STYPE_SEPARATE_REQ 9
#define FORMAT_CODE_LIST 000
#define FORMAT_CODE_BINARY 010
#define FORMAT_CODE_BOOLEAN 011
#define FORMAT_CODE_ASCII 020
#define FORMAT_CODE_JIS8 021
#define FORMAT_CODE_2BYTE 022
#define FORMAT_CODE_I8 030
#define FORMAT_CODE_I1 031
#define FORMAT_CODE_I2 032
#define FORMAT_CODE_I4 034
#define FORMAT_CODE_F8 040
#define FORMAT_CODE_F4 044
#define FORMAT_CODE_U8 050
#define FORMAT_CODE_U1 051
#define FORMAT_CODE_U2 052
#define FORMAT_CODE_U4 054
/* Prototypes */
void proto_reg_handoff_hsms(void);
void proto_register_hsms(void);
/* Initialize the protocol and registered fields */
static int proto_hsms = -1;
static int hf_hsms_packet_length = -1;
static int hf_hsms_header_sessionid = -1;
static int hf_hsms_header_statusbyte2 = -1;
static int hf_hsms_header_wbit = -1;
static int hf_hsms_header_stream = -1;
static int hf_hsms_header_statusbyte3 = -1;
static int hf_hsms_header_function = -1;
static int hf_hsms_header_ptype = -1;
static int hf_hsms_header_stype = -1;
static int hf_hsms_header_system = -1;
static int hf_hsms_data_item_format = -1;
static int hf_hsms_data_item_length_bytes = -1;
static int hf_hsms_data_item_length = -1;
static int hf_hsms_data_item_value_binary = -1;
static int hf_hsms_data_item_value_boolean = -1;
static int hf_hsms_data_item_value_string = -1;
static int hf_hsms_data_item_value_i8 = -1;
static int hf_hsms_data_item_value_i1 = -1;
static int hf_hsms_data_item_value_i2 = -1;
static int hf_hsms_data_item_value_i4 = -1;
static int hf_hsms_data_item_value_f8 = -1;
static int hf_hsms_data_item_value_f4 = -1;
static int hf_hsms_data_item_value_u8 = -1;
static int hf_hsms_data_item_value_u1 = -1;
static int hf_hsms_data_item_value_u2 = -1;
static int hf_hsms_data_item_value_u4 = -1;
static expert_field ei_hsms_ptype = EI_INIT;
static wmem_map_t *value_lengths;
/*
* Presentation type (ptype)
*
* 0 => SECS-II Encoding
* 1-127 => Reserved for subsidiary standards
* 128-255 => Reserved, not used
*/
static const value_string ptype_names[] = {
{ PTYPE_SECS, "SECS" },
{ 0, NULL }
};
/*
* Session type (stype)
*
* 0 => SECS-II data message
* 1 => Select request
* 2 => Select response
* 3 => Deselect request
* 4 => Deselect response
* 5 => Link test request
* 6 => Link test response
* 7 => Packet reject request
* 8 => Reserved, not used
* 9 => Separate request
* 10 => Reserved, not used
* 11-127 => Reserved for subsidiary standards
* 128-255 => Reserved, not used
*/
static const value_string stype_names[] = {
{ STYPE_SECS_DATA, "Data message" },
{ STYPE_SELECT_REQ, "Select.req" },
{ STYPE_SELECT_RSP, "Select.rsp" },
{ STYPE_DESELECT_REQ, "Deselect.req" },
{ STYPE_DESELECT_RSP, "Deselect.rsp" },
{ STYPE_LINKTEST_REQ, "Linktest.req" },
{ STYPE_LINKTEST_RSP, "Linktest.rsp" },
{ STYPE_REJECT_REQ, "Reject.req" },
{ STYPE_SEPARATE_REQ, "Separate.req" },
{ 0, NULL }
};
static const value_string item_format_names[] = {
{ FORMAT_CODE_LIST, "List" },
{ FORMAT_CODE_BINARY, "Binary" },
{ FORMAT_CODE_BOOLEAN, "Boolean" },
{ FORMAT_CODE_ASCII, "ASCII" },
{ FORMAT_CODE_JIS8, "JIS-8" },
{ FORMAT_CODE_2BYTE, "2-Byte Char" },
{ FORMAT_CODE_I8, "I8" },
{ FORMAT_CODE_I1, "I1" },
{ FORMAT_CODE_I2, "I2" },
{ FORMAT_CODE_I4, "I4" },
{ FORMAT_CODE_F8, "F8" },
{ FORMAT_CODE_F4, "F4" },
{ FORMAT_CODE_U8, "U8" },
{ FORMAT_CODE_U1, "U1" },
{ FORMAT_CODE_U2, "U2" },
{ FORMAT_CODE_U4, "U4" },
{ 0, NULL }
};
/* Global sample port preference - real port preferences should generally
* default to 0 unless there is an IANA-registered (or equivalent) port for your
* protocol. */
#define HSMS_TCP_PORT 0
/* Initialize the subtree pointers */
static gint ett_hsms = -1;
static gint ett_hsms_header = -1;
static gint ett_hsms_data = -1;
static gint ett_hsms_data_item = -1;
/* A sample #define of the minimum length (in bytes) of the protocol data.
* If data is received with fewer than this many bytes it is rejected by
* the current dissector. */
#define HSMS_MIN_LENGTH 14
static int
dissect_secs_variable(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data, int *offset)
{
proto_item *hdr_stream_item;
proto_tree *hsms_data_item_tree, *hsms_data_item_header_tree;
proto_item *hdr_item = NULL;
guint item_format_code = -1;
guint length_bytes = -1;
guint length = 0;
guint *value_length = NULL;
int len = 0;
int itemLength = 0;
/* extract item format code and number of length bytes from byte #1 */
item_format_code = (tvb_get_guint8(tvb, *offset) & 0xFC) >> 2;
length_bytes = (tvb_get_guint8(tvb, *offset) & 0x3);
/* extract item length in bytes */
switch (length_bytes)
{
case 3:
length = tvb_get_ntoh24(tvb, *offset + 1);
break;
case 2:
length = tvb_get_ntohs(tvb, *offset + 1);
break;
case 1:
length = tvb_get_guint8(tvb, *offset + 1);
break;
default:
return -1;
}
/* list has no item length and length is alreaty the count of items */
if (item_format_code != 0)
{
value_length = (guint*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
/* length must be dividable by item length, because it must be a multiple of items */
if (length % GPOINTER_TO_UINT(value_length) != 0)
return -1;
/* shorten length to actual count of items */
length = length / GPOINTER_TO_UINT(value_length);
}
/* add the item tree to the parent tree */
hsms_data_item_tree = proto_tree_add_subtree_format(tree, tvb, *offset, -1, ett_hsms_data_item, &hdr_item, "%s (%d items)", val_to_str(item_format_code, item_format_names, "Unknown (%02o)"), length);
/* add the formatcode/length bytes to the item tree */
hsms_data_item_header_tree = proto_tree_add_subtree_format(hsms_data_item_tree, tvb, *offset, 1, ett_hsms_header, &hdr_stream_item, "Data format: %s, Length bytes: %d", val_to_str(item_format_code, item_format_names, "Unknown (%02o)"), length_bytes);
proto_tree_add_item(hsms_data_item_header_tree, hf_hsms_data_item_format, tvb, *offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(hsms_data_item_header_tree, hf_hsms_data_item_length_bytes, tvb, *offset, 1, ENC_BIG_ENDIAN);
*offset += 1;
/* add the length to the item tree */
len = length_bytes;
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_length, tvb, *offset, len, ENC_BIG_ENDIAN);
*offset += len;
/* add the actual item to the item tree */
switch(item_format_code)
{
case FORMAT_CODE_BINARY:
/* add binary value as one to item list */
value_length = (guint*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
len = GPOINTER_TO_UINT(value_length) * length;
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_binary, tvb, *offset, len, ENC_NA);
itemLength = len;
*offset += len;
break;
case FORMAT_CODE_ASCII:
/* add ascii value as one to item list */
value_length = (guint*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
len = GPOINTER_TO_UINT(value_length) * length;
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_string, tvb, *offset, len, ENC_ASCII|ENC_NA);
itemLength = len;
*offset += len;
break;
default:
/* walk through the items */
for(unsigned int counter=0; counter<length; counter++)
{
if (item_format_code == 0)
{
/* add sub items for list element to item tree */
int subItemLength = dissect_secs_variable(tvb, pinfo, hsms_data_item_tree, data, offset);
/* check for parsing error in sub list */
if (subItemLength == -1)
{
return -1;
}
itemLength += subItemLength;
}
else
{
/* add single item of type item tree */
value_length = (guint*)wmem_map_lookup(value_lengths, GUINT_TO_POINTER(item_format_code));
len = GPOINTER_TO_UINT(value_length);
switch(item_format_code)
{
case FORMAT_CODE_BOOLEAN:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_boolean, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_I8:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i8, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_I1:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i1, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_I2:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i2, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_I4:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_i4, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_F8:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_f8, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_F4:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_f4, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_U8:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u8, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_U1:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u1, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_U2:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u2, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
case FORMAT_CODE_U4:
proto_tree_add_item(hsms_data_item_tree, hf_hsms_data_item_value_u4, tvb, *offset, len, ENC_BIG_ENDIAN);
break;
default:
return -1;
}
itemLength += len;
*offset += len;
}
}
}
/* update length of item tree */
proto_item_set_len(hsms_data_item_tree, itemLength + length_bytes + 1);
return 1 + length_bytes + itemLength;
}
static int
dissect_secs_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data, int *offset)
{
return dissect_secs_variable(tvb, pinfo, tree, data, offset);
}
/* Code to actually dissect the hsms packets */
static int
dissect_hsms_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
proto_item *hdr_item = NULL;
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *ti;
proto_tree *hsms_tree, *hsms_header_tree, *hsms_header_stream_tree;
/* Other misc. local variables. */
guint offset = 0;
guint sessionId = -1;
guint byte2 = -1;
guint byte3 = -1;
guint pType = -1;
guint sType = -1;
/*** HEURISTICS ***/
/* Check that the packet is long enough for it to belong to us. */
if (tvb_reported_length(tvb) < HSMS_MIN_LENGTH)
return 0;
/* Check if first byte describes length) */
if ((tvb_get_ntohl(tvb, 0) + 4) != tvb_reported_length(tvb))
return 0;
sessionId = tvb_get_ntohs(tvb, 4);
byte2 = tvb_get_guint8(tvb, 6);
byte3 = tvb_get_guint8(tvb, 7);
pType = tvb_get_guint8(tvb, 8);
sType = tvb_get_guint8(tvb, 9);
/* sTypes 8, 10 and 128+ are unused, 11-127 might be used for subsidiary standards */
if ((sType == 8) || (sType == 10) || (sType > 127))
return 0;
/* see definition of stype_names for details on the sType values */
switch (sType)
{
case STYPE_SECS_DATA:
if (byte2 == 0) // stream must be set
return 0;
break;
case STYPE_SELECT_REQ:
case STYPE_DESELECT_REQ:
case STYPE_SEPARATE_REQ:
if ((byte2 != 0) || (byte3 != 0)) // byte2&3 must be zero
return 0;
if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
return 0;
break;
case STYPE_SELECT_RSP:
case STYPE_DESELECT_RSP:
if (byte2 != 0) // byte2 must be zero
return 0;
if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
return 0;
break;
case STYPE_LINKTEST_REQ:
case STYPE_LINKTEST_RSP:
if (sessionId != 0xFFFF) // Session ID must be max
return 0;
if (byte2 != 0) // byte2 must be zero
return 0;
if (byte3 != 0) // byte3 must be zero
return 0;
if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
return 0;
break;
case STYPE_REJECT_REQ:
if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH) // no data for sType != 0
return 0;
break;
}
/*** COLUMN DATA ***/
col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSMS");
/* Clear out stuff in the info column */
col_clear(pinfo->cinfo,COL_INFO);
if (sType == STYPE_SECS_DATA)
{
col_add_fstr(pinfo->cinfo, COL_INFO, "HSMS SECS Stream/Function S%02dF%02d",
byte2 & 0x7F, byte3);
}
else
{
col_add_fstr(pinfo->cinfo, COL_INFO, "HSMS Message %s",
val_to_str(sType, stype_names, "Unknown (%02d)"));
}
/*** PROTOCOL TREE ***/
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_hsms, tvb, 0, -1, ENC_NA);
hsms_tree = proto_item_add_subtree(ti, ett_hsms);
/* packet size = 4 bytes */
proto_tree_add_item(hsms_tree, hf_hsms_packet_length, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* header = 10 bytes */
/* see definition of stype_names for details on the sType values */
switch (sType)
{
case STYPE_SECS_DATA:
hsms_header_tree = proto_tree_add_subtree_format(hsms_tree, tvb, offset, 10, ett_hsms_header, &hdr_item, "Header (S%02dF%02d)", byte2 & 0x7F, byte3);
break;
default:
hsms_header_tree = proto_tree_add_subtree_format(hsms_tree, tvb, offset, 10, ett_hsms_header, &hdr_item, "Header (%s)", val_to_str(sType, stype_names, "Unknown (%02d)"));
break;
}
/* session id = 2 bytes */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_sessionid, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* see definition of stype_names for details on the sType values */
switch (sType)
{
case STYPE_SECS_DATA:
/* wbit=1bit + stream=7bits = 1 byte */
hsms_header_stream_tree = proto_tree_add_subtree_format(hsms_header_tree, tvb, offset, 1, ett_hsms_header, &hdr_item, "Stream %d, Response requested: %s", byte2 & 0x7F, ((byte2 & 0x80) > 0) ? "Yes" : "No");
proto_tree_add_item(hsms_header_stream_tree, hf_hsms_header_wbit, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(hsms_header_stream_tree, hf_hsms_header_stream, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
/* function = 1 byte */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_function, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
break;
default:
/* status byte 2 = 1 byte */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_statusbyte2, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
/* status byte 3 = 1 byte */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_statusbyte3, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
break;
}
/* ptype = 1 byte */
ti = proto_tree_add_item(hsms_header_tree, hf_hsms_header_ptype, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
if (pType != 0)
expert_add_info(pinfo, ti, &ei_hsms_ptype);
/* stype = 1 byte */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_stype, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
/* system = 4 bytes */
proto_tree_add_item(hsms_header_tree, hf_hsms_header_system, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* decode secs data if available */
if (tvb_reported_length(tvb) > HSMS_MIN_LENGTH)
{
if (pType == PTYPE_SECS)
dissect_secs_message(tvb, pinfo, hsms_tree, data, &offset);
}
return offset;
}
/* determine PDU length of protocol foo */
static guint
get_hsms_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
/* first four bytes are length information */
return (guint)tvb_get_ntohl(tvb, offset) + 4;
}
/* The main dissecting routine */
static int
dissect_hsms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4,
get_hsms_message_len, dissect_hsms_message, data);
return tvb_captured_length(tvb);
}
static void
hsms_init(void)
{
value_lengths = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_LIST), GINT_TO_POINTER(0));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_BINARY), GINT_TO_POINTER(1));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_BOOLEAN), GINT_TO_POINTER(1));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_ASCII), GINT_TO_POINTER(1));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_JIS8), GINT_TO_POINTER(2));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_2BYTE), GINT_TO_POINTER(2));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I8), GINT_TO_POINTER(8));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I1), GINT_TO_POINTER(1));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I2), GINT_TO_POINTER(2));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_I4), GINT_TO_POINTER(4));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_F8), GINT_TO_POINTER(8));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_F4), GINT_TO_POINTER(4));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U8), GINT_TO_POINTER(8));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U1), GINT_TO_POINTER(1));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U2), GINT_TO_POINTER(2));
wmem_map_insert(value_lengths, GINT_TO_POINTER(FORMAT_CODE_U4), GINT_TO_POINTER(4));
}
void
proto_register_hsms(void)
{
expert_module_t* expert_hsms;
static hf_register_info hf[] = {
{ &hf_hsms_packet_length,
{ "Packet length", "hsms.length",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_sessionid,
{ "Session ID", "hsms.header.sessionid",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_statusbyte2,
{ "Status byte 2", "hsms.header.statusbyte2",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_wbit,
{ "W-bit (Response required)", "hsms.header.wbit",
FT_BOOLEAN, 8,
NULL, 0x80,
NULL, HFILL }
},
{ &hf_hsms_header_stream,
{ "Stream", "hsms.header.stream",
FT_UINT8, BASE_DEC,
NULL, 0x7F,
NULL, HFILL }
},
{ &hf_hsms_header_statusbyte3,
{ "Status byte 3", "hsms.header.statusbyte3",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_function,
{ "Function", "hsms.header.function",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_ptype,
{ "PType (Presentation type)", "hsms.header.ptype",
FT_UINT8, BASE_DEC,
VALS(ptype_names), 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_stype,
{ "SType (Session type)", "hsms.header.stype",
FT_UINT8, BASE_DEC,
VALS(stype_names), 0x0,
NULL, HFILL }
},
{ &hf_hsms_header_system,
{ "System Bytes", "hsms.header.system",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_hsms_data_item_format,
{ "Data type", "hsms.data.item.format",
FT_UINT8, BASE_OCT,
VALS(item_format_names), 0xFC,
NULL, HFILL }
},
{ &hf_hsms_data_item_length_bytes,
{ "Length bytes", "hsms.data.item.length_bytes",
FT_UINT8, BASE_OCT,
NULL, 0x03,
NULL, HFILL }
},
{ &hf_hsms_data_item_length,
{ "Length", "hsms.data.item.length",
FT_UINT32, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_binary,
{ "Value", "hsms.data.item.value",
FT_BYTES, SEP_COLON,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_boolean,
{ "Value", "hsms.data.item.value",
FT_BOOLEAN, 8,
NULL, 0x01,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_string,
{ "Value", "hsms.data.item.value",
FT_STRING, BASE_NONE,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_i8,
{ "Value", "hsms.data.item.value",
FT_INT64, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_i1,
{ "Value", "hsms.data.item.value",
FT_INT8, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_i2,
{ "Value", "hsms.data.item.value",
FT_INT16, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_i4,
{ "Value", "hsms.data.item.value",
FT_INT32, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_f8,
{ "Value", "hsms.data.item.value",
FT_DOUBLE, BASE_NONE,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_f4,
{ "Value", "hsms.data.item.value",
FT_FLOAT, BASE_NONE,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_u8,
{ "Value", "hsms.data.item.value",
FT_UINT64, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_u1,
{ "Value", "hsms.data.item.value",
FT_UINT8, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_u2,
{ "Value", "hsms.data.item.value",
FT_UINT16, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
{ &hf_hsms_data_item_value_u4,
{ "Value", "hsms.data.item.value",
FT_UINT32, BASE_DEC,
NULL, 0x00,
NULL, HFILL }
},
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_hsms,
&ett_hsms_header,
&ett_hsms_data,
&ett_hsms_data_item
};
static ei_register_info ei[] = {
{ &ei_hsms_ptype,
{ "hsms.header.ptype.unknown",
PI_RESPONSE_CODE,
PI_NOTE,
"Unknown presentation type (ptype)",
EXPFILL }
}
};
/* Register the protocol name and description */
proto_hsms = proto_register_protocol (
"High-speed SECS Message Service Protocol", /* name */
"HSMS", /* short name */
"hsms" /* abbrev */
);
/* Required function calls to register the header fields and subtrees */
proto_register_field_array(proto_hsms, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_hsms = expert_register_protocol(proto_hsms);
expert_register_field_array(expert_hsms, ei, array_length(ei));
register_init_routine(&hsms_init);
}
void
proto_reg_handoff_hsms(void)
{
static dissector_handle_t hsms_handle;
hsms_handle = create_dissector_handle(dissect_hsms, proto_hsms);
dissector_add_for_decode_as_with_preference("tcp.port", hsms_handle);
}
/*
* Editor modelines - https://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:
*/