123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714 |
- // 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.
- //
- //go:build !windows
- // +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: /usr/local/lib/libpcap.a
- #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>
- // 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);
- }
- 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 usec) {
- fd_set fds;
- int fd;
- struct timeval tv;
- fd = pcap_get_selectable_fd(p);
- if(fd < 0) {
- return fd;
- }
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = usec;
- if(usec != 0) {
- return select(fd+1, &fds, NULL, NULL, &tv);
- }
- // block indefinitely if no timeout provided
- return select(fd+1, &fds, NULL, NULL, NULL);
- }
- // libpcap version < v1.5 doesn't have timestamp precision (everything is microsecond)
- // see pcap.go for an explanation of why precision is ignored
- #ifndef PCAP_ERROR_TSTAMP_PRECISION_NOTSUP // < v1.5
- pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
- char *errbuf) {
- return pcap_fopen_offline(fp, errbuf);
- }
- #endif // < v1.5
- */
- 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
- 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),
- 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() {
- // need to wait less than the read timeout according to pcap documentation.
- // timeoutMillis rounds up to at least one millisecond so we can safely
- // subtract up to a millisecond.
- usec := timeoutMillis(p.timeout) * 1000
- usec -= 100
- C.pcap_wait(p.cptr, C.int(usec))
- }
- // 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
- }
|