tcpslice (1.2a3-4) 04_zero_and_one_packet_captures.patch

Summary

 search.c   |   21 +++++++++++++++++++--
 tcpslice.c |   47 +++++++++++++++++++++++++++++++++++++----------
 2 files changed, 56 insertions(+), 12 deletions(-)

    
download this patch

Patch contents

Index: tcpslice-1.2a3/search.c
===================================================================
--- tcpslice-1.2a3.orig/search.c	2009-10-21 12:29:51.000000000 +0200
+++ tcpslice-1.2a3/search.c	2009-10-21 12:30:50.000000000 +0200
@@ -327,8 +327,25 @@
 	if ( fread( (char *) bufpos, num_bytes, 1, pcap_file( p ) ) != 1 )
 		goto done;
 
-	if ( find_header( p, bufpos, num_bytes,
-			  first_time, 0L, &hdrpos, &hdr ) != HEADER_DEFINITELY )
+	status = find_header( p, bufpos, num_bytes,
+			  first_time, 0L, &hdrpos, &hdr );
+
+        /* When find_header finds what looks like a header it tries to verify
+         * that looking forward by caplen also finds what looks like a header.
+         * If moving forward points past the end of the buffer it returns
+         * _PERHAPS, because there wasn't enough data passed to it to verify
+         * the next header.  However, we know that the buffer ends with the
+         * last data in the file. If the _PERHAPS header just found + caplen
+         * points to exactly past the end of the file, that's as-if it pointed
+         * to a valid header, and we promote _PERHAPS to _DEFINITELY.
+         *
+         * This condition occurs with a single-packet capture.
+         */
+        if ( status == HEADER_PERHAPS &&
+		( hdrpos + PACKET_HDR_LEN + hdr.caplen ) == bufend )
+			status = HEADER_DEFINITELY;
+
+	if ( status != HEADER_DEFINITELY )
 		goto done;
 
 	/* Okay, we have a definite header in our hands.  Follow its
Index: tcpslice-1.2a3/tcpslice.c
===================================================================
--- tcpslice-1.2a3.orig/tcpslice.c	2009-10-21 12:29:52.000000000 +0200
+++ tcpslice-1.2a3/tcpslice.c	2009-10-21 12:31:07.000000000 +0200
@@ -112,6 +112,7 @@
 struct timeval first_packet_time(char filename[], pcap_t **p_addr);
 struct timeval lowest_start_time(struct state *states, int numfiles);
 void get_next_packet(struct state *s);
+void get_first_packet(const char *filename, pcap_t *p, struct pcap_pkthdr *hdr);
 struct state *open_files(char *filenames[], int numfiles);
 void extract_slice(struct state *states, int numfiles, char *write_file_name,
 			struct timeval *start_time, struct timeval *stop_time,
@@ -474,7 +475,9 @@
 {
 	*first_time = first_packet_time( filename, p );
 
-	if ( ! sf_find_end( *p, first_time, last_time ) )
+	*last_time = *first_time;
+
+	if ( first_time->tv_sec && ! sf_find_end( *p, first_time, last_time ) )
 		error( "couldn't find final packet in file %s", filename );
 }
 
@@ -494,8 +497,7 @@
 	if (! p)
 		error( "bad tcpdump file %s: %s", filename, errbuf );
 
-	if (pcap_next(p, &hdr) == 0)
-		error( "bad status reading first packet in %s", filename );
+	get_first_packet(filename, p, &hdr);
 
 	return hdr.ts;
 }
@@ -528,6 +530,27 @@
 	}
 }
 
+/* Get the first record in a file. Deal with empty captures. */
+void
+get_first_packet(const char *filename, pcap_t *p, struct pcap_pkthdr *hdr)
+{
+	struct pcap_pkthdr *next_hdr = 0;
+	const u_char *next_data = 0;
+	switch (pcap_next_ex(p, &next_hdr, &next_data))
+	{
+		case  1: /* success */
+			*hdr = *next_hdr;
+			break;
+		case -2: /* no more packets to read from the save-file */
+			/* valid but empty pcap, start and end time will be zero */
+			memset(hdr, 0, sizeof(*hdr));
+			break;
+		default:
+			error( "bad status reading first packet in %s: %s",
+					filename, pcap_geterr( p ) );
+	}
+}
+
 struct state *
 open_files(char *filenames[], int numfiles)
 {
@@ -559,16 +582,20 @@
 
 		s->start_pos = FTELL( pcap_file( s->p ) );
 
-		if (pcap_next(s->p, &s->hdr) == 0)
-			error( "error reading packet in %s: ",
-				s->filename, pcap_geterr( s->p ) );
+		get_first_packet(s->filename, s->p, &s->hdr);
 
 		s->file_start_time = s->hdr.ts;
 
-		if ( ! sf_find_end( s->p, &s->file_start_time,
-					  &s->file_stop_time ) )
-			error( "problems finding end packet of file %s",
-				s->filename );
+		/* For 0-packet captures the start time is 0, don't search for an
+		 * end time.
+		 */
+		if ( s->file_start_time.tv_sec )
+			{
+			if ( ! sf_find_end( s->p, &s->file_start_time,
+						  &s->file_stop_time ) )
+				error( "problems finding end packet of file %s",
+					s->filename );
+			}
 
 		s->stop_pos = FTELL( pcap_file( s->p ) );
 	}