aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debian/libwireshark0.symbols3
-rw-r--r--epan/dissectors/packet-tcp.c55
-rw-r--r--epan/follow.c366
-rw-r--r--epan/follow.h7
-rw-r--r--ui/cli/tap-follow.c15
-rw-r--r--ui/gtk/follow_http.c2
-rw-r--r--ui/gtk/follow_ssl.c2
-rw-r--r--ui/gtk/follow_tcp.c322
-rw-r--r--ui/gtk/follow_udp.c2
-rw-r--r--ui/qt/follow_stream_dialog.cpp405
-rw-r--r--ui/qt/follow_stream_dialog.h4
11 files changed, 279 insertions, 904 deletions
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols
index a6adb27e1e..a55dfdd0cc 100644
--- a/debian/libwireshark0.symbols
+++ b/debian/libwireshark0.symbols
@@ -1165,9 +1165,8 @@ libwireshark.so.0 libwireshark0 #MINVER#
reset_rtd_table@Base 1.99.8
reset_srt_table@Base 1.99.8
reset_stat_table@Base 1.99.8
+ reset_stream_follow@Base 2.1.0
reset_tap_listeners@Base 1.9.1
- reset_tcp_reassembly@Base 1.9.1
- reset_udp_follow@Base 1.99.2
rose_ctx_clean_data@Base 1.9.1
rose_ctx_init@Base 1.9.1
rpc_init_prog@Base 1.9.1
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
index 963dd6b750..7386eda7f3 100644
--- a/epan/dissectors/packet-tcp.c
+++ b/epan/dissectors/packet-tcp.c
@@ -52,6 +52,7 @@ void proto_register_tcp(void);
void proto_reg_handoff_tcp(void);
static int tcp_tap = -1;
+static int tcp_follow_tap = -1;
static int mptcp_tap = -1;
/* Place TCP summary in proto tree */
@@ -108,9 +109,6 @@ enum mptcp_dsn_conversion {
static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown;
-
-extern FILE* data_out_file;
-
static int proto_tcp = -1;
static int proto_mptcp = -1;
static int hf_tcp_srcport = -1;
@@ -2180,6 +2178,12 @@ again:
}
nbytes = tvb_reported_length_remaining(tvb, offset);
+
+ /* Give the follow tap what we've currently dissected */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, tvb_new_subset_length(tvb, offset, nbytes));
+ }
+
proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, offset,
nbytes, NULL, "%sTCP segment data (%u byte%s)", str, nbytes,
plurality(nbytes, "", "s"));
@@ -2259,6 +2263,11 @@ again:
*/
tcpinfo->seq = seq;
+ /* Give the follow tap what we've currently dissected */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, tvb_new_subset_length(tvb, 0, offset));
+ }
+
process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
sport, dport, 0, 0, FALSE, tcpd, tcpinfo);
called_dissector = TRUE;
@@ -2322,6 +2331,11 @@ again:
/* indicate that this is reassembled data */
tcpinfo->is_reassembled = TRUE;
+ /* Give the follow tap the payload */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, next_tvb);
+ }
+
/* call subdissector */
process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, sport,
dport, 0, 0, FALSE, tcpd, tcpinfo);
@@ -2536,6 +2550,12 @@ again:
* was, and report it as a continuation of that, instead?
*/
nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
+
+ /* Give the follow tap what we've currently dissected */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, tvb_new_subset_length(tvb, deseg_offset, nbytes));
+ }
+
proto_tree_add_bytes_format(tcp_tree, hf_tcp_segment_data, tvb, deseg_offset,
-1, NULL, "TCP segment data (%u byte%s)", nbytes,
plurality(nbytes, "", "s"));
@@ -4742,6 +4762,12 @@ dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
we don't report it as a malformed frame. */
save_fragmented = pinfo->fragmented;
pinfo->fragmented = TRUE;
+
+ /* Give the follow tap what we've currently dissected */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, tvb_new_subset_length(tvb, 0, offset));
+ }
+
process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
seq, nxtseq, TRUE, tcpd, tcpinfo);
pinfo->fragmented = save_fragmented;
@@ -5472,23 +5498,6 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
(it could be an ACK-only packet) */
captured_length_remaining = tvb_captured_length_remaining(tvb, offset);
- if (tcph->th_have_seglen) {
- if( data_out_file ) {
- reassemble_tcp( tcpd->stream, /* tcp stream index */
- tcph->th_seq, /* sequence number */
- tcph->th_ack, /* acknowledgment number */
- tcph->th_seglen, /* data length */
- (const gchar*)tvb_get_ptr(tvb, offset, captured_length_remaining), /* data */
- captured_length_remaining, /* captured data length */
- ( tcph->th_flags & TH_SYN ), /* is syn set? */
- &pinfo->net_src,
- &pinfo->net_dst,
- pinfo->srcport,
- pinfo->destport,
- pinfo->fd->num);
- }
- }
-
tap_queue_packet(tcp_tap, pinfo, tcph);
/* if it is an MPTCP packet */
@@ -5543,6 +5552,11 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
*/
pinfo->can_desegment = 0;
+ /* Give the follow tap the payload */
+ if(have_tap_listener(tcp_follow_tap)) {
+ tap_queue_packet(tcp_follow_tap, pinfo, next_tvb);
+ }
+
process_tcp_payload(next_tvb, 0, pinfo, tree, tcp_tree, tcph->th_sport, tcph->th_dport, tcph->th_seq,
nxtseq, FALSE, tcpd, &tcpinfo);
@@ -6670,6 +6684,7 @@ proto_reg_handoff_tcp(void)
data_handle = find_dissector("data");
sport_handle = find_dissector("sport");
tcp_tap = register_tap("tcp");
+ tcp_follow_tap = register_tap("tcp_follow");
register_capture_dissector("ip.proto", IP_PROTO_TCP, capture_tcp, proto_tcp);
register_capture_dissector("ipv6.nxt", IP_PROTO_TCP, capture_tcp, proto_tcp);
diff --git a/epan/follow.c b/epan/follow.c
index 89e6519193..8e64044ce1 100644
--- a/epan/follow.c
+++ b/epan/follow.c
@@ -65,9 +65,6 @@ static guint port[2];
static guint bytes_written[2];
static gboolean is_ipv6 = FALSE;
-static int check_fragments( int, tcp_stream_chunk *, guint32 );
-static void write_packet_data( int, tcp_stream_chunk *, const char * );
-
void
follow_stats(follow_stats_t* stats)
{
@@ -193,11 +190,45 @@ udp_follow_packet(void *tapdata _U_, packet_info *pinfo,
return FALSE;
}
+
+/* here we are going to try and reconstruct the data portion of a TCP
+ session. We will try and handle duplicates, TCP fragments, and out
+ of order packets in a smart way. */
+
+static tcp_frag *frags[2] = { 0, 0 };
+static guint32 seq[2];
+static guint8 src_addr[2][MAX_IPADDR_LEN];
+static guint src_port[2] = { 0, 0 };
+
void
-reset_udp_follow(void) {
- remove_tap_listener(&stream_to_follow[UDP_STREAM]);
- find_addr[UDP_STREAM] = FALSE;
- find_index[UDP_STREAM] = FALSE;
+reset_stream_follow(stream_type stream) {
+ tcp_frag *current, *next;
+ int i;
+
+ remove_tap_listener(&stream_to_follow[stream]);
+ find_addr[stream] = FALSE;
+ find_index[stream] = FALSE;
+ if (stream == TCP_STREAM) {
+ empty_tcp_stream = TRUE;
+ incomplete_tcp_stream = FALSE;
+
+ for( i=0; i<2; i++ ) {
+ seq[i] = 0;
+ memset(src_addr[i], '\0', MAX_IPADDR_LEN);
+ src_port[i] = 0;
+ memset(ip_address[i], '\0', MAX_IPADDR_LEN);
+ port[i] = 0;
+ bytes_written[i] = 0;
+ current = frags[i];
+ while( current ) {
+ next = current->next;
+ g_free( current->data );
+ g_free( current );
+ current = next;
+ }
+ frags[i] = NULL;
+ }
+ }
}
gchar*
@@ -278,327 +309,6 @@ get_follow_index(stream_type stream) {
return stream_to_follow[stream];
}
-/* here we are going to try and reconstruct the data portion of a TCP
- session. We will try and handle duplicates, TCP fragments, and out
- of order packets in a smart way. */
-
-static tcp_frag *frags[2] = { 0, 0 };
-static guint32 seq[2];
-static guint8 src_addr[2][MAX_IPADDR_LEN];
-static guint src_port[2] = { 0, 0 };
-
-void
-reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
- guint32 length, const char* data, guint32 data_length,
- int synflag, address *net_src, address *net_dst,
- guint srcport, guint dstport, guint32 packet_num) {
- guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
- int src_index, j, first = 0, len;
- guint32 newseq;
- tcp_frag *tmp_frag;
- tcp_stream_chunk sc;
-
- src_index = -1;
-
- /* First, check if this packet should be processed. */
- if (find_index[TCP_STREAM]) {
- if ((port[0] == srcport && port[1] == dstport &&
- addresses_equal(&tcp_addr[0], net_src) &&
- addresses_equal(&tcp_addr[1], net_dst))
- ||
- (port[1] == srcport && port[0] == dstport &&
- addresses_equal(&tcp_addr[1], net_src) &&
- addresses_equal(&tcp_addr[0], net_dst))) {
- find_index[TCP_STREAM] = FALSE;
- stream_to_follow[TCP_STREAM] = tcp_stream;
- }
- else {
- return;
- }
- }
- else if ( tcp_stream != stream_to_follow[TCP_STREAM] )
- return;
-
- if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) ||
- (net_dst->type != AT_IPv4 && net_dst->type != AT_IPv6))
- return;
-
- if (net_src->type == AT_IPv4)
- len = 4;
- else
- len = 16;
-
- memcpy(srcx, net_src->data, len);
- memcpy(dstx, net_dst->data, len);
-
- /* follow_tcp_index() needs to learn address/port pairs */
- if (find_addr[TCP_STREAM]) {
- find_addr[TCP_STREAM] = FALSE;
- memcpy(ip_address[0], net_src->data, net_src->len);
- port[0] = srcport;
- memcpy(ip_address[1], net_dst->data, net_dst->len);
- port[1] = dstport;
- if (net_src->type == AT_IPv6 && net_dst->type == AT_IPv6) {
- is_ipv6 = TRUE;
- } else {
- is_ipv6 = FALSE;
- }
- }
-
- /* Check to see if we have seen this source IP and port before.
- (Yes, we have to check both source IP and port; the connection
- might be between two different ports on the same machine.) */
- for( j=0; j<2; j++ ) {
- if (memcmp(src_addr[j], srcx, len) == 0 && src_port[j] == srcport ) {
- src_index = j;
- }
- }
- /* we didn't find it if src_index == -1 */
- if( src_index < 0 ) {
- /* assign it to a src_index and get going */
- for( j=0; j<2; j++ ) {
- if( src_port[j] == 0 ) {
- memcpy(src_addr[j], srcx, len);
- src_port[j] = srcport;
- src_index = j;
- first = 1;
- break;
- }
- }
- }
- if( src_index < 0 ) {
- fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
- return;
- }
-
- if( data_length < length ) {
- incomplete_tcp_stream = TRUE;
- }
-
- /* Before adding data for this flow to the data_out_file, check whether
- * this frame acks fragments that were already seen. This happens when
- * frames are not in the capture file, but were actually seen by the
- * receiving host (Fixes bug 592).
- */
- if( frags[1-src_index] ) {
- memcpy(sc.src_addr, dstx, len);
- sc.src_port = dstport;
- sc.dlen = 0; /* Will be filled in in check_fragments */
- while ( check_fragments( 1-src_index, &sc, acknowledgement ) )
- ;
- }
-
- /* Initialize our stream chunk. This data gets written to disk. */
- memcpy(sc.src_addr, srcx, len);
- sc.src_port = srcport;
- sc.dlen = data_length;
- sc.packet_num = packet_num;
-
- /* now that we have filed away the srcs, lets get the sequence number stuff
- figured out */
- if( first ) {
- /* this is the first time we have seen this src's sequence number */
- seq[src_index] = sequence + length;
- if( synflag ) {
- seq[src_index]++;
- }
- /* write out the packet data */
- write_packet_data( src_index, &sc, data );
- return;
- }
- /* if we are here, we have already seen this src, let's
- try and figure out if this packet is in the right place */
- if( LT_SEQ(sequence, seq[src_index]) ) {
- /* this sequence number seems dated, but
- check the end to make sure it has no more
- info than we have already seen */
- newseq = sequence + length;
- if( GT_SEQ(newseq, seq[src_index]) ) {
- guint32 new_len;
-
- /* this one has more than we have seen. let's get the
- payload that we have not seen. */
-
- new_len = seq[src_index] - sequence;
-
- if ( data_length <= new_len ) {
- data = NULL;
- data_length = 0;
- incomplete_tcp_stream = TRUE;
- } else {
- data += new_len;
- data_length -= new_len;
- }
- sc.dlen = data_length;
- sequence = seq[src_index];
- length = newseq - seq[src_index];
-
- /* this will now appear to be right on time :) */
- }
- }
- if ( EQ_SEQ(sequence, seq[src_index]) ) {
- /* right on time */
- seq[src_index] += length;
- if( synflag ) seq[src_index]++;
- if( data ) {
- write_packet_data( src_index, &sc, data );
- }
- /* done with the packet, see if it caused a fragment to fit */
- while( check_fragments( src_index, &sc, 0 ) )
- ;
- }
- else {
- /* out of order packet */
- if(data_length > 0 && GT_SEQ(sequence, seq[src_index]) ) {
- tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
- tmp_frag->data = (gchar *)g_malloc( data_length );
- tmp_frag->seq = sequence;
- tmp_frag->len = length;
- tmp_frag->data_len = data_length;
- memcpy( tmp_frag->data, data, data_length );
- if( frags[src_index] ) {
- tmp_frag->next = frags[src_index];
- } else {
- tmp_frag->next = NULL;
- }
- frags[src_index] = tmp_frag;
- }
- }
-} /* end reassemble_tcp */
-
-/* here we search through all the frag we have collected to see if
- one fits */
-static int
-check_fragments( int idx, tcp_stream_chunk *sc, guint32 acknowledged ) {
- tcp_frag *prev = NULL;
- tcp_frag *current;
- guint32 lowest_seq;
- gchar *dummy_str;
-
- current = frags[idx];
- if( current ) {
- lowest_seq = current->seq;
- while( current ) {
- if( GT_SEQ(lowest_seq, current->seq) ) {
- lowest_seq = current->seq;
- }
-
- if( LT_SEQ(current->seq, seq[idx]) ) {
- guint32 newseq;
- /* this sequence number seems dated, but
- check the end to make sure it has no more
- info than we have already seen */
- newseq = current->seq + current->len;
- if( GT_SEQ(newseq, seq[idx]) ) {
- guint32 new_pos;
-
- /* this one has more than we have seen. let's get the
- payload that we have not seen. This happens when
- part of this frame has been retransmitted */
-
- new_pos = seq[idx] - current->seq;
-
- if ( current->data_len > new_pos ) {
- sc->dlen = current->data_len - new_pos;
- write_packet_data( idx, sc, current->data + new_pos );
- }
-
- seq[idx] += (current->len - new_pos);
- }
-
- /* Remove the fragment from the list as the "new" part of it
- * has been processed or its data has been seen already in
- * another packet. */
- if( prev ) {
- prev->next = current->next;
- } else {
- frags[idx] = current->next;
- }
- g_free( current->data );
- g_free( current );
- return 1;
- }
-
- if( EQ_SEQ(current->seq, seq[idx]) ) {
- /* this fragment fits the stream */
- if( current->data ) {
- sc->dlen = current->data_len;
- write_packet_data( idx, sc, current->data );
- }
- seq[idx] += current->len;
- if( prev ) {
- prev->next = current->next;
- } else {
- frags[idx] = current->next;
- }
- g_free( current->data );
- g_free( current );
- return 1;
- }
- prev = current;
- current = current->next;
- }
- if( GT_SEQ(acknowledged, lowest_seq) ) {
- /* There are frames missing in the capture file that were seen
- * by the receiving host. Add dummy stream chunk with the data
- * "[xxx bytes missing in capture file]".
- */
- dummy_str = g_strdup_printf("[%d bytes missing in capture file]",
- (int)(lowest_seq - seq[idx]) );
- sc->dlen = (guint32) strlen(dummy_str);
- write_packet_data( idx, sc, dummy_str );
- g_free(dummy_str);
- seq[idx] = lowest_seq;
- return 1;
- }
- }
- return 0;
-}
-
-/* this should always be called before we start to reassemble a stream */
-void
-reset_tcp_reassembly(void)
-{
- tcp_frag *current, *next;
- int i;
-
- empty_tcp_stream = TRUE;
- incomplete_tcp_stream = FALSE;
- find_addr[TCP_STREAM] = FALSE;
- find_index[TCP_STREAM] = FALSE;
- for( i=0; i<2; i++ ) {
- seq[i] = 0;
- memset(src_addr[i], '\0', MAX_IPADDR_LEN);
- src_port[i] = 0;
- memset(ip_address[i], '\0', MAX_IPADDR_LEN);
- port[i] = 0;
- bytes_written[i] = 0;
- current = frags[i];
- while( current ) {
- next = current->next;
- g_free( current->data );
- g_free( current );
- current = next;
- }
- frags[i] = NULL;
- }
-}
-
-static void
-write_packet_data( int idx, tcp_stream_chunk *sc, const char *data )
-{
- size_t ret;
-
- ret = fwrite( sc, 1, sizeof(tcp_stream_chunk), data_out_file );
- DISSECTOR_ASSERT(sizeof(tcp_stream_chunk) == ret);
-
- ret = fwrite( data, 1, sc->dlen, data_out_file );
- DISSECTOR_ASSERT(sc->dlen == ret);
-
- bytes_written[idx] += sc->dlen;
- empty_tcp_stream = FALSE;
-}
-
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
diff --git a/epan/follow.h b/epan/follow.h
index 7eefe2270e..06f0e135e9 100644
--- a/epan/follow.h
+++ b/epan/follow.h
@@ -90,13 +90,8 @@ gboolean follow_index(stream_type stream, guint32 addr);
WS_DLL_PUBLIC
guint32 get_follow_index(stream_type stream);
-void reassemble_tcp( guint32, guint32, guint32, guint32, const char*, guint32,
- int, address *, address *, guint, guint, guint32 );
WS_DLL_PUBLIC
-void reset_tcp_reassembly( void );
-
-WS_DLL_PUBLIC
-void reset_udp_follow(void);
+void reset_stream_follow(stream_type stream);
typedef struct {
guint8 ip_address[2][MAX_IPADDR_LEN];
diff --git a/ui/cli/tap-follow.c b/ui/cli/tap-follow.c
index a938e12c9e..95473b2939 100644
--- a/ui/cli/tap-follow.c
+++ b/ui/cli/tap-follow.c
@@ -314,7 +314,7 @@ followFree(
}
static int
-followUdpPacket(
+follow_common_stream_packet(
void *contextp,
packet_info *pip,
epan_dissect_t *edp _U_,
@@ -898,7 +898,7 @@ followTcp(
followArgRange(&opt_argp, fp);
followArgDone(opt_argp);
- reset_tcp_reassembly();
+ reset_stream_follow(TCP_STREAM);
if (fp->stream_index != G_MAXUINT32)
{
if (!follow_index(TCP_STREAM, fp->stream_index))
@@ -917,8 +917,9 @@ followTcp(
followFileOpen(fp);
- errp = register_tap_listener("frame", fp, NULL, 0,
- NULL, NULL, followDraw);
+ errp = register_tap_listener("tcp_follow", fp, followStrFilter(fp), 0,
+ NULL, follow_common_stream_packet, followDraw);
+
if (errp != NULL)
{
followFree(fp);
@@ -945,7 +946,7 @@ followUdp(
followArgRange(&opt_argp, fp);
followArgDone(opt_argp);
- reset_udp_follow();
+ reset_stream_follow(UDP_STREAM);
if (fp->stream_index != G_MAXUINT32)
{
if (!follow_index(UDP_STREAM, fp->stream_index))
@@ -965,7 +966,7 @@ followUdp(
followFileOpen(fp);
errp = register_tap_listener("udp_follow", fp, followStrFilter(fp), 0,
- NULL, followUdpPacket, followDraw);
+ NULL, follow_common_stream_packet, followDraw);
if (errp != NULL)
{
followFree(fp);
@@ -992,7 +993,7 @@ followSsl(
followArgRange(&opt_argp, fp);
followArgDone(opt_argp);
- reset_tcp_reassembly();
+ reset_stream_follow(TCP_STREAM);
if (fp->stream_index == G_MAXUINT32)
{
followExit("SSL only supports index filters.");
diff --git a/ui/gtk/follow_http.c b/ui/gtk/follow_http.c
index 5362bfc4de..8e8bb96b3e 100644
--- a/ui/gtk/follow_http.c
+++ b/ui/gtk/follow_http.c
@@ -104,6 +104,8 @@ follow_http_stream_cb(GtkWidget *w _U_, gpointer data _U_)
return;
}
+ reset_stream_follow(TCP_STREAM);
+
follow_info = g_new0(follow_info_t, 1);
follow_info->follow_type = FOLLOW_HTTP;
follow_info->read_stream = follow_read_http_stream;
diff --git a/ui/gtk/follow_ssl.c b/ui/gtk/follow_ssl.c
index 1f446f458b..1ee6b49574 100644
--- a/ui/gtk/follow_ssl.c
+++ b/ui/gtk/follow_ssl.c
@@ -162,7 +162,7 @@ follow_ssl_stream_cb(GtkWidget * w _U_, gpointer data _U_)
/* Create a new filter that matches all packets in the SSL stream,
and set the display filter entry accordingly */
- reset_tcp_reassembly();
+ reset_stream_follow(TCP_STREAM);
follow_filter = build_follow_conv_filter(&cfile.edt->pi, NULL);
if (!follow_filter)
{
diff --git a/ui/gtk/follow_tcp.c b/ui/gtk/follow_tcp.c
index c8683c0f62..d94792d67d 100644
--- a/ui/gtk/follow_tcp.c
+++ b/ui/gtk/follow_tcp.c
@@ -27,41 +27,24 @@
#include <gtk/gtk.h>
-#include <epan/follow.h>
-#include <epan/dissectors/packet-ipv6.h>
-#include <epan/prefs.h>
#include <epan/addr_resolv.h>
-#include <epan/charsets.h>
#include <epan/epan_dissect.h>
-#include <wsutil/filesystem.h>
+#include <epan/follow.h>
+#include <epan/tap.h>
-#include "../file.h"
-#include "ui/alert_box.h"
-#include "ui/simple_dialog.h"
+#include <ui/simple_dialog.h>
#include <wsutil/utf8_entities.h>
-#include "wsutil/tempfile.h"
-#include <wsutil/file_util.h>
#include "gtkglobals.h"
-#include "ui/gtk/color_utils.h"
-#include "ui/gtk/follow_tcp.h"
-#include "ui/gtk/dlg_utils.h"
-#include "ui/gtk/file_dlg.h"
+#include "ui/gtk/follow_stream.h"
#include "ui/gtk/keys.h"
#include "ui/gtk/main.h"
-#include "ui/gtk/gui_utils.h"
-#include "ui/win32/print_win32.h"
-#include "ui/gtk/font_utils.h"
-#include "ui/gtk/help_dlg.h"
-#include "ui/gtk/follow_stream.h"
-#include "ws_symbol_export.h"
+#include "ui/gtk/follow_tcp.h"
+
static frs_return_t
follow_read_tcp_stream(follow_info_t *follow_info, follow_print_line_func follow_print, void *arg);
-/* With MSVC and a libwireshark.dll, we need a special declaration. */
-WS_DLL_PUBLIC FILE *data_out_file;
-
static void
follow_redraw(gpointer data, gpointer user_data _U_)
{
@@ -75,6 +58,38 @@ follow_tcp_redraw_all(void)
g_list_foreach(follow_infos, follow_redraw, NULL);
}
+static gboolean
+tcp_queue_packet_data(void *tapdata, packet_info *pinfo,
+ epan_dissect_t *edt _U_, const void *data)
+{
+ follow_record_t *follow_record;
+ follow_info_t *follow_info = (follow_info_t *)tapdata;
+ tvbuff_t *next_tvb = (tvbuff_t *)data;
+
+ follow_record = g_new(follow_record_t,1);
+
+ follow_record->data = g_byte_array_sized_new(tvb_captured_length(next_tvb));
+ follow_record->data = g_byte_array_append(follow_record->data,
+ tvb_get_ptr(next_tvb, 0, -1),
+ tvb_captured_length(next_tvb));
+
+ if (follow_info->client_port == 0) {
+ follow_info->client_port = pinfo->srcport;
+ copy_address(&follow_info->client_ip, &pinfo->src);
+ }
+
+ if (addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport)
+ follow_record->is_server = FALSE;
+ else
+ follow_record->is_server = TRUE;
+
+ /* update stream counter */
+ follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
+
+ follow_info->payload = g_list_append(follow_info->payload, follow_record);
+ return FALSE;
+}
+
/* Follow the TCP stream, if any, to which the last packet that we called
a dissection routine on belongs (this might be the most recently
selected packet, or it might be the last packet in the file). */
@@ -83,7 +98,6 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
{
GtkWidget *filter_cm;
GtkWidget *filter_te;
- int tmp_fd;
gchar *follow_filter;
const gchar *previous_filter;
int filter_out_filter_len;
@@ -94,10 +108,7 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
gchar *both_directions_string = NULL;
follow_stats_t stats;
follow_info_t *follow_info;
- tcp_stream_chunk sc;
- size_t nchars;
- gchar *data_out_filename;
- char stream_window_title[256];
+ GString *msg;
gboolean is_tcp = FALSE;
is_tcp = proto_is_frame_protocol(cfile.edt->pi.layers, "tcp");
@@ -109,13 +120,14 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
return;
}
+ reset_stream_follow(TCP_STREAM);
+
follow_info = g_new0(follow_info_t, 1);
follow_info->follow_type = FOLLOW_TCP;
follow_info->read_stream = follow_read_tcp_stream;
/* Create a new filter that matches all packets in the TCP stream,
and set the display filter entry accordingly */
- reset_tcp_reassembly();
follow_filter = build_follow_conv_filter(&cfile.edt->pi, NULL);
if (!follow_filter) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
@@ -125,40 +137,6 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
return;
}
- /* Create a temporary file into which to dump the reassembled data
- from the TCP stream, and set "data_out_file" to refer to it, so
- that the TCP code will write to it.
-
- XXX - it might be nicer to just have the TCP code directly
- append stuff to the text widget for the TCP stream window,
- if we can arrange that said window not pop up until we're
- done. */
- tmp_fd = create_tempfile(&data_out_filename, "follow");
- follow_info->data_out_filename = g_strdup(data_out_filename);
-
- if (tmp_fd == -1) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Could not create temporary file %s: %s",
- follow_info->data_out_filename, g_strerror(errno));
- g_free(follow_info->data_out_filename);
- g_free(follow_info);
- g_free(follow_filter);
- return;
- }
-
- data_out_file = ws_fdopen(tmp_fd, "w+b");
- if (data_out_file == NULL) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Could not create temporary file %s: %s",
- follow_info->data_out_filename, g_strerror(errno));
- ws_close(tmp_fd);
- ws_unlink(follow_info->data_out_filename);
- g_free(follow_info->data_out_filename);
- g_free(follow_info);
- g_free(follow_filter);
- return;
- }
-
/* Set the display filter entry accordingly */
filter_cm = (GtkWidget *)g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY);
filter_te = gtk_bin_get_child(GTK_BIN(filter_cm));
@@ -184,59 +162,26 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
"!(%s)", follow_filter);
}
- gtk_entry_set_text(GTK_ENTRY(filter_te), follow_filter);
-
- /* Run the display filter so it goes in effect - even if it's the
- same as the previous display filter. */
- main_filter_packets(&cfile, follow_filter, TRUE);
-
- /* Check whether we got any data written to the file. */
- if (empty_tcp_stream) {
+ /* data will be passed via tap callback*/
+ msg = register_tap_listener("tcp_follow", follow_info, follow_filter,
+ 0, NULL, tcp_queue_packet_data, NULL);
+ if (msg) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "The packets in the capture file for that stream have no data.");
- ws_close(tmp_fd);
- ws_unlink(follow_info->data_out_filename);
- g_free(follow_info->data_out_filename);
+ "Can't register tcp_follow tap: %s\n",
+ msg->str);
g_free(follow_info->filter_out_filter);
g_free(follow_info);
+ g_free(follow_filter);
return;
}
- /* Go back to the top of the file and read the first tcp_stream_chunk
- * to ensure that the IP addresses and port numbers in the drop-down
- * list are tied to the correct lines displayed by follow_read_stream()
- * later on (which also reads from this file). Close the file when
- * we're done.
- *
- * We read the data now, before we pop up a window, in case the
- * read fails. We use the data later.
- */
-
- rewind(data_out_file);
- nchars=fread(&sc, 1, sizeof(sc), data_out_file);
- if (nchars != sizeof(sc)) {
- if (ferror(data_out_file)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Could not read from temporary file %s: %s",
- follow_info->data_out_filename, g_strerror(errno));
- } else {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Short read from temporary file %s: expected %lu, got %lu",
- follow_info->data_out_filename,
- (unsigned long)sizeof(sc),
- (unsigned long)nchars);
- }
- ws_close(tmp_fd);
- ws_unlink(follow_info->data_out_filename);
- g_free(follow_info->data_out_filename);
- g_free(follow_info->filter_out_filter);
- g_free(follow_info);
- return;
- }
- fclose(data_out_file);
+ gtk_entry_set_text(GTK_ENTRY(filter_te), follow_filter);
+
+ /* Run the display filter so it goes in effect - even if it's the
+ same as the previous display filter. */
+ main_filter_packets(&cfile, follow_filter, TRUE);
- /* The data_out_filename file now has all the text that was in the
- session (this is dumped to file by the TCP dissector). */
+ remove_tap_listener(follow_info);
/* Stream to show */
follow_stats(&stats);
@@ -260,45 +205,38 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
port0 = (char*)tcp_port_to_display(NULL, stats.port[0]);
port1 = (char*)tcp_port_to_display(NULL, stats.port[1]);
- /* Host 0 --> Host 1 */
- if ((sc.src_port == stats.port[0]) &&
- ((stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[0], 16) == 0)) ||
- (!stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[0], 4) == 0)))) {
+ /* Both Stream Directions */
+ both_directions_string = g_strdup_printf("Entire conversation (%u bytes)", follow_info->bytes_written[0] + follow_info->bytes_written[1]);
+
+ if ((follow_info->client_port == stats.port[0]) &&
+ ((stats.is_ipv6 && (memcmp(follow_info->client_ip.data, stats.ip_address[0], 16) == 0)) ||
+ (!stats.is_ipv6 && (memcmp(follow_info->client_ip.data, stats.ip_address[0], 4) == 0)))) {
server_to_client_string =
g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
hostname0, port0,
hostname1, port1,
- stats.bytes_written[0]);
+ follow_info->bytes_written[0]);
+
+ client_to_server_string =
+ g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
+ hostname1, port1,
+ hostname0, port0,
+ follow_info->bytes_written[1]);
} else {
server_to_client_string =
g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
hostname1, port1,
- hostname0,port0,
- stats.bytes_written[0]);
- }
+ hostname0, port0,
+ follow_info->bytes_written[0]);
- /* Host 1 --> Host 0 */
- if ((sc.src_port == stats.port[1]) &&
- ((stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[1], 16) == 0)) ||
- (!stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[1], 4) == 0)))) {
client_to_server_string =
g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
hostname0, port0,
hostname1, port1,
- stats.bytes_written[1]);
- } else {
- client_to_server_string =
- g_strdup_printf("%s:%s " UTF8_RIGHTWARDS_ARROW " %s:%s (%u bytes)",
- hostname1, port1,
- hostname0, port0,
- stats.bytes_written[1]);
+ follow_info->bytes_written[1]);
}
- /* Both Stream Directions */
- both_directions_string = g_strdup_printf("Entire conversation (%u bytes)", stats.bytes_written[0] + stats.bytes_written[1]);
-
- g_snprintf(stream_window_title, 256, "Follow TCP Stream (%s)", follow_filter);
- follow_stream(stream_window_title, follow_info, both_directions_string,
+ follow_stream("Follow TCP Stream", follow_info, both_directions_string,
server_to_client_string, client_to_server_string);
/* Free the filter string, as we're done with it. */
@@ -309,8 +247,6 @@ follow_tcp_stream_cb(GtkWidget * w _U_, gpointer data _U_)
g_free(both_directions_string);
g_free(server_to_client_string);
g_free(client_to_server_string);
-
- data_out_file = NULL;
}
#define FLT_BUF_SIZE 1024
@@ -337,99 +273,49 @@ follow_read_tcp_stream(follow_info_t *follow_info,
follow_print_line_func follow_print,
void *arg)
{
- tcp_stream_chunk sc;
- size_t bcount;
- size_t bytes_read;
- int iplen;
- guint8 client_addr[MAX_IPADDR_LEN];
- guint16 client_port = 0;
- gboolean is_server;
- guint32 global_client_pos = 0, global_server_pos = 0;
- guint32 server_packet_count = 0;
- guint32 client_packet_count = 0;
- guint32 *global_pos;
- gboolean skip;
- char buffer[FLT_BUF_SIZE+1]; /* +1 to fix ws bug 1043 */
- size_t nchars;
- frs_return_t frs_return;
-
- iplen = (follow_info->is_ipv6) ? 16 : 4;
-
- data_out_file = ws_fopen(follow_info->data_out_filename, "rb");
- if (data_out_file == NULL) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Could not open temporary file %s: %s", follow_info->data_out_filename,
- g_strerror(errno));
- return FRS_OPEN_ERROR;
- }
-
- while ((nchars=fread(&sc, 1, sizeof(sc), data_out_file))) {
- if (nchars != sizeof(sc)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Short read from temporary file %s: expected %lu, got %lu",
- follow_info->data_out_filename,
- (unsigned long)sizeof(sc),
- (unsigned long)nchars);
- fclose(data_out_file);
- data_out_file = NULL;
- return FRS_READ_ERROR;
- }
- if (client_port == 0) {
- memcpy(client_addr, sc.src_addr, iplen);
- client_port = sc.src_port;
- }
+ guint32 global_client_pos = 0, global_server_pos = 0;
+ guint32 server_packet_count = 0;
+ guint32 client_packet_count = 0;
+ guint32 *global_pos;
+ gboolean skip;
+ GList* cur;
+ frs_return_t frs_return;
+ follow_record_t *follow_record;
+ char *buffer;
+
+
+ for (cur = follow_info->payload; cur; cur = g_list_next(cur)) {
+ follow_record = (follow_record_t *)cur->data;
skip = FALSE;
- if (memcmp(client_addr, sc.src_addr, iplen) == 0 &&
- client_port == sc.src_port) {
- is_server = FALSE;
- global_pos = &global_client_pos;
- if (follow_info->show_stream == FROM_SERVER) {
- skip = TRUE;
- }
- }
- else {
- is_server = TRUE;
+ if (!follow_record->is_server) {
+ global_pos = &global_client_pos;
+ if(follow_info->show_stream == FROM_SERVER) {
+ skip = TRUE;
+ }
+ } else {
global_pos = &global_server_pos;
if (follow_info->show_stream == FROM_CLIENT) {
skip = TRUE;
}
}
- bytes_read = 0;
- while (bytes_read < sc.dlen) {
- bcount = ((sc.dlen-bytes_read) < FLT_BUF_SIZE) ? (sc.dlen-bytes_read) : FLT_BUF_SIZE;
- nchars = fread(buffer, 1, bcount, data_out_file);
- if (nchars == 0)
- break;
- /* XXX - if we don't get "bcount" bytes, is that an error? */
- bytes_read += nchars;
-
- if (!skip) {
- frs_return = follow_show(follow_info, follow_print, buffer,
- nchars, is_server, arg, global_pos,
- &server_packet_count,
- &client_packet_count);
- if(frs_return == FRS_PRINT_ERROR) {
- fclose(data_out_file);
- data_out_file = NULL;
- return frs_return;
-
- }
- }
+ if (!skip) {
+ buffer = (char *)g_memdup(follow_record->data->data,
+ follow_record->data->len);
+
+ frs_return = follow_show(follow_info, follow_print,
+ buffer,
+ follow_record->data->len,
+ follow_record->is_server, arg,
+ global_pos,
+ &server_packet_count,
+ &client_packet_count);
+ g_free(buffer);
+ if(frs_return == FRS_PRINT_ERROR)
+ return frs_return;
}
}
- if (ferror(data_out_file)) {
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Error reading temporary file %s: %s", follow_info->data_out_filename,
- g_strerror(errno));
- fclose(data_out_file);
- data_out_file = NULL;
- return FRS_READ_ERROR;
- }
-
- fclose(data_out_file);
- data_out_file = NULL;
return FRS_OK;
}
diff --git a/ui/gtk/follow_udp.c b/ui/gtk/follow_udp.c
index 968fa5aeec..fa5f14ff40 100644
--- a/ui/gtk/follow_udp.c
+++ b/ui/gtk/follow_udp.c
@@ -104,6 +104,8 @@ follow_udp_stream_cb(GtkWidget *w _U_, gpointer data _U_)
return;
}
+ reset_stream_follow(UDP_STREAM);
+
follow_info = g_new0(follow_info_t, 1);
follow_info->follow_type = FOLLOW_UDP;
follow_info->read_stream = follow_read_udp_stream;
diff --git a/ui/qt/follow_stream_dialog.cpp b/ui/qt/follow_stream_dialog.cpp
index 175f8c04e7..058e70ab30 100644
--- a/ui/qt/follow_stream_dialog.cpp
+++ b/ui/qt/follow_stream_dialog.cpp
@@ -360,21 +360,15 @@ FollowStreamDialog::readStream()
switch(follow_type_) {
case FOLLOW_TCP :
- ret = readTcpStream();
- break;
-
case FOLLOW_UDP :
- ret = readUdpStream();
+ case FOLLOW_HTTP :
+ ret = readFollowStream();
break;
case FOLLOW_SSL :
ret = readSslStream();
break;
- case FOLLOW_HTTP :
- ret = readHttpStream();
- break;
-
default :
g_assert_not_reached();
ret = (frs_return_t)0;
@@ -384,6 +378,40 @@ FollowStreamDialog::readStream()
return ret;
}
+//Copy from ui/gtk/follow_tcp.c
+static gboolean
+tcp_queue_packet_data(void *tapdata, packet_info *pinfo,
+ epan_dissect_t *, const void *data)
+{
+ follow_record_t *follow_record;
+ follow_info_t *follow_info = (follow_info_t *)tapdata;
+ tvbuff_t *next_tvb = (tvbuff_t *)data;
+
+ follow_record = g_new(follow_record_t,1);
+
+ follow_record->data = g_byte_array_sized_new(tvb_captured_length(next_tvb));
+ follow_record->data = g_byte_array_append(follow_record->data,
+ tvb_get_ptr(next_tvb, 0, -1),
+ tvb_captured_length(next_tvb));
+ follow_record->packet_num = pinfo->fd->num;
+
+ if (follow_info->client_port == 0) {
+ follow_info->client_port = pinfo->srcport;
+ copy_address(&follow_info->client_ip, &pinfo->src);
+ }
+
+ if (addresses_equal(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport)
+ follow_record->is_server = FALSE;
+ else
+ follow_record->is_server = TRUE;
+
+ /* update stream counter */
+ follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
+
+ follow_info->payload = g_list_append(follow_info->payload, follow_record);
+ return FALSE;
+}
+
//Copy from ui/gtk/follow_udp.c
static gboolean
udp_queue_packet_data(void *tapdata, packet_info *pinfo,
@@ -565,52 +593,6 @@ FollowStreamDialog::readSslStream()
return FRS_OK;
}
-/* XXX - Currently the same as readUdpStream() */
-frs_return_t
-FollowStreamDialog::readHttpStream()
-{
- guint32 global_client_pos = 0, global_server_pos = 0;
- guint32 *global_pos;
- gboolean skip;
- GList* cur;
- frs_return_t frs_return;
- follow_record_t *follow_record;
- char *buffer;
-
- for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) {
- follow_record = (follow_record_t *)cur->data;
- skip = FALSE;
- if (!follow_record->is_server) {
- global_pos = &global_client_pos;
- if(follow_info_.show_stream == FROM_SERVER) {
- skip = TRUE;
- }
- } else {
- global_pos = &global_server_pos;
- if (follow_info_.show_stream == FROM_CLIENT) {
- skip = TRUE;
- }
- }
-
- if (!skip) {
- buffer = (char *)g_memdup(follow_record->data->data,
- follow_record->data->len);
-
- frs_return = showBuffer(
- buffer,
- follow_record->data->len,
- follow_record->is_server,
- follow_record->packet_num,
- global_pos);
- g_free(buffer);
- if(frs_return == FRS_PRINT_ERROR)
- return frs_return;
- }
- }
-
- return FRS_OK;
-}
-
void
FollowStreamDialog::followStream()
{
@@ -946,8 +928,6 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
QString client_to_server_string;
QString both_directions_string;
follow_stats_t stats;
- tcp_stream_chunk sc;
- size_t nchars;
gboolean is_tcp = FALSE, is_udp = FALSE, is_http = FALSE;
resetStream();
@@ -1006,10 +986,10 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
case FOLLOW_HTTP:
/* Create a new filter that matches all packets in the TCP stream,
and set the display filter entry accordingly */
- reset_tcp_reassembly();
+ reset_stream_follow(TCP_STREAM);
break;
case FOLLOW_UDP:
- reset_udp_follow();
+ reset_stream_follow(UDP_STREAM);
break;
}
@@ -1042,7 +1022,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
return false;
}
- if (follow_type_ == FOLLOW_TCP || follow_type_ == FOLLOW_SSL)
+ if (follow_type_ == FOLLOW_SSL)
{
/* Create a temporary file into which to dump the reassembled data
from the TCP stream, and set "data_out_file" to refer to it, so
@@ -1090,6 +1070,13 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
{
case FOLLOW_TCP:
{
+ /* data will be passed via tap callback*/
+ if (!registerTapListener("tcp_follow", &follow_info_,
+ follow_filter.toUtf8().constData(),
+ 0, NULL, tcp_queue_packet_data, NULL)) {
+ return false;
+ }
+
int stream_count = get_tcp_stream_count();
ui->streamNumberSpinBox->blockSignals(true);
ui->streamNumberSpinBox->setMaximum(stream_count-1);
@@ -1147,8 +1134,6 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
switch (follow_type_)
{
case FOLLOW_TCP:
-
- break;
case FOLLOW_UDP:
case FOLLOW_SSL:
case FOLLOW_HTTP:
@@ -1156,57 +1141,6 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
break;
}
- if (follow_type_ == FOLLOW_TCP)
- {
- /* Check whether we got any data written to the file. */
- if (empty_tcp_stream) {
- QMessageBox::warning(this, "Error",
- "The packets in the capture file for that stream have no data.");
- //ws_close(tmp_fd);
- ws_unlink(data_out_filename_.toUtf8().constData());
- data_out_filename_.clear();
- updateWidgets(false);
- endRetapPackets();
- return false;
- }
-
- /* Go back to the top of the file and read the first tcp_stream_chunk
- * to ensure that the IP addresses and port numbers in the drop-down
- * list are tied to the correct lines displayed by follow_read_stream()
- * later on (which also reads from this file). Close the file when
- * we're done.
- *
- * We read the data now, before we pop up a window, in case the
- * read fails. We use the data later.
- */
-
- rewind(data_out_file);
- nchars=fread(&sc, 1, sizeof(sc), data_out_file);
- if (nchars != sizeof(sc)) {
- if (ferror(data_out_file)) {
- QMessageBox::warning(this, "Error",
- QString(tr("Could not read from temporary file %1: %2"))
- .arg(data_out_filename_)
- .arg(g_strerror(errno)));
- } else {
- QMessageBox::warning(this, "Error",
- QString(tr("Short read from temporary file %1: expected %2, got %3"))
- .arg(data_out_filename_)
- .arg((unsigned long)sizeof(sc))
- .arg((unsigned long)nchars));
-
- }
- //ws_close(tmp_fd);
- ws_unlink(data_out_filename_.toUtf8().constData());
- data_out_filename_.clear();
- updateWidgets(false);
- endRetapPackets();
- return false;
- }
- fclose(data_out_file);
- data_out_file = NULL;
- }
-
/* Stream to show */
follow_stats(&stats);
@@ -1228,6 +1162,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
{
case FOLLOW_TCP:
case FOLLOW_HTTP:
+ case FOLLOW_SSL:
port0 = tcp_port_to_display(NULL, stats.port[0]);
port1 = tcp_port_to_display(NULL, stats.port[1]);
break;
@@ -1235,104 +1170,48 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index)
port0 = udp_port_to_display(NULL, stats.port[0]);
port1 = udp_port_to_display(NULL, stats.port[1]);
break;
- case FOLLOW_SSL:
- port0 = tcp_port_to_display(NULL, stats.port[0]);
- port1 = tcp_port_to_display(NULL, stats.port[1]);
- break;
}
follow_info_.is_ipv6 = stats.is_ipv6;
- if (follow_type_ == FOLLOW_TCP)
- {
- /* Host 0 --> Host 1 */
- if ((sc.src_port == stats.port[0]) &&
- ((stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[0], 16) == 0)) ||
- (!stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[0], 4) == 0)))) {
- server_to_client_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname0).arg(port0)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname1).arg(port1)
- .arg(gchar_free_to_qstring(format_size(
- stats.bytes_written[0],
- format_size_unit_bytes|format_size_prefix_si)));
- } else {
- server_to_client_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname1).arg(port1)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname0).arg(port0)
- .arg(gchar_free_to_qstring(format_size(
- stats.bytes_written[0],
- format_size_unit_bytes|format_size_prefix_si)));
- }
-
- /* Host 1 --> Host 0 */
- if ((sc.src_port == stats.port[1]) &&
- ((stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[1], 16) == 0)) ||
- (!stats.is_ipv6 && (memcmp(sc.src_addr, stats.ip_address[1], 4) == 0)))) {
- client_to_server_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname0).arg(port0)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname1).arg(port1)
- .arg(gchar_free_to_qstring(format_size(
- stats.bytes_written[1],
- format_size_unit_bytes|format_size_prefix_si)));
- } else {
- client_to_server_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname1).arg(port1)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname0).arg(port0)
- .arg(gchar_free_to_qstring(format_size(
- stats.bytes_written[1],
- format_size_unit_bytes|format_size_prefix_si)));
- }
-
- }
- else
- {
- if ((follow_info_.client_port == stats.port[0]) &&
- ((stats.is_ipv6 && (memcmp(follow_info_.client_ip.data, stats.ip_address[0], 16) == 0)) ||
- (!stats.is_ipv6 && (memcmp(follow_info_.client_ip.data, stats.ip_address[0], 4) == 0)))) {
- server_to_client_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname0).arg(port0)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname1).arg(port1)
- .arg(gchar_free_to_qstring(format_size(
- follow_info_.bytes_written[0],
- format_size_unit_bytes|format_size_prefix_si)));
-
- client_to_server_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname1).arg(port1)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname0).arg(port0)
- .arg(gchar_free_to_qstring(format_size(
- follow_info_.bytes_written[1],
- format_size_unit_bytes|format_size_prefix_si)));
- } else {
- server_to_client_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname1).arg(port1)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname0).arg(port0)
- .arg(gchar_free_to_qstring(format_size(
- follow_info_.bytes_written[0],
- format_size_unit_bytes|format_size_prefix_si)));
-
- client_to_server_string =
- QString("%1:%2 %3 %4:%5 (%6)")
- .arg(hostname0).arg(port0)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(hostname1).arg(port1)
- .arg(gchar_free_to_qstring(format_size(
- follow_info_.bytes_written[1],
- format_size_unit_bytes|format_size_prefix_si)));
- }
+ if ((follow_info_.client_port == stats.port[0]) &&
+ ((stats.is_ipv6 && (memcmp(follow_info_.client_ip.data, stats.ip_address[0], 16) == 0)) ||
+ (!stats.is_ipv6 && (memcmp(follow_info_.client_ip.data, stats.ip_address[0], 4) == 0)))) {
+ server_to_client_string =
+ QString("%1:%2 %3 %4:%5 (%6)")
+ .arg(hostname0).arg(port0)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(hostname1).arg(port1)
+ .arg(gchar_free_to_qstring(format_size(
+ follow_info_.bytes_written[0],
+ format_size_unit_bytes|format_size_prefix_si)));
+
+ client_to_server_string =
+ QString("%1:%2 %3 %4:%5 (%6)")
+ .arg(hostname1).arg(port1)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(hostname0).arg(port0)
+ .arg(gchar_free_to_qstring(format_size(
+ follow_info_.bytes_written[1],
+ format_size_unit_bytes|format_size_prefix_si)));
+ } else {
+ server_to_client_string =
+ QString("%1:%2 %3 %4:%5 (%6)")
+ .arg(hostname1).arg(port1)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(hostname0).arg(port0)
+ .arg(gchar_free_to_qstring(format_size(
+ follow_info_.bytes_written[0],
+ format_size_unit_bytes|format_size_prefix_si)));
+
+ client_to_server_string =
+ QString("%1:%2 %3 %4:%5 (%6)")
+ .arg(hostname0).arg(port0)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(hostname1).arg(port1)
+ .arg(gchar_free_to_qstring(format_size(
+ follow_info_.bytes_written[1],
+ format_size_unit_bytes|format_size_prefix_si)));
}
wmem_free(NULL, port0);
@@ -1417,119 +1296,7 @@ void FollowStreamDialog::captureFileClosing()
* correctly but get extra blank lines very other line when printed.
*/
frs_return_t
-FollowStreamDialog::readTcpStream()
-{
- FILE *data_out_fp;
- tcp_stream_chunk sc;
- size_t bcount;
- size_t bytes_read;
- int iplen;
- guint8 client_addr[MAX_IPADDR_LEN];
- guint16 client_port = 0;
- gboolean is_server;
- guint32 global_client_pos = 0, global_server_pos = 0;
- guint32 *global_pos;
- gboolean skip;
- char buffer[FLT_BUF_SIZE+1]; /* +1 to fix ws bug 1043 */
- size_t nchars;
- frs_return_t frs_return;
-
- iplen = (follow_info_.is_ipv6) ? 16 : 4;
-
- data_out_fp = ws_fopen(data_out_filename_.toUtf8().constData(), "rb");
- if (data_out_fp == NULL) {
- QMessageBox::critical(this, "Error",
- "Could not open temporary file %1: %2", data_out_filename_,
- g_strerror(errno));
- return FRS_OPEN_ERROR;
- }
-
- while ((nchars=fread(&sc, 1, sizeof(sc), data_out_fp))) {
- if (nchars != sizeof(sc)) {
- QMessageBox::critical(this, "Error",
- QString(tr("Short read from temporary file %1: expected %2, got %3"))
- .arg(data_out_filename_)
- .arg(sizeof(sc))
- .arg(nchars));
- fclose(data_out_fp);
- data_out_fp = NULL;
- return FRS_READ_ERROR;
- }
- if (client_port == 0) {
- memcpy(client_addr, sc.src_addr, iplen);
- client_port = sc.src_port;
- }
- skip = FALSE;
- if (memcmp(client_addr, sc.src_addr, iplen) == 0 &&
- client_port == sc.src_port) {
- is_server = FALSE;
- global_pos = &global_client_pos;
- if (follow_info_.show_stream == FROM_SERVER) {
- skip = TRUE;
- }
- } else {
- is_server = TRUE;
- global_pos = &global_server_pos;
- if (follow_info_.show_stream == FROM_CLIENT) {
- skip = TRUE;
- }
- }
-
- bytes_read = 0;
- while (bytes_read < sc.dlen) {
- bcount = ((sc.dlen-bytes_read) < FLT_BUF_SIZE) ? (sc.dlen-bytes_read) : FLT_BUF_SIZE;
- nchars = fread(buffer, 1, bcount, data_out_fp);
- if (nchars == 0)
- break;
- /* XXX - if we don't get "bcount" bytes, is that an error? */
- bytes_read += nchars;
-
- if (!skip)
- {
- frs_return = showBuffer(buffer,
- nchars, is_server, sc.packet_num, global_pos);
- if(frs_return == FRS_PRINT_ERROR) {
- fclose(data_out_fp);
- data_out_fp = NULL;
- return frs_return;
- }
-
- }
- }
- }
-
- if (ferror(data_out_fp)) {
- QMessageBox::critical(this, tr("Error reading temporary file"),
- QString("%1: %2").arg(data_out_filename_).arg(g_strerror(errno)));
- fclose(data_out_fp);
- data_out_fp = NULL;
- return FRS_READ_ERROR;
- }
-
- fclose(data_out_fp);
- data_out_fp = NULL;
- return FRS_OK;
-}
-
-/*
- * XXX - the routine pointed to by "print_line_fcn_p" doesn't get handed lines,
- * it gets handed bufferfuls. That's fine for "follow_write_raw()"
- * and "follow_add_to_gtk_text()", but, as "follow_print_text()" calls
- * the "print_line()" routine from "print.c", and as that routine might
- * genuinely expect to be handed a line (if, for example, it's using
- * some OS or desktop environment's printing API, and that API expects
- * to be handed lines), "follow_print_text()" should probably accumulate
- * lines in a buffer and hand them "print_line()". (If there's a
- * complete line in a buffer - i.e., there's nothing of the line in
- * the previous buffer or the next buffer - it can just hand that to
- * "print_line()" after filtering out non-printables, as an
- * optimization.)
- *
- * This might or might not be the reason why C arrays display
- * correctly but get extra blank lines very other line when printed.
- */
-frs_return_t
-FollowStreamDialog::readUdpStream()
+FollowStreamDialog::readFollowStream()
{
guint32 global_client_pos = 0, global_server_pos = 0;
guint32 *global_pos;
diff --git a/ui/qt/follow_stream_dialog.h b/ui/qt/follow_stream_dialog.h
index 2d82a83ea7..da0457175c 100644
--- a/ui/qt/follow_stream_dialog.h
+++ b/ui/qt/follow_stream_dialog.h
@@ -110,10 +110,8 @@ private:
guint32 packet_num, guint32 *global_pos);
frs_return_t readStream();
- frs_return_t readTcpStream();
- frs_return_t readUdpStream();
+ frs_return_t readFollowStream();
frs_return_t readSslStream();
- frs_return_t readHttpStream();
void followStream();
void addText(QString text, gboolean is_from_server, guint32 packet_num);