diff options
Diffstat (limited to 'vendor/github.com/google/gopacket/pcap')
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/doc.go | 106 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/gopacket_benchmark/benchmark.go | 247 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap.go | 1005 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap_test.go | 308 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap_tester.go | 109 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap_unix.go | 71 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcap_windows.go | 23 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/pcapgo_test.go | 56 | ||||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/test_dns.pcap | bin | 1001 -> 0 bytes | |||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/test_ethernet.pcap | bin | 7672 -> 0 bytes | |||
-rw-r--r-- | vendor/github.com/google/gopacket/pcap/test_loopback.pcap | bin | 58587 -> 0 bytes |
11 files changed, 0 insertions, 1925 deletions
diff --git a/vendor/github.com/google/gopacket/pcap/doc.go b/vendor/github.com/google/gopacket/pcap/doc.go deleted file mode 100644 index 5bf8d86..0000000 --- a/vendor/github.com/google/gopacket/pcap/doc.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2012 Google, Inc. 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 allows users of gopacket to read packets off the wire or from -pcap files. - -This package is meant to be used with its parent, -http://github.com/google/gopacket, although it can also be used independently -if you just want to get packet data from the wire. - -Reading PCAP Files - -The following code can be used to read in data from a pcap file. - - if handle, err := pcap.OpenOffline("/path/to/my/file"); err != nil { - panic(err) - } else { - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - for packet := range packetSource.Packets() { - handlePacket(packet) // Do something with a packet here. - } - } - -Reading Live Packets - -The following code can be used to read in data from a live device, in this case -"eth0". - - if handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever); err != nil { - panic(err) - } else if err := handle.SetBPFFilter("tcp and port 80"); err != nil { // optional - panic(err) - } else { - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - for packet := range packetSource.Packets() { - handlePacket(packet) // Do something with a packet here. - } - } - -Inactive Handles - -Newer PCAP functionality requires the concept of an 'inactive' PCAP handle. -Instead of constantly adding new arguments to pcap_open_live, users now call -pcap_create to create a handle, set it up with a bunch of optional function -calls, then call pcap_activate to activate it. This library mirrors that -mechanism, for those that want to expose/use these new features: - - inactive, err := pcap.NewInactiveHandle(deviceName) - if err != nil { - log.Fatal(err) - } - defer inactive.CleanUp() - - // Call various functions on inactive to set it up the way you'd like: - if err = inactive.SetTimeout(time.Minute); err != nil { - log.Fatal(err) - } else if err = inactive.SetTimestampSource("foo"); err != nil { - log.Fatal(err) - } - - // Finally, create the actual handle by calling Activate: - handle, err := inactive.Activate() // after this, inactive is no longer valid - if err != nil { - log.Fatal(err) - } - defer handle.Close() - - // Now use your handle as you see fit. - -PCAP Timeouts - -pcap.OpenLive and pcap.SetTimeout both take timeouts. -If you don't care about timeouts, just pass in BlockForever, -which should do what you expect with minimal fuss. - -A timeout of 0 is not recommended. Some platforms, like Macs -(http://www.manpages.info/macosx/pcap.3.html) say: - The read timeout is used to arrange that the read not necessarily return - immediately when a packet is seen, but that it wait for some amount of time - to allow more packets to arrive and to read multiple packets from the OS - kernel in one operation. -This means that if you only capture one packet, the kernel might decide to wait -'timeout' for more packets to batch with it before returning. A timeout of -0, then, means 'wait forever for more packets', which is... not good. - -To get around this, we've introduced the following behavior: if a negative -timeout is passed in, we set the positive timeout in the handle, then loop -internally in ReadPacketData/ZeroCopyReadPacketData when we see timeout -errors. - -PCAP File Writing - -This package does not implement PCAP file writing. However, gopacket/pcapgo -does! Look there if you'd like to write PCAP files. - -Note For Windows 10 Users - -If you're trying to use 64-bit winpcap on Windows 10, you might have to do -the crazy hijinks detailed at -http://stackoverflow.com/questions/38047858/compile-gopacket-on-windows-64bit -*/ -package pcap diff --git a/vendor/github.com/google/gopacket/pcap/gopacket_benchmark/benchmark.go b/vendor/github.com/google/gopacket/pcap/gopacket_benchmark/benchmark.go deleted file mode 100644 index cbcae17..0000000 --- a/vendor/github.com/google/gopacket/pcap/gopacket_benchmark/benchmark.go +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2012 Google, Inc. 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. - -// This benchmark reads in file <tempdir>/gopacket_benchmark.pcap and measures -// the time it takes to decode all packets from that file. If the file doesn't -// exist, it's pulled down from a publicly available location. However, you can -// feel free to substitute your own file at that location, in which case the -// benchmark will run on your own data. -// -// It's also useful for figuring out which packets may be causing errors. Pass -// in the --printErrors flag, and it'll print out error layers for each packet -// that has them. This includes any packets that it's just unable to decode, -// which is a great way to find new protocols to decode, and get test packets to -// write tests for them. -package main - -import ( - "compress/gzip" - "encoding/hex" - "flag" - "fmt" - "github.com/google/gopacket" - "github.com/google/gopacket/layers" - "github.com/google/gopacket/pcap" - "github.com/google/gopacket/tcpassembly" - "io" - "io/ioutil" - "net/http" - "os" - "runtime" - "runtime/pprof" - "time" -) - -var decodeLazy *bool = flag.Bool("lazy", false, "If true, use lazy decoding") -var decodeNoCopy *bool = flag.Bool("nocopy", true, "If true, avoid an extra copy when decoding packets") -var printErrors *bool = flag.Bool("printErrors", false, "If true, check for and print error layers.") -var printLayers *bool = flag.Bool("printLayers", false, "If true, print out the layers of each packet") -var repeat *int = flag.Int("repeat", 5, "Read over the file N times") -var cpuProfile *string = flag.String("cpuprofile", "", "If set, write CPU profile to filename") -var url *string = flag.String("url", "http://www.ll.mit.edu/mission/communications/cyber/CSTcorpora/ideval/data/1999/training/week1/tuesday/inside.tcpdump.gz", "URL to gzip'd pcap file") - -type BufferPacketSource struct { - index int - data [][]byte - ci []gopacket.CaptureInfo -} - -func NewBufferPacketSource(p gopacket.PacketDataSource) *BufferPacketSource { - start := time.Now() - b := &BufferPacketSource{} - for { - data, ci, err := p.ReadPacketData() - if err == io.EOF { - break - } - b.data = append(b.data, data) - b.ci = append(b.ci, ci) - } - duration := time.Since(start) - fmt.Printf("Reading packet data into memory: %d packets in %v, %v per packet\n", len(b.data), duration, duration/time.Duration(len(b.data))) - return b -} - -func (b *BufferPacketSource) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) { - if b.index >= len(b.data) { - err = io.EOF - return - } - data = b.data[b.index] - ci = b.ci[b.index] - b.index++ - return -} - -func (b *BufferPacketSource) Reset() { - runtime.GC() - b.index = 0 -} - -func main() { - flag.Parse() - filename := os.TempDir() + string(os.PathSeparator) + "gopacket_benchmark.pcap" - if _, err := os.Stat(filename); err != nil { - // This URL points to a publicly available packet data set from a DARPA - // intrusion detection evaluation. See - // http://www.ll.mit.edu/mission/communications/cyber/CSTcorpora/ideval/data/1999/training/week1/index.html - // for more details. - fmt.Println("Local pcap file", filename, "doesn't exist, reading from", *url) - if resp, err := http.Get(*url); err != nil { - panic(err) - } else if out, err := os.Create(filename); err != nil { - panic(err) - } else if gz, err := gzip.NewReader(resp.Body); err != nil { - panic(err) - } else if n, err := io.Copy(out, gz); err != nil { - panic(err) - } else if err := gz.Close(); err != nil { - panic(err) - } else if err := out.Close(); err != nil { - panic(err) - } else { - fmt.Println("Successfully read", n, "bytes from url, unzipped to local storage") - } - } - fmt.Println("Reading file once through to hopefully cache most of it") - if f, err := os.Open(filename); err != nil { - panic(err) - } else if n, err := io.Copy(ioutil.Discard, f); err != nil { - panic(err) - } else if err := f.Close(); err != nil { - panic(err) - } else { - fmt.Println("Read in file", filename, ", total of", n, "bytes") - } - if *cpuProfile != "" { - if cpu, err := os.Create(*cpuProfile); err != nil { - panic(err) - } else if err := pprof.StartCPUProfile(cpu); err != nil { - panic(err) - } else { - defer func() { - pprof.StopCPUProfile() - cpu.Close() - }() - } - } - var packetDataSource *BufferPacketSource - var packetSource *gopacket.PacketSource - fmt.Printf("Opening file %q for read\n", filename) - if h, err := pcap.OpenOffline(filename); err != nil { - panic(err) - } else { - fmt.Println("Reading all packets into memory with BufferPacketSource.") - start := time.Now() - packetDataSource = NewBufferPacketSource(h) - duration := time.Since(start) - fmt.Printf("Time to read packet data into memory from file: %v\n", duration) - packetSource = gopacket.NewPacketSource(packetDataSource, h.LinkType()) - packetSource.DecodeOptions.Lazy = *decodeLazy - packetSource.DecodeOptions.NoCopy = *decodeNoCopy - } - fmt.Println() - for i := 0; i < *repeat; i++ { - packetDataSource.Reset() - fmt.Printf("Benchmarking decode %d/%d\n", i+1, *repeat) - benchmarkPacketDecode(packetSource) - } - fmt.Println() - for i := 0; i < *repeat; i++ { - packetDataSource.Reset() - fmt.Printf("Benchmarking decoding layer parser %d/%d\n", i+1, *repeat) - benchmarkLayerDecode(packetDataSource, false) - } - fmt.Println() - for i := 0; i < *repeat; i++ { - packetDataSource.Reset() - fmt.Printf("Benchmarking decoding layer parser with assembly %d/%d\n", i+1, *repeat) - benchmarkLayerDecode(packetDataSource, true) - } -} - -func benchmarkPacketDecode(packetSource *gopacket.PacketSource) { - count, errors := 0, 0 - start := time.Now() - for packet, err := packetSource.NextPacket(); err != io.EOF; packet, err = packetSource.NextPacket() { - if err != nil { - fmt.Println("Error reading in packet:", err) - continue - } - count++ - var hasError bool - if *printErrors && packet.ErrorLayer() != nil { - fmt.Println("\n\n\nError decoding packet:", packet.ErrorLayer().Error()) - fmt.Println(hex.Dump(packet.Data())) - fmt.Printf("%#v\n", packet.Data()) - errors++ - hasError = true - } - if *printLayers || hasError { - fmt.Printf("\n=== PACKET %d ===\n", count) - for _, l := range packet.Layers() { - fmt.Printf("--- LAYER %v ---\n%#v\n\n", l.LayerType(), l) - } - fmt.Println() - } - } - duration := time.Since(start) - fmt.Printf("\tRead in %v packets in %v, %v per packet\n", count, duration, duration/time.Duration(count)) - if *printErrors { - fmt.Printf("%v errors, successfully decoded %.02f%%\n", errors, float64(count-errors)*100.0/float64(count)) - } -} - -type streamFactory struct { -} - -func (s *streamFactory) New(netFlow, tcpFlow gopacket.Flow) tcpassembly.Stream { - return s -} -func (s *streamFactory) Reassembled([]tcpassembly.Reassembly) { -} -func (s *streamFactory) ReassemblyComplete() { -} - -func benchmarkLayerDecode(source *BufferPacketSource, assemble bool) { - var tcp layers.TCP - var ip layers.IPv4 - var eth layers.Ethernet - var udp layers.UDP - var icmp layers.ICMPv4 - var payload gopacket.Payload - parser := gopacket.NewDecodingLayerParser( - layers.LayerTypeEthernet, - ð, &ip, &icmp, &tcp, &udp, &payload) - pool := tcpassembly.NewStreamPool(&streamFactory{}) - assembler := tcpassembly.NewAssembler(pool) - var decoded []gopacket.LayerType - start := time.Now() - packets, decodedlayers, assembled := 0, 0, 0 - for { - packets++ - data, ci, err := source.ReadPacketData() - if err == io.EOF { - break - } else if err != nil { - fmt.Println("Error reading packet: ", err) - continue - } - err = parser.DecodeLayers(data, &decoded) - for _, typ := range decoded { - decodedlayers++ - if typ == layers.LayerTypeTCP && assemble { - assembled++ - assembler.AssembleWithTimestamp(ip.NetworkFlow(), &tcp, ci.Timestamp) - } - } - } - if assemble { - assembler.FlushAll() - } - duration := time.Since(start) - fmt.Printf("\tRead in %d packets in %v, decoded %v layers, assembled %v packets: %v per packet\n", packets, duration, decodedlayers, assembled, duration/time.Duration(packets)) -} diff --git a/vendor/github.com/google/gopacket/pcap/pcap.go b/vendor/github.com/google/gopacket/pcap/pcap.go deleted file mode 100644 index 1ecdf03..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcap.go +++ /dev/null @@ -1,1005 +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 - -/* -#cgo solaris LDFLAGS: -L /opt/local/lib -lpcap -#cgo linux LDFLAGS: -lpcap -#cgo dragonfly LDFLAGS: -lpcap -#cgo freebsd LDFLAGS: -lpcap -#cgo openbsd LDFLAGS: -lpcap -#cgo netbsd LDFLAGS: -lpcap -#cgo darwin LDFLAGS: -lpcap -#cgo windows CFLAGS: -I C:/WpdPack/Include -#cgo windows,386 LDFLAGS: -L C:/WpdPack/Lib -lwpcap -#cgo windows,amd64 LDFLAGS: -L C:/WpdPack/Lib/x64 -lwpcap -#include <stdlib.h> -#include <pcap.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 - -int pcap_set_immediate_mode(pcap_t *p, int mode) { - return PCAP_ERROR; -} - -#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 - -// WinPcap doesn't export a pcap_statustostr, so use the less-specific -// pcap_strerror. Note that linking against something like cygwin libpcap -// may result is less-specific error messages. -#ifdef WIN32 -#define pcap_statustostr pcap_strerror - -// WinPcap also doesn't export pcap_can_set_rfmon and pcap_set_rfmon, -// as those are handled by separate libraries (airpcap). -// https://www.winpcap.org/docs/docs_412/html/group__wpcapfunc.html -// Stub out those functions here, returning values that indicate rfmon -// setting is unavailable/unsuccessful. -int pcap_can_set_rfmon(pcap_t *p) { - return 0; -} - -int pcap_set_rfmon(pcap_t *p, int rfmon) { - return PCAP_ERROR; -} -#endif - -// Windows, Macs, and Linux all use different time types. Joy. -#ifdef WIN32 -#define gopacket_time_secs_t long -#define gopacket_time_usecs_t long -#elif __APPLE__ -#define gopacket_time_secs_t __darwin_time_t -#define gopacket_time_usecs_t __darwin_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 -*/ -import "C" - -import ( - "errors" - "fmt" - "io" - "net" - "reflect" - "runtime" - "strconv" - "sync" - "sync/atomic" - "syscall" - "time" - "unsafe" - - "github.com/google/gopacket" - "github.com/google/gopacket/layers" -) - -const errorBufferSize = 256 - -// 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 { - // cptr is the handle for the actual pcap C object. - cptr *C.pcap_t - timeout time.Duration - device string - deviceIndex int - mu sync.Mutex - closeMu sync.Mutex - // stop is set to a non-zero value by Handle.Close to signal to - // getNextBufPtrLocked to stop trying to read packets - stop uint64 - - // 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 *C.struct_pcap_pkthdr - bufptr *C.u_char -} - -// 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 - Addresses []InterfaceAddress - // TODO: add more elements -} - -// 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. - // TODO: add broadcast + PtP dst ? -} - -// BPF is a compiled filter program, useful for offline packet matching. -type BPF struct { - orig string - bpf _Ctype_struct_bpf_program // takes a finalizer, not overriden by outsiders -} - -// 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) C.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 C.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. -// -// See the package documentation for important details regarding 'timeout'. -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{timeout: timeout, 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 - } - - 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)) - } - - if err := p.openLive(); err != nil { - C.pcap_close(p.cptr) - return nil, err - } - - return p, nil -} - -// OpenOffline opens a file and returns its contents as a *Handle. -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 -} - -// 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 = C.GoBytes(unsafe.Pointer(p.bufptr), C.int(ci.CaptureLength)) - } - p.mu.Unlock() - if err == NextErrorTimeoutExpired { - runtime.Gosched() - } - 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) - } -} - -// getNextBufPtrLocked is shared code for ReadPacketData and -// ZeroCopyReadPacketData. -func (p *Handle) getNextBufPtrLocked(ci *gopacket.CaptureInfo) error { - if p.cptr == nil { - return io.EOF - } - - for atomic.LoadUint64(&p.stop) == 0 { - // try to read a packet if one is immediately available - result := NextError(C.pcap_next_ex(p.cptr, &p.pkthdr, &p.bufptr)) - - switch result { - case NextErrorOk: - // got a packet, set capture info and return - sec := int64(p.pkthdr.ts.tv_sec) - // convert micros to nanos - nanos := int64(p.pkthdr.ts.tv_usec) * 1000 - - ci.Timestamp = time.Unix(sec, nanos) - ci.CaptureLength = int(p.pkthdr.caplen) - ci.Length = int(p.pkthdr.len) - ci.InterfaceIndex = p.deviceIndex - - return nil - case NextErrorNoMorePackets: - // no more packets, return EOF rather than libpcap-specific error - return io.EOF - case NextErrorTimeoutExpired: - // Negative timeout means to loop forever, instead of actually returning - // the timeout error. - if p.timeout < 0 { - // must have had a timeout... wait before trying again - p.waitForPacket() - continue - } - 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.cptr == nil { - return - } - - atomic.StoreUint64(&p.stop, 1) - - // wait for packet reader to stop - p.mu.Lock() - defer p.mu.Unlock() - - C.pcap_close(p.cptr) - p.cptr = nil -} - -// Error returns the current error associated with a pcap handle (pcap_geterr). -func (p *Handle) Error() error { - return errors.New(C.GoString(C.pcap_geterr(p.cptr))) -} - -// Stats returns statistics on the underlying pcap handle. -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 -} - -// ListDataLinks obtains a list of all possible data link types supported for an interface. -func (p *Handle) ListDataLinks() (datalinks []Datalink, err error) { - var dltbuf *C.int - - n := int(C.pcap_list_datalinks(p.cptr, &dltbuf)) - if -1 == n { - return nil, p.Error() - } - - defer C.pcap_free_datalinks(dltbuf) - - datalinks = make([]Datalink, n) - - dltArray := (*[100]C.int)(unsafe.Pointer(dltbuf)) - - 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 -} - -// pcap_compile is NOT thread-safe, so protect it. -var pcapCompileMu sync.Mutex - -// compileBPFFilter always returns an allocated _Ctype_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) (_Ctype_struct_bpf_program, error) { - errorBuf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(errorBuf)) - - var netp uint32 - var maskp uint32 - - // Only do the lookup on network interfaces. - // No device indicates we're handling a pcap file. - 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, - ) { - // We can't lookup the network, but that could be because the interface - // doesn't have an IPv4. - } - } - - var bpf _Ctype_struct_bpf_program - cexpr := C.CString(expr) - defer C.free(unsafe.Pointer(cexpr)) - - pcapCompileMu.Lock() - defer pcapCompileMu.Unlock() - if -1 == C.pcap_compile(p.cptr, &bpf, cexpr, 1, C.bpf_u_int32(maskp)) { - return bpf, p.Error() - } - - return bpf, nil -} - -// 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) { - cptr := C.pcap_open_dead(C.int(linkType), C.int(captureLength)) - if cptr == nil { - return nil, errors.New("error opening dead capture") - } - - h := Handle{cptr: cptr} - 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 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 -} - -// 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 C.pcap_freecode(&bpf) - if err != nil { - return err - } - - if -1 == C.pcap_setfilter(p.cptr, &bpf) { - return p.Error() - } - - return nil -} - -// 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 - } - - 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 -} - -// 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} - cexpr := C.CString(expr) - defer C.free(unsafe.Pointer(cexpr)) - - pcapCompileMu.Lock() - defer pcapCompileMu.Unlock() - if C.pcap_compile(p.cptr, &bpf.bpf, cexpr /* optimize */, 1, C.PCAP_NETMASK_UNKNOWN) != 0 { - return nil, p.Error() - } - - runtime.SetFinalizer(bpf, destroyBPF) - return bpf, nil -} - -// 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) { - C.pcap_freecode(&bpf.bpf) -} - -// 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 { - 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)) // 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(&b.bpf, &hdr, dataptr) != 0 -} - -// Version returns pcap_lib_version. -func Version() string { - return C.GoString(C.pcap_lib_version()) -} - -// LinkType returns pcap_datalink, as a layers.LinkType. -func (p *Handle) LinkType() layers.LinkType { - return layers.LinkType(C.pcap_datalink(p.cptr)) -} - -// SetLinkType calls pcap_set_datalink on the pcap handle. -func (p *Handle) SetLinkType(dlt layers.LinkType) error { - if -1 == C.pcap_set_datalink(p.cptr, C.int(dlt)) { - return p.Error() - } - return nil -} - -// FindAllDevs attempts to enumerate all interfaces on the current machine. -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) - // TODO: add more elements - ifs[j] = iface - j++ - } - return -} - -func findalladdresses(addresses *_Ctype_struct_pcap_addr) (retval []InterfaceAddress) { - // TODO - make it support more than IPv4 and IPv6? - retval = make([]InterfaceAddress, 0, 1) - for curaddr := addresses; curaddr != nil; curaddr = (*_Ctype_struct_pcap_addr)(curaddr.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 curaddr.addr == nil { - continue - } - var a InterfaceAddress - var err error - if a.IP, err = sockaddrToIP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.addr))); err != nil { - continue - } - // To be safe, we'll also check for netmask. - if curaddr.netmask == nil { - continue - } - if a.Netmask, err = sockaddrToIP((*syscall.RawSockaddr)(unsafe.Pointer(curaddr.netmask))); err != nil { - // If we got an IP address but we can't get a netmask, just return the IP - // address. - a.Netmask = nil - } - retval = append(retval, a) - } - return -} - -func sockaddrToIP(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 -} - -// WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle. -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 -} - -// Direction is used by Handle.SetDirection. -type Direction uint8 - -// Direction values for Handle.SetDirection. -const ( - DirectionIn Direction = C.PCAP_D_IN - DirectionOut Direction = C.PCAP_D_OUT - DirectionInOut Direction = C.PCAP_D_INOUT -) - -// 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) - } - if status := C.pcap_setdirection(p.cptr, (C.pcap_direction_t)(direction)); status < 0 { - return statusError(status) - } - return nil -} - -// TimestampSource tells PCAP which type of timestamp to use for packets. -type TimestampSource C.int - -// String returns the timestamp type as a human-readable string. -func (t TimestampSource) String() string { - return C.GoString(C.pcap_tstamp_type_val_to_name(C.int(t))) -} - -// TimestampSourceFromString translates a string into a timestamp type, case -// insensitive. -func TimestampSourceFromString(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 statusError(status C.int) error { - return errors.New(C.GoString(C.pcap_statustostr(status))) -} - -// 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 *C.pcap_t - device string - deviceIndex int - timeout time.Duration -} - -// Activate activates the handle. The current InactiveHandle becomes invalid -// and all future function calls on it will fail. -func (p *InactiveHandle) Activate() (*Handle, error) { - err := activateError(C.pcap_activate(p.cptr)) - if err != aeNoError { - return nil, err - } - h := &Handle{ - cptr: p.cptr, - timeout: p.timeout, - device: p.device, - deviceIndex: p.deviceIndex, - } - p.cptr = nil - return h, nil -} - -// CleanUp cleans up any stuff left over from a successful or failed building -// of a handle. -func (p *InactiveHandle) CleanUp() { - if p.cptr != nil { - C.pcap_close(p.cptr) - } -} - -// 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) { - buf := (*C.char)(C.calloc(errorBufferSize, 1)) - defer C.free(unsafe.Pointer(buf)) - dev := C.CString(device) - defer C.free(unsafe.Pointer(dev)) - - // 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: - cptr := C.pcap_create(dev, buf) - if cptr == nil { - return nil, errors.New(C.GoString(buf)) - } - return &InactiveHandle{cptr: cptr, device: device, deviceIndex: deviceIndex}, nil -} - -// SetSnapLen sets the snap length (max bytes per packet to capture). -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 -} - -// SetPromisc sets the handle to either be promiscuous (capture packets -// unrelated to this host) or not. -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 -} - -// 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 { - if status := C.pcap_set_timeout(p.cptr, timeoutMillis(timeout)); status < 0 { - return statusError(status) - } - p.timeout = timeout - return nil -} - -// SupportedTimestamps returns a list of supported timstamp types for this -// handle. -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 -} - -// SetTimestampSource sets the type of timestamp generator PCAP uses when -// attaching timestamps to packets. -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 -} - -// 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 { - 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 -} - -// SetBufferSize sets the buffer size (in bytes) of the handle. -func (p *InactiveHandle) SetBufferSize(bufferSize int) error { - if status := C.pcap_set_buffer_size(p.cptr, C.int(bufferSize)); status < 0 { - return statusError(status) - } - return nil -} - -// 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 { - 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 -} diff --git a/vendor/github.com/google/gopacket/pcap/pcap_test.go b/vendor/github.com/google/gopacket/pcap/pcap_test.go deleted file mode 100644 index 04f1812..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcap_test.go +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright 2012 Google, Inc. 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 ( - "fmt" - "io" - "io/ioutil" - "log" - "os" - "testing" - - "github.com/google/gopacket" - "github.com/google/gopacket/layers" -) - -func TestPcapNonexistentFile(t *testing.T) { - handle, err := OpenOffline("/path/to/nonexistent/file") - if err == nil { - t.Error("No error returned for nonexistent file open") - } else { - t.Logf("Error returned for nonexistent file: %v", err) - } - if handle != nil { - t.Error("Non-nil handle returned for nonexistent file open") - } -} - -func TestPcapFileRead(t *testing.T) { - invalidData := []byte{ - 0xAB, 0xAD, 0x1D, 0xEA, - } - - invalidPcap, err := ioutil.TempFile("", "invalid.pcap") - if err != nil { - t.Fatal(err) - } - defer os.Remove(invalidPcap.Name()) - - err = ioutil.WriteFile(invalidPcap.Name(), invalidData, 0644) - if err != nil { - t.Fatal(err) - } - defer invalidPcap.Close() - - for _, file := range []struct { - filename string - num int - expectedLayers []gopacket.LayerType - err string - }{ - {filename: "test_loopback.pcap", - num: 24, - expectedLayers: []gopacket.LayerType{ - layers.LayerTypeLoopback, - layers.LayerTypeIPv6, - layers.LayerTypeTCP, - }, - }, - {filename: "test_ethernet.pcap", - num: 16, - expectedLayers: []gopacket.LayerType{ - layers.LayerTypeEthernet, - layers.LayerTypeIPv4, - layers.LayerTypeTCP, - }, - }, - {filename: "test_dns.pcap", - num: 10, - expectedLayers: []gopacket.LayerType{ - layers.LayerTypeEthernet, - layers.LayerTypeIPv4, - layers.LayerTypeUDP, - layers.LayerTypeDNS, - }, - }, - {filename: invalidPcap.Name(), - num: 0, - err: "unknown file format", - }, - } { - t.Logf("\n\n\n\nProcessing file %s\n\n\n\n", file.filename) - - packets := []gopacket.Packet{} - if handle, err := OpenOffline(file.filename); err != nil { - if file.err != "" { - if err.Error() != file.err { - t.Errorf("expected message %q; got %q", file.err, err.Error()) - } - } else { - t.Fatal(err) - } - } else { - if file.err != "" { - t.Fatalf("Expected error, got none") - } - packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) - for packet := range packetSource.Packets() { - packets = append(packets, packet) - } - } - if len(packets) != file.num { - t.Fatal("Incorrect number of packets, want", file.num, "got", len(packets)) - } - for i, p := range packets { - t.Log(p.Dump()) - for _, layertype := range file.expectedLayers { - if p.Layer(layertype) == nil { - t.Fatal("Packet", i, "has no layer type\n%s", layertype, p.Dump()) - } - } - } - } -} - -func TestBPF(t *testing.T) { - handle, err := OpenOffline("test_ethernet.pcap") - if err != nil { - t.Fatal(err) - } - - for _, expected := range []struct { - expr string - Error bool - Result bool - }{ - {"foobar", true, false}, - {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)", false, true}, - {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack", false, true}, - {"udp", false, false}, - } { - data, ci, err := handle.ReadPacketData() - if err != nil { - t.Fatal(err) - } - t.Log("Testing filter", expected.expr) - if bpf, err := handle.NewBPF(expected.expr); err != nil { - if !expected.Error { - t.Error(err, "while compiling filter was unexpected") - } - } else if expected.Error { - t.Error("expected error but didn't see one") - } else if matches := bpf.Matches(ci, data); matches != expected.Result { - t.Error("Filter result was", matches, "but should be", expected.Result) - } - } -} - -func TestBPFInstruction(t *testing.T) { - handle, err := OpenOffline("test_ethernet.pcap") - if err != nil { - t.Fatal(err) - } - - cntr := 0 - oversizedBpfInstructionBuffer := [MaxBpfInstructions + 1]BPFInstruction{} - - for _, expected := range []struct { - Filter string - BpfInstruction []BPFInstruction - Error bool - Result bool - }{ - // {"foobar", true, false}, - {"foobar", []BPFInstruction{}, true, false}, - - // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)' - {"tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)", - []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}, - }, false, true}, - - // tcpdump -dd 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack' - {"tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-ack", - []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, 0x00000010}, - {0x6, 0, 0, 0x0000ffff}, - {0x6, 0, 0, 0x00000000}, - }, false, true}, - - // tcpdump -dd 'udp' - {"udp", - []BPFInstruction{ - {0x28, 0, 0, 0x0000000c}, - {0x15, 0, 5, 0x000086dd}, - {0x30, 0, 0, 0x00000014}, - {0x15, 6, 0, 0x00000011}, - {0x15, 0, 6, 0x0000002c}, - {0x30, 0, 0, 0x00000036}, - {0x15, 3, 4, 0x00000011}, - {0x15, 0, 3, 0x00000800}, - {0x30, 0, 0, 0x00000017}, - {0x15, 0, 1, 0x00000011}, - {0x6, 0, 0, 0x0000ffff}, - {0x6, 0, 0, 0x00000000}, - }, false, false}, - - {"", oversizedBpfInstructionBuffer[:], true, false}, - } { - cntr++ - data, ci, err := handle.ReadPacketData() - if err != nil { - t.Fatal(err) - } - - t.Log("Testing BpfInstruction filter", cntr) - if bpf, err := handle.NewBPFInstructionFilter(expected.BpfInstruction); err != nil { - if !expected.Error { - t.Error(err, "while compiling filter was unexpected") - } - } else if expected.Error { - t.Error("expected error but didn't see one") - } else if matches := bpf.Matches(ci, data); matches != expected.Result { - t.Error("Filter result was", matches, "but should be", expected.Result) - } - - if expected.Filter != "" { - t.Log("Testing dead bpf filter", cntr) - if bpf, err := CompileBPFFilter(layers.LinkTypeEthernet, 65535, expected.Filter); err != nil { - if !expected.Error { - t.Error(err, "while compiling filter was unexpected") - } - } else if expected.Error { - t.Error("expected error but didn't see one") - } else { - if len(bpf) != len(expected.BpfInstruction) { - t.Errorf("expected %d instructions, got %d", len(expected.BpfInstruction), len(bpf)) - } - for i := 0; i < len(bpf); i++ { - if bpf[i] != expected.BpfInstruction[i] { - t.Errorf("expected instruction %d = %d, got %d", i, expected.BpfInstruction[i], bpf[i]) - } - } - } - } - } -} - -func ExampleBPF() { - handle, err := OpenOffline("test_ethernet.pcap") - if err != nil { - log.Fatal(err) - } - synack, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)") - if err != nil { - log.Fatal(err) - } - syn, err := handle.NewBPF("tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn") - if err != nil { - log.Fatal(err) - } - for { - data, ci, err := handle.ReadPacketData() - switch { - case err == io.EOF: - return - case err != nil: - log.Fatal(err) - case synack.Matches(ci, data): - fmt.Println("SYN/ACK packet") - case syn.Matches(ci, data): - fmt.Println("SYN packet") - default: - fmt.Println("SYN flag not set") - } - } - // Output: - // SYN packet - // SYN/ACK packet - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set - // SYN flag not set -} diff --git a/vendor/github.com/google/gopacket/pcap/pcap_tester.go b/vendor/github.com/google/gopacket/pcap/pcap_tester.go deleted file mode 100644 index ee32690..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcap_tester.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2012 Google, Inc. 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. - -// +build ignore - -// This binary tests that PCAP packet capture is working correctly by issuing -// HTTP requests, then making sure we actually capture data off the wire. -package main - -import ( - "errors" - "flag" - "fmt" - "log" - "net" - "net/http" - "os" - "time" - - "github.com/google/gopacket/pcap" -) - -var mode = flag.String("mode", "basic", "One of: basic,filtered,timestamp") - -func generatePackets() { - if resp, err := http.Get("http://code.google.com"); err != nil { - log.Printf("Could not get HTTP: %v", err) - } else { - resp.Body.Close() - } -} - -func main() { - flag.Parse() - ifaces, err := net.Interfaces() - if err != nil { - log.Fatal(err) - } - for _, iface := range ifaces { - log.Printf("Trying capture on %q", iface.Name) - if err := tryCapture(iface); err != nil { - log.Printf("Error capturing on %q: %v", iface.Name, err) - } else { - log.Printf("Successfully captured on %q", iface.Name) - return - } - } - os.Exit(1) -} - -func tryCapture(iface net.Interface) error { - if iface.Name[:2] == "lo" { - return errors.New("skipping loopback") - } - var h *pcap.Handle - var err error - switch *mode { - case "basic": - h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) - if err != nil { - return fmt.Errorf("openlive: %v", err) - } - defer h.Close() - case "filtered": - h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) - if err != nil { - return fmt.Errorf("openlive: %v", err) - } - defer h.Close() - if err := h.SetBPFFilter("port 80 or port 443"); err != nil { - return fmt.Errorf("setbpf: %v", err) - } - case "timestamp": - u, err := pcap.NewInactiveHandle(iface.Name) - if err != nil { - return err - } - defer u.CleanUp() - if err = u.SetSnapLen(65536); err != nil { - return err - } else if err = u.SetPromisc(false); err != nil { - return err - } else if err = u.SetTimeout(time.Second * 3); err != nil { - return err - } - sources := u.SupportedTimestamps() - if len(sources) == 0 { - return errors.New("no supported timestamp sources") - } else if err := u.SetTimestampSource(sources[0]); err != nil { - return fmt.Errorf("settimestampsource(%v): %v", sources[0], err) - } else if h, err = u.Activate(); err != nil { - return fmt.Errorf("could not activate: %v", err) - } - defer h.Close() - default: - panic("Invalid --mode: " + *mode) - } - go generatePackets() - h.ReadPacketData() // Do one dummy read to clear any timeouts. - data, ci, err := h.ReadPacketData() - if err != nil { - return fmt.Errorf("readpacketdata: %v", err) - } - log.Printf("Read packet, %v bytes, CI: %+v", len(data), ci) - return nil -} diff --git a/vendor/github.com/google/gopacket/pcap/pcap_unix.go b/vendor/github.com/google/gopacket/pcap/pcap_unix.go deleted file mode 100644 index b2a6dcd..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcap_unix.go +++ /dev/null @@ -1,71 +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. -// -// +build !windows - -package pcap - -/* -#include <stdlib.h> -#include <pcap.h> - -// 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); -} -*/ -import "C" - -import ( - "errors" - "unsafe" -) - -func (p *Handle) openLive() 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, usec) -} diff --git a/vendor/github.com/google/gopacket/pcap/pcap_windows.go b/vendor/github.com/google/gopacket/pcap/pcap_windows.go deleted file mode 100644 index e3df123..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcap_windows.go +++ /dev/null @@ -1,23 +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 ( - "runtime" -) - -func (p *Handle) openLive() error { - // do nothing - return nil -} - -// waitForPacket waits for a packet or for the timeout to expire. -func (p *Handle) waitForPacket() { - // can't use select() so instead just switch goroutines - runtime.Gosched() -} diff --git a/vendor/github.com/google/gopacket/pcap/pcapgo_test.go b/vendor/github.com/google/gopacket/pcap/pcapgo_test.go deleted file mode 100644 index 4de018a..0000000 --- a/vendor/github.com/google/gopacket/pcap/pcapgo_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2012 Google, Inc. 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 ( - "bytes" - "github.com/google/gopacket" - "github.com/google/gopacket/layers" - "github.com/google/gopacket/pcapgo" - "io/ioutil" - "reflect" - "testing" - "time" -) - -func TestPCAPGoWrite(t *testing.T) { - f, err := ioutil.TempFile("", "pcapgo") - if err != nil { - t.Fatal(err) - } - data := []byte{0xab, 0xcd, 0xef, 0x01, 0x02, 0x03, 0x04} - ci := gopacket.CaptureInfo{ - Timestamp: time.Unix(12345667, 1234567000), - Length: 700, - CaptureLength: len(data), - } - func() { - defer f.Close() - w := pcapgo.NewWriter(f) - if err := w.WriteFileHeader(65536, layers.LinkTypeEthernet); err != nil { - t.Fatal(err) - } - if err := w.WritePacket(ci, data); err != nil { - t.Fatal(err) - } - }() - h, err := OpenOffline(f.Name()) - if err != nil { - t.Fatal(err) - } - defer h.Close() - gotData, gotCI, err := h.ReadPacketData() - if err != nil { - t.Fatal("could not read first packet:", err) - } - if !bytes.Equal(gotData, data) { - t.Errorf("byte mismatch:\nwant: %v\n got: %v", data, gotData) - } - if !reflect.DeepEqual(ci, gotCI) { - t.Errorf("CI mismatch:\nwant: %v\n got: %v", ci, gotCI) - } -} diff --git a/vendor/github.com/google/gopacket/pcap/test_dns.pcap b/vendor/github.com/google/gopacket/pcap/test_dns.pcap Binary files differdeleted file mode 100644 index 3a79f92..0000000 --- a/vendor/github.com/google/gopacket/pcap/test_dns.pcap +++ /dev/null diff --git a/vendor/github.com/google/gopacket/pcap/test_ethernet.pcap b/vendor/github.com/google/gopacket/pcap/test_ethernet.pcap Binary files differdeleted file mode 100644 index 1f8a87c..0000000 --- a/vendor/github.com/google/gopacket/pcap/test_ethernet.pcap +++ /dev/null diff --git a/vendor/github.com/google/gopacket/pcap/test_loopback.pcap b/vendor/github.com/google/gopacket/pcap/test_loopback.pcap Binary files differdeleted file mode 100644 index ddeb82c..0000000 --- a/vendor/github.com/google/gopacket/pcap/test_loopback.pcap +++ /dev/null |