Documentation ¶
Overview ¶
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
Index ¶
- Constants
- Variables
- func Version() string
- type BPF
- type BPFInstruction
- type Datalink
- type Direction
- type Handle
- func (p *Handle) Close()
- func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error)
- func (p *Handle) Error() error
- func (p *Handle) LinkType() layers.LinkType
- func (p *Handle) ListDataLinks() (datalinks []Datalink, err error)
- func (p *Handle) NewBPF(expr string) (*BPF, error)
- func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error)
- func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
- func (p *Handle) SetBPFFilter(expr string) (err error)
- func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error)
- func (p *Handle) SetDirection(direction Direction) error
- func (p *Handle) SetLinkType(dlt layers.LinkType) error
- func (p *Handle) Stats() (stat *Stats, err error)
- func (p *Handle) WritePacketData(data []byte) (err error)
- func (p *Handle) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
- type InactiveHandle
- func (p *InactiveHandle) Activate() (*Handle, error)
- func (p *InactiveHandle) CleanUp()
- func (p *InactiveHandle) SetBufferSize(bufferSize int) error
- func (p *InactiveHandle) SetImmediateMode(mode bool) error
- func (p *InactiveHandle) SetPromisc(promisc bool) error
- func (p *InactiveHandle) SetRFMon(monitor bool) error
- func (p *InactiveHandle) SetSnapLen(snaplen int) error
- func (p *InactiveHandle) SetTimeout(timeout time.Duration) error
- func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error
- func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource)
- type Interface
- type InterfaceAddress
- type NextError
- type Stats
- type TimestampSource
Examples ¶
Constants ¶
const BlockForever = -time.Millisecond * 10
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 MaxBpfInstructions = 4096
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
Variables ¶
var CannotSetRFMon = errors.New("Cannot set rfmon for this handle")
CannotSetRFMon is returned by SetRFMon if the handle does not allow setting RFMon because pcap_can_set_rfmon returns 0.
Functions ¶
Types ¶
type BPF ¶ added in v1.1.7
type BPF struct {
// contains filtered or unexported fields
}
BPF is a compiled filter program, useful for offline packet matching.
Example ¶
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
type BPFInstruction ¶ added in v1.1.12
BPFInstruction is a byte encoded structure holding a BPF instruction
func CompileBPFFilter ¶ added in v1.1.13
func CompileBPFFilter(linkType layers.LinkType, captureLength int, expr string) ([]BPFInstruction, error)
CompileBPFFilter compiles and returns a BPF filter with given a link type and capture length.
type Direction ¶ added in v1.1.8
type Direction uint8
Direction is used by Handle.SetDirection.
const ( DirectionIn Direction = C.PCAP_D_IN DirectionOut Direction = C.PCAP_D_OUT DirectionInOut Direction = C.PCAP_D_INOUT )
Direction values for Handle.SetDirection.
type Handle ¶
type Handle struct {
// contains filtered or unexported fields
}
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
func OpenLive ¶
func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error)
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 OpenOffline ¶
OpenOffline opens a file and returns its contents as a *Handle.
func (*Handle) CompileBPFFilter ¶ added in v1.1.12
func (p *Handle) CompileBPFFilter(expr string) ([]BPFInstruction, error)
CompileBPFFilter compiles and returns a BPF filter for the pcap handle.
func (*Handle) ListDataLinks ¶ added in v1.1.9
ListDataLinks obtains a list of all possible data link types supported for an interface.
func (*Handle) NewBPF ¶ added in v1.1.7
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 (*Handle) NewBPFInstructionFilter ¶ added in v1.1.12
func (p *Handle) NewBPFInstructionFilter(bpfInstructions []BPFInstruction) (*BPF, error)
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 (*Handle) ReadPacketData ¶
func (p *Handle) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
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 (*Handle) SetBPFFilter ¶
SetBPFFilter compiles and sets a BPF filter for the pcap handle.
func (*Handle) SetBPFInstructionFilter ¶ added in v1.1.12
func (p *Handle) SetBPFInstructionFilter(bpfInstructions []BPFInstruction) (err error)
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 (*Handle) SetDirection ¶ added in v1.1.8
SetDirection sets the direction for which packets will be captured.
func (*Handle) SetLinkType ¶
SetLinkType calls pcap_set_datalink on the pcap handle.
func (*Handle) WritePacketData ¶
WritePacketData calls pcap_sendpacket, injecting the given data into the pcap handle.
func (*Handle) ZeroCopyReadPacketData ¶
func (p *Handle) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
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
type InactiveHandle ¶ added in v1.1.0
type InactiveHandle struct {
// contains filtered or unexported fields
}
InactiveHandle allows you to call pre-pcap_activate functions on your pcap handle to set it up just the way you'd like.
func NewInactiveHandle ¶ added in v1.1.0
func NewInactiveHandle(device string) (*InactiveHandle, error)
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 (*InactiveHandle) Activate ¶ added in v1.1.0
func (p *InactiveHandle) Activate() (*Handle, error)
Activate activates the handle. The current InactiveHandle becomes invalid and all future function calls on it will fail.
func (*InactiveHandle) CleanUp ¶ added in v1.1.0
func (p *InactiveHandle) CleanUp()
CleanUp cleans up any stuff left over from a successful or failed building of a handle.
func (*InactiveHandle) SetBufferSize ¶ added in v1.1.8
func (p *InactiveHandle) SetBufferSize(bufferSize int) error
SetBufferSize sets the buffer size (in bytes) of the handle.
func (*InactiveHandle) SetImmediateMode ¶ added in v1.1.8
func (p *InactiveHandle) SetImmediateMode(mode bool) error
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 (*InactiveHandle) SetPromisc ¶ added in v1.1.0
func (p *InactiveHandle) SetPromisc(promisc bool) error
SetPromisc sets the handle to either be promiscuous (capture packets unrelated to this host) or not.
func (*InactiveHandle) SetRFMon ¶ added in v1.1.5
func (p *InactiveHandle) SetRFMon(monitor bool) error
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 (*InactiveHandle) SetSnapLen ¶ added in v1.1.0
func (p *InactiveHandle) SetSnapLen(snaplen int) error
SetSnapLen sets the snap length (max bytes per packet to capture).
func (*InactiveHandle) SetTimeout ¶ added in v1.1.0
func (p *InactiveHandle) SetTimeout(timeout time.Duration) error
SetTimeout sets the read timeout for the handle.
See the package documentation for important details regarding 'timeout'.
func (*InactiveHandle) SetTimestampSource ¶ added in v1.1.0
func (p *InactiveHandle) SetTimestampSource(t TimestampSource) error
SetTimestampSource sets the type of timestamp generator PCAP uses when attaching timestamps to packets.
func (*InactiveHandle) SupportedTimestamps ¶ added in v1.1.0
func (p *InactiveHandle) SupportedTimestamps() (out []TimestampSource)
SupportedTimestamps returns a list of supported timstamp types for this handle.
type Interface ¶
type Interface struct { Name string Description string Addresses []InterfaceAddress }
Interface describes a single network interface on a machine.
func FindAllDevs ¶
FindAllDevs attempts to enumerate all interfaces on the current machine.
type InterfaceAddress ¶
type InterfaceAddress struct { IP net.IP Netmask net.IPMask // Netmask may be nil if we were unable to retrieve it. }
InterfaceAddress describes an address associated with an Interface. Currently, it's IPv4/6 specific.
type NextError ¶
type NextError int32
NextError is the return code from a call to Next.
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 )
NextError values.
type Stats ¶
Stats contains statistics on how many packets were handled by a pcap handle, and what was done with those packets.
type TimestampSource ¶ added in v1.0.8
TimestampSource tells PCAP which type of timestamp to use for packets.
func TimestampSourceFromString ¶ added in v1.0.8
func TimestampSourceFromString(s string) (TimestampSource, error)
TimestampSourceFromString translates a string into a timestamp type, case insensitive.
func (TimestampSource) String ¶ added in v1.0.8
func (t TimestampSource) String() string
String returns the timestamp type as a human-readable string.
Directories ¶
Path | Synopsis |
---|---|
This benchmark reads in file <tempdir>/gopacket_benchmark.pcap and measures the time it takes to decode all packets from that file.
|
This benchmark reads in file <tempdir>/gopacket_benchmark.pcap and measures the time it takes to decode all packets from that file. |