Fixed FieldInfo documentation.
[metze/wireshark/wip.git] / epan / follow.c
1 /* follow.c
2  *
3  * $Id$
4  *
5  * Copyright 1998 Mike Hall <mlh@io.com>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  */
26
27 #include "config.h"
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/ipproto.h>
39 #include <epan/dissectors/packet-tcp.h>
40 #include "follow.h"
41 #include <epan/conversation.h>
42
43 #define MAX_IPADDR_LEN  16
44
45 typedef struct _tcp_frag {
46   guint32             seq;
47   guint32             len;
48   guint32             data_len;
49   gchar              *data;
50   struct _tcp_frag   *next;
51 } tcp_frag;
52
53 WS_DLL_PUBLIC_DEF
54 FILE* data_out_file = NULL;
55
56 gboolean empty_tcp_stream;
57 gboolean incomplete_tcp_stream;
58
59 static guint32 tcp_stream_to_follow;
60 static guint8  ip_address[2][MAX_IPADDR_LEN];
61 static guint   port[2];
62 static guint   bytes_written[2];
63 static gboolean is_ipv6 = FALSE;
64
65 static int check_fragments( int, tcp_stream_chunk *, guint32 );
66 static void write_packet_data( int, tcp_stream_chunk *, const char * );
67
68 void
69 follow_stats(follow_stats_t* stats)
70 {
71         int i;
72
73         for (i = 0; i < 2 ; i++) {
74                 memcpy(stats->ip_address[i], ip_address[i], MAX_IPADDR_LEN);
75                 stats->port[i] = port[i];
76                 stats->bytes_written[i] = bytes_written[i];
77                 stats->is_ipv6 = is_ipv6;
78         }
79 }
80
81 /* this will build libpcap filter text that will only
82    pass the packets related to the stream. There is a
83    chance that two streams could intersect, but not a
84    very good one */
85 char*
86 build_follow_filter( packet_info *pi ) {
87   char* buf;
88   int len;
89   conversation_t *conv=NULL;
90   struct tcp_analysis *tcpd;
91
92   if( ((pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4) ||
93        (pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6))
94         && pi->ipproto == IP_PROTO_TCP 
95         && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
96               pi->srcport, pi->destport, 0)) != NULL ) {
97     /* TCP over IPv4 */
98     tcpd=get_tcp_conversation_data(conv, pi);
99     if (tcpd) {
100       buf = g_strdup_printf("tcp.stream eq %d", tcpd->stream);
101       tcp_stream_to_follow = tcpd->stream;
102       if (pi->net_src.type == AT_IPv4) {
103         len = 4;
104         is_ipv6 = FALSE;
105       } else {
106         len = 16;
107         is_ipv6 = TRUE;
108       }
109     } else {
110       return NULL;
111     }
112   }
113   else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
114            && pi->ipproto == IP_PROTO_UDP ) {
115   /* UDP over IPv4 */
116     buf = g_strdup_printf(
117              "(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
118              ip_to_str((guint8 *)pi->net_src.data),
119              ip_to_str((guint8 *)pi->net_dst.data),
120              pi->srcport, pi->destport );
121     len = 4;
122     is_ipv6 = FALSE;
123   }
124   else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
125         && pi->ipproto == IP_PROTO_UDP ) {
126     /* UDP over IPv6 */
127     buf = g_strdup_printf(
128              "(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
129              ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
130              ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
131              pi->srcport, pi->destport );
132     len = 16;
133     is_ipv6 = TRUE;
134   }
135   else {
136     return NULL;
137   }
138   memcpy(ip_address[0], pi->net_src.data, len);
139   memcpy(ip_address[1], pi->net_dst.data, len);
140   port[0] = pi->srcport;
141   port[1] = pi->destport;
142   return buf;
143 }
144
145 static gboolean         find_tcp_addr;
146 static address          tcp_addr[2];
147 static gboolean         find_tcp_index;
148
149 /* select a tcp stream to follow via it's address/port pairs */
150 gboolean
151 follow_tcp_addr(const address *addr0, guint port0,
152                 const address *addr1, guint port1)
153 {
154   if (addr0 == NULL || addr1 == NULL || addr0->type != addr1->type ||
155       port0 > G_MAXUINT16 || port1 > G_MAXUINT16 )  {
156     return FALSE;
157   }
158
159   if (find_tcp_index || find_tcp_addr) {
160     return FALSE;
161   }
162
163   switch (addr0->type) {
164   default:
165     return FALSE;
166   case AT_IPv4:
167   case AT_IPv6:
168     is_ipv6 = addr0->type == AT_IPv6;
169     break;
170   }
171
172   find_tcp_index = TRUE;
173
174   memcpy(ip_address[0], addr0->data, addr0->len);
175   SET_ADDRESS(&tcp_addr[0], addr0->type, addr0->len, ip_address[0]);
176   port[0] = port0;
177
178   memcpy(ip_address[1], addr1->data, addr1->len);
179   SET_ADDRESS(&tcp_addr[1], addr1->type, addr1->len, ip_address[1]);
180   port[1] = port1;
181
182   return TRUE;
183 }
184
185 /* select a tcp stream to follow via its index */
186 gboolean
187 follow_tcp_index(guint32 indx)
188 {
189   if (find_tcp_index || find_tcp_addr) {
190     return FALSE;
191   }
192
193   find_tcp_addr = TRUE;
194   tcp_stream_to_follow = indx;
195   memset(ip_address, 0, sizeof ip_address);
196   port[0] = port[1] = 0;
197
198   return TRUE;
199 }
200
201 /* here we are going to try and reconstruct the data portion of a TCP
202    session. We will try and handle duplicates, TCP fragments, and out
203    of order packets in a smart way. */
204
205 static tcp_frag *frags[2] = { 0, 0 };
206 static guint32 seq[2];
207 static guint8 src_addr[2][MAX_IPADDR_LEN];
208 static guint src_port[2] = { 0, 0 };
209
210 void
211 reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
212                 guint32 length, const char* data, guint32 data_length, 
213                 int synflag, address *net_src, address *net_dst, 
214                 guint srcport, guint dstport) {
215   guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
216   int src_index, j, first = 0, len;
217   guint32 newseq;
218   tcp_frag *tmp_frag;
219   tcp_stream_chunk sc;
220
221   src_index = -1;
222
223   /* First, check if this packet should be processed. */
224   if (find_tcp_index) {
225     if ((port[0] == srcport && port[1] == dstport &&
226          ADDRESSES_EQUAL(&tcp_addr[0], net_src) &&
227          ADDRESSES_EQUAL(&tcp_addr[1], net_dst))
228         ||
229         (port[1] == srcport && port[0] == dstport &&
230          ADDRESSES_EQUAL(&tcp_addr[1], net_src) &&
231          ADDRESSES_EQUAL(&tcp_addr[0], net_dst))) {
232       find_tcp_index = FALSE;
233       tcp_stream_to_follow = tcp_stream;
234     }
235     else {
236       return;
237     }
238   }
239   else if ( tcp_stream != tcp_stream_to_follow )
240     return;
241
242   if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) ||
243       (net_dst->type != AT_IPv4 && net_dst->type != AT_IPv6))
244     return;
245
246   if (net_src->type == AT_IPv4)
247     len = 4;
248   else
249     len = 16;
250
251   memcpy(srcx, net_src->data, len);
252   memcpy(dstx, net_dst->data, len);
253
254   /* follow_tcp_index() needs to learn address/port pairs */
255   if (find_tcp_addr) {
256     find_tcp_addr = FALSE;
257     memcpy(ip_address[0], net_src->data, net_src->len);
258     port[0] = srcport;
259     memcpy(ip_address[1], net_dst->data, net_dst->len);
260     port[1] = dstport;
261   }
262
263   /* Check to see if we have seen this source IP and port before.
264      (Yes, we have to check both source IP and port; the connection
265      might be between two different ports on the same machine.) */
266   for( j=0; j<2; j++ ) {
267     if (memcmp(src_addr[j], srcx, len) == 0 && src_port[j] == srcport ) {
268       src_index = j;
269     }
270   }
271   /* we didn't find it if src_index == -1 */
272   if( src_index < 0 ) {
273     /* assign it to a src_index and get going */
274     for( j=0; j<2; j++ ) {
275       if( src_port[j] == 0 ) {
276         memcpy(src_addr[j], srcx, len);
277         src_port[j] = srcport;
278         src_index = j;
279         first = 1;
280         break;
281       }
282     }
283   }
284   if( src_index < 0 ) {
285     fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
286     return;
287   }
288
289   if( data_length < length ) {
290     incomplete_tcp_stream = TRUE;
291   }
292
293   /* Before adding data for this flow to the data_out_file, check whether
294    * this frame acks fragments that were already seen. This happens when
295    * frames are not in the capture file, but were actually seen by the 
296    * receiving host (Fixes bug 592).
297    */
298   if( frags[1-src_index] ) {
299     memcpy(sc.src_addr, dstx, len);
300     sc.src_port = dstport;
301     sc.dlen     = 0;        /* Will be filled in in check_fragments */
302     while ( check_fragments( 1-src_index, &sc, acknowledgement ) )
303       ;
304   }
305
306   /* Initialize our stream chunk.  This data gets written to disk. */
307   memcpy(sc.src_addr, srcx, len);
308   sc.src_port = srcport;
309   sc.dlen     = data_length;
310
311   /* now that we have filed away the srcs, lets get the sequence number stuff
312      figured out */
313   if( first ) {
314     /* this is the first time we have seen this src's sequence number */
315     seq[src_index] = sequence + length;
316     if( synflag ) {
317       seq[src_index]++;
318     }
319     /* write out the packet data */
320     write_packet_data( src_index, &sc, data );
321     return;
322   }
323   /* if we are here, we have already seen this src, let's
324      try and figure out if this packet is in the right place */
325   if( sequence < seq[src_index] ) {
326     /* this sequence number seems dated, but
327        check the end to make sure it has no more
328        info than we have already seen */
329     newseq = sequence + length;
330     if( newseq > seq[src_index] ) {
331       guint32 new_len;
332
333       /* this one has more than we have seen. let's get the
334          payload that we have not seen. */
335
336       new_len = seq[src_index] - sequence;
337
338       if ( data_length <= new_len ) {
339         data = NULL;
340         data_length = 0;
341         incomplete_tcp_stream = TRUE;
342       } else {
343         data += new_len;
344         data_length -= new_len;
345       }
346       sc.dlen = data_length;
347       sequence = seq[src_index];
348       length = newseq - seq[src_index];
349
350       /* this will now appear to be right on time :) */
351     }
352   }
353   if ( sequence == seq[src_index] ) {
354     /* right on time */
355     seq[src_index] += length;
356     if( synflag ) seq[src_index]++;
357     if( data ) {
358       write_packet_data( src_index, &sc, data );
359     }
360     /* done with the packet, see if it caused a fragment to fit */
361     while( check_fragments( src_index, &sc, 0 ) )
362       ;
363   }
364   else {
365     /* out of order packet */
366     if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
367       tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
368       tmp_frag->data = (gchar *)g_malloc( data_length );
369       tmp_frag->seq = sequence;
370       tmp_frag->len = length;
371       tmp_frag->data_len = data_length;
372       memcpy( tmp_frag->data, data, data_length );
373       if( frags[src_index] ) {
374         tmp_frag->next = frags[src_index];
375       } else {
376         tmp_frag->next = NULL;
377       }
378       frags[src_index] = tmp_frag;
379     }
380   }
381 } /* end reassemble_tcp */
382
383 /* here we search through all the frag we have collected to see if
384    one fits */
385 static int
386 check_fragments( int idx, tcp_stream_chunk *sc, guint32 acknowledged ) {
387   tcp_frag *prev = NULL;
388   tcp_frag *current;
389   guint32 lowest_seq;
390   gchar *dummy_str;
391
392   current = frags[idx];
393   if( current ) {
394     lowest_seq = current->seq;
395     while( current ) {
396       if( (glong)(lowest_seq - current->seq) > 0 ) {
397         lowest_seq = current->seq;
398       }
399
400       if( current->seq < seq[idx] ) {
401         guint32 newseq;
402         /* this sequence number seems dated, but
403            check the end to make sure it has no more
404            info than we have already seen */
405         newseq = current->seq + current->len;
406         if( newseq > seq[idx] ) {
407           guint32 new_pos;
408
409           /* this one has more than we have seen. let's get the
410              payload that we have not seen. This happens when 
411              part of this frame has been retransmitted */
412
413           new_pos = seq[idx] - current->seq;
414
415           if ( current->data_len > new_pos ) {
416             sc->dlen = current->data_len - new_pos;
417             write_packet_data( idx, sc, current->data + new_pos );
418           }
419
420           seq[idx] += (current->len - new_pos);
421         } 
422
423         /* Remove the fragment from the list as the "new" part of it
424          * has been processed or its data has been seen already in 
425          * another packet. */
426         if( prev ) {
427           prev->next = current->next;
428         } else {
429           frags[idx] = current->next;
430         }
431         g_free( current->data );
432         g_free( current );
433         return 1;
434       }
435
436       if( current->seq == seq[idx] ) {
437         /* this fragment fits the stream */
438         if( current->data ) {
439           sc->dlen = current->data_len;
440           write_packet_data( idx, sc, current->data );
441         }
442         seq[idx] += current->len;
443         if( prev ) {
444           prev->next = current->next;
445         } else {
446           frags[idx] = current->next;
447         }
448         g_free( current->data );
449         g_free( current );
450         return 1;
451       }
452       prev = current;
453       current = current->next;
454     }
455     if( (glong)(acknowledged - lowest_seq) > 0 ) {
456       /* There are frames missing in the capture file that were seen
457        * by the receiving host. Add dummy stream chunk with the data
458        * "[xxx bytes missing in capture file]".
459        */
460       dummy_str = g_strdup_printf("[%d bytes missing in capture file]",
461                         (int)(lowest_seq - seq[idx]) );
462       sc->dlen = (guint32) strlen(dummy_str);
463       write_packet_data( idx, sc, dummy_str );
464       g_free(dummy_str);
465       seq[idx] = lowest_seq;
466       return 1;
467     }
468   } 
469   return 0;
470 }
471
472 /* this should always be called before we start to reassemble a stream */
473 void
474 reset_tcp_reassembly(void)
475 {
476   tcp_frag *current, *next;
477   int i;
478
479   empty_tcp_stream = TRUE;
480   incomplete_tcp_stream = FALSE;
481   find_tcp_addr = FALSE;
482   find_tcp_index = FALSE;
483   for( i=0; i<2; i++ ) {
484     seq[i] = 0;
485     memset(src_addr[i], '\0', MAX_IPADDR_LEN);
486     src_port[i] = 0;
487     memset(ip_address[i], '\0', MAX_IPADDR_LEN);
488     port[i] = 0;
489     bytes_written[i] = 0;
490     current = frags[i];
491     while( current ) {
492       next = current->next;
493       g_free( current->data );
494       g_free( current );
495       current = next;
496     }
497     frags[i] = NULL;
498   }
499 }
500
501 static void
502 write_packet_data( int idx, tcp_stream_chunk *sc, const char *data )
503 {
504   size_t ret;
505
506   ret = fwrite( sc, 1, sizeof(tcp_stream_chunk), data_out_file );
507   DISSECTOR_ASSERT(sizeof(tcp_stream_chunk) == ret);
508   
509   ret = fwrite( data, 1, sc->dlen, data_out_file );
510   DISSECTOR_ASSERT(sc->dlen == ret);
511
512   bytes_written[idx] += sc->dlen;
513   empty_tcp_stream = FALSE;
514 }