diff options
Diffstat (limited to 'src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/google/gopacket/pcap/pcap.go')
-rw-r--r-- | src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/google/gopacket/pcap/pcap.go | 866 |
1 files changed, 0 insertions, 866 deletions
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/google/gopacket/pcap/pcap.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/google/gopacket/pcap/pcap.go deleted file mode 100644 index 6eeeb6535e8..00000000000 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/google/gopacket/pcap/pcap.go +++ /dev/null @@ -1,866 +0,0 @@ -// 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" - "io" - "net" - "os" - "reflect" - "runtime" - "strconv" - "sync" - "sync/atomic" - "syscall" - "time" - "unsafe" - - "github.com/google/gopacket" - "github.com/google/gopacket/layers" -) - -// ErrNotActive is returned if handle is not activated -const ErrNotActive = pcapErrorNotActivated - -// MaxBpfInstructions is the maximum number of BPF instructions supported (BPF_MAXINSNS), -// taken from Linux kernel: include/uapi/linux/bpf_common.h -// -// https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf_common.h -const MaxBpfInstructions = 4096 - -// 8 bytes per instruction, max 4096 instructions -const bpfInstructionBufferSize = 8 * MaxBpfInstructions - -// Handle provides a connection to a pcap handle, allowing users to read packets -// off the wire (Next), inject packets onto the wire (Inject), and -// perform a number of other functions to affect and understand packet output. -// -// Handles are already pcap_activate'd -type Handle struct { - // stop is set to a non-zero value by Handle.Close to signal to - // getNextBufPtrLocked to stop trying to read packets - // This must be the first entry to ensure alignment for sync.atomic - stop uint64 - // cptr is the handle for the actual pcap C object. - cptr pcapTPtr - timeout time.Duration - device string - deviceIndex int - mu sync.Mutex - closeMu sync.Mutex - nanoSecsFactor int64 - - // Since pointers to these objects are passed into a C function, if - // they're declared locally then the Go compiler thinks they may have - // escaped into C-land, so it allocates them on the heap. This causes a - // huge memory hit, so to handle that we store them here instead. - pkthdr *pcapPkthdr - bufptr *uint8 -} - -// Stats contains statistics on how many packets were handled by a pcap handle, -// and what was done with those packets. -type Stats struct { - PacketsReceived int - PacketsDropped int - PacketsIfDropped int -} - -// Interface describes a single network interface on a machine. -type Interface struct { - Name string - Description string - Flags uint32 - Addresses []InterfaceAddress -} - -// Datalink describes the datalink -type Datalink struct { - Name string - Description string -} - -// InterfaceAddress describes an address associated with an Interface. -// Currently, it's IPv4/6 specific. -type InterfaceAddress struct { - IP net.IP - Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it. - Broadaddr net.IP // Broadcast address for this IP may be nil - P2P net.IP // P2P destination address for this IP may be nil -} - -// BPF is a compiled filter program, useful for offline packet matching. -type BPF struct { - orig string - bpf pcapBpfProgram // takes a finalizer, not overriden by outsiders - hdr pcapPkthdr // allocate on the heap to enable optimizations -} - -// BPFInstruction is a byte encoded structure holding a BPF instruction -type BPFInstruction struct { - Code uint16 - Jt uint8 - Jf uint8 - K uint32 -} - -// BlockForever causes it to block forever waiting for packets, when passed -// into SetTimeout or OpenLive, while still returning incoming packets to userland relatively -// quickly. -const BlockForever = -time.Millisecond * 10 - -func timeoutMillis(timeout time.Duration) int { - // Flip sign if necessary. See package docs on timeout for reasoning behind this. - if timeout < 0 { - timeout *= -1 - } - // Round up - if timeout != 0 && timeout < time.Millisecond { - timeout = time.Millisecond - } - return int(timeout / time.Millisecond) -} - -// OpenLive opens a device and returns a *Handle. -// It takes as arguments the name of the device ("eth0"), the maximum size to -// read for each packet (snaplen), whether to put the interface in promiscuous -// mode, and a timeout. Warning: this function supports only microsecond timestamps. -// For nanosecond resolution use an InactiveHandle. -// -// See the package documentation for important details regarding 'timeout'. -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 { - // The device wasn't found in the OS, but could be "any" - // Set index to 0 - p.deviceIndex = 0 - } else { - p.deviceIndex = ifc.Index - } - - p.nanoSecsFactor = 1000 - - // Only set the PCAP handle into non-blocking mode if we have a timeout - // greater than zero. If the user wants to block forever, we'll let libpcap - // handle that. - if p.timeout > 0 { - if err := p.setNonBlocking(); err != nil { - p.pcapClose() - return nil, err - } - } - - return p, nil -} - -// OpenOffline opens a file and returns its contents as a *Handle. Depending on libpcap support and -// on the timestamp resolution used in the file, nanosecond or microsecond resolution is used -// internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used -// to query the actual resolution used. -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 -} - -// OpenOfflineFile returns contents of input file as a *Handle. Depending on libpcap support and -// on the timestamp resolution used in the file, nanosecond or microsecond resolution is used -// internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used -// to query the actual resolution used. -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 -} - -// NextError is the return code from a call to Next. -type NextError int32 - -// NextError implements the error interface. -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)) -} - -// NextError values. -const ( - NextErrorOk NextError = 1 - NextErrorTimeoutExpired NextError = 0 - NextErrorReadError NextError = -1 - // NextErrorNoMorePackets is returned when reading from a file (OpenOffline) and - // EOF is reached. When this happens, Next() returns io.EOF instead of this. - NextErrorNoMorePackets NextError = -2 - NextErrorNotActivated NextError = -3 -) - -// ReadPacketData returns the next packet read from the pcap handle, along with an error -// code associated with that packet. If the packet is read successfully, the -// returned error is nil. -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) -) - -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()) - default: - return fmt.Sprintf("unknown activated error: %d", a) - } -} - -// getNextBufPtrLocked is shared code for ReadPacketData and -// ZeroCopyReadPacketData. -func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error { - if !p.isOpen() { - return io.EOF - } - - // set after we have call waitForPacket for the first time - var waited bool - - for atomic.LoadUint64(&p.stop) == 0 { - // try to read a packet if one is immediately available - result := p.pcapNextPacketEx() - - switch result { - case NextErrorOk: - sec := p.pkthdr.getSec() - // convert micros to nanos - 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: - // no more packets, return EOF rather than libpcap-specific error - return io.EOF - case NextErrorTimeoutExpired: - // we've already waited for a packet and we're supposed to time out - // - // we should never actually hit this if we were passed BlockForever - // since we should block on C.pcap_next_ex until there's a packet - // to read. - if waited && p.timeout > 0 { - return result - } - - // wait for packet before trying again - p.waitForPacket() - waited = true - default: - return result - } - } - - // stop must be set - return io.EOF -} - -// ZeroCopyReadPacketData reads the next packet off the wire, and returns its data. -// The slice returned by ZeroCopyReadPacketData points to bytes owned by the -// the Handle. Each call to ZeroCopyReadPacketData invalidates any data previously -// returned by ZeroCopyReadPacketData. Care must be taken not to keep pointers -// to old bytes when using ZeroCopyReadPacketData... if you need to keep data past -// the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies -// the bytes into a new buffer for you. -// data1, _, _ := handle.ZeroCopyReadPacketData() -// // do everything you want with data1 here, copying bytes out of it if you'd like to keep them around. -// data2, _, _ := handle.ZeroCopyReadPacketData() // invalidates bytes in data1 -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 -} - -// Close closes the underlying pcap handle. -func (p *Handle) Close() { - p.closeMu.Lock() - defer p.closeMu.Unlock() - - if !p.isOpen() { - return - } - - atomic.StoreUint64(&p.stop, 1) - - // wait for packet reader to stop - p.mu.Lock() - defer p.mu.Unlock() - - p.pcapClose() -} - -// Error returns the current error associated with a pcap handle (pcap_geterr). -func (p *Handle) Error() error { - return p.pcapGeterr() -} - -// Stats returns statistics on the underlying pcap handle. -func (p *Handle) Stats() (stat *Stats, err error) { - return p.pcapStats() -} - -// ListDataLinks obtains a list of all possible data link types supported for an interface. -func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) { - return p.pcapListDatalinks() -} - -// compileBPFFilter always returns an allocated C.struct_bpf_program -// It is the callers responsibility to free the memory again, e.g. -// -// C.pcap_freecode(&bpf) -// -func (p *Handle) compileBPFFilter(expr string) (pcapBpfProgram, error) { - var maskp = uint32(pcapNetmaskUnknown) - - // Only do the lookup on network interfaces. - // No device indicates we're handling a pcap file. - if len(p.device) > 0 { - var err error - _, maskp, err = pcapLookupnet(p.device) - if err != nil { - // We can't lookup the network, but that could be because the interface - // doesn't have an IPv4. - maskp = uint32(pcapNetmaskUnknown) - } - } - - return p.pcapCompile(expr, maskp) -} - -// CompileBPFFilter compiles and returns a BPF filter with given a link type and capture length. -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) -} - -// CompileBPFFilter compiles and returns a BPF filter for the pcap handle. -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 -} - -// SetBPFFilter compiles and sets a BPF filter for the pcap handle. -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) -} - -// SetBPFInstructionFilter may be used to apply a filter in BPF asm byte code format. -// -// Simplest way to generate BPF asm byte code is with tcpdump: -// tcpdump -dd 'udp' -// -// The output may be used directly to add a filter, e.g.: -// bpfInstructions := []pcap.BpfInstruction{ -// {0x28, 0, 0, 0x0000000c}, -// {0x15, 0, 9, 0x00000800}, -// {0x30, 0, 0, 0x00000017}, -// {0x15, 0, 7, 0x00000006}, -// {0x28, 0, 0, 0x00000014}, -// {0x45, 5, 0, 0x00001fff}, -// {0xb1, 0, 0, 0x0000000e}, -// {0x50, 0, 0, 0x0000001b}, -// {0x54, 0, 0, 0x00000012}, -// {0x15, 0, 1, 0x00000012}, -// {0x6, 0, 0, 0x0000ffff}, -// {0x6, 0, 0, 0x00000000}, -// } -// -// An other posibility is to write the bpf code in bpf asm. -// Documentation: https://www.kernel.org/doc/Documentation/networking/filter.txt -// -// To compile the code use bpf_asm from -// https://github.com/torvalds/linux/tree/master/tools/net -// -// The following command may be used to convert bpf_asm output to c/go struct, usable for SetBPFFilterByte: -// bpf_asm -c tcp.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 -} - -// NewBPF compiles the given string into a new filter program. -// -// BPF filters need to be created from activated handles, because they need to -// know the underlying link type to correctly compile their offsets. -func (p *Handle) NewBPF(expr string) (*BPF, error) { - bpf := &BPF{orig: expr} - - var err error - bpf.bpf, err = p.pcapCompile(expr, pcapNetmaskUnknown) - if err != nil { - return nil, err - } - - runtime.SetFinalizer(bpf, destroyBPF) - return bpf, nil -} - -// NewBPF allows to create a BPF without requiring an existing handle. -// This allows to match packets obtained from a-non GoPacket capture source -// to be matched. -// -// buf := make([]byte, MaxFrameSize) -// bpfi, _ := pcap.NewBPF(layers.LinkTypeEthernet, MaxFrameSize, "icmp") -// n, _ := someIO.Read(buf) -// ci := gopacket.CaptureInfo{CaptureLength: n, Length: n} -// if bpfi.Matches(ci, buf) { -// doSomething() -// } -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) -} - -// NewBPFInstructionFilter sets the given BPFInstructions as new filter program. -// -// More details see func SetBPFInstructionFilter -// -// BPF filters need to be created from activated handles, because they need to -// know the underlying link type to correctly compile their offsets. -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) { - bpf.bpf.free() -} - -// String returns the original string this BPF filter was compiled from. -func (b *BPF) String() string { - return b.orig -} - -// Matches returns true if the given packet data matches this filter. -func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool { - return b.pcapOfflineFilter(ci, data) -} - -// Version returns pcap_lib_version. -func Version() string { - return pcapLibVersion() -} - -// LinkType returns pcap_datalink, as a layers.LinkType. -func (p *Handle) LinkType() layers.LinkType { - return p.pcapDatalink() -} - -// SetLinkType calls pcap_set_datalink on the pcap handle. -func (p *Handle) SetLinkType(dlt layers.LinkType) error { - return p.pcapSetDatalink(dlt) -} - -// DatalinkValToName returns pcap_datalink_val_to_name as string -func DatalinkValToName(dlt int) string { - return pcapDatalinkValToName(dlt) -} - -// DatalinkValToDescription returns pcap_datalink_val_to_description as string -func DatalinkValToDescription(dlt int) string { - return pcapDatalinkValToDescription(dlt) -} - -// DatalinkNameToVal returns pcap_datalink_name_to_val as int -func DatalinkNameToVal(name string) int { - return pcapDatalinkNameToVal(name) -} - -// FindAllDevs attempts to enumerate all interfaces on the current machine. -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) { - // TODO - make it support more than IPv4 and IPv6? - retval = make([]InterfaceAddress, 0, 1) - for addresses.next() { - // Strangely, it appears that in some cases, we get a pcap address back from - // pcap_findalldevs with a nil .addr. It appears that we can skip over - // these. - if addresses.addr() == nil { - continue - } - var a InterfaceAddress - var err error - if a.IP, err = sockaddrToIP(addresses.addr()); err != nil { - continue - } - // To be safe, we'll also check for netmask. - if addresses.netmask() == nil { - continue - } - if a.Netmask, err = sockaddrToIP(addresses.netmask()); err != nil { - // If we got an IP address but we can't get a netmask, just return the IP - // address. - 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 -} - -// WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle. -func (p *Handle) WritePacketData(data []byte) (err error) { - return p.pcapSendpacket(data) -} - -// Direction is used by Handle.SetDirection. -type Direction uint8 - -// Direction values for Handle.SetDirection. -const ( - DirectionIn = Direction(pcapDIN) - DirectionOut = Direction(pcapDOUT) - DirectionInOut = Direction(pcapDINOUT) -) - -// SetDirection sets the direction for which packets will be captured. -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) -} - -// SnapLen returns the snapshot length -func (p *Handle) SnapLen() int { - return p.pcapSnapshot() -} - -// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution. -func (p *Handle) Resolution() gopacket.TimestampResolution { - if p.nanoSecsFactor == 1 { - return gopacket.TimestampResolutionMicrosecond - } - return gopacket.TimestampResolutionNanosecond -} - -// TimestampSource tells PCAP which type of timestamp to use for packets. -type TimestampSource int - -// String returns the timestamp type as a human-readable string. -func (t TimestampSource) String() string { - return t.pcapTstampTypeValToName() -} - -// TimestampSourceFromString translates a string into a timestamp type, case -// insensitive. -func TimestampSourceFromString(s string) (TimestampSource, error) { - return pcapTstampTypeNameToVal(s) -} - -// InactiveHandle allows you to call pre-pcap_activate functions on your pcap -// handle to set it up just the way you'd like. -type InactiveHandle struct { - // cptr is the handle for the actual pcap C object. - cptr pcapTPtr - device string - deviceIndex int - timeout time.Duration -} - -// holds the err messoge in case activation returned a Warning -var activateErrMsg error - -// Error returns the current error associated with a pcap handle (pcap_geterr). -func (p *InactiveHandle) Error() error { - return p.pcapGeterr() -} - -// Activate activates the handle. The current InactiveHandle becomes invalid -// and all future function calls on it will fail. -func (p *InactiveHandle) Activate() (*Handle, error) { - // ignore error with set_tstamp_precision, since the actual precision is queried later anyway - pcapSetTstampPrecision(p.cptr, pcapTstampPrecisionNano) - handle, err := p.pcapActivate() - if err != aeNoError { - if err == aeWarning { - 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 -} - -// CleanUp cleans up any stuff left over from a successful or failed building -// of a handle. -func (p *InactiveHandle) CleanUp() { - p.pcapClose() -} - -// NewInactiveHandle creates a new InactiveHandle, which wraps an un-activated PCAP handle. -// Callers of NewInactiveHandle should immediately defer 'CleanUp', as in: -// inactive := NewInactiveHandle("eth0") -// defer inactive.CleanUp() -func NewInactiveHandle(device string) (*InactiveHandle, error) { - // Try to get the interface index, but iy could be something like "any" - // in which case use 0, which doesn't exist in nature - deviceIndex := 0 - ifc, err := net.InterfaceByName(device) - if err == nil { - deviceIndex = ifc.Index - } - - // This copies a bunch of the pcap_open_live implementation from pcap.c: - handle, err := pcapCreate(device) - if err != nil { - return nil, err - } - handle.device = device - handle.deviceIndex = deviceIndex - return handle, nil -} - -// SetSnapLen sets the snap length (max bytes per packet to capture). -func (p *InactiveHandle) SetSnapLen(snaplen int) error { - return p.pcapSetSnaplen(snaplen) -} - -// SetPromisc sets the handle to either be promiscuous (capture packets -// unrelated to this host) or not. -func (p *InactiveHandle) SetPromisc(promisc bool) error { - return p.pcapSetPromisc(promisc) -} - -// SetTimeout sets the read timeout for the handle. -// -// See the package documentation for important details regarding 'timeout'. -func (p *InactiveHandle) SetTimeout(timeout time.Duration) error { - err := p.pcapSetTimeout(timeout) - if err != nil { - return err - } - p.timeout = timeout - return nil -} - -// SupportedTimestamps returns a list of supported timstamp types for this -// handle. -func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource) { - return p.pcapListTstampTypes() -} - -// SetTimestampSource sets the type of timestamp generator PCAP uses when -// attaching timestamps to packets. -func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error { - return p.pcapSetTstampType(t) -} - -// CannotSetRFMon is returned by SetRFMon if the handle does not allow -// setting RFMon because pcap_can_set_rfmon returns 0. -var CannotSetRFMon = errors.New("Cannot set rfmon for this handle") - -// 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. -func (p *InactiveHandle) SetRFMon(monitor bool) error { - return p.pcapSetRfmon(monitor) -} - -// SetBufferSize sets the buffer size (in bytes) of the handle. -func (p *InactiveHandle) SetBufferSize(bufferSize int) error { - return p.pcapSetBufferSize(bufferSize) -} - -// SetImmediateMode sets (or unsets) the immediate mode of the -// handle. In immediate mode, packets are delivered to the application -// as soon as they arrive. In other words, this overrides SetTimeout. -func (p *InactiveHandle) SetImmediateMode(mode bool) error { - return p.pcapSetImmediateMode(mode) -} |