- Future improve/clean up the now generic follow stream code
authorsfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 3 Nov 2007 04:45:35 +0000 (04:45 +0000)
committersfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 3 Nov 2007 04:45:35 +0000 (04:45 +0000)
- Add "Follow UDP Stream" feature

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@23346 f5534014-38df-0310-8fa8-9805f1628bb7

docbook/wsug_src/WSUG_chapter_use.xml
epan/dissectors/packet-udp.c
epan/follow.c
epan/follow.h
gtk/Makefile.common
gtk/follow_ssl.c
gtk/follow_stream.c
gtk/follow_stream.h
gtk/follow_tcp.c
gtk/main.c
gtk/menu.c

index ff56b6445df3687eec0278ed1264e50a7243e2db..fb287f0e8aae01e62f7872cac789a652e790544a 100644 (file)
                    <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>
index ea1f825b10bc9e9889084490f5defd61b43df38e..a7da76e6c61c3388558b693078252ee2dce24def 100644 (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");
 }
index 55f5be3c9ef970970b3ab984667dea0fcf2faee5..61aaee55755935a3e5430f7f54ffab242097c45d 100644 (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 ) {
index 86edbd3acad7247fab222d839bb4c5e0ac928dbb..f84e4ad9601f68cf4e4062b294606549ee6508cf 100644 (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
index c8edd225f4be940b5a10a430ae1a5b94776944f6..4f7abf58ec9edf574f8c91cd1dd72b4a63156275 100644 (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 \
index a682a628d3b9961b9a006e7e2b1fc15716ec3fd4..335e7c09a22e92bda393f1f8c18aae025c0e922c 100644 (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);
index 155044881b1b69d5b906adaaefb5b5d0afa2af64..f44de7cc8be2243b2bccf0913958025e407f98b6 100644 (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;
        }
 
index b70b2866200b9415396c9354be2dea5708838b52..419de3ab66166e0b833a84b8e60970b661dc3246 100644 (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);
index 86364cdaaf3f7e3e8f0265089f215ccb652f7be4..221f8006b29a47d4dc40e16fe3a685845a895229 100644 (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)) {
index 84802b704653c2e6e8d81d718ee753b3cb56cd7a..eb18ffe87051473559c3cb8540ced78d15eef918 100644 (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,
index e53618013fad868c1c5e3a4236838927152fc463..a4377ae38a97b732a47f0d0c09115c1a5ff77182 100644 (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",