diff --git a/capture/capture.go b/capture/capture.go index 8175b1a..4d69b20 100644 --- a/capture/capture.go +++ b/capture/capture.go @@ -253,6 +253,7 @@ func (l *Listener) Listen(ctx context.Context) (err error) { break } } + l.Unlock() } } @@ -585,6 +586,10 @@ func (l *Listener) readHandle(key string, hndl packetHandle) { continue } if err == io.EOF || err == io.ErrClosedPipe { + // File replays too fast, give it some time to process packets + if l.config.Engine == EnginePcapFile { + time.Sleep(time.Second) + } log.Printf("stopped reading from %s interface with error %s\n", key, err) return } diff --git a/tcp/tcp_packet.go b/tcp/tcp_packet.go index 43fb994..bbf3fc7 100644 --- a/tcp/tcp_packet.go +++ b/tcp/tcp_packet.go @@ -110,6 +110,7 @@ func (pckt *Packet) parse(data []byte, lType, lTypeLen int, cp *gopacket.Capture ldata := data[lTypeLen:] var proto byte var netLayer, transLayer []byte + var tcpLen int if ldata[0]>>4 == 4 { // IPv4 header @@ -124,6 +125,10 @@ func (pckt *Packet) parse(data []byte, lType, lTypeLen int, cp *gopacket.Capture if len(ldata) < ihl { return ErrHdrLength("IPv4 opts") } + + totalPacketLen := binary.BigEndian.Uint16(ldata[2:4]) + tcpLen = int(totalPacketLen) - ihl + netLayer = ldata[:ihl] } else if ldata[0]>>4 == 6 { if len(ldata) < 40 { @@ -146,6 +151,10 @@ func (pckt *Packet) parse(data []byte, lType, lTypeLen int, cp *gopacket.Capture proto = ldata[totalLen] totalLen += extLen } + + totalPacketLen := binary.BigEndian.Uint16(ldata[4:6]) + tcpLen = int(totalPacketLen) - totalLen + netLayer = ldata[:totalLen] } else { return ErrHdrExpected("IPv4 or IPv6") @@ -157,6 +166,12 @@ func (pckt *Packet) parse(data []byte, lType, lTypeLen int, cp *gopacket.Capture return ErrHdrMissing("TCP") } ndata := ldata[len(netLayer):] + + // When packet is less then 60 bytes, ethernet layer can add trailers to the end of packet + // IP layer has total length of the payload, so here we ensure that we operate only on TCP packet layer + // https://stackoverflow.com/questions/13738206/ip-packet-has-trailer-on-the-receiver-side-but-not-on-the-sender-side + ndata = ndata[:tcpLen] + // TCP header if len(ndata) < 20 { return ErrHdrLength("TCP")