implementl get user and database

Signed-off-by: zhuhuijun <zhuhuijunzhj@gmail.com>
This commit is contained in:
zhuhuijun
2022-12-07 18:07:00 +08:00
parent add66245ba
commit af88bad075
166 changed files with 58325 additions and 102 deletions

View File

@@ -0,0 +1,74 @@
// 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
}

View File

@@ -0,0 +1,76 @@
// 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
Pad_cgo_0 [4]byte
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
Pad_cgo_0 [4]byte
}
type pcapAddr struct {
Next *pcapAddr
Addr *syscall.RawSockaddr
Netmask *syscall.RawSockaddr
Broadaddr *syscall.RawSockaddr
Dstaddr *syscall.RawSockaddr
}

112
vendor/github.com/google/gopacket/pcap/doc.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
// 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/google/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

876
vendor/github.com/google/gopacket/pcap/pcap.go generated vendored Normal file
View File

@@ -0,0 +1,876 @@
// 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/google/gopacket"
"github.com/google/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)
}

707
vendor/github.com/google/gopacket/pcap/pcap_unix.go generated vendored Normal file
View File

@@ -0,0 +1,707 @@
// 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.
//
// +build !windows
package pcap
import (
"errors"
"os"
"sync"
"syscall"
"time"
"unsafe"
"github.com/google/gopacket"
"github.com/google/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 <stdlib.h>
#include <pcap.h>
#include <stdint.h>
#include <poll.h>
// 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 <v1.5
// to always return micro resolution.
#define PCAP_TSTAMP_PRECISION_MICRO 0
#define PCAP_TSTAMP_PRECISION_NANO 1
pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
char *errbuf) {
return pcap_open_offline(fname, errbuf);
}
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
char *errbuf) {
return pcap_fopen_offline(fp, errbuf);
}
int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) {
if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO)
return 0;
return PCAP_ERROR_TSTAMP_PRECISION_NOTSUP;
}
int pcap_get_tstamp_precision(pcap_t *p) {
return PCAP_TSTAMP_PRECISION_MICRO;
}
#ifndef PCAP_TSTAMP_HOST // < v1.2
int pcap_set_tstamp_type(pcap_t* p, int t) { return -1; }
int pcap_list_tstamp_types(pcap_t* p, int** t) { return 0; }
void pcap_free_tstamp_types(int *tstamp_types) {}
const char* pcap_tstamp_type_val_to_name(int t) {
return "pcap timestamp types not supported";
}
int pcap_tstamp_type_name_to_val(const char* t) {
return PCAP_ERROR;
}
#endif // < v1.2
#endif // < v1.5
#ifndef PCAP_ERROR_PROMISC_PERM_DENIED
#define PCAP_ERROR_PROMISC_PERM_DENIED -11
#endif
// Windows, Macs, and Linux all use different time types. Joy.
#ifdef __APPLE__
#define gopacket_time_secs_t __darwin_time_t
#define gopacket_time_usecs_t __darwin_suseconds_t
#elif __ANDROID__
#define gopacket_time_secs_t __kernel_time_t
#define gopacket_time_usecs_t __kernel_suseconds_t
#elif __GLIBC__
#define gopacket_time_secs_t __time_t
#define gopacket_time_usecs_t __suseconds_t
#else // Some form of linux/bsd/etc...
#include <sys/param.h>
#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
}

898
vendor/github.com/google/gopacket/pcap/pcap_windows.go generated vendored Normal file
View File

@@ -0,0 +1,898 @@
// 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/google/gopacket"
"github.com/google/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
}

BIN
vendor/github.com/google/gopacket/pcap/test_dns.pcap generated vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.