aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorPaul Offord <paul.offord@advance7.com>2017-11-20 09:49:38 +0000
committerMichael Mann <mmann78@netscape.net>2017-11-22 14:37:01 +0000
commit36372a2465c94784240ba8c38b53b4eedb234868 (patch)
tree9a832c902b3183606286508128e2ca5124aecb8b /plugins
parent871f75ce85b7c3d0c58e05e90d34791042a8d5b8 (diff)
TRANSUM: Fix DNS-related bug and improve performance
These changes significantly improve the speed and accuracy of TRANSUM. I have removed the concept of rrpd status as it wasn't being used in any significant way and created unnecessary code. The find_latest_rrpd(...) function was becoming very complex which made it difficult to optimise performance for certain protocols. To overcome this, I have introduced an equivalent function for each protocol e.g. find_latest_rrpd_smb2(...). each of these new functions has a loop that steps through the rrpd_list. I could have placed this loop one level up in the nested call and so had one loop in the code that calls the new function. However, I have found that this area is the prime cause of delays in TRANSUM execution and so I want to avoid calling these new functions with each step through the rrpd_list. Finally, I have added code to improve the handling of retransmissions. Bug: 14210 Change-Id: I038097f22a45ee74173aad1ae5732347f769b9bd Reviewed-on: https://code.wireshark.org/review/24506 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/transum/decoders.c37
-rw-r--r--plugins/transum/packet-transum.c694
-rw-r--r--plugins/transum/packet-transum.h22
-rw-r--r--plugins/transum/preferences.h1
4 files changed, 446 insertions, 308 deletions
diff --git a/plugins/transum/decoders.c b/plugins/transum/decoders.c
index 77d647d54c..e47539e5ac 100644
--- a/plugins/transum/decoders.c
+++ b/plugins/transum/decoders.c
@@ -44,13 +44,11 @@ int decode_syn(packet_info *pinfo _U_, proto_tree *tree _U_, PKT_INFO* pkt_info)
else
{
pkt_info->rrpd.c2s = TRUE;
- pkt_info->rrpd.state = RRPD_STATE_4;
add_detected_tcp_svc(pkt_info->dstport);
}
- pkt_info->rrpd.session_id = 1;
- pkt_info->rrpd.msg_id = 1;
- pkt_info->rrpd.suffix = 1;
+ pkt_info->rrpd.session_id = 1; /* Fake session ID */
+ pkt_info->rrpd.msg_id = 1; /* Fake message ID */
pkt_info->rrpd.decode_based = TRUE;
pkt_info->rrpd.calculation = RTE_CALC_SYN;
pkt_info->pkt_of_interest = TRUE;
@@ -132,7 +130,6 @@ int decode_dcerpc(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info)
wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport), GUINT_TO_POINTER(RTE_CALC_DCERPC)); /* make sure we have this DCE-RPC service port set */
}
- pkt_info->rrpd.suffix = 1;
pkt_info->rrpd.decode_based = TRUE;
pkt_info->rrpd.calculation = RTE_CALC_DCERPC;
pkt_info->pkt_of_interest = TRUE;
@@ -169,7 +166,6 @@ int decode_smb(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info, PKT
/* Default in case we don't have header information */
pkt_info->rrpd.session_id = 0;
pkt_info->rrpd.msg_id = 0;
- pkt_info->rrpd.suffix = 1;
pkt_info->rrpd.decode_based = TRUE;
pkt_info->rrpd.calculation = RTE_CALC_SMB2;
pkt_info->pkt_of_interest = TRUE;
@@ -187,7 +183,6 @@ int decode_smb(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info, PKT
subpackets[i].rrpd.session_id = ses_id[i];
subpackets[i].rrpd.msg_id = msg_id[i];
- subpackets[i].rrpd.suffix = 1;
subpackets[i].rrpd.decode_based = TRUE;
subpackets[i].rrpd.calculation = RTE_CALC_SMB2;
@@ -244,18 +239,28 @@ int decode_gtcp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info)
pkt_info->tcp_keep_alive = field_bool[0];
}
- if (((wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL) ||
- (wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport)) != NULL)) &&
- (pkt_info->len > 0))
+ /* we use the SSL Content Type to detect SSL Alerts */
+ if (!extract_uint(tree, hf_of_interest[HF_INTEREST_SSL_CONTENT_TYPE].hf, field_uint, &field_value_count))
+ {
+ if (field_value_count)
+ pkt_info->ssl_content_type = field_uint[0];
+ else
+ pkt_info->ssl_content_type = 0;
+ }
+
+ if (wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL ||
+ wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport)) != NULL)
{
if (wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL)
pkt_info->rrpd.c2s = TRUE;
- pkt_info->rrpd.session_id = 1;
- pkt_info->rrpd.msg_id = 1;
+ pkt_info->rrpd.is_retrans = pkt_info->tcp_retran;
+ pkt_info->rrpd.session_id = 0;
+ pkt_info->rrpd.msg_id = 0;
pkt_info->rrpd.calculation = RTE_CALC_GTCP;
pkt_info->rrpd.decode_based = FALSE;
- pkt_info->pkt_of_interest = TRUE;
+ if (pkt_info->len > 0)
+ pkt_info->pkt_of_interest = TRUE;
return 1;
}
@@ -275,7 +280,6 @@ int decode_dns(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info)
}
pkt_info->rrpd.session_id = 1;
- pkt_info->rrpd.suffix = 1; /* need to do something tricky here as dns.id gets reused */
pkt_info->rrpd.decode_based = TRUE;
pkt_info->rrpd.calculation = RTE_CALC_DNS;
pkt_info->pkt_of_interest = TRUE;
@@ -308,9 +312,8 @@ int decode_gudp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info)
if (wmem_map_lookup(preferences.udp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL)
pkt_info->rrpd.c2s = TRUE;
- pkt_info->rrpd.session_id = 1;
- pkt_info->rrpd.msg_id = 1;
- pkt_info->rrpd.suffix = 1;
+ pkt_info->rrpd.session_id = 0;
+ pkt_info->rrpd.msg_id = 0;
pkt_info->rrpd.decode_based = FALSE;
pkt_info->rrpd.calculation = RTE_CALC_GUDP;
pkt_info->pkt_of_interest = TRUE;
diff --git a/plugins/transum/packet-transum.c b/plugins/transum/packet-transum.c
index 0d08d722dc..7c4e0065ab 100644
--- a/plugins/transum/packet-transum.c
+++ b/plugins/transum/packet-transum.c
@@ -48,13 +48,6 @@ static dissector_handle_t transum_handle;
#define RTE_TIME_MSEC 1000
#define RTE_TIME_USEC 1000000
-#define CONTINUE_PROCESSING TRUE
-
-#define RRPD_REQUIRES_SUFFIX TRUE
-#define RRPD_NEEDS_NO_SUFFIX FALSE;
-
-#define SMB2_CMD_SESSION_SETUP 1
-
/* The following are the field ids for the protocol values used by TRANSUM.
Make sure they line up with ehf_of_interest order */
HF_OF_INTEREST_INFO hf_of_interest[HF_INTEREST_END_OF_LIST] = {
@@ -78,6 +71,8 @@ HF_OF_INTEREST_INFO hf_of_interest[HF_INTEREST_END_OF_LIST] = {
{ -1, "udp.stream" },
{ -1, "udp.length" },
+ { -1, "ssl.record.content_type" },
+
{ -1, "tds.type" },
{ -1, "tds.length" },
@@ -107,6 +102,8 @@ static wmem_map_t *detected_tcp_svc; /* this array is used to track services de
static wmem_map_t *dcerpc_req_pkt_type; /* used to indicate if a DCE-RPC pkt_type is a request */
+static wmem_map_t *dcerpc_streams = NULL; /* used to record TCP stream numbers that are carrying DCE-RPC data */
+
/*
This array contains calls and returns that have no TRUE context_id
This is needed to overcome an apparent bug in Wireshark where
@@ -115,11 +112,6 @@ in a message header
*/
static wmem_map_t *dcerpc_context_zero;
-#if 0
-/* rrpd-related globals */
-guint32 rrpd_suffix = 0;
-#endif
-
/*
The rrpd_list holds information about all of the APDU Request-Response Pairs seen in the trace.
*/
@@ -134,13 +126,19 @@ static wmem_map_t *output_rrpd;
/*
The temp_rsp_rrpd_list holds RRPDs for APDUs where we have not yet seen the header information and so we can't
- fully qualify the identification of the RRPD (the identification being ip_proto:stream_no:session_id:msg_id:suffix).
+ fully qualify the identification of the RRPD (the identification being ip_proto:stream_no:session_id:msg_id).
This only occurs when a) we are using one of the decode_based calculations (such as SMB2), and b) when we have
TCP Reassembly enabled. Once we receive a header packet for an APDU we migrate the entry from this array to the
main rrpd_list.
*/
static wmem_list_t *temp_rsp_rrpd_list = NULL; /* Reuse these for speed and efficient memory use - issue a warning if we run out */
+/* Optimisation data - the following is used for various optimisation measures */
+static int highest_tcp_stream_no;
+static int highest_udp_stream_no;
+wmem_map_t *tcp_stream_exceptions;
+
+
static gint ett_transum = -1;
static gint ett_transum_header = -1;
static gint ett_transum_data = -1;
@@ -160,6 +158,8 @@ static int hf_tsum_rsp_spread = -1;
static int hf_tsum_clip_filter = -1;
static int hf_tsum_calculation = -1;
static int hf_tsum_summary = -1;
+static int hf_tsum_req_search = -1;
+static int hf_tsum_rsp_search = -1;
static const enum_val_t capture_position_vals[] = {
{ "TRACE_CAP_CLIENT", "Client", TRACE_CAP_CLIENT },
@@ -204,6 +204,11 @@ static void init_dcerpc_data(void)
wmem_map_insert(dcerpc_context_zero, GUINT_TO_POINTER(15), GUINT_TO_POINTER(15));
}
+static void register_dcerpc_stream(guint32 stream_no)
+{
+ wmem_map_insert(dcerpc_streams, GUINT_TO_POINTER(stream_no), GUINT_TO_POINTER(1));
+}
+
/* This function should be called before any change to RTE data. */
static void null_output_rrpd_entries(RRPD *in_rrpd)
{
@@ -234,21 +239,6 @@ static RRPD* append_to_rrpd_list(RRPD *in_rrpd)
{
RRPD *next_rrpd = (RRPD*)wmem_memdup(wmem_file_scope(), in_rrpd, sizeof(RRPD));
- if (preferences.reassembly)
- {
- if (next_rrpd->msg_id)
- next_rrpd->state = RRPD_STATE_3;
- else
- next_rrpd->state = RRPD_STATE_1;
- }
- else
- {
- if (next_rrpd->msg_id)
- next_rrpd->state = RRPD_STATE_4;
- else
- next_rrpd->state = RRPD_STATE_2;
- }
-
update_output_rrpd(next_rrpd);
wmem_list_append(rrpd_list, next_rrpd);
@@ -256,233 +246,352 @@ static RRPD* append_to_rrpd_list(RRPD *in_rrpd)
return next_rrpd;
}
-/*
-This function finds the latest entry in the rrpd_list that matches the
-ip_proto, stream_no, session_id, msg_id and suffix values.
-
-An input state value of 0 means that we don't care about state.
-
-Returns the rrpd_list index value of the match or -1 if no match is found.
-*/
-static RRPD *find_latest_rrpd(RRPD *in_rrpd, int state)
+static RRPD *find_latest_rrpd_dcerpc(RRPD *in_rrpd)
{
- RRPD *rrpd_index = NULL, *rrpd;
+ RRPD *rrpd;
wmem_list_frame_t* i;
- /* If this is a SYN from C2S there is no point searching the list */
- if (in_rrpd->c2s && in_rrpd->calculation == RTE_CALC_SYN)
- return NULL;
-
for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
{
rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_DCERPC && rrpd->calculation != RTE_CALC_SYN)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- if (in_rrpd->decode_based)
+ /* if we can match on session_id and msg_id must be a retransmission of the last request packet or the response */
+ /* this logic works whether or not we are using reassembly */
+ if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id)
+ return rrpd;
+
+ /* If this is a retransmission, we assume it relates to this rrpd_list entry.
+ This is a bit of a kludge and not ideal but a compromise.*/
+ /* ToDo: look at using TCP sequence number to allocate a retransmission to the correct APDU */
+ if (in_rrpd->is_retrans)
+ return rrpd;
+
+ if (preferences.reassembly)
{
- /* If this is decode-based and we are checking for entries in RRPD_STATE_1 we need to match on ip_proto and stream_no alone. */
- if (state == RRPD_STATE_1)
+ if (in_rrpd->c2s)
{
- if (rrpd->session_id == 0 && rrpd->msg_id == 0 && rrpd->suffix == 1)
- {
- rrpd_index = rrpd;
- break;
- }
+ /* if the input rrpd is for c2s and the one we have found already has response information, then the
+ in_rrpd represents a new RR Pair. */
+ if (rrpd->rsp_first_frame)
+ return NULL;
+
+ /* If the current rrpd_list entry doesn't have a msg_id then we assume we are mid Request APDU and so we have a match. */
+ if (!rrpd->msg_id)
+ return rrpd;
}
-
- /* if this stream is decode_based we need to take into account the session_id, msg_id and suffix */
- if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id && rrpd->suffix == in_rrpd->suffix)
+ else /* The in_rrpd relates to a packet going s2c */
{
- if (state == RRPD_STATE_DONT_CARE || rrpd->state == state)
- {
- rrpd_index = rrpd;
- break;
- }
+ /* When reassembly is enabled, multi-packet response information is actually migrated from the temp_rsp_rrpd_list
+ to the rrpd_list and so we won't come through here. */
+ ;
}
}
- else
+ else /* we are not using reassembly */
{
- /* if this stream is not decode_based we don't need to take into account the session_id, msg_id and suffix */
- if (state == RRPD_STATE_DONT_CARE || rrpd->state == state)
+ if (in_rrpd->c2s)
{
- rrpd_index = rrpd;
- break;
+ if (in_rrpd->msg_id)
+ /* if we have a message id this is a new Request APDU */
+ return NULL;
+ else /* No msg_id */
+ {
+ return rrpd; /* add this packet to the matching stream */
+ }
+ }
+ else /* this packet is going s2c */
+ {
+ if (!in_rrpd->msg_id && rrpd->rsp_first_frame)
+ /* we need to add this frame to the response APDU of the most recent rrpd_list entry that has already had response packets */
+ return rrpd;
}
}
- }
- }
- return rrpd_index;
+ } /* this is the end of the 5-tuple check */
+
+ if (in_rrpd->c2s)
+ in_rrpd->req_search_total++;
+ else
+ in_rrpd->rsp_search_total++;
+ } /* end of the for loop */
+
+ return NULL;
}
-static void update_rrpd_list_entry(RRPD *match, RRPD *in_rrpd)
+static RRPD *find_latest_rrpd_dns(RRPD *in_rrpd)
{
- null_output_rrpd_entries(match);
+ RRPD *rrpd;
+ wmem_list_frame_t* i;
- switch (match->state)
+ for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
{
- case RRPD_STATE_1:
- if (in_rrpd->c2s)
+ rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_DNS)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
+ if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- match->req_last_frame = in_rrpd->req_last_frame;
- match->req_last_rtime = in_rrpd->req_last_rtime;
- if (in_rrpd->msg_id)
+ if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id)
{
- match->session_id = in_rrpd->session_id;
- match->msg_id = in_rrpd->msg_id;
- match->suffix = in_rrpd->suffix;
- match->state = RRPD_STATE_3;
+ if (in_rrpd->c2s && rrpd->rsp_first_frame)
+ return NULL; /* this is new */
+ else
+ return rrpd;
}
- }
- else
- {
- match->rsp_first_frame = in_rrpd->rsp_first_frame;
- match->rsp_first_rtime = in_rrpd->rsp_first_rtime;
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_7;
- else
- match->state = RRPD_STATE_5;
- }
- break;
+ } /* this is the end of the 5-tuple check */
- case RRPD_STATE_2:
if (in_rrpd->c2s)
- {
- match->req_last_frame = in_rrpd->req_last_frame;
- match->req_last_rtime = in_rrpd->req_last_rtime;
- if (in_rrpd->msg_id)
- {
- match->session_id = in_rrpd->session_id;
- match->msg_id = in_rrpd->msg_id;
- match->suffix = in_rrpd->suffix;
- match->state = RRPD_STATE_4;
- }
- }
+ in_rrpd->req_search_total++;
else
+ in_rrpd->rsp_search_total++;
+ } /* this is the end of the for loop */
+
+ return NULL;
+}
+
+static RRPD *find_latest_rrpd_gtcp(RRPD *in_rrpd)
+{
+ RRPD *rrpd;
+ wmem_list_frame_t* i;
+
+ for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
+ {
+ rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_GTCP && rrpd->calculation != RTE_CALC_SYN)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
+ if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- match->rsp_first_frame = in_rrpd->rsp_first_frame;
- match->rsp_first_rtime = in_rrpd->rsp_first_rtime;
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_8;
+ if (in_rrpd->c2s && rrpd->rsp_first_frame)
+ return NULL; /* this is new */
else
- match->state = RRPD_STATE_6;
- }
- break;
+ return rrpd;
+ } /* this is the end of the 5-tuple check */
- case RRPD_STATE_3:
if (in_rrpd->c2s)
- {
- match->req_last_frame = in_rrpd->req_last_frame;
- match->req_last_rtime = in_rrpd->req_last_rtime;
- if (in_rrpd->msg_id)
- {
- match->session_id = in_rrpd->session_id;
- match->msg_id = in_rrpd->msg_id;
- match->suffix = in_rrpd->suffix;
- match->state = RRPD_STATE_3;
- }
- }
+ in_rrpd->req_search_total++;
else
+ in_rrpd->rsp_search_total++;
+ } /* this is the end of the for loop */
+
+ return NULL;
+}
+
+static RRPD *find_latest_rrpd_gudp(RRPD *in_rrpd)
+{
+ RRPD *rrpd;
+ wmem_list_frame_t* i;
+
+ for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
+ {
+ rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_GUDP)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
+ if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- match->rsp_first_frame = in_rrpd->rsp_first_frame;
- match->rsp_first_rtime = in_rrpd->rsp_first_rtime;
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_7;
+ if (in_rrpd->c2s && rrpd->rsp_first_frame)
+ return NULL; /* this is new */
else
- match->state = RRPD_STATE_5;
- }
- break;
+ return rrpd;
+ } /* this is the end of the 5-tuple check */
- case RRPD_STATE_4:
if (in_rrpd->c2s)
+ in_rrpd->req_search_total++;
+ else
+ in_rrpd->rsp_search_total++;
+ } /* this is the end of the for loop */
+
+ return NULL;
+}
+
+static RRPD *find_latest_rrpd_smb2(RRPD *in_rrpd)
+{
+ RRPD *rrpd;
+ wmem_list_frame_t* i;
+
+ for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
+ {
+ rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_SMB2 && rrpd->calculation != RTE_CALC_SYN)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
+ if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- match->req_last_frame = in_rrpd->req_last_frame;
- match->req_last_rtime = in_rrpd->req_last_rtime;
- if (in_rrpd->msg_id)
+ /* if we can match on session_id and msg_id must be a retransmission of the last request packet or the response */
+ /* this logic works whether or not we are using reassembly */
+ if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id)
+ return rrpd;
+
+ /* If this is a retransmission, we assume it relates to this rrpd_list entry.
+ This is a bit of a kludge and not ideal but a compromise.*/
+ /* ToDo: look at using TCP sequence number to allocate a retransmission to the correct APDU */
+ if (in_rrpd->is_retrans)
+ return rrpd;
+
+ if (preferences.reassembly)
{
- match->session_id = in_rrpd->session_id;
- match->msg_id = in_rrpd->msg_id;
- match->suffix = in_rrpd->suffix;
- match->state = RRPD_STATE_4;
+ if (in_rrpd->c2s)
+ {
+ /* if the input rrpd is for c2s and the one we have found already has response information, then the
+ in_rrpd represents a new RR Pair. */
+ if (rrpd->rsp_first_frame)
+ return NULL;
+
+ /* If the current rrpd_list entry doesn't have a msg_id then we assume we are mid Request APDU and so we have a match. */
+ if (!rrpd->msg_id)
+ return rrpd;
+ }
+ else /* The in_rrpd relates to a packet going s2c */
+ {
+ /* When reassembly is enabled, multi-packet response information is actually migrated from the temp_rsp_rrpd_list
+ to the rrpd_list and so we won't come through here. */
+ ;
+ }
}
- }
- else
- {
- match->rsp_first_frame = in_rrpd->rsp_first_frame;
- match->rsp_first_rtime = in_rrpd->rsp_first_rtime;
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_8;
- else
- match->state = RRPD_STATE_6;
- }
- break;
+ else /* we are not using reassembly */
+ {
+ if (in_rrpd->c2s)
+ {
+ if (in_rrpd->msg_id)
+ /* if we have a message id this is a new Request APDU */
+ return NULL;
+ else /* No msg_id */
+ {
+ return rrpd; /* add this packet to the matching stream */
+ }
+ }
+ else /* this packet is going s2c */
+ {
+ if (!in_rrpd->msg_id && rrpd->rsp_first_frame)
+ /* we need to add this frame to the response APDU of the most recent rrpd_list entry that has already had response packets */
+ return rrpd;
+ }
+ }
+ } /* this is the end of the 5-tuple check */
- case RRPD_STATE_5:
if (in_rrpd->c2s)
- {
- /* we've change direction */
- ;
- }
+ in_rrpd->req_search_total++;
else
+ in_rrpd->rsp_search_total++;
+ } /* end of the for loop */
+
+ return NULL;
+}
+
+static RRPD *find_latest_rrpd_syn(RRPD *in_rrpd)
+{
+ RRPD *rrpd;
+ wmem_list_frame_t* i;
+
+ for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i))
+ {
+ rrpd = (RRPD*)wmem_list_frame_data(i);
+
+ if (rrpd->calculation != RTE_CALC_SYN)
+ continue;
+
+ /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */
+ if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no)
{
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_7;
- else
- match->state = RRPD_STATE_5;
- }
- break;
+ return rrpd;
+ } /* this is the end of the 5-tuple check */
- case RRPD_STATE_6:
if (in_rrpd->c2s)
- {
- /* we've change direction */
- ;
- }
+ in_rrpd->req_search_total++;
else
- {
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- if (in_rrpd->msg_id)
- match->state = RRPD_STATE_8;
- else
- match->state = RRPD_STATE_6;
- }
+ in_rrpd->rsp_search_total++;
+ } /* this is the end of the for loop */
+
+ return NULL;
+}
+
+static RRPD *find_latest_rrpd(RRPD *in_rrpd)
+{
+ /* Optimisation Code */
+ if (in_rrpd->ip_proto == IP_PROTO_TCP && (int)in_rrpd->stream_no > highest_tcp_stream_no)
+ {
+ highest_tcp_stream_no = in_rrpd->stream_no;
+ return NULL;
+ }
+ else if (in_rrpd->ip_proto == IP_PROTO_UDP && (int)in_rrpd->stream_no > highest_udp_stream_no)
+ {
+ highest_udp_stream_no = in_rrpd->stream_no;
+ return NULL;
+ }
+ /* End of Optimisation Code */
+
+ switch (in_rrpd->calculation)
+ {
+ case RTE_CALC_DCERPC:
+ return find_latest_rrpd_dcerpc(in_rrpd);
break;
- case RRPD_STATE_7:
- if (in_rrpd->c2s)
- {
- /* we've change direction */
- ;
- }
- else
- {
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
- }
+ case RTE_CALC_DNS:
+ return find_latest_rrpd_dns(in_rrpd);
break;
- case RRPD_STATE_8:
- if (in_rrpd->c2s)
+ case RTE_CALC_GTCP:
+ return find_latest_rrpd_gtcp(in_rrpd);
+ break;
+
+ case RTE_CALC_GUDP:
+ return find_latest_rrpd_gudp(in_rrpd);
+ break;
+
+ case RTE_CALC_SMB2:
+ return find_latest_rrpd_smb2(in_rrpd);
+ break;
+
+ case RTE_CALC_SYN:
+ return find_latest_rrpd_syn(in_rrpd);
+ break;
+ }
+
+ return NULL;
+}
+
+static void update_rrpd_list_entry(RRPD *match, RRPD *in_rrpd)
+{
+ null_output_rrpd_entries(match);
+
+ if (preferences.debug_enabled)
+ {
+ match->req_search_total += in_rrpd->req_search_total;
+ match->rsp_search_total += in_rrpd->rsp_search_total;
+ }
+
+ if (in_rrpd->c2s)
+ {
+ match->req_last_frame = in_rrpd->req_last_frame;
+ match->req_last_rtime = in_rrpd->req_last_rtime;
+ if (in_rrpd->msg_id)
{
- /* we've change direction */
- ;
+ match->session_id = in_rrpd->session_id;
+ match->msg_id = in_rrpd->msg_id;
}
- else
+ }
+ else
+ {
+ if (!match->rsp_first_frame)
{
- match->rsp_last_frame = in_rrpd->rsp_last_frame;
- match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
+ match->rsp_first_frame = in_rrpd->rsp_first_frame;
+ match->rsp_first_rtime = in_rrpd->rsp_first_rtime;
}
- break;
+ match->rsp_last_frame = in_rrpd->rsp_last_frame;
+ match->rsp_last_rtime = in_rrpd->rsp_last_rtime;
}
update_output_rrpd(match);
@@ -495,61 +604,17 @@ static void update_rrpd_list_entry_req(RRPD *in_rrpd)
{
RRPD *match;
- if (in_rrpd->decode_based)
- {
- while (TRUE)
- {
- if (preferences.reassembly)
- {
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_1);
- if (match != NULL) /* Check to cover TCP Reassembly enabled */
- {
- update_rrpd_list_entry(match, in_rrpd);
- break;
- }
- }
- else
- {
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_4);
- if (match != NULL)
- {
- update_rrpd_list_entry(match, in_rrpd);
- break;
- }
- }
+ match = find_latest_rrpd(in_rrpd);
- /* No entries and so add one */
- append_to_rrpd_list(in_rrpd);
- break;
- }
- }
+ if (match != NULL)
+ update_rrpd_list_entry(match, in_rrpd);
else
- {
- /*
- This is not a decode_based calculation and so a change from s2c to c2s
- means that this packets starts of a new APDU RR pair.
- */
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_DONT_CARE);
- if (match != NULL)
- {
- if (match->state > RRPD_STATE_4 && in_rrpd->c2s)
- {
- append_to_rrpd_list(in_rrpd);
- }
- else
- /* no change of direction so just update the RTE data */
- update_rrpd_list_entry(match, in_rrpd);
- }
- else
- {
- append_to_rrpd_list(in_rrpd);
- }
- }
+ append_to_rrpd_list(in_rrpd);
}
/*
This function inserts an RRPD into the temp_rsp_rrpd_list. If this is
- successful return the index of the entry. If there is no space return -1.
+ successful return a pointer to the entry, else return NULL.
*/
static RRPD* insert_into_temp_rsp_rrpd_list(RRPD *in_rrpd)
{
@@ -587,12 +652,6 @@ static void migrate_temp_rsp_rrpd(RRPD *main_list, RRPD *temp_list)
update_rrpd_list_entry(main_list, temp_list);
wmem_list_remove(temp_rsp_rrpd_list, temp_list);
-
- /* Update the state to 7 or 8 based on reassembly */
- if (preferences.reassembly)
- main_list->state = RRPD_STATE_7;
- else
- main_list->state = RRPD_STATE_8;
}
static void update_rrpd_list_entry_rsp(RRPD *in_rrpd)
@@ -613,13 +672,13 @@ static void update_rrpd_list_entry_rsp(RRPD *in_rrpd)
update_temp_rsp_rrpd(temp_list, in_rrpd);
/* Migrate the temp_rsp_rrpd_list entry to the main rrpd_list */
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_3);
+ match = find_latest_rrpd(in_rrpd);
if (match != NULL)
migrate_temp_rsp_rrpd(match, temp_list);
}
else
{
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_3);
+ match = find_latest_rrpd(in_rrpd);
/* There isn't an entry in the temp_rsp_rrpd_list so update the master rrpd_list entry */
if (match != NULL)
update_rrpd_list_entry(match, in_rrpd);
@@ -633,13 +692,27 @@ static void update_rrpd_list_entry_rsp(RRPD *in_rrpd)
if (temp_list != NULL)
update_temp_rsp_rrpd(temp_list, in_rrpd);
else
- insert_into_temp_rsp_rrpd_list(in_rrpd);
+ {
+ /* If this is a retransmission we need to add it to the last completed rrpd_list entry for this stream */
+ if (in_rrpd->is_retrans)
+ {
+ match = find_latest_rrpd(in_rrpd);
+
+ if (match != NULL)
+ update_rrpd_list_entry(match, in_rrpd);
+ else
+ insert_into_temp_rsp_rrpd_list(in_rrpd);
+ }
+ else
+ /* As it's not a retransmission, just create a new entry on the temp list */
+ insert_into_temp_rsp_rrpd_list(in_rrpd);
+ }
}
}
else
{
/* Reassembly isn't set and so just go ahead and use the list function */
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_8);
+ match = find_latest_rrpd(in_rrpd);
if (match != NULL)
update_rrpd_list_entry(match, in_rrpd);
}
@@ -647,7 +720,7 @@ static void update_rrpd_list_entry_rsp(RRPD *in_rrpd)
else
{
/* if this isn't decode_based then just go ahead and update the RTE data */
- match = find_latest_rrpd(in_rrpd, RRPD_STATE_DONT_CARE);
+ match = find_latest_rrpd(in_rrpd);
if (match != NULL)
update_rrpd_list_entry(match, in_rrpd);
}
@@ -670,21 +743,6 @@ static void update_rrpd_rte_data(RRPD *in_rrpd)
update_rrpd_list_entry_rsp(in_rrpd);
}
-#if 0
-void set_pkt_rrpd(PKT_INFO *current_pkt, guint8 ip_proto, guint32 stream_no, guint64 session_id, guint64 msg_id, gboolean requires_suffix)
-{
- current_pkt->rrpd.ip_proto = ip_proto;
- current_pkt->rrpd.stream_no = stream_no;
- current_pkt->rrpd.session_id = session_id;
- current_pkt->rrpd.msg_id = msg_id;
-
- if (requires_suffix)
- current_pkt->rrpd.suffix = ++rrpd_suffix;
- else
- current_pkt->rrpd.suffix = 0;
-}
-#endif
-
gboolean is_dcerpc_context_zero(guint32 pkt_type)
{
return (wmem_map_lookup(dcerpc_context_zero, GUINT_TO_POINTER(pkt_type)) != NULL);
@@ -695,6 +753,10 @@ gboolean is_dcerpc_req_pkt_type(guint32 pkt_type)
return (wmem_map_lookup(dcerpc_req_pkt_type, GUINT_TO_POINTER(pkt_type)) != NULL);
}
+gboolean is_dcerpc_stream(guint32 stream_no)
+{
+ return (wmem_map_lookup(dcerpc_streams, GUINT_TO_POINTER(stream_no)) != NULL);
+}
/*
This function initialises the global variables and populates the
@@ -705,7 +767,11 @@ static void init_globals(void)
if (!proto_is_protocol_enabled(find_protocol_by_id(proto_transum)))
return;
+ highest_tcp_stream_no = -1;
+ highest_udp_stream_no = -1;
+
/* Create and initialise some dynamic memory areas */
+ tcp_stream_exceptions = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
detected_tcp_svc = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
rrpd_list = wmem_list_new(wmem_file_scope());
temp_rsp_rrpd_list = wmem_list_new(wmem_file_scope());
@@ -742,6 +808,7 @@ static void init_globals(void)
/* create arrays to hold some DCE-RPC values */
dcerpc_context_zero = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
dcerpc_req_pkt_type = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
+ dcerpc_streams = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
init_dcerpc_data();
wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(445), GUINT_TO_POINTER(RTE_CALC_SMB2));
@@ -849,6 +916,14 @@ static void write_rte(RRPD *in_rrpd, tvbuff_t *tvb, proto_tree *tree, char *summ
}
}
}
+
+ if (preferences.debug_enabled)
+ {
+ pi = proto_tree_add_uint(rte_tree, hf_tsum_req_search, tvb, 0, 0, in_rrpd->req_search_total);
+ PROTO_ITEM_SET_GENERATED(pi);
+ pi = proto_tree_add_uint(rte_tree, hf_tsum_rsp_search, tvb, 0, 0, in_rrpd->rsp_search_total);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
}
}
@@ -882,6 +957,32 @@ static void set_proto_values(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt
calculate RTE figures for all SYNs and also we may detect DCE-RPC later
(even though we don't currently have an entry in the tcp_svc_ports list). */
+ /* Optimisation code */
+ if (pkt_info->len || pkt_info->tcp_flags_syn)
+ {
+ if (pkt_info->ssl_content_type == 21) /* this is an SSL Alert */
+ {
+ pkt_info->pkt_of_interest = FALSE;
+ return;
+ }
+
+ if ((int)pkt_info->rrpd.stream_no > highest_tcp_stream_no && !pkt_info->rrpd.c2s)
+ {
+ /* first packet on the stream is s2c and so add to exception list */
+ if (wmem_map_lookup(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no)) == NULL)
+ wmem_map_insert(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no), GUINT_TO_POINTER(1));
+ }
+
+ if (wmem_map_lookup(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no)) != NULL)
+ {
+ if (pkt_info->rrpd.c2s)
+ wmem_map_remove(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no));
+ else
+ pkt_info->pkt_of_interest = FALSE;
+ }
+ }
+ /* End of Optimisation Code */
+
if (pkt_info->tcp_retran)
{
/* we may not want to continue with this packet if it's a retransmission */
@@ -929,11 +1030,27 @@ static void set_proto_values(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt
if (pkt_info->dstport == 445 || pkt_info->srcport == 445)
number_sub_pkts_of_interest = decode_smb(pinfo, tree, pkt_info, subpackets);
- /* check if DCE-RPC */
- else if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_VER].hf, field_uint, &field_value_count))
+ else
{
- if (field_value_count)
- number_sub_pkts_of_interest = decode_dcerpc(pinfo, tree, pkt_info);
+ /* check if DCE-RPC */
+ /* We need to set RTE_CALC_DCERPC even when we don't have header info. */
+ if (is_dcerpc_stream(pkt_info->rrpd.stream_no))
+ {
+ pkt_info->rrpd.calculation = RTE_CALC_DCERPC;
+ pkt_info->rrpd.decode_based = TRUE;
+ pkt_info->pkt_of_interest = TRUE;
+ }
+
+ if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_VER].hf, field_uint, &field_value_count))
+ {
+ if (field_value_count)
+ {
+ if (pkt_info->rrpd.calculation != RTE_CALC_DCERPC)
+ register_dcerpc_stream(pkt_info->rrpd.stream_no);
+
+ number_sub_pkts_of_interest = decode_dcerpc(pinfo, tree, pkt_info);
+ }
+ }
}
}
@@ -1096,7 +1213,20 @@ proto_register_transum(void)
{ "Summary", "transum.summary",
FT_STRING, BASE_NONE, NULL, 0x0,
"Summarizer information", HFILL }
+ },
+
+ { &hf_tsum_req_search,
+ { "Req Search Count", "transum.req_search",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "rrpd_list search total for the request packets", HFILL }
+ },
+
+ { &hf_tsum_rsp_search,
+ { "Rsp Search Counts", "transum.rsp_search",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "rrpd_list search total for the reponse packets", HFILL }
}
+
};
/* Setup protocol subtree array */
@@ -1126,6 +1256,8 @@ proto_register_transum(void)
preferences.rte_on_first_rsp = FALSE;
preferences.rte_on_last_rsp = FALSE;
+ preferences.debug_enabled = FALSE;
+
/* no start registering stuff */
proto_register_field_array(proto_transum, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
@@ -1203,6 +1335,12 @@ proto_register_transum(void)
"RTE data will be added to the last response packet",
&preferences.rte_on_last_rsp);
+ prefs_register_bool_preference(transum_module,
+ "debug_enabled",
+ "Enable debug info",
+ "Set this only to troubleshoot problems",
+ &preferences.debug_enabled);
+
transum_handle = register_dissector("transum", dissect_transum, proto_transum);
register_init_routine(init_globals);
diff --git a/plugins/transum/packet-transum.h b/plugins/transum/packet-transum.h
index ed3665069e..f633e80b9a 100644
--- a/plugins/transum/packet-transum.h
+++ b/plugins/transum/packet-transum.h
@@ -28,17 +28,6 @@
#define IP_PROTO_TCP 6
#define IP_PROTO_UDP 17
-#define RRPD_STATE_DONT_CARE 0
-#define RRPD_STATE_INIT 0
-#define RRPD_STATE_1 1
-#define RRPD_STATE_2 2
-#define RRPD_STATE_3 3
-#define RRPD_STATE_4 4
-#define RRPD_STATE_5 5
-#define RRPD_STATE_6 6
-#define RRPD_STATE_7 7
-#define RRPD_STATE_8 8
-
#define RTE_CALC_SYN 1
#define RTE_CALC_GTCP 2
#define RTE_CALC_GUDP 3
@@ -68,7 +57,6 @@ typedef struct _RRPD
guint32 stream_no;
guint64 session_id;
guint64 msg_id;
- guint32 suffix;
/*
Some request-response pairs are demarked simple by a change in direction on a
@@ -79,7 +67,7 @@ typedef struct _RRPD
*/
gboolean decode_based;
- int state;
+ gboolean is_retrans;
guint32 req_first_frame;
nstime_t req_first_rtime;
@@ -92,6 +80,10 @@ typedef struct _RRPD
nstime_t rsp_last_rtime;
guint calculation;
+
+ /* The following numbers are for tuning purposes */
+ guint32 req_search_total; /* The total number of steps back through the rrpd_list when matching requests to this entry */
+ guint32 rsp_search_total; /* The total number of steps back through the rrpd_list when matching responses to this entry */
} RRPD;
typedef struct _PKT_INFO
@@ -112,6 +104,8 @@ typedef struct _PKT_INFO
guint16 dstport; /* tcp.dstport or udp.dstport*/
guint16 len; /* tcp.len or udp.len */
+ guint8 ssl_content_type; /*ssl.record.content_type */
+
guint8 tds_type; /*tds.type */
guint16 tds_length; /* tds.length */
@@ -158,6 +152,8 @@ typedef enum {
HF_INTEREST_UDP_STREAM,
HF_INTEREST_UDP_LENGTH,
+ HF_INTEREST_SSL_CONTENT_TYPE,
+
HF_INTEREST_TDS_TYPE,
HF_INTEREST_TDS_LENGTH,
diff --git a/plugins/transum/preferences.h b/plugins/transum/preferences.h
index 6cde8ad8ae..50b68419c9 100644
--- a/plugins/transum/preferences.h
+++ b/plugins/transum/preferences.h
@@ -50,4 +50,5 @@ typedef struct _TSUM_PREFERENCES
gboolean summarisers_enabled;
gboolean summarise_tds;
gboolean summarisers_escape_quotes;
+ gboolean debug_enabled;
} TSUM_PREFERENCES;