factor network handling into package
This commit is contained in:
parent
3f5370882f
commit
931e2ca8a9
68
main.go
68
main.go
|
@ -3,92 +3,52 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"git.freifunk-franken.de/jkimmel/abbel/packet"
|
||||
"git.freifunk-franken.de/jkimmel/abbel/tlv"
|
||||
"golang.org/x/net/ipv6"
|
||||
"inet.af/netaddr"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
Group net.IP
|
||||
Group string
|
||||
Port uint16
|
||||
Ifs []net.Interface
|
||||
Ifs []string
|
||||
}
|
||||
|
||||
func parseOpts() (options, error) {
|
||||
var opt options
|
||||
var err error
|
||||
|
||||
opt.Group = net.ParseIP("ff02::1:6")
|
||||
opt.Port = 6696
|
||||
ifi, err := net.InterfaceByName("babel")
|
||||
if err != nil {
|
||||
return opt, err
|
||||
opt = options{
|
||||
Group: "ff02:0:0:0:0:0:1:6",
|
||||
Port: 6696,
|
||||
Ifs: []string{"babel"},
|
||||
}
|
||||
opt.Ifs = []net.Interface{*ifi}
|
||||
|
||||
return opt, err
|
||||
}
|
||||
|
||||
func readBabelPacket(up *ipv6.PacketConn, b []byte) ([]byte, netaddr.IP, error) {
|
||||
n, rcm, src, err := up.ReadFrom(b)
|
||||
if err != nil {
|
||||
return nil, netaddr.IP{}, err
|
||||
}
|
||||
|
||||
_ = rcm
|
||||
|
||||
b = b[:n]
|
||||
if len(b) < 4 {
|
||||
fmt.Println("packet too short:", len(b))
|
||||
}
|
||||
magic := b[0]
|
||||
version := b[1]
|
||||
length := uint16(b[2])<<8 + uint16(b[3])
|
||||
b = b[4:]
|
||||
|
||||
if magic != 42 {
|
||||
return nil, netaddr.IP{}, fmt.Errorf("Invalid magic number %d", magic)
|
||||
}
|
||||
if int(length) > len(b) {
|
||||
fmt.Println("invalid length:", length)
|
||||
}
|
||||
|
||||
fmt.Println(src, rcm, magic, version, length, n)
|
||||
srcipport, err := netaddr.ParseIPPort(src.String())
|
||||
return b, srcipport.IP(), err
|
||||
}
|
||||
|
||||
func run(opt options) error {
|
||||
var err error
|
||||
uc, err := net.ListenUDP("udp6", &net.UDPAddr{Port: int(opt.Port)})
|
||||
conn, err := packet.ListenPort(opt.Port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer uc.Close()
|
||||
up := ipv6.NewPacketConn(uc)
|
||||
|
||||
if err := up.SetControlMessage(ipv6.FlagDst, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for ifi := range opt.Ifs {
|
||||
if err := up.JoinGroup(&opt.Ifs[ifi], &net.UDPAddr{IP: opt.Group}); err != nil {
|
||||
defer conn.Close()
|
||||
for _, iface := range opt.Ifs {
|
||||
if err = conn.JoinGroup(iface, opt.Group); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
buf := [4096]byte{}
|
||||
var s tlv.PacketDecoder
|
||||
for {
|
||||
b, src, err := readBabelPacket(up, buf[:])
|
||||
b, src, ifindex, err := conn.ReadFrom(buf[:])
|
||||
if err != nil {
|
||||
fmt.Println("Skipping packet:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
var s tlv.PacketDecoder
|
||||
s.Reset(b, src)
|
||||
s.Reset(b, src, ifindex)
|
||||
for s.Scan() {
|
||||
switch t := s.TLV().(type) {
|
||||
case tlv.NextHop:
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package packet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"golang.org/x/net/ipv6"
|
||||
"inet.af/netaddr"
|
||||
)
|
||||
|
||||
const (
|
||||
BabelMagic = 42
|
||||
BabelVersion = 2
|
||||
BabelPacketHeaderSize = 4
|
||||
)
|
||||
|
||||
type Conn struct {
|
||||
v6pc *ipv6.PacketConn
|
||||
}
|
||||
|
||||
func ListenPort(port uint16) (Conn, error) {
|
||||
var c Conn
|
||||
|
||||
uc, err := net.ListenUDP("udp6", &net.UDPAddr{Port: int(port)})
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
c.v6pc = ipv6.NewPacketConn(uc)
|
||||
|
||||
return c, c.v6pc.SetControlMessage(ipv6.FlagDst, true)
|
||||
}
|
||||
|
||||
func (c Conn) Close() error {
|
||||
return c.v6pc.Close()
|
||||
}
|
||||
|
||||
func (c Conn) JoinGroup(ifname string, addr string) error {
|
||||
ifi, err := net.InterfaceByName(ifname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ip, err := netaddr.ParseIP(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.v6pc.JoinGroup(ifi, &net.UDPAddr{IP: ip.IPAddr().IP})
|
||||
}
|
||||
|
||||
func (c Conn) ReadFrom(b []byte) (body []byte, src netaddr.IP, ifindex int, err error) {
|
||||
n, rcm, _, err := c.v6pc.ReadFrom(b)
|
||||
if err != nil {
|
||||
return nil, netaddr.IP{}, 0, err
|
||||
}
|
||||
|
||||
b = b[:n]
|
||||
if len(b) < BabelPacketHeaderSize {
|
||||
return nil, netaddr.IP{}, 0, fmt.Errorf("Packet too short: %d", len(b))
|
||||
}
|
||||
|
||||
magic := b[0]
|
||||
version := b[1]
|
||||
length := uint16(b[2])<<8 + uint16(b[3])
|
||||
b = b[4:]
|
||||
|
||||
if magic != BabelMagic {
|
||||
return nil, netaddr.IP{}, 0, fmt.Errorf("Invalid magic number %d", magic)
|
||||
}
|
||||
if version != BabelVersion {
|
||||
return nil, netaddr.IP{}, 0, fmt.Errorf("Unsupported version number %d", version)
|
||||
}
|
||||
if int(length) > len(b) {
|
||||
return nil, netaddr.IP{}, 0, fmt.Errorf("Invalid length for packet of size %d: %d", n, length)
|
||||
}
|
||||
|
||||
var ok bool
|
||||
src, ok = netaddr.FromStdIPRaw(rcm.Src)
|
||||
|
||||
if !ok {
|
||||
return nil, netaddr.IP{}, 0, fmt.Errorf("Invalid src address %q", rcm.Src)
|
||||
}
|
||||
|
||||
return b, src, rcm.IfIndex, err
|
||||
|
||||
}
|
|
@ -183,7 +183,7 @@ type PacketDecoder struct {
|
|||
}
|
||||
|
||||
// Reset clears the parser state and sets a new byte slice to work on.
|
||||
func (s *PacketDecoder) Reset(b []byte, nexthop netaddr.IP) {
|
||||
func (s *PacketDecoder) Reset(b []byte, nexthop netaddr.IP, ifindex int) {
|
||||
*s = PacketDecoder{}
|
||||
s.tlvscanner.Reset(b)
|
||||
switch {
|
||||
|
|
Loading…
Reference in New Issue