Added back x509af_get_last_algorithm_id() removed in revision 54647 to
[metze/wireshark/wip.git] / epan / follow.c
index 859d5f42052b5174ccbf709d6c7386d99531500e..fe17c1740cf07957cdd84d0719122d3f1681033d 100644 (file)
@@ -35,7 +35,8 @@
 
 #include <glib.h>
 #include <epan/packet.h>
-#include <epan/ipproto.h>
+#include <epan/to_str.h>
+#include <epan/emem.h>
 #include <epan/dissectors/packet-tcp.h>
 #include "follow.h"
 #include <epan/conversation.h>
 #define MAX_IPADDR_LEN  16
 
 typedef struct _tcp_frag {
-  gulong              seq;
-  gulong              len;
-  gulong              data_len;
+  guint32             seq;
+  guint32             len;
+  guint32             data_len;
   gchar              *data;
   struct _tcp_frag   *next;
 } tcp_frag;
 
+WS_DLL_PUBLIC_DEF
 FILE* data_out_file = NULL;
 
 gboolean empty_tcp_stream;
 gboolean incomplete_tcp_stream;
 
-static guint32 tcp_stream_to_follow;
+static guint32 tcp_stream_to_follow = 0;
 static guint8  ip_address[2][MAX_IPADDR_LEN];
 static guint   port[2];
 static guint   bytes_written[2];
 static gboolean is_ipv6 = FALSE;
 
-static int check_fragments( int, tcp_stream_chunk *, gulong );
+static int check_fragments( int, tcp_stream_chunk *, guint32 );
 static void write_packet_data( int, tcp_stream_chunk *, const char * );
 
 void
@@ -77,21 +79,42 @@ follow_stats(follow_stats_t* stats)
        }
 }
 
-/* this will build libpcap filter text that will only
+/* This will build a display filter text that will only
    pass the packets related to the stream. There is a
    chance that two streams could intersect, but not a
    very good one */
-char*
-build_follow_filter( packet_info *pi ) {
+gchar*
+build_follow_conv_filter( packet_info *pi ) {
   char* buf;
   int len;
   conversation_t *conv=NULL;
   struct tcp_analysis *tcpd;
+  wmem_list_frame_t* protos;
+  int proto_id;
+  const char* proto_name;
+  gboolean is_tcp = FALSE, is_udp = FALSE;
+
+  protos = wmem_list_head(pi->layers);
+
+  /* walk the list of a available protocols in the packet to
+      figure out if any of them affect context sensitivity */
+  while (protos != NULL)
+  {
+    proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
+    proto_name = proto_get_protocol_filter_name(proto_id);
+
+    if (!strcmp(proto_name, "tcp")) {
+        is_tcp = TRUE;
+    } else if (!strcmp(proto_name, "udp")) {
+        is_udp = TRUE;
+    }
+            
+    protos = wmem_list_frame_next(protos);
+  }
 
   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))
-       && pi->ipproto == IP_PROTO_TCP 
-        && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
+       && is_tcp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
               pi->srcport, pi->destport, 0)) != NULL ) {
     /* TCP over IPv4 */
     tcpd=get_tcp_conversation_data(conv, pi);
@@ -110,18 +133,18 @@ build_follow_filter( packet_info *pi ) {
     }
   }
   else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
-          && pi->ipproto == IP_PROTO_UDP ) {
+          && 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)",
-            ip_to_str( pi->net_src.data),
-            ip_to_str( pi->net_dst.data),
+            ip_to_str((const guint8 *)pi->net_src.data),
+            ip_to_str((const guint8 *)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 == IP_PROTO_UDP ) {
+       && 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)",
@@ -145,6 +168,15 @@ static gboolean         find_tcp_addr;
 static address          tcp_addr[2];
 static gboolean         find_tcp_index;
 
+gchar*
+build_follow_index_filter(void) {
+  gchar *buf;
+
+  find_tcp_addr = TRUE;
+  buf = g_strdup_printf("tcp.stream eq %d", tcp_stream_to_follow);
+  return buf;
+}
+
 /* select a tcp stream to follow via it's address/port pairs */
 gboolean
 follow_tcp_addr(const address *addr0, guint port0,
@@ -189,6 +221,10 @@ follow_tcp_index(guint32 indx)
     return FALSE;
   }
 
+  if (indx > get_tcp_stream_count()) {
+    return FALSE;
+  }
+
   find_tcp_addr = TRUE;
   tcp_stream_to_follow = indx;
   memset(ip_address, 0, sizeof ip_address);
@@ -197,23 +233,28 @@ follow_tcp_index(guint32 indx)
   return TRUE;
 }
 
+guint32
+get_follow_tcp_index(void) {
+  return tcp_stream_to_follow;
+}
+
 /* here we are going to try and reconstruct the data portion of a TCP
    session. We will try and handle duplicates, TCP fragments, and out
    of order packets in a smart way. */
 
 static tcp_frag *frags[2] = { 0, 0 };
-static gulong seq[2];
+static guint32 seq[2];
 static guint8 src_addr[2][MAX_IPADDR_LEN];
 static guint src_port[2] = { 0, 0 };
 
 void
-reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
-                gulong length, const char* data, gulong data_length, 
+reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
+                guint32 length, const char* data, guint32 data_length, 
                 int synflag, address *net_src, address *net_dst, 
-                guint srcport, guint dstport) {
+                guint srcport, guint dstport, guint32 packet_num) {
   guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
   int src_index, j, first = 0, len;
-  gulong newseq;
+  guint32 newseq;
   tcp_frag *tmp_frag;
   tcp_stream_chunk sc;
 
@@ -257,6 +298,11 @@ reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
     port[0] = srcport;
     memcpy(ip_address[1], net_dst->data, net_dst->len);
     port[1] = dstport;
+    if (net_src->type == AT_IPv6 && net_dst->type == AT_IPv6) {
+      is_ipv6 = TRUE;
+    } else {
+      is_ipv6 = FALSE;
+    }
   }
 
   /* Check to see if we have seen this source IP and port before.
@@ -304,8 +350,9 @@ reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
 
   /* Initialize our stream chunk.  This data gets written to disk. */
   memcpy(sc.src_addr, srcx, len);
-  sc.src_port = srcport;
-  sc.dlen     = data_length;
+  sc.src_port   = srcport;
+  sc.dlen       = data_length;
+  sc.packet_num = packet_num;
 
   /* now that we have filed away the srcs, lets get the sequence number stuff
      figured out */
@@ -327,7 +374,7 @@ reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
        info than we have already seen */
     newseq = sequence + length;
     if( newseq > seq[src_index] ) {
-      gulong new_len;
+      guint32 new_len;
 
       /* this one has more than we have seen. let's get the
         payload that we have not seen. */
@@ -362,7 +409,7 @@ reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
   }
   else {
     /* out of order packet */
-    if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
+    if(data_length > 0 && GT_SEQ(sequence, seq[src_index]) ) {
       tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
       tmp_frag->data = (gchar *)g_malloc( data_length );
       tmp_frag->seq = sequence;
@@ -382,28 +429,28 @@ reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
 /* here we search through all the frag we have collected to see if
    one fits */
 static int
-check_fragments( int idx, tcp_stream_chunk *sc, gulong acknowledged ) {
+check_fragments( int idx, tcp_stream_chunk *sc, guint32 acknowledged ) {
   tcp_frag *prev = NULL;
   tcp_frag *current;
-  gulong lowest_seq;
+  guint32 lowest_seq;
   gchar *dummy_str;
 
   current = frags[idx];
   if( current ) {
     lowest_seq = current->seq;
     while( current ) {
-      if( (glong)(lowest_seq - current->seq) > 0 ) {
+      if( GT_SEQ(lowest_seq, current->seq) ) {
         lowest_seq = current->seq;
       }
 
       if( current->seq < seq[idx] ) {
-        gulong newseq;
+        guint32 newseq;
         /* this sequence number seems dated, but
            check the end to make sure it has no more
            info than we have already seen */
         newseq = current->seq + current->len;
         if( newseq > seq[idx] ) {
-          gulong new_pos;
+          guint32 new_pos;
 
           /* this one has more than we have seen. let's get the
              payload that we have not seen. This happens when 
@@ -451,7 +498,7 @@ check_fragments( int idx, tcp_stream_chunk *sc, gulong acknowledged ) {
       prev = current;
       current = current->next;
     }
-    if( (glong)(acknowledged - lowest_seq) > 0 ) {
+    if( GT_SEQ(acknowledged, lowest_seq) ) {
       /* There are frames missing in the capture file that were seen
        * by the receiving host. Add dummy stream chunk with the data
        * "[xxx bytes missing in capture file]".