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 ) );
}