diff --git a/pcap/pcap.go b/pcap/pcap.go index c28e65d05..723651bbb 100644 --- a/pcap/pcap.go +++ b/pcap/pcap.go @@ -15,7 +15,6 @@ import ( "github.com/gopacket/gopacket" "github.com/gopacket/gopacket/layers" - "github.com/gopacket/gopacket/pcap" "github.com/gopacket/gopacket/pcapgo" "golang.org/x/crypto/ssh" @@ -286,22 +285,18 @@ func openPcapHandle(tcpdumpCmd string, session *ssh.Session, wg *sync.WaitGroup, // The pcap handle can be created without blocking after readable exists. out := make(chan gopacket.Packet) go func() { - handle, err := pcap.OpenOfflineFile(readable) + ngReader, err := pcapgo.NewReader(readable) if err != nil { cancel(openHandleError) return } - packetSource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet) + packetSource := gopacket.NewPacketSource(ngReader, layers.LayerTypeEthernet) // Run a goroutine that will write packets to the channel - go func() { - defer handle.Close() - - for packet := range packetSource.Packets() { - out <- packet - } - }() + for packet := range packetSource.Packets() { + out <- packet + } }() return out, nil } diff --git a/vendor/github.com/gopacket/gopacket/pcap/defs_windows.go b/vendor/github.com/gopacket/gopacket/pcap/defs_windows.go deleted file mode 100644 index 774e907e8..000000000 --- a/vendor/github.com/gopacket/gopacket/pcap/defs_windows.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2019 The GoPacket Authors. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -// This file contains necessary structs/constants generated from libpcap headers with cgo -godefs -// generated with: generate_defs.exe -// DO NOT MODIFY - -package pcap - -import "syscall" - -const errorBufferSize = 0x100 - -const ( - pcapErrorNotActivated = -0x3 - pcapErrorActivated = -0x4 - pcapWarningPromisc = 0x2 - pcapErrorNoSuchDevice = -0x5 - pcapErrorDenied = -0x8 - pcapErrorNotUp = -0x9 - pcapError = -0x1 - pcapWarning = 0x1 - pcapDIN = 0x1 - pcapDOUT = 0x2 - pcapDINOUT = 0x0 - pcapNetmaskUnknown = 0xffffffff - pcapTstampPrecisionMicro = 0x0 - pcapTstampPrecisionNano = 0x1 -) - -type timeval struct { - Sec int32 - Usec int32 -} -type pcapPkthdr struct { - Ts timeval - Caplen uint32 - Len uint32 -} -type pcapTPtr uintptr -type pcapBpfInstruction struct { - Code uint16 - Jt uint8 - Jf uint8 - K uint32 -} -type pcapBpfProgram struct { - Len uint32 - Insns *pcapBpfInstruction -} -type pcapStats struct { - Recv uint32 - Drop uint32 - Ifdrop uint32 -} -type pcapCint int32 -type pcapIf struct { - Next *pcapIf - Name *int8 - Description *int8 - Addresses *pcapAddr - Flags uint32 -} - -type pcapAddr struct { - Next *pcapAddr - Addr *syscall.RawSockaddr - Netmask *syscall.RawSockaddr - Broadaddr *syscall.RawSockaddr - Dstaddr *syscall.RawSockaddr -} diff --git a/vendor/github.com/gopacket/gopacket/pcap/doc.go b/vendor/github.com/gopacket/gopacket/pcap/doc.go deleted file mode 100644 index 7cdc7a83a..000000000 --- a/vendor/github.com/gopacket/gopacket/pcap/doc.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -/* -Package pcap allows users of gopacket to read packets off the wire or from -pcap files. - -This package is meant to be used with its parent, -http://github.com/gopacket/gopacket, although it can also be used independently -if you just want to get packet data from the wire. - -Depending on libpcap version, os support, or file timestamp resolution, -nanosecond resolution is used for the internal timestamps. Returned timestamps -are always scaled to nanosecond resolution due to the usage of time.Time. -libpcap must be at least version 1.5 to support nanosecond timestamps. OpenLive -supports only microsecond resolution. - -# Reading PCAP Files - -The following code can be used to read in data from a pcap file. - - if handle, err := pcap.OpenOffline("/path/to/my/file"); err != nil { - panic(err) - } else { - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - for packet := range packetSource.Packets() { - handlePacket(packet) // Do something with a packet here. - } - } - -# Reading Live Packets - -The following code can be used to read in data from a live device, in this case -"eth0". Be aware, that OpenLive only supports microsecond resolution. - - if handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever); err != nil { - panic(err) - } else if err := handle.SetBPFFilter("tcp and port 80"); err != nil { // optional - panic(err) - } else { - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - for packet := range packetSource.Packets() { - handlePacket(packet) // Do something with a packet here. - } - } - -# Inactive Handles - -Newer PCAP functionality requires the concept of an 'inactive' PCAP handle. -Instead of constantly adding new arguments to pcap_open_live, users now call -pcap_create to create a handle, set it up with a bunch of optional function -calls, then call pcap_activate to activate it. This library mirrors that -mechanism, for those that want to expose/use these new features: - - inactive, err := pcap.NewInactiveHandle(deviceName) - if err != nil { - log.Fatal(err) - } - defer inactive.CleanUp() - - // Call various functions on inactive to set it up the way you'd like: - if err = inactive.SetTimeout(time.Minute); err != nil { - log.Fatal(err) - } else if err = inactive.SetTimestampSource("foo"); err != nil { - log.Fatal(err) - } - - // Finally, create the actual handle by calling Activate: - handle, err := inactive.Activate() // after this, inactive is no longer valid - if err != nil { - log.Fatal(err) - } - defer handle.Close() - - // Now use your handle as you see fit. - -# PCAP Timeouts - -pcap.OpenLive and pcap.SetTimeout both take timeouts. -If you don't care about timeouts, just pass in BlockForever, -which should do what you expect with minimal fuss. - -A timeout of 0 is not recommended. Some platforms, like Macs -(http://www.manpages.info/macosx/pcap.3.html) say: - - The read timeout is used to arrange that the read not necessarily return - immediately when a packet is seen, but that it wait for some amount of time - to allow more packets to arrive and to read multiple packets from the OS - kernel in one operation. - -This means that if you only capture one packet, the kernel might decide to wait -'timeout' for more packets to batch with it before returning. A timeout of -0, then, means 'wait forever for more packets', which is... not good. - -To get around this, we've introduced the following behavior: if a negative -timeout is passed in, we set the positive timeout in the handle, then loop -internally in ReadPacketData/ZeroCopyReadPacketData when we see timeout -errors. - -# PCAP File Writing - -This package does not implement PCAP file writing. However, gopacket/pcapgo -does! Look there if you'd like to write PCAP files. - -# Note For Windows Users - -gopacket can use winpcap or npcap. If both are installed at the same time, -npcap is preferred. Make sure the right windows service is loaded (npcap for npcap -and npf for winpcap). -*/ -package pcap diff --git a/vendor/github.com/gopacket/gopacket/pcap/pcap.go b/vendor/github.com/gopacket/gopacket/pcap/pcap.go deleted file mode 100644 index 8093abb5e..000000000 --- a/vendor/github.com/gopacket/gopacket/pcap/pcap.go +++ /dev/null @@ -1,879 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// Copyright 2009-2011 Andreas Krennmair. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -package pcap - -import ( - "errors" - "fmt" - "io" - "net" - "os" - "reflect" - "runtime" - "strconv" - "sync" - "sync/atomic" - "syscall" - "time" - "unsafe" - - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/layers" -) - -// ErrNotActive is returned if handle is not activated -const ErrNotActive = pcapErrorNotActivated - -// MaxBpfInstructions is the maximum number of BPF instructions supported (BPF_MAXINSNS), -// taken from Linux kernel: include/uapi/linux/bpf_common.h -// -// https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf_common.h -const MaxBpfInstructions = 4096 - -// 8 bytes per instruction, max 4096 instructions -const bpfInstructionBufferSize = 8 * MaxBpfInstructions - -// Handle provides a connection to a pcap handle, allowing users to read packets -// off the wire (Next), inject packets onto the wire (Inject), and -// perform a number of other functions to affect and understand packet output. -// -// Handles are already pcap_activate'd -type Handle struct { - // stop is set to a non-zero value by Handle.Close to signal to - // getNextBufPtrLocked to stop trying to read packets - // This must be the first entry to ensure alignment for sync.atomic - stop uint64 - // cptr is the handle for the actual pcap C object. - cptr pcapTPtr - timeout time.Duration - device string - deviceIndex int - mu sync.Mutex - closeMu sync.Mutex - nanoSecsFactor int64 - - // Since pointers to these objects are passed into a C function, if - // they're declared locally then the Go compiler thinks they may have - // escaped into C-land, so it allocates them on the heap. This causes a - // huge memory hit, so to handle that we store them here instead. - pkthdr *pcapPkthdr - bufptr *uint8 -} - -// Stats contains statistics on how many packets were handled by a pcap handle, -// and what was done with those packets. -type Stats struct { - PacketsReceived int - PacketsDropped int - PacketsIfDropped int -} - -// Interface describes a single network interface on a machine. -type Interface struct { - Name string - Description string - Flags uint32 - Addresses []InterfaceAddress -} - -// Datalink describes the datalink -type Datalink struct { - Name string - Description string -} - -// InterfaceAddress describes an address associated with an Interface. -// Currently, it's IPv4/6 specific. -type InterfaceAddress struct { - IP net.IP - Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it. - Broadaddr net.IP // Broadcast address for this IP may be nil - P2P net.IP // P2P destination address for this IP may be nil -} - -// bpfFilter keeps C.struct_bpf_program separate from BPF.orig which might be a pointer to go memory. -// This is a workaround for https://github.com/golang/go/issues/32970 which will be fixed in go1.14. -// (type conversion is in pcap_unix.go pcapOfflineFilter) -type bpfFilter struct { - bpf pcapBpfProgram // takes a finalizer, not overriden by outsiders -} - -// BPF is a compiled filter program, useful for offline packet matching. -type BPF struct { - orig string - bpf *bpfFilter - hdr pcapPkthdr // allocate on the heap to enable optimizations -} - -// BPFInstruction is a byte encoded structure holding a BPF instruction -type BPFInstruction struct { - Code uint16 - Jt uint8 - Jf uint8 - K uint32 -} - -// BlockForever causes it to block forever waiting for packets, when passed -// into SetTimeout or OpenLive, while still returning incoming packets to userland relatively -// quickly. -const BlockForever = -time.Millisecond * 10 - -func timeoutMillis(timeout time.Duration) int { - // Flip sign if necessary. See package docs on timeout for reasoning behind this. - if timeout < 0 { - timeout *= -1 - } - // Round up - if timeout != 0 && timeout < time.Millisecond { - timeout = time.Millisecond - } - return int(timeout / time.Millisecond) -} - -// OpenLive opens a device and returns a *Handle. -// It takes as arguments the name of the device ("eth0"), the maximum size to -// read for each packet (snaplen), whether to put the interface in promiscuous -// mode, and a timeout. Warning: this function supports only microsecond timestamps. -// For nanosecond resolution use an InactiveHandle. -// -// See the package documentation for important details regarding 'timeout'. -func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) { - var pro int - if promisc { - pro = 1 - } - - p, err := pcapOpenLive(device, int(snaplen), pro, timeoutMillis(timeout)) - if err != nil { - return nil, err - } - p.timeout = timeout - p.device = device - - ifc, err := net.InterfaceByName(device) - if err != nil { - // The device wasn't found in the OS, but could be "any" - // Set index to 0 - p.deviceIndex = 0 - } else { - p.deviceIndex = ifc.Index - } - - p.nanoSecsFactor = 1000 - - // Only set the PCAP handle into non-blocking mode if we have a timeout - // greater than zero. If the user wants to block forever, we'll let libpcap - // handle that. - if p.timeout > 0 { - if err := p.setNonBlocking(); err != nil { - p.pcapClose() - return nil, err - } - } - - return p, nil -} - -// OpenOffline opens a file and returns its contents as a *Handle. Depending on libpcap support and -// on the timestamp resolution used in the file, nanosecond or microsecond resolution is used -// internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used -// to query the actual resolution used. -func OpenOffline(file string) (handle *Handle, err error) { - handle, err = openOffline(file) - if err != nil { - return - } - if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { - handle.nanoSecsFactor = 1 - } else { - handle.nanoSecsFactor = 1000 - } - return -} - -// OpenOfflineFile returns contents of input file as a *Handle. Depending on libpcap support and -// on the timestamp resolution used in the file, nanosecond or microsecond resolution is used -// internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used -// to query the actual resolution used. -func OpenOfflineFile(file *os.File) (handle *Handle, err error) { - handle, err = openOfflineFile(file) - if err != nil { - return - } - if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { - handle.nanoSecsFactor = 1 - } else { - handle.nanoSecsFactor = 1000 - } - return -} - -// NextError is the return code from a call to Next. -type NextError int32 - -// NextError implements the error interface. -func (n NextError) Error() string { - switch n { - case NextErrorOk: - return "OK" - case NextErrorTimeoutExpired: - return "Timeout Expired" - case NextErrorReadError: - return "Read Error" - case NextErrorNoMorePackets: - return "No More Packets In File" - case NextErrorNotActivated: - return "Not Activated" - } - return strconv.Itoa(int(n)) -} - -// NextError values. -const ( - NextErrorOk NextError = 1 - NextErrorTimeoutExpired NextError = 0 - NextErrorReadError NextError = -1 - // NextErrorNoMorePackets is returned when reading from a file (OpenOffline) and - // EOF is reached. When this happens, Next() returns io.EOF instead of this. - NextErrorNoMorePackets NextError = -2 - NextErrorNotActivated NextError = -3 -) - -// ReadPacketData returns the next packet read from the pcap handle, along with an error -// code associated with that packet. If the packet is read successfully, the -// returned error is nil. -func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) { - p.mu.Lock() - err = p.getNextBufPtrLocked(&ci) - if err == nil { - data = make([]byte, ci.CaptureLength) - copy(data, (*(*[1 << 30]byte)(unsafe.Pointer(p.bufptr)))[:]) - } - p.mu.Unlock() - if err == NextErrorTimeoutExpired { - runtime.Gosched() - } - return -} - -type activateError int - -const ( - aeNoError = activateError(0) - aeActivated = activateError(pcapErrorActivated) - aePromisc = activateError(pcapWarningPromisc) - aeNoSuchDevice = activateError(pcapErrorNoSuchDevice) - aeDenied = activateError(pcapErrorDenied) - aeNotUp = activateError(pcapErrorNotUp) - aeWarning = activateError(pcapWarning) - aeError = activateError(pcapError) -) - -func (a activateError) Error() string { - switch a { - case aeNoError: - return "No Error" - case aeActivated: - return "Already Activated" - case aePromisc: - return "Cannot set as promisc" - case aeNoSuchDevice: - return "No Such Device" - case aeDenied: - return "Permission Denied" - case aeNotUp: - return "Interface Not Up" - case aeWarning: - return fmt.Sprintf("Warning: %v", activateErrMsg.Error()) - case aeError: - return fmt.Sprintf("Error: %v", activateErrMsg.Error()) - default: - return fmt.Sprintf("unknown activated error: %d", a) - } -} - -// getNextBufPtrLocked is shared code for ReadPacketData and -// ZeroCopyReadPacketData. -func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error { - if !p.isOpen() { - return io.EOF - } - - // set after we have call waitForPacket for the first time - var waited bool - - for atomic.LoadUint64(&p.stop) == 0 { - // try to read a packet if one is immediately available - result := p.pcapNextPacketEx() - - switch result { - case NextErrorOk: - sec := p.pkthdr.getSec() - // convert micros to nanos - nanos := int64(p.pkthdr.getUsec()) * p.nanoSecsFactor - - ci.Timestamp = time.Unix(sec, nanos) - ci.CaptureLength = p.pkthdr.getCaplen() - ci.Length = p.pkthdr.getLen() - ci.InterfaceIndex = p.deviceIndex - - return nil - case NextErrorNoMorePackets: - // no more packets, return EOF rather than libpcap-specific error - return io.EOF - case NextErrorTimeoutExpired: - // we've already waited for a packet and we're supposed to time out - // - // we should never actually hit this if we were passed BlockForever - // since we should block on C.pcap_next_ex until there's a packet - // to read. - if waited && p.timeout > 0 { - return result - } - - // wait for packet before trying again - p.waitForPacket() - waited = true - default: - return result - } - } - - // stop must be set - return io.EOF -} - -// ZeroCopyReadPacketData reads the next packet off the wire, and returns its data. -// The slice returned by ZeroCopyReadPacketData points to bytes owned by the -// the Handle. Each call to ZeroCopyReadPacketData invalidates any data previously -// returned by ZeroCopyReadPacketData. Care must be taken not to keep pointers -// to old bytes when using ZeroCopyReadPacketData... if you need to keep data past -// the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies -// the bytes into a new buffer for you. -// -// data1, _, _ := handle.ZeroCopyReadPacketData() -// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around. -// data2, _, _ := handle.ZeroCopyReadPacketData() // invalidates bytes in data1 -func (p *Handle) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) { - p.mu.Lock() - err = p.getNextBufPtrLocked(&ci) - if err == nil { - slice := (*reflect.SliceHeader)(unsafe.Pointer(&data)) - slice.Data = uintptr(unsafe.Pointer(p.bufptr)) - slice.Len = ci.CaptureLength - slice.Cap = ci.CaptureLength - } - p.mu.Unlock() - if err == NextErrorTimeoutExpired { - runtime.Gosched() - } - return -} - -// Close closes the underlying pcap handle. -func (p *Handle) Close() { - p.closeMu.Lock() - defer p.closeMu.Unlock() - - if !p.isOpen() { - return - } - - atomic.StoreUint64(&p.stop, 1) - - // wait for packet reader to stop - p.mu.Lock() - defer p.mu.Unlock() - - p.pcapClose() -} - -// Error returns the current error associated with a pcap handle (pcap_geterr). -func (p *Handle) Error() error { - return p.pcapGeterr() -} - -// Stats returns statistics on the underlying pcap handle. -func (p *Handle) Stats() (stat *Stats, err error) { - return p.pcapStats() -} - -// ListDataLinks obtains a list of all possible data link types supported for an interface. -func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) { - return p.pcapListDatalinks() -} - -// compileBPFFilter always returns an allocated C.struct_bpf_program -// It is the callers responsibility to free the memory again, e.g. -// -// C.pcap_freecode(&bpf) -func (p *Handle) compileBPFFilter(expr string) (pcapBpfProgram, error) { - var maskp = uint32(pcapNetmaskUnknown) - - // Only do the lookup on network interfaces. - // No device indicates we're handling a pcap file. - if len(p.device) > 0 { - var err error - _, maskp, err = pcapLookupnet(p.device) - if err != nil { - // We can't lookup the network, but that could be because the interface - // doesn't have an IPv4. - maskp = uint32(pcapNetmaskUnknown) - } - } - - return p.pcapCompile(expr, maskp) -} - -// CompileBPFFilter compiles and returns a BPF filter with given a link type and capture length. -func CompileBPFFilter(linkType layers.LinkType, captureLength int, expr string) ([]BPFInstruction, error) { - h, err := pcapOpenDead(linkType, captureLength) - if err != nil { - return nil, err - } - defer h.Close() - return h.CompileBPFFilter(expr) -} - -// CompileBPFFilter compiles and returns a BPF filter for the pcap handle. -func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error) { - bpf, err := p.compileBPFFilter(expr) - defer bpf.free() - if err != nil { - return nil, err - } - - return bpf.toBPFInstruction(), nil -} - -// SetBPFFilter compiles and sets a BPF filter for the pcap handle. -func (p *Handle) SetBPFFilter(expr string) (err error) { - bpf, err := p.compileBPFFilter(expr) - defer bpf.free() - if err != nil { - return err - } - - return p.pcapSetfilter(bpf) -} - -// SetBPFInstructionFilter may be used to apply a filter in BPF asm byte code format. -// -// Simplest way to generate BPF asm byte code is with tcpdump: -// -// tcpdump -dd 'udp' -// -// The output may be used directly to add a filter, e.g.: -// -// bpfInstructions := []pcap.BpfInstruction{ -// {0x28, 0, 0, 0x0000000c}, -// {0x15, 0, 9, 0x00000800}, -// {0x30, 0, 0, 0x00000017}, -// {0x15, 0, 7, 0x00000006}, -// {0x28, 0, 0, 0x00000014}, -// {0x45, 5, 0, 0x00001fff}, -// {0xb1, 0, 0, 0x0000000e}, -// {0x50, 0, 0, 0x0000001b}, -// {0x54, 0, 0, 0x00000012}, -// {0x15, 0, 1, 0x00000012}, -// {0x6, 0, 0, 0x0000ffff}, -// {0x6, 0, 0, 0x00000000}, -// } -// -// An other posibility is to write the bpf code in bpf asm. -// Documentation: https://www.kernel.org/doc/Documentation/networking/filter.txt -// -// To compile the code use bpf_asm from -// https://github.com/torvalds/linux/tree/master/tools/net -// -// The following command may be used to convert bpf_asm output to c/go struct, usable for SetBPFFilterByte: -// bpf_asm -c tcp.bpf -func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error) { - bpf, err := bpfInstructionFilter(bpfInstructions) - if err != nil { - return err - } - defer bpf.free() - - return p.pcapSetfilter(bpf) -} - -func bpfInstructionFilter(bpfInstructions []BPFInstruction) (bpf pcapBpfProgram, err error) { - if len(bpfInstructions) < 1 { - return bpf, errors.New("bpfInstructions must not be empty") - } - - if len(bpfInstructions) > MaxBpfInstructions { - return bpf, fmt.Errorf("bpfInstructions must not be larger than %d", MaxBpfInstructions) - } - - return pcapBpfProgramFromInstructions(bpfInstructions), nil -} - -// NewBPF compiles the given string into a new filter program. -// -// BPF filters need to be created from activated handles, because they need to -// know the underlying link type to correctly compile their offsets. -func (p *Handle) NewBPF(expr string) (*BPF, error) { - bpf := &BPF{orig: expr, bpf: new(bpfFilter)} - - var err error - bpf.bpf.bpf, err = p.pcapCompile(expr, pcapNetmaskUnknown) - if err != nil { - return nil, err - } - - runtime.SetFinalizer(bpf, destroyBPF) - return bpf, nil -} - -// NewBPF allows to create a BPF without requiring an existing handle. -// This allows to match packets obtained from a-non GoPacket capture source -// to be matched. -// -// buf := make([]byte, MaxFrameSize) -// bpfi, _ := pcap.NewBPF(layers.LinkTypeEthernet, MaxFrameSize, "icmp") -// n, _ := someIO.Read(buf) -// ci := gopacket.CaptureInfo{CaptureLength: n, Length: n} -// if bpfi.Matches(ci, buf) { -// doSomething() -// } -func NewBPF(linkType layers.LinkType, captureLength int, expr string) (*BPF, error) { - h, err := pcapOpenDead(linkType, captureLength) - if err != nil { - return nil, err - } - defer h.Close() - return h.NewBPF(expr) -} - -// NewBPFInstructionFilter sets the given BPFInstructions as new filter program. -// -// # More details see func SetBPFInstructionFilter -// -// BPF filters need to be created from activated handles, because they need to -// know the underlying link type to correctly compile their offsets. -func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error) { - var err error - bpf := &BPF{orig: "BPF Instruction Filter", bpf: new(bpfFilter)} - - bpf.bpf.bpf, err = bpfInstructionFilter(bpfInstructions) - if err != nil { - return nil, err - } - - runtime.SetFinalizer(bpf, destroyBPF) - return bpf, nil -} -func destroyBPF(bpf *BPF) { - bpf.bpf.bpf.free() -} - -// String returns the original string this BPF filter was compiled from. -func (b *BPF) String() string { - return b.orig -} - -// Matches returns true if the given packet data matches this filter. -func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool { - return b.pcapOfflineFilter(ci, data) -} - -// Version returns pcap_lib_version. -func Version() string { - return pcapLibVersion() -} - -// LinkType returns pcap_datalink, as a layers.LinkType. -func (p *Handle) LinkType() layers.LinkType { - return p.pcapDatalink() -} - -// SetLinkType calls pcap_set_datalink on the pcap handle. -func (p *Handle) SetLinkType(dlt layers.LinkType) error { - return p.pcapSetDatalink(dlt) -} - -// DatalinkValToName returns pcap_datalink_val_to_name as string -func DatalinkValToName(dlt int) string { - return pcapDatalinkValToName(dlt) -} - -// DatalinkValToDescription returns pcap_datalink_val_to_description as string -func DatalinkValToDescription(dlt int) string { - return pcapDatalinkValToDescription(dlt) -} - -// DatalinkNameToVal returns pcap_datalink_name_to_val as int -func DatalinkNameToVal(name string) int { - return pcapDatalinkNameToVal(name) -} - -// FindAllDevs attempts to enumerate all interfaces on the current machine. -func FindAllDevs() (ifs []Interface, err error) { - alldevsp, err := pcapFindAllDevs() - if err != nil { - return nil, err - } - defer alldevsp.free() - - for alldevsp.next() { - var iface Interface - iface.Name = alldevsp.name() - iface.Description = alldevsp.description() - iface.Addresses = findalladdresses(alldevsp.addresses()) - iface.Flags = alldevsp.flags() - ifs = append(ifs, iface) - } - return -} - -func findalladdresses(addresses pcapAddresses) (retval []InterfaceAddress) { - // TODO - make it support more than IPv4 and IPv6? - retval = make([]InterfaceAddress, 0, 1) - for addresses.next() { - // Strangely, it appears that in some cases, we get a pcap address back from - // pcap_findalldevs with a nil .addr. It appears that we can skip over - // these. - if addresses.addr() == nil { - continue - } - var a InterfaceAddress - var err error - if a.IP, err = sockaddrToIP(addresses.addr()); err != nil { - continue - } - // To be safe, we'll also check for netmask. - if addresses.netmask() == nil { - continue - } - if a.Netmask, err = sockaddrToIP(addresses.netmask()); err != nil { - // If we got an IP address but we can't get a netmask, just return the IP - // address. - a.Netmask = nil - } - if a.Broadaddr, err = sockaddrToIP(addresses.broadaddr()); err != nil { - a.Broadaddr = nil - } - if a.P2P, err = sockaddrToIP(addresses.dstaddr()); err != nil { - a.P2P = nil - } - retval = append(retval, a) - } - return -} - -func sockaddrToIP(rsa *syscall.RawSockaddr) (IP []byte, err error) { - if rsa == nil { - err = errors.New("Value not set") - return - } - switch rsa.Family { - case syscall.AF_INET: - pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) - IP = make([]byte, 4) - for i := 0; i < len(IP); i++ { - IP[i] = pp.Addr[i] - } - return - case syscall.AF_INET6: - pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) - IP = make([]byte, 16) - for i := 0; i < len(IP); i++ { - IP[i] = pp.Addr[i] - } - return - } - err = errors.New("Unsupported address type") - return -} - -// WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle. -func (p *Handle) WritePacketData(data []byte) (err error) { - return p.pcapSendpacket(data) -} - -// Direction is used by Handle.SetDirection. -type Direction uint8 - -// Direction values for Handle.SetDirection. -const ( - DirectionIn = Direction(pcapDIN) - DirectionOut = Direction(pcapDOUT) - DirectionInOut = Direction(pcapDINOUT) -) - -// SetDirection sets the direction for which packets will be captured. -func (p *Handle) SetDirection(direction Direction) error { - if direction != DirectionIn && direction != DirectionOut && direction != DirectionInOut { - return fmt.Errorf("Invalid direction: %v", direction) - } - return p.pcapSetdirection(direction) -} - -// SnapLen returns the snapshot length -func (p *Handle) SnapLen() int { - return p.pcapSnapshot() -} - -// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution. -func (p *Handle) Resolution() gopacket.TimestampResolution { - if p.nanoSecsFactor == 1 { - return gopacket.TimestampResolutionMicrosecond - } - return gopacket.TimestampResolutionNanosecond -} - -// TimestampSource tells PCAP which type of timestamp to use for packets. -type TimestampSource int - -// String returns the timestamp type as a human-readable string. -func (t TimestampSource) String() string { - return t.pcapTstampTypeValToName() -} - -// TimestampSourceFromString translates a string into a timestamp type, case -// insensitive. -func TimestampSourceFromString(s string) (TimestampSource, error) { - return pcapTstampTypeNameToVal(s) -} - -// InactiveHandle allows you to call pre-pcap_activate functions on your pcap -// handle to set it up just the way you'd like. -type InactiveHandle struct { - // cptr is the handle for the actual pcap C object. - cptr pcapTPtr - device string - deviceIndex int - timeout time.Duration -} - -// holds the err messoge in case activation returned a Warning -var activateErrMsg error - -// Error returns the current error associated with a pcap handle (pcap_geterr). -func (p *InactiveHandle) Error() error { - return p.pcapGeterr() -} - -// Activate activates the handle. The current InactiveHandle becomes invalid -// and all future function calls on it will fail. -func (p *InactiveHandle) Activate() (*Handle, error) { - // ignore error with set_tstamp_precision, since the actual precision is queried later anyway - pcapSetTstampPrecision(p.cptr, pcapTstampPrecisionNano) - handle, err := p.pcapActivate() - if err != aeNoError { - if err == aeWarning || err == aeError { - activateErrMsg = p.Error() - } - return nil, err - } - handle.timeout = p.timeout - if p.timeout > 0 { - if err := handle.setNonBlocking(); err != nil { - handle.pcapClose() - return nil, err - } - } - handle.device = p.device - handle.deviceIndex = p.deviceIndex - if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano { - handle.nanoSecsFactor = 1 - } else { - handle.nanoSecsFactor = 1000 - } - return handle, nil -} - -// CleanUp cleans up any stuff left over from a successful or failed building -// of a handle. -func (p *InactiveHandle) CleanUp() { - p.pcapClose() -} - -// NewInactiveHandle creates a new InactiveHandle, which wraps an un-activated PCAP handle. -// Callers of NewInactiveHandle should immediately defer 'CleanUp', as in: -// -// inactive := NewInactiveHandle("eth0") -// defer inactive.CleanUp() -func NewInactiveHandle(device string) (*InactiveHandle, error) { - // Try to get the interface index, but iy could be something like "any" - // in which case use 0, which doesn't exist in nature - deviceIndex := 0 - ifc, err := net.InterfaceByName(device) - if err == nil { - deviceIndex = ifc.Index - } - - // This copies a bunch of the pcap_open_live implementation from pcap.c: - handle, err := pcapCreate(device) - if err != nil { - return nil, err - } - handle.device = device - handle.deviceIndex = deviceIndex - return handle, nil -} - -// SetSnapLen sets the snap length (max bytes per packet to capture). -func (p *InactiveHandle) SetSnapLen(snaplen int) error { - return p.pcapSetSnaplen(snaplen) -} - -// SetPromisc sets the handle to either be promiscuous (capture packets -// unrelated to this host) or not. -func (p *InactiveHandle) SetPromisc(promisc bool) error { - return p.pcapSetPromisc(promisc) -} - -// SetTimeout sets the read timeout for the handle. -// -// See the package documentation for important details regarding 'timeout'. -func (p *InactiveHandle) SetTimeout(timeout time.Duration) error { - err := p.pcapSetTimeout(timeout) - if err != nil { - return err - } - p.timeout = timeout - return nil -} - -// SupportedTimestamps returns a list of supported timstamp types for this -// handle. -func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource) { - return p.pcapListTstampTypes() -} - -// SetTimestampSource sets the type of timestamp generator PCAP uses when -// attaching timestamps to packets. -func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error { - return p.pcapSetTstampType(t) -} - -// CannotSetRFMon is returned by SetRFMon if the handle does not allow -// setting RFMon because pcap_can_set_rfmon returns 0. -var CannotSetRFMon = errors.New("Cannot set rfmon for this handle") - -// SetRFMon turns on radio monitoring mode, similar to promiscuous mode but for -// wireless networks. If this mode is enabled, the interface will not need to -// associate with an access point before it can receive traffic. -func (p *InactiveHandle) SetRFMon(monitor bool) error { - return p.pcapSetRfmon(monitor) -} - -// SetBufferSize sets the buffer size (in bytes) of the handle. -func (p *InactiveHandle) SetBufferSize(bufferSize int) error { - return p.pcapSetBufferSize(bufferSize) -} - -// SetImmediateMode sets (or unsets) the immediate mode of the -// handle. In immediate mode, packets are delivered to the application -// as soon as they arrive. In other words, this overrides SetTimeout. -func (p *InactiveHandle) SetImmediateMode(mode bool) error { - return p.pcapSetImmediateMode(mode) -} diff --git a/vendor/github.com/gopacket/gopacket/pcap/pcap_unix.go b/vendor/github.com/gopacket/gopacket/pcap/pcap_unix.go deleted file mode 100644 index 7578b24b6..000000000 --- a/vendor/github.com/gopacket/gopacket/pcap/pcap_unix.go +++ /dev/null @@ -1,708 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// Copyright 2009-2011 Andreas Krennmair. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. -// -//go:build !windows -// +build !windows - -package pcap - -import ( - "errors" - "os" - "sync" - "syscall" - "time" - "unsafe" - - "github.com/gopacket/gopacket" - - "github.com/gopacket/gopacket/layers" -) - -/* -#cgo solaris LDFLAGS: -L /opt/local/lib -lpcap -#cgo linux LDFLAGS: -lpcap -#cgo dragonfly LDFLAGS: -lpcap -#cgo freebsd LDFLAGS: -lpcap -#cgo openbsd LDFLAGS: -lpcap -#cgo netbsd LDFLAGS: -lpcap -#cgo darwin LDFLAGS: -lpcap -#include -#include -#include -#include - -// Some old versions of pcap don't define this constant. -#ifndef PCAP_NETMASK_UNKNOWN -#define PCAP_NETMASK_UNKNOWN 0xffffffff -#endif - -// libpcap doesn't actually export its version in a #define-guardable way, -// so we have to use other defined things to differentiate versions. -// We assume at least libpcap v1.1 at the moment. -// See http://upstream-tracker.org/versions/libpcap.html - -#ifndef PCAP_ERROR_TSTAMP_PRECISION_NOTSUP // < v1.5 -#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 - -int pcap_set_immediate_mode(pcap_t *p, int mode) { - return PCAP_ERROR; -} - -// libpcap version < v1.5 doesn't have timestamp precision (everything is microsecond) -// -// This means *_tstamp_* functions and macros are missing. Therefore, we emulate these -// functions here and pretend the setting the precision works. This is actually the way -// the pcap_open_offline_with_tstamp_precision works, because it doesn't return an error -// if it was not possible to set the precision, which depends on support by the given file. -// => The rest of the functions always pretend as if they could set nano precision and -// verify the actual precision with pcap_get_tstamp_precision, which is emulated for -#ifdef __OpenBSD__ -#define gopacket_time_secs_t u_int32_t -#define gopacket_time_usecs_t u_int32_t -#else -#define gopacket_time_secs_t time_t -#define gopacket_time_usecs_t suseconds_t -#endif -#endif - -// The things we do to avoid pointers escaping to the heap... -// According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 , -// the return value of pcap_next_ex could be greater than 1 for success. -// Let's just make it 1 if it comes bigger than 1. -int pcap_next_ex_escaping(pcap_t *p, uintptr_t pkt_hdr, uintptr_t pkt_data) { - int ex = pcap_next_ex(p, (struct pcap_pkthdr**)(pkt_hdr), (const u_char**)(pkt_data)); - if (ex > 1) { - ex = 1; - } - return ex; -} - -int pcap_offline_filter_escaping(struct bpf_program *fp, uintptr_t pkt_hdr, uintptr_t pkt) { - return pcap_offline_filter(fp, (struct pcap_pkthdr*)(pkt_hdr), (const u_char*)(pkt)); -} - -// pcap_wait returns when the next packet is available or the timeout expires. -// Since it uses pcap_get_selectable_fd, it will not work in Windows. -int pcap_wait(pcap_t *p, int msec) { - struct pollfd fds[1]; - int fd; - - fd = pcap_get_selectable_fd(p); - if(fd < 0) { - return fd; - } - - fds[0].fd = fd; - fds[0].events = POLLIN; - - if(msec != 0) { - return poll(fds, 1, msec); - } - - // block indefinitely if no timeout provided - return poll(fds, 1, -1); -} - -*/ -import "C" - -const errorBufferSize = C.PCAP_ERRBUF_SIZE - -const ( - pcapErrorNotActivated = C.PCAP_ERROR_NOT_ACTIVATED - pcapErrorActivated = C.PCAP_ERROR_ACTIVATED - pcapWarningPromisc = C.PCAP_WARNING_PROMISC_NOTSUP - pcapErrorNoSuchDevice = C.PCAP_ERROR_NO_SUCH_DEVICE - pcapErrorDenied = C.PCAP_ERROR_PERM_DENIED - pcapErrorNotUp = C.PCAP_ERROR_IFACE_NOT_UP - pcapWarning = C.PCAP_WARNING - pcapError = C.PCAP_ERROR - pcapDIN = C.PCAP_D_IN - pcapDOUT = C.PCAP_D_OUT - pcapDINOUT = C.PCAP_D_INOUT - pcapNetmaskUnknown = C.PCAP_NETMASK_UNKNOWN - pcapTstampPrecisionMicro = C.PCAP_TSTAMP_PRECISION_MICRO - pcapTstampPrecisionNano = C.PCAP_TSTAMP_PRECISION_NANO -) - -type pcapPkthdr C.struct_pcap_pkthdr -type pcapTPtr *C.struct_pcap -type pcapBpfProgram C.struct_bpf_program - -func (h *pcapPkthdr) getSec() int64 { - return int64(h.ts.tv_sec) -} - -func (h *pcapPkthdr) getUsec() int64 { - return int64(h.ts.tv_usec) -} - -func (h *pcapPkthdr) getLen() int { - return int(h.len) -} - -func (h *pcapPkthdr) getCaplen() int { - return int(h.caplen) -} - -func pcapGetTstampPrecision(cptr pcapTPtr) int { - return int(C.pcap_get_tstamp_precision(cptr)) -} - -func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error { - ret := C.pcap_set_tstamp_precision(cptr, C.int(precision)) - if ret < 0 { - return errors.New(C.GoString(C.pcap_geterr(cptr))) - } - return nil -} - -func statusError(status C.int) error { - return errors.New(C.GoString(C.pcap_statustostr(status))) -} - -func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - - dev := C.CString(device) - defer C.free(unsafe.Pointer(dev)) - - cptr := C.pcap_open_live(dev, C.int(snaplen), C.int(pro), C.int(timeout), buf) - if cptr == nil { - return nil, errors.New(C.GoString(buf)) - } - return &Handle{cptr: cptr}, nil -} - -func openOffline(file string) (handle *Handle, err error) { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - cf := C.CString(file) - defer C.free(unsafe.Pointer(cf)) - - cptr := C.pcap_open_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf) - if cptr == nil { - return nil, errors.New(C.GoString(buf)) - } - return &Handle{cptr: cptr}, nil -} - -func (p *Handle) pcapClose() { - if p.cptr != nil { - C.pcap_close(p.cptr) - } - p.cptr = nil -} - -func (p *Handle) pcapGeterr() error { - return errors.New(C.GoString(C.pcap_geterr(p.cptr))) -} - -func (p *Handle) pcapStats() (*Stats, error) { - var cstats C.struct_pcap_stat - if C.pcap_stats(p.cptr, &cstats) < 0 { - return nil, p.pcapGeterr() - } - return &Stats{ - PacketsReceived: int(cstats.ps_recv), - PacketsDropped: int(cstats.ps_drop), - PacketsIfDropped: int(cstats.ps_ifdrop), - }, nil -} - -// for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it. -var pcapCompileMu sync.Mutex - -func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) { - var bpf pcapBpfProgram - cexpr := C.CString(expr) - defer C.free(unsafe.Pointer(cexpr)) - - pcapCompileMu.Lock() - defer pcapCompileMu.Unlock() - if C.pcap_compile(p.cptr, (*C.struct_bpf_program)(&bpf), cexpr, 1, C.bpf_u_int32(maskp)) < 0 { - return bpf, p.pcapGeterr() - } - return bpf, nil -} - -func (p pcapBpfProgram) free() { - C.pcap_freecode((*C.struct_bpf_program)(&p)) -} - -func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction { - bpfInsn := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(unsafe.Pointer(p.bf_insns))[0:p.bf_len:p.bf_len] - bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn)) - - for i, v := range bpfInsn { - bpfInstruction[i].Code = uint16(v.code) - bpfInstruction[i].Jt = uint8(v.jt) - bpfInstruction[i].Jf = uint8(v.jf) - bpfInstruction[i].K = uint32(v.k) - } - return bpfInstruction -} - -func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram { - var bpf pcapBpfProgram - bpf.bf_len = C.u_int(len(bpfInstructions)) - cbpfInsns := C.calloc(C.size_t(len(bpfInstructions)), C.size_t(unsafe.Sizeof(bpfInstructions[0]))) - gbpfInsns := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(cbpfInsns) - - for i, v := range bpfInstructions { - gbpfInsns[i].code = C.u_short(v.Code) - gbpfInsns[i].jt = C.u_char(v.Jt) - gbpfInsns[i].jf = C.u_char(v.Jf) - gbpfInsns[i].k = C.bpf_u_int32(v.K) - } - - bpf.bf_insns = (*C.struct_bpf_insn)(cbpfInsns) - return bpf -} - -func pcapLookupnet(device string) (netp, maskp uint32, err error) { - errorBuf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(errorBuf)) - dev := C.CString(device) - defer C.free(unsafe.Pointer(dev)) - if C.pcap_lookupnet( - dev, - (*C.bpf_u_int32)(unsafe.Pointer(&netp)), - (*C.bpf_u_int32)(unsafe.Pointer(&maskp)), - errorBuf, - ) < 0 { - return 0, 0, errors.New(C.GoString(errorBuf)) - // We can't lookup the network, but that could be because the interface - // doesn't have an IPv4. - } - return -} - -func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool { - hdr := (*C.struct_pcap_pkthdr)(&b.hdr) - hdr.ts.tv_sec = C.gopacket_time_secs_t(ci.Timestamp.Unix()) - hdr.ts.tv_usec = C.gopacket_time_usecs_t(ci.Timestamp.Nanosecond() / 1000) - hdr.caplen = C.bpf_u_int32(len(data)) // Trust actual length over ci.Length. - hdr.len = C.bpf_u_int32(ci.Length) - dataptr := (*C.u_char)(unsafe.Pointer(&data[0])) - return C.pcap_offline_filter_escaping((*C.struct_bpf_program)(&b.bpf.bpf), - C.uintptr_t(uintptr(unsafe.Pointer(hdr))), - C.uintptr_t(uintptr(unsafe.Pointer(dataptr)))) != 0 -} - -func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error { - if C.pcap_setfilter(p.cptr, (*C.struct_bpf_program)(&bpf)) < 0 { - return p.pcapGeterr() - } - return nil -} - -func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) { - var dltbuf *C.int - - n := int(C.pcap_list_datalinks(p.cptr, &dltbuf)) - if n < 0 { - return nil, p.pcapGeterr() - } - - defer C.pcap_free_datalinks(dltbuf) - - datalinks = make([]Datalink, n) - - dltArray := (*[1 << 28]C.int)(unsafe.Pointer(dltbuf)) - - for i := 0; i < n; i++ { - datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i])) - datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i])) - } - - return datalinks, nil -} - -func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) { - cptr := C.pcap_open_dead(C.int(linkType), C.int(captureLength)) - if cptr == nil { - return nil, errors.New("error opening dead capture") - } - - return &Handle{cptr: cptr}, nil -} - -func (p *Handle) pcapNextPacketEx() NextError { - // This horrible magic allows us to pass a ptr-to-ptr to pcap_next_ex - // without causing that ptr-to-ptr to itself be allocated on the heap. - // Since Handle itself survives through the duration of the pcap_next_ex - // call, this should be perfectly safe for GC stuff, etc. - - return NextError(C.pcap_next_ex_escaping(p.cptr, C.uintptr_t(uintptr(unsafe.Pointer(&p.pkthdr))), C.uintptr_t(uintptr(unsafe.Pointer(&p.bufptr))))) -} - -func (p *Handle) pcapDatalink() layers.LinkType { - return layers.LinkType(C.pcap_datalink(p.cptr)) -} - -func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error { - if C.pcap_set_datalink(p.cptr, C.int(dlt)) < 0 { - return p.pcapGeterr() - } - return nil -} - -func pcapDatalinkValToName(dlt int) string { - return C.GoString(C.pcap_datalink_val_to_name(C.int(dlt))) -} - -func pcapDatalinkValToDescription(dlt int) string { - return C.GoString(C.pcap_datalink_val_to_description(C.int(dlt))) -} - -func pcapDatalinkNameToVal(name string) int { - cptr := C.CString(name) - defer C.free(unsafe.Pointer(cptr)) - return int(C.pcap_datalink_name_to_val(cptr)) -} - -func pcapLibVersion() string { - return C.GoString(C.pcap_lib_version()) -} - -func (p *Handle) isOpen() bool { - return p.cptr != nil -} - -type pcapDevices struct { - all, cur *C.pcap_if_t -} - -func (p pcapDevices) free() { - C.pcap_freealldevs((*C.pcap_if_t)(p.all)) -} - -func (p *pcapDevices) next() bool { - if p.cur == nil { - p.cur = p.all - if p.cur == nil { - return false - } - return true - } - if p.cur.next == nil { - return false - } - p.cur = p.cur.next - return true -} - -func (p pcapDevices) name() string { - return C.GoString(p.cur.name) -} - -func (p pcapDevices) description() string { - return C.GoString(p.cur.description) -} - -func (p pcapDevices) flags() uint32 { - return uint32(p.cur.flags) -} - -type pcapAddresses struct { - all, cur *C.pcap_addr_t -} - -func (p *pcapAddresses) next() bool { - if p.cur == nil { - p.cur = p.all - if p.cur == nil { - return false - } - return true - } - if p.cur.next == nil { - return false - } - p.cur = p.cur.next - return true -} - -func (p pcapAddresses) addr() *syscall.RawSockaddr { - return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.addr)) -} - -func (p pcapAddresses) netmask() *syscall.RawSockaddr { - return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.netmask)) -} - -func (p pcapAddresses) broadaddr() *syscall.RawSockaddr { - return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.broadaddr)) -} - -func (p pcapAddresses) dstaddr() *syscall.RawSockaddr { - return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.dstaddr)) -} - -func (p pcapDevices) addresses() pcapAddresses { - return pcapAddresses{all: p.cur.addresses} -} - -func pcapFindAllDevs() (pcapDevices, error) { - var buf *C.char - buf = (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - var alldevsp pcapDevices - - if C.pcap_findalldevs((**C.pcap_if_t)(&alldevsp.all), buf) < 0 { - return pcapDevices{}, errors.New(C.GoString(buf)) - } - return alldevsp, nil -} - -func (p *Handle) pcapSendpacket(data []byte) error { - if C.pcap_sendpacket(p.cptr, (*C.u_char)(&data[0]), (C.int)(len(data))) < 0 { - return p.pcapGeterr() - } - return nil -} - -func (p *Handle) pcapSetdirection(direction Direction) error { - if status := C.pcap_setdirection(p.cptr, (C.pcap_direction_t)(direction)); status < 0 { - return statusError(status) - } - return nil -} - -func (p *Handle) pcapSnapshot() int { - return int(C.pcap_snapshot(p.cptr)) -} - -func (t TimestampSource) pcapTstampTypeValToName() string { - return C.GoString(C.pcap_tstamp_type_val_to_name(C.int(t))) -} - -func pcapTstampTypeNameToVal(s string) (TimestampSource, error) { - cs := C.CString(s) - defer C.free(unsafe.Pointer(cs)) - t := C.pcap_tstamp_type_name_to_val(cs) - if t < 0 { - return 0, statusError(t) - } - return TimestampSource(t), nil -} - -func (p *InactiveHandle) pcapGeterr() error { - return errors.New(C.GoString(C.pcap_geterr(p.cptr))) -} - -func (p *InactiveHandle) pcapActivate() (*Handle, activateError) { - ret := activateError(C.pcap_activate(p.cptr)) - if ret != aeNoError { - return nil, ret - } - h := &Handle{ - cptr: p.cptr, - } - p.cptr = nil - return h, ret -} - -func (p *InactiveHandle) pcapClose() { - if p.cptr != nil { - C.pcap_close(p.cptr) - } -} - -func pcapCreate(device string) (*InactiveHandle, error) { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - dev := C.CString(device) - defer C.free(unsafe.Pointer(dev)) - - cptr := C.pcap_create(dev, buf) - if cptr == nil { - return nil, errors.New(C.GoString(buf)) - } - return &InactiveHandle{cptr: cptr}, nil -} - -func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error { - if status := C.pcap_set_snaplen(p.cptr, C.int(snaplen)); status < 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapSetPromisc(promisc bool) error { - var pro C.int - if promisc { - pro = 1 - } - if status := C.pcap_set_promisc(p.cptr, pro); status < 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error { - if status := C.pcap_set_timeout(p.cptr, C.int(timeoutMillis(timeout))); status < 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) { - var types *C.int - n := int(C.pcap_list_tstamp_types(p.cptr, &types)) - if n < 0 { - return // public interface doesn't have error :( - } - defer C.pcap_free_tstamp_types(types) - typesArray := (*[1 << 28]C.int)(unsafe.Pointer(types)) - for i := 0; i < n; i++ { - out = append(out, TimestampSource((*typesArray)[i])) - } - return -} - -func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error { - if status := C.pcap_set_tstamp_type(p.cptr, C.int(t)); status < 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapSetRfmon(monitor bool) error { - var mon C.int - if monitor { - mon = 1 - } - switch canset := C.pcap_can_set_rfmon(p.cptr); canset { - case 0: - return CannotSetRFMon - case 1: - // success - default: - return statusError(canset) - } - if status := C.pcap_set_rfmon(p.cptr, mon); status != 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error { - if status := C.pcap_set_buffer_size(p.cptr, C.int(bufferSize)); status < 0 { - return statusError(status) - } - return nil -} - -func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error { - var md C.int - if mode { - md = 1 - } - if status := C.pcap_set_immediate_mode(p.cptr, md); status < 0 { - return statusError(status) - } - return nil -} - -func (p *Handle) setNonBlocking() error { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - - // Change the device to non-blocking, we'll use pcap_wait to wait until the - // handle is ready to read. - if v := C.pcap_setnonblock(p.cptr, 1, buf); v < -1 { - return errors.New(C.GoString(buf)) - } - - return nil -} - -// waitForPacket waits for a packet or for the timeout to expire. -func (p *Handle) waitForPacket() { - // According to pcap_get_selectable_fd() man page, there are some cases where it will - // return a file descriptor, but a simple call of select() or poll() will not indicate - // that the descriptor is readable until a full buffer's worth of packets is received, - // so the call must have a timeout less than *or equal* to the packet buffer timeout. - // The packet buffer timeout is set to timeoutMillis(p.timeout) in pcapOpenLive(), - // so we should be fine to use it here too. - C.pcap_wait(p.cptr, C.int(timeoutMillis(p.timeout))) -} - -// openOfflineFile returns contents of input file as a *Handle. -func openOfflineFile(file *os.File) (handle *Handle, err error) { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - cmode := C.CString("rb") - defer C.free(unsafe.Pointer(cmode)) - cf := C.fdopen(C.int(file.Fd()), cmode) - - cptr := C.pcap_fopen_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf) - if cptr == nil { - return nil, errors.New(C.GoString(buf)) - } - return &Handle{cptr: cptr}, nil -} diff --git a/vendor/github.com/gopacket/gopacket/pcap/pcap_windows.go b/vendor/github.com/gopacket/gopacket/pcap/pcap_windows.go deleted file mode 100644 index 587e4aa5e..000000000 --- a/vendor/github.com/gopacket/gopacket/pcap/pcap_windows.go +++ /dev/null @@ -1,898 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// Copyright 2009-2011 Andreas Krennmair. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -package pcap - -import ( - "errors" - "fmt" - "os" - "runtime" - "sync" - "syscall" - "time" - "unsafe" - - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/layers" - "golang.org/x/sys/windows" -) - -var pcapLoaded = false - -const npcapPath = "\\Npcap" - -func initDllPath(kernel32 syscall.Handle) { - setDllDirectory, err := syscall.GetProcAddress(kernel32, "SetDllDirectoryA") - if err != nil { - // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter - return - } - getSystemDirectory, err := syscall.GetProcAddress(kernel32, "GetSystemDirectoryA") - if err != nil { - // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter - return - } - buf := make([]byte, 4096) - r, _, _ := syscall.Syscall(getSystemDirectory, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) - if r == 0 || r > 4096-uintptr(len(npcapPath))-1 { - // we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter - return - } - copy(buf[r:], npcapPath) - _, _, _ = syscall.Syscall(setDllDirectory, 1, uintptr(unsafe.Pointer(&buf[0])), 0, 0) - // ignore errors here - we just fallback to load wpcap.dll from default locations -} - -// loadedDllPath will hold the full pathname of the loaded wpcap.dll after init if possible -var loadedDllPath = "wpcap.dll" - -func initLoadedDllPath(kernel32 syscall.Handle) { - getModuleFileName, err := syscall.GetProcAddress(kernel32, "GetModuleFileNameA") - if err != nil { - // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll - return - } - buf := make([]byte, 4096) - r, _, _ := syscall.Syscall(getModuleFileName, 3, uintptr(wpcapHandle), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf))) - if r == 0 { - // we can't get the filename of the loaded module in this case - just leave default of wpcap.dll - return - } - loadedDllPath = string(buf[:int(r)]) -} - -func mustLoad(fun string) uintptr { - addr, err := windows.GetProcAddress(wpcapHandle, fun) - if err != nil { - panic(fmt.Sprintf("Couldn't load function %s from %s", fun, loadedDllPath)) - } - return addr -} - -func mightLoad(fun string) uintptr { - addr, err := windows.GetProcAddress(wpcapHandle, fun) - if err != nil { - return 0 - } - return addr -} - -func byteSliceToString(bval []byte) string { - for i := range bval { - if bval[i] == 0 { - return string(bval[:i]) - } - } - return string(bval[:]) -} - -// bytePtrToString returns a string copied from pointer to a null terminated byte array -// WARNING: ONLY SAFE WITH IF r POINTS TO C MEMORY! -// govet will complain about this function for the reason stated above -func bytePtrToString(r uintptr) string { - if r == 0 { - return "" - } - bval := (*[1 << 30]byte)(unsafe.Pointer(r)) - return byteSliceToString(bval[:]) -} - -var wpcapHandle windows.Handle -var msvcrtHandle syscall.Handle -var ( - callocPtr, - pcapStrerrorPtr, - pcapStatustostrPtr, - pcapOpenLivePtr, - pcapOpenOfflinePtr, - pcapClosePtr, - pcapGeterrPtr, - pcapStatsPtr, - pcapCompilePtr, - pcapFreecodePtr, - pcapLookupnetPtr, - pcapOfflineFilterPtr, - pcapSetfilterPtr, - pcapListDatalinksPtr, - pcapFreeDatalinksPtr, - pcapDatalinkValToNamePtr, - pcapDatalinkValToDescriptionPtr, - pcapOpenDeadPtr, - pcapNextExPtr, - pcapDatalinkPtr, - pcapSetDatalinkPtr, - pcapDatalinkNameToValPtr, - pcapLibVersionPtr, - pcapFreealldevsPtr, - pcapFindalldevsPtr, - pcapSendpacketPtr, - pcapSetdirectionPtr, - pcapSnapshotPtr, - pcapTstampTypeValToNamePtr, - pcapTstampTypeNameToValPtr, - pcapListTstampTypesPtr, - pcapFreeTstampTypesPtr, - pcapSetTstampTypePtr, - pcapGetTstampPrecisionPtr, - pcapSetTstampPrecisionPtr, - pcapOpenOfflineWithTstampPrecisionPtr, - pcapHOpenOfflineWithTstampPrecisionPtr, - pcapActivatePtr, - pcapCreatePtr, - pcapSetSnaplenPtr, - pcapSetPromiscPtr, - pcapSetTimeoutPtr, - pcapCanSetRfmonPtr, - pcapSetRfmonPtr, - pcapSetBufferSizePtr, - pcapSetImmediateModePtr, - pcapHopenOfflinePtr uintptr -) - -func init() { - LoadWinPCAP() -} - -// LoadWinPCAP attempts to dynamically load the wpcap DLL and resolve necessary functions -func LoadWinPCAP() error { - if pcapLoaded { - return nil - } - - kernel32, err := syscall.LoadLibrary("kernel32.dll") - if err != nil { - return fmt.Errorf("couldn't load kernel32.dll") - } - defer syscall.FreeLibrary(kernel32) - - initDllPath(kernel32) - - if haveSearch, _ := syscall.GetProcAddress(kernel32, "AddDllDirectory"); haveSearch != 0 { - // if AddDllDirectory is present, we can use LOAD_LIBRARY_* stuff with LoadLibraryEx to avoid wpcap.dll hijacking - // see: https://msdn.microsoft.com/en-us/library/ff919712%28VS.85%29.aspx - const LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400 - const LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 - wpcapHandle, err = windows.LoadLibraryEx("wpcap.dll", 0, LOAD_LIBRARY_SEARCH_USER_DIRS|LOAD_LIBRARY_SEARCH_SYSTEM32) - if err != nil { - return fmt.Errorf("couldn't load wpcap.dll") - } - } else { - // otherwise fall back to load it with the unsafe search cause by SetDllDirectory - wpcapHandle, err = windows.LoadLibrary("wpcap.dll") - if err != nil { - return fmt.Errorf("couldn't load wpcap.dll") - } - } - initLoadedDllPath(kernel32) - msvcrtHandle, err = syscall.LoadLibrary("msvcrt.dll") - if err != nil { - return fmt.Errorf("couldn't load msvcrt.dll") - } - callocPtr, err = syscall.GetProcAddress(msvcrtHandle, "calloc") - if err != nil { - return fmt.Errorf("couldn't get calloc function") - } - - pcapStrerrorPtr = mustLoad("pcap_strerror") - pcapStatustostrPtr = mightLoad("pcap_statustostr") // not available on winpcap - pcapOpenLivePtr = mustLoad("pcap_open_live") - pcapOpenOfflinePtr = mustLoad("pcap_open_offline") - pcapClosePtr = mustLoad("pcap_close") - pcapGeterrPtr = mustLoad("pcap_geterr") - pcapStatsPtr = mustLoad("pcap_stats") - pcapCompilePtr = mustLoad("pcap_compile") - pcapFreecodePtr = mustLoad("pcap_freecode") - pcapLookupnetPtr = mustLoad("pcap_lookupnet") - pcapOfflineFilterPtr = mustLoad("pcap_offline_filter") - pcapSetfilterPtr = mustLoad("pcap_setfilter") - pcapListDatalinksPtr = mustLoad("pcap_list_datalinks") - pcapFreeDatalinksPtr = mustLoad("pcap_free_datalinks") - pcapDatalinkValToNamePtr = mustLoad("pcap_datalink_val_to_name") - pcapDatalinkValToDescriptionPtr = mustLoad("pcap_datalink_val_to_description") - pcapOpenDeadPtr = mustLoad("pcap_open_dead") - pcapNextExPtr = mustLoad("pcap_next_ex") - pcapDatalinkPtr = mustLoad("pcap_datalink") - pcapSetDatalinkPtr = mustLoad("pcap_set_datalink") - pcapDatalinkNameToValPtr = mustLoad("pcap_datalink_name_to_val") - pcapLibVersionPtr = mustLoad("pcap_lib_version") - pcapFreealldevsPtr = mustLoad("pcap_freealldevs") - pcapFindalldevsPtr = mustLoad("pcap_findalldevs") - pcapSendpacketPtr = mustLoad("pcap_sendpacket") - pcapSetdirectionPtr = mustLoad("pcap_setdirection") - pcapSnapshotPtr = mustLoad("pcap_snapshot") - //libpcap <1.2 doesn't have pcap_*_tstamp_* functions - pcapTstampTypeValToNamePtr = mightLoad("pcap_tstamp_type_val_to_name") - pcapTstampTypeNameToValPtr = mightLoad("pcap_tstamp_type_name_to_val") - pcapListTstampTypesPtr = mightLoad("pcap_list_tstamp_types") - pcapFreeTstampTypesPtr = mightLoad("pcap_free_tstamp_types") - pcapSetTstampTypePtr = mightLoad("pcap_set_tstamp_type") - pcapGetTstampPrecisionPtr = mightLoad("pcap_get_tstamp_precision") - pcapSetTstampPrecisionPtr = mightLoad("pcap_set_tstamp_precision") - pcapOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_open_offline_with_tstamp_precision") - pcapHOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_hopen_offline_with_tstamp_precision") - pcapActivatePtr = mustLoad("pcap_activate") - pcapCreatePtr = mustLoad("pcap_create") - pcapSetSnaplenPtr = mustLoad("pcap_set_snaplen") - pcapSetPromiscPtr = mustLoad("pcap_set_promisc") - pcapSetTimeoutPtr = mustLoad("pcap_set_timeout") - //winpcap does not support rfmon - pcapCanSetRfmonPtr = mightLoad("pcap_can_set_rfmon") - pcapSetRfmonPtr = mightLoad("pcap_set_rfmon") - pcapSetBufferSizePtr = mustLoad("pcap_set_buffer_size") - //libpcap <1.5 does not have pcap_set_immediate_mode - pcapSetImmediateModePtr = mightLoad("pcap_set_immediate_mode") - pcapHopenOfflinePtr = mustLoad("pcap_hopen_offline") - - pcapLoaded = true - return nil -} - -func (h *pcapPkthdr) getSec() int64 { - return int64(h.Ts.Sec) -} - -func (h *pcapPkthdr) getUsec() int64 { - return int64(h.Ts.Usec) -} - -func (h *pcapPkthdr) getLen() int { - return int(h.Len) -} - -func (h *pcapPkthdr) getCaplen() int { - return int(h.Caplen) -} - -func statusError(status pcapCint) error { - var ret uintptr - if pcapStatustostrPtr == 0 { - ret, _, _ = syscall.Syscall(pcapStrerrorPtr, 1, uintptr(status), 0, 0) - } else { - ret, _, _ = syscall.Syscall(pcapStatustostrPtr, 1, uintptr(status), 0, 0) - } - return errors.New(bytePtrToString(ret)) -} - -func pcapGetTstampPrecision(cptr pcapTPtr) int { - if pcapGetTstampPrecisionPtr == 0 { - return pcapTstampPrecisionMicro - } - ret, _, _ := syscall.Syscall(pcapGetTstampPrecisionPtr, 1, uintptr(cptr), 0, 0) - return int(pcapCint(ret)) -} - -func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error { - if pcapSetTstampPrecisionPtr == 0 { - return errors.New("Not supported") - } - ret, _, _ := syscall.Syscall(pcapSetTstampPrecisionPtr, 2, uintptr(cptr), uintptr(precision), 0) - if pcapCint(ret) < 0 { - return errors.New("Not supported") - } - return nil -} - -func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) { - err := LoadWinPCAP() - if err != nil { - return nil, err - } - - buf := make([]byte, errorBufferSize) - dev, err := syscall.BytePtrFromString(device) - if err != nil { - return nil, err - } - - cptr, _, _ := syscall.Syscall6(pcapOpenLivePtr, 5, uintptr(unsafe.Pointer(dev)), uintptr(snaplen), uintptr(pro), uintptr(timeout), uintptr(unsafe.Pointer(&buf[0])), 0) - - if cptr == 0 { - return nil, errors.New(byteSliceToString(buf)) - } - return &Handle{cptr: pcapTPtr(cptr)}, nil -} - -func openOffline(file string) (handle *Handle, err error) { - err = LoadWinPCAP() - if err != nil { - return nil, err - } - - buf := make([]byte, errorBufferSize) - f, err := syscall.BytePtrFromString(file) - if err != nil { - return nil, err - } - - var cptr uintptr - if pcapOpenOfflineWithTstampPrecisionPtr == 0 { - cptr, _, _ = syscall.Syscall(pcapOpenOfflinePtr, 2, uintptr(unsafe.Pointer(f)), uintptr(unsafe.Pointer(&buf[0])), 0) - } else { - cptr, _, _ = syscall.Syscall(pcapOpenOfflineWithTstampPrecisionPtr, 3, uintptr(unsafe.Pointer(f)), uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0]))) - } - - if cptr == 0 { - return nil, errors.New(byteSliceToString(buf)) - } - - h := &Handle{cptr: pcapTPtr(cptr)} - return h, nil -} - -func (p *Handle) pcapClose() { - if p.cptr != 0 { - _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0) - } - p.cptr = 0 -} - -func (p *Handle) pcapGeterr() error { - ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0) - return errors.New(bytePtrToString(ret)) -} - -func (p *Handle) pcapStats() (*Stats, error) { - var cstats pcapStats - ret, _, _ := syscall.Syscall(pcapStatsPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&cstats)), 0) - if pcapCint(ret) < 0 { - return nil, p.pcapGeterr() - } - return &Stats{ - PacketsReceived: int(cstats.Recv), - PacketsDropped: int(cstats.Drop), - PacketsIfDropped: int(cstats.Ifdrop), - }, nil -} - -// for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it. -var pcapCompileMu sync.Mutex - -func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) { - var bpf pcapBpfProgram - cexpr, err := syscall.BytePtrFromString(expr) - if err != nil { - return pcapBpfProgram{}, err - } - pcapCompileMu.Lock() - defer pcapCompileMu.Unlock() - res, _, _ := syscall.Syscall6(pcapCompilePtr, 5, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), uintptr(unsafe.Pointer(cexpr)), uintptr(1), uintptr(maskp), 0) - if pcapCint(res) < 0 { - return bpf, p.pcapGeterr() - } - return bpf, nil -} - -func (p pcapBpfProgram) free() { - _, _, _ = syscall.Syscall(pcapFreecodePtr, 1, uintptr(unsafe.Pointer(&p)), 0, 0) -} - -func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction { - bpfInsn := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(p.Insns))[0:p.Len:p.Len] - bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn)) - - for i, v := range bpfInsn { - bpfInstruction[i].Code = v.Code - bpfInstruction[i].Jt = v.Jt - bpfInstruction[i].Jf = v.Jf - bpfInstruction[i].K = v.K - } - return bpfInstruction -} - -func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram { - var bpf pcapBpfProgram - bpf.Len = uint32(len(bpfInstructions)) - cbpfInsns, _, _ := syscall.Syscall(callocPtr, 2, uintptr(len(bpfInstructions)), uintptr(unsafe.Sizeof(bpfInstructions[0])), 0) - gbpfInsns := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(cbpfInsns)) - - for i, v := range bpfInstructions { - gbpfInsns[i].Code = v.Code - gbpfInsns[i].Jt = v.Jt - gbpfInsns[i].Jf = v.Jf - gbpfInsns[i].K = v.K - } - - bpf.Insns = (*pcapBpfInstruction)(unsafe.Pointer(cbpfInsns)) - return bpf -} - -func pcapLookupnet(device string) (netp, maskp uint32, err error) { - err = LoadWinPCAP() - if err != nil { - return 0, 0, err - } - - buf := make([]byte, errorBufferSize) - dev, err := syscall.BytePtrFromString(device) - if err != nil { - return 0, 0, err - } - e, _, _ := syscall.Syscall6(pcapLookupnetPtr, 4, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&netp)), uintptr(unsafe.Pointer(&maskp)), uintptr(unsafe.Pointer(&buf[0])), 0, 0) - if pcapCint(e) < 0 { - return 0, 0, errors.New(byteSliceToString(buf)) - } - return -} - -func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool { - var hdr pcapPkthdr - hdr.Ts.Sec = int32(ci.Timestamp.Unix()) - hdr.Ts.Usec = int32(ci.Timestamp.Nanosecond() / 1000) - hdr.Caplen = uint32(len(data)) // Trust actual length over ci.Length. - hdr.Len = uint32(ci.Length) - e, _, _ := syscall.Syscall(pcapOfflineFilterPtr, 3, uintptr(unsafe.Pointer(&b.bpf.bpf)), uintptr(unsafe.Pointer(&hdr)), uintptr(unsafe.Pointer(&data[0]))) - return e != 0 -} - -func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error { - e, _, _ := syscall.Syscall(pcapSetfilterPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), 0) - if pcapCint(e) < 0 { - return p.pcapGeterr() - } - return nil -} - -func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) { - var dltbuf *pcapCint - ret, _, _ := syscall.Syscall(pcapListDatalinksPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&dltbuf)), 0) - - n := int(pcapCint(ret)) - - if n < 0 { - return nil, p.pcapGeterr() - } - defer syscall.Syscall(pcapFreeDatalinksPtr, 1, uintptr(unsafe.Pointer(dltbuf)), 0, 0) - - datalinks = make([]Datalink, n) - - dltArray := (*[1 << 28]pcapCint)(unsafe.Pointer(dltbuf)) - - for i := 0; i < n; i++ { - datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i])) - datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i])) - } - - return datalinks, nil -} - -func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) { - err := LoadWinPCAP() - if err != nil { - return nil, err - } - - cptr, _, _ := syscall.Syscall(pcapOpenDeadPtr, 2, uintptr(linkType), uintptr(captureLength), 0) - if cptr == 0 { - return nil, errors.New("error opening dead capture") - } - - return &Handle{cptr: pcapTPtr(cptr)}, nil -} - -func (p *Handle) pcapNextPacketEx() NextError { - r, _, _ := syscall.Syscall(pcapNextExPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&p.pkthdr)), uintptr(unsafe.Pointer(&p.bufptr))) - ret := pcapCint(r) - // According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 , - // the return value of pcap_next_ex could be greater than 1 for success. - // Let's just make it 1 if it comes bigger than 1. - if ret > 1 { - ret = 1 - } - return NextError(ret) -} - -func (p *Handle) pcapDatalink() layers.LinkType { - ret, _, _ := syscall.Syscall(pcapDatalinkPtr, 1, uintptr(p.cptr), 0, 0) - return layers.LinkType(ret) -} - -func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error { - ret, _, _ := syscall.Syscall(pcapSetDatalinkPtr, 2, uintptr(p.cptr), uintptr(dlt), 0) - if pcapCint(ret) < 0 { - return p.pcapGeterr() - } - return nil -} - -func pcapDatalinkValToName(dlt int) string { - err := LoadWinPCAP() - if err != nil { - panic(err) - } - ret, _, _ := syscall.Syscall(pcapDatalinkValToNamePtr, 1, uintptr(dlt), 0, 0) - return bytePtrToString(ret) -} - -func pcapDatalinkValToDescription(dlt int) string { - err := LoadWinPCAP() - if err != nil { - panic(err) - } - ret, _, _ := syscall.Syscall(pcapDatalinkValToDescriptionPtr, 1, uintptr(dlt), 0, 0) - return bytePtrToString(ret) -} - -func pcapDatalinkNameToVal(name string) int { - err := LoadWinPCAP() - if err != nil { - panic(err) - } - cptr, err := syscall.BytePtrFromString(name) - if err != nil { - return 0 - } - ret, _, _ := syscall.Syscall(pcapDatalinkNameToValPtr, 1, uintptr(unsafe.Pointer(cptr)), 0, 0) - return int(pcapCint(ret)) -} - -func pcapLibVersion() string { - err := LoadWinPCAP() - if err != nil { - panic(err) - } - ret, _, _ := syscall.Syscall(pcapLibVersionPtr, 0, 0, 0, 0) - return bytePtrToString(ret) -} - -func (p *Handle) isOpen() bool { - return p.cptr != 0 -} - -type pcapDevices struct { - all, cur *pcapIf -} - -func (p pcapDevices) free() { - syscall.Syscall(pcapFreealldevsPtr, 1, uintptr(unsafe.Pointer(p.all)), 0, 0) -} - -func (p *pcapDevices) next() bool { - if p.cur == nil { - p.cur = p.all - if p.cur == nil { - return false - } - return true - } - if p.cur.Next == nil { - return false - } - p.cur = p.cur.Next - return true -} - -func (p pcapDevices) name() string { - return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Name))) -} - -func (p pcapDevices) description() string { - return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Description))) -} - -func (p pcapDevices) flags() uint32 { - return p.cur.Flags -} - -type pcapAddresses struct { - all, cur *pcapAddr -} - -func (p *pcapAddresses) next() bool { - if p.cur == nil { - p.cur = p.all - if p.cur == nil { - return false - } - return true - } - if p.cur.Next == nil { - return false - } - p.cur = p.cur.Next - return true -} - -func (p pcapAddresses) addr() *syscall.RawSockaddr { - return p.cur.Addr -} - -func (p pcapAddresses) netmask() *syscall.RawSockaddr { - return p.cur.Netmask -} - -func (p pcapAddresses) broadaddr() *syscall.RawSockaddr { - return p.cur.Broadaddr -} - -func (p pcapAddresses) dstaddr() *syscall.RawSockaddr { - return p.cur.Dstaddr -} - -func (p pcapDevices) addresses() pcapAddresses { - return pcapAddresses{all: p.cur.Addresses} -} - -func pcapFindAllDevs() (pcapDevices, error) { - var alldevsp pcapDevices - err := LoadWinPCAP() - if err != nil { - return alldevsp, err - } - - buf := make([]byte, errorBufferSize) - - ret, _, _ := syscall.Syscall(pcapFindalldevsPtr, 2, uintptr(unsafe.Pointer(&alldevsp.all)), uintptr(unsafe.Pointer(&buf[0])), 0) - - if pcapCint(ret) < 0 { - return pcapDevices{}, errors.New(byteSliceToString(buf)) - } - return alldevsp, nil -} - -func (p *Handle) pcapSendpacket(data []byte) error { - ret, _, _ := syscall.Syscall(pcapSendpacketPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data))) - if pcapCint(ret) < 0 { - return p.pcapGeterr() - } - return nil -} - -func (p *Handle) pcapSetdirection(direction Direction) error { - status, _, _ := syscall.Syscall(pcapSetdirectionPtr, 2, uintptr(p.cptr), uintptr(direction), 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *Handle) pcapSnapshot() int { - ret, _, _ := syscall.Syscall(pcapSnapshotPtr, 1, uintptr(p.cptr), 0, 0) - return int(pcapCint(ret)) -} - -func (t TimestampSource) pcapTstampTypeValToName() string { - err := LoadWinPCAP() - if err != nil { - return err.Error() - } - - //libpcap <1.2 doesn't have pcap_*_tstamp_* functions - if pcapTstampTypeValToNamePtr == 0 { - return "pcap timestamp types not supported" - } - ret, _, _ := syscall.Syscall(pcapTstampTypeValToNamePtr, 1, uintptr(t), 0, 0) - return bytePtrToString(ret) -} - -func pcapTstampTypeNameToVal(s string) (TimestampSource, error) { - err := LoadWinPCAP() - if err != nil { - return 0, err - } - - //libpcap <1.2 doesn't have pcap_*_tstamp_* functions - if pcapTstampTypeNameToValPtr == 0 { - return 0, statusError(pcapCint(pcapError)) - } - cs, err := syscall.BytePtrFromString(s) - if err != nil { - return 0, err - } - ret, _, _ := syscall.Syscall(pcapTstampTypeNameToValPtr, 1, uintptr(unsafe.Pointer(cs)), 0, 0) - t := pcapCint(ret) - if t < 0 { - return 0, statusError(pcapCint(t)) - } - return TimestampSource(t), nil -} - -func (p *InactiveHandle) pcapGeterr() error { - ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0) - return errors.New(bytePtrToString(ret)) -} - -func (p *InactiveHandle) pcapActivate() (*Handle, activateError) { - r, _, _ := syscall.Syscall(pcapActivatePtr, 1, uintptr(p.cptr), 0, 0) - ret := activateError(pcapCint(r)) - if ret != aeNoError { - return nil, ret - } - h := &Handle{ - cptr: p.cptr, - } - p.cptr = 0 - return h, ret -} - -func (p *InactiveHandle) pcapClose() { - if p.cptr != 0 { - _, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0) - } - p.cptr = 0 -} - -func pcapCreate(device string) (*InactiveHandle, error) { - err := LoadWinPCAP() - if err != nil { - return nil, err - } - - buf := make([]byte, errorBufferSize) - dev, err := syscall.BytePtrFromString(device) - if err != nil { - return nil, err - } - cptr, _, _ := syscall.Syscall(pcapCreatePtr, 2, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&buf[0])), 0) - if cptr == 0 { - return nil, errors.New(byteSliceToString(buf)) - } - return &InactiveHandle{cptr: pcapTPtr(cptr)}, nil -} - -func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error { - status, _, _ := syscall.Syscall(pcapSetSnaplenPtr, 2, uintptr(p.cptr), uintptr(snaplen), 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapSetPromisc(promisc bool) error { - var pro uintptr - if promisc { - pro = 1 - } - status, _, _ := syscall.Syscall(pcapSetPromiscPtr, 2, uintptr(p.cptr), pro, 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error { - status, _, _ := syscall.Syscall(pcapSetTimeoutPtr, 2, uintptr(p.cptr), uintptr(timeoutMillis(timeout)), 0) - - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) { - //libpcap <1.2 doesn't have pcap_*_tstamp_* functions - if pcapListTstampTypesPtr == 0 { - return - } - var types *pcapCint - ret, _, _ := syscall.Syscall(pcapListTstampTypesPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&types)), 0) - n := int(pcapCint(ret)) - if n < 0 { - return // public interface doesn't have error :( - } - defer syscall.Syscall(pcapFreeTstampTypesPtr, 1, uintptr(unsafe.Pointer(types)), 0, 0) - typesArray := (*[1 << 28]pcapCint)(unsafe.Pointer(types)) - for i := 0; i < n; i++ { - out = append(out, TimestampSource((*typesArray)[i])) - } - return -} - -func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error { - //libpcap <1.2 doesn't have pcap_*_tstamp_* functions - if pcapSetTstampTypePtr == 0 { - return statusError(pcapError) - } - status, _, _ := syscall.Syscall(pcapSetTstampTypePtr, 2, uintptr(p.cptr), uintptr(t), 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapSetRfmon(monitor bool) error { - //winpcap does not support rfmon - if pcapCanSetRfmonPtr == 0 { - return CannotSetRFMon - } - var mon uintptr - if monitor { - mon = 1 - } - canset, _, _ := syscall.Syscall(pcapCanSetRfmonPtr, 1, uintptr(p.cptr), 0, 0) - switch canset { - case 0: - return CannotSetRFMon - case 1: - // success - default: - return statusError(pcapCint(canset)) - } - status, _, _ := syscall.Syscall(pcapSetRfmonPtr, 2, uintptr(p.cptr), mon, 0) - if status != 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error { - status, _, _ := syscall.Syscall(pcapSetBufferSizePtr, 2, uintptr(p.cptr), uintptr(bufferSize), 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error { - //libpcap <1.5 does not have pcap_set_immediate_mode - if pcapSetImmediateModePtr == 0 { - return statusError(pcapError) - } - var md uintptr - if mode { - md = 1 - } - status, _, _ := syscall.Syscall(pcapSetImmediateModePtr, 2, uintptr(p.cptr), md, 0) - if pcapCint(status) < 0 { - return statusError(pcapCint(status)) - } - return nil -} - -func (p *Handle) setNonBlocking() error { - // do nothing - return nil -} - -// waitForPacket waits for a packet or for the timeout to expire. -func (p *Handle) waitForPacket() { - // can't use select() so instead just switch goroutines - runtime.Gosched() -} - -// openOfflineFile returns contents of input file as a *Handle. -func openOfflineFile(file *os.File) (handle *Handle, err error) { - err = LoadWinPCAP() - if err != nil { - return nil, err - } - - buf := make([]byte, errorBufferSize) - cf := file.Fd() - - var cptr uintptr - if pcapOpenOfflineWithTstampPrecisionPtr == 0 { - cptr, _, _ = syscall.Syscall(pcapHopenOfflinePtr, 2, cf, uintptr(unsafe.Pointer(&buf[0])), 0) - } else { - cptr, _, _ = syscall.Syscall(pcapHOpenOfflineWithTstampPrecisionPtr, 3, cf, uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0]))) - } - - if cptr == 0 { - return nil, errors.New(byteSliceToString(buf)) - } - return &Handle{cptr: pcapTPtr(cptr)}, nil -} diff --git a/vendor/github.com/gopacket/gopacket/pcap/test_dns.pcap b/vendor/github.com/gopacket/gopacket/pcap/test_dns.pcap deleted file mode 100644 index 3a79f928a..000000000 Binary files a/vendor/github.com/gopacket/gopacket/pcap/test_dns.pcap and /dev/null differ diff --git a/vendor/github.com/gopacket/gopacket/pcap/test_ethernet.pcap b/vendor/github.com/gopacket/gopacket/pcap/test_ethernet.pcap deleted file mode 100644 index 1d01bd918..000000000 Binary files a/vendor/github.com/gopacket/gopacket/pcap/test_ethernet.pcap and /dev/null differ diff --git a/vendor/github.com/gopacket/gopacket/pcap/test_loopback.pcap b/vendor/github.com/gopacket/gopacket/pcap/test_loopback.pcap deleted file mode 100644 index ddeb82cd7..000000000 Binary files a/vendor/github.com/gopacket/gopacket/pcap/test_loopback.pcap and /dev/null differ diff --git a/vendor/modules.txt b/vendor/modules.txt index 618ef91f9..c9a4de22e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -497,7 +497,6 @@ github.com/googleapis/gax-go/v2/internal ## explicit; go 1.20 github.com/gopacket/gopacket github.com/gopacket/gopacket/layers -github.com/gopacket/gopacket/pcap github.com/gopacket/gopacket/pcapgo # github.com/gordonklaus/ineffassign v0.1.0 ## explicit; go 1.14