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