func (p *InactiveHandle) CleanUp() {
	p.pcapClose()
}
CleanUp cleans up any stuff left over from a successful or failed building
of a handle.
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"
)
const ErrNotActive = pcapErrorNotActivated
const MaxBpfInstructions = 4096
const bpfInstructionBufferSize = 8 * MaxBpfInstructions
type Handle struct {
	stop uint64
	cptr           pcapTPtr
	timeout        time.Duration
	device         string
	deviceIndex    int
	mu             sync.Mutex
	closeMu        sync.Mutex
	nanoSecsFactor int64
	pkthdr *pcapPkthdr
	bufptr *uint8
}
type Stats struct {
	PacketsReceived  int
	PacketsDropped   int
	PacketsIfDropped int
}
type Interface struct {
	Name        string
	Description string
	Flags       uint32
	Addresses   []InterfaceAddress
}
type Datalink struct {
	Name        string
	Description string
}
type InterfaceAddress struct {
	IP        net.IP
	Netmask   net.IPMask  
	Broadaddr net.IP      
	P2P       net.IP      
}
type bpfFilter struct {
	bpf pcapBpfProgram  
}
type BPF struct {
	orig string
	bpf  *bpfFilter
	hdr  pcapPkthdr  
}
type BPFInstruction struct {
	Code uint16
	Jt   uint8
	Jf   uint8
	K    uint32
}
const BlockForever = -time.Millisecond * 10
func timeoutMillis(timeout time.Duration) int {
	if timeout < 0 {
		timeout *= -1
	}
	if timeout != 0 && timeout < time.Millisecond {
		timeout = time.Millisecond
	}
	return int(timeout / time.Millisecond)
}
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 {
		p.deviceIndex = 0
	} else {
		p.deviceIndex = ifc.Index
	}
	p.nanoSecsFactor = 1000
	if p.timeout > 0 {
		if err := p.setNonBlocking(); err != nil {
			p.pcapClose()
			return nil, err
		}
	}
	return p, nil
}
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
}
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
}
type NextError int32
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))
}
const (
	NextErrorOk             NextError = 1
	NextErrorTimeoutExpired NextError = 0
	NextErrorReadError      NextError = -1
	NextErrorNoMorePackets NextError = -2
	NextErrorNotActivated  NextError = -3
)
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)
	}
}
func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error {
	if !p.isOpen() {
		return io.EOF
	}
	var waited bool
	for atomic.LoadUint64(&p.stop) == 0 {
		result := p.pcapNextPacketEx()
		switch result {
		case NextErrorOk:
			sec := p.pkthdr.getSec()
			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:
			return io.EOF
		case NextErrorTimeoutExpired:
			if waited && p.timeout > 0 {
				return result
			}
			p.waitForPacket()
			waited = true
		default:
			return result
		}
	}
	return io.EOF
}
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
}
func (p *Handle) Close() {
	p.closeMu.Lock()
	defer p.closeMu.Unlock()
	if !p.isOpen() {
		return
	}
	atomic.StoreUint64(&p.stop, 1)
	p.mu.Lock()
	defer p.mu.Unlock()
	p.pcapClose()
}
func (p *Handle) Error() error {
	return p.pcapGeterr()
}
func (p *Handle) Stats() (stat *Stats, err error) {
	return p.pcapStats()
}
func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) {
	return p.pcapListDatalinks()
}
func (p *Handle) compileBPFFilter(expr string) (pcapBpfProgram, error) {
	var maskp = uint32(pcapNetmaskUnknown)
	if len(p.device) > 0 {
		var err error
		_, maskp, err = pcapLookupnet(p.device)
		if err != nil {
			maskp = uint32(pcapNetmaskUnknown)
		}
	}
	return p.pcapCompile(expr, maskp)
}
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)
}
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
}
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)
}
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
}
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
}
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)
}
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()
}
func (b *BPF) String() string {
	return b.orig
}
func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool {
	return b.pcapOfflineFilter(ci, data)
}
func Version() string {
	return pcapLibVersion()
}
func (p *Handle) LinkType() layers.LinkType {
	return p.pcapDatalink()
}
func (p *Handle) SetLinkType(dlt layers.LinkType) error {
	return p.pcapSetDatalink(dlt)
}
func DatalinkValToName(dlt int) string {
	return pcapDatalinkValToName(dlt)
}
func DatalinkValToDescription(dlt int) string {
	return pcapDatalinkValToDescription(dlt)
}
func DatalinkNameToVal(name string) int {
	return pcapDatalinkNameToVal(name)
}
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) {
	retval = make([]InterfaceAddress, 0, 1)
	for addresses.next() {
		if addresses.addr() == nil {
			continue
		}
		var a InterfaceAddress
		var err error
		if a.IP, err = sockaddrToIP(addresses.addr()); err != nil {
			continue
		}
		if addresses.netmask() == nil {
			continue
		}
		if a.Netmask, err = sockaddrToIP(addresses.netmask()); err != nil {
			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
}
func (p *Handle) WritePacketData(data []byte) (err error) {
	return p.pcapSendpacket(data)
}
type Direction uint8
const (
	DirectionIn    = Direction(pcapDIN)
	DirectionOut   = Direction(pcapDOUT)
	DirectionInOut = Direction(pcapDINOUT)
)
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)
}
func (p *Handle) SnapLen() int {
	return p.pcapSnapshot()
}
func (p *Handle) Resolution() gopacket.TimestampResolution {
	if p.nanoSecsFactor == 1 {
		return gopacket.TimestampResolutionMicrosecond
	}
	return gopacket.TimestampResolutionNanosecond
}
type TimestampSource int
func (t TimestampSource) String() string {
	return t.pcapTstampTypeValToName()
}
func TimestampSourceFromString(s string) (TimestampSource, error) {
	return pcapTstampTypeNameToVal(s)
}
type InactiveHandle struct {
	cptr        pcapTPtr
	device      string
	deviceIndex int
	timeout     time.Duration
}
var activateErrMsg error
func (p *InactiveHandle) Error() error {
	return p.pcapGeterr()
}
func (p *InactiveHandle) Activate() (*Handle, error) {
	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
}