Committing vendored dependencies and generated protos
Change-Id: I349c149b513d9de7d9f60bde2c954a939da2fc54
diff --git a/vendor/github.com/google/gopacket/pcap/pcap_windows.go b/vendor/github.com/google/gopacket/pcap/pcap_windows.go
new file mode 100644
index 0000000..0a53338
--- /dev/null
+++ b/vendor/github.com/google/gopacket/pcap/pcap_windows.go
@@ -0,0 +1,885 @@
+// 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"
+)
+
+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 := syscall.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 := syscall.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 syscall.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)
+
+ wpcapHandle, err = syscall.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)), 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
+}