diff options
author | Pascal Quantin <pascal.quantin@gmail.com> | 2014-12-27 23:15:41 +0100 |
---|---|---|
committer | Pascal Quantin <pascal.quantin@gmail.com> | 2014-12-29 22:17:47 +0000 |
commit | 0d414e5d7fc6d466974bbc935c3543cb8f840f6c (patch) | |
tree | 4a5997891f437da623984be32bdd6bf04c697e8a /epan/follow.c | |
parent | 0905202c4e365873f65ffc3c9bcbd6681645404d (diff) |
Add ability to follow UDP stream by index
-z "follow,udp" tshark cli command now supports a stream index
It is now possible to select the UDP stream displayed in Qt GUI (like for TCP)
Change-Id: Ia367f36ea4f60db0fddb997a7e0903c09e172f2d
Reviewed-on: https://code.wireshark.org/review/6083
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Diffstat (limited to 'epan/follow.c')
-rw-r--r-- | epan/follow.c | 141 |
1 files changed, 90 insertions, 51 deletions
diff --git a/epan/follow.c b/epan/follow.c index 4b894393d9..61f73b596f 100644 --- a/epan/follow.c +++ b/epan/follow.c @@ -36,8 +36,10 @@ #include <epan/to_str.h> #include <epan/emem.h> #include <epan/dissectors/packet-tcp.h> +#include <epan/dissectors/packet-udp.h> #include "follow.h" #include <epan/conversation.h> +#include <epan/tap.h> #define MAX_IPADDR_LEN 16 @@ -55,7 +57,10 @@ FILE* data_out_file = NULL; gboolean empty_tcp_stream; gboolean incomplete_tcp_stream; -static guint32 tcp_stream_to_follow = 0; +static guint32 stream_to_follow[MAX_STREAM] = {0}; +static gboolean find_addr[MAX_STREAM] = {FALSE}; +static gboolean find_index[MAX_STREAM] = {FALSE}; +static address tcp_addr[2]; static guint8 ip_address[2][MAX_IPADDR_LEN]; static guint port[2]; static guint bytes_written[2]; @@ -87,6 +92,7 @@ build_follow_conv_filter( packet_info *pi ) { int len; conversation_t *conv=NULL; struct tcp_analysis *tcpd; + struct udp_analysis *udpd; wmem_list_frame_t* protos; int proto_id; const char* proto_name; @@ -114,11 +120,11 @@ build_follow_conv_filter( packet_info *pi ) { (pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6)) && is_tcp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype, pi->srcport, pi->destport, 0)) != NULL ) { - /* TCP over IPv4 */ + /* TCP over IPv4/6 */ tcpd=get_tcp_conversation_data(conv, pi); if (tcpd) { buf = g_strdup_printf("tcp.stream eq %d", tcpd->stream); - tcp_stream_to_follow = tcpd->stream; + stream_to_follow[TCP_STREAM] = tcpd->stream; if (pi->net_src.type == AT_IPv4) { len = 4; is_ipv6 = FALSE; @@ -130,27 +136,25 @@ build_follow_conv_filter( packet_info *pi ) { return NULL; } } - else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4 - && is_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)", - address_to_str(pi->pool, &pi->net_src), - address_to_str(pi->pool, &pi->net_dst), - pi->srcport, pi->destport ); - len = 4; - is_ipv6 = FALSE; - } - else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6 - && is_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)", - address_to_str(pi->pool, &pi->net_src), - address_to_str(pi->pool, &pi->net_dst), - pi->srcport, pi->destport ); - len = 16; - is_ipv6 = TRUE; + else if( ((pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4) || + (pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6)) + && is_udp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype, + pi->srcport, pi->destport, 0)) != NULL ) { + /* UDP over IPv4/6 */ + udpd=get_udp_conversation_data(conv, pi); + if (udpd) { + buf = g_strdup_printf("udp.stream eq %d", udpd->stream); + stream_to_follow[UDP_STREAM] = udpd->stream; + if (pi->net_src.type == AT_IPv4) { + len = 4; + is_ipv6 = FALSE; + } else { + len = 16; + is_ipv6 = TRUE; + } + } else { + return NULL; + } } else { return NULL; @@ -162,30 +166,62 @@ build_follow_conv_filter( packet_info *pi ) { return buf; } -static gboolean find_tcp_addr; -static address tcp_addr[2]; -static gboolean find_tcp_index; +static gboolean +udp_follow_packet(void *tapdata _U_, packet_info *pinfo, + epan_dissect_t *edt _U_, const void *data _U_) +{ + if (find_addr[UDP_STREAM]) { + if (pinfo->net_src.type == AT_IPv6) { + is_ipv6 = TRUE; + } else { + is_ipv6 = FALSE; + } + memcpy(ip_address[0], pinfo->net_src.data, pinfo->net_src.len); + memcpy(ip_address[1], pinfo->net_dst.data, pinfo->net_dst.len); + port[0] = pinfo->srcport; + port[1] = pinfo->destport; + find_addr[UDP_STREAM] = FALSE; + } + + return FALSE; +} + +void +reset_udp_follow(void) { + remove_tap_listener(&stream_to_follow[UDP_STREAM]); + find_addr[UDP_STREAM] = FALSE; + find_addr[UDP_STREAM] = FALSE; +} gchar* -build_follow_index_filter(void) { +build_follow_index_filter(stream_type stream) { gchar *buf; - find_tcp_addr = TRUE; - buf = g_strdup_printf("tcp.stream eq %d", tcp_stream_to_follow); + find_addr[stream] = TRUE; + if (stream == TCP_STREAM) { + buf = g_strdup_printf("tcp.stream eq %d", stream_to_follow[TCP_STREAM]); + } else { + GString * error_string; + buf = g_strdup_printf("udp.stream eq %d", stream_to_follow[UDP_STREAM]); + error_string = register_tap_listener("udp_follow", &stream_to_follow[UDP_STREAM], buf, 0, NULL, udp_follow_packet, NULL); + if (error_string) { + g_string_free(error_string, TRUE); + } + } return buf; } /* select a tcp stream to follow via it's address/port pairs */ gboolean -follow_tcp_addr(const address *addr0, guint port0, - const address *addr1, guint port1) +follow_addr(stream_type stream, const address *addr0, guint port0, + const address *addr1, guint port1) { if (addr0 == NULL || addr1 == NULL || addr0->type != addr1->type || port0 > G_MAXUINT16 || port1 > G_MAXUINT16 ) { return FALSE; } - if (find_tcp_index || find_tcp_addr) { + if (find_index[stream] || find_addr[stream]) { return FALSE; } @@ -198,29 +234,32 @@ follow_tcp_addr(const address *addr0, guint port0, break; } - find_tcp_index = TRUE; memcpy(ip_address[0], addr0->data, addr0->len); - SET_ADDRESS(&tcp_addr[0], addr0->type, addr0->len, ip_address[0]); port[0] = port0; memcpy(ip_address[1], addr1->data, addr1->len); - SET_ADDRESS(&tcp_addr[1], addr1->type, addr1->len, ip_address[1]); port[1] = port1; + if (stream == TCP_STREAM) { + find_index[TCP_STREAM] = TRUE; + SET_ADDRESS(&tcp_addr[0], addr0->type, addr0->len, ip_address[0]); + SET_ADDRESS(&tcp_addr[1], addr1->type, addr1->len, ip_address[1]); + } + return TRUE; } -/* select a tcp stream to follow via its index */ +/* select a stream to follow via its index */ gboolean -follow_tcp_index(guint32 indx) +follow_index(stream_type stream, guint32 indx) { - if (find_tcp_index || find_tcp_addr) { + if (find_index[stream] || find_addr[stream]) { return FALSE; } - find_tcp_addr = TRUE; - tcp_stream_to_follow = indx; + find_addr[stream] = TRUE; + stream_to_follow[stream] = indx; memset(ip_address, 0, sizeof ip_address); port[0] = port[1] = 0; @@ -228,8 +267,8 @@ follow_tcp_index(guint32 indx) } guint32 -get_follow_tcp_index(void) { - return tcp_stream_to_follow; +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 @@ -255,7 +294,7 @@ reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement, src_index = -1; /* First, check if this packet should be processed. */ - if (find_tcp_index) { + 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)) @@ -263,14 +302,14 @@ reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement, (port[1] == srcport && port[0] == dstport && ADDRESSES_EQUAL(&tcp_addr[1], net_src) && ADDRESSES_EQUAL(&tcp_addr[0], net_dst))) { - find_tcp_index = FALSE; - tcp_stream_to_follow = tcp_stream; + find_index[TCP_STREAM] = FALSE; + stream_to_follow[TCP_STREAM] = tcp_stream; } else { return; } } - else if ( tcp_stream != tcp_stream_to_follow ) + else if ( tcp_stream != stream_to_follow[TCP_STREAM] ) return; if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) || @@ -286,8 +325,8 @@ reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement, memcpy(dstx, net_dst->data, len); /* follow_tcp_index() needs to learn address/port pairs */ - if (find_tcp_addr) { - find_tcp_addr = FALSE; + 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); @@ -518,8 +557,8 @@ reset_tcp_reassembly(void) empty_tcp_stream = TRUE; incomplete_tcp_stream = FALSE; - find_tcp_addr = FALSE; - find_tcp_index = 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); |