- Future improve/clean up the now generic follow stream code

- Add "Follow UDP Stream" feature


svn path=/trunk/; revision=23346
This commit is contained in:
Stephen Fisher 2007-11-03 04:45:35 +00:00
parent fafa0a1c06
commit 700d8194b8
11 changed files with 115 additions and 36 deletions

View File

@ -1350,6 +1350,14 @@
<xref linkend="ChAdvFollowTCPSection"/>
</para></entry>
</row>
<row>
<entry><command>Follow UDP Stream</command></entry>
<entry></entry>
<entry><para>
Same functionality as "Follow TCP Stream" but
for UDP streams.
</para></entry>
</row>
<row>
<entry><command>Follow SSL Stream</command></entry>
<entry></entry>

View File

@ -49,6 +49,7 @@
#include <epan/tap.h>
static int udp_tap = -1;
static int udp_follow_tap = -1;
static int proto_udp = -1;
static int proto_udplite = -1;
@ -110,8 +111,14 @@ decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
if (len > reported_len)
len = reported_len;
}
next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
/* If the user has a "Follow UDP Stream" window loading, pass a pointer
* to the payload tvb through the tap system. */
if(have_tap_listener(udp_follow_tap))
tap_queue_packet(udp_follow_tap, pinfo, next_tvb);
/* determine if this packet is part of a conversation and call dissector */
/* for the conversation if available */
@ -532,4 +539,5 @@ proto_reg_handoff_udp(void)
dissector_add("ip.proto", IP_PROTO_UDPLITE, udplite_handle);
data_handle = find_dissector("data");
udp_tap = register_tap("udp");
udp_follow_tap = register_tap("udp_follow");
}

View File

@ -37,6 +37,7 @@
#include <glib.h>
#include <epan/packet.h>
#include <epan/ipproto.h>
#include "follow.h"
#define MAX_IPADDR_LEN 16
@ -55,7 +56,7 @@ gboolean empty_tcp_stream;
gboolean incomplete_tcp_stream;
static guint8 ip_address[2][MAX_IPADDR_LEN];
static guint tcp_port[2];
static guint port[2];
static guint bytes_written[2];
static gboolean is_ipv6 = FALSE;
@ -63,13 +64,13 @@ static int check_fragments( int, tcp_stream_chunk * );
static void write_packet_data( int, tcp_stream_chunk *, const char * );
void
follow_tcp_stats(follow_tcp_stats_t* stats)
follow_stats(follow_stats_t* stats)
{
int i;
for (i = 0; i < 2 ; i++) {
memcpy(stats->ip_address[i], ip_address[i], MAX_IPADDR_LEN);
stats->tcp_port[i] = tcp_port[i];
stats->port[i] = port[i];
stats->bytes_written[i] = bytes_written[i];
stats->is_ipv6 = is_ipv6;
}
@ -84,7 +85,7 @@ build_follow_filter( packet_info *pi ) {
char* buf;
int len;
if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
&& pi->ipproto == 6 ) {
&& pi->ipproto == IP_PROTO_TCP ) {
/* TCP over IPv4 */
buf = g_strdup_printf(
"(ip.addr eq %s and ip.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
@ -94,8 +95,19 @@ build_follow_filter( packet_info *pi ) {
len = 4;
is_ipv6 = FALSE;
}
else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
&& pi->ipproto == IP_PROTO_UDP ) {
/* UDP over IPv4 */
buf = g_strdup_printf(
"(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
ip_to_str( pi->net_src.data),
ip_to_str( pi->net_dst.data),
pi->srcport, pi->destport );
len = 4;
is_ipv6 = FALSE;
}
else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
&& pi->ipproto == 6 ) {
&& pi->ipproto == IP_PROTO_TCP ) {
/* TCP over IPv6 */
buf = g_strdup_printf(
"(ipv6.addr eq %s and ipv6.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
@ -105,13 +117,24 @@ build_follow_filter( packet_info *pi ) {
len = 16;
is_ipv6 = TRUE;
}
else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
&& pi->ipproto == IP_PROTO_UDP ) {
/* UDP over IPv6 */
buf = g_strdup_printf(
"(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
pi->srcport, pi->destport );
len = 16;
is_ipv6 = TRUE;
}
else {
return NULL;
}
memcpy(ip_address[0], pi->net_src.data, len);
memcpy(ip_address[1], pi->net_dst.data, len);
tcp_port[0] = pi->srcport;
tcp_port[1] = pi->destport;
port[0] = pi->srcport;
port[1] = pi->destport;
return buf;
}
@ -154,14 +177,14 @@ reassemble_tcp( gulong sequence, gulong length, const char* data,
! (
memcmp(srcx, ip_address[0], len) == 0 &&
memcmp(dstx, ip_address[1], len) == 0 &&
srcport == tcp_port[0] &&
dstport == tcp_port[1]
srcport == port[0] &&
dstport == port[1]
) &&
! (
memcmp(srcx, ip_address[1], len) == 0 &&
memcmp(dstx, ip_address[0], len) == 0 &&
srcport == tcp_port[1] &&
dstport == tcp_port[0]
srcport == port[1] &&
dstport == port[0]
)
)
return;
@ -317,7 +340,7 @@ reset_tcp_reassembly(void)
memset(src_addr[i], '\0', MAX_IPADDR_LEN);
src_port[i] = 0;
memset(ip_address[i], '\0', MAX_IPADDR_LEN);
tcp_port[i] = 0;
port[i] = 0;
bytes_written[i] = 0;
current = frags[i];
while( current ) {

View File

@ -48,11 +48,11 @@ void reset_tcp_reassembly( void );
typedef struct {
guint8 ip_address[2][MAX_IPADDR_LEN];
guint32 tcp_port[2];
guint32 port[2];
unsigned int bytes_written[2];
gboolean is_ipv6;
} follow_tcp_stats_t;
} follow_stats_t;
void follow_tcp_stats(follow_tcp_stats_t* stats);
void follow_stats(follow_stats_t* stats);
#endif

View File

@ -73,6 +73,7 @@ WIRESHARK_GTK_SRC = \
follow_ssl.c \
follow_stream.c \
follow_tcp.c \
follow_udp.c \
font_utils.c \
goto_dlg.c \
graph_analysis.c \

View File

@ -125,8 +125,8 @@ ssl_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_
p += appl_data->plain_data.data_len;
appl_data = appl_data->next;
} while (appl_data);
follow_info->ssl_decrypted_data = g_list_append(
follow_info->ssl_decrypted_data,rec);
follow_info->payload = g_list_append(
follow_info->payload,rec);
return 0;
}
@ -150,7 +150,7 @@ follow_ssl_stream_cb(GtkWidget * w, gpointer data _U_)
gchar *server_to_client_string = NULL;
gchar *client_to_server_string = NULL;
gchar *both_directions_string = NULL;
follow_tcp_stats_t stats;
follow_stats_t stats;
follow_info_t *follow_info;
GString* msg;
@ -223,7 +223,7 @@ follow_ssl_stream_cb(GtkWidget * w, gpointer data _U_)
remove_tap_listener(follow_info);
/* Stream to show */
follow_tcp_stats(&stats);
follow_stats(&stats);
if (stats.is_ipv6) {
struct e_in6_addr ipaddr;
@ -239,8 +239,8 @@ follow_ssl_stream_cb(GtkWidget * w, gpointer data _U_)
hostname1 = get_hostname(ipaddr);
}
port0 = get_tcp_port(stats.tcp_port[0]);
port1 = get_tcp_port(stats.tcp_port[1]);
port0 = get_tcp_port(stats.port[0]);
port1 = get_tcp_port(stats.port[1]);
follow_info->is_ipv6 = stats.is_ipv6;
@ -302,7 +302,7 @@ follow_read_ssl_stream(follow_info_t *follow_info,
iplen = (follow_info->is_ipv6) ? 16 : 4;
for (cur = follow_info->ssl_decrypted_data; cur; cur = g_list_next(cur)) {
for (cur = follow_info->payload; cur; cur = g_list_next(cur)) {
SslDecryptedRecord* rec = cur->data;
skip = FALSE;
if (!rec->is_server) {
@ -320,7 +320,7 @@ follow_read_ssl_stream(follow_info_t *follow_info,
if (!skip) {
size_t nchars = rec->data.data_len;
gchar *buffer = g_strndup(rec->data.data, nchars);
gchar *buffer = g_memdup(rec->data.data, nchars);
frs_return = follow_show(follow_info, print_line, buffer, nchars,
rec->is_server, arg, global_pos);

View File

@ -81,6 +81,9 @@ follow_read_stream(follow_info_t *follow_info,
case FOLLOW_TCP :
return follow_read_tcp_stream(follow_info, print_line, arg);
case FOLLOW_UDP :
return follow_read_udp_stream(follow_info, print_line, arg);
case FOLLOW_SSL :
return follow_read_ssl_stream(follow_info, print_line, arg);
@ -542,7 +545,7 @@ follow_save_as_cmd_cb(GtkWidget *w _U_, gpointer data)
return;
}
new_win = file_selection_new("Wireshark: Save TCP Follow Stream As",
new_win = file_selection_new("Wireshark: Save Follow Stream As",
FILE_SELECTION_SAVE);
follow_info->follow_save_as_w = new_win;
@ -728,7 +731,7 @@ follow_stream(gchar *title, follow_info_t *follow_info,
GtkWidget *stream_fr, *stream_vb;
GtkWidget *stream_om, *stream_menu, *stream_mi;
GtkTooltips *tooltips;
follow_tcp_stats_t stats;
follow_stats_t stats;
streamwindow = dlg_window_new(title);
@ -803,7 +806,7 @@ follow_stream(gchar *title, follow_info_t *follow_info,
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
/* Stream to show */
follow_tcp_stats(&stats);
follow_stats(&stats);
follow_info->is_ipv6 = stats.is_ipv6;
@ -947,6 +950,7 @@ static void
follow_destroy_cb(GtkWidget *w, gpointer data _U_)
{
follow_info_t *follow_info;
follow_record_t *follow_record;
GList *cur;
int i;
@ -955,22 +959,35 @@ follow_destroy_cb(GtkWidget *w, gpointer data _U_)
switch(follow_info->follow_type) {
case FOLLOW_TCP :
i = unlink(follow_info->data_out_filename);
if(i != 0) {
g_warning("Follow: Couldn't remove temporary file: \"%s\", errno: %s (%u)", follow_info->data_out_filename, strerror(errno), errno);
}
break;
case FOLLOW_UDP :
for(cur = follow_info->payload; cur; cur = g_list_next(cur))
if(cur->data) {
follow_record = cur->data;
if(follow_record->data)
g_byte_array_free(follow_record->data,
TRUE);
g_free(follow_record);
}
g_list_free(follow_info->payload);
break;
case FOLLOW_SSL :
/* free decrypted data list*/
for (cur = follow_info->ssl_decrypted_data; cur; cur = g_list_next(cur))
for (cur = follow_info->payload; cur; cur = g_list_next(cur))
if (cur->data)
{
g_free(cur->data);
cur->data = NULL;
}
g_list_free (follow_info->ssl_decrypted_data);
g_list_free (follow_info->payload);
break;
}

View File

@ -32,7 +32,8 @@
/* Type of follow we are doing */
typedef enum {
FOLLOW_TCP,
FOLLOW_SSL
FOLLOW_SSL,
FOLLOW_UDP
} follow_type_t;
/* Show Stream */
@ -58,6 +59,11 @@ typedef enum {
FRS_PRINT_ERROR
} frs_return_t;
typedef struct {
gboolean is_server;
GByteArray *data;
} follow_record_t;
typedef struct {
follow_type_t follow_type;
show_stream_t show_stream;
@ -77,7 +83,7 @@ typedef struct {
char *filter_out_filter;
GtkWidget *filter_te;
GtkWidget *streamwindow;
GList *ssl_decrypted_data;
GList *payload;
guint bytes_written[2];
guint client_port;
char client_ip[MAX_IPADDR_LEN];
@ -117,4 +123,5 @@ frs_return_t follow_show(follow_info_t *follow_info,
void *arg, guint32 *global_pos);
frs_return_t follow_read_tcp_stream(follow_info_t *follow_info, gboolean (*print_line)(char *, size_t, gboolean, void *), void *arg);
frs_return_t follow_read_udp_stream(follow_info_t *follow_info, gboolean (*print_line)(char *, size_t, gboolean, void *), void *arg);
frs_return_t follow_read_ssl_stream(follow_info_t *follow_info, gboolean (*print_line)(char *, size_t, gboolean, void *), void *arg);

View File

@ -111,7 +111,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
gchar *server_to_client_string = NULL;
gchar *client_to_server_string = NULL;
gchar *both_directions_string = NULL;
follow_tcp_stats_t stats;
follow_stats_t stats;
follow_info_t *follow_info;
tcp_stream_chunk sc;
size_t nchars;
@ -240,7 +240,7 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
session (this is dumped to file by the TCP dissector). */
/* Stream to show */
follow_tcp_stats(&stats);
follow_stats(&stats);
if (stats.is_ipv6) {
struct e_in6_addr ipaddr;
@ -258,8 +258,8 @@ follow_tcp_stream_cb(GtkWidget * w, gpointer data _U_)
follow_info->is_ipv6 = stats.is_ipv6;
port0 = get_tcp_port(stats.tcp_port[0]);
port1 = get_tcp_port(stats.tcp_port[1]);
port0 = get_tcp_port(stats.port[0]);
port1 = get_tcp_port(stats.port[1]);
/* Host 0 --> Host 1 */
if(sc.src_port == strtol(port0, NULL, 10)) {

View File

@ -4750,6 +4750,8 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
filter_te);
set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
filter_te);
set_menu_object_data("/Analyze/Follow UDP Stream", E_DFILTER_TE_KEY,
filter_te);
set_menu_object_data("/Analyze/Follow SSL Stream", E_DFILTER_TE_KEY,
filter_te);
set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,

View File

@ -56,6 +56,8 @@
#include "packet_win.h"
#include "print.h"
#include "follow_tcp.h"
#include "follow_udp.h"
#include "follow_ssl.h"
#include "decode_as_dlg.h"
#include "help_dlg.h"
#include "supported_protos_dlg.h"
@ -79,7 +81,6 @@
#include "simple_dialog.h"
#include "packet_history.h"
#include "color_filters.h"
#include "follow_ssl.h"
#include "sctp_stat.h"
#include "firewall_dlg.h"
#include "u3.h"
@ -622,6 +623,8 @@ static GtkItemFactoryEntry menu_items[] =
ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
ITEM_FACTORY_ENTRY("/Analyze/_Follow TCP Stream", NULL,
follow_tcp_stream_cb, 0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Analyze/_Follow UDP Stream", NULL,
follow_udp_stream_cb, 0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Analyze/_Follow SSL Stream", NULL,
follow_ssl_stream_cb, 0, NULL, NULL),
ITEM_FACTORY_ENTRY("/_Statistics", NULL, NULL, 0, "<Branch>", NULL),
@ -721,6 +724,8 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_tcp_stream_cb,
0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Follow UDP Stream", NULL, follow_udp_stream_cb,
0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Follow SSL Stream", NULL, follow_ssl_stream_cb,
0, NULL, NULL),
@ -792,6 +797,8 @@ static GtkItemFactoryEntry tree_view_menu_items[] =
ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_tcp_stream_cb,
0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Follow UDP Stream", NULL, follow_udp_stream_cb,
0, NULL, NULL),
ITEM_FACTORY_ENTRY("/Follow SSL Stream", NULL, follow_ssl_stream_cb,
0, NULL, NULL),
@ -2465,6 +2472,12 @@ set_menus_for_selected_packet(capture_file *cf)
cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
cf->current_frame != NULL ? is_ssl : FALSE);
set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",