github.com/gopacket/gopacket@v1.1.0/pcap/pcap.go (about)

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  // Copyright 2009-2011 Andreas Krennmair. All rights reserved.
     3  //
     4  // Use of this source code is governed by a BSD-style license
     5  // that can be found in the LICENSE file in the root of the source
     6  // tree.
     7  
     8  package pcap
     9  
    10  import (
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"net"
    15  	"os"
    16  	"reflect"
    17  	"runtime"
    18  	"strconv"
    19  	"sync"
    20  	"sync/atomic"
    21  	"syscall"
    22  	"time"
    23  	"unsafe"
    24  
    25  	"github.com/gopacket/gopacket"
    26  	"github.com/gopacket/gopacket/layers"
    27  )
    28  
    29  // ErrNotActive is returned if handle is not activated
    30  const ErrNotActive = pcapErrorNotActivated
    31  
    32  // MaxBpfInstructions is the maximum number of BPF instructions supported (BPF_MAXINSNS),
    33  // taken from Linux kernel: include/uapi/linux/bpf_common.h
    34  //
    35  // https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf_common.h
    36  const MaxBpfInstructions = 4096
    37  
    38  // 8 bytes per instruction, max 4096 instructions
    39  const bpfInstructionBufferSize = 8 * MaxBpfInstructions
    40  
    41  // Handle provides a connection to a pcap handle, allowing users to read packets
    42  // off the wire (Next), inject packets onto the wire (Inject), and
    43  // perform a number of other functions to affect and understand packet output.
    44  //
    45  // Handles are already pcap_activate'd
    46  type Handle struct {
    47  	// stop is set to a non-zero value by Handle.Close to signal to
    48  	// getNextBufPtrLocked to stop trying to read packets
    49  	// This must be the first entry to ensure alignment for sync.atomic
    50  	stop uint64
    51  	// cptr is the handle for the actual pcap C object.
    52  	cptr           pcapTPtr
    53  	timeout        time.Duration
    54  	device         string
    55  	deviceIndex    int
    56  	mu             sync.Mutex
    57  	closeMu        sync.Mutex
    58  	nanoSecsFactor int64
    59  
    60  	// Since pointers to these objects are passed into a C function, if
    61  	// they're declared locally then the Go compiler thinks they may have
    62  	// escaped into C-land, so it allocates them on the heap.  This causes a
    63  	// huge memory hit, so to handle that we store them here instead.
    64  	pkthdr *pcapPkthdr
    65  	bufptr *uint8
    66  }
    67  
    68  // Stats contains statistics on how many packets were handled by a pcap handle,
    69  // and what was done with those packets.
    70  type Stats struct {
    71  	PacketsReceived  int
    72  	PacketsDropped   int
    73  	PacketsIfDropped int
    74  }
    75  
    76  // Interface describes a single network interface on a machine.
    77  type Interface struct {
    78  	Name        string
    79  	Description string
    80  	Flags       uint32
    81  	Addresses   []InterfaceAddress
    82  }
    83  
    84  // Datalink describes the datalink
    85  type Datalink struct {
    86  	Name        string
    87  	Description string
    88  }
    89  
    90  // InterfaceAddress describes an address associated with an Interface.
    91  // Currently, it's IPv4/6 specific.
    92  type InterfaceAddress struct {
    93  	IP        net.IP
    94  	Netmask   net.IPMask // Netmask may be nil if we were unable to retrieve it.
    95  	Broadaddr net.IP     // Broadcast address for this IP may be nil
    96  	P2P       net.IP     // P2P destination address for this IP may be nil
    97  }
    98  
    99  // bpfFilter keeps C.struct_bpf_program separate from BPF.orig which might be a pointer to go memory.
   100  // This is a workaround for https://github.com/golang/go/issues/32970 which will be fixed in go1.14.
   101  // (type conversion is in pcap_unix.go pcapOfflineFilter)
   102  type bpfFilter struct {
   103  	bpf pcapBpfProgram // takes a finalizer, not overriden by outsiders
   104  }
   105  
   106  // BPF is a compiled filter program, useful for offline packet matching.
   107  type BPF struct {
   108  	orig string
   109  	bpf  *bpfFilter
   110  	hdr  pcapPkthdr // allocate on the heap to enable optimizations
   111  }
   112  
   113  // BPFInstruction is a byte encoded structure holding a BPF instruction
   114  type BPFInstruction struct {
   115  	Code uint16
   116  	Jt   uint8
   117  	Jf   uint8
   118  	K    uint32
   119  }
   120  
   121  // BlockForever causes it to block forever waiting for packets, when passed
   122  // into SetTimeout or OpenLive, while still returning incoming packets to userland relatively
   123  // quickly.
   124  const BlockForever = -time.Millisecond * 10
   125  
   126  func timeoutMillis(timeout time.Duration) int {
   127  	// Flip sign if necessary.  See package docs on timeout for reasoning behind this.
   128  	if timeout < 0 {
   129  		timeout *= -1
   130  	}
   131  	// Round up
   132  	if timeout != 0 && timeout < time.Millisecond {
   133  		timeout = time.Millisecond
   134  	}
   135  	return int(timeout / time.Millisecond)
   136  }
   137  
   138  // OpenLive opens a device and returns a *Handle.
   139  // It takes as arguments the name of the device ("eth0"), the maximum size to
   140  // read for each packet (snaplen), whether to put the interface in promiscuous
   141  // mode, and a timeout. Warning: this function supports only microsecond timestamps.
   142  // For nanosecond resolution use an InactiveHandle.
   143  //
   144  // See the package documentation for important details regarding 'timeout'.
   145  func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error) {
   146  	var pro int
   147  	if promisc {
   148  		pro = 1
   149  	}
   150  
   151  	p, err := pcapOpenLive(device, int(snaplen), pro, timeoutMillis(timeout))
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	p.timeout = timeout
   156  	p.device = device
   157  
   158  	ifc, err := net.InterfaceByName(device)
   159  	if err != nil {
   160  		// The device wasn't found in the OS, but could be "any"
   161  		// Set index to 0
   162  		p.deviceIndex = 0
   163  	} else {
   164  		p.deviceIndex = ifc.Index
   165  	}
   166  
   167  	p.nanoSecsFactor = 1000
   168  
   169  	// Only set the PCAP handle into non-blocking mode if we have a timeout
   170  	// greater than zero. If the user wants to block forever, we'll let libpcap
   171  	// handle that.
   172  	if p.timeout > 0 {
   173  		if err := p.setNonBlocking(); err != nil {
   174  			p.pcapClose()
   175  			return nil, err
   176  		}
   177  	}
   178  
   179  	return p, nil
   180  }
   181  
   182  // OpenOffline opens a file and returns its contents as a *Handle. Depending on libpcap support and
   183  // on the timestamp resolution used in the file, nanosecond or microsecond resolution is used
   184  // internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used
   185  // to query the actual resolution used.
   186  func OpenOffline(file string) (handle *Handle, err error) {
   187  	handle, err = openOffline(file)
   188  	if err != nil {
   189  		return
   190  	}
   191  	if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano {
   192  		handle.nanoSecsFactor = 1
   193  	} else {
   194  		handle.nanoSecsFactor = 1000
   195  	}
   196  	return
   197  }
   198  
   199  // OpenOfflineFile returns contents of input file as a *Handle. Depending on libpcap support and
   200  // on the timestamp resolution used in the file, nanosecond or microsecond resolution is used
   201  // internally. All returned timestamps are scaled to nanosecond resolution. Resolution() can be used
   202  // to query the actual resolution used.
   203  func OpenOfflineFile(file *os.File) (handle *Handle, err error) {
   204  	handle, err = openOfflineFile(file)
   205  	if err != nil {
   206  		return
   207  	}
   208  	if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano {
   209  		handle.nanoSecsFactor = 1
   210  	} else {
   211  		handle.nanoSecsFactor = 1000
   212  	}
   213  	return
   214  }
   215  
   216  // NextError is the return code from a call to Next.
   217  type NextError int32
   218  
   219  // NextError implements the error interface.
   220  func (n NextError) Error() string {
   221  	switch n {
   222  	case NextErrorOk:
   223  		return "OK"
   224  	case NextErrorTimeoutExpired:
   225  		return "Timeout Expired"
   226  	case NextErrorReadError:
   227  		return "Read Error"
   228  	case NextErrorNoMorePackets:
   229  		return "No More Packets In File"
   230  	case NextErrorNotActivated:
   231  		return "Not Activated"
   232  	}
   233  	return strconv.Itoa(int(n))
   234  }
   235  
   236  // NextError values.
   237  const (
   238  	NextErrorOk             NextError = 1
   239  	NextErrorTimeoutExpired NextError = 0
   240  	NextErrorReadError      NextError = -1
   241  	// NextErrorNoMorePackets is returned when reading from a file (OpenOffline) and
   242  	// EOF is reached.  When this happens, Next() returns io.EOF instead of this.
   243  	NextErrorNoMorePackets NextError = -2
   244  	NextErrorNotActivated  NextError = -3
   245  )
   246  
   247  // ReadPacketData returns the next packet read from the pcap handle, along with an error
   248  // code associated with that packet.  If the packet is read successfully, the
   249  // returned error is nil.
   250  func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
   251  	p.mu.Lock()
   252  	err = p.getNextBufPtrLocked(&ci)
   253  	if err == nil {
   254  		data = make([]byte, ci.CaptureLength)
   255  		copy(data, (*(*[1 << 30]byte)(unsafe.Pointer(p.bufptr)))[:])
   256  	}
   257  	p.mu.Unlock()
   258  	if err == NextErrorTimeoutExpired {
   259  		runtime.Gosched()
   260  	}
   261  	return
   262  }
   263  
   264  type activateError int
   265  
   266  const (
   267  	aeNoError      = activateError(0)
   268  	aeActivated    = activateError(pcapErrorActivated)
   269  	aePromisc      = activateError(pcapWarningPromisc)
   270  	aeNoSuchDevice = activateError(pcapErrorNoSuchDevice)
   271  	aeDenied       = activateError(pcapErrorDenied)
   272  	aeNotUp        = activateError(pcapErrorNotUp)
   273  	aeWarning      = activateError(pcapWarning)
   274  	aeError        = activateError(pcapError)
   275  )
   276  
   277  func (a activateError) Error() string {
   278  	switch a {
   279  	case aeNoError:
   280  		return "No Error"
   281  	case aeActivated:
   282  		return "Already Activated"
   283  	case aePromisc:
   284  		return "Cannot set as promisc"
   285  	case aeNoSuchDevice:
   286  		return "No Such Device"
   287  	case aeDenied:
   288  		return "Permission Denied"
   289  	case aeNotUp:
   290  		return "Interface Not Up"
   291  	case aeWarning:
   292  		return fmt.Sprintf("Warning: %v", activateErrMsg.Error())
   293  	case aeError:
   294  		return fmt.Sprintf("Error: %v", activateErrMsg.Error())
   295  	default:
   296  		return fmt.Sprintf("unknown activated error: %d", a)
   297  	}
   298  }
   299  
   300  // getNextBufPtrLocked is shared code for ReadPacketData and
   301  // ZeroCopyReadPacketData.
   302  func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error {
   303  	if !p.isOpen() {
   304  		return io.EOF
   305  	}
   306  
   307  	// set after we have call waitForPacket for the first time
   308  	var waited bool
   309  
   310  	for atomic.LoadUint64(&p.stop) == 0 {
   311  		// try to read a packet if one is immediately available
   312  		result := p.pcapNextPacketEx()
   313  
   314  		switch result {
   315  		case NextErrorOk:
   316  			sec := p.pkthdr.getSec()
   317  			// convert micros to nanos
   318  			nanos := int64(p.pkthdr.getUsec()) * p.nanoSecsFactor
   319  
   320  			ci.Timestamp = time.Unix(sec, nanos)
   321  			ci.CaptureLength = p.pkthdr.getCaplen()
   322  			ci.Length = p.pkthdr.getLen()
   323  			ci.InterfaceIndex = p.deviceIndex
   324  
   325  			return nil
   326  		case NextErrorNoMorePackets:
   327  			// no more packets, return EOF rather than libpcap-specific error
   328  			return io.EOF
   329  		case NextErrorTimeoutExpired:
   330  			// we've already waited for a packet and we're supposed to time out
   331  			//
   332  			// we should never actually hit this if we were passed BlockForever
   333  			// since we should block on C.pcap_next_ex until there's a packet
   334  			// to read.
   335  			if waited && p.timeout > 0 {
   336  				return result
   337  			}
   338  
   339  			// wait for packet before trying again
   340  			p.waitForPacket()
   341  			waited = true
   342  		default:
   343  			return result
   344  		}
   345  	}
   346  
   347  	// stop must be set
   348  	return io.EOF
   349  }
   350  
   351  // ZeroCopyReadPacketData reads the next packet off the wire, and returns its data.
   352  // The slice returned by ZeroCopyReadPacketData points to bytes owned by the
   353  // the Handle.  Each call to ZeroCopyReadPacketData invalidates any data previously
   354  // returned by ZeroCopyReadPacketData.  Care must be taken not to keep pointers
   355  // to old bytes when using ZeroCopyReadPacketData... if you need to keep data past
   356  // the next time you call ZeroCopyReadPacketData, use ReadPacketData, which copies
   357  // the bytes into a new buffer for you.
   358  //
   359  //	data1, _, _ := handle.ZeroCopyReadPacketData()
   360  //	// do everything you want with data1 here, copying bytes out of it if you'd like to keep them around.
   361  //	data2, _, _ := handle.ZeroCopyReadPacketData()  // invalidates bytes in data1
   362  func (p *Handle) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
   363  	p.mu.Lock()
   364  	err = p.getNextBufPtrLocked(&ci)
   365  	if err == nil {
   366  		slice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
   367  		slice.Data = uintptr(unsafe.Pointer(p.bufptr))
   368  		slice.Len = ci.CaptureLength
   369  		slice.Cap = ci.CaptureLength
   370  	}
   371  	p.mu.Unlock()
   372  	if err == NextErrorTimeoutExpired {
   373  		runtime.Gosched()
   374  	}
   375  	return
   376  }
   377  
   378  // Close closes the underlying pcap handle.
   379  func (p *Handle) Close() {
   380  	p.closeMu.Lock()
   381  	defer p.closeMu.Unlock()
   382  
   383  	if !p.isOpen() {
   384  		return
   385  	}
   386  
   387  	atomic.StoreUint64(&p.stop, 1)
   388  
   389  	// wait for packet reader to stop
   390  	p.mu.Lock()
   391  	defer p.mu.Unlock()
   392  
   393  	p.pcapClose()
   394  }
   395  
   396  // Error returns the current error associated with a pcap handle (pcap_geterr).
   397  func (p *Handle) Error() error {
   398  	return p.pcapGeterr()
   399  }
   400  
   401  // Stats returns statistics on the underlying pcap handle.
   402  func (p *Handle) Stats() (stat *Stats, err error) {
   403  	return p.pcapStats()
   404  }
   405  
   406  // ListDataLinks obtains a list of all possible data link types supported for an interface.
   407  func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) {
   408  	return p.pcapListDatalinks()
   409  }
   410  
   411  // compileBPFFilter always returns an allocated C.struct_bpf_program
   412  // It is the callers responsibility to free the memory again, e.g.
   413  //
   414  //	C.pcap_freecode(&bpf)
   415  func (p *Handle) compileBPFFilter(expr string) (pcapBpfProgram, error) {
   416  	var maskp = uint32(pcapNetmaskUnknown)
   417  
   418  	// Only do the lookup on network interfaces.
   419  	// No device indicates we're handling a pcap file.
   420  	if len(p.device) > 0 {
   421  		var err error
   422  		_, maskp, err = pcapLookupnet(p.device)
   423  		if err != nil {
   424  			// We can't lookup the network, but that could be because the interface
   425  			// doesn't have an IPv4.
   426  			maskp = uint32(pcapNetmaskUnknown)
   427  		}
   428  	}
   429  
   430  	return p.pcapCompile(expr, maskp)
   431  }
   432  
   433  // CompileBPFFilter compiles and returns a BPF filter with given a link type and capture length.
   434  func CompileBPFFilter(linkType layers.LinkType, captureLength int, expr string) ([]BPFInstruction, error) {
   435  	h, err := pcapOpenDead(linkType, captureLength)
   436  	if err != nil {
   437  		return nil, err
   438  	}
   439  	defer h.Close()
   440  	return h.CompileBPFFilter(expr)
   441  }
   442  
   443  // CompileBPFFilter compiles and returns a BPF filter for the pcap handle.
   444  func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error) {
   445  	bpf, err := p.compileBPFFilter(expr)
   446  	defer bpf.free()
   447  	if err != nil {
   448  		return nil, err
   449  	}
   450  
   451  	return bpf.toBPFInstruction(), nil
   452  }
   453  
   454  // SetBPFFilter compiles and sets a BPF filter for the pcap handle.
   455  func (p *Handle) SetBPFFilter(expr string) (err error) {
   456  	bpf, err := p.compileBPFFilter(expr)
   457  	defer bpf.free()
   458  	if err != nil {
   459  		return err
   460  	}
   461  
   462  	return p.pcapSetfilter(bpf)
   463  }
   464  
   465  // SetBPFInstructionFilter may be used to apply a filter in BPF asm byte code format.
   466  //
   467  // Simplest way to generate BPF asm byte code is with tcpdump:
   468  //
   469  //	tcpdump -dd 'udp'
   470  //
   471  // The output may be used directly to add a filter, e.g.:
   472  //
   473  //	    bpfInstructions := []pcap.BpfInstruction{
   474  //				{0x28, 0, 0, 0x0000000c},
   475  //				{0x15, 0, 9, 0x00000800},
   476  //				{0x30, 0, 0, 0x00000017},
   477  //				{0x15, 0, 7, 0x00000006},
   478  //				{0x28, 0, 0, 0x00000014},
   479  //				{0x45, 5, 0, 0x00001fff},
   480  //				{0xb1, 0, 0, 0x0000000e},
   481  //				{0x50, 0, 0, 0x0000001b},
   482  //				{0x54, 0, 0, 0x00000012},
   483  //				{0x15, 0, 1, 0x00000012},
   484  //				{0x6, 0, 0, 0x0000ffff},
   485  //				{0x6, 0, 0, 0x00000000},
   486  //			}
   487  //
   488  // An other posibility is to write the bpf code in bpf asm.
   489  // Documentation: https://www.kernel.org/doc/Documentation/networking/filter.txt
   490  //
   491  // To compile the code use bpf_asm from
   492  // https://github.com/torvalds/linux/tree/master/tools/net
   493  //
   494  // The following command may be used to convert bpf_asm output to c/go struct, usable for SetBPFFilterByte:
   495  // bpf_asm -c tcp.bpf
   496  func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error) {
   497  	bpf, err := bpfInstructionFilter(bpfInstructions)
   498  	if err != nil {
   499  		return err
   500  	}
   501  	defer bpf.free()
   502  
   503  	return p.pcapSetfilter(bpf)
   504  }
   505  
   506  func bpfInstructionFilter(bpfInstructions []BPFInstruction) (bpf pcapBpfProgram, err error) {
   507  	if len(bpfInstructions) < 1 {
   508  		return bpf, errors.New("bpfInstructions must not be empty")
   509  	}
   510  
   511  	if len(bpfInstructions) > MaxBpfInstructions {
   512  		return bpf, fmt.Errorf("bpfInstructions must not be larger than %d", MaxBpfInstructions)
   513  	}
   514  
   515  	return pcapBpfProgramFromInstructions(bpfInstructions), nil
   516  }
   517  
   518  // NewBPF compiles the given string into a new filter program.
   519  //
   520  // BPF filters need to be created from activated handles, because they need to
   521  // know the underlying link type to correctly compile their offsets.
   522  func (p *Handle) NewBPF(expr string) (*BPF, error) {
   523  	bpf := &BPF{orig: expr, bpf: new(bpfFilter)}
   524  
   525  	var err error
   526  	bpf.bpf.bpf, err = p.pcapCompile(expr, pcapNetmaskUnknown)
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  
   531  	runtime.SetFinalizer(bpf, destroyBPF)
   532  	return bpf, nil
   533  }
   534  
   535  // NewBPF allows to create a BPF without requiring an existing handle.
   536  // This allows to match packets obtained from a-non GoPacket capture source
   537  // to be matched.
   538  //
   539  //	buf := make([]byte, MaxFrameSize)
   540  //	bpfi, _ := pcap.NewBPF(layers.LinkTypeEthernet, MaxFrameSize, "icmp")
   541  //	n, _ := someIO.Read(buf)
   542  //	ci := gopacket.CaptureInfo{CaptureLength: n, Length: n}
   543  //	if bpfi.Matches(ci, buf) {
   544  //		doSomething()
   545  //	}
   546  func NewBPF(linkType layers.LinkType, captureLength int, expr string) (*BPF, error) {
   547  	h, err := pcapOpenDead(linkType, captureLength)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  	defer h.Close()
   552  	return h.NewBPF(expr)
   553  }
   554  
   555  // NewBPFInstructionFilter sets the given BPFInstructions as new filter program.
   556  //
   557  // # More details see func SetBPFInstructionFilter
   558  //
   559  // BPF filters need to be created from activated handles, because they need to
   560  // know the underlying link type to correctly compile their offsets.
   561  func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error) {
   562  	var err error
   563  	bpf := &BPF{orig: "BPF Instruction Filter", bpf: new(bpfFilter)}
   564  
   565  	bpf.bpf.bpf, err = bpfInstructionFilter(bpfInstructions)
   566  	if err != nil {
   567  		return nil, err
   568  	}
   569  
   570  	runtime.SetFinalizer(bpf, destroyBPF)
   571  	return bpf, nil
   572  }
   573  func destroyBPF(bpf *BPF) {
   574  	bpf.bpf.bpf.free()
   575  }
   576  
   577  // String returns the original string this BPF filter was compiled from.
   578  func (b *BPF) String() string {
   579  	return b.orig
   580  }
   581  
   582  // Matches returns true if the given packet data matches this filter.
   583  func (b *BPF) Matches(ci gopacket.CaptureInfo, data []byte) bool {
   584  	return b.pcapOfflineFilter(ci, data)
   585  }
   586  
   587  // Version returns pcap_lib_version.
   588  func Version() string {
   589  	return pcapLibVersion()
   590  }
   591  
   592  // LinkType returns pcap_datalink, as a layers.LinkType.
   593  func (p *Handle) LinkType() layers.LinkType {
   594  	return p.pcapDatalink()
   595  }
   596  
   597  // SetLinkType calls pcap_set_datalink on the pcap handle.
   598  func (p *Handle) SetLinkType(dlt layers.LinkType) error {
   599  	return p.pcapSetDatalink(dlt)
   600  }
   601  
   602  // DatalinkValToName returns pcap_datalink_val_to_name as string
   603  func DatalinkValToName(dlt int) string {
   604  	return pcapDatalinkValToName(dlt)
   605  }
   606  
   607  // DatalinkValToDescription returns pcap_datalink_val_to_description as string
   608  func DatalinkValToDescription(dlt int) string {
   609  	return pcapDatalinkValToDescription(dlt)
   610  }
   611  
   612  // DatalinkNameToVal returns pcap_datalink_name_to_val as int
   613  func DatalinkNameToVal(name string) int {
   614  	return pcapDatalinkNameToVal(name)
   615  }
   616  
   617  // FindAllDevs attempts to enumerate all interfaces on the current machine.
   618  func FindAllDevs() (ifs []Interface, err error) {
   619  	alldevsp, err := pcapFindAllDevs()
   620  	if err != nil {
   621  		return nil, err
   622  	}
   623  	defer alldevsp.free()
   624  
   625  	for alldevsp.next() {
   626  		var iface Interface
   627  		iface.Name = alldevsp.name()
   628  		iface.Description = alldevsp.description()
   629  		iface.Addresses = findalladdresses(alldevsp.addresses())
   630  		iface.Flags = alldevsp.flags()
   631  		ifs = append(ifs, iface)
   632  	}
   633  	return
   634  }
   635  
   636  func findalladdresses(addresses pcapAddresses) (retval []InterfaceAddress) {
   637  	// TODO - make it support more than IPv4 and IPv6?
   638  	retval = make([]InterfaceAddress, 0, 1)
   639  	for addresses.next() {
   640  		// Strangely, it appears that in some cases, we get a pcap address back from
   641  		// pcap_findalldevs with a nil .addr.  It appears that we can skip over
   642  		// these.
   643  		if addresses.addr() == nil {
   644  			continue
   645  		}
   646  		var a InterfaceAddress
   647  		var err error
   648  		if a.IP, err = sockaddrToIP(addresses.addr()); err != nil {
   649  			continue
   650  		}
   651  		// To be safe, we'll also check for netmask.
   652  		if addresses.netmask() == nil {
   653  			continue
   654  		}
   655  		if a.Netmask, err = sockaddrToIP(addresses.netmask()); err != nil {
   656  			// If we got an IP address but we can't get a netmask, just return the IP
   657  			// address.
   658  			a.Netmask = nil
   659  		}
   660  		if a.Broadaddr, err = sockaddrToIP(addresses.broadaddr()); err != nil {
   661  			a.Broadaddr = nil
   662  		}
   663  		if a.P2P, err = sockaddrToIP(addresses.dstaddr()); err != nil {
   664  			a.P2P = nil
   665  		}
   666  		retval = append(retval, a)
   667  	}
   668  	return
   669  }
   670  
   671  func sockaddrToIP(rsa *syscall.RawSockaddr) (IP []byte, err error) {
   672  	if rsa == nil {
   673  		err = errors.New("Value not set")
   674  		return
   675  	}
   676  	switch rsa.Family {
   677  	case syscall.AF_INET:
   678  		pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
   679  		IP = make([]byte, 4)
   680  		for i := 0; i < len(IP); i++ {
   681  			IP[i] = pp.Addr[i]
   682  		}
   683  		return
   684  	case syscall.AF_INET6:
   685  		pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
   686  		IP = make([]byte, 16)
   687  		for i := 0; i < len(IP); i++ {
   688  			IP[i] = pp.Addr[i]
   689  		}
   690  		return
   691  	}
   692  	err = errors.New("Unsupported address type")
   693  	return
   694  }
   695  
   696  // WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle.
   697  func (p *Handle) WritePacketData(data []byte) (err error) {
   698  	return p.pcapSendpacket(data)
   699  }
   700  
   701  // Direction is used by Handle.SetDirection.
   702  type Direction uint8
   703  
   704  // Direction values for Handle.SetDirection.
   705  const (
   706  	DirectionIn    = Direction(pcapDIN)
   707  	DirectionOut   = Direction(pcapDOUT)
   708  	DirectionInOut = Direction(pcapDINOUT)
   709  )
   710  
   711  // SetDirection sets the direction for which packets will be captured.
   712  func (p *Handle) SetDirection(direction Direction) error {
   713  	if direction != DirectionIn && direction != DirectionOut && direction != DirectionInOut {
   714  		return fmt.Errorf("Invalid direction: %v", direction)
   715  	}
   716  	return p.pcapSetdirection(direction)
   717  }
   718  
   719  // SnapLen returns the snapshot length
   720  func (p *Handle) SnapLen() int {
   721  	return p.pcapSnapshot()
   722  }
   723  
   724  // Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution.
   725  func (p *Handle) Resolution() gopacket.TimestampResolution {
   726  	if p.nanoSecsFactor == 1 {
   727  		return gopacket.TimestampResolutionMicrosecond
   728  	}
   729  	return gopacket.TimestampResolutionNanosecond
   730  }
   731  
   732  // TimestampSource tells PCAP which type of timestamp to use for packets.
   733  type TimestampSource int
   734  
   735  // String returns the timestamp type as a human-readable string.
   736  func (t TimestampSource) String() string {
   737  	return t.pcapTstampTypeValToName()
   738  }
   739  
   740  // TimestampSourceFromString translates a string into a timestamp type, case
   741  // insensitive.
   742  func TimestampSourceFromString(s string) (TimestampSource, error) {
   743  	return pcapTstampTypeNameToVal(s)
   744  }
   745  
   746  // InactiveHandle allows you to call pre-pcap_activate functions on your pcap
   747  // handle to set it up just the way you'd like.
   748  type InactiveHandle struct {
   749  	// cptr is the handle for the actual pcap C object.
   750  	cptr        pcapTPtr
   751  	device      string
   752  	deviceIndex int
   753  	timeout     time.Duration
   754  }
   755  
   756  // holds the err messoge in case activation returned a Warning
   757  var activateErrMsg error
   758  
   759  // Error returns the current error associated with a pcap handle (pcap_geterr).
   760  func (p *InactiveHandle) Error() error {
   761  	return p.pcapGeterr()
   762  }
   763  
   764  // Activate activates the handle.  The current InactiveHandle becomes invalid
   765  // and all future function calls on it will fail.
   766  func (p *InactiveHandle) Activate() (*Handle, error) {
   767  	// ignore error with set_tstamp_precision, since the actual precision is queried later anyway
   768  	pcapSetTstampPrecision(p.cptr, pcapTstampPrecisionNano)
   769  	handle, err := p.pcapActivate()
   770  	if err != aeNoError {
   771  		if err == aeWarning || err == aeError {
   772  			activateErrMsg = p.Error()
   773  		}
   774  		return nil, err
   775  	}
   776  	handle.timeout = p.timeout
   777  	if p.timeout > 0 {
   778  		if err := handle.setNonBlocking(); err != nil {
   779  			handle.pcapClose()
   780  			return nil, err
   781  		}
   782  	}
   783  	handle.device = p.device
   784  	handle.deviceIndex = p.deviceIndex
   785  	if pcapGetTstampPrecision(handle.cptr) == pcapTstampPrecisionNano {
   786  		handle.nanoSecsFactor = 1
   787  	} else {
   788  		handle.nanoSecsFactor = 1000
   789  	}
   790  	return handle, nil
   791  }
   792  
   793  // CleanUp cleans up any stuff left over from a successful or failed building
   794  // of a handle.
   795  func (p *InactiveHandle) CleanUp() {
   796  	p.pcapClose()
   797  }
   798  
   799  // NewInactiveHandle creates a new InactiveHandle, which wraps an un-activated PCAP handle.
   800  // Callers of NewInactiveHandle should immediately defer 'CleanUp', as in:
   801  //
   802  //	inactive := NewInactiveHandle("eth0")
   803  //	defer inactive.CleanUp()
   804  func NewInactiveHandle(device string) (*InactiveHandle, error) {
   805  	// Try to get the interface index, but iy could be something like "any"
   806  	// in which case use 0, which doesn't exist in nature
   807  	deviceIndex := 0
   808  	ifc, err := net.InterfaceByName(device)
   809  	if err == nil {
   810  		deviceIndex = ifc.Index
   811  	}
   812  
   813  	// This copies a bunch of the pcap_open_live implementation from pcap.c:
   814  	handle, err := pcapCreate(device)
   815  	if err != nil {
   816  		return nil, err
   817  	}
   818  	handle.device = device
   819  	handle.deviceIndex = deviceIndex
   820  	return handle, nil
   821  }
   822  
   823  // SetSnapLen sets the snap length (max bytes per packet to capture).
   824  func (p *InactiveHandle) SetSnapLen(snaplen int) error {
   825  	return p.pcapSetSnaplen(snaplen)
   826  }
   827  
   828  // SetPromisc sets the handle to either be promiscuous (capture packets
   829  // unrelated to this host) or not.
   830  func (p *InactiveHandle) SetPromisc(promisc bool) error {
   831  	return p.pcapSetPromisc(promisc)
   832  }
   833  
   834  // SetTimeout sets the read timeout for the handle.
   835  //
   836  // See the package documentation for important details regarding 'timeout'.
   837  func (p *InactiveHandle) SetTimeout(timeout time.Duration) error {
   838  	err := p.pcapSetTimeout(timeout)
   839  	if err != nil {
   840  		return err
   841  	}
   842  	p.timeout = timeout
   843  	return nil
   844  }
   845  
   846  // SupportedTimestamps returns a list of supported timstamp types for this
   847  // handle.
   848  func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource) {
   849  	return p.pcapListTstampTypes()
   850  }
   851  
   852  // SetTimestampSource sets the type of timestamp generator PCAP uses when
   853  // attaching timestamps to packets.
   854  func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error {
   855  	return p.pcapSetTstampType(t)
   856  }
   857  
   858  // CannotSetRFMon is returned by SetRFMon if the handle does not allow
   859  // setting RFMon because pcap_can_set_rfmon returns 0.
   860  var CannotSetRFMon = errors.New("Cannot set rfmon for this handle")
   861  
   862  // SetRFMon turns on radio monitoring mode, similar to promiscuous mode but for
   863  // wireless networks.  If this mode is enabled, the interface will not need to
   864  // associate with an access point before it can receive traffic.
   865  func (p *InactiveHandle) SetRFMon(monitor bool) error {
   866  	return p.pcapSetRfmon(monitor)
   867  }
   868  
   869  // SetBufferSize sets the buffer size (in bytes) of the handle.
   870  func (p *InactiveHandle) SetBufferSize(bufferSize int) error {
   871  	return p.pcapSetBufferSize(bufferSize)
   872  }
   873  
   874  // SetImmediateMode sets (or unsets) the immediate mode of the
   875  // handle. In immediate mode, packets are delivered to the application
   876  // as soon as they arrive.  In other words, this overrides SetTimeout.
   877  func (p *InactiveHandle) SetImmediateMode(mode bool) error {
   878  	return p.pcapSetImmediateMode(mode)
   879  }