func (p *InactiveHandle) SetRFMon(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:
	default:
		return statusError(canset)
	}
	if status := C.pcap_set_rfmon(p.cptr, mon); status != 0 {
		return statusError(status)
	}
	return nil
}
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.
package pcap
import "C"
import (
	"errors"
	"fmt"
	"io"
	"net"
	"reflect"
	"runtime"
	"strconv"
	"sync"
	"syscall"
	"time"
	"unsafe"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
)
const errorBufferSize = 256
const MaxBpfInstructions = 4096
const bpfInstructionBufferSize = 8 * MaxBpfInstructions
type Handle struct {
	cptr         *C.pcap_t
	blockForever bool
	device       string
	mu           sync.Mutex
	pkthdr  *C.struct_pcap_pkthdr
	buf_ptr *C.u_char
}
type Stats struct {
	PacketsReceived  int
	PacketsDropped   int
	PacketsIfDropped int
}
type Interface struct {
	Name        string
	Description string
	Addresses   []InterfaceAddress
}
type Datalink struct {
	Name        string
	Description string
}
type InterfaceAddress struct {
	IP      net.IP
	Netmask net.IPMask  
}
type BPF struct {
	orig string
	bpf  _Ctype_struct_bpf_program  
}
type BPFInstruction struct {
	Code uint16
	Jt   uint8
	Jf   uint8
	K    uint32
}
const BlockForever = -time.Millisecond * 10
func timeoutMillis(timeout time.Duration) C.int {
	if timeout < 0 {
		timeout *= -1
	}
	if timeout != 0 && timeout < time.Millisecond {
		timeout = time.Millisecond
	}
	return C.int(timeout / time.Millisecond)
}
func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) {
	buf := (*C.char)(C.calloc(errorBufferSize, 1))
	defer C.free(unsafe.Pointer(buf))
	var pro C.int
	if promisc {
		pro = 1
	}
	p := &Handle{}
	p.blockForever = timeout < 0
	p.device = device
	dev := C.CString(device)
	defer C.free(unsafe.Pointer(dev))
	p.cptr = C.pcap_open_live(dev, C.int(snaplen), pro, timeoutMillis(timeout), buf)
	if p.cptr == nil {
		return nil, errors.New(C.GoString(buf))
	}
	return p, 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(cf, buf)
	if cptr == nil {
		return nil, errors.New(C.GoString(buf))
	}
	return &Handle{cptr: cptr}, nil
}
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 = C.GoBytes(unsafe.Pointer(p.buf_ptr), C.int(ci.CaptureLength))
	}
	p.mu.Unlock()
	return
}
type activateError C.int
const (
	aeNoError      = 0
	aeActivated    = C.PCAP_ERROR_ACTIVATED
	aePromisc      = C.PCAP_WARNING_PROMISC_NOTSUP
	aeNoSuchDevice = C.PCAP_ERROR_NO_SUCH_DEVICE
	aeDenied       = C.PCAP_ERROR_PERM_DENIED
	aeNotUp        = C.PCAP_ERROR_IFACE_NOT_UP
)
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"
	default:
		return fmt.Sprintf("unknown activated error: %d", a)
	}
}
func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error {
	if p.cptr == nil {
		return io.EOF
	}
	var result NextError
	for {
		result = NextError(C.pcap_next_ex(p.cptr, &p.pkthdr, &p.buf_ptr))
		if p.blockForever && result == NextErrorTimeoutExpired {
			continue
		}
		break
	}
	if result != NextErrorOk {
		if result == NextErrorNoMorePackets {
			return io.EOF
		} else {
			return result
		}
	}
	ci.Timestamp = time.Unix(int64(p.pkthdr.ts.tv_sec),
		int64(p.pkthdr.ts.tv_usec)*1000)  
	ci.CaptureLength = int(p.pkthdr.caplen)
	ci.Length = int(p.pkthdr.len)
	return nil
}
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.buf_ptr))
		slice.Len = ci.CaptureLength
		slice.Cap = ci.CaptureLength
	}
	p.mu.Unlock()
	return
}
func (p *Handle) Close() {
	p.mu.Lock()
	if p.cptr == nil {
		return
	}
	C.pcap_close(p.cptr)
	p.cptr = nil
	p.mu.Unlock()
}
func (p *Handle) Error() error {
	return errors.New(C.GoString(C.pcap_geterr(p.cptr)))
}
func (p *Handle) Stats() (stat *Stats, err error) {
	var cstats _Ctype_struct_pcap_stat
	if -1 == C.pcap_stats(p.cptr, &cstats) {
		return nil, p.Error()
	}
	return &Stats{
		PacketsReceived:  int(cstats.ps_recv),
		PacketsDropped:   int(cstats.ps_drop),
		PacketsIfDropped: int(cstats.ps_ifdrop),
	}, nil
}
func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) {
	var dlt_buf *C.int
	n := int(C.pcap_list_datalinks(p.cptr, &dlt_buf))
	if -1 == n {
		return nil, p.Error()
	}
	defer C.pcap_free_datalinks(dlt_buf)
	datalinks = make([]Datalink, n)
	dltArray := (*[100]C.int)(unsafe.Pointer(dlt_buf))
	for i := 0; i < n; i++ {
		expr := C.pcap_datalink_val_to_name((*dltArray)[i])
		datalinks[i].Name = C.GoString(expr)
		expr = C.pcap_datalink_val_to_description((*dltArray)[i])
		datalinks[i].Description = C.GoString(expr)
	}
	return datalinks, nil
}
func (p *Handle) compileBPFFilter(expr string) (_Ctype_struct_bpf_program, error) {
	errorBuf := (*C.char)(C.calloc(errorBufferSize, 1))
	defer C.free(unsafe.Pointer(errorBuf))
	var netp uint32
	var maskp uint32
	if len(p.device) > 0 {
		dev := C.CString(p.device)
		defer C.free(unsafe.Pointer(dev))
		if -1 == C.pcap_lookupnet(
			dev,
			(*C.bpf_u_int32)(unsafe.Pointer(&netp)),
			(*C.bpf_u_int32)(unsafe.Pointer(&maskp)),
			errorBuf,
		) {
		}
	}
	var bpf _Ctype_struct_bpf_program
	cexpr := C.CString(expr)
	defer C.free(unsafe.Pointer(cexpr))
	if -1 == C.pcap_compile(p.cptr, &bpf, cexpr, 1, C.bpf_u_int32(maskp)) {
		return bpf, p.Error()
	}
	return bpf, nil
}
func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error) {
	bpf, err := p.compileBPFFilter(expr)
	defer C.pcap_freecode(&bpf)
	if err != nil {
		return nil, err
	}
	bpfInsn := (*[bpfInstructionBufferSize]_Ctype_struct_bpf_insn)(unsafe.Pointer(bpf.bf_insns))[0:bpf.bf_len:bpf.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, nil
}
func (p *Handle) SetBPFFilter(expr string) (err error) {
	bpf, err := p.compileBPFFilter(expr)
	defer C.pcap_freecode(&bpf)
	if err != nil {
		return err
	}
	if -1 == C.pcap_setfilter(p.cptr, &bpf) {
		C.pcap_freecode(&bpf)
		return p.Error()
	}
	return nil
}
func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error) {
	bpf, err := bpfInstructionFilter(bpfInstructions)
	if err != nil {
		return err
	}
	if -1 == C.pcap_setfilter(p.cptr, &bpf) {
		C.pcap_freecode(&bpf)
		return p.Error()
	}
	C.pcap_freecode(&bpf)
	return nil
}
func bpfInstructionFilter(bpfInstructions []BPFInstruction) (bpf _Ctype_struct_bpf_program, 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)
	}
	bpf.bf_len = C.u_int(len(bpfInstructions))
	cbpfInsns := C.calloc(C.size_t(len(bpfInstructions)), C.size_t(unsafe.Sizeof(bpfInstructions[0])))
	copy((*[bpfInstructionBufferSize]BPFInstruction)(cbpfInsns)[0:len(bpfInstructions)], bpfInstructions)
	bpf.bf_insns = (*_Ctype_struct_bpf_insn)(cbpfInsns)
	return
}
func (p *Handle) NewBPF(expr string) (*BPF, error) {
	bpf := &BPF{orig: expr}
	cexpr := C.CString(expr)
	defer C.free(unsafe.Pointer(cexpr))
	if C.pcap_compile(p.cptr, &bpf.bpf, cexpr  , 1, C.PCAP_NETMASK_UNKNOWN) != 0 {
		return nil, p.Error()
	}
	runtime.SetFinalizer(bpf, destroyBPF)
	return bpf, nil
}
func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error) {
	var err error
	bpf := &BPF{orig: "BPF Instruction Filter"}
	bpf.bpf, err = bpfInstructionFilter(bpfInstructions)
	if err != nil {
		return nil, err
	}
	runtime.SetFinalizer(bpf, destroyBPF)
	return bpf, nil
}
func destroyBPF(bpf *BPF) {
	C.pcap_freecode(&bpf.bpf)
}
func (b *BPF) String() string {
	return b.orig
}
func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool {
	var hdr C.struct_pcap_pkthdr
	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))  
	hdr.len = C.bpf_u_int32(ci.Length)
	dataptr := (*C.u_char)(unsafe.Pointer(&data[0]))
	return C.pcap_offline_filter(&b.bpf, &hdr, dataptr) != 0
}
func Version() string {
	return C.GoString(C.pcap_lib_version())
}
func (p *Handle) LinkType() layers.LinkType {
	return layers.LinkType(C.pcap_datalink(p.cptr))
}
func (p *Handle) SetLinkType(dlt layers.LinkType) error {
	if -1 == C.pcap_set_datalink(p.cptr, C.int(dlt)) {
		return p.Error()
	}
	return nil
}
func FindAllDevs() (ifs []Interface, err error) {
	var buf *C.char
	buf = (*C.char)(C.calloc(errorBufferSize, 1))
	defer C.free(unsafe.Pointer(buf))
	var alldevsp *C.pcap_if_t
	if -1 == C.pcap_findalldevs((**C.pcap_if_t)(&alldevsp), buf) {
		return nil, errors.New(C.GoString(buf))
	}
	defer C.pcap_freealldevs((*C.pcap_if_t)(alldevsp))
	dev := alldevsp
	var i uint32
	for i = 0; dev != nil; dev = (*C.pcap_if_t)(dev.next) {
		i++
	}
	ifs = make([]Interface, i)
	dev = alldevsp
	for j := uint32(0); dev != nil; dev = (*C.pcap_if_t)(dev.next) {
		var iface Interface
		iface.Name = C.GoString(dev.name)
		iface.Description = C.GoString(dev.description)
		iface.Addresses = findalladdresses(dev.addresses)
		ifs[j] = iface
		j++
	}
	return
}
func findalladdresses(addresses *_Ctype_struct_pcap_addr) (retval []InterfaceAddress) {
	retval = make([]InterfaceAddress, 0, 1)
	for curaddr := addresses; curaddr != nil; curaddr = (*_Ctype_struct_pcap_addr)(curaddr.next) {
		if curaddr.addr == nil {
			continue
		}
		var a InterfaceAddress
		var err error
		if a.IP, err = sockaddr_to_IP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.addr))); err != nil {
			continue
		}
		if curaddr.netmask == nil {
			continue
		}
		if a.Netmask, err = sockaddr_to_IP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.netmask))); err != nil {
			a.Netmask = nil
		}
		retval = append(retval, a)
	}
	return
}
func sockaddr_to_IP(rsa *syscall.RawSockaddr) (IP []byte, err error) {
	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) {
	if -1 == C.pcap_sendpacket(p.cptr, (*C.u_char)(&data[0]), (C.int)(len(data))) {
		err = p.Error()
	}
	return
}
type Direction uint8
const (
	DirectionIn    Direction = C.PCAP_D_IN
	DirectionOut   Direction = C.PCAP_D_OUT
	DirectionInOut Direction = C.PCAP_D_INOUT
)
func (p *Handle) SetDirection(direction Direction) error {
	if direction != DirectionIn && direction != DirectionOut && direction != DirectionInOut {
		return fmt.Errorf("Invalid direction: %v", direction)
	}
	if status := C.pcap_setdirection(p.cptr, (C.pcap_direction_t)(direction)); status < 0 {
		return statusError(status)
	}
	return nil
}
type TimestampSource C.int
func (t TimestampSource) String() string {
	return C.GoString(C.pcap_tstamp_type_val_to_name(C.int(t)))
}
func TimestampSourceFromString(s string) (TimestampSource, error) {
	t := C.pcap_tstamp_type_name_to_val(C.CString(s))
	if t < 0 {
		return 0, statusError(t)
	}
	return TimestampSource(t), nil
}
func statusError(status C.int) error {
	return errors.New(C.GoString(C.pcap_statustostr(status)))
}
type InactiveHandle struct {
	cptr         *C.pcap_t
	device       string
	blockForever bool
}
func (p *InactiveHandle) Activate() (*Handle, error) {
	err := activateError(C.pcap_activate(p.cptr))
	if err != aeNoError {
		return nil, err
	}
	h := &Handle{cptr: p.cptr, device: p.device, blockForever: p.blockForever}
	p.cptr = nil
	return h, nil
}
func (p *InactiveHandle) CleanUp() {
	if p.cptr != nil {
		C.pcap_close(p.cptr)
	}
}
func NewInactiveHandle(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, device: device}, nil
}
func (p *InactiveHandle) SetSnapLen(snaplen int) error {
	if status := C.pcap_set_snaplen(p.cptr, C.int(snaplen)); status < 0 {
		return statusError(status)
	}
	return nil
}
func (p *InactiveHandle) SetPromisc(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) SetTimeout(timeout time.Duration) error {
	p.blockForever = timeout < 0
	if status := C.pcap_set_timeout(p.cptr, timeoutMillis(timeout)); status < 0 {
		return statusError(status)
	}
	return nil
}
func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource) {
	var types *C.int
	n := int(C.pcap_list_tstamp_types(p.cptr, &types))
	defer C.pcap_free_tstamp_types(types)
	typesArray := (*[100]C.int)(unsafe.Pointer(types))
	for i := 0; i < n; i++ {
		out = append(out, TimestampSource((*typesArray)[i]))
	}
	return
}
func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error {
	if status := C.pcap_set_tstamp_type(p.cptr, C.int(t)); status < 0 {
		return statusError(status)
	}
	return nil
}
var CannotSetRFMon = errors.New("Cannot set rfmon for this handle")