[VOL-1349] EPON OLT adapter (package B)

Change-Id: I634ef62c53813dcf4456f54948f13e06358e263c
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
+}