From 01525fcb08bae1559900298b55807fe5c67e65d1 Mon Sep 17 00:00:00 2001 From: Adrian Serrano Date: Mon, 19 Mar 2018 16:53:18 +0100 Subject: [PATCH] Updated dependency `github.com/tsg/gopacket` (#6583) Fixes packetbeat termination problems with both af_packet and pcap captures. Fixes #6535 --- CHANGELOG.asciidoc | 1 + NOTICE.txt | 2 +- .../tsg/gopacket/afpacket/afpacket.go | 16 ++++-- vendor/github.com/tsg/gopacket/layers/lldp.go | 3 +- vendor/github.com/tsg/gopacket/pcap/pcap.go | 18 ++++++- .../tsg/gopacket/pcap/pcap_poll_common.go | 18 +++++++ .../tsg/gopacket/pcap/pcap_poll_linux.go | 52 +++++++++++++++++++ vendor/vendor.json | 4 +- 8 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 vendor/github.com/tsg/gopacket/pcap/pcap_poll_common.go create mode 100644 vendor/github.com/tsg/gopacket/pcap/pcap_poll_linux.go diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index b034cd010b8..7fe97248bad 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -310,6 +310,7 @@ https://github.com/elastic/beats/compare/v6.0.1...v6.1.0[View commits] - Fix corruption when parsing repeated headers in an HTTP request or response. {pull}6325[6325] - Fix panic when parsing partial AMQP messages. {pull}6384[6384] - Fix out of bounds access to slice in MongoDB parser. {pull}6256[6256] +- Fix sniffer hanging on exit under Linux. {pull}6535[6535] *Winlogbeat* diff --git a/NOTICE.txt b/NOTICE.txt index 6b80ef2b4bf..9b968540ef2 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -3259,7 +3259,7 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- Dependency: github.com/tsg/gopacket -Revision: 8e703b9968693c15f25cabb6ba8be4370cf431d0 +Revision: f289b3ea3e41a01b2822be9caf5f40c01fdda05c License type (autodetected): BSD-3-Clause ./vendor/github.com/tsg/gopacket/LICENSE: -------------------------------------------------------------------- diff --git a/vendor/github.com/tsg/gopacket/afpacket/afpacket.go b/vendor/github.com/tsg/gopacket/afpacket/afpacket.go index ed0c5ce73a7..fe622918a30 100644 --- a/vendor/github.com/tsg/gopacket/afpacket/afpacket.go +++ b/vendor/github.com/tsg/gopacket/afpacket/afpacket.go @@ -16,14 +16,16 @@ package afpacket import ( "errors" "fmt" - "github.com/tsg/gopacket" - "github.com/tsg/gopacket/layers" - "github.com/tsg/gopacket/pcap" "net" "runtime" "sync" + "syscall" "time" "unsafe" + + "github.com/tsg/gopacket" + "github.com/tsg/gopacket/layers" + "github.com/tsg/gopacket/pcap" ) /* @@ -310,7 +312,13 @@ func (h *TPacket) pollForFirstPacket(hdr header) error { h.pollset.events = C.POLLIN h.pollset.revents = 0 timeout := C.int(h.opts.timeout / time.Millisecond) - _, err := C.poll(&h.pollset, 1, timeout) + n, err := C.poll(&h.pollset, 1, timeout) + if n == 0 { + /* propagate timeout when no packets are available + otherwise it will loop forever until a packet + is received. */ + return syscall.EINTR + } h.stats.Polls++ if err != nil { return err diff --git a/vendor/github.com/tsg/gopacket/layers/lldp.go b/vendor/github.com/tsg/gopacket/layers/lldp.go index c77bd981ab3..613d382084c 100644 --- a/vendor/github.com/tsg/gopacket/layers/lldp.go +++ b/vendor/github.com/tsg/gopacket/layers/lldp.go @@ -9,6 +9,7 @@ package layers import ( "encoding/binary" "fmt" + "github.com/tsg/gopacket" ) @@ -737,7 +738,7 @@ func decodeLinkLayerDiscovery(data []byte, p gopacket.PacketBuilder) error { for len(vData) > 0 { nbit := vData[0] & 0x01 t := LLDPTLVType(vData[0] >> 1) - val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit<<8 + vData[1])} + val := LinkLayerDiscoveryValue{Type: t, Length: uint16(nbit)<<8 + uint16(vData[1])} if val.Length > 0 { val.Value = vData[2 : val.Length+2] } diff --git a/vendor/github.com/tsg/gopacket/pcap/pcap.go b/vendor/github.com/tsg/gopacket/pcap/pcap.go index f5612e6ffd2..c869bcc1599 100644 --- a/vendor/github.com/tsg/gopacket/pcap/pcap.go +++ b/vendor/github.com/tsg/gopacket/pcap/pcap.go @@ -131,6 +131,10 @@ type Handle struct { // huge memory hit, so to handle that we store them here instead. pkthdr *C.struct_pcap_pkthdr buf_ptr *C.u_char + // This is required to poll the pcap handle for incoming packets, due to + // newer Linux kernels supporting TPACKET_V3 not starting the timeout until + // the first packet is received. + packetPoller *packetPoll } // Stats contains statistics on how many packets were handled by a pcap handle, @@ -206,10 +210,14 @@ func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) dev := C.CString(device) defer C.free(unsafe.Pointer(dev)) - p.cptr = C.pcap_open_live(dev, C.int(snaplen), pro, timeoutMillis(timeout), buf) + timeoutMs := timeoutMillis(timeout) + p.cptr = C.pcap_open_live(dev, C.int(snaplen), pro, timeoutMs, buf) if p.cptr == nil { return nil, errors.New(C.GoString(buf)) } + if !p.blockForever { + p.packetPoller = NewPacketPoll(p.cptr, timeoutMs) + } return p, nil } @@ -316,6 +324,9 @@ func (a activateError) Error() string { func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error { var result NextError for { + if !p.packetPoller.AwaitForPackets() { + return NextErrorTimeoutExpired + } result = NextError(C.pcap_next_ex(p.cptr, &p.pkthdr, &p.buf_ptr)) if p.blockForever && result == NextErrorTimeoutExpired { continue @@ -544,6 +555,11 @@ func findalladdresses(addresses *_Ctype_struct_pcap_addr) (retval []InterfaceAdd for curaddr := addresses; curaddr != nil; curaddr = (*_Ctype_struct_pcap_addr)(curaddr.next) { var a InterfaceAddress var err error + // In case of a tun device on Linux the link layer has no curaddr.addr. + // Do not crash trying to check the family type. + if curaddr.addr == nil { + continue + } if a.IP, err = sockaddr_to_IP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.addr))); err != nil { continue } diff --git a/vendor/github.com/tsg/gopacket/pcap/pcap_poll_common.go b/vendor/github.com/tsg/gopacket/pcap/pcap_poll_common.go new file mode 100644 index 00000000000..9d96f485a58 --- /dev/null +++ b/vendor/github.com/tsg/gopacket/pcap/pcap_poll_common.go @@ -0,0 +1,18 @@ +// +build !linux + +package pcap + +/* +#include +*/ +import "C" + +type packetPoll struct{} + +func NewPacketPoll(_ *C.pcap_t, _ C.int) *packetPoll { + return nil +} + +func (t *packetPoll) AwaitForPackets() bool { + return true +} diff --git a/vendor/github.com/tsg/gopacket/pcap/pcap_poll_linux.go b/vendor/github.com/tsg/gopacket/pcap/pcap_poll_linux.go new file mode 100644 index 00000000000..30ec8de72f0 --- /dev/null +++ b/vendor/github.com/tsg/gopacket/pcap/pcap_poll_linux.go @@ -0,0 +1,52 @@ +// +build linux + +package pcap + +/* +#include +#include +#include +*/ +import "C" +import "syscall" + +// packetPoll holds all the parameters required to use poll(2) on the pcap +// file descriptor. +type packetPoll struct { + pollfd C.struct_pollfd + timeout C.int +} + +func captureIsTPacketV3(fildes int) bool { + version, err := syscall.GetsockoptInt(fildes, syscall.SOL_PACKET, C.PACKET_VERSION) + return err == nil && version == C.TPACKET_V3 +} + +// NewPacketPoll returns a new packetPoller if the pcap handle requires it +// in order to timeout effectively when no packets are received. This is only +// necessary when TPACKET_V3 interface is used to receive packets. +func NewPacketPoll(ptr *C.pcap_t, timeout C.int) *packetPoll { + fildes := C.pcap_fileno(ptr) + if !captureIsTPacketV3(int(fildes)) { + return nil + } + return &packetPoll{ + pollfd: C.struct_pollfd{ + fd: fildes, + events: C.POLLIN, + revents: 0, + }, + timeout: timeout, + } +} + +func (t *packetPoll) AwaitForPackets() bool { + if t != nil { + t.pollfd.revents = 0 + // block until the capture file descriptor is readable or a timeout + // happens. + n, err := C.poll(&t.pollfd, 1, t.timeout) + return err != nil || n != 0 + } + return true +} diff --git a/vendor/vendor.json b/vendor/vendor.json index c1f4d7d194d..51423b2afaa 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -971,8 +971,8 @@ { "checksumSHA1": "M0S9278lG9Fztu+ZUsLUi40GDJU=", "path": "github.com/tsg/gopacket", - "revision": "8e703b9968693c15f25cabb6ba8be4370cf431d0", - "revisionTime": "2016-08-17T18:24:57Z" + "revision": "f289b3ea3e41a01b2822be9caf5f40c01fdda05c", + "revisionTime": "2018-03-16T21:03:30Z" }, { "checksumSHA1": "STY8i3sZLdZfFcKiyOdpV852nls=",