init
This commit is contained in:
commit
1d913cb5a7
|
@ -0,0 +1,28 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/go
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=go
|
||||
|
||||
### Go ###
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
### Go Patch ###
|
||||
/vendor/
|
||||
/Godeps/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/go
|
||||
|
||||
abbel
|
|
@ -0,0 +1,5 @@
|
|||
module git.freifunk-franken.de/jkimmel/abbel
|
||||
|
||||
go 1.15
|
||||
|
||||
require golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
|
@ -0,0 +1,7 @@
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
@ -0,0 +1,126 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//go:generate stringer -type=TLV
|
||||
package tlv
|
||||
|
||||
import "fmt"
|
||||
|
||||
type TLV uint8
|
||||
|
||||
const (
|
||||
Pad1 TLV = iota
|
||||
PadN
|
||||
AckReq
|
||||
Ack
|
||||
Hello
|
||||
IHU
|
||||
RouterID
|
||||
NextHop
|
||||
Update
|
||||
RouteRequest
|
||||
RouteUpdate
|
||||
TSPC
|
||||
HMAC
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
buf []byte
|
||||
err error
|
||||
t TLV
|
||||
l uint8
|
||||
}
|
||||
|
||||
func NewTLVScanner(buf []byte) *Scanner {
|
||||
return &Scanner{
|
||||
buf: buf,
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *Scanner) Scan() bool {
|
||||
if ts.err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(ts.buf) <= int(ts.l) {
|
||||
return false
|
||||
}
|
||||
|
||||
// move beginning of the buffer to the next TLV
|
||||
ts.buf = ts.buf[ts.l:]
|
||||
ts.t, ts.l = TLV(ts.buf[0]), 0
|
||||
|
||||
switch ts.t {
|
||||
case Pad1:
|
||||
ts.buf = ts.buf[1:]
|
||||
default:
|
||||
ts.l = ts.buf[1]
|
||||
if 2+int(ts.l) > len(ts.buf) {
|
||||
ts.err = fmt.Errorf("Invalid length: type %d, length %d, size %d", ts.t, ts.l, len(ts.buf))
|
||||
return false
|
||||
}
|
||||
// move beginning of the buffer behind the header
|
||||
ts.buf = ts.buf[2:]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ts *Scanner) Err() error {
|
||||
return ts.err
|
||||
}
|
||||
|
||||
func (ts *Scanner) TLV() (TLV, []byte) {
|
||||
if ts.err != nil {
|
||||
return 0, nil
|
||||
}
|
||||
return ts.t, ts.buf[:ts.l]
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "stringer -type=TLV"; DO NOT EDIT.
|
||||
|
||||
package tlv
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Pad1-0]
|
||||
_ = x[PadN-1]
|
||||
_ = x[AckReq-2]
|
||||
_ = x[Ack-3]
|
||||
_ = x[Hello-4]
|
||||
_ = x[IHU-5]
|
||||
_ = x[RouterID-6]
|
||||
_ = x[NextHop-7]
|
||||
_ = x[Update-8]
|
||||
_ = x[RouteRequest-9]
|
||||
_ = x[RouteUpdate-10]
|
||||
_ = x[TSPC-11]
|
||||
_ = x[HMAC-12]
|
||||
}
|
||||
|
||||
const _TLV_name = "Pad1PadNAckReqAckHelloIHURouterIDNextHopUpdateRouteRequestRouteUpdateTSPCHMAC"
|
||||
|
||||
var _TLV_index = [...]uint8{0, 4, 8, 14, 17, 22, 25, 33, 40, 46, 58, 69, 73, 77}
|
||||
|
||||
func (i TLV) String() string {
|
||||
if i >= TLV(len(_TLV_index)-1) {
|
||||
return "TLV(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _TLV_name[_TLV_index[i]:_TLV_index[i+1]]
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package tlv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
)
|
||||
|
||||
type PacketUpdateHeader struct {
|
||||
AE uint8
|
||||
Flags uint8
|
||||
Plen uint8
|
||||
Omitted uint8
|
||||
Interval uint16
|
||||
Seqno uint16
|
||||
Metric uint16
|
||||
}
|
||||
|
||||
type PacketUpdate struct {
|
||||
PacketUpdateHeader
|
||||
Prefix net.IPNet
|
||||
}
|
||||
|
||||
type PacketDecoder struct {
|
||||
routerID [8]byte
|
||||
v4 [4]byte
|
||||
v6 [16]byte
|
||||
}
|
||||
|
||||
func (s *PacketDecoder) UpdateFromBytes(b []byte) (PacketUpdate, error) {
|
||||
var u PacketUpdate
|
||||
|
||||
r := bytes.NewReader(b[:10])
|
||||
err := binary.Read(r, binary.BigEndian, &u.PacketUpdateHeader)
|
||||
|
||||
b = b[10:]
|
||||
|
||||
psize := (u.Plen+7)/8 - u.Omitted
|
||||
switch u.AE {
|
||||
case 0:
|
||||
case 1:
|
||||
u.Prefix.Mask = net.CIDRMask(int(u.Plen), 4*8)
|
||||
u.Prefix.IP = append([]byte{}, s.v4[:]...)
|
||||
copy(u.Prefix.IP[u.Omitted:], b[:psize])
|
||||
if u.Flags&0x80 > 0 {
|
||||
copy(s.v4[:], u.Prefix.IP)
|
||||
}
|
||||
case 2:
|
||||
u.Prefix.Mask = net.CIDRMask(int(u.Plen), 16*8)
|
||||
u.Prefix.IP = append([]byte{}, s.v6[:]...)
|
||||
copy(u.Prefix.IP[u.Omitted:], b[:psize])
|
||||
if u.Flags&0x80 > 0 {
|
||||
copy(s.v6[:], u.Prefix.IP)
|
||||
}
|
||||
case 3:
|
||||
u.Prefix.Mask = net.CIDRMask(8, 16*8)
|
||||
u.Prefix.IP = make([]byte, 16)
|
||||
u.Prefix.IP[0] = 0xfe
|
||||
u.Prefix.IP[1] = 0x80
|
||||
copy(u.Prefix.IP[8:], b[:8])
|
||||
}
|
||||
|
||||
return u, err
|
||||
}
|
Loading…
Reference in New Issue