Showing preview only (278K chars total). Download the full file or copy to clipboard to get everything.
Repository: ghedo/go.pkt
Branch: master
Commit: c97f47ad982f
Files: 63
Total size: 261.3 KB
Directory structure:
gitextract_y_3guso3/
├── .travis.yml
├── COPYING
├── README.md
├── capture/
│ ├── capture.go
│ ├── file/
│ │ ├── capture.go
│ │ ├── capture_test.go
│ │ └── capture_test.pcap
│ └── pcap/
│ ├── capture.go
│ └── capture_test.go
├── examples/
│ ├── arp/
│ │ └── main.go
│ ├── bpf_asm/
│ │ ├── Makefile
│ │ ├── bpf_asm.l
│ │ └── bpf_asm.y
│ ├── dump/
│ │ └── main.go
│ ├── ping/
│ │ └── main.go
│ ├── route/
│ │ └── main.go
│ ├── syn_scan/
│ │ └── main.go
│ ├── tracereply/
│ │ └── main.go
│ └── traceroute/
│ └── main.go
├── filter/
│ ├── bpf_builder.go
│ ├── bpf_builder_test.go
│ ├── bpf_filter.c
│ ├── bpf_filter.go
│ ├── bpf_filter.h
│ ├── bpf_filter_test.go
│ └── pcap.go
├── go.mod
├── go.sum
├── layers/
│ ├── layers.go
│ └── layers_test.go
├── network/
│ └── network.go
├── packet/
│ ├── arp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── buffer.go
│ ├── eth/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── icmpv4/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── icmpv6/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── ipv4/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── ipv6/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── llc/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── packet.go
│ ├── radiotap/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── raw/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── sll/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── snap/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── tcp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── udp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ └── vlan/
│ ├── pkt.go
│ └── pkt_test.go
└── routing/
├── routing.go
└── routing_linux.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .travis.yml
================================================
language: go
sudo: false
addons:
apt:
packages:
- libpcap0.8-dev
go:
- "1.11"
- "tip"
env:
- GO111MODULE=on
script:
- go build ./...
- go test ./...
================================================
FILE: COPYING
================================================
Copyright (c) 2014, Alessandro Ghedini <alessandro@ghedini.me>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
go.pkt
======

**go.pkt** provides Go libraries for capturing, injecting, filtering, encoding and
decoding network packets.
* [capture][capture]: provides the basic interface for packet capturing and
injection. Different implementations ("pcap", "file", ...) are provided as
subpackages.
* [filter][filter]: provides an API for compiling and manipulating BPF filters.
A filter can be either compiled from tcpdump-like expressions, or created from
basic BPF instructions. Filters can then be either applied to packet sources
(see the capture package) or directly run against binary data.
* [packet][packet]: provides the interfaces for implementing packet encoders
and decoders. Every supported protocol implements the Packet interface as a
submodule of this package (e.g. packet/ipv4, packet/tcp, ...).
* [layers][layers]: provides utility functions for encoding and decoding
packets to/from binary data. Differently from the basic "packet" interface,
this can encode and decode complete "stacks" of packets, instead of
manipulating single ones.
* [network][network]: provides utility functions for sending and receiving
packets over the network. Basically, it hides some of the complexity of using
the capture and layers packages together.
* [routing][routing]: provides network routing information about the system. It
can either return all available routes or select a specific route depending on
a destination address.
[capture]: http://godoc.org/github.com/ghedo/go.pkt/capture
[filter]: http://godoc.org/github.com/ghedo/go.pkt/filter
[packet]: http://godoc.org/github.com/ghedo/go.pkt/packet
[layers]: http://godoc.org/github.com/ghedo/go.pkt/layers
[network]: http://godoc.org/github.com/ghedo/go.pkt/network
[routing]: http://godoc.org/github.com/ghedo/go.pkt/routing
## Getting Started
### Capturing
Packet capturing is done using a packet "source" such as a network interface or
a dump file.
In the following example we create a "pcap" capture handle using the `eth0`
network interface, we activate it and then capture packets using the `Capture()`
method.
```go
src, err := pcap.Open("eth0")
if err != nil {
log.Fatal(err)
}
defer src.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = src.Activate()
if err != nil {
log.Fatal(err)
}
for {
buf, err := src.Capture()
if err != nil {
log.Fatal(err)
}
log.Println("PACKET!!!")
// do something with the packet
}
```
### Injection
Similarly to packet capturing, packet injection requires a capture handle.
In the following example we create a capture handle like before and then use
the `Inject()` method to send some data (we'll see later how to encode data in
the propert formats).
```go
dst, err := pcap.Open("eth0")
if err != nil {
log.Fatal(err)
}
defer dst.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = dst.Activate()
if err != nil {
log.Fatal(err)
}
err = dst.Inject([]byte("random data"))
if err != nil {
log.Fatal(err)
}
```
### Filtering
Packet filtering is done by creating a filter (e.g. by compiling it from an
expression) which can be either applied to a capture handle (by using the
`ApplyFilter()` method) or used directly against a data buffer.
In the following example we create a filter by compiling a tcpdump-like
expression and then try to match some data against it.
```go
// Match UDP or TCP packets on top of Ethernet
flt, err := filter.Compile("udp or tcp", packet.Eth)
if err != nil {
log.Fatal(err)
}
if flt.Match([]byte("random data")) {
log.Println("MATCH!!!")
}
```
### Encoding
Encoding packets is done by using the functions provided by the `layers`
package.
In the following example we create an ARP packet on top of an Ethernet packet
and we encode them to binary data by using the `Pack()` method. Note that you'll
need to import the packages of the protocols used (`packet/eth` and `packet/arp`).
```go
// Create an Ethernet packet
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
// Create an ARP packet
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr = net.ParseIP("192.168.1.135")
arp_pkt.ProtoDstAddr = net.ParseIP("192.168.1.254")
buf, err := layers.Pack(eth_pkt, arp_pkt)
if err != nil {
log.Fatal(err)
}
// do something with the packet
log.Println(buf)
```
### Decoding
Like encoding, decoding is done by using the functions provided by the `layers`
package.
The following example uses the `UnpackAll()` function to decode a whole chain of
packets (e.g. ethernet -> ipv4 -> udp).
```go
// Create the buf data
buf := []byte("random data")
// Assume Ethernet as datalink layer
pkt, err := layers.UnpackAll(buf, packet.Eth)
if err != nil {
log.Fatal(err)
}
log.Println(pkt)
```
### Network
Instead of using the layers and capture packages together, the network package
can be used instead.
The following example creates an ARP request packet and uses `SendRecv()` to
send it and receive a suitable answer.
```go
c, err := pcap.Open("eth0")
if err != nil {
log.Fatal(err)
}
defer c.Close()
err = c.Activate()
if err != nil {
log.Fatal(err)
}
// Create an Ethernet packet
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
// Create an ARP packet
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr = net.ParseIP("192.168.1.135")
arp_pkt.ProtoDstAddr = net.ParseIP("192.168.1.254")
rsp_pkt, err := network.SendRecv(c, 0, eth_pkt, arp_pkt)
if err != nil {
log.Fatal(err)
}
log.Println(rsp_pkt)
```
### Routing
TODO
For more examples have a look at the [examples](examples/) directory in the
source repository.
## Dependencies
* `libpcap`
## Copyright
Copyright (C) 2014 Alessandro Ghedini <alessandro@ghedini.me>
See COPYING for the license.
================================================
FILE: capture/capture.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides the basic interface for packet capturing and injection. Different
// implementations ("pcap", "file", ...) are provided as subpackages.
package capture
import "github.com/ghedo/go.pkt/filter"
import "github.com/ghedo/go.pkt/packet"
type Handle interface {
LinkType() packet.Type
SetMTU(mtu int) error
SetPromiscMode(promisc bool) error
SetMonitorMode(monitor bool) error
ApplyFilter(filter *filter.Filter) error
Activate() error
Capture() ([]byte, error)
Inject(buf []byte) error
Close()
}
================================================
FILE: capture/file/capture.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides native packet capturing and injection on pcap dump files without
// requiring the libpcap library.
package file
import "bytes"
import "encoding/binary"
import "fmt"
import "io"
import "os"
import "github.com/ghedo/go.pkt/filter"
import "github.com/ghedo/go.pkt/packet"
type Handle struct {
File string
file *os.File
out *os.File
order binary.ByteOrder
link uint32
mtu uint32
filter *filter.Filter
}
var BigEndian = []byte{0xa1, 0xb2, 0xc3, 0xd4}
var LittleEndian = []byte{0xd4, 0xc3, 0xb2, 0xa1}
// Create a new capture handle from the given dump file. This will either open
// the file if it exists, or create a new one.
func Open(file_name string) (*Handle, error) {
handle := &Handle{ File: file_name }
open := open_file
if _, err := os.Stat(file_name); os.IsNotExist(err) {
open = create_file
}
file, err := open(file_name)
if err != nil {
return nil, err
}
handle.file = file
handle.file.Seek(0, 0)
magic := make([]byte, 4)
file.Read(magic)
switch {
case bytes.Equal(magic, BigEndian):
handle.order = binary.BigEndian
case bytes.Equal(magic, LittleEndian):
handle.order = binary.LittleEndian
default:
handle.file.Close()
return nil, fmt.Errorf("Invalid file")
}
var ver_maj, ver_min uint16
var discard, mtu, link_type uint32
binary.Read(file, handle.order, &ver_maj)
binary.Read(file, handle.order, &ver_min)
binary.Read(file, handle.order, &discard)
binary.Read(file, handle.order, &discard)
binary.Read(file, handle.order, &mtu)
binary.Read(file, handle.order, &link_type)
handle.link = link_type
handle.mtu = mtu
/*
* Use a different file handle for injecting packages so that we don't
* need to seek back and forth for capturing and injecting
*/
handle.out, _ = open_file(file_name)
handle.out.Seek(0, 2)
return handle, nil
}
func create_file(file_name string) (*os.File, error) {
file, err := os.Create(file_name)
if err != nil {
return nil, fmt.Errorf("Could not create file: %s", err)
}
file.Write(BigEndian) /* endiannes */
binary.Write(file, binary.BigEndian, uint16(2)) /* ver major */
binary.Write(file, binary.BigEndian, uint16(4)) /* ver minor */
binary.Write(file, binary.BigEndian, uint32(0))
binary.Write(file, binary.BigEndian, uint32(0))
binary.Write(file, binary.BigEndian, uint32(0x7fff)) /* MTU */
binary.Write(file, binary.BigEndian, uint32(1)) /* link type */
return file, nil
}
func open_file(file_name string) (*os.File, error) {
file, err := os.OpenFile(file_name, os.O_RDWR, 0644);
if err != nil {
return nil, fmt.Errorf("Could not open file: %s", err)
}
return file, nil
}
// Return the link type of the capture handle (that is, the type of packets that
// come out of the packet source).
func (h *Handle) LinkType() packet.Type {
return packet.LinkType(h.link)
}
// Not supported.
func (h *Handle) SetMTU(mtu int) error {
return fmt.Errorf("Unsupported")
}
// Not supported.
func (h *Handle) SetPromiscMode(promisc bool) error {
return fmt.Errorf("Unsupported")
}
// Not supported.
func (h *Handle) SetMonitorMode(monitor bool) error {
return fmt.Errorf("Unsupported")
}
// Apply the given filter it to the packet source. Only packets that match this
// filter will be captured.
func (h *Handle) ApplyFilter(filter *filter.Filter) error {
if !filter.Validate() {
return fmt.Errorf("Invalid filter")
}
h.filter = filter
return nil
}
// Activate the capture handle (this is not needed for the file capture handle,
// but you may want to call it anyway in order to make switching to different
// packet sources easier).
func (h *Handle) Activate() error {
return nil
}
// Capture a single packet from the packet source. If no packet is available
// (i.e. if the end of the dump file has been reached) it will return a nil
// slice.
func (h *Handle) Capture() ([]byte, error) {
var buf []byte
var sec, usec, caplen, wirelen uint32
for {
binary.Read(h.file, h.order, &sec)
binary.Read(h.file, h.order, &usec)
binary.Read(h.file, h.order, &caplen)
binary.Read(h.file, h.order, &wirelen)
if caplen == 0 {
return nil, nil
}
buf = make([]byte, int(caplen))
_, err := h.file.Read(buf)
if err == io.EOF {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("Could not capture: %s", err)
}
if h.filter != nil && !h.filter.Match(buf) {
continue
}
break
}
return buf, nil
}
// Inject a packet in the packet source. This will automatically append packets
// at the end of the dump file, instead of truncating it.
func (h *Handle) Inject(buf []byte) error {
var sec, usec, caplen, wirelen uint32
sec = 0
usec = 0
caplen = uint32(len(buf))
wirelen = caplen
binary.Write(h.out, h.order, sec)
binary.Write(h.out, h.order, usec)
binary.Write(h.out, h.order, caplen)
binary.Write(h.out, h.order, wirelen)
n, err := h.out.Write(buf)
if err != nil || n < len(buf) {
return fmt.Errorf("Could not write packet: %s", err)
}
return nil
}
// Close the packet source.
func (h *Handle) Close() {
h.file.Close()
h.out.Close()
}
================================================
FILE: capture/file/capture_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package file_test
import "log"
import "testing"
import "github.com/ghedo/go.pkt/capture/file"
import "github.com/ghedo/go.pkt/filter"
func TestCapture(t *testing.T) {
src, err := file.Open("capture_test.pcap")
if err != nil {
t.Fatalf("Error opening: %s", err)
}
defer src.Close()
var count uint64
for {
buf, err := src.Capture()
if err != nil {
t.Fatalf("Error reading: %s", err)
}
if buf == nil {
break
}
count++
}
if count != 16 {
t.Fatalf("Count mismatch: %d", count)
}
}
func TestCaptureFilter(t *testing.T) {
src, err := file.Open("capture_test.pcap")
if err != nil {
t.Fatalf("Error opening: %s", err)
}
defer src.Close()
flt, err := filter.Compile("arp", src.LinkType(), false)
if err != nil {
t.Fatalf("Error parsing filter: %s", err)
}
defer flt.Cleanup()
err = src.ApplyFilter(flt)
if err != nil {
t.Fatalf("Error applying filter: %s", err)
}
var count uint64
for {
buf, err := src.Capture()
if err != nil {
t.Fatalf("Error reading: %s %d", err, count)
}
if buf == nil {
break
}
count++
}
if count != 2 {
t.Fatalf("Count mismatch: %d", count)
}
}
func TestInject(t *testing.T) {
src, err := file.Open("capture_test.pcap")
if err != nil {
t.Fatalf("Error opening: %s", err)
}
defer src.Close()
dst, err := file.Open("inject_test.pcap")
if err != nil {
t.Fatalf("Error opening: %s", err)
}
defer dst.Close()
var count uint64
for {
buf, err := src.Capture()
if err != nil {
t.Fatalf("Error reading: %s", err)
}
if buf == nil {
break
}
err = dst.Inject(buf)
if err != nil {
t.Fatalf("Error writing: %s", err)
}
count++
}
if count != 16 {
t.Fatalf("Count mismatch: %d", count)
}
}
func ExampleCapture() {
src, err := file.Open("/path/to/file/dump.pcap")
if err != nil {
log.Fatal(err)
}
defer src.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = src.Activate()
if err != nil {
log.Fatal(err)
}
for {
buf, err := src.Capture()
if err != nil {
log.Fatal(err)
}
if buf == nil {
break
}
log.Println("PACKET!!!")
// do something with the packet
}
}
func ExampleInject() {
dst, err := file.Open("/path/to/file/dump.pcap")
if err != nil {
log.Fatal(err)
}
defer dst.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = dst.Activate()
if err != nil {
log.Fatal(err)
}
err = dst.Inject([]byte("random data"))
if err != nil {
log.Fatal(err)
}
}
================================================
FILE: capture/pcap/capture.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides packet capturing and injection on live network interfaces via
// libpcap.
package pcap
// #cgo LDFLAGS: -lpcap
// #include <stdlib.h>
// #include <pcap.h>
import "C"
import "fmt"
import "unsafe"
import "github.com/ghedo/go.pkt/filter"
import "github.com/ghedo/go.pkt/packet"
type Handle struct {
Device string
pcap *C.pcap_t
}
// Create a new capture handle from the given network interface. Noe that this
// may require root privileges.
func Open(dev_name string) (*Handle, error) {
handle := &Handle{ Device: dev_name }
dev_str := C.CString(dev_name)
defer C.free(unsafe.Pointer(dev_str))
err_str := (*C.char)(C.calloc(256, 1))
defer C.free(unsafe.Pointer(err_str))
handle.pcap = C.pcap_create(dev_str, err_str)
if handle == nil {
return nil, fmt.Errorf(
"Could not open device: %s", C.GoString(err_str),
)
}
return handle, nil
}
// Return the link type of the capture handle (that is, the type of packets that
// come out of the packet source).
func (h *Handle) LinkType() packet.Type {
return packet.LinkType(uint32(C.pcap_datalink(h.pcap)))
}
func (h *Handle) SetMTU(mtu int) error {
err := C.pcap_set_snaplen(h.pcap, C.int(mtu))
if err < 0 {
return fmt.Errorf("Handle already active")
}
return nil
}
// Enable/disable promiscuous mode.
func (h *Handle) SetPromiscMode(promisc bool) error {
var promisc_int C.int
if promisc {
promisc_int = 1
} else {
promisc_int = 0
}
err := C.pcap_set_promisc(h.pcap, promisc_int)
if err < 0 {
return fmt.Errorf("Handle already active")
}
return nil
}
// Enable/disable monitor mode. This is only relevant to RF-based packet sources
// (e.g. a WiFi or Bluetooth network interface)
func (h *Handle) SetMonitorMode(monitor bool) error {
var rfmon_int C.int
if monitor {
rfmon_int = 1
} else {
rfmon_int = 0
}
err := C.pcap_set_rfmon(h.pcap, rfmon_int)
if err < 0 {
return fmt.Errorf("Handle already active")
}
return nil
}
// Apply the given filter it to the packet source. Only packets that match this
// filter will be captured.
func (h *Handle) ApplyFilter(filter *filter.Filter) error {
if !filter.Validate() {
return fmt.Errorf("Invalid filter")
}
err_str := (*C.char)(C.calloc(256, 1))
defer C.free(unsafe.Pointer(err_str))
dev_str := C.CString(h.Device)
defer C.free(unsafe.Pointer(dev_str))
err := C.pcap_setfilter(h.pcap, (*C.struct_bpf_program)(filter.Program()))
if err < 0 {
return fmt.Errorf("Could not set filter: %s", h.get_error())
}
return nil
}
// Activate the packet source. Note that after calling this method it will not
// be possible to change the packet source configuration (MTU, promiscuous mode,
// monitor mode, ...)
func (h *Handle) Activate() error {
err := C.pcap_activate(h.pcap)
if err < 0 {
return fmt.Errorf("Could not activate: %s", h.get_error())
}
return nil
}
// Capture a single packet from the packet source. This will block until a
// packet is received.
func (h *Handle) Capture() ([]byte, error) {
var buf *C.u_char
var pkt_hdr *C.struct_pcap_pkthdr
for {
err := C.pcap_next_ex(h.pcap, &pkt_hdr, &buf)
switch err {
case -2:
return nil, nil
case -1:
return nil, fmt.Errorf(
"Could not read packet: %s", h.get_error(),
)
case 0:
continue
case 1:
return C.GoBytes(unsafe.Pointer(buf),
C.int(pkt_hdr.len)), nil
}
}
return nil, fmt.Errorf("WTF")
}
// Inject a packet in the packet source.
func (h *Handle) Inject(buf []byte) error {
cbuf := (*C.u_char)(&buf[0])
blen := C.int(len(buf))
err := C.pcap_sendpacket(h.pcap, cbuf, blen)
if err < 0 {
return fmt.Errorf("Could not inject packet: %s", h.get_error())
}
return nil
}
// Close the packet source.
func (h *Handle) Close() {
C.pcap_close(h.pcap)
}
func (h *Handle) get_error() error {
err_str := C.pcap_geterr(h.pcap)
return fmt.Errorf(C.GoString(err_str))
}
================================================
FILE: capture/pcap/capture_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package pcap_test
import "log"
import "github.com/ghedo/go.pkt/capture/pcap"
func ExampleCapture() {
src, err := pcap.Open("eth0")
if err != nil {
log.Fatal(err)
}
defer src.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = src.Activate()
if err != nil {
log.Fatal(err)
}
for {
buf, err := src.Capture()
if err != nil {
log.Fatal(err)
}
log.Printf("PACKET!!! %v", buf)
// do something with the packet
}
}
func ExampleInject() {
dst, err := pcap.Open("eth0")
if err != nil {
log.Fatal(err)
}
defer dst.Close()
// you may configure the source further, e.g. by activating
// promiscuous mode.
err = dst.Activate()
if err != nil {
log.Fatal(err)
}
err = dst.Inject([]byte("random data"))
if err != nil {
log.Fatal(err)
}
}
================================================
FILE: examples/arp/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "log"
import "net"
import "time"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/capture/pcap"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/arp"
import "github.com/ghedo/go.pkt/network"
import "github.com/ghedo/go.pkt/routing"
func main() {
log.SetFlags(0)
usage := `Usage: arp <addr>
Resolve the given IP address using ARP.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
addr := args["<addr>"].(string)
addr_ip := net.ParseIP(addr)
timeout := 5 * time.Second
route, err := routing.RouteTo(addr_ip)
if err != nil {
log.Fatalf("Error: %s", err)
}
if route == nil {
log.Println("No route found")
}
c, err := pcap.Open(route.Iface.Name)
if err != nil {
log.Fatalf("Error opening interface: %s", err)
}
defer c.Close()
err = c.Activate()
if err != nil {
log.Fatalf("Error activating source: %s", err)
}
eth_pkt := eth.Make()
eth_pkt.SrcAddr = route.Iface.HardwareAddr
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr = route.Iface.HardwareAddr
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr, _ = route.GetIfaceIPv4Addr()
arp_pkt.ProtoDstAddr = addr_ip
pkt, err := network.SendRecv(c, timeout, eth_pkt, arp_pkt)
if err != nil {
log.Fatal(err)
}
log.Println(pkt.Payload().(*arp.Packet).HWSrcAddr)
}
================================================
FILE: examples/bpf_asm/Makefile
================================================
all: bpf_asm
bpf_asm: bpf_asm.nn.go y.go
go build -o bpf_asm bpf_asm.nn.go y.go
y.go: bpf_asm.y
go tool yacc bpf_asm.y
bpf_asm.nn.go: bpf_asm.l
nex bpf_asm.l
================================================
FILE: examples/bpf_asm/bpf_asm.l
================================================
/ldb/ { return OP_LDB }
/ldh/ { return OP_LDH }
/ld/ { return OP_LD }
/ldi/ { return OP_LDI }
/ldx/ { return OP_LDX }
/ldxi/ { return OP_LDXI }
/ldxb/ { return OP_LDXB }
/st/ { return OP_ST }
/stx/ { return OP_STX }
/jmp/ { return OP_JMP }
/ja/ { return OP_JMP }
/jeq/ { return OP_JEQ }
/jneq/ { return OP_JNEQ }
/jne/ { return OP_JNEQ }
/jlt/ { return OP_JLT }
/jle/ { return OP_JLE }
/jgt/ { return OP_JGT }
/jge/ { return OP_JGE }
/jset/ { return OP_JSET }
/add/ { return OP_ADD }
/sub/ { return OP_SUB }
/mul/ { return OP_MUL }
/div/ { return OP_DIV }
/neg/ { return OP_NEG }
/and/ { return OP_AND }
/or/ { return OP_OR }
/lsh/ { return OP_LSH }
/rsh/ { return OP_RSH }
/ret/ { return OP_RET }
/tax/ { return OP_TAX }
/txa/ { return OP_TXA }
/#?len/ { return K_PKT_LEN }
/#?proto/ { return K_PROTO }
/#?type/ { return K_TYPE }
/#?poff/ { return K_POFF }
/#?ifidx/ { return K_IFIDX }
/#?nla/ { return K_NLATTR }
/#?nlan/ { return K_NLATTR_NEST }
/#?mark/ { return K_MARK }
/#?queue/ { return K_QUEUE }
/#?hatype/ { return K_HATYPE }
/#?rxhash/ { return K_RXHASH }
/#?cpu/ { return K_CPU }
/#?vlan_tci/ { return K_VLANT }
/#?vlan_pr/ { return K_VLANP }
/:/ { return ':' }
/,/ { return ',' }
/#/ { return '#' }
/%/ { return '%' }
/\[/ { return '[' }
/\]/ { return ']' }
/\(/ { return '(' }
/\)/ { return ')' }
/x/ { return 'x' }
/a/ { return 'a' }
/\+/ { return '+' }
/M/ { return 'M' }
/\*/ { return '*' }
/&/ { return '&' }
/([0][x][a-fA-F0-9]+)/ {
str := strings.TrimPrefix(yylex.Text(), "0x")
num, _ := strconv.ParseUint(str, 16, 32)
lval.number = uint32(num)
return number
}
/([0][b][0-1]+)/ {
str := strings.TrimPrefix(yylex.Text(), "0b")
num, _ := strconv.ParseUint(str, 2, 32)
lval.number = uint32(num)
return number
}
/(([0])|([-+]?[1-9][0-9]*))/ {
num, _ := strconv.ParseUint(yylex.Text(), 10, 32)
lval.number = uint32(num)
return number
}
/([0][0-9]+)/ {
str := strings.TrimPrefix(yylex.Text(), "0")
num, _ := strconv.ParseUint(str, 8, 32)
lval.number = uint32(num)
return number
}
/[a-zA-Z_][a-zA-Z0-9_]+/ {
lval.label = yylex.Text()
return label
}
//
package main
import "log"
import "strconv"
import "os"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/filter"
var bld *filter.Builder
func main() {
log.SetFlags(0)
usage := `Usage: bpf_asm <file>`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
file, err := os.Open(args["<file>"].(string))
if err != nil {
log.Fatalf("Error opening file: %s", err)
}
bld = filter.NewBuilder()
lex := NewLexer(file)
yyParse(lex)
flt := bld.Build()
if !flt.Validate() {
log.Fatalf("Invalid filter")
}
log.Println(flt)
}
================================================
FILE: examples/bpf_asm/bpf_asm.y
================================================
%{
package main
import "github.com/ghedo/go.pkt/filter"
%}
%union {
label string
number uint32
}
%token OP_LDB
%token OP_LDH
%token OP_LD
%token OP_LDI
%token OP_LDX
%token OP_LDXI
%token OP_LDXB
%token OP_ST
%token OP_STX
%token OP_JMP
%token OP_JEQ
%token OP_JNEQ
%token OP_JLT
%token OP_JLE
%token OP_JGT
%token OP_JGE
%token OP_JSET
%token OP_ADD
%token OP_SUB
%token OP_MUL
%token OP_DIV
%token OP_NEG
%token OP_AND
%token OP_OR
%token OP_LSH
%token OP_RSH
%token OP_RET
%token OP_TAX
%token OP_TXA
%token K_PKT_LEN
%token K_PROTO
%token K_TYPE
%token K_POFF
%token K_IFIDX
%token K_NLATTR
%token K_NLATTR_NEST
%token K_MARK
%token K_QUEUE
%token K_HATYPE
%token K_RXHASH
%token K_CPU
%token K_VLANT
%token K_VLANP
%token number
%token label
%token jtl
%token jfl
%token jkl
%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
%type <label> label
%type <number> number
%%
prog
: line
| prog line
;
line
: instr
| labelled_instr
;
labelled_instr
: labelled instr
;
instr
: ldb
| ldh
| ld
| ldi
| ldx
| ldxi
| st
| stx
| jmp
| jeq
| jneq
| jlt
| jle
| jgt
| jge
| jset
| add
| sub
| mul
| div
| neg
| and
| or
| lsh
| rsh
| ret
| tax
| txa
;
labelled
: label ':' { bld.Label($1)
}
;
ldb
: OP_LDB '[' 'x' '+' number ']' {
bld.LD(filter.Byte, filter.IND, $5)
}
| OP_LDB '[' '%' 'x' '+' number ']' {
bld.LD(filter.Byte, filter.IND, $6)
}
| OP_LDB '[' number ']' {
bld.LD(filter.Byte, filter.ABS, $3)
}
;
ldh
: OP_LDH '[' 'x' '+' number ']' {
bld.LD(filter.Half, filter.IND, $5)
}
| OP_LDH '[' '%' 'x' '+' number ']' {
bld.LD(filter.Half, filter.IND, $6)
}
| OP_LDH '[' number ']' {
bld.LD(filter.Half, filter.ABS, $3)
}
;
ldi
: OP_LDI '#' number {
bld.LD(filter.Word, filter.IMM, $3)
}
| OP_LDI number {
bld.LD(filter.Word, filter.IMM, $2)
}
;
ld
: OP_LD '#' number {
bld.LD(filter.Word, filter.IMM, $3)
}
| OP_LD K_PKT_LEN {
bld.LD(filter.Word, filter.LEN, 0)
}
| OP_LD 'M' '[' number ']' {
bld.LD(filter.Word, filter.MEM, $4)
}
| OP_LD '[' 'x' '+' number ']' {
bld.LD(filter.Word, filter.IND, $5)
}
| OP_LD '[' '%' 'x' '+' number ']' {
bld.LD(filter.Word, filter.IND, $6)
}
| OP_LD '[' number ']' {
bld.LD(filter.Word, filter.ABS, $3)
}
;
ldxi
: OP_LDXI '#' number {
bld.LDX(filter.Word, filter.IMM, $3)
}
| OP_LDXI number {
bld.LDX(filter.Word, filter.IMM, $2)
}
;
ldx
: OP_LDX '#' number {
bld.LDX(filter.Word, filter.IMM, $3)
}
| OP_LDX K_PKT_LEN {
bld.LDX(filter.Word, filter.LEN, 0)
}
| OP_LDX 'M' '[' number ']' {
bld.LDX(filter.Word, filter.MEM, $4)
}
| OP_LDXB number '*' '(' '[' number ']' '&' number ')' {
if ($2 != 4 || $9 != 0xf) {
yylex.Error("ldxb offset not supported!")
} else {
bld.LDX(filter.Byte, filter.MSH, $6)
}
}
| OP_LDX number '*' '(' '[' number ']' '&' number ')' {
if ($2 != 4 || $9 != 0xf) {
yylex.Error("ldxb offset not supported!")
} else {
bld.LDX(filter.Byte, filter.MSH, $6)
}
}
;
st
: OP_ST 'M' '[' number ']' {
bld.ST($4)
}
;
stx
: OP_STX 'M' '[' number ']' {
bld.STX($4)
}
;
jmp
: OP_JMP label {
bld.JA($2)
}
;
jeq
: OP_JEQ '#' number ',' label ',' label {
bld.JEQ(filter.Const, $5, $7, $3)
}
| OP_JEQ 'x' ',' label ',' label {
bld.JEQ(filter.Index, $4, $6, 0)
}
| OP_JEQ '%' 'x' ',' label ',' label {
bld.JEQ(filter.Index, $5, $7, 0)
}
| OP_JEQ '#' number ',' label {
bld.JEQ(filter.Const, "", $5, $3)
}
| OP_JEQ 'x' ',' label {
bld.JEQ(filter.Index, "", $4, 0)
}
| OP_JEQ '%' 'x' ',' label {
bld.JEQ(filter.Index, "", $5, 0)
}
;
jneq
: OP_JNEQ '#' number ',' label {
bld.JEQ(filter.Const, "", $5, $3)
}
| OP_JNEQ 'x' ',' label {
bld.JEQ(filter.Index, "", $4, 0)
}
| OP_JNEQ '%' 'x' ',' label {
bld.JEQ(filter.Index, "", $5, 0)
}
;
jlt
: OP_JLT '#' number ',' label {
bld.JGE(filter.Const, "", $5, $3)
}
| OP_JLT 'x' ',' label {
bld.JGE(filter.Index, "", $4, 0)
}
| OP_JLT '%' 'x' ',' label {
bld.JGE(filter.Index, "", $5, 0)
}
;
jle
: OP_JLE '#' number ',' label {
bld.JGT(filter.Const, "", $5, $3)
}
| OP_JLE 'x' ',' label {
bld.JGT(filter.Index, "", $4, 0)
}
| OP_JLE '%' 'x' ',' label {
bld.JGT(filter.Index, "", $5, 0)
}
;
jgt
: OP_JGT '#' number ',' label ',' label {
bld.JGT(filter.Const, $5, $7, $3)
}
| OP_JGT 'x' ',' label ',' label {
bld.JGT(filter.Index, $4, $6, 0)
}
| OP_JGT '%' 'x' ',' label ',' label {
bld.JGT(filter.Index, $5, $7, 0)
}
| OP_JGT '#' number ',' label {
bld.JGT(filter.Const, "", $5, $3)
}
| OP_JGT 'x' ',' label {
bld.JGT(filter.Index, "", $4, 0)
}
| OP_JGT '%' 'x' ',' label {
bld.JGT(filter.Index, "", $5, 0)
}
;
jge
: OP_JGE '#' number ',' label ',' label {
bld.JGE(filter.Const, $5, $7, $3)
}
| OP_JGE 'x' ',' label ',' label {
bld.JGE(filter.Index, $4, $6, 0)
}
| OP_JGE '%' 'x' ',' label ',' label {
bld.JGE(filter.Index, $5, $7, 0)
}
| OP_JGE '#' number ',' label {
bld.JGE(filter.Const, "", $5, $3)
}
| OP_JGE 'x' ',' label {
bld.JGE(filter.Index, "", $4, 0)
}
| OP_JGE '%' 'x' ',' label {
bld.JGE(filter.Index, "", $5, 0)
}
;
jset
: OP_JSET '#' number ',' label ',' label {
bld.JSET(filter.Const, $5, $7, $3)
}
| OP_JSET 'x' ',' label ',' label {
bld.JSET(filter.Index, $4, $6, 0)
}
| OP_JSET '%' 'x' ',' label ',' label {
bld.JSET(filter.Index, $5, $7, 0)
}
| OP_JSET '#' number ',' label {
bld.JSET(filter.Const, "", $5, $3)
}
| OP_JSET 'x' ',' label {
bld.JSET(filter.Index, "", $4, 0)
}
| OP_JSET '%' 'x' ',' label {
bld.JSET(filter.Index, "", $5, 0)
}
;
add
: OP_ADD '#' number {
bld.ADD(filter.Const, $3)
}
| OP_ADD 'x' {
bld.ADD(filter.Index, 0)
}
| OP_ADD '%' 'x' {
bld.ADD(filter.Index, 0)
}
;
sub
: OP_SUB '#' number {
bld.SUB(filter.Const, $3)
}
| OP_SUB 'x' {
bld.SUB(filter.Index, 0)
}
| OP_SUB '%' 'x' {
bld.SUB(filter.Index, 0)
}
;
mul
: OP_MUL '#' number {
bld.MUL(filter.Const, $3)
}
| OP_MUL 'x' {
bld.MUL(filter.Index, 0)
}
| OP_MUL '%' 'x' {
bld.MUL(filter.Index, 0)
}
;
div
: OP_DIV '#' number {
bld.DIV(filter.Const, $3)
}
| OP_DIV 'x' {
bld.DIV(filter.Index, 0)
}
| OP_DIV '%' 'x' {
bld.DIV(filter.Index, 0)
}
;
neg
: OP_NEG {
bld.NEG()
}
;
and
: OP_AND '#' number {
bld.AND(filter.Const, $3)
}
| OP_AND 'x' {
bld.AND(filter.Index, 0)
}
| OP_AND '%' 'x' {
bld.AND(filter.Index, 0)
}
;
or
: OP_OR '#' number {
bld.OR(filter.Const, $3)
}
| OP_OR 'x' {
bld.OR(filter.Index, 0)
}
| OP_OR '%' 'x' {
bld.OR(filter.Index, 0)
}
;
lsh
: OP_LSH '#' number {
bld.LSH(filter.Const, $3)
}
| OP_LSH 'x' {
bld.LSH(filter.Index, 0)
}
| OP_LSH '%' 'x' {
bld.LSH(filter.Index, 0)
}
;
rsh
: OP_RSH '#' number {
bld.RSH(filter.Const, $3)
}
| OP_RSH 'x' {
bld.RSH(filter.Index, 0)
}
| OP_RSH '%' 'x' {
bld.RSH(filter.Index, 0)
}
;
ret
: OP_RET 'a' {
bld.RET(filter.Acc, 0)
}
| OP_RET '%' 'a' {
bld.RET(filter.Acc, 0)
}
| OP_RET 'x' {
bld.RET(filter.Index, 0)
}
| OP_RET '%' 'x' {
bld.RET(filter.Index, 0)
}
| OP_RET '#' number {
bld.RET(filter.Const, $3)
}
;
tax
: OP_TAX {
bld.TAX()
}
;
txa
: OP_TXA {
bld.TXA()
}
;
%%
================================================
FILE: examples/dump/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "log"
import "strconv"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/capture"
import "github.com/ghedo/go.pkt/capture/pcap"
import "github.com/ghedo/go.pkt/capture/file"
import "github.com/ghedo/go.pkt/filter"
import "github.com/ghedo/go.pkt/layers"
func main() {
log.SetFlags(0)
usage := `Usage: dump [options] [<expression>]
Dump the traffic on the network (like tcpdump).
Options:
-c <count> Exit after receiving count packets.
-i <iface> Listen on interface.
-r <file> Read packets from file.
-w <file> Write the raw packets to file.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
var count uint64
if args["-c"] != nil {
count, err = strconv.ParseUint(args["-c"].(string), 10, 64)
if err != nil {
log.Fatalf("Error parsing count: %s", err)
}
}
var src capture.Handle
if args["-i"] != nil {
src, err = pcap.Open(args["-i"].(string))
if err != nil {
log.Fatalf("Error opening iface: %s", err)
}
} else if args["-r"] != nil {
src, err = file.Open(args["-r"].(string))
if err != nil {
log.Fatalf("Error opening file: %s", err)
}
} else {
log.Fatalf("Must select a source (either -i or -r)")
}
defer src.Close()
var dst capture.Handle
if args["-w"] != nil {
dst, err = file.Open(args["-w"].(string))
if err != nil {
log.Fatalf("Error opening file: %s", err)
}
defer dst.Close()
}
err = src.Activate()
if err != nil {
log.Fatalf("Error activating source: %s", err)
}
if args["<expression>"] != nil {
expr := args["<expression>"].(string)
flt, err := filter.Compile(expr, src.LinkType(), false)
if err != nil {
log.Fatalf("Error parsing filter: %s", err)
}
defer flt.Cleanup()
err = src.ApplyFilter(flt)
if err != nil {
log.Fatalf("Error appying filter: %s", err)
}
}
var i uint64
for {
buf, err := src.Capture()
if err != nil {
log.Fatalf("Error: %s", err)
break
}
if buf == nil {
break
}
i++
if dst == nil {
rcv_pkt, err := layers.UnpackAll(buf, src.LinkType())
if err != nil {
log.Printf("Error: %s\n", err)
}
log.Println(rcv_pkt)
} else {
dst.Inject(buf)
}
if count > 0 && i >= count {
break
}
}
}
================================================
FILE: examples/ping/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "log"
import "math/rand"
import "net"
import "time"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/capture/pcap"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/icmpv4"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/network"
import "github.com/ghedo/go.pkt/routing"
func main() {
log.SetFlags(0)
usage := `Usage: ping <addr>
Ping the given IP address.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
addr := args["<addr>"].(string)
addr_ip := net.ParseIP(addr)
timeout := 5 * time.Second
route, err := routing.RouteTo(addr_ip)
if err != nil {
log.Fatalf("Error: %s", err)
}
if route == nil {
log.Println("No route found")
}
c, err := pcap.Open(route.Iface.Name)
if err != nil {
log.Fatalf("Error opening interface: %s", err)
}
defer c.Close()
err = c.Activate()
if err != nil {
log.Fatalf("Error activating source: %s", err)
}
eth_pkt := eth.Make()
eth_pkt.SrcAddr = route.Iface.HardwareAddr
eth_pkt.DstAddr, _ = network.NextHopMAC(c, timeout, route, addr_ip)
ipv4_pkt := ipv4.Make()
ipv4_pkt.SrcAddr, _ = route.GetIfaceIPv4Addr()
ipv4_pkt.DstAddr = addr_ip
icmp_pkt := icmpv4.Make()
icmp_pkt.Type = icmpv4.EchoRequest
icmp_pkt.Seq = 0
icmp_pkt.Id = uint16(rand.Intn(65535))
_, err = network.SendRecv(c, timeout, eth_pkt, ipv4_pkt, icmp_pkt)
if err != nil {
log.Fatal(err)
}
log.Println("ping")
}
================================================
FILE: examples/route/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "log"
import "net"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/routing"
func main() {
log.SetFlags(0)
usage := `Usage: route [options] [<dest_addr>]
Find the best route on the local routing table to the given destination IP
address (or dump all routes).
Options:
-a Dump all routes.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
if args["-a"].(bool) {
routes, err := routing.Routes()
if err != err {
log.Fatalf("Error: %s", err)
}
for _, r := range routes {
log.Println(r)
}
return
}
if args["<dest_addr>"] == nil {
log.Fatalf("Must pass destination address")
}
route, err := routing.RouteTo(net.ParseIP(args["<dest_addr>"].(string)))
if err != nil {
log.Fatalf("Error: %s", err)
}
if route != nil {
log.Println(route)
} else {
log.Println("No route found")
}
}
================================================
FILE: examples/syn_scan/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "fmt"
import "log"
import "math"
import "math/rand"
import "net"
import "time"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/capture/pcap"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/packet/tcp"
import "github.com/ghedo/go.pkt/layers"
import "github.com/ghedo/go.pkt/network"
import "github.com/ghedo/go.pkt/routing"
func main() {
log.SetFlags(0)
usage := `Usage: syn_scan <addr>
Simple TCP port scanner.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
addr := args["<addr>"].(string)
addr_ip := net.ParseIP(addr)
timeout := 1 * time.Second
route, err := routing.RouteTo(addr_ip)
if err != nil {
log.Fatalf("Error: %s", err)
}
if route == nil {
log.Println("No route found")
}
c, err := pcap.Open(route.Iface.Name)
if err != nil {
log.Fatalf("Error opening interface: %s", err)
}
defer c.Close()
err = c.Activate()
if err != nil {
log.Fatalf("Error activating source: %s", err)
}
eth_pkt := eth.Make()
eth_pkt.SrcAddr = route.Iface.HardwareAddr
eth_pkt.DstAddr, _ = network.NextHopMAC(c, timeout, route, addr_ip)
ipv4_pkt := ipv4.Make()
ipv4_pkt.SrcAddr, _ = route.GetIfaceIPv4Addr()
ipv4_pkt.DstAddr = addr_ip
tcp_pkt := tcp.Make()
tcp_pkt.SrcPort = 49152
tcp_pkt.DstPort = 1
tcp_pkt.Flags = tcp.Syn
tcp_pkt.Seq = uint32(rand.Intn(math.MaxUint32))
tcp_pkt.WindowSize = 5840
for port := uint16(1); port < math.MaxUint16; port ++ {
tcp_pkt.DstPort = port
fmt.Printf("Scanning port %.5d: ", port)
pkt, err := network.SendRecv(c, timeout, eth_pkt, ipv4_pkt, tcp_pkt)
if err != nil {
fmt.Printf("%s\n", err)
continue
}
tcp_pkt := layers.FindLayer(pkt, packet.TCP).(*tcp.Packet)
if tcp_pkt.Flags & tcp.Rst == 0 {
fmt.Printf("OPEN\n")
} else if tcp_pkt.Flags & tcp.Syn == 0{
fmt.Printf("CLOSED\n")
}
}
}
================================================
FILE: examples/tracereply/main.go
================================================
package main
import "log"
import "net"
import "strconv"
import "github.com/docopt/docopt-go"
import "github.com/songgao/water"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv6"
import "github.com/ghedo/go.pkt/packet/icmpv6"
import "github.com/ghedo/go.pkt/packet/tcp"
import "github.com/ghedo/go.pkt/packet/udp"
import "github.com/ghedo/go.pkt/layers"
func main() {
log.SetFlags(0)
usage := `Usage: tracereply <netif> <hops> <start_addr>
Reply to ICMPv6 traceroutes.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
netif := args["<netif>"].(string)
ip := net.ParseIP(args["<start_addr>"].(string))
hops, err := strconv.ParseUint(args["<hops>"].(string), 10, 8)
if err != nil {
log.Fatalf("Error parsing hop paramenter: %s", err)
}
config := water.Config{ DeviceType: water.TUN }
config.Name = netif
capture, err := water.New(config)
if err != nil {
log.Fatalf("Error creating capture interface: %s", err)
}
for {
buf := make([]byte, 1500)
buf_len, err := capture.Read(buf)
if err != nil {
log.Fatalf("Error reading packet from interface: %s", err)
}
buf = buf[:buf_len]
pkt, err := layers.UnpackAll(buf, packet.IPv6)
if err != nil {
log.Printf("Error unpacking packet: %s", err)
continue;
}
ip_pkt := layers.FindLayer(pkt, packet.IPv6)
if ip_pkt == nil {
continue;
}
if ip_pkt.Payload() == nil {
continue
}
reply_ip_pkt := ipv6.Make()
reply_ip_pkt.DstAddr = ip_pkt.(*ipv6.Packet).SrcAddr
ttl := ip_pkt.(*ipv6.Packet).HopLimit
reply_pkts := []packet.Packet{ reply_ip_pkt }
switch {
case uint64(ttl) < hops:
[]byte(ip)[len(ip) - 1] = ttl
reply_ip_pkt.SrcAddr = ip
reply_pkt := icmpv6.Make()
reply_pkt.Type = icmpv6.TimeExceeded
reply_pkt.Code = 0
reply_pkts = append(reply_pkts, reply_pkt, ip_pkt, ip_pkt.Payload())
case uint64(ttl) >= hops:
reply_ip_pkt.SrcAddr = ip_pkt.(*ipv6.Packet).DstAddr
switch ip_pkt.Payload().GetType() {
case packet.ICMPv6:
reply_pkt := icmpv6.Make()
reply_pkt.Type = icmpv6.EchoReply
reply_pkt.Code = 0
reply_pkt.Body = ip_pkt.Payload().(*icmpv6.Packet).Body
reply_pkts = append(reply_pkts, reply_pkt)
case packet.TCP:
reply_pkt := tcp.Make()
reply_pkt.SrcPort = ip_pkt.Payload().(*tcp.Packet).DstPort
reply_pkt.DstPort = ip_pkt.Payload().(*tcp.Packet).SrcPort
reply_pkt.Flags = tcp.Rst
reply_pkts = append(reply_pkts, reply_pkt)
case packet.UDP:
reply_pkt := udp.Make()
reply_pkt.SrcPort = ip_pkt.Payload().(*udp.Packet).DstPort
reply_pkt.DstPort = ip_pkt.Payload().(*udp.Packet).SrcPort
reply_pkts = append(reply_pkts, reply_pkt,
ip_pkt.Payload().Payload())
}
}
reply_buf, err := layers.Pack(reply_pkts...)
if err != nil {
log.Printf("Error while packing: %s\n", err)
continue;
}
capture.Write(reply_buf)
}
}
================================================
FILE: examples/traceroute/main.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package main
import "log"
import "math"
import "math/rand"
import "net"
import "time"
import "github.com/docopt/docopt-go"
import "github.com/ghedo/go.pkt/capture/pcap"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/icmpv4"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/packet/raw"
import "github.com/ghedo/go.pkt/packet/tcp"
import "github.com/ghedo/go.pkt/packet/udp"
import "github.com/ghedo/go.pkt/layers"
import "github.com/ghedo/go.pkt/network"
import "github.com/ghedo/go.pkt/routing"
func main() {
log.SetFlags(0)
usage := `Usage: traceroute (--icmp | --udp | --tcp ) <addr>
Find the route to the given IP address using ICMP, UDP or TCP packets.
Options:
--icmp Use ICMP packets.
--udp Use UDP packets.
--tcp Use TCP packets.`
args, err := docopt.Parse(usage, nil, true, "", false)
if err != nil {
log.Fatalf("Invalid arguments: %s", err)
}
addr := args["<addr>"].(string)
addr_ip := net.ParseIP(addr)
timeout := 5 * time.Second
route, err := routing.RouteTo(addr_ip)
if err != nil {
log.Fatalf("Error: %s", err)
}
if route == nil {
log.Println("No route found")
}
c, err := pcap.Open(route.Iface.Name)
if err != nil {
log.Fatalf("Error opening interface: %s", err)
}
defer c.Close()
err = c.Activate()
if err != nil {
log.Fatalf("Error activating source: %s", err)
}
eth_pkt := eth.Make()
eth_pkt.SrcAddr = route.Iface.HardwareAddr
eth_pkt.DstAddr, _ = network.NextHopMAC(c, timeout, route, addr_ip)
ipv4_pkt := ipv4.Make()
ipv4_pkt.SrcAddr, _ = route.GetIfaceIPv4Addr()
ipv4_pkt.DstAddr = addr_ip
ipv4_pkt.Id = uint16(rand.Intn(math.MaxUint16))
ipv4_pkt.TTL = 1
var payload_pkt packet.Packet
if args["--icmp"].(bool) {
icmp_pkt := icmpv4.Make()
icmp_pkt.Type = icmpv4.EchoRequest
icmp_pkt.Id = uint16(rand.Intn(math.MaxUint16))
icmp_pkt.Seq = 1
payload_pkt = icmp_pkt
}
if args["--udp"].(bool) {
udp_pkt := udp.Make()
udp_pkt.SrcPort = 49152
udp_pkt.DstPort = 33434
raw_pkt := raw.Make()
raw_pkt.Data = make([]byte, 40 - udp_pkt.GetLength())
for i := 0; i < len(raw_pkt.Data); i++ {
raw_pkt.Data[i] = byte(0x40 + (i & 0x3f))
}
udp_pkt.SetPayload(raw_pkt)
payload_pkt = udp_pkt
}
if args["--tcp"].(bool) {
tcp_pkt := tcp.Make()
tcp_pkt.SrcPort = 49152
tcp_pkt.DstPort = 80
tcp_pkt.Flags = tcp.Syn | tcp.ECE | tcp.Cwr
tcp_pkt.Seq = uint32(rand.Intn(math.MaxUint32))
tcp_pkt.WindowSize = 5840
raw_pkt := raw.Make()
raw_pkt.Data = make([]byte, 40 - tcp_pkt.GetLength())
for i := 0; i < len(raw_pkt.Data); i++ {
raw_pkt.Data[i] = byte(0x40 + (i & 0x3f))
}
tcp_pkt.SetPayload(raw_pkt)
payload_pkt = tcp_pkt
}
for {
pkt, err := network.SendRecv(c, timeout, eth_pkt, ipv4_pkt, payload_pkt)
if err != nil {
log.Fatal(err)
}
ipv4_rsp := layers.FindLayer(pkt, packet.IPv4).(*ipv4.Packet)
log.Println(ipv4_rsp.SrcAddr)
if ipv4_rsp.SrcAddr.Equal(addr_ip) {
return
}
ipv4_pkt.TTL++
ipv4_pkt.Id++
if ipv4_pkt.TTL > 64 {
return
}
}
}
================================================
FILE: filter/bpf_builder.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package filter
// #include "bpf_filter.h"
import "C"
// A Builder is used to compile a BPF filter from basic BPF instructions.
type Builder struct {
filter *Filter
labels map[string]int
jumps_k map[int]string
jumps_jt map[int]string
jumps_jf map[int]string
}
// Allocate and initialize a new Builder.
func NewBuilder() *Builder {
b := &Builder{}
b.filter = &Filter{}
b.labels = make(map[string]int)
b.jumps_k = make(map[int]string)
b.jumps_jt = make(map[int]string)
b.jumps_jf = make(map[int]string)
return b
}
// Generate and return the Filter associated with the Builder.
func (b *Builder) Build() *Filter {
prog := (*C.struct_bpf_program)(b.filter.Program())
flen := int(C.bpf_get_len(prog))
for i := 0; i < flen; i++ {
insn := C.bpf_get_insn(prog, C.int(i))
if lbl, ok := b.jumps_k[i]; ok {
addr := b.labels[lbl]
if addr != 0 {
insn.k = C.bpf_u_int32(addr - i - 1)
}
}
if lbl, ok := b.jumps_jt[i]; ok {
addr := b.labels[lbl]
if addr != 0 {
insn.jt = C.u_char(addr - i - 1)
}
}
if lbl, ok := b.jumps_jf[i]; ok {
addr := b.labels[lbl]
if addr != 0 {
insn.jf = C.u_char(addr - i - 1)
}
}
}
return b.filter
}
// Define a new label at the next instruction position. Labels are used in jump
// instructions to identify the jump target.
func (b *Builder) Label(name string) *Builder {
b.labels[name] = b.filter.Len()
return b
}
// Append an LD instruction to the filter, which loads a value of size s into
// the accumulator. m represents the addressing mode of the source operand and
// can be IMM (load a constant value), ABS (load packet data at the given fixed
// offset), IND (load packet data at the given relative offset), LEN (load the
// packet length or MEM (load a value from memory at the given offset).
func (b *Builder) LD(s Size, m Mode, val uint32) *Builder {
code := Code(uint16(s) | uint16(m)) | LD
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a LDX (load index) instruction to the filter, which loads a value of
// size s into the index register. m represents the addressing mode of the
// source operand and can be IMM (load a constant value), LEN (load the packet
// length, MEM (load a value from memory at the given offset) or MSH (load the
// length of the IP header).
func (b *Builder) LDX(s Size, m Mode, val uint32) *Builder {
code := Code(uint16(s) | uint16(m) | LDX)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a ST (store) instruction to the filter, which stores the value of the
// accumulator in memory at the given offset.
func (b *Builder) ST(off uint32) *Builder {
b.filter.append_insn(ST, 0, 0, off)
return b
}
// Append a STX (store index) instruction to the filter, which stores the value
// of the index register in memory at the given offset.
func (b *Builder) STX(off uint32) *Builder {
b.filter.append_insn(STX, 0, 0, off)
return b
}
// Append an ADD instruction to the filter, which adds a value to the
// accumulator. s represents the source operand type and can be either Const
// (which adds the supplied value) or Index (which adds the index register
// value).
func (b *Builder) ADD(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x00) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a SUB instruction to the filter, which subtracts a value from the
// accumulator. s represents the source operand type and can be either Const
// (which subtracts the supplied value) or Index (which subtracts the index
// register value).
func (b *Builder) SUB(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x10) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a MUL instruction to the filter, which multiplies a value to the
// accumulator. s represents the source operand type and can be either Const
// (which multiplies the supplied value) or Index (which multiplies the index
// register value).
func (b *Builder) MUL(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x20) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a DIV instruction to the filter, which divides the accumulator by a
// value. s represents the source operand type and can be either Const (which
// divides by the supplied value) or Index (which divides by the index register
// value).
func (b *Builder) DIV(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x30) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append an OR instruction to the filter, which performs the binary "or"
// between the accumulator and a value. s represents the source operand type and
// can be either Const (which uses the supplied value) or Index (which uses the
// index register value).
func (b *Builder) OR(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x40) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append an AND instruction to the filter, which performs the binary "and"
// between the accumulator and a value. s represents the source operand type and
// can be either Const (which uses the supplied value) or Index (which uses the
// index register value).
func (b *Builder) AND(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x50) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append an LSH instruction to the filter, which shifts to the left the
// accumulator register by a value. s represents the source operand type and can
// be either Const (which shifts by the supplied value) or Index (which shifts
// by the index register value).
func (b *Builder) LSH(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x60) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append an RSH instruction to the filter, which shifts to the right the
// accumulator register by a value. s represents the source operand type and can
// be either Const (which shifts by the supplied value) or Index (which shifts
// by the index register value).
func (b *Builder) RSH(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x70) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a NEG instruction to the filter which negates the accumulator.
func (b *Builder) NEG() *Builder {
code := Code(uint16(0x80) | ALU)
b.filter.append_insn(code, 0, 0, 0)
return b
}
// Append a MOD instruction to the filter, which computes the accumulator modulo a
// value. s represents the source operand type and can be either Const (which
// divides by the supplied value) or Index (which divides by the index register
// value).
func (b *Builder) MOD(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0x90) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append an XOR instruction to the filter, which performs the binary "xor"
// between the accumulator and a value. s represents the source operand type and
// can be either Const (which uses the supplied value) or Index (which uses the
// index register value).
func (b *Builder) XOR(s Src, val uint32) *Builder {
code := Code(uint16(s) | uint16(0xa0) | ALU)
b.filter.append_insn(code, 0, 0, val)
return b
}
// Append a JA instruction to the filter, which performs a jump to the given
// label.
func (b *Builder) JA(j string) *Builder {
b.jumps_k[b.filter.Len()] = j
code := Code(uint16(0x00) | JMP)
b.filter.append_insn(code, 0, 0, 0)
return b
}
// Append a JEQ instruction to the filter, which performs a jump to the jt label
// if the accumulator value equals cmp (if s is Const) or the index register (if
// s is Index), otherwise jumps to jf.
func (b *Builder) JEQ(s Src, jt, jf string, cmp uint32) *Builder {
b.jumps_jt[b.filter.Len()] = jt
b.jumps_jf[b.filter.Len()] = jf
code := Code(uint16(s) | uint16(0x10) | JMP)
b.filter.append_insn(code, 0, 0, cmp)
return b
}
// Append a JGT instruction to the filter, which performs a jump to the jt label
// if the accumulator value is greater than cmp (if s is Const) or the index
// register (if s is Index), otherwise jumps to jf.
func (b *Builder) JGT(s Src, jt, jf string, cmp uint32) *Builder {
b.jumps_jt[b.filter.Len()] = jt
b.jumps_jf[b.filter.Len()] = jf
code := Code(uint16(s) | uint16(0x20) | JMP)
b.filter.append_insn(code, 0, 0, cmp)
return b
}
// Append a JGE instruction to the filter, which performs a jump to the jt label
// if the accumulator value is greater than or equals cmp (if s is Const) or the
// index register (if s is Index), otherwise jumps to jf.
func (b *Builder) JGE(s Src, jt, jf string, cmp uint32) *Builder {
b.jumps_jt[b.filter.Len()] = jt
b.jumps_jf[b.filter.Len()] = jf
code := Code(uint16(s) | uint16(0x30) | JMP)
b.filter.append_insn(code, 0, 0, cmp)
return b
}
// Append a JSET instruction to the filter.
func (b *Builder) JSET(s Src, jt, jf string, cmp uint32) *Builder {
b.jumps_jt[b.filter.Len()] = jt
b.jumps_jf[b.filter.Len()] = jf
code := Code(uint16(s) | uint16(0x40) | JMP)
b.filter.append_insn(code, 0, 0, cmp)
return b
}
// Append a RET instruction to the filter, which terminates the filter program
// and specifies the amount of the packet to accept. s represents the source
// operand type and can be either Const (which returns the supplied value) or
// Acc (which returns the accumulator value).
func (b *Builder) RET(s Src, bytes uint32) *Builder {
code := Code(uint16(s) | RET)
b.filter.append_insn(code, 0, 0, bytes)
return b
}
// Append a TAX instruction to the filter. TAX transfers the accumulator value
// into the index register.
func (b *Builder) TAX() *Builder {
code := Code(uint16(0x00) | MISC)
b.filter.append_insn(code, 0, 0, 0)
return b
}
// Append a TXA instruction to the filter. TXA transfers the index register
// value into the accumulator.
func (b *Builder) TXA() *Builder {
code := Code(uint16(0x80) | MISC)
b.filter.append_insn(code, 0, 0, 0)
return b
}
// Append a raw BPF instruction
func (b *Builder) AppendInstruction(code Code, jt, jf uint8, k uint32) *Builder {
b.filter.append_insn(code, jt, jf, k)
return b
}
================================================
FILE: filter/bpf_builder_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package filter_test
import "log"
import "testing"
import "github.com/ghedo/go.pkt/filter"
func TestEmpty(t *testing.T) {
bld := filter.NewBuilder()
flt := bld.Build()
if flt.Len() != 0 {
t.Fatalf("Len mismatch: %d", flt.Len())
}
flt.Cleanup()
}
var test_arp = `{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 1, 0x00000806 },
{ 0x06, 0, 0, 0x00040000 },
{ 0x06, 0, 0, 0x00000000 },`
func TestARP(t *testing.T) {
arp := filter.NewBuilder().
LD(filter.Half, filter.ABS, 12).
JEQ(filter.Const, "", "fail", 0x806).
RET(filter.Const, 0x40000).
Label("fail").
RET(filter.Const, 0x0).
Build()
if arp.String() != test_arp {
t.Fatalf("Program mismatch: %s", arp.String())
}
}
func TestARPcBPF(t *testing.T) {
arp := filter.NewBuilder().
AppendInstruction(40, 0, 0, 12).
AppendInstruction(21, 0, 1, 2054).
AppendInstruction(6, 0, 0, 262144).
AppendInstruction(6, 0, 0, 0).
Build()
if arp.String() != test_arp {
t.Fatalf("Program mismatch: %s", arp.String())
}
}
var test_dns = `{ 0x00, 0, 0, 0x00000014 },
{ 0xb1, 0, 0, 0x00000000 },
{ 0x0c, 0, 0, 0x00000000 },
{ 0x07, 0, 0, 0x00000000 },
{ 0x40, 0, 0, 0x00000000 },
{ 0x15, 0, 7, 0x07657861 },
{ 0x40, 0, 0, 0x00000004 },
{ 0x15, 0, 5, 0x6d706c65 },
{ 0x40, 0, 0, 0x00000008 },
{ 0x15, 0, 3, 0x03636f6d },
{ 0x50, 0, 0, 0x0000000c },
{ 0x15, 0, 1, 0x00000000 },
{ 0x06, 0, 0, 0x00000001 },
{ 0x06, 0, 0, 0x00000000 },`
func TestDNS(t *testing.T) {
dns := filter.NewBuilder().
LD(filter.Word, filter.IMM, 20).
LDX(filter.Byte, filter.MSH, 0).
ADD(filter.Index, 0).
TAX().
Label("lb_0").
LD(filter.Word, filter.IND, 0).
JEQ(filter.Const, "", "lb_1", 0x07657861).
LD(filter.Word, filter.IND, 4).
JEQ(filter.Const, "", "lb_1", 0x6d706c65).
LD(filter.Word, filter.IND, 8).
JEQ(filter.Const, "", "lb_1", 0x03636f6d).
LD(filter.Byte, filter.IND, 12).
JEQ(filter.Const, "", "lb_1", 0x00).
RET(filter.Const, 1).
Label("lb_1").
RET(filter.Const, 0).
Build()
if dns.String() != test_dns {
t.Fatalf("Program mismatch: %s", dns.String())
}
}
func TestALUOps(t *testing.T) {
flt := filter.NewBuilder().
LD(filter.Byte, filter.ABS, 0).
JEQ(filter.Const, "", "fail", 0x0f).
ADD(filter.Const, 1).
JEQ(filter.Const, "", "fail", 0x10).
SUB(filter.Const, 1).
JEQ(filter.Const, "", "fail", 0x0f).
MUL(filter.Const, 2).
JEQ(filter.Const, "", "fail", 0x1e).
DIV(filter.Const, 2).
JEQ(filter.Const, "", "fail", 0x0f).
OR(filter.Const, 0xf0).
JEQ(filter.Const, "", "fail", 0xff).
AND(filter.Const, 0x0f).
JEQ(filter.Const, "", "fail", 0x0f).
LSH(filter.Const, 4).
JEQ(filter.Const, "", "fail", 0xf0).
RSH(filter.Const, 4).
JEQ(filter.Const, "", "fail", 0x0f).
MOD(filter.Const, 0x0d).
JEQ(filter.Const, "", "fail", 0x02).
XOR(filter.Const, 0x03).
JEQ(filter.Const, "", "fail", 0x01).
RET(filter.Const, 0x40000).
Label("fail").
RET(filter.Const, 0x0).
Build()
if !flt.Validate() {
t.Fatalf("Invalid filter: %s", flt.String())
}
if !flt.Match([]byte{0x0f}) {
t.Fatal("Bad Math")
}
}
func ExampleBuilder() {
// Build a filter to match ARP packets on top of Ethernet
flt := filter.NewBuilder().
LD(filter.Half, filter.ABS, 12).
JEQ(filter.Const, "", "fail", 0x806).
RET(filter.Const, 0x40000).
Label("fail").
RET(filter.Const, 0x0).
Build()
if flt.Match([]byte("random data")) {
log.Println("MATCH!!!")
}
}
================================================
FILE: filter/bpf_filter.c
================================================
/*-
* Copyright (c) 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93
*/
#include <stdint.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#include <netinet/in.h>
#ifndef __i386__
#define BPF_ALIGN
#endif
#define EXTRACT_BYTE(p)\
((u_int8_t)\
((u_int8_t)*((u_char *)p)))
#ifndef BPF_ALIGN
#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p))
#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
#else
#define EXTRACT_SHORT(p)\
((u_int16_t)\
((u_int16_t)*((u_char *)p+0)<<8|\
(u_int16_t)*((u_char *)p+1)<<0))
#define EXTRACT_LONG(p)\
((u_int32_t)*((u_char *)p+0)<<24|\
(u_int32_t)*((u_char *)p+1)<<16|\
(u_int32_t)*((u_char *)p+2)<<8|\
(u_int32_t)*((u_char *)p+3)<<0)
#endif
#include "bpf_filter.h"
/*
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
* buflen is the amount of data present
*/
u_int
bpf_filter(const struct bpf_insn *pc, char *p, u_int wirelen, u_int buflen)
{
u_int32_t A = 0, X = 0;
u_int32_t k;
u_int32_t mem[BPF_MEMWORDS];
bzero(mem, sizeof(mem));
if (pc == NULL)
/*
* No filter means accept all.
*/
return ((u_int)-1);
--pc;
while (1) {
++pc;
switch (pc->code) {
default:
abort();
case BPF_RET|BPF_K:
return ((u_int)pc->k);
case BPF_RET|BPF_A:
return ((u_int)A);
case BPF_LD|BPF_W|BPF_ABS:
k = pc->k;
if (k > buflen || sizeof(int32_t) > buflen - k) {
return (0);
}
#ifdef BPF_ALIGN
if (((intptr_t)(p + k) & 3) != 0)
A = EXTRACT_LONG(&p[k]);
else
#endif
A = ntohl(*(int32_t *)(p + k));
continue;
case BPF_LD|BPF_H|BPF_ABS:
k = pc->k;
if (k > buflen || sizeof(int16_t) > buflen - k) {
return (0);
}
A = EXTRACT_SHORT(&p[k]);
continue;
case BPF_LD|BPF_B|BPF_ABS:
k = pc->k;
if (k >= buflen) {
return (0);
}
A = EXTRACT_BYTE(&p[k]);
continue;
case BPF_LD|BPF_W|BPF_LEN:
A = wirelen;
continue;
case BPF_LDX|BPF_W|BPF_LEN:
X = wirelen;
continue;
case BPF_LD|BPF_W|BPF_IND:
k = X + pc->k;
if (pc->k > buflen || X > buflen - pc->k ||
sizeof(int32_t) > buflen - k) {
return (0);
}
#ifdef BPF_ALIGN
if (((intptr_t)(p + k) & 3) != 0)
A = EXTRACT_LONG(&p[k]);
else
#endif
A = ntohl(*(int32_t *)(p + k));
continue;
case BPF_LD|BPF_H|BPF_IND:
k = X + pc->k;
if (X > buflen || pc->k > buflen - X ||
sizeof(int16_t) > buflen - k) {
return (0);
}
A = EXTRACT_SHORT(&p[k]);
continue;
case BPF_LD|BPF_B|BPF_IND:
k = X + pc->k;
if (pc->k >= buflen || X >= buflen - pc->k) {
return (0);
}
A = EXTRACT_BYTE(&p[k]);
continue;
case BPF_LDX|BPF_MSH|BPF_B:
k = pc->k;
if (k >= buflen) {
return (0);
}
X = (p[pc->k] & 0xf) << 2;
continue;
case BPF_LD|BPF_IMM:
A = pc->k;
continue;
case BPF_LDX|BPF_IMM:
X = pc->k;
continue;
case BPF_LD|BPF_MEM:
A = mem[pc->k];
continue;
case BPF_LDX|BPF_MEM:
X = mem[pc->k];
continue;
case BPF_ST:
mem[pc->k] = A;
continue;
case BPF_STX:
mem[pc->k] = X;
continue;
case BPF_JMP|BPF_JA:
pc += pc->k;
continue;
case BPF_JMP|BPF_JGT|BPF_K:
pc += (A > pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGE|BPF_K:
pc += (A >= pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JEQ|BPF_K:
pc += (A == pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JSET|BPF_K:
pc += (A & pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGT|BPF_X:
pc += (A > X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGE|BPF_X:
pc += (A >= X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JEQ|BPF_X:
pc += (A == X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JSET|BPF_X:
pc += (A & X) ? pc->jt : pc->jf;
continue;
case BPF_ALU|BPF_ADD|BPF_X:
A += X;
continue;
case BPF_ALU|BPF_SUB|BPF_X:
A -= X;
continue;
case BPF_ALU|BPF_MUL|BPF_X:
A *= X;
continue;
case BPF_ALU|BPF_DIV|BPF_X:
if (X == 0)
return (0);
A /= X;
continue;
case BPF_ALU|BPF_MOD|BPF_X:
if (X == 0)
return 0;
A %= X;
continue;
case BPF_ALU|BPF_AND|BPF_X:
A &= X;
continue;
case BPF_ALU|BPF_OR|BPF_X:
A |= X;
continue;
case BPF_ALU|BPF_XOR|BPF_X:
A ^= X;
continue;
case BPF_ALU|BPF_LSH|BPF_X:
A <<= X;
continue;
case BPF_ALU|BPF_RSH|BPF_X:
A >>= X;
continue;
case BPF_ALU|BPF_ADD|BPF_K:
A += pc->k;
continue;
case BPF_ALU|BPF_SUB|BPF_K:
A -= pc->k;
continue;
case BPF_ALU|BPF_MUL|BPF_K:
A *= pc->k;
continue;
case BPF_ALU|BPF_DIV|BPF_K:
A /= pc->k;
continue;
case BPF_ALU|BPF_MOD|BPF_K:
A %= pc->k;
continue;
case BPF_ALU|BPF_AND|BPF_K:
A &= pc->k;
continue;
case BPF_ALU|BPF_OR|BPF_K:
A |= pc->k;
continue;
case BPF_ALU|BPF_XOR|BPF_K:
A ^= pc->k;
continue;
case BPF_ALU|BPF_LSH|BPF_K:
A <<= pc->k;
continue;
case BPF_ALU|BPF_RSH|BPF_K:
A >>= pc->k;
continue;
case BPF_ALU|BPF_NEG:
A = -A;
continue;
case BPF_MISC|BPF_TAX:
X = A;
continue;
case BPF_MISC|BPF_TXA:
A = X;
continue;
}
}
}
static const u_short bpf_code_map[] = {
0x10ff, /* 0x00-0x0f: 1111111100001000 */
0x3070, /* 0x10-0x1f: 0000111000001100 */
0x3131, /* 0x20-0x2f: 1000110010001100 */
0x3031, /* 0x30-0x3f: 1000110000001100 */
0x3131, /* 0x40-0x4f: 1000110010001100 */
0x1011, /* 0x50-0x5f: 1000100000001000 */
0x1013, /* 0x60-0x6f: 1100100000001000 */
0x1010, /* 0x70-0x7f: 0000100000001000 */
0x0093, /* 0x80-0x8f: 1100100100000000 */
0x1010, /* 0x90-0x9f: 0000100000001000 */
0x1010, /* 0xa0-0xaf: 0000100000001000 */
0x0002, /* 0xb0-0xbf: 0100000000000000 */
0x0000, /* 0xc0-0xcf: 0000000000000000 */
0x0000, /* 0xd0-0xdf: 0000000000000000 */
0x0000, /* 0xe0-0xef: 0000000000000000 */
0x0000 /* 0xf0-0xff: 0000000000000000 */
};
#define BPF_VALIDATE_CODE(c) \
((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
/*
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
* code. The code must terminate with either an accept or reject.
*/
int
bpf_validate(const struct bpf_insn *f, int len)
{
register int i;
register const struct bpf_insn *p;
/* Do not accept negative length filter. */
if (len < 0)
return (0);
/* An empty filter means accept all. */
if (len == 0)
return (1);
for (i = 0; i < len; ++i) {
p = &f[i];
/*
* Check that the code is valid.
*/
if (!BPF_VALIDATE_CODE(p->code))
return (0);
/*
* Check that that jumps are forward, and within
* the code block.
*/
if (BPF_CLASS(p->code) == BPF_JMP) {
register u_int offset;
if (p->code == (BPF_JMP|BPF_JA))
offset = p->k;
else
offset = p->jt > p->jf ? p->jt : p->jf;
if (offset >= (u_int)(len - i) - 1)
return (0);
continue;
}
/*
* Check that memory operations use valid addresses.
*/
if (p->code == BPF_ST || p->code == BPF_STX ||
p->code == (BPF_LD|BPF_MEM) ||
p->code == (BPF_LDX|BPF_MEM)) {
if (p->k >= BPF_MEMWORDS)
return (0);
continue;
}
/*
* Check for constant division by 0.
*/
if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) ||
p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0)
return (0);
}
return (BPF_CLASS(f[len - 1].code) == BPF_RET);
}
int
bpf_append_insn(struct bpf_program *p, unsigned short code,
unsigned char jt, unsigned char jf, unsigned int k)
{
p->bf_insns = realloc(p->bf_insns, ++p->bf_len*sizeof(struct bpf_insn));
if (p->bf_insns == NULL)
return -1;
p->bf_insns[p->bf_len - 1].code = code;
p->bf_insns[p->bf_len - 1].jt = jt;
p->bf_insns[p->bf_len - 1].jf = jf;
p->bf_insns[p->bf_len - 1].k = k;
return 0;
}
int
bpf_get_len(struct bpf_program *p)
{
return p->bf_len;
}
struct bpf_insn *
bpf_get_insn(struct bpf_program *p, int i)
{
if (i > p->bf_len)
return NULL;
return &p->bf_insns[i];
}
================================================
FILE: filter/bpf_filter.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides an API for compiling and manipulating BPF filters. A filter can be
// either compiled from tcpdump-like expressions, or created from basic BPF
// instructions. Filters can then be either applied to packet sources (see the
// capture package) or directly run against binary data.
package filter
// #include <stdlib.h>
// #include "bpf_filter.h"
import "C"
import "fmt"
import "strings"
import "syscall"
import "unsafe"
type Filter struct {
program C.struct_bpf_program
}
type Code uint16
const (
LD Code = syscall.BPF_LD
LDX = syscall.BPF_LDX
ST = syscall.BPF_ST
STX = syscall.BPF_STX
ALU = syscall.BPF_ALU
JMP = syscall.BPF_JMP
RET = syscall.BPF_RET
MISC = syscall.BPF_MISC
)
type Size uint16
const (
Word Size = syscall.BPF_W
Half = syscall.BPF_H
Byte = syscall.BPF_B
)
type Mode uint16
const (
IMM Mode = syscall.BPF_IMM
ABS = syscall.BPF_ABS
IND = syscall.BPF_IND
MEM = syscall.BPF_MEM
LEN = syscall.BPF_LEN
MSH = syscall.BPF_MSH
)
type Src uint16
const (
Const Src = syscall.BPF_K
Index = syscall.BPF_X
Acc = syscall.BPF_A
)
// Try to match the given buffer against the filter.
func (f *Filter) Match(buf []byte) bool {
cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
blen := C.uint(len(buf))
if C.bpf_filter(f.program.bf_insns, cbuf, blen, blen) > 0 {
return true
}
return false
}
// Run filter on the given buffer and return its result.
func (f *Filter) Filter(buf []byte) uint {
cbuf := (*C.char)(unsafe.Pointer(&buf[0]))
blen := C.uint(len(buf))
rc := C.bpf_filter(f.program.bf_insns, cbuf, blen, blen)
return uint(rc)
}
// Validate the filter. The constraints are that each jump be forward and to a
// valid code. The code must terminate with either an accept or reject.
func (f *Filter) Validate() bool {
if C.bpf_validate(f.program.bf_insns, C.int(f.program.bf_len)) > 0 {
return true
}
return false
}
// Deallocate the filter.
func (f *Filter) Cleanup() {
f.program.bf_len = 0
if f.program.bf_insns != nil {
C.free(unsafe.Pointer(f.program.bf_insns))
f.program.bf_insns = nil
}
}
// Return the number of instructions in the filter.
func (f *Filter) Len() int {
prog := (*C.struct_bpf_program)(f.Program())
flen := C.bpf_get_len(prog)
return int(flen)
}
// Return the compiled BPF program.
func (f *Filter) Program() unsafe.Pointer {
return unsafe.Pointer(&f.program)
}
func (f *Filter) String() string {
var insns []string
prog := (*C.struct_bpf_program)(f.Program())
flen := C.bpf_get_len(prog)
for i := C.int(0); i < flen; i++ {
insn := C.bpf_get_insn(prog, i)
str := fmt.Sprintf(
"{ 0x%.2x, %3d, %3d, 0x%.8x },",
insn.code, insn.jt, insn.jf, insn.k,
)
insns = append(insns, str)
}
return strings.Join(insns, "\n")
}
func (f *Filter) append_insn(code Code, jt, jf uint8, k uint32) {
prog := (*C.struct_bpf_program)(f.Program())
C.bpf_append_insn(
prog, C.ushort(code), C.uchar(jt), C.uchar(jf), C.uint(k),
)
}
================================================
FILE: filter/bpf_filter.h
================================================
/*-
* Copyright (c) 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bpf.h 8.1 (Berkeley) 6/10/93
* @(#)bpf.h 1.34 (LBL) 6/16/96
*
* $FreeBSD$
*/
typedef unsigned int bpf_u_int32; /* cgo is stupid... */
typedef unsigned char u_char; /* oh, so stupid... */
struct bpf_program {
unsigned int bf_len; /* u_int */
struct bpf_insn *bf_insns;
};
/*
* The instruction encodings.
*/
/* instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x18)
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_MOD 0x90
#define BPF_XOR 0xa0
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x08)
#define BPF_K 0x00
#define BPF_X 0x08
/* ret - BPF_K and BPF_X also apply */
#define BPF_RVAL(code) ((code) & 0x18)
#define BPF_A 0x10
/* misc */
#define BPF_MISCOP(code) ((code) & 0xf8)
#define BPF_TAX 0x00
#define BPF_TXA 0x80
/*
* The instruction data structure.
*/
struct bpf_insn {
unsigned short code; /* u_short */
unsigned char jt; /* u_char */
unsigned char jf; /* u_char */
unsigned int k; /* u_int32_t */
};
/*
* Macros for insn array initializers.
*/
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
/*
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
*/
#define BPF_MEMWORDS 16
unsigned int bpf_filter(const struct bpf_insn *pc, char *p,
unsigned int wirelen, unsigned int buflen);
int bpf_validate(const struct bpf_insn *f, int len);
int bpf_append_insn(struct bpf_program *p, unsigned short code,
unsigned char jt, unsigned char jf, unsigned int k);
int bpf_get_len(struct bpf_program *p);
struct bpf_insn *bpf_get_insn(struct bpf_program *p, int i);
================================================
FILE: filter/bpf_filter_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package filter_test
import "log"
import "testing"
import "github.com/ghedo/go.pkt/filter"
import "github.com/ghedo/go.pkt/packet"
var test_eth_arp = []byte{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x4c, 0x72,
0xb9, 0x54, 0xe5, 0x3d, 0xc0, 0xa8, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc1, 0x1b, 0xd0, 0x25,
}
var test_eth_vlan_arp = []byte{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x81, 0x00, 0x00, 0x87, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
0x00, 0x01, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d, 0xc0, 0xa8, 0x01, 0x87,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x1b, 0xd0, 0x25,
}
var test_eth_ipv4_udp = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
0x27, 0x60, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x08, 0xe9, 0x80,
}
var test_eth_ipv4_tcp = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
0x27, 0x5f, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
0x20, 0x00, 0x79, 0x85, 0x00, 0x00,
}
var test_ipv4_tcp_single_byte = []byte{
0x45, 0x00, 0x00, 0x3c, 0xf4, 0x65, 0x40, 0x00, 0x36, 0x06, 0x07, 0xec,
0x6e, 0x34, 0x6d, 0x8c, 0x3d, 0x36, 0x2f, 0x74, 0x98, 0x64, 0x00, 0x50,
0xa4, 0x30, 0x06, 0xd1, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x39, 0x08,
0x90, 0x33, 0x00, 0x00, 0x02, 0x04, 0x05, 0xa0, 0x04, 0x02, 0x08, 0x0a,
0x00, 0x04, 0xf2, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06,
}
func TestMatch(t *testing.T) {
arp, err := filter.Compile("arp", packet.Eth, false)
if err != nil {
t.Fatalf("Error compiling arp")
}
if !arp.Validate() {
t.Fatalf("Invalid filter ARP\n%s", arp)
}
udp, err := filter.Compile("udp", packet.Eth, false)
if err != nil {
t.Fatalf("Error compiling udp")
}
port, err := filter.Compile("port 8338", packet.Eth, false)
if err != nil {
t.Fatalf("Error compiling port")
}
single, err := filter.Compile("tcp[12] != 0xa0", packet.IPv4, false)
if err != nil {
t.Fatalf("Error compiling single")
}
if !arp.Match(test_eth_arp) {
t.Fatalf("ARP mismatch")
}
if arp.Match(test_eth_ipv4_udp) {
t.Fatalf("ARP matched (but it shouldn't have)")
}
if !udp.Match(test_eth_ipv4_udp) {
t.Fatalf("ARP mismatch")
}
if udp.Match(test_eth_ipv4_tcp) {
t.Fatalf("UDP matched (but it shouldn't have)")
}
if !port.Match(test_eth_ipv4_udp) {
t.Fatalf("UDP port mismatch")
}
if !port.Match(test_eth_ipv4_tcp) {
t.Fatalf("TCP port mismatch")
}
if port.Match(test_eth_vlan_arp) {
t.Fatalf("Port matched (but it shouldn't have)")
}
if single.Match(test_ipv4_tcp_single_byte) {
t.Fatalf("Byte matched (but it shouldn't have)")
}
}
func BenchmarkMatch(b *testing.B) {
test_filter, _ := filter.Compile("port 8338", packet.Eth, false)
for n := 0; n < b.N; n++ {
test_filter.Match(test_eth_ipv4_tcp)
}
}
func ExampleFilter() {
// Match UDP or TCP packets on top of Ethernet
flt, err := filter.Compile("udp or tcp", packet.Eth, false)
if err != nil {
log.Fatal(err)
}
if flt.Match([]byte("random data")) {
log.Println("MATCH!!!")
}
}
================================================
FILE: filter/pcap.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package filter
// #cgo LDFLAGS: -lpcap
// #include <stdlib.h>
// #include <pcap.h>
import "C"
import "fmt"
import "unsafe"
import "github.com/ghedo/go.pkt/packet"
// Compile the given tcpdump-like expression to a BPF filter.
func Compile(filter string, link_type packet.Type, optimize bool) (*Filter, error) {
var do_optimize int
if optimize {
do_optimize = 1
} else {
do_optimize = 0
}
f := &Filter{}
filter_str := C.CString(filter)
defer C.free(unsafe.Pointer(filter_str))
pcap_type := link_type.ToLinkType()
err := C.pcap_compile_nopcap(
C.int(0x7fff), C.int(pcap_type),
(*C.struct_bpf_program)(f.Program()),
filter_str, C.int(do_optimize), 0xffffffff,
)
if err < 0 {
return nil, fmt.Errorf("Could not compile filter")
}
return f, nil
}
================================================
FILE: go.mod
================================================
module github.com/ghedo/go.pkt
require (
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/songgao/water v0.0.0-20180420064739-bf1a5d02778f
)
================================================
FILE: go.sum
================================================
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/songgao/water v0.0.0-20180420064739-bf1a5d02778f h1:UExbpoG328zaxx4MhWPRZZpc527IdNUfQ1Z0uejVddc=
github.com/songgao/water v0.0.0-20180420064739-bf1a5d02778f/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
================================================
FILE: layers/layers.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides utility functions for encoding and decoding packets to/from binary
// data. Differently from the basic "packet" interface, this can encode and
// decode complete "stacks" of packets, instead of manipulating single ones.
package layers
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/arp"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/icmpv4"
import "github.com/ghedo/go.pkt/packet/icmpv6"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/packet/ipv6"
import "github.com/ghedo/go.pkt/packet/llc"
import "github.com/ghedo/go.pkt/packet/radiotap"
import "github.com/ghedo/go.pkt/packet/raw"
import "github.com/ghedo/go.pkt/packet/sll"
import "github.com/ghedo/go.pkt/packet/snap"
import "github.com/ghedo/go.pkt/packet/tcp"
import "github.com/ghedo/go.pkt/packet/udp"
import "github.com/ghedo/go.pkt/packet/vlan"
// Compose packets into a chain and update their values (e.g. length, payload
// protocol) accordingly.
func Compose(pkts ...packet.Packet) (packet.Packet, error) {
next_pkt := packet.Packet(nil)
for i := len(pkts) - 1; i >= 0; i-- {
if next_pkt != nil {
err := pkts[i].SetPayload(next_pkt)
if err != nil {
return nil, err
}
}
next_pkt = pkts[i]
}
return pkts[0], nil
}
// Pack packets into their binary form. This will stack the packets before
// encoding them (see the Compose() method) and also calculate the checksums.
func Pack(pkts ...packet.Packet) ([]byte, error) {
var buf packet.Buffer
base_pkt, err := Compose(pkts...)
if err != nil {
return nil, err
}
tot_len := int(base_pkt.GetLength())
buf.Init(make([]byte, tot_len))
for i := len(pkts) - 1; i >= 0; i-- {
cur_pkt := pkts[i]
cur_len := int(cur_pkt.GetLength())
buf.SetOffset(tot_len - cur_len)
buf.NewLayer()
err := cur_pkt.Pack(&buf)
if err != nil {
return nil, err
}
}
buf.SetOffset(0)
return buf.Bytes(), nil
}
// Unpack the given byte slice into the packet list supplied. Note that this
// will not check whether the packet types provided match the raw data. If the
// packet types to be decoded are unknown, UnpackAll() should be used instead.
//
// Note that unpacking is done without copying the input slice, which means that
// if the slice is modifed, it may affect the packets that where unpacked from
// it. If you can't guarantee that the data slice won't change, you'll need to
// copy it and pass the copy to Unpack().
func Unpack(buf []byte, pkts ...packet.Packet) (packet.Packet, error) {
var b packet.Buffer
b.Init(buf)
prev_pkt := packet.Packet(nil)
for _, p := range pkts {
if b.Len() <= 0 {
break
}
b.NewLayer()
err := p.Unpack(&b)
if err != nil {
return nil, err
}
if prev_pkt != nil {
prev_pkt.SetPayload(p)
}
if p.GuessPayloadType() == packet.None {
break
}
prev_pkt = p
}
return pkts[0], nil
}
// Recursively unpack the given byte slice into a packet. The link_type argument
// must specify the type of the first layer in the input data, successive layers
// will be detected automatically.
//
// Note that unpacking is done without copying the input slice, which means that
// if the slice is modifed, it may affect the packets that where unpacked from
// it. If you can't guarantee that the data slice won't change, you'll need to
// copy it and pass the copy to UnpackAll().
func UnpackAll(buf []byte, link_type packet.Type) (packet.Packet, error) {
var b packet.Buffer
b.Init(buf)
first_pkt := packet.Packet(nil)
prev_pkt := packet.Packet(nil)
for link_type != packet.None {
var p packet.Packet
if b.Len() <= 0 {
break
}
switch link_type {
case packet.ARP: p = &arp.Packet{}
case packet.Eth: p = ð.Packet{}
case packet.ICMPv4: p = &icmpv4.Packet{}
case packet.ICMPv6: p = &icmpv6.Packet{}
case packet.IPv4: p = &ipv4.Packet{}
case packet.IPv6: p = &ipv6.Packet{}
case packet.LLC: p = &llc.Packet{}
case packet.RadioTap: p = &radiotap.Packet{}
case packet.SLL: p = &sll.Packet{}
case packet.SNAP: p = &snap.Packet{}
case packet.TCP: p = &tcp.Packet{}
case packet.UDP: p = &udp.Packet{}
case packet.VLAN: p = &vlan.Packet{}
default: p = &raw.Packet{}
}
if p == nil {
break
}
b.NewLayer()
err := p.Unpack(&b)
if err != nil {
return nil, err
}
if prev_pkt != nil {
prev_pkt.SetPayload(p)
} else {
first_pkt = p
}
prev_pkt = p
link_type = p.GuessPayloadType()
}
return first_pkt, nil
}
// Return the first layer of the given type in the packet. If no suitable layer
// is found, return nil.
func FindLayer(p packet.Packet, layer packet.Type) packet.Packet {
switch {
case p == nil:
return nil
case p.GetType() == layer:
return p
default:
return FindLayer(p.Payload(), layer)
}
}
================================================
FILE: layers/layers_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package layers_test
import "bytes"
import "log"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/layers"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/arp"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/packet/raw"
import "github.com/ghedo/go.pkt/packet/udp"
import "github.com/ghedo/go.pkt/packet/tcp"
import "github.com/ghedo/go.pkt/packet/vlan"
var hwsrc_str = "4c:72:b9:54:e5:3d"
var hwdst_str = "00:21:96:6e:f0:70"
var ipsrc_str = "192.168.1.135"
var ipdst_str = "193.27.208.37"
var test_eth_arp = []byte{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x4c, 0x72,
0xb9, 0x54, 0xe5, 0x3d, 0xc0, 0xa8, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc1, 0x1b, 0xd0, 0x25,
}
func TestPackEthArp(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr, _ = net.ParseMAC(hwsrc_str)
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr = net.ParseIP(ipsrc_str)
arp_pkt.ProtoDstAddr = net.ParseIP(ipdst_str)
buf, err := layers.Pack(eth_pkt, arp_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_eth_arp, buf) {
t.Fatalf("Raw packet mismatch: %x", buf)
}
}
func TestUnpackEthArp(t *testing.T) {
_, err := layers.Unpack(test_eth_arp, ð.Packet{}, &arp.Packet{})
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthArp(bn *testing.B) {
var eth_pkt eth.Packet
var arp_pkt arp.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_arp, ð_pkt, &arp_pkt)
}
}
func TestUnpackAllEthArp(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_arp, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
if pkt.Payload().GetType() != packet.ARP {
t.Fatalf("Packet type mismatch, %s", pkt.Payload().GetType())
}
}
func BenchmarkUnpackAllEthArp(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_arp, packet.Eth)
}
}
var test_eth_vlan_arp = []byte{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x81, 0x00, 0x00, 0x87, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04,
0x00, 0x01, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d, 0xc0, 0xa8, 0x01, 0x87,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x1b, 0xd0, 0x25,
}
func TestPackEthVLANArp(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
vlan_pkt := vlan.Make()
vlan_pkt.VLAN = 135
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr, _ = net.ParseMAC(hwsrc_str)
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr = net.ParseIP(ipsrc_str)
arp_pkt.ProtoDstAddr = net.ParseIP(ipdst_str)
buf, err := layers.Pack(eth_pkt, vlan_pkt, arp_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_eth_vlan_arp, buf) {
t.Fatalf("Raw packet mismatch: %x", buf)
}
}
func TestUnpackEthVLANArp(t *testing.T) {
_, err := layers.Unpack(test_eth_arp, ð.Packet{}, &vlan.Packet{}, &arp.Packet{})
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthVLANArp(bn *testing.B) {
var eth_pkt eth.Packet
var vlan_pkt vlan.Packet
var arp_pkt arp.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_vlan_arp, ð_pkt, &vlan_pkt, &arp_pkt)
}
}
func TestUnpackAllEthVLANArp(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_vlan_arp, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.VLAN {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.ARP {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
}
func BenchmarkUnpackAllEthVLANArp(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_vlan_arp, packet.Eth)
}
}
var test_eth_ipv4_udp = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
0x27, 0x60, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x08, 0xe9, 0x80,
}
func TestPackEthIPv4UDP(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC(hwdst_str)
ip4_pkt := ipv4.Make()
ip4_pkt.SrcAddr = net.ParseIP(ipsrc_str)
ip4_pkt.DstAddr = net.ParseIP(ipdst_str)
udp_pkt := udp.Make()
udp_pkt.SrcPort = 41562
udp_pkt.DstPort = 8338
buf, err := layers.Pack(eth_pkt, ip4_pkt, udp_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_eth_ipv4_udp, buf) {
t.Fatalf("Raw packet mismatch: %x", buf)
}
}
func TestUnpackEthUPv4UDP(t *testing.T) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var udp_pkt udp.Packet
_, err := layers.Unpack(test_eth_ipv4_udp, ð_pkt, &ip4_pkt, &udp_pkt)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthUPv4UDP(bn *testing.B) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var udp_pkt udp.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_ipv4_udp, ð_pkt, &ip4_pkt, &udp_pkt)
}
}
func TestUnpackAllEthIPv4UDP(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_ipv4_udp, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.IPv4 {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.UDP {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
}
func BenchmarkUnpackAllEthIPv4UDP(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_ipv4_udp, packet.Eth)
}
}
var test_eth_ipv4_udp_raw = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x42, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11,
0x27, 0x3a, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x2e, 0x07, 0x03, 0x66, 0x64, 0x67, 0x20, 0x61, 0x67,
0x66, 0x68, 0x20, 0x6c, 0x64, 0x66, 0x68, 0x67, 0x6b, 0x20, 0x68, 0x66,
0x64, 0x6b, 0x67, 0x68, 0x20, 0x6b, 0x66, 0x6a, 0x64, 0x68, 0x73, 0x67,
0x20, 0x6b, 0x73, 0x68, 0x66, 0x64, 0x67, 0x6b,
}
func TestPackEthIPv4UDPRaw(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC(hwdst_str)
ip4_pkt := ipv4.Make()
ip4_pkt.SrcAddr = net.ParseIP(ipsrc_str)
ip4_pkt.DstAddr = net.ParseIP(ipdst_str)
udp_pkt := udp.Make()
udp_pkt.SrcPort = 41562
udp_pkt.DstPort = 8338
raw_pkt := raw.Make()
raw_pkt.Data = []byte("fdg agfh ldfhgk hfdkgh kfjdhsg kshfdgk")
data, err := layers.Pack(eth_pkt, ip4_pkt, udp_pkt, raw_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if ip4_pkt.GetLength() != 66 {
t.Fatalf("IPv4 length mismatch: %d", ip4_pkt.GetLength())
}
if udp_pkt.GetLength() != 46 {
t.Fatalf("UDP length mismatch: %d", udp_pkt.GetLength())
}
if !bytes.Equal(test_eth_ipv4_udp_raw, data) {
t.Fatalf("Raw packet mismatch: %x", data)
}
}
func TestUnpackEthUPv4UDPRaw(t *testing.T) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var udp_pkt udp.Packet
var raw_pkt raw.Packet
_, err := layers.Unpack(test_eth_ipv4_udp_raw,
ð_pkt, &ip4_pkt, &udp_pkt, &raw_pkt)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthUPv4UDPRaw(bn *testing.B) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var udp_pkt udp.Packet
var raw_pkt raw.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_ipv4_udp_raw,
ð_pkt, &ip4_pkt, &udp_pkt, &raw_pkt)
}
}
func TestUnpackAllEthIPv4UDPRaw(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_ipv4_udp_raw, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.IPv4 {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.UDP {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.Raw {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
}
func BenchmarkUnpackAllEthIPv4UDPRaw(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_ipv4_udp_raw, packet.Eth)
}
}
var test_eth_ipv4_tcp = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
0x27, 0x5f, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
0x20, 0x00, 0x79, 0x85, 0x00, 0x00,
}
func TestPackEthIPv4TCP(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC(hwdst_str)
ip4_pkt := ipv4.Make()
ip4_pkt.SrcAddr = net.ParseIP(ipsrc_str)
ip4_pkt.DstAddr = net.ParseIP(ipdst_str)
tcp_pkt := tcp.Make()
tcp_pkt.SrcPort = 41562
tcp_pkt.DstPort = 8338
tcp_pkt.Flags = tcp.Syn
tcp_pkt.WindowSize = 8192
buf, err := layers.Pack(eth_pkt, ip4_pkt, tcp_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_eth_ipv4_tcp, buf) {
t.Fatalf("Raw packet mismatch: %x", buf)
}
}
func TestUnpackEthUPv4TCP(t *testing.T) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var tcp_pkt tcp.Packet
_, err := layers.Unpack(test_eth_ipv4_tcp, ð_pkt, &ip4_pkt, &tcp_pkt)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthUPv4TCP(bn *testing.B) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var tcp_pkt tcp.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_ipv4_tcp, ð_pkt, &ip4_pkt, &tcp_pkt)
}
}
func TestUnpackAllEthIPv4TCP(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_ipv4_tcp, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.IPv4 {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.TCP {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
}
func BenchmarkUnpackAllEthIPv4TCP(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_ipv4_tcp, packet.Eth)
}
}
var test_eth_ipv4_tcp_raw = []byte{
0x00, 0x21, 0x96, 0x6e, 0xf0, 0x70, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00, 0x45, 0x00, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
0x27, 0x39, 0xc0, 0xa8, 0x01, 0x87, 0xc1, 0x1b, 0xd0, 0x25, 0xa2, 0x5a,
0x20, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02,
0x20, 0x00, 0x97, 0x2d, 0x00, 0x00, 0x66, 0x64, 0x67, 0x20, 0x61, 0x67,
0x66, 0x68, 0x20, 0x6c, 0x64, 0x66, 0x68, 0x67, 0x6b, 0x20, 0x68, 0x66,
0x64, 0x6b, 0x67, 0x68, 0x20, 0x6b, 0x66, 0x6a, 0x64, 0x68, 0x73, 0x67,
0x20, 0x6b, 0x73, 0x68, 0x66, 0x64, 0x67, 0x6b,
}
func TestPackEthIPv4TCPRaw(t *testing.T) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC(hwsrc_str)
eth_pkt.DstAddr, _ = net.ParseMAC(hwdst_str)
ip4_pkt := ipv4.Make()
ip4_pkt.SrcAddr = net.ParseIP(ipsrc_str)
ip4_pkt.DstAddr = net.ParseIP(ipdst_str)
tcp_pkt := tcp.Make()
tcp_pkt.SrcPort = 41562
tcp_pkt.DstPort = 8338
tcp_pkt.Flags = tcp.Syn
tcp_pkt.WindowSize = 8192
raw_pkt := raw.Make()
raw_pkt.Data = []byte("fdg agfh ldfhgk hfdkgh kfjdhsg kshfdgk")
data, err := layers.Pack(eth_pkt, ip4_pkt, tcp_pkt, raw_pkt)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if ip4_pkt.GetLength() != 78 {
t.Fatalf("IPv4 length mismatch: %d", ip4_pkt.GetLength())
}
if tcp_pkt.GetLength() != 58 {
t.Fatalf("TCP length mismatch: %d", tcp_pkt.GetLength())
}
if !bytes.Equal(test_eth_ipv4_tcp_raw, data) {
t.Fatalf("Raw packet mismatch: %x", data)
}
}
func TestUnpackEthUPv4TCPRaw(t *testing.T) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var tcp_pkt tcp.Packet
var raw_pkt raw.Packet
_, err := layers.Unpack(test_eth_ipv4_tcp_raw,
ð_pkt, &ip4_pkt, &tcp_pkt, &raw_pkt)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
}
func BenchmarkUnpackEthUPv4TCPRaw(bn *testing.B) {
var eth_pkt eth.Packet
var ip4_pkt ipv4.Packet
var tcp_pkt tcp.Packet
var raw_pkt raw.Packet
for n := 0; n < bn.N; n++ {
layers.Unpack(test_eth_ipv4_tcp_raw,
ð_pkt, &ip4_pkt, &tcp_pkt, &raw_pkt)
}
}
func TestUnpackAllEthIPv4TCPRaw(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_ipv4_tcp_raw, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if pkt.GetType() != packet.Eth {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.IPv4 {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.TCP {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
pkt = pkt.Payload()
if pkt.GetType() != packet.Raw {
t.Fatalf("Packet type mismatch, %s", pkt.GetType())
}
}
func BenchmarkUnpackAllEthIPv4TCPRaw(bn *testing.B) {
for n := 0; n < bn.N; n++ {
layers.UnpackAll(test_eth_ipv4_tcp_raw, packet.Eth)
}
}
func TestFindLayer(t *testing.T) {
pkt, err := layers.UnpackAll(test_eth_ipv4_tcp, packet.Eth)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
ipv4_pkt := layers.FindLayer(pkt, packet.IPv4)
if ipv4_pkt == nil || ipv4_pkt.GetType() != packet.IPv4 {
t.Fatalf("Not IPv4: %s", ipv4_pkt)
}
tcp_pkt := layers.FindLayer(pkt, packet.TCP)
if tcp_pkt == nil || tcp_pkt.GetType() != packet.TCP {
t.Fatalf("Not TCP: %s", tcp_pkt)
}
udp_pkt := layers.FindLayer(pkt, packet.UDP)
if udp_pkt != nil {
t.Fatalf("Not nil: %s", udp_pkt)
}
}
func ExamplePack() {
// Create an Ethernet packet
eth_pkt := eth.Make()
eth_pkt.SrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
// Create an ARP packet
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr, _ = net.ParseMAC("4c:72:b9:54:e5:3d")
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr = net.ParseIP("192.168.1.135")
arp_pkt.ProtoDstAddr = net.ParseIP("192.168.1.254")
buf, err := layers.Pack(eth_pkt, arp_pkt)
if err != nil {
log.Fatal(err)
}
// do something with the packet
log.Println(buf)
}
func ExampleUnpack() {
// Create the buf data
buf := []byte("random data")
// Assume Ethernet as datalink layer
pkt, err := layers.UnpackAll(buf, packet.Eth)
if err != nil {
log.Fatal(err)
}
log.Println(pkt)
}
================================================
FILE: network/network.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides utility functions for sending and receiving packets over the
// network. Basically, it hides some of the complexity of using the capture and
// layers packages together.
package network
import "fmt"
import "net"
import "time"
import "github.com/ghedo/go.pkt/capture"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/arp"
import "github.com/ghedo/go.pkt/packet/eth"
import "github.com/ghedo/go.pkt/layers"
import "github.com/ghedo/go.pkt/routing"
// Pack packets into their binary form and inject them in the given capture
// handle.. This will stack the packets before encoding them and also calculate
// the checksums.
func Send(c capture.Handle, pkts ...packet.Packet) error {
if pkts[0].GetType() != c.LinkType() {
return fmt.Errorf("Expected packet type %s, got %s",
pkts[0].GetType(), c.LinkType())
}
buf, err := layers.Pack(pkts...)
if err != nil {
return fmt.Errorf("Could not pack: %s", err)
}
err = c.Inject(buf)
if err != nil {
return fmt.Errorf("Could not inject: %s", err)
}
return nil
}
// Capture a single packet from the given capture handle, unpack it and return
// it. This will block until a packet is received.
func Recv(c capture.Handle) (packet.Packet, error) {
buf, err := c.Capture()
if err != nil {
return nil, fmt.Errorf("Could not capture: %s", err)
}
pkt, err := layers.UnpackAll(buf, c.LinkType())
if err != nil {
return nil, fmt.Errorf("Could not unpack: %s", err)
}
return pkt, nil
}
// Like Send() and Recv() combined. This only returns a suitable answer for the
// sent packets. If t is not zero, this will return if not answer is received
// before t expires.
func SendRecv(c capture.Handle, t time.Duration, pkts ...packet.Packet) (packet.Packet, error) {
err := Send(c, pkts...)
if err != nil {
return nil, err
}
now := time.Now()
for {
pkt, err := Recv(c)
if err != nil {
return nil, err
}
if pkt == nil {
return nil, nil
}
if pkt.Answers(pkts[0]) {
return pkt, nil
}
if int64(t) > 0 &&
int64(time.Since(now)) > int64(t.Nanoseconds()) {
return nil, fmt.Errorf("Timeout")
}
}
return nil, fmt.Errorf("WTF")
}
// Determine the next hop's MAX address to reach the given IP address and route
// by doing an ARP resolution.
func NextHopMAC(c capture.Handle, t time.Duration, r *routing.Route, addr net.IP) (net.HardwareAddr, error) {
eth_pkt := eth.Make()
eth_pkt.SrcAddr = r.Iface.HardwareAddr
eth_pkt.DstAddr, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff")
arp_pkt := arp.Make()
arp_pkt.HWSrcAddr = r.Iface.HardwareAddr
arp_pkt.HWDstAddr, _ = net.ParseMAC("00:00:00:00:00:00")
arp_pkt.ProtoSrcAddr, _ = r.GetIfaceIPv4Addr()
if r.Default {
arp_pkt.ProtoDstAddr = r.Gateway
} else {
arp_pkt.ProtoDstAddr = addr
}
pkt, err := SendRecv(c, t, eth_pkt, arp_pkt)
if err != nil {
return nil, err
}
return pkt.Payload().(*arp.Packet).HWSrcAddr, nil
}
================================================
FILE: packet/arp/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for ARP packets.
package arp
import "net"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/eth"
type Packet struct {
Operation Operation `string:"op"`
HWType uint16
HWAddrLen uint8 `string:"hwlen"`
HWSrcAddr net.HardwareAddr `string:"hwsrc"`
HWDstAddr net.HardwareAddr `string:"hwdst"`
ProtoType eth.EtherType `string:"ptype"`
ProtoAddrLen uint8 `string:"plen"`
ProtoSrcAddr net.IP `string:"psrc"`
ProtoDstAddr net.IP `string:"pdst"`
}
type Operation uint16
const (
Request Operation = 1
Reply = 2
)
func Make() *Packet {
return &Packet {
Operation: Request,
HWType: 1,
HWAddrLen: 6,
ProtoType: eth.IPv4,
ProtoAddrLen: 4,
}
}
func (p *Packet) GetType() packet.Type {
return packet.ARP
}
func (p *Packet) GetLength() uint16 {
return 8 + uint16(p.HWAddrLen) * 2 + uint16(p.ProtoAddrLen) * 2
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.ARP {
return false
}
if p.Operation == Reply && other.(*Packet).Operation == Request &&
p.ProtoSrcAddr.Equal(other.(*Packet).ProtoDstAddr) {
return true
}
return false
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.WriteN(p.HWType)
buf.WriteN(p.ProtoType)
buf.WriteN(p.HWAddrLen)
buf.WriteN(p.ProtoAddrLen)
buf.WriteN(p.Operation)
buf.Write(p.HWSrcAddr[len(p.HWSrcAddr) - int(p.HWAddrLen):])
buf.Write(p.ProtoSrcAddr[len(p.ProtoSrcAddr) - int(p.ProtoAddrLen):])
buf.Write(p.HWDstAddr[len(p.HWDstAddr) - int(p.HWAddrLen):])
buf.Write(p.ProtoDstAddr[len(p.ProtoDstAddr) - int(p.ProtoAddrLen):])
return nil
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
buf.ReadN(&p.HWType)
buf.ReadN(&p.ProtoType)
buf.ReadN(&p.HWAddrLen)
buf.ReadN(&p.ProtoAddrLen)
buf.ReadN(&p.Operation)
p.HWSrcAddr = net.HardwareAddr(buf.Next(int(p.HWAddrLen)))
p.ProtoSrcAddr = net.IP(buf.Next(int(p.ProtoAddrLen)))
p.HWDstAddr = net.HardwareAddr(buf.Next(int(p.HWAddrLen)))
p.ProtoDstAddr = net.IP(buf.Next(int(p.ProtoAddrLen)))
return nil
}
func (p *Packet) Payload() packet.Packet {
return nil
}
func (p *Packet) GuessPayloadType() packet.Type {
return packet.None
}
func (p *Packet) SetPayload(pl packet.Packet) error {
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
func (o Operation) String() string {
switch o {
case Request:
return "request"
case Reply:
return "reply"
default:
return "invalid"
}
}
================================================
FILE: packet/arp/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package arp_test
import "bytes"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/arp"
import "github.com/ghedo/go.pkt/packet/eth"
var test_simple = []byte{
0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x4C, 0x72, 0xB9, 0x54,
0xE5, 0x3D, 0xC0, 0xA8, 0x01, 0x87, 0x1F, 0x92, 0x2B, 0x56, 0xED, 0x77,
0x1C, 0x3C, 0x09, 0xBF,
}
var hwsrc_str = "4c:72:b9:54:e5:3d"
var hwdst_str = "1f:92:2b:56:ed:77"
var ipsrc_str = "192.168.1.135"
var ipdst_str = "28.60.9.191"
func MakeTestSimple() *arp.Packet {
hwsrc, _ := net.ParseMAC(hwsrc_str)
hwdst, _ := net.ParseMAC(hwdst_str)
ipsrc := net.ParseIP(ipsrc_str)
ipdst := net.ParseIP(ipdst_str)
return &arp.Packet{
Operation: arp.Request,
HWType: 1,
HWAddrLen: 6,
HWSrcAddr: hwsrc,
HWDstAddr: hwdst,
ProtoType: eth.IPv4,
ProtoAddrLen: 4,
ProtoSrcAddr: ipsrc,
ProtoDstAddr: ipdst,
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p arp.Packet
cmp := MakeTestSimple()
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p arp.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
================================================
FILE: packet/buffer.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package packet
import "encoding/binary"
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// It's based on the bytes.Buffer code provided by the standard library, but
// implements additional convenience methods.
//
// This is used internally to provide packet encoding and decoding, and should
// not be used directly.
type Buffer struct {
buf []byte
off int
layer_off int
}
// Initialize the buffer with the given slice.
func (b *Buffer) Init(buf []byte) {
b.buf = buf
b.off = 0
b.layer_off = 0
}
// Return the unread portion of the buffer as slice.
func (b *Buffer) Bytes() []byte {
return b.buf[b.off:]
}
// Return the whole buffer as slice.
func (b *Buffer) Buffer() []byte {
return b.buf
}
// Return the number of bytes of the unread portion of the buffer.
func (b *Buffer) Len() int {
return len(b.buf) - b.off
}
// Manually set the buffer offset to off.
func (b *Buffer) SetOffset(off int) {
b.off = off
}
// Point the layer starting offset to the current buffer offset.
func (b *Buffer) NewLayer() {
b.layer_off = len(b.buf) - b.Len()
}
// Return the buffer of the current layer as slice.
func (b *Buffer) LayerBytes() []byte {
return b.buf[b.layer_off:]
}
// Return the length of the current decoded layer.
func (b *Buffer) LayerLen() int {
return b.off - b.layer_off
}
// Append the contents of p to the buffer.
func (b *Buffer) Write(p []byte) (n int, err error) {
n = copy(b.buf[b.off:], p)
b.off += n
return
}
// Append the value of data to the buffer in network byter order.
func (b *Buffer) WriteN(data interface{}) error {
return binary.Write(b, binary.BigEndian, data)
}
// Append the value of data to the buffer in little endian byter order.
func (b *Buffer) WriteL(data interface{}) error {
return binary.Write(b, binary.LittleEndian, data)
}
// Write data in network byte order to the specified offset relative to the
// start of the current layer.
func (b *Buffer) PutUint16N(off int, data uint16) {
binary.BigEndian.PutUint16(b.buf[b.layer_off + off:], data)
}
// Read the next len(p) bytes from the buffer or until the buffer is drained.
func (b *Buffer) Read(p []byte) (n int, err error) {
n = copy(p, b.buf[b.off:])
b.off += n
return
}
// Read structured data from the buffer in network byte order.
func (p *Buffer) ReadN(data interface{}) error {
return binary.Read(p, binary.BigEndian, data)
}
// Read structured data from the buffer in little endian byte order.
func (p *Buffer) ReadL(data interface{}) error {
return binary.Read(p, binary.LittleEndian, data)
}
// Read aligned structured data from the buffer in little endian byte order.
func (p *Buffer) ReadLAligned(data interface{}, width uintptr) error {
p.off = ((((p.off) + ((int(width)) - 1)) & (^((int(width)) - 1))) - p.off)
return binary.Read(p, binary.LittleEndian, data)
}
// Return a slice containing the next n bytes from the buffer, advancing the
// buffer as if the bytes had been returned by Read
func (b *Buffer) Next(n int) []byte {
m := b.Len()
if n > m {
n = m
}
data := b.buf[b.off : b.off+n]
b.off += n
return data
}
================================================
FILE: packet/eth/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for Ethernet (both EthernetII and 802.3)
// packets.
package eth
import "fmt"
import "net"
import "github.com/ghedo/go.pkt/packet"
type Packet struct {
DstAddr net.HardwareAddr `string:"dst"`
SrcAddr net.HardwareAddr `string:"src"`
Type EtherType
Length uint16 `cmp:"skip"`
pkt_payload packet.Packet `cmp:"skip" string:"skip"`
}
type EtherType uint16
const (
None EtherType = 0x0000
ARP = 0x0806
IPv4 = 0x0800
IPv6 = 0x86dd
LLC = 0x0001 /* pseudo ethertype */
LLDP = 0x088cc
QinQ = 0x88a8
TRILL = 0x22f3
VLAN = 0x8100
WoL = 0x0842
)
func Make() *Packet {
return &Packet{
DstAddr: make([]byte, 6),
SrcAddr: make([]byte, 6),
Length: 14,
}
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.Eth {
return false
}
if p.Type != other.(*Packet).Type {
return false
}
if p.Payload() != nil {
return p.Payload().Answers(other.Payload())
}
return true
}
func (p *Packet) GetType() packet.Type {
return packet.Eth
}
func (p *Packet) GetLength() uint16 {
if p.pkt_payload != nil {
return p.pkt_payload.GetLength() + 14
}
return 14
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.Write(p.DstAddr)
buf.Write(p.SrcAddr)
if p.Type != LLC {
buf.WriteN(p.Type)
} else {
buf.WriteN(p.Length)
}
return nil
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
p.DstAddr = net.HardwareAddr(buf.Next(6))
p.SrcAddr = net.HardwareAddr(buf.Next(6))
buf.ReadN(&p.Type)
if p.Type < 0x0600 {
p.Length = uint16(p.Type)
p.Type = LLC
}
return nil
}
func (p *Packet) Payload() packet.Packet {
return p.pkt_payload
}
func (p *Packet) GuessPayloadType() packet.Type {
return EtherTypeToType(p.Type)
}
func (p *Packet) SetPayload(pl packet.Packet) error {
p.pkt_payload = pl
p.Type = TypeToEtherType(pl.GetType())
if p.Type < 0x0600 {
p.Length = p.GetLength()
}
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
var ethertype_to_type_map = map[EtherType]packet.Type{
None: packet.None,
ARP: packet.ARP,
IPv4: packet.IPv4,
IPv6: packet.IPv6,
LLC: packet.LLC,
LLDP: packet.LLDP,
VLAN: packet.VLAN,
QinQ: packet.VLAN,
TRILL: packet.TRILL,
WoL: packet.WoL,
}
// Create a new Type from the given EtherType.
func EtherTypeToType(ethertype EtherType) packet.Type {
for e, t := range ethertype_to_type_map {
if e == ethertype {
return t
}
}
return packet.Raw
}
// Convert the Type to the corresponding EtherType.
func TypeToEtherType(pkttype packet.Type) EtherType {
/* Hack to avoid non-determinism due to map iteration ordering */
if pkttype == packet.VLAN {
return VLAN
}
for e, t := range ethertype_to_type_map {
if t == pkttype {
return e
}
}
return None
}
func (t EtherType) String() string {
switch t {
case ARP: return "ARP"
case IPv4: return "IPv4"
case IPv6: return "IPv6"
case LLC: return "LLC"
case LLDP: return "LLDP"
case None: return "None"
case QinQ: return "QinQ"
case TRILL: return "TRILL"
case VLAN: return "VLAN"
case WoL: return "WoL"
default: return fmt.Sprintf("0x%x", uint16(t))
}
}
================================================
FILE: packet/eth/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package eth_test
import "bytes"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/eth"
var hwsrc_str = "4c:72:b9:54:e5:3d"
var hwdst_str = "1f:92:2b:56:ed:77"
var test_simple = []byte{
0x1f, 0x92, 0x2b, 0x56, 0xed, 0x77, 0x4c, 0x72, 0xb9, 0x54, 0xe5, 0x3d,
0x08, 0x00,
}
func MakeTestSimple() *eth.Packet {
hwsrc, _ := net.ParseMAC(hwsrc_str)
hwdst, _ := net.ParseMAC(hwdst_str)
return ð.Packet{
SrcAddr: hwsrc,
DstAddr: hwdst,
Type: eth.IPv4,
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p eth.Packet
cmp := MakeTestSimple()
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p eth.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
================================================
FILE: packet/icmpv4/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for ICMPv4 packets.
package icmpv4
import "fmt"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv4"
type Packet struct {
Type Type
Code Code
Checksum uint16 `string:"sum"`
Id uint16
Seq uint16
pkt_payload packet.Packet `cmp:"skip" string:"skip"`
}
type Type uint8
type Code uint8
const (
EchoReply Type = iota
Reserved1
Reserved2
DstUnreachable
SrcQuench
RedirectMsg
Reserved3
Reserved4
EchoRequest
RouterAdv
RouterSol
TimeExceeded
ParamProblem
Timestamp
TimestampReply
InfoRequest
InfoReply
AddrMaskRequest
AddrMaskReply
)
func Make() *Packet {
return &Packet{
Type: EchoRequest,
}
}
func (p *Packet) GetType() packet.Type {
return packet.ICMPv4
}
func (p *Packet) GetLength() uint16 {
if p.pkt_payload != nil {
return p.pkt_payload.GetLength() + 8
}
return 8
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.ICMPv4 {
return false
}
if (other.(*Packet).Type == EchoRequest && p.Type == EchoReply) ||
(other.(*Packet).Type == Timestamp && p.Type == TimestampReply) ||
(other.(*Packet).Type == InfoRequest && p.Type == InfoReply) ||
(other.(*Packet).Type == AddrMaskRequest && p.Type == AddrMaskReply) {
return (other.(*Packet).Seq == p.Seq) &&
(other.(*Packet).Id == p.Id)
}
return false
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.WriteN(byte(p.Type))
buf.WriteN(byte(p.Code))
buf.WriteN(uint16(0x0000))
buf.WriteN(p.Id)
buf.WriteN(p.Seq)
p.Checksum = ipv4.CalculateChecksum(buf.LayerBytes(), 0)
buf.PutUint16N(2, p.Checksum)
return nil
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
buf.ReadN(&p.Type)
buf.ReadN(&p.Code)
buf.ReadN(&p.Checksum)
buf.ReadN(&p.Id)
buf.ReadN(&p.Seq)
/* TODO: data */
return nil
}
func (p *Packet) Payload() packet.Packet {
return p.pkt_payload
}
func (p *Packet) GuessPayloadType() packet.Type {
switch p.Type {
case DstUnreachable, SrcQuench, RedirectMsg, TimeExceeded, ParamProblem:
return packet.IPv4
}
return packet.None
}
func (p *Packet) SetPayload(pl packet.Packet) error {
switch p.Type {
case DstUnreachable, SrcQuench, RedirectMsg, TimeExceeded, ParamProblem:
p.pkt_payload = pl
}
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
func (t Type) String() string {
switch t {
case EchoReply: return "echo-reply"
case DstUnreachable: return "dst-unreach"
case SrcQuench: return "src-quench"
case RedirectMsg: return "redirect"
case EchoRequest: return "echo-request"
case RouterAdv: return "router-adv"
case RouterSol: return "router-sol"
case TimeExceeded: return "time-exceeded"
case ParamProblem: return "param-problem"
case Timestamp: return "timestamp-request"
case TimestampReply: return "timestamp-reply"
case InfoRequest: return "info-request"
case InfoReply: return "info-reply"
case AddrMaskRequest: return "addr-mask-request"
case AddrMaskReply: return "addr-mask-reply"
default: return "unknown"
}
}
func (c Code) String() string {
if c != 0 {
return fmt.Sprintf("%x", uint8(c))
}
return ""
}
================================================
FILE: packet/icmpv4/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package icmpv4_test
import "bytes"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/icmpv4"
var test_simple = []byte{
0x08, 0x00, 0xf7, 0xd2, 0x00, 0x0f, 0x00, 0x1e,
}
func MakeTestSimple() *icmpv4.Packet {
return &icmpv4.Packet{
Type: icmpv4.EchoRequest,
Code: 0,
Id: 15,
Seq: 30,
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p icmpv4.Packet
cmp := MakeTestSimple()
cmp.Checksum = 0xf7d2
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p icmpv4.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
================================================
FILE: packet/icmpv6/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for ICMPv6 packets.
package icmpv6
import "fmt"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv4"
type Packet struct {
Type Type
Code Code
Checksum uint16 `string:"sum"`
csum_seed uint32 `cmp:"skip" string:"skip"`
Body uint32 `cmp:"skip" string:"skip"`
pkt_payload packet.Packet `cmp:"skip" string:"skip"`
}
type Type uint8
type Code uint8
const (
DstUnreachable Type = 1
PacketTooBig = 2
TimeExceeded = 3
ParamProblem = 4
Private1 = 100
Private2 = 101
Reserved1 = 127
EchoRequest = 128
EchoReply = 129
/* TODO: more types */
)
func Make() *Packet {
return &Packet{
Type: EchoRequest,
}
}
func (p *Packet) GetType() packet.Type {
return packet.ICMPv6
}
func (p *Packet) GetLength() uint16 {
if p.pkt_payload != nil {
return p.pkt_payload.GetLength() + 8
}
return 8
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.ICMPv6 {
return false
}
if other.(*Packet).Type == EchoRequest && p.Type == EchoReply {
return true
}
return false
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.WriteN(byte(p.Type))
buf.WriteN(byte(p.Code))
buf.WriteN(uint16(0x00))
buf.WriteN(p.Body)
if p.csum_seed != 0 {
p.Checksum = ipv4.CalculateChecksum(buf.LayerBytes(), p.csum_seed)
buf.PutUint16N(2, p.Checksum)
}
return nil
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
buf.ReadN(&p.Type)
buf.ReadN(&p.Code)
buf.ReadN(&p.Checksum)
/* TODO: data */
buf.ReadN(&p.Body)
return nil
}
func (p *Packet) Payload() packet.Packet {
return p.pkt_payload
}
func (p *Packet) GuessPayloadType() packet.Type {
switch p.Type {
case DstUnreachable, PacketTooBig, TimeExceeded, ParamProblem:
return packet.IPv6
}
return packet.None
}
func (p *Packet) SetPayload(pl packet.Packet) error {
switch p.Type {
case DstUnreachable, PacketTooBig, TimeExceeded, ParamProblem:
p.pkt_payload = pl
}
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
p.csum_seed = csum
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
func (t Type) String() string {
switch t {
case DstUnreachable: return "dst-unreach"
case PacketTooBig: return "too-big"
case TimeExceeded: return "timeout"
case ParamProblem: return "param-problem"
case EchoRequest: return "echo-request"
case EchoReply: return "echo-reply"
default: return "unknown"
}
}
func (c Code) String() string {
if c != 0 {
return fmt.Sprintf("%x", uint8(c))
}
return ""
}
================================================
FILE: packet/icmpv6/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package icmpv6_test
import "bytes"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/icmpv6"
import "github.com/ghedo/go.pkt/packet/ipv6"
var test_simple = []byte{
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
func MakeTestSimple() *icmpv6.Packet {
return &icmpv6.Packet{
Type: icmpv6.EchoRequest,
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p icmpv6.Packet
cmp := MakeTestSimple()
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p icmpv6.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
var test_with_ipv6 = []byte{
0x80, 0x00, 0x5b, 0xed, 0x00, 0x00, 0x00, 0x00,
}
var ipsrc_str = "fe80::4e72:b9ff:fe54:e53d"
var ipdst_str = "2001:4860:4860::8888"
func TestPackWithIPv6(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_with_ipv6)))
ip6 := ipv6.Make()
ip6.SrcAddr = net.ParseIP(ipsrc_str)
ip6.DstAddr = net.ParseIP(ipdst_str)
icmp6 := MakeTestSimple()
ip6.SetPayload(icmp6)
err := icmp6.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_with_ipv6, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func TestUnpackWithIPv6(t *testing.T) {
var p icmpv6.Packet
cmp := MakeTestSimple()
cmp.Checksum = 0x5bed
var b packet.Buffer
b.Init(test_with_ipv6)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
================================================
FILE: packet/ipv4/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for IPv4 packets.
package ipv4
import "fmt"
import "net"
import "strings"
import "github.com/ghedo/go.pkt/packet"
type Packet struct {
Version uint8
IHL uint8
TOS uint8 `cmp:"skip"`
Length uint16 `cmp:"skip"`
Id uint16
Flags Flags
FragOff uint16
TTL uint8 `cmp:"skip"`
Protocol Protocol `string:"proto"`
Checksum uint16 `cmp:"skip" string:"sum"`
SrcAddr net.IP `string:"src"`
DstAddr net.IP `string:"dst"`
pkt_payload packet.Packet `cmp:"skip" string:"skip"`
}
type Flags uint8
const (
Evil Flags = 1 << 2 /* RFC3514 */
DontFragment = 1 << 1
MoreFragments = 1 << 0
)
type Protocol uint8
const (
None Protocol = 0x00
GRE = 0x2F
ICMPv4 = 0x01
ICMPv6 = 0x3A
IGMP = 0x02
IPSecAH = 0x33
IPSecESP = 0x32
IPv6 = 0x29
ISIS = 0x7C
L2TP = 0x73
OSPF = 0x59
SCTP = 0x84
TCP = 0x06
UDP = 0x11
UDPLite = 0x88
)
func Make() *Packet {
return &Packet{
Version: 4,
IHL: 5,
Length: 20,
TTL: 64,
Id: 1,
}
}
func (p *Packet) GetType() packet.Type {
return packet.IPv4
}
func (p *Packet) GetLength() uint16 {
if p.pkt_payload != nil {
return p.pkt_payload.GetLength() + 20
}
return 20
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.IPv4 {
return false
}
if p.Payload() != nil &&
p.Payload().GetType() == packet.ICMPv4 &&
p.Payload().Payload() != nil {
return p.Payload().Payload().Equals(other)
}
if !p.SrcAddr.Equal(other.(*Packet).DstAddr) ||
p.Protocol != other.(*Packet).Protocol {
return false
}
if p.Payload() != nil {
return p.Payload().Answers(other.Payload())
}
return true
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.WriteN((p.Version << 4) | p.IHL)
buf.WriteN(p.TOS)
buf.WriteN(p.Length)
buf.WriteN(p.Id)
buf.WriteN((uint16(p.Flags) << 13) | p.FragOff)
buf.WriteN(p.TTL)
buf.WriteN(p.Protocol)
buf.WriteN(uint16(0x00))
buf.Write(p.SrcAddr.To4())
buf.Write(p.DstAddr.To4())
p.checksum(buf.LayerBytes()[:20])
buf.PutUint16N(10, p.Checksum)
return nil
}
func (p *Packet) checksum(raw_bytes []byte) {
var csum uint32
for i := 0; i < len(raw_bytes) - 1; i += 2 {
csum += uint32(raw_bytes[i]) << 8
csum += uint32(raw_bytes[i + 1])
}
p.Checksum = ^uint16((csum >> 16) + csum)
}
func (p *Packet) pseudo_checksum() uint32 {
var csum uint32
csum += (uint32(p.SrcAddr.To4()[0]) + uint32(p.SrcAddr.To4()[2])) << 8
csum += uint32(p.SrcAddr.To4()[1]) + uint32(p.SrcAddr.To4()[3])
csum += (uint32(p.DstAddr.To4()[0]) + uint32(p.DstAddr.To4()[2])) << 8
csum += uint32(p.DstAddr.To4()[1]) + uint32(p.DstAddr.To4()[3])
csum += uint32(p.Protocol)
csum += uint32(p.pkt_payload.GetLength())
return csum
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
var versihl uint8
buf.ReadN(&versihl)
p.Version = versihl >> 4
p.IHL = versihl & 0x0F
buf.ReadN(&p.TOS)
buf.ReadN(&p.Length)
buf.ReadN(&p.Id)
var flagsfrag uint16
buf.ReadN(&flagsfrag)
p.Flags = Flags(flagsfrag >> 13)
p.FragOff = flagsfrag & 0x1FFF
buf.ReadN(&p.TTL)
buf.ReadN(&p.Protocol)
buf.ReadN(&p.Checksum)
p.SrcAddr = net.IP(buf.Next(4))
p.DstAddr = net.IP(buf.Next(4))
/* TODO: Options */
return nil
}
func (p *Packet) Payload() packet.Packet {
return p.pkt_payload
}
func (p *Packet) GuessPayloadType() packet.Type {
return ProtocolToType(p.Protocol)
}
func (p *Packet) SetPayload(pl packet.Packet) error {
p.pkt_payload = pl
p.Protocol = TypeToProtocol(pl.GetType())
p.Length = p.GetLength()
pl.InitChecksum(p.pseudo_checksum())
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
func (f Flags) String() string {
var flags []string
if f & Evil != 0 {
flags = append(flags, "evil")
}
if f & DontFragment != 0 {
flags = append(flags, "dont-fragment")
}
if f & MoreFragments != 0 {
flags = append(flags, "more-fragments")
}
return strings.Join(flags, "|")
}
func CalculateChecksum(raw_bytes []byte, csum uint32) uint16 {
length := len(raw_bytes) - 1
for i := 0; i < length; i += 2 {
csum += uint32(raw_bytes[i]) << 8
csum += uint32(raw_bytes[i + 1])
}
csum = (csum >> 16) + (csum & 0xffff)
return ^uint16(csum + (csum >> 16))
}
var ipv4proto_to_type_map = map[Protocol]packet.Type{
None: packet.None,
GRE: packet.GRE,
ICMPv4: packet.ICMPv4,
ICMPv6: packet.ICMPv6,
IGMP: packet.IGMP,
IPSecAH: packet.IPSec,
IPSecESP: packet.IPSec,
IPv6: packet.IPv6,
UDP: packet.UDP,
ISIS: packet.ISIS,
L2TP: packet.L2TP,
OSPF: packet.OSPF,
SCTP: packet.SCTP,
UDPLite: packet.UDPLite,
TCP: packet.TCP,
}
// Create a new Type from the given IP protocol ID.
func ProtocolToType(proto Protocol) packet.Type {
for p, t := range ipv4proto_to_type_map {
if p == proto {
return t
}
}
return packet.Raw
}
// Convert the Type to the corresponding IP protocol ID.
func TypeToProtocol(pkttype packet.Type) Protocol {
for p, t := range ipv4proto_to_type_map {
if t == pkttype {
return p
}
}
return None
}
func (p Protocol) String() string {
switch p {
case GRE: return "GRE"
case ICMPv4: return "ICMPv4"
case ICMPv6: return "ICMPv6"
case IGMP: return "IGMP"
case IPSecAH: return "IPSecAH"
case IPSecESP: return "IPSecESP"
case IPv6: return "IPv6"
case UDP: return "UDP"
case ISIS: return "ISIS"
case L2TP: return "L2TP"
case OSPF: return "OSPF"
case SCTP: return "SCTP"
case UDPLite: return "UDPLite"
case TCP: return "TCP"
default: return fmt.Sprintf("0x%x", uint16(p))
}
}
================================================
FILE: packet/ipv4/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ipv4_test
import "bytes"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv4"
var test_simple = []byte{
0x45, 0x03, 0x00, 0x14, 0x00, 0x0f, 0x40, 0x00, 0x64, 0x06, 0x48, 0x97,
0xc0, 0xa8, 0x01, 0x87, 0x08, 0x08, 0x04, 0x04,
}
var ipsrc_str = "192.168.1.135"
var ipdst_str = "8.8.4.4"
func MakeTestSimple() *ipv4.Packet {
return &ipv4.Packet{
Version: 4,
IHL: 5,
Length: 20,
TOS: 3,
Id: 15,
TTL: 100,
Flags: ipv4.DontFragment,
Protocol: ipv4.TCP,
SrcAddr: net.ParseIP(ipsrc_str),
DstAddr: net.ParseIP(ipdst_str),
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p ipv4.Packet
cmp := MakeTestSimple()
cmp.Checksum = 0x4897
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p ipv4.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
================================================
FILE: packet/ipv6/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Provides encoding and decoding for IPv6 packets.
package ipv6
import "encoding/binary"
import "net"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv4"
type Packet struct {
Version uint8
Class uint8
Label uint32
Length uint16 `string:"len"`
NextHdr ipv4.Protocol `string:"next"`
HopLimit uint8 `cmp:"skip" string:"hop"`
SrcAddr net.IP `string:"src"`
DstAddr net.IP `string:"dst"`
pkt_payload packet.Packet `cmp:"skip" string:"skip"`
}
type Flags uint8
func Make() *Packet {
return &Packet{
Version: 6,
HopLimit: 64,
}
}
func (p *Packet) GetType() packet.Type {
return packet.IPv6
}
func (p *Packet) GetLength() uint16 {
if p.pkt_payload != nil {
return p.pkt_payload.GetLength() + 40
}
return 40
}
func (p *Packet) Equals(other packet.Packet) bool {
return packet.Compare(p, other)
}
func (p *Packet) Answers(other packet.Packet) bool {
if other == nil || other.GetType() != packet.IPv6 {
return false
}
/* TODO: check link-local broadcast addresses */
if !p.DstAddr.Equal(other.(*Packet).SrcAddr) {
return false
}
/* TODO: check ICMPv6 errors */
if p.Payload() != nil {
return p.Payload().Answers(other.Payload())
}
return true
}
func (p *Packet) Pack(buf *packet.Buffer) error {
buf.WriteN(uint8(p.Version << 4 | (p.Class >> 4)))
buf.WriteN(p.Class << 4 | uint8(p.Label >> 16))
buf.WriteN(uint16(p.Label))
buf.WriteN(p.Length)
buf.WriteN(p.NextHdr)
buf.WriteN(p.HopLimit)
buf.Write(p.SrcAddr.To16())
buf.Write(p.DstAddr.To16())
return nil
}
func (p *Packet) pseudo_checksum() uint32 {
var csum uint32
for i := 0; i < 16; i += 2 {
csum += uint32(p.SrcAddr.To16()[i]) << 8
csum += uint32(p.SrcAddr.To16()[i + 1])
csum += uint32(p.DstAddr.To16()[i]) << 8
csum += uint32(p.DstAddr.To16()[i + 1])
}
csum += uint32(p.Length)
csum += uint32(p.NextHdr)
return csum
}
func (p *Packet) Unpack(buf *packet.Buffer) error {
var versclass uint8
buf.ReadN(&versclass)
p.Version = versclass >> 4
p.Class =
uint8((binary.BigEndian.Uint16(buf.LayerBytes()[0:2]) >> 4) & 0x00FF)
p.Label =
binary.BigEndian.Uint32(buf.LayerBytes()[0:4]) & 0x000FFFFF
buf.Next(3)
buf.ReadN(&p.Length)
buf.ReadN(&p.NextHdr)
buf.ReadN(&p.HopLimit)
p.SrcAddr = net.IP(buf.Next(16))
p.DstAddr = net.IP(buf.Next(16))
/* TODO: Options */
return nil
}
func (p *Packet) Payload() packet.Packet {
return p.pkt_payload
}
func (p *Packet) GuessPayloadType() packet.Type {
return ipv4.ProtocolToType(p.NextHdr)
}
func (p *Packet) SetPayload(pl packet.Packet) error {
p.pkt_payload = pl
p.NextHdr = ipv4.TypeToProtocol(pl.GetType())
p.Length = pl.GetLength()
pl.InitChecksum(p.pseudo_checksum())
return nil
}
func (p *Packet) InitChecksum(csum uint32) {
}
func (p *Packet) String() string {
return packet.Stringify(p)
}
================================================
FILE: packet/ipv6/pkt_test.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ipv6_test
import "bytes"
import "net"
import "testing"
import "github.com/ghedo/go.pkt/packet"
import "github.com/ghedo/go.pkt/packet/ipv4"
import "github.com/ghedo/go.pkt/packet/ipv6"
var test_simple = []byte{
0x63, 0x0d, 0x5b, 0x0a, 0x00, 0x08, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4e, 0x72, 0xb9, 0xff, 0xfe, 0x54, 0xe5, 0x3d,
0x07, 0x9a, 0x19, 0xb9, 0x11, 0x15, 0xed, 0x67, 0x99, 0xf5, 0xf0, 0x7a,
0x66, 0x87, 0x5b, 0x0f,
}
var ipsrc_str = "fe80::4e72:b9ff:fe54:e53d"
var ipdst_str = "79a:19b9:1115:ed67:99f5:f07a:6687:5b0f"
func MakeTestSimple() *ipv6.Packet {
return &ipv6.Packet{
Version: 6,
Class: 48,
Label: 875274,
Length: 8,
NextHdr: ipv4.UDP,
HopLimit: 64,
SrcAddr: net.ParseIP(ipsrc_str),
DstAddr: net.ParseIP(ipdst_str),
}
}
func TestPack(t *testing.T) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
err := p.Pack(&b)
if err != nil {
t.Fatalf("Error packing: %s", err)
}
if !bytes.Equal(test_simple, b.Buffer()) {
t.Fatalf("Raw packet mismatch: %x", b.Buffer())
}
}
func BenchmarkPack(bn *testing.B) {
var b packet.Buffer
b.Init(make([]byte, len(test_simple)))
p := MakeTestSimple()
for n := 0; n < bn.N; n++ {
p.Pack(&b)
}
}
func TestUnpack(t *testing.T) {
var p ipv6.Packet
cmp := MakeTestSimple()
var b packet.Buffer
b.Init(test_simple)
err := p.Unpack(&b)
if err != nil {
t.Fatalf("Error unpacking: %s", err)
}
if !p.Equals(cmp) {
t.Fatalf("Packet mismatch:\n%s\n%s", &p, cmp)
}
}
func BenchmarkUnpack(bn *testing.B) {
var p ipv6.Packet
var b packet.Buffer
for n := 0; n < bn.N; n++ {
b.Init(test_simple)
p.Unpack(&b)
}
}
================================================
FILE: packet/llc/pkt.go
================================================
/*
* Network packet analysis framework.
*
* Copyright (c) 2014, Alessandro Ghedini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the foll
gitextract_y_3guso3/
├── .travis.yml
├── COPYING
├── README.md
├── capture/
│ ├── capture.go
│ ├── file/
│ │ ├── capture.go
│ │ ├── capture_test.go
│ │ └── capture_test.pcap
│ └── pcap/
│ ├── capture.go
│ └── capture_test.go
├── examples/
│ ├── arp/
│ │ └── main.go
│ ├── bpf_asm/
│ │ ├── Makefile
│ │ ├── bpf_asm.l
│ │ └── bpf_asm.y
│ ├── dump/
│ │ └── main.go
│ ├── ping/
│ │ └── main.go
│ ├── route/
│ │ └── main.go
│ ├── syn_scan/
│ │ └── main.go
│ ├── tracereply/
│ │ └── main.go
│ └── traceroute/
│ └── main.go
├── filter/
│ ├── bpf_builder.go
│ ├── bpf_builder_test.go
│ ├── bpf_filter.c
│ ├── bpf_filter.go
│ ├── bpf_filter.h
│ ├── bpf_filter_test.go
│ └── pcap.go
├── go.mod
├── go.sum
├── layers/
│ ├── layers.go
│ └── layers_test.go
├── network/
│ └── network.go
├── packet/
│ ├── arp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── buffer.go
│ ├── eth/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── icmpv4/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── icmpv6/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── ipv4/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── ipv6/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── llc/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── packet.go
│ ├── radiotap/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── raw/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── sll/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── snap/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── tcp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ ├── udp/
│ │ ├── pkt.go
│ │ └── pkt_test.go
│ └── vlan/
│ ├── pkt.go
│ └── pkt_test.go
└── routing/
├── routing.go
└── routing_linux.go
SYMBOL INDEX (622 symbols across 54 files)
FILE: capture/capture.go
type Handle (line 38) | type Handle interface
FILE: capture/file/capture.go
type Handle (line 44) | type Handle struct
method LinkType (line 144) | func (h *Handle) LinkType() packet.Type {
method SetMTU (line 149) | func (h *Handle) SetMTU(mtu int) error {
method SetPromiscMode (line 154) | func (h *Handle) SetPromiscMode(promisc bool) error {
method SetMonitorMode (line 159) | func (h *Handle) SetMonitorMode(monitor bool) error {
method ApplyFilter (line 165) | func (h *Handle) ApplyFilter(filter *filter.Filter) error {
method Activate (line 177) | func (h *Handle) Activate() error {
method Capture (line 184) | func (h *Handle) Capture() ([]byte, error) {
method Inject (line 221) | func (h *Handle) Inject(buf []byte) error {
method Close (line 243) | func (h *Handle) Close() {
function Open (line 59) | func Open(file_name string) (*Handle, error) {
function create_file (line 115) | func create_file(file_name string) (*os.File, error) {
function open_file (line 133) | func open_file(file_name string) (*os.File, error) {
FILE: capture/file/capture_test.go
function TestCapture (line 39) | func TestCapture(t *testing.T) {
function TestCaptureFilter (line 65) | func TestCaptureFilter(t *testing.T) {
function TestInject (line 102) | func TestInject(t *testing.T) {
function ExampleCapture (line 139) | func ExampleCapture() {
function ExampleInject (line 170) | func ExampleInject() {
FILE: capture/pcap/capture.go
type Handle (line 46) | type Handle struct
method LinkType (line 74) | func (h *Handle) LinkType() packet.Type {
method SetMTU (line 78) | func (h *Handle) SetMTU(mtu int) error {
method SetPromiscMode (line 88) | func (h *Handle) SetPromiscMode(promisc bool) error {
method SetMonitorMode (line 107) | func (h *Handle) SetMonitorMode(monitor bool) error {
method ApplyFilter (line 126) | func (h *Handle) ApplyFilter(filter *filter.Filter) error {
method Activate (line 148) | func (h *Handle) Activate() error {
method Capture (line 159) | func (h *Handle) Capture() ([]byte, error) {
method Inject (line 187) | func (h *Handle) Inject(buf []byte) error {
method Close (line 200) | func (h *Handle) Close() {
method get_error (line 204) | func (h *Handle) get_error() error {
function Open (line 53) | func Open(dev_name string) (*Handle, error) {
FILE: capture/pcap/capture_test.go
function ExampleCapture (line 37) | func ExampleCapture() {
function ExampleInject (line 64) | func ExampleInject() {
FILE: examples/arp/main.go
function main (line 46) | func main() {
FILE: examples/dump/main.go
function main (line 44) | func main() {
FILE: examples/ping/main.go
function main (line 49) | func main() {
FILE: examples/route/main.go
function main (line 40) | func main() {
FILE: examples/syn_scan/main.go
function main (line 53) | func main() {
FILE: examples/tracereply/main.go
function main (line 18) | func main() {
FILE: examples/traceroute/main.go
function main (line 55) | func main() {
FILE: filter/bpf_builder.go
type Builder (line 37) | type Builder struct
method Build (line 60) | func (b *Builder) Build() *Filter {
method Label (line 94) | func (b *Builder) Label(name string) *Builder {
method LD (line 104) | func (b *Builder) LD(s Size, m Mode, val uint32) *Builder {
method LDX (line 115) | func (b *Builder) LDX(s Size, m Mode, val uint32) *Builder {
method ST (line 123) | func (b *Builder) ST(off uint32) *Builder {
method STX (line 130) | func (b *Builder) STX(off uint32) *Builder {
method ADD (line 139) | func (b *Builder) ADD(s Src, val uint32) *Builder {
method SUB (line 149) | func (b *Builder) SUB(s Src, val uint32) *Builder {
method MUL (line 159) | func (b *Builder) MUL(s Src, val uint32) *Builder {
method DIV (line 169) | func (b *Builder) DIV(s Src, val uint32) *Builder {
method OR (line 179) | func (b *Builder) OR(s Src, val uint32) *Builder {
method AND (line 189) | func (b *Builder) AND(s Src, val uint32) *Builder {
method LSH (line 199) | func (b *Builder) LSH(s Src, val uint32) *Builder {
method RSH (line 209) | func (b *Builder) RSH(s Src, val uint32) *Builder {
method NEG (line 216) | func (b *Builder) NEG() *Builder {
method MOD (line 226) | func (b *Builder) MOD(s Src, val uint32) *Builder {
method XOR (line 236) | func (b *Builder) XOR(s Src, val uint32) *Builder {
method JA (line 244) | func (b *Builder) JA(j string) *Builder {
method JEQ (line 255) | func (b *Builder) JEQ(s Src, jt, jf string, cmp uint32) *Builder {
method JGT (line 267) | func (b *Builder) JGT(s Src, jt, jf string, cmp uint32) *Builder {
method JGE (line 279) | func (b *Builder) JGE(s Src, jt, jf string, cmp uint32) *Builder {
method JSET (line 289) | func (b *Builder) JSET(s Src, jt, jf string, cmp uint32) *Builder {
method RET (line 302) | func (b *Builder) RET(s Src, bytes uint32) *Builder {
method TAX (line 310) | func (b *Builder) TAX() *Builder {
method TXA (line 318) | func (b *Builder) TXA() *Builder {
method AppendInstruction (line 325) | func (b *Builder) AppendInstruction(code Code, jt, jf uint8, k uint32)...
function NewBuilder (line 47) | func NewBuilder() *Builder {
FILE: filter/bpf_builder_test.go
function TestEmpty (line 38) | func TestEmpty(t *testing.T) {
function TestARP (line 53) | func TestARP(t *testing.T) {
function TestARPcBPF (line 67) | func TestARPcBPF(t *testing.T) {
function TestDNS (line 95) | func TestDNS(t *testing.T) {
function TestALUOps (line 121) | func TestALUOps(t *testing.T) {
function ExampleBuilder (line 159) | func ExampleBuilder() {
FILE: filter/bpf_filter.c
function u_int (line 76) | u_int
function bpf_validate (line 366) | int
function bpf_append_insn (line 422) | int
function bpf_get_len (line 438) | int
type bpf_insn (line 444) | struct bpf_insn
type bpf_program (line 445) | struct bpf_program
FILE: filter/bpf_filter.go
type Filter (line 46) | type Filter struct
method Match (line 91) | func (f *Filter) Match(buf []byte) bool {
method Filter (line 103) | func (f *Filter) Filter(buf []byte) uint {
method Validate (line 113) | func (f *Filter) Validate() bool {
method Cleanup (line 122) | func (f *Filter) Cleanup() {
method Len (line 132) | func (f *Filter) Len() int {
method Program (line 139) | func (f *Filter) Program() unsafe.Pointer {
method String (line 143) | func (f *Filter) String() string {
method append_insn (line 163) | func (f *Filter) append_insn(code Code, jt, jf uint8, k uint32) {
type Code (line 50) | type Code
constant LD (line 53) | LD Code = syscall.BPF_LD
constant LDX (line 54) | LDX = syscall.BPF_LDX
constant ST (line 55) | ST = syscall.BPF_ST
constant STX (line 56) | STX = syscall.BPF_STX
constant ALU (line 57) | ALU = syscall.BPF_ALU
constant JMP (line 58) | JMP = syscall.BPF_JMP
constant RET (line 59) | RET = syscall.BPF_RET
constant MISC (line 60) | MISC = syscall.BPF_MISC
type Size (line 63) | type Size
constant Word (line 66) | Word Size = syscall.BPF_W
constant Half (line 67) | Half = syscall.BPF_H
constant Byte (line 68) | Byte = syscall.BPF_B
type Mode (line 71) | type Mode
constant IMM (line 74) | IMM Mode = syscall.BPF_IMM
constant ABS (line 75) | ABS = syscall.BPF_ABS
constant IND (line 76) | IND = syscall.BPF_IND
constant MEM (line 77) | MEM = syscall.BPF_MEM
constant LEN (line 78) | LEN = syscall.BPF_LEN
constant MSH (line 79) | MSH = syscall.BPF_MSH
type Src (line 82) | type Src
constant Const (line 85) | Const Src = syscall.BPF_K
constant Index (line 86) | Index = syscall.BPF_X
constant Acc (line 87) | Acc = syscall.BPF_A
FILE: filter/bpf_filter.h
type bpf_u_int32 (line 40) | typedef unsigned int bpf_u_int32;
type u_char (line 41) | typedef unsigned char u_char;
type bpf_program (line 43) | struct bpf_program {
type bpf_insn (line 110) | struct bpf_insn {
type bpf_insn (line 128) | struct bpf_insn
type bpf_insn (line 131) | struct bpf_insn
type bpf_program (line 133) | struct bpf_program
type bpf_program (line 136) | struct bpf_program
type bpf_insn (line 138) | struct bpf_insn
type bpf_program (line 138) | struct bpf_program
FILE: filter/bpf_filter_test.go
function TestMatch (line 76) | func TestMatch(t *testing.T) {
function BenchmarkMatch (line 134) | func BenchmarkMatch(b *testing.B) {
function ExampleFilter (line 142) | func ExampleFilter() {
FILE: filter/pcap.go
function Compile (line 44) | func Compile(filter string, link_type packet.Type, optimize bool) (*Filt...
FILE: layers/layers.go
function Compose (line 55) | func Compose(pkts ...packet.Packet) (packet.Packet, error) {
function Pack (line 74) | func Pack(pkts ...packet.Packet) ([]byte, error) {
function Unpack (line 112) | func Unpack(buf []byte, pkts ...packet.Packet) (packet.Packet, error) {
function UnpackAll (line 153) | func UnpackAll(buf []byte, link_type packet.Type) (packet.Packet, error) {
function FindLayer (line 210) | func FindLayer(p packet.Packet, layer packet.Type) packet.Packet {
FILE: layers/layers_test.go
function TestPackEthArp (line 61) | func TestPackEthArp(t *testing.T) {
function TestUnpackEthArp (line 82) | func TestUnpackEthArp(t *testing.T) {
function BenchmarkUnpackEthArp (line 89) | func BenchmarkUnpackEthArp(bn *testing.B) {
function TestUnpackAllEthArp (line 98) | func TestUnpackAllEthArp(t *testing.T) {
function BenchmarkUnpackAllEthArp (line 113) | func BenchmarkUnpackAllEthArp(bn *testing.B) {
function TestPackEthVLANArp (line 126) | func TestPackEthVLANArp(t *testing.T) {
function TestUnpackEthVLANArp (line 150) | func TestUnpackEthVLANArp(t *testing.T) {
function BenchmarkUnpackEthVLANArp (line 157) | func BenchmarkUnpackEthVLANArp(bn *testing.B) {
function TestUnpackAllEthVLANArp (line 167) | func TestUnpackAllEthVLANArp(t *testing.T) {
function BenchmarkUnpackAllEthVLANArp (line 188) | func BenchmarkUnpackAllEthVLANArp(bn *testing.B) {
function TestPackEthIPv4UDP (line 201) | func TestPackEthIPv4UDP(t *testing.T) {
function TestUnpackEthUPv4UDP (line 224) | func TestUnpackEthUPv4UDP(t *testing.T) {
function BenchmarkUnpackEthUPv4UDP (line 235) | func BenchmarkUnpackEthUPv4UDP(bn *testing.B) {
function TestUnpackAllEthIPv4UDP (line 245) | func TestUnpackAllEthIPv4UDP(t *testing.T) {
function BenchmarkUnpackAllEthIPv4UDP (line 266) | func BenchmarkUnpackAllEthIPv4UDP(bn *testing.B) {
function TestPackEthIPv4UDPRaw (line 282) | func TestPackEthIPv4UDPRaw(t *testing.T) {
function TestUnpackEthUPv4UDPRaw (line 316) | func TestUnpackEthUPv4UDPRaw(t *testing.T) {
function BenchmarkUnpackEthUPv4UDPRaw (line 329) | func BenchmarkUnpackEthUPv4UDPRaw(bn *testing.B) {
function TestUnpackAllEthIPv4UDPRaw (line 341) | func TestUnpackAllEthIPv4UDPRaw(t *testing.T) {
function BenchmarkUnpackAllEthIPv4UDPRaw (line 367) | func BenchmarkUnpackAllEthIPv4UDPRaw(bn *testing.B) {
function TestPackEthIPv4TCP (line 381) | func TestPackEthIPv4TCP(t *testing.T) {
function TestUnpackEthUPv4TCP (line 406) | func TestUnpackEthUPv4TCP(t *testing.T) {
function BenchmarkUnpackEthUPv4TCP (line 417) | func BenchmarkUnpackEthUPv4TCP(bn *testing.B) {
function TestUnpackAllEthIPv4TCP (line 427) | func TestUnpackAllEthIPv4TCP(t *testing.T) {
function BenchmarkUnpackAllEthIPv4TCP (line 448) | func BenchmarkUnpackAllEthIPv4TCP(bn *testing.B) {
function TestPackEthIPv4TCPRaw (line 465) | func TestPackEthIPv4TCPRaw(t *testing.T) {
function TestUnpackEthUPv4TCPRaw (line 501) | func TestUnpackEthUPv4TCPRaw(t *testing.T) {
function BenchmarkUnpackEthUPv4TCPRaw (line 514) | func BenchmarkUnpackEthUPv4TCPRaw(bn *testing.B) {
function TestUnpackAllEthIPv4TCPRaw (line 526) | func TestUnpackAllEthIPv4TCPRaw(t *testing.T) {
function BenchmarkUnpackAllEthIPv4TCPRaw (line 552) | func BenchmarkUnpackAllEthIPv4TCPRaw(bn *testing.B) {
function TestFindLayer (line 558) | func TestFindLayer(t *testing.T) {
function ExamplePack (line 580) | func ExamplePack() {
function ExampleUnpack (line 602) | func ExampleUnpack() {
FILE: network/network.go
function Send (line 50) | func Send(c capture.Handle, pkts ...packet.Packet) error {
function Recv (line 71) | func Recv(c capture.Handle) (packet.Packet, error) {
function SendRecv (line 88) | func SendRecv(c capture.Handle, t time.Duration, pkts ...packet.Packet) ...
function NextHopMAC (line 121) | func NextHopMAC(c capture.Handle, t time.Duration, r *routing.Route, add...
FILE: packet/arp/pkt.go
type Packet (line 39) | type Packet struct
method GetType (line 72) | func (p *Packet) GetType() packet.Type {
method GetLength (line 76) | func (p *Packet) GetLength() uint16 {
method Equals (line 80) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 84) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 97) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 115) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 133) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 137) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 141) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 145) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 148) | func (p *Packet) String() string {
type Operation (line 53) | type Operation
method String (line 152) | func (o Operation) String() string {
constant Request (line 56) | Request Operation = 1
constant Reply (line 57) | Reply = 2
function Make (line 60) | func Make() *Packet {
FILE: packet/arp/pkt_test.go
function MakeTestSimple (line 52) | func MakeTestSimple() *arp.Packet {
function TestPack (line 73) | func TestPack(t *testing.T) {
function BenchmarkPack (line 89) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 100) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 118) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/buffer.go
type Buffer (line 41) | type Buffer struct
method Init (line 48) | func (b *Buffer) Init(buf []byte) {
method Bytes (line 55) | func (b *Buffer) Bytes() []byte {
method Buffer (line 60) | func (b *Buffer) Buffer() []byte {
method Len (line 65) | func (b *Buffer) Len() int {
method SetOffset (line 70) | func (b *Buffer) SetOffset(off int) {
method NewLayer (line 75) | func (b *Buffer) NewLayer() {
method LayerBytes (line 80) | func (b *Buffer) LayerBytes() []byte {
method LayerLen (line 85) | func (b *Buffer) LayerLen() int {
method Write (line 90) | func (b *Buffer) Write(p []byte) (n int, err error) {
method WriteN (line 97) | func (b *Buffer) WriteN(data interface{}) error {
method WriteL (line 102) | func (b *Buffer) WriteL(data interface{}) error {
method PutUint16N (line 108) | func (b *Buffer) PutUint16N(off int, data uint16) {
method Read (line 113) | func (b *Buffer) Read(p []byte) (n int, err error) {
method ReadN (line 120) | func (p *Buffer) ReadN(data interface{}) error {
method ReadL (line 125) | func (p *Buffer) ReadL(data interface{}) error {
method ReadLAligned (line 130) | func (p *Buffer) ReadLAligned(data interface{}, width uintptr) error {
method Next (line 138) | func (b *Buffer) Next(n int) []byte {
FILE: packet/eth/pkt.go
type Packet (line 40) | type Packet struct
method Equals (line 71) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 75) | func (p *Packet) Answers(other packet.Packet) bool {
method GetType (line 91) | func (p *Packet) GetType() packet.Type {
method GetLength (line 95) | func (p *Packet) GetLength() uint16 {
method Pack (line 103) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 116) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 130) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 134) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 138) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 149) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 152) | func (p *Packet) String() string {
type EtherType (line 48) | type EtherType
method String (line 196) | func (t EtherType) String() string {
constant None (line 51) | None EtherType = 0x0000
constant ARP (line 52) | ARP = 0x0806
constant IPv4 (line 53) | IPv4 = 0x0800
constant IPv6 (line 54) | IPv6 = 0x86dd
constant LLC (line 55) | LLC = 0x0001
constant LLDP (line 56) | LLDP = 0x088cc
constant QinQ (line 57) | QinQ = 0x88a8
constant TRILL (line 58) | TRILL = 0x22f3
constant VLAN (line 59) | VLAN = 0x8100
constant WoL (line 60) | WoL = 0x0842
function Make (line 63) | func Make() *Packet {
function EtherTypeToType (line 170) | func EtherTypeToType(ethertype EtherType) packet.Type {
function TypeToEtherType (line 181) | func TypeToEtherType(pkttype packet.Type) EtherType {
FILE: packet/eth/pkt_test.go
function MakeTestSimple (line 48) | func MakeTestSimple() *eth.Packet {
function TestPack (line 59) | func TestPack(t *testing.T) {
function BenchmarkPack (line 75) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 86) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 104) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/icmpv4/pkt.go
type Packet (line 39) | type Packet struct
method GetType (line 79) | func (p *Packet) GetType() packet.Type {
method GetLength (line 83) | func (p *Packet) GetLength() uint16 {
method Equals (line 91) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 95) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 111) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 124) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 136) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 140) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 149) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 158) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 161) | func (p *Packet) String() string {
type Type (line 48) | type Type
method String (line 165) | func (t Type) String() string {
type Code (line 49) | type Code
method String (line 186) | func (c Code) String() string {
constant EchoReply (line 52) | EchoReply Type = iota
constant Reserved1 (line 53) | Reserved1
constant Reserved2 (line 54) | Reserved2
constant DstUnreachable (line 55) | DstUnreachable
constant SrcQuench (line 56) | SrcQuench
constant RedirectMsg (line 57) | RedirectMsg
constant Reserved3 (line 58) | Reserved3
constant Reserved4 (line 59) | Reserved4
constant EchoRequest (line 60) | EchoRequest
constant RouterAdv (line 61) | RouterAdv
constant RouterSol (line 62) | RouterSol
constant TimeExceeded (line 63) | TimeExceeded
constant ParamProblem (line 64) | ParamProblem
constant Timestamp (line 65) | Timestamp
constant TimestampReply (line 66) | TimestampReply
constant InfoRequest (line 67) | InfoRequest
constant InfoReply (line 68) | InfoReply
constant AddrMaskRequest (line 69) | AddrMaskRequest
constant AddrMaskReply (line 70) | AddrMaskReply
function Make (line 73) | func Make() *Packet {
FILE: packet/icmpv4/pkt_test.go
function MakeTestSimple (line 43) | func MakeTestSimple() *icmpv4.Packet {
function TestPack (line 52) | func TestPack(t *testing.T) {
function BenchmarkPack (line 68) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 79) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 98) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/icmpv6/pkt.go
type Packet (line 39) | type Packet struct
method GetType (line 70) | func (p *Packet) GetType() packet.Type {
method GetLength (line 74) | func (p *Packet) GetLength() uint16 {
method Equals (line 82) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 86) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 98) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 112) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 123) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 127) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 136) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 145) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 149) | func (p *Packet) String() string {
type Type (line 48) | type Type
method String (line 153) | func (t Type) String() string {
type Code (line 49) | type Code
method String (line 165) | func (c Code) String() string {
constant DstUnreachable (line 52) | DstUnreachable Type = 1
constant PacketTooBig (line 53) | PacketTooBig = 2
constant TimeExceeded (line 54) | TimeExceeded = 3
constant ParamProblem (line 55) | ParamProblem = 4
constant Private1 (line 56) | Private1 = 100
constant Private2 (line 57) | Private2 = 101
constant Reserved1 (line 58) | Reserved1 = 127
constant EchoRequest (line 59) | EchoRequest = 128
constant EchoReply (line 60) | EchoReply = 129
function Make (line 64) | func Make() *Packet {
FILE: packet/icmpv6/pkt_test.go
function MakeTestSimple (line 45) | func MakeTestSimple() *icmpv6.Packet {
function TestPack (line 51) | func TestPack(t *testing.T) {
function BenchmarkPack (line 67) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 78) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 96) | func BenchmarkUnpack(bn *testing.B) {
function TestPackWithIPv6 (line 113) | func TestPackWithIPv6(t *testing.T) {
function TestUnpackWithIPv6 (line 135) | func TestUnpackWithIPv6(t *testing.T) {
FILE: packet/ipv4/pkt.go
type Packet (line 40) | type Packet struct
method GetType (line 94) | func (p *Packet) GetType() packet.Type {
method GetLength (line 98) | func (p *Packet) GetLength() uint16 {
method Equals (line 106) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 110) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 133) | func (p *Packet) Pack(buf *packet.Buffer) error {
method checksum (line 151) | func (p *Packet) checksum(raw_bytes []byte) {
method pseudo_checksum (line 162) | func (p *Packet) pseudo_checksum() uint32 {
method Unpack (line 175) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 205) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 209) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 213) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 223) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 226) | func (p *Packet) String() string {
type Flags (line 56) | type Flags
method String (line 230) | func (f Flags) String() string {
constant Evil (line 59) | Evil Flags = 1 << 2
constant DontFragment (line 60) | DontFragment = 1 << 1
constant MoreFragments (line 61) | MoreFragments = 1 << 0
type Protocol (line 64) | type Protocol
method String (line 301) | func (p Protocol) String() string {
constant None (line 67) | None Protocol = 0x00
constant GRE (line 68) | GRE = 0x2F
constant ICMPv4 (line 69) | ICMPv4 = 0x01
constant ICMPv6 (line 70) | ICMPv6 = 0x3A
constant IGMP (line 71) | IGMP = 0x02
constant IPSecAH (line 72) | IPSecAH = 0x33
constant IPSecESP (line 73) | IPSecESP = 0x32
constant IPv6 (line 74) | IPv6 = 0x29
constant ISIS (line 75) | ISIS = 0x7C
constant L2TP (line 76) | L2TP = 0x73
constant OSPF (line 77) | OSPF = 0x59
constant SCTP (line 78) | SCTP = 0x84
constant TCP (line 79) | TCP = 0x06
constant UDP (line 80) | UDP = 0x11
constant UDPLite (line 81) | UDPLite = 0x88
function Make (line 84) | func Make() *Packet {
function CalculateChecksum (line 248) | func CalculateChecksum(raw_bytes []byte, csum uint32) uint16 {
function ProtocolToType (line 280) | func ProtocolToType(proto Protocol) packet.Type {
function TypeToProtocol (line 291) | func TypeToProtocol(pkttype packet.Type) Protocol {
FILE: packet/ipv4/pkt_test.go
function MakeTestSimple (line 48) | func MakeTestSimple() *ipv4.Packet {
function TestPack (line 63) | func TestPack(t *testing.T) {
function BenchmarkPack (line 79) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 90) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 109) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/ipv6/pkt.go
type Packet (line 40) | type Packet struct
method GetType (line 61) | func (p *Packet) GetType() packet.Type {
method GetLength (line 65) | func (p *Packet) GetLength() uint16 {
method Equals (line 73) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 77) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 96) | func (p *Packet) Pack(buf *packet.Buffer) error {
method pseudo_checksum (line 111) | func (p *Packet) pseudo_checksum() uint32 {
method Unpack (line 127) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 153) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 157) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 161) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 171) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 174) | func (p *Packet) String() string {
type Flags (line 52) | type Flags
function Make (line 54) | func Make() *Packet {
FILE: packet/ipv6/pkt_test.go
function MakeTestSimple (line 51) | func MakeTestSimple() *ipv6.Packet {
function TestPack (line 64) | func TestPack(t *testing.T) {
function BenchmarkPack (line 80) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 91) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 109) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/llc/pkt.go
type Packet (line 36) | type Packet struct
method GetType (line 48) | func (p *Packet) GetType() packet.Type {
method GetLength (line 52) | func (p *Packet) GetLength() uint16 {
method Equals (line 60) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 64) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 68) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 81) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 97) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 101) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 109) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 115) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 118) | func (p *Packet) String() string {
function Make (line 44) | func Make() *Packet {
FILE: packet/llc/pkt_test.go
function MakeTestSimple (line 43) | func MakeTestSimple() *llc.Packet {
function TestPack (line 51) | func TestPack(t *testing.T) {
function BenchmarkPack (line 67) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 78) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 96) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/packet.go
type Type (line 42) | type Type
method ToLinkType (line 131) | func (pkttype Type) ToLinkType() uint32 {
method String (line 141) | func (t Type) String() string {
constant None (line 45) | None Type = iota
constant ARP (line 46) | ARP
constant Bluetooth (line 47) | Bluetooth
constant Eth (line 48) | Eth
constant GRE (line 49) | GRE
constant ICMPv4 (line 50) | ICMPv4
constant ICMPv6 (line 51) | ICMPv6
constant IGMP (line 52) | IGMP
constant IPSec (line 53) | IPSec
constant IPv4 (line 54) | IPv4
constant IPv6 (line 55) | IPv6
constant ISIS (line 56) | ISIS
constant L2TP (line 57) | L2TP
constant LLC (line 58) | LLC
constant LLDP (line 59) | LLDP
constant OSPF (line 60) | OSPF
constant RadioTap (line 61) | RadioTap
constant Raw (line 62) | Raw
constant SCTP (line 63) | SCTP
constant SLL (line 64) | SLL
constant SNAP (line 65) | SNAP
constant TCP (line 66) | TCP
constant TRILL (line 67) | TRILL
constant UDP (line 68) | UDP
constant UDPLite (line 69) | UDPLite
constant VLAN (line 70) | VLAN
constant WiFi (line 71) | WiFi
constant WoL (line 72) | WoL
type Packet (line 77) | type Packet interface
function LinkType (line 120) | func LinkType(link_type uint32) Type {
function Compare (line 175) | func Compare(a, b Packet) bool {
function compare_value (line 203) | func compare_value(a, b reflect.Value) bool {
function Stringify (line 259) | func Stringify(p Packet) string {
function stringify_value (line 293) | func stringify_value(key string, val reflect.Value) string {
FILE: packet/radiotap/pkt.go
type Packet (line 38) | type Packet struct
method GetType (line 71) | func (p *Packet) GetType() packet.Type {
method GetLength (line 75) | func (p *Packet) GetLength() uint16 {
method Equals (line 83) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 87) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 91) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 103) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 118) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 122) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 126) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 133) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 136) | func (p *Packet) String() string {
type Present (line 46) | type Present
method String (line 140) | func (p Present) String() string {
constant TSFT (line 49) | TSFT Present = 1 << iota
constant Flags (line 50) | Flags
constant Rate (line 51) | Rate
constant Channel (line 52) | Channel
constant FHSS (line 53) | FHSS
constant DbmAntSignal (line 54) | DbmAntSignal
constant DbmAntNoise (line 55) | DbmAntNoise
constant LockQuality (line 56) | LockQuality
constant TXAttenuation (line 57) | TXAttenuation
constant DbTXAttenuation (line 58) | DbTXAttenuation
constant DbmTXPower (line 59) | DbmTXPower
constant Antenna (line 60) | Antenna
constant DbAntSignal (line 61) | DbAntSignal
constant DbAntNoise (line 62) | DbAntNoise
constant EXT (line 63) | EXT
function Make (line 66) | func Make() *Packet {
FILE: packet/radiotap/pkt_test.go
function MakeTestSimple (line 45) | func MakeTestSimple() *radiotap.Packet {
function TestPack (line 57) | func TestPack(t *testing.T) {
function BenchmarkPack (line 73) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 84) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 102) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/raw/pkt.go
type Packet (line 38) | type Packet struct
method GetType (line 46) | func (p *Packet) GetType() packet.Type {
method GetLength (line 50) | func (p *Packet) GetLength() uint16 {
method Equals (line 54) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 58) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 62) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 68) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 74) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 78) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 82) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 86) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 89) | func (p *Packet) String() string {
function Make (line 42) | func Make() *Packet {
FILE: packet/raw/pkt_test.go
function MakeTestSimple (line 44) | func MakeTestSimple() *raw.Packet {
function TestPack (line 50) | func TestPack(t *testing.T) {
function BenchmarkPack (line 66) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 77) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 95) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/sll/pkt.go
type Packet (line 39) | type Packet struct
method GetType (line 66) | func (p *Packet) GetType() packet.Type {
method GetLength (line 70) | func (p *Packet) GetLength() uint16 {
method Equals (line 78) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 82) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 86) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 101) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 114) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 118) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 122) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 129) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 132) | func (p *Packet) String() string {
type Type (line 48) | type Type
method String (line 136) | func (t Type) String() string {
constant Host (line 51) | Host Type = 0
constant Broadcast (line 52) | Broadcast Type = 1
constant Multicast (line 53) | Multicast Type = 2
constant OtherHost (line 54) | OtherHost Type = 3
constant Outgoing (line 55) | Outgoing Type = 4
function Make (line 58) | func Make() *Packet {
FILE: packet/sll/pkt_test.go
function MakeTestSimple (line 48) | func MakeTestSimple() *sll.Packet {
function TestPack (line 60) | func TestPack(t *testing.T) {
function BenchmarkPack (line 76) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 87) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 105) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/snap/pkt.go
type Packet (line 37) | type Packet struct
method GetType (line 48) | func (p *Packet) GetType() packet.Type {
method GetLength (line 52) | func (p *Packet) GetLength() uint16 {
method Equals (line 60) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 64) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 68) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 75) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 82) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 86) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 94) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 101) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 104) | func (p *Packet) String() string {
function Make (line 44) | func Make() *Packet {
FILE: packet/snap/pkt_test.go
function MakeTestSimple (line 44) | func MakeTestSimple() *snap.Packet {
function TestPack (line 50) | func TestPack(t *testing.T) {
function BenchmarkPack (line 66) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 77) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 95) | func BenchmarkUnpack(bn *testing.B) {
FILE: packet/tcp/pkt.go
type Packet (line 39) | type Packet struct
method GetType (line 94) | func (p *Packet) GetType() packet.Type {
method GetLength (line 98) | func (p *Packet) GetLength() uint16 {
method Equals (line 106) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 110) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 123) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 194) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 278) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 282) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 286) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 292) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 296) | func (p *Packet) String() string {
type Flags (line 54) | type Flags
method String (line 300) | func (f Flags) String() string {
constant Syn (line 57) | Syn Flags = 1<<1
constant Fin (line 58) | Fin = 1<<2
constant Rst (line 59) | Rst = 1<<3
constant PSH (line 60) | PSH = 1<<4
constant Ack (line 61) | Ack = 1<<5
constant Urg (line 62) | Urg = 1<<6
constant ECE (line 63) | ECE = 1<<7
constant Cwr (line 64) | Cwr = 1<<8
constant NS (line 65) | NS = 1<<9
type Option (line 68) | type Option struct
type OptType (line 74) | type OptType
constant End (line 77) | End OptType = 0x00
constant Nop (line 78) | Nop = 0x01
constant MSS (line 79) | MSS = 0x02
constant WindowScale (line 80) | WindowScale = 0x03
constant SAckOk (line 81) | SAckOk = 0x04
constant SAck (line 82) | SAck = 0x05
constant Timestamp (line 83) | Timestamp = 0x08
function Make (line 86) | func Make() *Packet {
FILE: packet/tcp/pkt_test.go
function MakeTestSimple (line 46) | func MakeTestSimple() *tcp.Packet {
function TestPack (line 59) | func TestPack(t *testing.T) {
function BenchmarkPack (line 75) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 86) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 104) | func BenchmarkUnpack(bn *testing.B) {
function TestPackWithIPv4 (line 122) | func TestPackWithIPv4(t *testing.T) {
function TestUnpackWithIPv4 (line 144) | func TestUnpackWithIPv4(t *testing.T) {
function TestPackOptions (line 170) | func TestPackOptions(t *testing.T) {
function TestUnpackOptions (line 225) | func TestUnpackOptions(t *testing.T) {
FILE: packet/udp/pkt.go
type Packet (line 37) | type Packet struct
method GetType (line 52) | func (p *Packet) GetType() packet.Type {
method GetLength (line 56) | func (p *Packet) GetLength() uint16 {
method Equals (line 64) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 68) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 81) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 96) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 105) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 109) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 113) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 120) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 124) | func (p *Packet) String() string {
function Make (line 46) | func Make() *Packet {
FILE: packet/udp/pkt_test.go
function MakeTestSimple (line 45) | func MakeTestSimple() *udp.Packet {
function TestPack (line 53) | func TestPack(t *testing.T) {
function BenchmarkPack (line 69) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 80) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 98) | func BenchmarkUnpack(bn *testing.B) {
function TestPackWithIPv4 (line 115) | func TestPackWithIPv4(t *testing.T) {
function TestUnpackWithIPv4 (line 141) | func TestUnpackWithIPv4(t *testing.T) {
FILE: packet/vlan/pkt.go
type Packet (line 37) | type Packet struct
method GetType (line 49) | func (p *Packet) GetType() packet.Type {
method GetLength (line 53) | func (p *Packet) GetLength() uint16 {
method Equals (line 61) | func (p *Packet) Equals(other packet.Packet) bool {
method Answers (line 65) | func (p *Packet) Answers(other packet.Packet) bool {
method Pack (line 82) | func (p *Packet) Pack(buf *packet.Buffer) error {
method Unpack (line 94) | func (p *Packet) Unpack(buf *packet.Buffer) error {
method Payload (line 107) | func (p *Packet) Payload() packet.Packet {
method GuessPayloadType (line 111) | func (p *Packet) GuessPayloadType() packet.Type {
method SetPayload (line 115) | func (p *Packet) SetPayload(pl packet.Packet) error {
method InitChecksum (line 122) | func (p *Packet) InitChecksum(csum uint32) {
method String (line 125) | func (p *Packet) String() string {
function Make (line 45) | func Make() *Packet {
FILE: packet/vlan/pkt_test.go
function MakeTestSimple (line 44) | func MakeTestSimple() *vlan.Packet {
function TestPack (line 52) | func TestPack(t *testing.T) {
function BenchmarkPack (line 68) | func BenchmarkPack(bn *testing.B) {
function TestUnpack (line 79) | func TestUnpack(t *testing.T) {
function BenchmarkUnpack (line 97) | func BenchmarkUnpack(bn *testing.B) {
FILE: routing/routing.go
type Route (line 41) | type Route struct
method GetIfaceIPv4Addr (line 109) | func (r *Route) GetIfaceIPv4Addr() (net.IP, error) {
method GetIfaceIPv6Addr (line 129) | func (r *Route) GetIfaceIPv6Addr() (net.IP, error) {
method String (line 148) | func (r *Route) String() string {
type route_slice (line 49) | type route_slice
method Len (line 51) | func (r route_slice) Len() int {
method Swap (line 55) | func (r route_slice) Swap(i, j int) {
method Less (line 59) | func (r route_slice) Less(i, j int) bool {
function RouteTo (line 81) | func RouteTo(dst net.IP) (*Route, error) {
FILE: routing/routing_linux.go
type rtmsg (line 38) | type rtmsg struct
function Routes (line 51) | func Routes() ([]*Route, error) {
Condensed preview — 63 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (284K chars).
[
{
"path": ".travis.yml",
"chars": 167,
"preview": "language: go\n\nsudo: false\n\naddons:\n apt:\n packages:\n - libpcap0.8-dev\n\ngo:\n - \"1.11\"\n - \"tip\"\n\nenv:\n - GO111MODULE="
},
{
"path": "COPYING",
"chars": 1327,
"preview": "Copyright (c) 2014, Alessandro Ghedini <alessandro@ghedini.me>\nAll rights reserved.\n\nRedistribution and use in source an"
},
{
"path": "README.md",
"chars": 6175,
"preview": "go.pkt\n======\n\n\n\n**go.pkt** provides Go libraries for capturi"
},
{
"path": "capture/capture.go",
"chars": 1986,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "capture/file/capture.go",
"chars": 6948,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "capture/file/capture_test.go",
"chars": 4490,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "capture/pcap/capture.go",
"chars": 5699,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "capture/pcap/capture_test.go",
"chars": 2401,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/arp/main.go",
"chars": 3054,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/bpf_asm/Makefile",
"chars": 164,
"preview": "all: bpf_asm\n\nbpf_asm: bpf_asm.nn.go y.go\n\tgo build -o bpf_asm bpf_asm.nn.go y.go\n\ny.go: bpf_asm.y\n\tgo tool yacc bpf_asm"
},
{
"path": "examples/bpf_asm/bpf_asm.l",
"chars": 2731,
"preview": "/ldb/\t{ return OP_LDB }\n/ldh/\t{ return OP_LDH }\n/ld/\t{ return OP_LD }\n/ldi/\t{ return OP_LDI }\n/ldx/\t{ return OP_LDX }\n/l"
},
{
"path": "examples/bpf_asm/bpf_asm.y",
"chars": 7204,
"preview": "%{\npackage main\n\nimport \"github.com/ghedo/go.pkt/filter\"\n%}\n\n%union {\n\tlabel string\n\tnumber uint32\n}\n\n%token OP_LDB\n%to"
},
{
"path": "examples/dump/main.go",
"chars": 4166,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/ping/main.go",
"chars": 3118,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/route/main.go",
"chars": 2506,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/syn_scan/main.go",
"chars": 3693,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "examples/tracereply/main.go",
"chars": 3562,
"preview": "package main\n\nimport \"log\"\nimport \"net\"\nimport \"strconv\"\n\nimport \"github.com/docopt/docopt-go\"\n\nimport \"github.com/songg"
},
{
"path": "examples/traceroute/main.go",
"chars": 4988,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "filter/bpf_builder.go",
"chars": 11935,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "filter/bpf_builder_test.go",
"chars": 5350,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "filter/bpf_filter.c",
"chars": 9842,
"preview": "/*-\n * Copyright (c) 1990, 1991, 1993\n *\tThe Regents of the University of California. All rights reserved.\n *\n * This c"
},
{
"path": "filter/bpf_filter.go",
"chars": 4666,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "filter/bpf_filter.h",
"chars": 4319,
"preview": "/*-\n * Copyright (c) 1990, 1991, 1993\n *\tThe Regents of the University of California. All rights reserved.\n *\n * This c"
},
{
"path": "filter/bpf_filter_test.go",
"chars": 5142,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "filter/pcap.go",
"chars": 2291,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "go.mod",
"chars": 169,
"preview": "module github.com/ghedo/go.pkt\n\nrequire (\n\tgithub.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815\n\tgithub.com/so"
},
{
"path": "go.sum",
"chars": 452,
"preview": "github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=\ngithub.co"
},
{
"path": "layers/layers.go",
"chars": 6873,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "layers/layers_test.go",
"chars": 17974,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "network/network.go",
"chars": 4646,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/arp/pkt.go",
"chars": 4366,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/arp/pkt_test.go",
"chars": 3450,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/buffer.go",
"chars": 4656,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/eth/pkt.go",
"chars": 5238,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/eth/pkt_test.go",
"chars": 3017,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/icmpv4/pkt.go",
"chars": 5178,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/icmpv4/pkt_test.go",
"chars": 2863,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/icmpv6/pkt.go",
"chars": 4441,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/icmpv6/pkt_test.go",
"chars": 3852,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/ipv4/pkt.go",
"chars": 8002,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/ipv4/pkt_test.go",
"chars": 3165,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/ipv6/pkt.go",
"chars": 4594,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/ipv6/pkt_test.go",
"chars": 3317,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/llc/pkt.go",
"chars": 3171,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/llc/pkt_test.go",
"chars": 2773,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/packet.go",
"chars": 8357,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/radiotap/pkt.go",
"chars": 3495,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/radiotap/pkt_test.go",
"chars": 3200,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/raw/pkt.go",
"chars": 2515,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/raw/pkt_test.go",
"chars": 2836,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/sll/pkt.go",
"chars": 3808,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/sll/pkt_test.go",
"chars": 3044,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/snap/pkt.go",
"chars": 2916,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/snap/pkt_test.go",
"chars": 2791,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/tcp/pkt.go",
"chars": 7131,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/tcp/pkt_test.go",
"chars": 6247,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/udp/pkt.go",
"chars": 3434,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/udp/pkt_test.go",
"chars": 3898,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/vlan/pkt.go",
"chars": 3385,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "packet/vlan/pkt_test.go",
"chars": 2834,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "routing/routing.go",
"chars": 4414,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
},
{
"path": "routing/routing_linux.go",
"chars": 3192,
"preview": "/*\n * Network packet analysis framework.\n *\n * Copyright (c) 2014, Alessandro Ghedini\n * All rights reserved.\n *\n * Redi"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the ghedo/go.pkt GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 63 files (261.3 KB), approximately 77.4k tokens, and a symbol index with 622 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.