Add FT_EUI64 Field Type
[obnox/wireshark/wip.git] / epan / follow.c
index 749d0396001569ef6e7a5bbc4ad576e00b66c153..83f2c4b4e18a2f5104bea139365e49982ebbd16e 100644 (file)
@@ -56,6 +56,7 @@ FILE* data_out_file = NULL;
 gboolean empty_tcp_stream;
 gboolean incomplete_tcp_stream;
 
+static guint32 tcp_stream_to_follow;
 static guint8  ip_address[2][MAX_IPADDR_LEN];
 static guint   port[2];
 static guint   bytes_written[2];
@@ -95,6 +96,7 @@ build_follow_filter( packet_info *pi ) {
     buf = g_strdup_printf("tcp.stream eq %d", conv->index);
     len = 4;
     is_ipv6 = FALSE;
+    tcp_stream_to_follow = conv->index;
   }
   else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
           && pi->ipproto == IP_PROTO_UDP ) {
@@ -115,6 +117,7 @@ build_follow_filter( packet_info *pi ) {
     buf = g_strdup_printf("tcp.stream eq %d", conv->index);
     len = 16;
     is_ipv6 = TRUE;
+    tcp_stream_to_follow = conv->index;
   }
   else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
        && pi->ipproto == IP_PROTO_UDP ) {
@@ -147,9 +150,9 @@ static guint8 src_addr[2][MAX_IPADDR_LEN];
 static guint src_port[2] = { 0, 0 };
 
 void
-reassemble_tcp( gulong sequence, gulong acknowledgement, gulong length,
-                const char* data, gulong data_length, int synflag,
-                address *net_src, address *net_dst, 
+reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
+                gulong length, const char* data, gulong data_length, 
+                int synflag, address *net_src, address *net_dst, 
                 guint srcport, guint dstport) {
   guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
   int src_index, j, first = 0, len;
@@ -160,6 +163,8 @@ reassemble_tcp( gulong sequence, gulong acknowledgement, gulong length,
   src_index = -1;
 
   /* First, check if this packet should be processed. */
+  if ( tcp_stream != tcp_stream_to_follow )
+    return;
 
   if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) ||
       (net_dst->type != AT_IPv4 && net_dst->type != AT_IPv6))
@@ -170,24 +175,8 @@ reassemble_tcp( gulong sequence, gulong acknowledgement, gulong length,
   else
     len = 16;
 
-  /* Now check if the packet is for this connection. */
   memcpy(srcx, net_src->data, len);
   memcpy(dstx, net_dst->data, len);
-  if (
-      ! (
-        memcmp(srcx, ip_address[0], len) == 0 &&
-        memcmp(dstx, ip_address[1], len) == 0 &&
-        srcport == port[0] &&
-        dstport == port[1]
-       ) &&
-      ! (
-        memcmp(srcx, ip_address[1], len) == 0 &&
-        memcmp(dstx, ip_address[0], len) == 0 &&
-        srcport == port[1] &&
-        dstport == port[0]
-       )
-     )
-    return;
 
   /* Check to see if we have seen this source IP and port before.
      (Yes, we have to check both source IP and port; the connection
@@ -292,7 +281,7 @@ reassemble_tcp( gulong sequence, gulong acknowledgement, gulong length,
   }
   else {
     /* out of order packet */
-    if(data_length > 0 && sequence > seq[src_index] ) {
+    if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
       tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
       tmp_frag->data = (gchar *)g_malloc( data_length );
       tmp_frag->seq = sequence;
@@ -312,13 +301,13 @@ reassemble_tcp( gulong sequence, gulong acknowledgement, gulong length,
 /* here we search through all the frag we have collected to see if
    one fits */
 static int
-check_fragments( int index, tcp_stream_chunk *sc, gulong acknowledged ) {
+check_fragments( int idx, tcp_stream_chunk *sc, gulong acknowledged ) {
   tcp_frag *prev = NULL;
   tcp_frag *current;
   gulong lowest_seq;
   gchar *dummy_str;
 
-  current = frags[index];
+  current = frags[idx];
   if( current ) {
     lowest_seq = current->seq;
     while( current ) {
@@ -326,49 +315,53 @@ check_fragments( int index, tcp_stream_chunk *sc, gulong acknowledged ) {
         lowest_seq = current->seq;
       }
 
-      if( current->seq < seq[index] ) {
+      if( current->seq < seq[idx] ) {
         gulong 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[index] ) {
+        if( newseq > seq[idx] ) {
           gulong new_pos;
 
           /* this one has more than we have seen. let's get the
              payload that we have not seen. This happens when 
              part of this frame has been retransmitted */
 
-          new_pos = seq[index] - current->seq;
+          new_pos = seq[idx] - current->seq;
 
           if ( current->data_len > new_pos ) {
             sc->dlen = current->data_len - new_pos;
-            write_packet_data( index, sc, current->data + new_pos );
+            write_packet_data( idx, sc, current->data + new_pos );
           }
 
-          seq[index] += (current->len - new_pos);
-          if( prev ) {
-            prev->next = current->next;
-          } else {
-            frags[index] = current->next;
-          }
-          g_free( current->data );
-          g_free( current );
-          return 1;
+          seq[idx] += (current->len - new_pos);
+        } 
+
+        /* Remove the fragment from the list as the "new" part of it
+         * has been processed or its data has been seen already in 
+         * another packet. */
+        if( prev ) {
+          prev->next = current->next;
+        } else {
+          frags[idx] = current->next;
         }
+        g_free( current->data );
+        g_free( current );
+        return 1;
       }
 
-      if( current->seq == seq[index] ) {
+      if( current->seq == seq[idx] ) {
         /* this fragment fits the stream */
         if( current->data ) {
           sc->dlen = current->data_len;
-          write_packet_data( index, sc, current->data );
+          write_packet_data( idx, sc, current->data );
         }
-        seq[index] += current->len;
+        seq[idx] += current->len;
         if( prev ) {
           prev->next = current->next;
         } else {
-          frags[index] = current->next;
+          frags[idx] = current->next;
         }
         g_free( current->data );
         g_free( current );
@@ -383,11 +376,11 @@ check_fragments( int index, tcp_stream_chunk *sc, gulong acknowledged ) {
        * "[xxx bytes missing in capture file]".
        */
       dummy_str = g_strdup_printf("[%d bytes missing in capture file]",
-                        (int)(lowest_seq - seq[index]) );
-      sc->dlen = strlen(dummy_str);
-      write_packet_data( index, sc, dummy_str );
+                        (int)(lowest_seq - seq[idx]) );
+      sc->dlen = (guint32) strlen(dummy_str);
+      write_packet_data( idx, sc, dummy_str );
       g_free(dummy_str);
-      seq[index] = lowest_seq;
+      seq[idx] = lowest_seq;
       return 1;
     }
   } 
@@ -422,10 +415,16 @@ reset_tcp_reassembly(void)
 }
 
 static void
-write_packet_data( int index, tcp_stream_chunk *sc, const char *data )
+write_packet_data( int idx, tcp_stream_chunk *sc, const char *data )
 {
-  DISSECTOR_ASSERT(1 * sizeof(tcp_stream_chunk) == fwrite( sc, 1, sizeof(tcp_stream_chunk), data_out_file ));
-  DISSECTOR_ASSERT(1 * sc->dlen == fwrite( data, 1, sc->dlen, data_out_file ));
-  bytes_written[index] += sc->dlen;
+  size_t ret;
+
+  ret = fwrite( sc, 1, sizeof(tcp_stream_chunk), data_out_file );
+  DISSECTOR_ASSERT(sizeof(tcp_stream_chunk) == ret);
+  
+  ret = fwrite( data, 1, sc->dlen, data_out_file );
+  DISSECTOR_ASSERT(sc->dlen == ret);
+
+  bytes_written[idx] += sc->dlen;
   empty_tcp_stream = FALSE;
 }