package capture import ( "fmt" "git.freifunk-franken.de/jkimmel/abbel/packet" "github.com/google/gopacket" "github.com/google/gopacket/afpacket" "github.com/google/gopacket/layers" "golang.org/x/net/bpf" "inet.af/netaddr" ) var ( // tcpdump -y RAW -dd ip6 and udp dst port 6696 babelBPFRAW = []bpf.RawInstruction{ {0x30, 0, 0, 0x00000000}, {0x54, 0, 0, 0x000000f0}, {0x15, 0, 5, 0x00000060}, {0x30, 0, 0, 0x00000006}, {0x15, 0, 3, 0x00000011}, {0x28, 0, 0, 0x0000002a}, {0x15, 0, 1, 0x00001a28}, {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000}, } ) type Handle struct { tp *afpacket.TPacket } func FromInterface(iface string) (Handle, error) { var h Handle var err error if iface != "any" { h.tp, err = afpacket.NewTPacket( afpacket.SocketDgram, afpacket.OptInterface(iface), ) } else { h.tp, err = afpacket.NewTPacket( afpacket.SocketDgram, ) } if err != nil { fmt.Println("here") return Handle{}, err } err = h.tp.SetBPF(babelBPFRAW) if err != nil { return Handle{}, err } return h, nil } func (h Handle) Close() error { h.tp.Close() return nil } func (h Handle) ReadFrom(b []byte) (body []byte, src netaddr.IP, ifindex int, err error) { data, ci, err := h.tp.ZeroCopyReadPacketData() if err != nil { return nil, netaddr.IP{}, 0, err } pckt := gopacket.NewPacket(data, layers.LayerTypeIPv6, gopacket.NoCopy) ip6, ok := pckt.NetworkLayer().(*layers.IPv6) if !ok { return nil, netaddr.IP{}, 0, fmt.Errorf("Expected IPv6 layer, got %v", pckt.NetworkLayer()) } src, ok = netaddr.FromStdIP(ip6.SrcIP) if !ok { return nil, netaddr.IP{}, 0, fmt.Errorf("Error parsing packet src address %q", ip6.SrcIP) } payload := pckt.ApplicationLayer().Payload() copy(b, payload) b, err = packet.Validate(b[:len(payload)]) if err != nil { return nil, netaddr.IP{}, 0, err } return b, src, ci.InterfaceIndex, nil }