the-tcpdump-group / tcpslice

tcpslice concatenates multiple pcap files together, or extracts time slices from one or more pcap files.
67 stars 23 forks source link

tcpslice can't read capture file with just one packet #23

Open mruprich opened 1 year ago

mruprich commented 1 year ago

When using tcpslice to merge two capture files, if one of those files has just one packet, tcpslice will fail with following error:

tcpslice: problems finding end packet of file capture-file

This does not have to be just the action of merging two files. Just reading the one file with one packet ends up the same. This is reproducible in a following ways:

1. Start a capture with tcpdump -c 1 on any interface and capture one packet from any traffic:
    # tcpdump -c 1 -w one-packet-capture -i eth0
2. Run tcpslice on this one:
    # tcpslice -v one-packet-capture -w one-packet-capture-out
    tcpslice: problems finding end packet of file one-packet-capture
3. You can also capture another file with more packets and then merge:
    # tcpdump -c 10 -w ten-packets-capture -i eth0
    # tcpslice one-packet-capture ten-packet-capture -w merged-capture
    tcpslice: problems finding end packet of file one-packet-capture

The error appears even when the captures are merged with a different tool like mergecap:

1. Capture one packet in one file and ten packets in a different file like in the previous example
2. Use mergecap (from wireshark) to merge these together:
    # mergecap -w merged-with-mergecap one-packet-capture ten-packet-capture
    # tcpdump --count -r merged-with-mergecap 
    reading from file merged-with-mergecap, link-type EN10MB (Ethernet), snapshot length 262144
    11 packets
3. Try to read the file with tcpslice:
    # tcpslice merged-with-mergecap 
    tcpslice: problems finding end packet of file merged-with-mergecap
infrastation commented 1 year ago

Thank you for reporting this bug, it reproduces as described.

mruprich commented 10 months ago

@infrastation Tried a little bit of debugging, I think the problem is in the find_header() function. In sf_find_end, we expect that find_header will return HEADER_DEFINITELY:

if ( find_header( p, bufpos, num_bytes,
        first_time, 0L, &hdrpos, &hdr ) != HEADER_DEFINITELY )
    goto done;

But HEADER_DEFINITELY is never set in find_header function unless there are at least two packets:

if ( next_header + PACKET_HDR_LEN < bufend )
    { /* check for another good header */
        extract_header( p, next_header, &hdr2 );

        if ( reasonable_header( &hdr2, hdr.ts.tv_sec,
          hdr.ts.tv_sec + MAX_REASONABLE_HDR_SEPARATION ) )
        { /* a confirmed header */
      switch ( status )
      {
          case HEADER_NONE:
          case HEADER_PERHAPS:
        status = HEADER_DEFINITELY;   <----- only when there is a next_header
        *hdrpos_addr = bufptr;
        *return_hdr = hdr;

Only HEADER_PERHAPS is set for the first packet:

case HEADER_NONE:
          status = HEADER_PERHAPS;
          *hdrpos_addr = bufptr;
          *return_hdr = hdr;
          break;

So at the end of the function:

if ( status == HEADER_PERHAPS && saw_PERHAPS_clash )
    status = HEADER_CLASH;

  return status;

Status is always HEADER_PERHAPS. Not sure if the solution would be to simply assume that HEADER_DEFINITELY could be returned instead since saw_PERHAPS_clash is 0?

infrastation commented 10 months ago

Thank you for looking into this. A pcap savefile with one packet is a valid file and as far as the man page and the command-line options go, there seems to be no fundamental reason to require more than one packet to process pcap savefile(s) as described. So ideally it would be nice to have this edge case bug fixed. However, if due to implementation details fixing the bug would be too difficult, at the very least it would be appropriate to document it and to print a more useful error message.

fxlb commented 10 months ago

The error appears even when the captures are merged with a different tool like mergecap

$ file merged-with-mergecap
merged-with-mergecap: pcapng capture file - version 1.0

If you do:

$ mergecap -F pcap -w merged-with-mergecap one-packet-capture ten-packet-capture
$ file merged-with-mergecap                            
merged-with-mergecap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Ethernet, capture length 262144)
$ tcpslice merged-with-mergecap -w merged-capture

With a pcap file (11 packets), no error.

guyharris commented 10 months ago

So two issues have come up here:

  1. tcpslice doesn't handle a pcap file with only one packet (the correct action on such a file would just be to write that packet to an new file);
  2. tcpslice doesn't handle a pcapng file, no matter how many packets it contains (the correct action on such a file would be to recognize that it's reading a pcapng file and use code not as yet written to correctly split the file up, which is a more complicated process than splitting up a pcap file).
infrastation commented 10 months ago
  1. ...subject to start-time and end-time, as usual;
  2. maybe just a correct error message would be a good starting point, something such as "the input file F uses pcapng format, which tcpslice does not support, to add such support please contribute code...".
mruprich commented 6 months ago

Hi guys, just checking whether there is some update here. Is there a consensus on what would be the best approach?

infrastation commented 6 months ago

Perhaps updating the man page could be the easiest starting point.

infrastation commented 6 months ago

Apparently, tcpslice also fails to handle correctly an input file with 0 packets. tcpslice(1) now mentions that and the problems above.