summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-lbttcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-lbttcp.c')
-rw-r--r--epan/dissectors/packet-lbttcp.c836
1 files changed, 836 insertions, 0 deletions
diff --git a/epan/dissectors/packet-lbttcp.c b/epan/dissectors/packet-lbttcp.c
new file mode 100644
index 00000000..41e4b9e7
--- /dev/null
+++ b/epan/dissectors/packet-lbttcp.c
@@ -0,0 +1,836 @@
+/* packet-lbttcp.c
+ * Routines for LBM TCP Packet dissection
+ *
+ * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved.
+ *
+ * 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/prefs.h>
+#include <epan/uat.h>
+#include <epan/to_str.h>
+#include "packet-tcp.h"
+#include "packet-lbm.h"
+#include "packet-lbttcp.h"
+
+void proto_register_lbttcp(void);
+void proto_reg_handoff_lbttcp(void);
+
+/* Protocol handle */
+static int proto_lbttcp = -1;
+
+/* Dissector handle */
+static dissector_handle_t lbttcp_dissector_handle;
+
+/*----------------------------------------------------------------------------*/
+/* LBT-TCP protocol management. */
+/*----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ wmem_tree_t * frame_tree;
+ wmem_tree_t * session_tree;
+} lbttcp_transport_conv_data_t;
+
+static const address lbttcp_null_address = ADDRESS_INIT_NONE;
+
+lbttcp_transport_t * lbttcp_transport_find(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame)
+{
+ lbttcp_transport_t * entry = NULL;
+ conversation_t * conv = NULL;
+ lbttcp_transport_conv_data_t * conv_data = NULL;
+
+ conv = find_conversation(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ if (conv != NULL)
+ {
+ conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
+ if (conv_data != NULL)
+ {
+ entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id);
+ }
+ }
+ return (entry);
+}
+
+static lbttcp_transport_t * lbttcp_transport_create(const address * source_address, guint16 source_port, guint32 session_id)
+{
+ lbttcp_transport_t * transport = NULL;
+
+ transport = wmem_new(wmem_file_scope(), lbttcp_transport_t);
+ copy_address_wmem(wmem_file_scope(), &(transport->source_address), source_address);
+ transport->source_port = source_port;
+ transport->session_id = session_id;
+ transport->channel = lbm_channel_assign(LBM_CHANNEL_TRANSPORT_LBTTCP);
+ transport->next_client_id = 1;
+ transport->client_list = wmem_list_new(wmem_file_scope());
+ return (transport);
+}
+
+lbttcp_transport_t * lbttcp_transport_add(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame)
+{
+ lbttcp_transport_t * entry = NULL;
+ conversation_t * conv = NULL;
+ lbttcp_transport_conv_data_t * conv_data = NULL;
+
+ conv = find_conversation(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ if (conv == NULL)
+ {
+ conv = conversation_new(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ }
+ conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
+ if (conv_data == NULL)
+ {
+ conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t);
+ conv_data->frame_tree = wmem_tree_new(wmem_file_scope());
+ conv_data->session_tree = wmem_tree_new(wmem_file_scope());
+ conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data);
+ }
+ entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id);
+ if (entry != NULL)
+ {
+ return (entry);
+ }
+ entry = lbttcp_transport_create(source_address, source_port, session_id);
+ wmem_tree_insert32(conv_data->session_tree, session_id, (void *) entry);
+ wmem_tree_insert32(conv_data->frame_tree, frame, (void *) entry);
+ return (entry);
+}
+
+static lbttcp_client_transport_t * lbttcp_client_transport_find(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame)
+{
+ lbttcp_client_transport_t * entry = NULL;
+ conversation_t * client_conv = NULL;
+
+ if (transport == NULL)
+ {
+ return (NULL);
+ }
+ client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_TCP, transport->source_port, receiver_port, 0);
+ if (client_conv != NULL)
+ {
+ wmem_tree_t * session_tree = NULL;
+
+ session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp);
+ if (session_tree != NULL)
+ {
+ entry = (lbttcp_client_transport_t *) wmem_tree_lookup32(session_tree, transport->session_id);
+ }
+ }
+ return (entry);
+}
+
+static lbttcp_client_transport_t * lbttcp_client_transport_add(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame)
+{
+ lbttcp_client_transport_t * entry;
+ conversation_t * client_conv = NULL;
+ wmem_tree_t * session_tree = NULL;
+
+ if (transport == NULL)
+ {
+ return (NULL);
+ }
+ entry = lbttcp_client_transport_find(transport, receiver_address, receiver_port, frame);
+ if (entry != NULL)
+ {
+ return (entry);
+ }
+ entry = wmem_new(wmem_file_scope(), lbttcp_client_transport_t);
+ copy_address_wmem(wmem_file_scope(), &(entry->receiver_address), receiver_address);
+ entry->receiver_port = receiver_port;
+ entry->id = transport->next_client_id++;
+
+ /* See if a conversation for this address/port pair exists. */
+ client_conv = find_conversation(frame, &(transport->source_address), receiver_address, CONVERSATION_TCP, transport->source_port, receiver_port, 0);
+ if (client_conv == NULL)
+ {
+ client_conv = conversation_new(frame, &(transport->source_address), receiver_address, CONVERSATION_TCP, transport->source_port, receiver_port, 0);
+ session_tree = wmem_tree_new(wmem_file_scope());
+ conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree);
+ }
+ session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp);
+ if (session_tree == NULL)
+ {
+ session_tree = wmem_tree_new(wmem_file_scope());
+ conversation_add_proto_data(client_conv, proto_lbttcp, (void *) session_tree);
+ }
+ wmem_tree_insert32(session_tree, transport->session_id, (void *) entry);
+
+ /* Add this client to the transport. */
+ wmem_list_append(transport->client_list, (void *) entry);
+ return (entry);
+}
+
+char * lbttcp_transport_source_string(const address * source_address, guint16 source_port, guint32 session_id)
+{
+ char * bufptr = NULL;
+
+ if (session_id == 0)
+ {
+ bufptr = wmem_strdup_printf(wmem_file_scope(), "TCP:%s:%" PRIu16, address_to_str(wmem_packet_scope(), source_address), source_port);
+ }
+ else
+ {
+ bufptr = wmem_strdup_printf(wmem_file_scope(), "TCP:%s:%" PRIu16 ":%08x", address_to_str(wmem_packet_scope(), source_address), source_port, session_id);
+ }
+ return (bufptr);
+}
+
+gboolean lbttcp_transport_sid_find(const address * source_address, guint16 source_port, guint32 frame, guint32 * session_id)
+{
+ conversation_t * conv = NULL;
+ lbttcp_transport_conv_data_t * conv_data = NULL;
+ lbttcp_transport_t * transport = NULL;
+
+ conv = find_conversation(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ if (conv == NULL)
+ {
+ return (FALSE);
+ }
+ conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
+ if (conv_data == NULL)
+ {
+ return (FALSE);
+ }
+ if (conv_data->frame_tree == NULL)
+ {
+ return (FALSE);
+ }
+ transport = (lbttcp_transport_t *)wmem_tree_lookup32_le(conv_data->frame_tree, frame);
+ if (transport == NULL)
+ {
+ return (FALSE);
+ }
+ *session_id = transport->session_id;
+ return (TRUE);
+}
+
+void lbttcp_transport_sid_add(const address * source_address, guint16 source_port, guint32 frame, guint32 session_id)
+{
+ conversation_t * conv = NULL;
+ lbttcp_transport_conv_data_t * conv_data = NULL;
+ lbttcp_transport_t * transport = NULL;
+
+ conv = find_conversation(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ if (conv == NULL)
+ {
+ conv = conversation_new(frame, source_address, &lbttcp_null_address, CONVERSATION_TCP, source_port, 0, 0);
+ }
+ conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp);
+ if (conv_data == NULL)
+ {
+ conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t);
+ conv_data->frame_tree = wmem_tree_new(wmem_file_scope());
+ conv_data->session_tree = wmem_tree_new(wmem_file_scope());
+ conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data);
+ }
+ /* Lookup by frame */
+ transport = (lbttcp_transport_t *) wmem_tree_lookup32_le(conv_data->frame_tree, frame);
+ if (transport != NULL)
+ {
+ if (transport->session_id != session_id)
+ {
+ transport = NULL;
+ }
+ }
+ if (transport == NULL)
+ {
+ transport = lbttcp_transport_create(source_address, source_port, session_id);
+ wmem_tree_insert32(conv_data->session_tree, session_id, (void *) transport);
+ wmem_tree_insert32(conv_data->frame_tree, frame, (void *) transport);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+/* Preferences. */
+/*----------------------------------------------------------------------------*/
+
+/* Preferences default values. */
+#define LBTTCP_DEFAULT_SOURCE_PORT_LOW 14371
+#define LBTTCP_DEFAULT_SOURCE_PORT_HIGH 14390
+#define LBTTCP_DEFAULT_REQUEST_PORT_LOW 14391
+#define LBTTCP_DEFAULT_REQUEST_PORT_HIGH 14395
+#define LBTTCP_DEFAULT_STORE_PORT_LOW 0
+#define LBTTCP_DEFAULT_STORE_PORT_HIGH 0
+
+/* Global preferences variables (altered by the preferences dialog). */
+static guint32 global_lbttcp_source_port_low = LBTTCP_DEFAULT_SOURCE_PORT_LOW;
+static guint32 global_lbttcp_source_port_high = LBTTCP_DEFAULT_SOURCE_PORT_HIGH;
+static guint32 global_lbttcp_request_port_low = LBTTCP_DEFAULT_REQUEST_PORT_LOW;
+static guint32 global_lbttcp_request_port_high = LBTTCP_DEFAULT_REQUEST_PORT_HIGH;
+static guint32 global_lbttcp_store_port_low = LBTTCP_DEFAULT_STORE_PORT_LOW;
+static guint32 global_lbttcp_store_port_high = LBTTCP_DEFAULT_STORE_PORT_HIGH;
+static gboolean global_lbttcp_use_tag = FALSE;
+
+/* Local preferences variables (used by the dissector). */
+static guint32 lbttcp_source_port_low = LBTTCP_DEFAULT_SOURCE_PORT_LOW;
+static guint32 lbttcp_source_port_high = LBTTCP_DEFAULT_SOURCE_PORT_HIGH;
+static guint32 lbttcp_request_port_low = LBTTCP_DEFAULT_REQUEST_PORT_LOW;
+static guint32 lbttcp_request_port_high = LBTTCP_DEFAULT_REQUEST_PORT_HIGH;
+static guint32 lbttcp_store_port_low = LBTTCP_DEFAULT_STORE_PORT_LOW;
+static guint32 lbttcp_store_port_high = LBTTCP_DEFAULT_STORE_PORT_HIGH;
+static gboolean lbttcp_use_tag = FALSE;
+
+/* Tag definitions. */
+typedef struct
+{
+ char * name;
+ guint32 source_port_low;
+ guint32 source_port_high;
+ guint32 request_port_low;
+ guint32 request_port_high;
+ guint32 store_port_low;
+ guint32 store_port_high;
+} lbttcp_tag_entry_t;
+
+static lbttcp_tag_entry_t * lbttcp_tag_entry = NULL;
+static guint lbttcp_tag_count = 0;
+
+UAT_CSTRING_CB_DEF(lbttcp_tag, name, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, source_port_low, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, source_port_high, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, request_port_low, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, request_port_high, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, store_port_low, lbttcp_tag_entry_t)
+UAT_DEC_CB_DEF(lbttcp_tag, store_port_high, lbttcp_tag_entry_t)
+static uat_field_t lbttcp_tag_array[] =
+{
+ UAT_FLD_CSTRING(lbttcp_tag, name, "Tag name", "Tag name"),
+ UAT_FLD_DEC(lbttcp_tag, source_port_low, "Source port low", "Source port low"),
+ UAT_FLD_DEC(lbttcp_tag, source_port_high, "Source port high", "Source port high"),
+ UAT_FLD_DEC(lbttcp_tag, request_port_low, "Request port low", "Request port low"),
+ UAT_FLD_DEC(lbttcp_tag, request_port_high, "Request port high", "Request port high"),
+ UAT_FLD_DEC(lbttcp_tag, store_port_low, "Store port low", "Store port low"),
+ UAT_FLD_DEC(lbttcp_tag, store_port_high, "Store port high", "Store port high"),
+ UAT_END_FIELDS
+};
+
+/*----------------------------------------------------------------------------*/
+/* UAT callback functions. */
+/*----------------------------------------------------------------------------*/
+static bool lbttcp_tag_update_cb(void * record, char * * error_string)
+{
+ lbttcp_tag_entry_t * tag = (lbttcp_tag_entry_t *)record;
+
+ if (tag->name == NULL)
+ {
+ *error_string = g_strdup("Tag name can't be empty");
+ return FALSE;
+ }
+ else
+ {
+ g_strstrip(tag->name);
+ if (tag->name[0] == 0)
+ {
+ *error_string = g_strdup("Tag name can't be empty");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void * lbttcp_tag_copy_cb(void * destination, const void * source, size_t length _U_)
+{
+ const lbttcp_tag_entry_t * src = (const lbttcp_tag_entry_t *)source;
+ lbttcp_tag_entry_t * dest = (lbttcp_tag_entry_t *)destination;
+
+ dest->name = g_strdup(src->name);
+ dest->source_port_low = src->source_port_low;
+ dest->source_port_high = src->source_port_high;
+ dest->request_port_low = src->request_port_low;
+ dest->request_port_high = src->request_port_high;
+ dest->store_port_low = src->store_port_low;
+ dest->store_port_high = src->store_port_high;
+ return (dest);
+}
+
+static void lbttcp_tag_free_cb(void * record)
+{
+ lbttcp_tag_entry_t * tag = (lbttcp_tag_entry_t *)record;
+
+ if (tag->name != NULL)
+ {
+ g_free(tag->name);
+ tag->name = NULL;
+ }
+}
+
+static const lbttcp_tag_entry_t * lbttcp_tag_locate(packet_info * pinfo)
+{
+ guint idx;
+ const lbttcp_tag_entry_t * tag = NULL;
+
+ if (!lbttcp_use_tag)
+ {
+ return (NULL);
+ }
+
+ for (idx = 0; idx < lbttcp_tag_count; ++idx)
+ {
+ tag = &(lbttcp_tag_entry[idx]);
+ if (((pinfo->srcport >= tag->source_port_low) && (pinfo->srcport <= tag->source_port_high))
+ || ((pinfo->destport >= tag->source_port_low) && (pinfo->destport <= tag->source_port_high))
+ || ((pinfo->srcport >= tag->request_port_low) && (pinfo->srcport <= tag->request_port_high))
+ || ((pinfo->destport >= tag->request_port_low) && (pinfo->destport <= tag->request_port_high))
+ || ((pinfo->srcport >= tag->store_port_low) && (pinfo->srcport <= tag->store_port_high))
+ || ((pinfo->destport >= tag->store_port_low) && (pinfo->destport <= tag->store_port_high)))
+ {
+ return (tag);
+ }
+ }
+ return (NULL);
+}
+
+static char * lbttcp_tag_find(packet_info * pinfo)
+{
+ const lbttcp_tag_entry_t * tag = NULL;
+
+ if (!lbttcp_use_tag)
+ {
+ return (NULL);
+ }
+
+ tag = lbttcp_tag_locate(pinfo);
+ if (tag != NULL)
+ {
+ return tag->name;
+ }
+ return (NULL);
+}
+
+/*----------------------------------------------------------------------------*/
+/* Handles of all types. */
+/*----------------------------------------------------------------------------*/
+
+/* Dissector tree handles */
+static gint ett_lbttcp = -1;
+static gint ett_lbttcp_channel = -1;
+
+/* Dissector field handles */
+static int hf_lbttcp_tag = -1;
+static int hf_lbttcp_channel = -1;
+static int hf_lbttcp_channel_id = -1;
+static int hf_lbttcp_channel_client = -1;
+
+static gboolean lbttcp_packet_is_transport_source(packet_info * pinfo, const lbttcp_tag_entry_t * tag)
+{
+ gboolean is_transport_source_packet = FALSE;
+
+ if (tag == NULL)
+ {
+ if ((pinfo->srcport >= lbttcp_source_port_low) && (pinfo->srcport <= lbttcp_source_port_high))
+ {
+ is_transport_source_packet = TRUE;
+ }
+ }
+ else
+ {
+ if ((pinfo->srcport >= tag->source_port_low) && (pinfo->srcport <= tag->source_port_high))
+ {
+ is_transport_source_packet = TRUE;
+ }
+ }
+ return (is_transport_source_packet);
+}
+
+static gboolean lbttcp_packet_is_transport_client(packet_info * pinfo, const lbttcp_tag_entry_t * tag)
+{
+ gboolean is_transport_client_packet = FALSE;
+
+ if (tag == NULL)
+ {
+ if ((pinfo->destport >= lbttcp_source_port_low) && (pinfo->destport <= lbttcp_source_port_high))
+ {
+ is_transport_client_packet = TRUE;
+ }
+ }
+ else
+ {
+ if ((pinfo->destport >= tag->source_port_low) && (pinfo->destport <= tag->source_port_high))
+ {
+ is_transport_client_packet = TRUE;
+ }
+ }
+ return (is_transport_client_packet);
+}
+
+static guint get_lbttcp_pdu_length(packet_info * pinfo _U_, tvbuff_t * tvb,
+ int offset, void *data _U_)
+{
+ return lbmc_get_message_length(tvb, offset);
+}
+
+static int dissect_lbttcp_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * dissector_data _U_)
+{
+ proto_tree * lbttcp_tree = NULL;
+ proto_item * ti = NULL;
+ char * tag_name = NULL;
+ int len_dissected;
+ const lbttcp_tag_entry_t * tag = NULL;
+ guint64 channel = LBM_CHANNEL_NO_CHANNEL;
+ guint32 client_id = 0;
+ gboolean from_source = FALSE;
+ gboolean transport_packet = FALSE;
+
+ if (lbttcp_use_tag)
+ {
+ tag = lbttcp_tag_locate(pinfo);
+ tag_name = lbttcp_tag_find(pinfo);
+ }
+ if (tag_name != NULL)
+ {
+ ti = proto_tree_add_protocol_format(tree, proto_lbttcp, tvb, 0, -1, "LBT-TCP Protocol (Tag: %s)", tag_name);
+ }
+ else
+ {
+ ti = proto_tree_add_protocol_format(tree, proto_lbttcp, tvb, 0, -1, "LBT-TCP Protocol");
+ }
+ lbttcp_tree = proto_item_add_subtree(ti, ett_lbttcp);
+ if (tag_name != NULL)
+ {
+ proto_item * item = NULL;
+
+ item = proto_tree_add_string(lbttcp_tree, hf_lbttcp_tag, tvb, 0, 0, tag_name);
+ proto_item_set_generated(item);
+ }
+ if (lbttcp_packet_is_transport_source(pinfo, tag))
+ {
+ from_source = TRUE;
+ transport_packet = TRUE;
+ }
+ else if (lbttcp_packet_is_transport_client(pinfo, tag))
+ {
+ from_source = FALSE;
+ transport_packet = TRUE;
+ }
+ if (transport_packet)
+ {
+ address source_address;
+ address client_address;
+ guint16 srcport;
+ guint16 clntport;
+ guint32 sid = 0;
+ lbttcp_transport_t * transport = NULL;
+ lbttcp_client_transport_t * client = NULL;
+
+ if (from_source)
+ {
+ copy_address_shallow(&source_address, &(pinfo->src));
+ srcport = pinfo->srcport;
+ copy_address_shallow(&client_address, &(pinfo->dst));
+ clntport = pinfo->destport;
+ }
+ else
+ {
+ copy_address_shallow(&source_address, &(pinfo->dst));
+ srcport = pinfo->destport;
+ copy_address_shallow(&client_address, &(pinfo->src));
+ clntport = pinfo->srcport;
+ }
+ /* See if we have a matching transport with no session ID. */
+ transport = lbttcp_transport_find(&source_address, srcport, sid, pinfo->num);
+ if (transport == NULL)
+ {
+ /* See if we know about a SID */
+ if (lbttcp_transport_sid_find(&source_address, srcport, pinfo->num, &sid))
+ {
+ transport = lbttcp_transport_find(&source_address, srcport, sid, pinfo->num);
+ }
+ }
+ if (transport != NULL)
+ {
+ channel = transport->channel;
+ /* See if we already know about this client */
+ client = lbttcp_client_transport_find(transport, &client_address, clntport, pinfo->num);
+ if (client == NULL)
+ {
+ /* No - add it. */
+ client = lbttcp_client_transport_add(transport, &client_address, clntport, pinfo->num);
+ }
+ if (client != NULL)
+ {
+ client_id = client->id;
+ }
+ }
+ else
+ {
+ if (PINFO_FD_VISITED(pinfo))
+ {
+ /* No TIR and no session ID seen, so create the transport */
+ transport = lbttcp_transport_add(&source_address, srcport, 0, pinfo->num);
+ if (transport != NULL)
+ {
+ channel = transport->channel;
+ client = lbttcp_client_transport_add(transport, &client_address, clntport, pinfo->num);
+ if (client != NULL)
+ {
+ client_id = client->id;
+ }
+ }
+ }
+ else
+ {
+ /* Defer determining the channel. */
+ if (from_source)
+ {
+ channel = lbm_channel_assign_unknown_transport_source_lbttcp();
+ }
+ else
+ {
+ channel = lbm_channel_assign_unknown_transport_client_lbttcp();
+ }
+ }
+ }
+ }
+ else
+ {
+ channel = lbm_channel_assign_unknown_stream_tcp();
+ }
+ if (lbm_channel_is_known(channel))
+ {
+ proto_item * channel_item = NULL;
+ proto_tree * channel_tree = NULL;
+
+ channel_item = proto_tree_add_item(lbttcp_tree, hf_lbttcp_channel, tvb, 0, 0, ENC_NA);
+ proto_item_set_generated(channel_item);
+ channel_tree = proto_item_add_subtree(channel_item, ett_lbttcp_channel);
+ channel_item = proto_tree_add_uint64(channel_tree, hf_lbttcp_channel_id, tvb, 0, 0, channel);
+ proto_item_set_generated(channel_item);
+ channel_item = proto_tree_add_uint(channel_tree, hf_lbttcp_channel_client, tvb, 0, 0, client_id);
+ proto_item_set_generated(channel_item);
+ }
+ len_dissected = lbmc_dissect_lbmc_packet(tvb, 0, pinfo, tree, tag_name, channel);
+ return (len_dissected);
+}
+
+/*
+ * dissect_lbttcp_real - The "common" dissection for LBT-TCP
+ */
+static int dissect_lbttcp_real(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
+{
+ char * tag_name = NULL;
+
+ col_add_str(pinfo->cinfo, COL_PROTOCOL, "LBT-TCP");
+ col_clear(pinfo->cinfo, COL_INFO);
+ if (lbttcp_use_tag)
+ {
+ tag_name = lbttcp_tag_find(pinfo);
+ }
+ if (tag_name != NULL)
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "[Tag: %s]", tag_name);
+ }
+ col_set_fence(pinfo->cinfo, COL_INFO);
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, lbmc_get_minimum_length(), /* Need at least the msglen */
+ get_lbttcp_pdu_length, dissect_lbttcp_pdu, NULL);
+
+ return tvb_captured_length(tvb);
+}
+
+/*
+ * dissect_lbttcp - The dissector for LBT-TCP
+ */
+static int dissect_lbttcp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
+{
+ if (!lbmc_test_lbmc_header(tvb, 0))
+ return 0;
+
+ return dissect_lbttcp_real(tvb, pinfo, tree, data);
+}
+
+static gboolean test_lbttcp_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data)
+{
+ /* Destination address must be IPV4 and 4 bytes in length. */
+ if ((pinfo->dst.type != AT_IPv4) || (pinfo->dst.len != 4))
+ {
+ return (FALSE);
+ }
+
+ if (lbttcp_use_tag)
+ {
+ if (lbttcp_tag_find(pinfo) != NULL)
+ {
+ dissect_lbttcp_real(tvb, pinfo, tree, data);
+ return (TRUE);
+ }
+ else
+ {
+ return (FALSE);
+ }
+ }
+
+ /*
+ Source port or destination port must be in the source port range, or destination port must be in
+ the request port range, or either port in the UME store port range.
+ */
+ if (!(((pinfo->srcport >= lbttcp_source_port_low) && (pinfo->srcport <= lbttcp_source_port_high))
+ || ((pinfo->destport >= lbttcp_source_port_low) && (pinfo->destport <= lbttcp_source_port_high))
+ || ((pinfo->srcport >= lbttcp_request_port_low) && (pinfo->srcport <= lbttcp_request_port_high))
+ || ((pinfo->destport >= lbttcp_request_port_low) && (pinfo->destport <= lbttcp_request_port_high))
+ || ((pinfo->srcport >= lbttcp_store_port_low) && (pinfo->srcport <= lbttcp_store_port_high))
+ || ((pinfo->destport >= lbttcp_store_port_low) && (pinfo->destport <= lbttcp_store_port_high))))
+ {
+ return (FALSE);
+ }
+
+ if (!lbmc_test_lbmc_header(tvb, 0))
+ return FALSE;
+
+ /* One of ours. Probably. */
+ dissect_lbttcp_real(tvb, pinfo, tree, data);
+ return (TRUE);
+}
+
+/* Register all the bits needed with the filtering engine */
+void proto_register_lbttcp(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_lbttcp_tag,
+ { "Tag", "lbttcp.tag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
+ { &hf_lbttcp_channel,
+ { "Channel", "lbttcp.channel", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
+ { &hf_lbttcp_channel_id,
+ { "Channel ID", "lbttcp.channel.channel", FT_UINT64, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL } },
+ { &hf_lbttcp_channel_client,
+ { "Channel Client", "lbttcp.channel.client", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+ };
+ static gint * ett[] =
+ {
+ &ett_lbttcp,
+ &ett_lbttcp_channel
+ };
+ module_t * lbttcp_module;
+ uat_t * tag_uat;
+
+ proto_lbttcp = proto_register_protocol("LBT TCP Protocol", "LBT-TCP", "lbttcp");
+
+ proto_register_field_array(proto_lbttcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ lbttcp_dissector_handle = register_dissector("lbttcp", dissect_lbttcp, proto_lbttcp);
+
+ lbttcp_module = prefs_register_protocol_subtree("29West", proto_lbttcp, proto_reg_handoff_lbttcp);
+ prefs_register_uint_preference(lbttcp_module,
+ "source_port_low",
+ "Source port range low (default " MAKESTRING(LBTTCP_DEFAULT_SOURCE_PORT_LOW)")",
+ "Set the low end of the LBT-TCP source TCP port range (context transport_tcp_port_low)",
+ 10,
+ &global_lbttcp_source_port_low);
+
+ prefs_register_uint_preference(lbttcp_module,
+ "source_port_high",
+ "Source port range high (default " MAKESTRING(LBTTCP_DEFAULT_SOURCE_PORT_HIGH)")",
+ "Set the high end of the LBT-TCP source TCP port range (context transport_tcp_port_high)",
+ 10,
+ &global_lbttcp_source_port_high);
+
+ prefs_register_uint_preference(lbttcp_module,
+ "request_port_low",
+ "Request port range low (default " MAKESTRING(LBTTCP_DEFAULT_REQUEST_PORT_LOW)")",
+ "Set the low end of the LBT-TCP request TCP port range (context request_tcp_port_low)",
+ 10,
+ &global_lbttcp_request_port_low);
+
+ prefs_register_uint_preference(lbttcp_module,
+ "request_port_high",
+ "Request port range high (default " MAKESTRING(LBTTCP_DEFAULT_REQUEST_PORT_HIGH)")",
+ "Set the high end of the LBT-TCP request TCP port range (context request_tcp_port_high)",
+ 10,
+ &global_lbttcp_request_port_high);
+
+ prefs_register_uint_preference(lbttcp_module,
+ "store_port_low",
+ "UME Store port range low (default " MAKESTRING(LBTTCP_DEFAULT_STORE_PORT_LOW)")",
+ "Set the low end of the LBT-TCP UME Store TCP port range",
+ 10,
+ &global_lbttcp_store_port_low);
+
+ prefs_register_uint_preference(lbttcp_module,
+ "store_port_high",
+ "UME Store port range high (default " MAKESTRING(LBTTCP_DEFAULT_STORE_PORT_HIGH)")",
+ "Set the high end of the LBT-TCP UME Store TCP port range",
+ 10,
+ &global_lbttcp_store_port_high);
+
+ prefs_register_bool_preference(lbttcp_module,
+ "use_lbttcp_domain",
+ "Use LBT-TCP tag table",
+ "Use table of LBT-TCP tags to decode the packet instead of above values",
+ &global_lbttcp_use_tag);
+ tag_uat = uat_new("LBT-TCP tag definitions",
+ sizeof(lbttcp_tag_entry_t),
+ "lbttcp_domains",
+ TRUE,
+ (void * *)&lbttcp_tag_entry,
+ &lbttcp_tag_count,
+ UAT_AFFECTS_DISSECTION,
+ NULL,
+ lbttcp_tag_copy_cb,
+ lbttcp_tag_update_cb,
+ lbttcp_tag_free_cb,
+ NULL,
+ NULL,
+ lbttcp_tag_array);
+ prefs_register_uat_preference(lbttcp_module,
+ "tnw_lbttcp_tags",
+ "LBT-TCP Tags",
+ "A table to define LBT-TCP tags",
+ tag_uat);
+}
+
+/* The registration hand-off routine */
+void proto_reg_handoff_lbttcp(void)
+{
+ static gboolean already_registered = FALSE;
+
+ if (!already_registered)
+ {
+ dissector_add_for_decode_as_with_preference("tcp.port", lbttcp_dissector_handle);
+ heur_dissector_add("tcp", test_lbttcp_packet, "LBT over TCP", "lbttcp_tcp", proto_lbttcp, HEURISTIC_ENABLE);
+ }
+
+ /* Make sure the source port low is <= the source port high. If not, don't change them. */
+ if (global_lbttcp_source_port_low <= global_lbttcp_source_port_high)
+ {
+ lbttcp_source_port_low = global_lbttcp_source_port_low;
+ lbttcp_source_port_high = global_lbttcp_source_port_high;
+ }
+
+ /* Make sure the request port low is <= the request port high. If not, don't change them. */
+ if (global_lbttcp_request_port_low <= global_lbttcp_request_port_high)
+ {
+ lbttcp_request_port_low = global_lbttcp_request_port_low;
+ lbttcp_request_port_high = global_lbttcp_request_port_high;
+ }
+
+ /* Make sure the store port low is <= the store port high. If not, don't change them. */
+ if (global_lbttcp_store_port_low <= global_lbttcp_store_port_high)
+ {
+ lbttcp_store_port_low = global_lbttcp_store_port_low;
+ lbttcp_store_port_high = global_lbttcp_store_port_high;
+ }
+
+ lbttcp_use_tag = global_lbttcp_use_tag;
+
+ already_registered = TRUE;
+}
+
+/*
+ * 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:
+ */