diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-hsms.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-hsms.c')
-rw-r--r-- | epan/dissectors/packet-hsms.c | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/epan/dissectors/packet-hsms.c b/epan/dissectors/packet-hsms.c new file mode 100644 index 00000000..361012aa --- /dev/null +++ b/epan/dissectors/packet-hsms.c @@ -0,0 +1,771 @@ +/* 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 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * 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 "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); + +static dissector_handle_t hsms_handle; + +/* 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); + 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_epan_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.binary", + FT_BYTES, SEP_COLON, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_boolean, + { "Value", "hsms.data.item.value.boolean", + FT_BOOLEAN, 8, + NULL, 0x01, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_string, + { "Value", "hsms.data.item.value.string", + FT_STRING, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_i8, + { "Value", "hsms.data.item.value.int64", + FT_INT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_i1, + { "Value", "hsms.data.item.value.int8", + FT_INT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_i2, + { "Value", "hsms.data.item.value.int16", + FT_INT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_i4, + { "Value", "hsms.data.item.value.int32", + FT_INT32, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_f8, + { "Value", "hsms.data.item.value.double", + FT_DOUBLE, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_f4, + { "Value", "hsms.data.item.value.float", + FT_FLOAT, BASE_NONE, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_u8, + { "Value", "hsms.data.item.value.uint64", + FT_UINT64, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_u1, + { "Value", "hsms.data.item.value.uint8", + FT_UINT8, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_u2, + { "Value", "hsms.data.item.value.uint16", + FT_UINT16, BASE_DEC, + NULL, 0x00, + NULL, HFILL } + }, + { &hf_hsms_data_item_value_u4, + { "Value", "hsms.data.item.value.uint32", + 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)); + + hsms_handle = register_dissector("hsms", dissect_hsms, proto_hsms); + + hsms_init(); +} + +void +proto_reg_handoff_hsms(void) +{ + 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: + */ |