factor network handling into package

This commit is contained in:
Johannes Kimmel 2021-12-14 10:17:05 +01:00
parent 3f5370882f
commit 931e2ca8a9
3 changed files with 101 additions and 55 deletions

68
main.go
View File

@ -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:

86
packet/packet.go Normal file
View File

@ -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
}

View File

@ -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 {