summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-bluecom.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-bluecom.c')
-rw-r--r--epan/dissectors/packet-bluecom.c804
1 files changed, 804 insertions, 0 deletions
diff --git a/epan/dissectors/packet-bluecom.c b/epan/dissectors/packet-bluecom.c
new file mode 100644
index 00000000..e21f0e51
--- /dev/null
+++ b/epan/dissectors/packet-bluecom.c
@@ -0,0 +1,804 @@
+/* packet-bluecom.c
+ *
+ * Routines and register functions of bluecom dissector
+ *
+ * Bachmann bluecom Protocol
+ * Packet dissector based on Ethernet
+ *
+ * COPYRIGHT BY BACHMANN ELECTRONIC GmbH 2016
+ * Contact: Gerhard Khueny <g.khueny@bachmann.info>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/etypes.h>
+#include <epan/to_str.h>
+#include <epan/exceptions.h>
+#include <epan/show_exception.h>
+
+/* bluecom protocol defines */
+
+/* BCP_ETH_VLAN_HDR */
+#define BCP_VLAN_TYPE 0x8100 /* ethernet vlan type */
+#define BCP_ETH_TYPE 0x892D /* ethernet type */
+
+#define BCP_PROT_FLG_REQ 0x01 /* request */
+#define BCP_PROT_FLG_RSP 0x02 /* response */
+#define BCP_PROT_FLG_PRIM 0x80 /* primary */
+
+/* BCP_BLOCK_HDR */
+#define BCP_SLAVEID_ANY 0x0000 /* zero reserved */
+#define BCP_SLAVEID_MASK 0x01FF /* open range for 512 nodes */
+ /* see 'BCP_MAX_NODE_NB' */
+#define BCP_SLAVEID_MST 0x1000 /* master bit */
+#define BCP_SLAVEID_SLV 0x2000 /* slave bit */
+
+#define BCP_BLK_CMD_SYNC 0 /* master -> slave */
+#define BCP_BLK_CMD_DATA 1 /* master/slave -> slave/master */
+#define BCP_BLK_CMD_IDENTIFY 2 /* slave -> master */
+#define BCP_BLK_CMD_SEARCH 3 /* master/slave -> slave */
+#define BCP_BLK_CMD_CONNECT 4 /* master -> slave */
+
+#define BCP_BLK_FLG_VALID 0x01 /* data written by APP -> valid */
+#define BCP_BLK_FLG_PTP 0x02 /* PTP timestamp */
+
+/* BCP_SEARCH_XXX */
+#define BCP_NAME_LEN 32 /* slave name length */
+
+#define BCP_SEARCH_NAME 1 /* search options */
+#define BCP_SEARCH_IPADDR 2
+#define BCP_SEARCH_DEFAULT BCP_SEARCH_NAME
+
+#define BCP_ETHADDR_LEN 6 /* ethernet address length */
+
+#define BCP_PROTOCOL_HDR_LEN 10 /* FIXME: use sizeof with packed from header */
+#define BCP_BLOCK_HDR_LEN 24
+
+/* helper defines */
+#define BOOLSTR(val) ((val) ? "True" : "False")
+#define REQRSP(val) ((val & BCP_PROT_FLG_REQ) ? "Request " : "Response ")
+
+/* prototypes */
+void proto_reg_handoff_bluecom(void);
+void proto_register_bluecom(void);
+
+/* static handles */
+static dissector_handle_t bcp_handle;
+static dissector_table_t bcp_subdissector_table;
+
+static gint proto_bcp = -1;
+static gint ett_bcp = -1;
+static gint ett_bcp_header = -1;
+static gint ett_bcp_blockheader = -1;
+static gint ett_bcp_data = -1;
+
+/* protocol data id */
+static gint hf_bcp_hdr_version = -1;
+static gint hf_bcp_hdr_format = -1;
+static gint hf_bcp_hdr_protflags = -1;
+static gint hf_bcp_hdr_blocknb = -1;
+static gint hf_bcp_hdr_segcode = -1;
+static gint hf_bcp_hdr_auth = -1;
+static gint hf_bcp_hdr_sourceid = -1;
+static gint hf_bcp_hdr_destid = -1;
+static gint hf_bcp_hdr_transid = -1;
+static gint hf_bcp_hdr_cmd = -1;
+static gint hf_bcp_hdr_slavestate = -1;
+static gint hf_bcp_hdr_blockflags = -1;
+static gint hf_bcp_hdr_len = -1;
+static gint hf_bcp_hdr_timestamp = -1;
+static gint hf_bcp_hdr_fragoffset = -1;
+
+static gint hf_bcp_sync_starttime = -1;
+static gint hf_bcp_sync_cycletime = -1;
+static gint hf_bcp_sync_dataratio = -1;
+static gint hf_bcp_sync_identify = -1;
+static gint hf_bcp_sync_vlantag = -1;
+static gint hf_bcp_sync_ethaddr = -1;
+static gint hf_bcp_sync_ethaddr2 = -1;
+
+static gint hf_bcp_identify_error = -1;
+static gint hf_bcp_identify_starttime = -1;
+static gint hf_bcp_identify_ipaddr = -1;
+static gint hf_bcp_identify_name = -1;
+static gint hf_bcp_identify_ethaddr = -1;
+static gint hf_bcp_identify_ethaddr2 = -1;
+
+static gint hf_bcp_searchreq_addrtype = -1;
+static gint hf_bcp_searchreq_reserved = -1;
+static gint hf_bcp_searchreq_name = -1;
+static gint hf_bcp_searchreq_ipaddrfirst = -1;
+static gint hf_bcp_searchreq_ipaddrlast = -1;
+static gint hf_bcp_searchreq_addrdata = -1;
+
+static gint hf_bcp_searchrsp_error = -1;
+static gint hf_bcp_searchrsp_starttime = -1;
+static gint hf_bcp_searchrsp_lenin = -1;
+static gint hf_bcp_searchrsp_lenout = -1;
+static gint hf_bcp_searchrsp_ipaddr = -1;
+static gint hf_bcp_searchrsp_name = -1;
+static gint hf_bcp_searchrsp_ethaddr = -1;
+static gint hf_bcp_searchrsp_ethaddr2 = -1;
+
+static gint hf_bcp_connectreq_lenin = -1;
+static gint hf_bcp_connectreq_lenout = -1;
+static gint hf_bcp_connectreq_cycletime = -1;
+static gint hf_bcp_connectreq_offlinefactor = -1;
+static gint hf_bcp_connectreq_ipaddr = -1;
+static gint hf_bcp_connectreq_name = -1;
+static gint hf_bcp_connectreq_ethaddr = -1;
+static gint hf_bcp_connectreq_ethaddr2 = -1;
+
+static gint hf_bcp_connectrsp_error = -1;
+static gint hf_bcp_connectrsp_lenin = -1;
+static gint hf_bcp_connectrsp_lenout = -1;
+
+static gint hf_bcp_userdata = -1;
+
+/* command defines */
+static const value_string bcp_cmds[] = {
+ { BCP_BLK_CMD_SYNC, "SYNC" },
+ { BCP_BLK_CMD_DATA, "DATA" },
+ { BCP_BLK_CMD_IDENTIFY, "IDENTIFY" },
+ { BCP_BLK_CMD_SEARCH, "SEARCH" },
+ { BCP_BLK_CMD_CONNECT, "CONNECT" },
+ { 0, NULL }
+};
+
+/*
+ * dissector function of connect data (request and response)
+ *
+ * input: tree, buffer (block data), flags (req or rsp)
+ * return: nothing
+ */
+static void
+dissect_bcp_connect_data(packet_info *pinfo, proto_tree *bcp_tree, tvbuff_t *tvb, gint flags)
+{
+ proto_tree *bcp_subtree = NULL;
+ guint offset = 0;
+ guint offset_base = offset;
+ guint len = tvb_reported_length(tvb);
+
+ if (flags & BCP_PROT_FLG_REQ)
+ {
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Connect Request: Name=%s IpAddr=%s",
+ tvb_get_string_enc(pinfo->pool, tvb, offset + 16, BCP_NAME_LEN, ENC_ASCII),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 12));
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_cycletime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_offlinefactor, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII);
+ offset += BCP_NAME_LEN;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ offset += BCP_ETHADDR_LEN;
+ if((len-(offset-offset_base)))
+ {
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectreq_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ offset += BCP_ETHADDR_LEN;
+ }
+ }
+
+ if (flags & BCP_PROT_FLG_RSP)
+ {
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Connect Response: Error=%d",
+ tvb_get_ntohl(tvb, offset));
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_error, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_connectrsp_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
+ }
+}
+
+/*
+ * dissector function of search data (request and response)
+ *
+ * input: tree, buffer (block data) flags (req or rsp)
+ * return: nothing
+ */
+static void
+dissect_bcp_search_data(packet_info *pinfo, proto_tree *bcp_tree, tvbuff_t *tvb, gint flags)
+{
+ proto_tree *bcp_subtree = NULL;
+ guint type = 0;
+ guint offset = 0;
+ guint offset_base = offset;
+ guint len = tvb_reported_length(tvb);
+
+ if (flags & BCP_PROT_FLG_REQ)
+ {
+ type = tvb_get_ntohl(tvb, offset);
+ switch (type)
+ {
+ case BCP_SEARCH_IPADDR:
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Search Request: IpAddrFirst=%s, IpAddrLast=%s",
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 8),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 12)
+ );
+ break;
+
+ case BCP_SEARCH_NAME:
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Search Request: Name=%s",
+ tvb_get_string_enc(pinfo->pool, tvb, offset + 8, BCP_NAME_LEN, ENC_ASCII)
+ );
+ break;
+
+ default:
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Search Request: Unknown AddrType");
+ break;
+ }
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_addrtype, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_reserved, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ switch (type)
+ {
+ case BCP_SEARCH_IPADDR:
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrfirst, tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_ipaddrlast, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
+ break;
+
+ case BCP_SEARCH_NAME:
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchreq_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII);
+ break;
+
+ default:
+ proto_tree_add_bytes_format(bcp_subtree, hf_bcp_searchreq_addrdata, tvb, offset, BCP_NAME_LEN,
+ NULL, "Unknown Address Data (%u bytes)", BCP_NAME_LEN);
+ break;
+ }
+ offset += BCP_NAME_LEN;
+ }
+
+ if (flags & BCP_PROT_FLG_RSP)
+ {
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Search Response: Name=%s, IpAddr=%s Error=%d",
+ tvb_get_string_enc(pinfo->pool, tvb, offset + 16, BCP_NAME_LEN, ENC_ASCII),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 12),
+ tvb_get_letohl(tvb, offset)
+ );
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_error, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenin, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_lenout, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII);
+ offset += BCP_NAME_LEN;
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ offset += BCP_ETHADDR_LEN;
+ if((len-(offset-offset_base)))
+ {
+ proto_tree_add_item(bcp_subtree, hf_bcp_searchrsp_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ }
+ }
+}
+
+/*
+ * dissector function of identify data (request)
+ *
+ * input: tree, buffer (block data), flags (req or rsp)
+ * return: nothing
+ */
+static void
+dissect_bcp_identify_data(packet_info *pinfo, proto_tree *bcp_tree, tvbuff_t *tvb)
+{
+ proto_tree *bcp_subtree = NULL;
+ guint offset = 0;
+ guint offset_base = offset;
+ guint len = tvb_reported_length(tvb);
+
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Identify Request: Name=%s, IpAddr=%s",
+ tvb_get_string_enc(pinfo->pool, tvb, offset + 12, BCP_NAME_LEN, ENC_ASCII),
+ tvb_ip_to_str(pinfo->pool, tvb, offset + 8)
+ );
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_error, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_ipaddr, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_name, tvb, offset, BCP_NAME_LEN, ENC_ASCII);
+ offset += BCP_NAME_LEN;
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ offset += BCP_ETHADDR_LEN;
+ if((len-(offset-offset_base)))
+ {
+ proto_tree_add_item(bcp_subtree, hf_bcp_identify_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ }
+}
+
+/*
+ * dissector function of sync data
+ *
+ * input: tree, buffer (block data)
+ * return: nothing
+ */
+static void
+dissect_bcp_sync_data(proto_tree *bcp_tree, tvbuff_t *tvb)
+{
+ proto_tree *bcp_subtree = NULL;
+ guint offset = 0;
+ guint offset_base = offset;
+ guint len = tvb_reported_length(tvb);
+
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, len, ett_bcp_data, NULL,
+ "BCP Sync Data: Identify=%s",
+ BOOLSTR(tvb_get_guint8(tvb, offset + 9)));
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_starttime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_cycletime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_dataratio, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_identify, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_vlantag, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ /* protocol expansion*/
+ if((len-(offset-offset_base)))
+ {
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ offset += BCP_ETHADDR_LEN;
+ proto_tree_add_item(bcp_subtree, hf_bcp_sync_ethaddr2, tvb, offset, BCP_ETHADDR_LEN, ENC_NA);
+ }
+}
+
+/*
+ * dissector function of data command
+ *
+ * input: tree, buffer (block data)
+ * return: nothing
+ */
+static void
+dissect_bcp_data(proto_tree *bcp_tree, packet_info *pinfo, tvbuff_t *tvb,
+ guint segcode)
+{
+ dissector_handle_t handle;
+
+ /* Probably a sub-dissector exists for this type/version combination. */
+ handle = dissector_get_uint_handle(bcp_subdissector_table, segcode);
+
+ if (handle)
+ {
+ /* Call the sub-dissector. */
+ call_dissector(handle, tvb, pinfo, bcp_tree);
+ }
+ else
+ {
+ proto_tree_add_item(bcp_tree, hf_bcp_userdata, tvb, 0, -1, ENC_NA);
+ }
+}
+
+
+/*
+ * dissector function of block header
+ *
+ * input: tree, buffer (data), offset (data pointer), number of header block
+ * output: command from header, length of following data
+ * return: updated offset
+ */
+static guint
+dissect_bcp_block_header(proto_tree *bcp_tree, tvbuff_t *tvb, guint offset,
+ guint blocknb, guint *cmd, guint *len)
+{
+ proto_tree *bcp_subtree = NULL;
+
+ *cmd = tvb_get_guint8(tvb, offset + 6);
+ *len = tvb_get_ntohs(tvb, offset + 12);
+
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, offset, BCP_BLOCK_HDR_LEN, ett_bcp_blockheader, NULL,
+ "BCP Block Header (%u): Cmd=%s (%u), Len=%u",
+ blocknb,
+ val_to_str_const(*cmd, bcp_cmds, "UNKNOWN"), *cmd,
+ *len
+ );
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_sourceid, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_destid, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_transid, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_cmd, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_slavestate, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_blockflags, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_len, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_fragoffset, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
+ offset += 8;
+ return offset;
+}
+
+/*
+ * dissector function of protocol header
+ *
+ * input: tree, buffer (data), offset (data pointer)
+ * output: flags, block count, segcode from header
+ * return: updated offset
+ */
+static guint
+dissect_bcp_protocol_header(proto_tree *bcp_tree, tvbuff_t *tvb,
+ guint offset, gint *flags, guint *blocknb,
+ guint *segcode)
+{
+ proto_tree *bcp_subtree = NULL;
+
+ *flags = tvb_get_guint8(tvb, offset + 2);
+ *blocknb = tvb_get_guint8(tvb, offset + 3);
+ *segcode = tvb_get_ntohs(tvb, offset + 4);
+
+ bcp_subtree = proto_tree_add_subtree_format(bcp_tree, tvb, 0, BCP_PROTOCOL_HDR_LEN, ett_bcp_header, NULL,
+ "BCP Protocol Header: BlockNb=%d, SegCode=%d",
+ *blocknb,
+ *segcode);
+
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_format, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_protflags, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_blocknb, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_segcode, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(bcp_subtree, hf_bcp_hdr_auth, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ return offset;
+}
+
+
+/*
+ * dissect_bcp - the bcp dissector function
+ */
+static int dissect_bluecom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ guint cmd, flags, blocknb;
+ volatile guint block;
+ guint len;
+ volatile guint offset = 0;
+ proto_tree *bcp_tree = NULL;
+ proto_item *bcp_item_base = NULL;
+ tvbuff_t *block_tvb;
+ guint segcode = 0;
+
+ /* set protocol name column */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "bluecom");
+ /* clear out stuff in the info column */
+ col_set_str(pinfo->cinfo, COL_INFO, "CMD: ");
+
+ /* add base item */
+ bcp_item_base = proto_tree_add_item(tree, proto_bcp, tvb, 0, -1, ENC_NA);
+ /* add base tree */
+ bcp_tree = proto_item_add_subtree(bcp_item_base, ett_bcp);
+
+ /* BCP header */
+ offset = dissect_bcp_protocol_header(bcp_tree, tvb, offset, &flags, &blocknb, &segcode);
+
+ /* set info column */
+ col_append_fstr(pinfo->cinfo, COL_INFO, "segcode=%u blocks=%u",
+ segcode, blocknb);
+
+ /* Iterate over blocks */
+ for (block = 0; block < blocknb; block++)
+ {
+ /* BCP block header*/
+ offset = dissect_bcp_block_header(bcp_tree, tvb, offset, block, &cmd, &len);
+
+ /* append text to BCP base */
+ proto_item_append_text(bcp_item_base, ", %s (%u) len=%u",
+ val_to_str_const(cmd, bcp_cmds, "UNKNOWN"), cmd, len);
+
+ block_tvb = tvb_new_subset_length(tvb, offset, len);
+ TRY {
+ switch (cmd)
+ {
+ case BCP_BLK_CMD_SYNC:
+ dissect_bcp_sync_data(bcp_tree, block_tvb);
+ break;
+
+ case BCP_BLK_CMD_IDENTIFY:
+ dissect_bcp_identify_data(pinfo, bcp_tree, block_tvb);
+ break;
+
+ case BCP_BLK_CMD_SEARCH:
+ col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
+ dissect_bcp_search_data(pinfo, bcp_tree, block_tvb, flags);
+ break;
+
+ case BCP_BLK_CMD_CONNECT:
+ col_append_str(pinfo->cinfo, COL_INFO, REQRSP(flags));
+ dissect_bcp_connect_data(pinfo, bcp_tree, block_tvb, flags);
+ break;
+
+ case BCP_BLK_CMD_DATA:
+ default:
+ dissect_bcp_data(bcp_tree, pinfo, block_tvb, segcode);
+ break;
+ }
+ } CATCH_NONFATAL_ERRORS {
+ /*
+ * Somebody threw an exception that means that there was
+ * a problem dissecting the block. Just show the exception
+ * and then continue to dissect blocks.
+ */
+ show_exception(block_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
+ } ENDTRY;
+ offset += len;
+ }
+
+ return offset;
+}
+
+/*
+ * register dissector
+ */
+void
+proto_register_bluecom(void)
+{
+ static hf_register_info hf_bcp[] = {
+ /* BCP_PROTOCOL_HDR */
+ { &hf_bcp_hdr_version, {
+ "Version", "bluecom.hdr.version", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_format, {
+ "Format", "bluecom.hdr.format", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_protflags, {
+ "Flags", "bluecom.hdr.protflags", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_blocknb, {
+ "BlockNb", "bluecom.hdr.blocknb", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_segcode, {
+ "SegCode", "bluecom.hdr.segcode", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_auth, {
+ "Auth", "bluecom.hdr.auth", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+
+ /* BCP_BLOCK_HDR */
+ { &hf_bcp_hdr_sourceid, {
+ "SourceId", "bluecom.hdr.sourceid", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_destid, {
+ "DestId", "bluecom.hdr.destid", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_transid, {
+ "TransId", "bluecom.hdr.transid", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_cmd, {
+ "Cmd", "bluecom.hdr.cmd", FT_UINT8,
+ BASE_HEX, VALS(bcp_cmds), 0, NULL, HFILL }},
+ { &hf_bcp_hdr_slavestate, {
+ "SlaveState", "bluecom.hdr.slavestate", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_blockflags, {
+ "Flags", "bluecom.hdr.blockflags", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_len, {
+ "Len", "bluecom.hdr.len", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_fragoffset, {
+ "FragOffset", "bluecom.hdr.fragoffset", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_hdr_timestamp, {
+ "Timestamp", "bluecom.hdr.timestamp", FT_ABSOLUTE_TIME,
+ ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
+
+ /* BCP_SYNC_DATA */
+ { &hf_bcp_sync_starttime, {
+ "StartTime", "bluecom.sync.blockflags", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_cycletime, {
+ "CycleTime", "bluecom.sync.cycletime", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_dataratio, {
+ "DataRatio", "bluecom.sync.dataratio", FT_UINT8,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_identify, {
+ "Identify", "bluecom.sync.identify", FT_BOOLEAN,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_vlantag, {
+ "VlanTag", "bluecom.sync.vlantag", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_ethaddr, {
+ "EthAddr", "bluecom.sync.ethaddr", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_sync_ethaddr2, {
+ "EthAddr2", "bluecom.sync.ethaddr2", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ /* BCP_IDENTIFY_REQ */
+ { &hf_bcp_identify_error, {
+ "Error", "bluecom.identify.error", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_identify_starttime, {
+ "StartTime", "bluecom.identify.starttime", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_identify_ipaddr, {
+ "IpAddr", "bluecom.identify.ipaddr", FT_IPv4,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_identify_name, {
+ "Name", "bluecom.identify.name", FT_STRING,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_identify_ethaddr, {
+ "EthAddr", "bluecom.identify.ethaddr", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_identify_ethaddr2, {
+ "EthAddr2", "bluecom.identify.ethaddr2", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ /* BCP_SEARCH_REQ */
+ { &hf_bcp_searchreq_addrtype, {
+ "AddrType", "bluecom.searchreq.addrtype", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchreq_reserved, {
+ "Reserved", "bluecom.searchreq.reserved", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchreq_name, {
+ "Name", "bluecom.searchreq.name", FT_STRING,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchreq_ipaddrfirst, {
+ "IpAddrFirst", "bluecom.searchreq.ipaddrfirst", FT_IPv4,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchreq_ipaddrlast, {
+ "IpAddrLast", "bluecom.searchreq.ipaddrlast", FT_IPv4,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchreq_addrdata, {
+ "Data", "bluecom.searchreq.addrdata", FT_BYTES,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ /* BCP_SEARCH_RSP */
+ { &hf_bcp_searchrsp_error, {
+ "Error", "bluecom.searchrsp.error", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_starttime, {
+ "StartTime", "bluecom.searchrsp.starttime", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_lenin, {
+ "LenIn", "bluecom.searchrsp.lenin", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_lenout, {
+ "LenOut", "bluecom.searchrsp.lenout", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_ipaddr, {
+ "IpAddr", "bluecom.searchrsp.ipaddr", FT_IPv4,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_name, {
+ "Name", "bluecom.searchrsp.name", FT_STRING,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_ethaddr, {
+ "EthAddr", "bluecom.searchrsp.ethaddr", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_searchrsp_ethaddr2, {
+ "EthAddr2", "bluecom.searchrsp.ethaddr2", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ /* BCP_CONNECT_REQ */
+ { &hf_bcp_connectreq_lenin, {
+ "LenIn", "bluecom.connectreq.lenin", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_lenout, {
+ "LenOut", "bluecom.connectreq.lenout", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_cycletime, {
+ "CycleTime", "bluecom.connectreq.cycletime", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_offlinefactor, {
+ "OfflineFactor", "bluecom.connectreq.offlinefactor", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_ipaddr, {
+ "IpAddr", "bluecom.connectreq.ipaddr", FT_IPv4,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_name, {
+ "Name", "bluecom.connectreq.name", FT_STRING,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_ethaddr, {
+ "EthAddr", "bluecom.connectreq.ethaddr", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectreq_ethaddr2, {
+ "EthAddr2", "bluecom.connectreq.ethaddr2", FT_ETHER,
+ BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ /* BCP_CONNECT_RSP */
+ { &hf_bcp_connectrsp_error, {
+ "Error", "bluecom.connectrsp.error", FT_UINT32,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectrsp_lenin, {
+ "LenIn", "bluecom.connectrsp.lenin", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+ { &hf_bcp_connectrsp_lenout, {
+ "LenOut", "bluecom.connectrsp.lenout", FT_UINT16,
+ BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+
+ /* USERDATA */
+ { &hf_bcp_userdata, {
+ "BCP Userdata", "bluecom.userdata", FT_BYTES,
+ BASE_NONE, NULL, 0, NULL, HFILL }}
+ };
+
+ /* define subtree elements - this is used for behavior of tree display */
+ static gint *ett[] = {
+ &ett_bcp,
+ &ett_bcp_header,
+ &ett_bcp_blockheader,
+ &ett_bcp_data,
+ };
+
+ /* register protocol */
+ proto_bcp = proto_register_protocol("bluecom Protocol", "bluecom", "bluecom");
+
+ /* register elements */
+ proto_register_field_array(proto_bcp, hf_bcp, array_length(hf_bcp));
+ /* register subtree elements */
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* register dissector */
+ bcp_handle = register_dissector("bluecom", dissect_bluecom, proto_bcp);
+
+ /* add dissector table */
+ bcp_subdissector_table = register_dissector_table("bluecomseg", "bluecom SegCode", proto_bcp,
+ FT_UINT8, BASE_DEC);
+}
+
+/*
+ * hand off dissector
+ */
+void
+proto_reg_handoff_bluecom(void)
+{
+ /* Add dissector handle */
+ dissector_add_uint("ethertype", ETHERTYPE_BLUECOM, bcp_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:
+ */