diff options
-rw-r--r-- | debian/libwireshark0.symbols | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-tcp.c | 55 | ||||
-rw-r--r-- | epan/follow.c | 366 | ||||
-rw-r--r-- | epan/follow.h | 7 | ||||
-rw-r--r-- | ui/cli/tap-follow.c | 15 | ||||
-rw-r--r-- | ui/gtk/follow_http.c | 2 | ||||
-rw-r--r-- | ui/gtk/follow_ssl.c | 2 | ||||
-rw-r--r-- | ui/gtk/follow_tcp.c | 322 | ||||
-rw-r--r-- | ui/gtk/follow_udp.c | 2 | ||||
-rw-r--r-- | ui/qt/follow_stream_dialog.cpp | 405 | ||||
-rw-r--r-- | ui/qt/follow_stream_dialog.h | 4 |
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); |