<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>
#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;
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 */
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");
}
#include <glib.h>
#include <epan/packet.h>
+#include <epan/ipproto.h>
#include "follow.h"
#define MAX_IPADDR_LEN 16
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;
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;
}
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)",
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)",
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;
}
! (
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;
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 ) {
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
follow_ssl.c \
follow_stream.c \
follow_tcp.c \
+ follow_udp.c \
font_utils.c \
goto_dlg.c \
graph_analysis.c \
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;
}
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;
remove_tap_listener(follow_info);
/* Stream to show */
- follow_tcp_stats(&stats);
+ follow_stats(&stats);
if (stats.is_ipv6) {
struct e_in6_addr ipaddr;
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;
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) {
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);
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);
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;
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);
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;
follow_destroy_cb(GtkWidget *w, gpointer data _U_)
{
follow_info_t *follow_info;
+ follow_record_t *follow_record;
GList *cur;
int i;
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;
}
/* Type of follow we are doing */
typedef enum {
FOLLOW_TCP,
- FOLLOW_SSL
+ FOLLOW_SSL,
+ FOLLOW_UDP
} follow_type_t;
/* Show Stream */
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;
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];
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);
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;
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;
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)) {
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,
#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"
#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"
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),
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),
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),
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",