diff options
Diffstat (limited to 'epan/dissectors/packet-lbttcp.c')
-rw-r--r-- | epan/dissectors/packet-lbttcp.c | 836 |
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: + */ |