forked from osmocom/wireshark
- 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:
parent
fafa0a1c06
commit
700d8194b8
|
@ -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>
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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,
|
||||
|
|
15
gtk/menu.c
15
gtk/menu.c
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue