package main import ( "fmt" "log" "net" "git.freifunk-franken.de/jkimmel/abbel/tlv" "golang.org/x/net/ipv6" ) type options struct { Group net.IP Port uint16 Ifs []net.Interface } 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.Ifs = []net.Interface{*ifi} return opt, err } func run(opt options) error { var err error uc, err := net.ListenUDP("udp6", &net.UDPAddr{Port: int(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 { return err } } b := make([]byte, 1500) for { n, rcm, src, err := up.ReadFrom(b) if err != nil { return err } _ = rcm magic := b[0] version := b[1] length := uint16(b[2])<<8 + uint16(b[3]) if magic != 42 { continue } if int(length)+4 > n { fmt.Println("invalid length") } fmt.Println(src, rcm, magic, version, length, n) var u tlv.PacketUpdate var s tlv.PacketDecoder ts := tlv.NewTLVScanner(b[4 : 4+length]) for ts.Scan() { t, v := ts.TLV() switch t { case tlv.Update: u, err = s.UpdateFromBytes(v) if err != nil { fmt.Println(u.PacketUpdateHeader, &u.Prefix, err) } else { if u.PacketUpdateHeader.Metric == 0xFFFF { fmt.Print("\x1B[1m") } fmt.Printf("%43s: %+v\x1B[0m\n", &u.Prefix, u.PacketUpdateHeader) } default: fmt.Printf(" T: %12s (%2d), L: %3d\n", t, t, len(v)) } } if ts.Err() != nil { fmt.Println(err) } //{ // var bbuf bytes.Buffer // lzww := lzw.NewWriter(&bbuf, lzw.LSB, 8) // lzww.Write(b[:n]) // lzww.Close() // fmt.Println(n, len(bbuf.Bytes())) //} //{ // var bbuf bytes.Buffer // gzw, _ := gzip.NewWriterLevel(&bbuf, 9) // gzw.Write(b[:n]) // gzw.Close() // fmt.Println(n, len(bbuf.Bytes())) //} } return nil } func main() { opt, err := parseOpts() if err != nil { log.Fatal(err) } if err := run(opt); err != nil { log.Fatal(err) } }