complete tlv parser
This commit is contained in:
parent
9fe17ce7ed
commit
ff695a5956
7
go.mod
7
go.mod
|
@ -1,5 +1,8 @@
|
|||
module git.freifunk-franken.de/jkimmel/abbel
|
||||
|
||||
go 1.15
|
||||
go 1.0
|
||||
|
||||
require golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
require (
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6
|
||||
)
|
||||
|
|
29
go.sum
29
go.sum
|
@ -1,7 +1,34 @@
|
|||
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
|
||||
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 h1:Tx9kY6yUkLge/pFG7IEMwDZy6CS2ajFc9TvQdPCW0uA=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw=
|
||||
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8=
|
||||
|
|
108
main.go
108
main.go
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"git.freifunk-franken.de/jkimmel/abbel/tlv"
|
||||
"golang.org/x/net/ipv6"
|
||||
"inet.af/netaddr"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
|
@ -30,6 +31,35 @@ func parseOpts() (options, error) {
|
|||
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)})
|
||||
|
@ -49,50 +79,66 @@ func run(opt options) error {
|
|||
}
|
||||
}
|
||||
|
||||
b := make([]byte, 1500)
|
||||
buf := [4096]byte{}
|
||||
for {
|
||||
n, rcm, src, err := up.ReadFrom(b)
|
||||
b, src, err := readBabelPacket(up, buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_ = rcm
|
||||
|
||||
magic := b[0]
|
||||
version := b[1]
|
||||
length := uint16(b[2])<<8 + uint16(b[3])
|
||||
|
||||
if magic != 42 {
|
||||
fmt.Println("Skipping packet:", err)
|
||||
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 {
|
||||
s.Reset(b, src)
|
||||
for s.Scan() {
|
||||
var subtlv []byte
|
||||
switch t := s.TLV().(type) {
|
||||
case tlv.NextHop:
|
||||
fmt.Printf("%12s %s\n", t.T(), t.Address)
|
||||
case tlv.Hello:
|
||||
fmt.Printf("% 12s %+v\n", t.T(), t)
|
||||
case tlv.Update:
|
||||
u, err = s.UpdateFromBytes(v)
|
||||
if err != nil {
|
||||
fmt.Println(u.PacketUpdateHeader, &u.Prefix, err)
|
||||
fmt.Println(t, t.Prefix, err)
|
||||
} else {
|
||||
if u.PacketUpdateHeader.Metric == 0xFFFF {
|
||||
fmt.Print("\x1B[1m")
|
||||
if t.Metric == 0xFFFF {
|
||||
fmt.Print("\x1B[31m")
|
||||
} else {
|
||||
fmt.Print("\x1B[36m")
|
||||
}
|
||||
fmt.Printf("%43s: %+v\x1B[0m\n", &u.Prefix, u.PacketUpdateHeader)
|
||||
fmt.Printf("% 12s %-43s%s\x1B[0m\n", t.T(), t.Prefix, t.FormatHeader())
|
||||
}
|
||||
case tlv.RouterID:
|
||||
fmt.Printf("%12s %s\n", t.T(), t)
|
||||
case tlv.RouteRequest:
|
||||
fmt.Printf("%12s %s\n", t.T(), t.Prefix)
|
||||
case tlv.Raw:
|
||||
fmt.Printf(" T: %12s (%2d), L: %3d\n", t.T(), t.T(), len(t.V()))
|
||||
case tlv.IHU:
|
||||
fmt.Printf("%12s %-43sRxcost %5d Interval %4d \n", t.T(), t.Address, t.Rxcost, t.Interval)
|
||||
default:
|
||||
fmt.Printf(" T: %12s (%2d), L: %3d\n", t, t, len(v))
|
||||
if t != nil {
|
||||
fmt.Println("Unknown TLV", t.T(), t)
|
||||
} else {
|
||||
fmt.Println("got nil TLV")
|
||||
}
|
||||
}
|
||||
for len(subtlv) > 0 {
|
||||
switch tlv.SubType(subtlv[0]) {
|
||||
case tlv.SubTypeSourcePrefix:
|
||||
var pfx tlv.SourcePrefix
|
||||
pfx, subtlv, err = tlv.SourcePrefixFromBytes(subtlv[2:])
|
||||
fmt.Print("\x1B[7;36m")
|
||||
fmt.Printf("%12s %s\x1B[0m\n", pfx.T(), pfx)
|
||||
case tlv.SubTypeDiversity, tlv.SubTypePad1, tlv.SubTypePadN, tlv.SubTypeTimestamp:
|
||||
fmt.Print("\x1B[7m")
|
||||
fmt.Printf("%12s: %v\x1B[0m\n", "Subtlv", subtlv)
|
||||
subtlv = nil
|
||||
default:
|
||||
panic("unknown subtlv type")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ts.Err() != nil {
|
||||
if s.Err() != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
|
@ -111,8 +157,6 @@ func run(opt options) error {
|
|||
// fmt.Println(n, len(bbuf.Bytes()))
|
||||
//}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// Code generated by "stringer -type=SubType -trimprefix SubType"; 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[SubTypePad1-0]
|
||||
_ = x[SubTypePadN-1]
|
||||
_ = x[SubTypeDiversity-2]
|
||||
_ = x[SubTypeTimestamp-3]
|
||||
_ = x[SubTypeSourcePrefix-128]
|
||||
}
|
||||
|
||||
const (
|
||||
_SubType_name_0 = "Pad1PadNDiversityTimestamp"
|
||||
_SubType_name_1 = "SourcePrefix"
|
||||
)
|
||||
|
||||
var (
|
||||
_SubType_index_0 = [...]uint8{0, 4, 8, 17, 26}
|
||||
)
|
||||
|
||||
func (i SubType) String() string {
|
||||
switch {
|
||||
case i <= 3:
|
||||
return _SubType_name_0[_SubType_index_0[i]:_SubType_index_0[i+1]]
|
||||
case i == 128:
|
||||
return _SubType_name_1
|
||||
default:
|
||||
return "SubType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
}
|
727
tlv/tlv.go
727
tlv/tlv.go
|
@ -1,30 +1,57 @@
|
|||
//go:generate stringer -type=TLV
|
||||
//go:generate stringer -type=Type -trimprefix Type
|
||||
//go:generate stringer -type=SubType -trimprefix SubType
|
||||
package tlv
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
type TLV uint8
|
||||
"inet.af/netaddr"
|
||||
)
|
||||
|
||||
type Type uint8
|
||||
|
||||
const (
|
||||
Pad1 TLV = iota
|
||||
PadN
|
||||
AckReq
|
||||
Ack
|
||||
Hello
|
||||
IHU
|
||||
RouterID
|
||||
NextHop
|
||||
Update
|
||||
RouteRequest
|
||||
RouteUpdate
|
||||
TSPC
|
||||
HMAC
|
||||
TypePad1 = Type(0)
|
||||
TypePadN = Type(1)
|
||||
TypeAckReq = Type(2)
|
||||
TypeAck = Type(3)
|
||||
TypeHello = Type(4)
|
||||
TypeIHU = Type(5)
|
||||
TypeRouterID = Type(6)
|
||||
TypeNextHop = Type(7)
|
||||
TypeUpdate = Type(8)
|
||||
TypeRouteRequest = Type(9)
|
||||
TypeSeqnoRequest = Type(10)
|
||||
TypeTSPC = Type(11)
|
||||
TypeHMAC = Type(12)
|
||||
)
|
||||
|
||||
type TLV interface {
|
||||
T() Type
|
||||
L() uint8
|
||||
}
|
||||
|
||||
type SubType uint8
|
||||
|
||||
const (
|
||||
SubTypePad1 = SubType(0)
|
||||
SubTypePadN = SubType(1)
|
||||
SubTypeDiversity = SubType(2)
|
||||
SubTypeTimestamp = SubType(3)
|
||||
SubTypeSourcePrefix = SubType(128)
|
||||
)
|
||||
|
||||
type SubTLV interface {
|
||||
T() SubType
|
||||
L() uint8
|
||||
}
|
||||
|
||||
type Scanner struct {
|
||||
buf []byte
|
||||
err error
|
||||
t TLV
|
||||
t Type
|
||||
l uint8
|
||||
}
|
||||
|
||||
|
@ -34,6 +61,11 @@ func NewTLVScanner(buf []byte) *Scanner {
|
|||
}
|
||||
}
|
||||
|
||||
func (ts *Scanner) Reset(buf []byte) {
|
||||
*ts = Scanner{}
|
||||
ts.buf = buf
|
||||
}
|
||||
|
||||
func (ts *Scanner) Scan() bool {
|
||||
if ts.err != nil {
|
||||
return false
|
||||
|
@ -45,12 +77,23 @@ func (ts *Scanner) Scan() bool {
|
|||
|
||||
// move beginning of the buffer to the next TLV
|
||||
ts.buf = ts.buf[ts.l:]
|
||||
ts.t, ts.l = TLV(ts.buf[0]), 0
|
||||
ts.t, ts.l = Type(ts.buf[0]), 0
|
||||
|
||||
switch ts.t {
|
||||
case Pad1:
|
||||
case TypePad1:
|
||||
ts.buf = ts.buf[1:]
|
||||
default:
|
||||
case TypePadN,
|
||||
TypeAckReq,
|
||||
TypeAck,
|
||||
TypeHello,
|
||||
TypeIHU,
|
||||
TypeRouterID,
|
||||
TypeNextHop,
|
||||
TypeUpdate,
|
||||
TypeRouteRequest,
|
||||
TypeSeqnoRequest,
|
||||
TypeTSPC,
|
||||
TypeHMAC:
|
||||
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))
|
||||
|
@ -58,7 +101,10 @@ func (ts *Scanner) Scan() bool {
|
|||
}
|
||||
// move beginning of the buffer behind the header
|
||||
ts.buf = ts.buf[2:]
|
||||
default:
|
||||
panic("unknown type")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -66,9 +112,640 @@ 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]
|
||||
func (ts *Scanner) Raw() Raw {
|
||||
return Raw{ts.t, ts.l, ts.buf[:ts.l:ts.l]}
|
||||
}
|
||||
|
||||
type PacketDecoder struct {
|
||||
tlvscanner Scanner
|
||||
|
||||
// parser state
|
||||
routerID RouterID
|
||||
nexthopv6 netaddr.IP
|
||||
nexthopv4 netaddr.IP
|
||||
v6 [16]byte
|
||||
v4 [4]byte
|
||||
|
||||
tlv TLV
|
||||
subtlv []byte
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *PacketDecoder) Reset(b []byte, nexthop netaddr.IP) {
|
||||
*s = PacketDecoder{}
|
||||
s.tlvscanner.Reset(b)
|
||||
switch {
|
||||
case nexthop.Is6():
|
||||
s.nexthopv6 = nexthop
|
||||
case nexthop.Is4():
|
||||
s.nexthopv4 = nexthop
|
||||
}
|
||||
}
|
||||
func (s *PacketDecoder) Scan() bool {
|
||||
if s.err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if !s.tlvscanner.Scan() {
|
||||
if err := s.tlvscanner.Err(); err != nil {
|
||||
s.err = err
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
raw := s.tlvscanner.Raw()
|
||||
|
||||
switch raw.T() {
|
||||
case TypePad1:
|
||||
s.tlv, s.subtlv, s.err = Pad1FromBytes(raw.V())
|
||||
case TypePadN:
|
||||
s.tlv, s.subtlv, s.err = PadNFromBytes(raw.V())
|
||||
case TypeAckReq:
|
||||
s.tlv, s.subtlv, s.err = AckReqFromBytes(raw.V())
|
||||
case TypeAck:
|
||||
s.tlv, s.subtlv, s.err = AckFromBytes(raw.V())
|
||||
case TypeHello:
|
||||
s.tlv, s.subtlv, s.err = HelloFromBytes(raw.V())
|
||||
case TypeIHU:
|
||||
s.tlv, s.subtlv, s.err = IHUFromBytes(raw.V())
|
||||
case TypeRouterID:
|
||||
var rid RouterID
|
||||
rid, s.subtlv, s.err = RouterIDFromBytes(raw.V())
|
||||
if s.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
s.tlv = rid
|
||||
s.routerID = rid
|
||||
case TypeNextHop:
|
||||
var nh NextHop
|
||||
nh, s.subtlv, s.err = NextHopFromBytes(raw.V())
|
||||
if s.err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
s.tlv = nh
|
||||
|
||||
switch AEFromIP(nh.Address) {
|
||||
case 1:
|
||||
s.nexthopv4 = nh.Address
|
||||
case 2, 3:
|
||||
s.nexthopv6 = nh.Address
|
||||
}
|
||||
case TypeUpdate:
|
||||
s.tlv, s.subtlv, s.err = s.UpdateFromBytes(raw.V())
|
||||
case TypeRouteRequest:
|
||||
s.tlv, s.subtlv, s.err = RouteRequestFromBytes(raw.V())
|
||||
case TypeSeqnoRequest:
|
||||
s.tlv, s.subtlv, s.err = SeqnoRequestFromBytes(raw.V())
|
||||
case TypeTSPC:
|
||||
s.tlv = raw
|
||||
s.subtlv = nil
|
||||
case TypeHMAC:
|
||||
s.tlv = raw
|
||||
s.subtlv = nil
|
||||
default:
|
||||
s.err = fmt.Errorf("Unknown TLV Type: %+v", raw)
|
||||
}
|
||||
|
||||
return s.err == nil
|
||||
}
|
||||
func (s *PacketDecoder) TLV() TLV {
|
||||
if s.err != nil {
|
||||
return nil
|
||||
}
|
||||
return s.tlv
|
||||
}
|
||||
func (s *PacketDecoder) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
type Raw struct {
|
||||
t Type
|
||||
l uint8
|
||||
v []byte
|
||||
}
|
||||
|
||||
func (t Raw) T() Type {
|
||||
return t.t
|
||||
}
|
||||
|
||||
func (t Raw) L() uint8 {
|
||||
return t.l
|
||||
}
|
||||
|
||||
func (t Raw) V() []byte {
|
||||
return t.v
|
||||
}
|
||||
|
||||
type ErrTypeMismatch struct {
|
||||
want Type
|
||||
got Type
|
||||
}
|
||||
|
||||
func (e ErrTypeMismatch) Error() string {
|
||||
return fmt.Sprintf("Error parsing TLV: Wrong type %s, wanted %s", e.got, e.want)
|
||||
}
|
||||
|
||||
type ErrTLVLength struct {
|
||||
l int
|
||||
want int
|
||||
t Type
|
||||
}
|
||||
|
||||
func (e ErrTLVLength) Error() string {
|
||||
return fmt.Sprintf("Invalid TLV length: %d, Type %q needs at least %d", e.l, e.t, e.want)
|
||||
}
|
||||
func assertLengthGreater(b []byte, t Type, l int) error {
|
||||
if len(b) < l {
|
||||
return ErrTLVLength{len(b), l, t}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ErrSubTLVLength struct {
|
||||
l int
|
||||
want int
|
||||
t SubType
|
||||
}
|
||||
|
||||
func (e ErrSubTLVLength) Error() string {
|
||||
return fmt.Sprintf("Invalid SubTLV length: %d, Type %q needs at least %d", e.l, e.t, e.want)
|
||||
}
|
||||
func assertSubLengthGreater(b []byte, t SubType, l int) error {
|
||||
if len(b) < l {
|
||||
return ErrSubTLVLength{len(b), l, t}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Pad1 struct{}
|
||||
|
||||
func (Pad1) T() Type {
|
||||
return TypePad1
|
||||
}
|
||||
func (Pad1) L() uint8 {
|
||||
return 8
|
||||
}
|
||||
func Pad1FromBytes(b []byte) (Pad1, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypePad1, 0); err != nil {
|
||||
return Pad1{}, b, err
|
||||
}
|
||||
return Pad1{}, b[1:], nil
|
||||
}
|
||||
|
||||
type PadN uint8
|
||||
|
||||
func (PadN) T() Type {
|
||||
return TypePadN
|
||||
}
|
||||
func (p PadN) L() uint8 {
|
||||
return 2 + uint8(p) // TODO: overflow?
|
||||
}
|
||||
func PadNFromBytes(b []byte) (PadN, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypePadN, 0); err != nil {
|
||||
return PadN(0), b, err
|
||||
}
|
||||
return PadN(b[1]), b[1:], nil
|
||||
}
|
||||
|
||||
type AckReq struct {
|
||||
Opaque [2]byte
|
||||
Interval uint16
|
||||
}
|
||||
|
||||
func (AckReq) T() Type {
|
||||
return TypeAckReq
|
||||
}
|
||||
func (a AckReq) L() uint8 {
|
||||
return 8
|
||||
}
|
||||
func AckReqFromBytes(b []byte) (AckReq, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeAckReq, 6); err != nil {
|
||||
return AckReq{}, b, err
|
||||
}
|
||||
var ar AckReq
|
||||
|
||||
ar.Opaque[0] = b[2]
|
||||
ar.Opaque[1] = b[3]
|
||||
ar.Interval = uint16(b[4])<<8 | uint16(b[5])
|
||||
|
||||
return ar, b[6:], nil
|
||||
}
|
||||
|
||||
type Ack struct {
|
||||
Opaque uint16
|
||||
}
|
||||
|
||||
func (Ack) T() Type {
|
||||
return TypeAck
|
||||
}
|
||||
|
||||
func (Ack) L() uint8 {
|
||||
return 4
|
||||
}
|
||||
|
||||
func AckFromBytes(b []byte) (Ack, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeAck, 2); err != nil {
|
||||
return Ack{}, b, err
|
||||
}
|
||||
|
||||
return Ack{uint16(b[0])<<8 | uint16(b[1])}, b[4:], nil
|
||||
}
|
||||
|
||||
type Hello struct {
|
||||
Flags uint16
|
||||
Seqno uint16
|
||||
Interval uint16
|
||||
}
|
||||
|
||||
func (Hello) T() Type {
|
||||
return TypeHello
|
||||
}
|
||||
func (Hello) L() uint8 {
|
||||
return 8
|
||||
}
|
||||
func HelloFromBytes(b []byte) (Hello, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeHello, 6); err != nil {
|
||||
return Hello{}, b, err
|
||||
}
|
||||
var h Hello
|
||||
|
||||
h.Flags = uint16(b[0])<<8 | uint16(b[1])
|
||||
h.Seqno = uint16(b[2])<<8 | uint16(b[3])
|
||||
h.Interval = uint16(b[4])<<8 | uint16(b[5])
|
||||
|
||||
return h, b[6:], nil
|
||||
}
|
||||
|
||||
type IHU struct {
|
||||
// AE uint8
|
||||
// reserved uint8
|
||||
Rxcost uint16
|
||||
Interval uint16
|
||||
Address netaddr.IP
|
||||
}
|
||||
|
||||
func (IHU) T() Type {
|
||||
return TypeIHU
|
||||
}
|
||||
func (i IHU) AE() uint8 {
|
||||
return AEFromIP(i.Address)
|
||||
}
|
||||
func (i IHU) L() uint8 {
|
||||
switch i.AE() {
|
||||
case 0:
|
||||
return 6 // Header only
|
||||
case 1:
|
||||
return 6 + 4 // IPv4 - no compression
|
||||
case 2:
|
||||
return 6 + 16 // IPv6 - no compression
|
||||
case 3:
|
||||
return 6 + 8 // IPv6 Link Local
|
||||
}
|
||||
panic("invalid AE field")
|
||||
}
|
||||
func IHUFromBytes(b []byte) (IHU, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeIHU, 6); err != nil {
|
||||
return IHU{}, b, err
|
||||
}
|
||||
|
||||
var ihu IHU
|
||||
var err error
|
||||
|
||||
ae := b[0]
|
||||
ihu.Rxcost = uint16(b[2])<<8 | uint16(b[3])
|
||||
ihu.Interval = uint16(b[4])<<8 | uint16(b[5])
|
||||
ihu.Address, b, err = ipFromBytes(ae, b[6:])
|
||||
|
||||
return ihu, b, err
|
||||
}
|
||||
|
||||
type RouterID [8]byte
|
||||
|
||||
var (
|
||||
ErrRouterIDZeros = errors.New("Invalid RouterID: consists of all zeros")
|
||||
ErrRouterIDOnes = errors.New("Invalid RouterID: consists of all ones")
|
||||
)
|
||||
|
||||
func RouterIDFromBytes(b []byte) (RouterID, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeRouterID, 10); err != nil {
|
||||
return RouterID{}, b, err
|
||||
}
|
||||
|
||||
// skip 2 reserved bytes
|
||||
var rid RouterID
|
||||
copy(rid[:], b[2:])
|
||||
b = b[10:]
|
||||
|
||||
if rid == (RouterID{}) {
|
||||
return RouterID{}, b, ErrRouterIDZeros
|
||||
}
|
||||
if rid == (RouterID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) {
|
||||
return RouterID{}, b, ErrRouterIDOnes
|
||||
}
|
||||
|
||||
return rid, b, nil
|
||||
}
|
||||
|
||||
func (RouterID) T() Type {
|
||||
return TypeRouterID
|
||||
}
|
||||
|
||||
func (RouterID) L() uint8 {
|
||||
return 8
|
||||
}
|
||||
|
||||
func (r RouterID) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.Grow(8*3 - 1)
|
||||
for i, b := range r {
|
||||
if i > 0 {
|
||||
buf.WriteByte(':')
|
||||
}
|
||||
fmt.Fprintf(&buf, "%02x", b)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type NextHop struct {
|
||||
// AE uint8
|
||||
// reserved uint8
|
||||
Address netaddr.IP
|
||||
}
|
||||
|
||||
func (NextHop) T() Type {
|
||||
return TypeNextHop
|
||||
}
|
||||
func (n NextHop) L() uint8 {
|
||||
switch AEFromIP(n.Address) {
|
||||
case 1:
|
||||
return 2 + 4 // IPv4 - no compression
|
||||
case 2:
|
||||
return 2 + 16 // IPv6 - no compression
|
||||
case 3:
|
||||
return 2 + 8 // IPv6 Link Local
|
||||
}
|
||||
panic("invalid AE field")
|
||||
}
|
||||
func NextHopFromBytes(b []byte) (NextHop, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeNextHop, 6); err != nil {
|
||||
return NextHop{}, b, err
|
||||
}
|
||||
|
||||
var nh NextHop
|
||||
var err error
|
||||
ae := b[0]
|
||||
nh.Address, b, err = ipFromBytes(ae, b[2:])
|
||||
return nh, b, err
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
// AE uint8
|
||||
Flags uint8
|
||||
// Plen uint8
|
||||
Omitted uint8
|
||||
Interval uint16
|
||||
Seqno uint16
|
||||
Metric uint16
|
||||
Prefix netaddr.IPPrefix
|
||||
NextHop netaddr.IP
|
||||
}
|
||||
|
||||
func (Update) T() Type {
|
||||
return TypeUpdate
|
||||
}
|
||||
|
||||
func (u Update) L() uint8 {
|
||||
return 10 + psizeFromPlen(u.Prefix.Bits())
|
||||
}
|
||||
|
||||
func (u Update) FormatHeader() string {
|
||||
return fmt.Sprintf("Flags 0x%02x Omitted %2d Interval %4d Seqno %5d Metric %5d NextHop %s",
|
||||
u.Flags, u.Omitted, u.Interval, u.Seqno, u.Metric, u.NextHop,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *PacketDecoder) UpdateFromBytes(b []byte) (Update, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeUpdate, 10); err != nil {
|
||||
return Update{}, b, err
|
||||
}
|
||||
var u Update
|
||||
var err error
|
||||
|
||||
ae := b[0]
|
||||
u.Flags = b[1]
|
||||
plen := b[2]
|
||||
u.Omitted = b[3]
|
||||
u.Interval = uint16(b[4])<<8 | uint16(b[5])
|
||||
u.Seqno = uint16(b[6])<<8 | uint16(b[7])
|
||||
u.Metric = uint16(b[8])<<8 | uint16(b[8])
|
||||
|
||||
b = b[10:]
|
||||
switch ae {
|
||||
case 0:
|
||||
case 1:
|
||||
u.Prefix, b, err = prefixV4Default(s.v4, plen, u.Omitted, b)
|
||||
if u.Flags&0x80 > 0 {
|
||||
s.v4 = u.Prefix.IP().As4()
|
||||
}
|
||||
u.NextHop = s.nexthopv4
|
||||
case 2:
|
||||
u.Prefix, b, err = prefixV6Default(s.v6, plen, u.Omitted, b)
|
||||
if u.Flags&0x80 > 0 {
|
||||
s.v6 = u.Prefix.IP().As16()
|
||||
}
|
||||
u.NextHop = s.nexthopv6
|
||||
case 3:
|
||||
u.Prefix, b, err = prefixV6LL(b)
|
||||
u.NextHop = s.nexthopv6
|
||||
}
|
||||
|
||||
return u, b, err
|
||||
}
|
||||
|
||||
func AEFromPrefix(p netaddr.IPPrefix) uint8 {
|
||||
return AEFromIP(p.IP())
|
||||
}
|
||||
func AEFromIP(p netaddr.IP) uint8 {
|
||||
if p.IsZero() {
|
||||
return 0
|
||||
}
|
||||
if p.Is4() {
|
||||
return 1
|
||||
}
|
||||
if p.IsLinkLocalUnicast() {
|
||||
return 3
|
||||
}
|
||||
if p.Is6() {
|
||||
return 2
|
||||
}
|
||||
panic("unknown AE")
|
||||
}
|
||||
|
||||
type RouteRequest struct {
|
||||
// AE uint8
|
||||
// plen uint8
|
||||
Prefix netaddr.IPPrefix
|
||||
}
|
||||
|
||||
func (r RouteRequest) AE() uint8 {
|
||||
return AEFromPrefix(r.Prefix)
|
||||
}
|
||||
func (RouteRequest) T() Type {
|
||||
return TypeRouteRequest
|
||||
}
|
||||
func (r RouteRequest) L() uint8 {
|
||||
return 4 + psizeFromPlen(r.Prefix.Bits())
|
||||
}
|
||||
func RouteRequestFromBytes(b []byte) (RouteRequest, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeRouteRequest, 2); err != nil {
|
||||
return RouteRequest{}, b, err
|
||||
}
|
||||
var rr RouteRequest
|
||||
var err error
|
||||
|
||||
rr.Prefix, b, err = prefixUncompressed(b[0], b[1], b[2:])
|
||||
|
||||
return rr, b, err
|
||||
}
|
||||
|
||||
type SeqnoRequest struct {
|
||||
// AE uint8
|
||||
// Plen uint8
|
||||
Seqno uint16
|
||||
HopCount uint8
|
||||
RouterID RouterID
|
||||
Prefix netaddr.IPPrefix
|
||||
}
|
||||
|
||||
func (SeqnoRequest) T() Type {
|
||||
return TypeSeqnoRequest
|
||||
}
|
||||
func (r SeqnoRequest) L() uint8 {
|
||||
return 14 + psizeFromPlen(r.Prefix.Bits())
|
||||
}
|
||||
func SeqnoRequestFromBytes(b []byte) (SeqnoRequest, []byte, error) {
|
||||
if err := assertLengthGreater(b, TypeSeqnoRequest, 14); err != nil {
|
||||
return SeqnoRequest{}, b, err
|
||||
}
|
||||
|
||||
var err error
|
||||
var sr SeqnoRequest
|
||||
|
||||
ae := b[0]
|
||||
plen := b[1]
|
||||
sr.Seqno = uint16(b[2])<<8 | uint16(b[3])
|
||||
sr.HopCount = b[4]
|
||||
copy(sr.RouterID[:], b[6:])
|
||||
sr.Prefix, b, err = prefixUncompressed(ae, plen, b[14:])
|
||||
|
||||
return sr, b, err
|
||||
}
|
||||
|
||||
type SourcePrefix struct {
|
||||
netaddr.IPPrefix
|
||||
}
|
||||
|
||||
func (SourcePrefix) T() SubType {
|
||||
return SubTypeSourcePrefix
|
||||
}
|
||||
func (s SourcePrefix) L() uint8 {
|
||||
return psizeFromPlen(s.Bits())
|
||||
}
|
||||
func SourcePrefixFromBytes(b []byte) (SourcePrefix, []byte, error) {
|
||||
if err := assertSubLengthGreater(b, SubTypeSourcePrefix, 2); err != nil {
|
||||
return SourcePrefix{}, b, err
|
||||
}
|
||||
|
||||
plen := b[0] // TODO: error on 0
|
||||
b = b[1:]
|
||||
pfx, b, err := prefixUncompressed(2, plen, b)
|
||||
|
||||
return SourcePrefix{pfx}, b, err
|
||||
}
|
||||
|
||||
func psizeFromPlen(plen uint8) uint8 {
|
||||
return uint8((uint16(plen) + 7) / 8)
|
||||
}
|
||||
func prefixUncompressed(ae uint8, plen uint8, b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
if len(b) < int(psizeFromPlen(plen)) {
|
||||
return netaddr.IPPrefix{}, b, fmt.Errorf("plen too large")
|
||||
}
|
||||
|
||||
switch ae {
|
||||
case 0:
|
||||
return prefixWildcard()
|
||||
case 1:
|
||||
return prefixV4(plen, b)
|
||||
case 2:
|
||||
return prefixV6(plen, b)
|
||||
case 3:
|
||||
return prefixV6LL(b)
|
||||
default:
|
||||
return netaddr.IPPrefix{}, b, fmt.Errorf("Invalid AE %d", ae)
|
||||
}
|
||||
}
|
||||
|
||||
func prefixWildcard() (netaddr.IPPrefix, []byte, error) {
|
||||
return netaddr.IPPrefix{}, nil, nil
|
||||
}
|
||||
|
||||
func prefixV4(plen uint8, b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
return prefixV4Default([4]byte{}, plen, 0, b)
|
||||
}
|
||||
func prefixV4Default(ip4default [4]byte, plen uint8, omit uint8, b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
var ip4 [4]byte
|
||||
psize := psizeFromPlen(plen) - omit
|
||||
copy(ip4[:], ip4default[:omit])
|
||||
copy(ip4[omit:], b[:psize])
|
||||
return netaddr.IPPrefixFrom(netaddr.IPFrom4(ip4), plen), b[psize:], nil
|
||||
}
|
||||
func prefixV6(plen uint8, b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
return prefixV6Default([16]byte{}, plen, 0, b)
|
||||
}
|
||||
func prefixV6Default(ip6default [16]byte, plen uint8, omit uint8, b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
var ip6 [16]byte
|
||||
psize := psizeFromPlen(plen) - omit
|
||||
copy(ip6[:], ip6default[:omit])
|
||||
copy(ip6[omit:], b[:psize])
|
||||
return netaddr.IPPrefixFrom(netaddr.IPv6Raw(ip6), plen), b[psize:], nil
|
||||
}
|
||||
func prefixV6LL(b []byte) (netaddr.IPPrefix, []byte, error) {
|
||||
var ip6ll [16]byte
|
||||
ip6ll[0] = 0xfe
|
||||
ip6ll[1] = 0x80
|
||||
copy(ip6ll[8:], b[:8])
|
||||
return netaddr.IPPrefixFrom(netaddr.IPv6Raw(ip6ll), 8), b[8:], nil
|
||||
}
|
||||
func ipFromBytes(ae uint8, b []byte) (netaddr.IP, []byte, error) {
|
||||
switch ae {
|
||||
case 0:
|
||||
return netaddr.IP{}, b, nil
|
||||
case 1:
|
||||
if len(b) < 4 {
|
||||
return netaddr.IP{}, b, fmt.Errorf("Not enough bytes for v4 address: %d", len(b))
|
||||
}
|
||||
var ip4 [4]byte
|
||||
copy(ip4[:], b[:4])
|
||||
return netaddr.IPFrom4(ip4), b[4:], nil
|
||||
case 2:
|
||||
if len(b) < 16 {
|
||||
return netaddr.IP{}, b, fmt.Errorf("Not enough bytes for v6 address: %d", len(b))
|
||||
}
|
||||
var ip6 [16]byte
|
||||
copy(ip6[:], b[:16])
|
||||
return netaddr.IPv6Raw(ip6), b[16:], nil
|
||||
case 3:
|
||||
if len(b) < 8 {
|
||||
return netaddr.IP{}, b, fmt.Errorf("Not enough bytes for v6ll address: %d", len(b))
|
||||
}
|
||||
var ip6ll [16]byte
|
||||
ip6ll[0] = 0xfe
|
||||
ip6ll[1] = 0x80
|
||||
copy(ip6ll[8:], b[:8])
|
||||
return netaddr.IPv6Raw(ip6ll), b[8:], nil
|
||||
default:
|
||||
return netaddr.IP{}, b, fmt.Errorf("Invalid AE %d", ae)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// 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,41 @@
|
|||
package tlv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRouterIDFailZeros(t *testing.T) {
|
||||
zeros := [10]byte{}
|
||||
if _, _, err := RouterIDFromBytes(zeros[:]); err != ErrRouterIDZeros {
|
||||
t.Error("RouterIDFromBytes should fail with ErrRouterIDZeros")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterIDFailOnes(t *testing.T) {
|
||||
ones := [10]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
if _, _, err := RouterIDFromBytes(ones[:]); err != ErrRouterIDOnes {
|
||||
t.Error("RouterIDFromBytes should fail with ErrRouterIDOnes")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterIDFailLength(t *testing.T) {
|
||||
testbytes := [300]byte{}
|
||||
for i := 0; i <= len(testbytes); i++ {
|
||||
_, _, err := RouterIDFromBytes(testbytes[:i])
|
||||
l, isErrRouterIDLength := err.(ErrTLVLength)
|
||||
|
||||
switch {
|
||||
case i >= 10:
|
||||
if isErrRouterIDLength {
|
||||
t.Error("RouterIDFromBytes returns ErrRouterIDLength for correct length data")
|
||||
}
|
||||
default:
|
||||
if l.l != i {
|
||||
t.Errorf("RouterIDFromBytes returns wrong length %d, expected %d", l, i)
|
||||
}
|
||||
if !isErrRouterIDLength {
|
||||
t.Errorf("RouterIDFromBytes returns wrong error for packet of wrong length %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "stringer -type=Type -trimprefix Type"; 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[TypePad1-0]
|
||||
_ = x[TypePadN-1]
|
||||
_ = x[TypeAckReq-2]
|
||||
_ = x[TypeAck-3]
|
||||
_ = x[TypeHello-4]
|
||||
_ = x[TypeIHU-5]
|
||||
_ = x[TypeRouterID-6]
|
||||
_ = x[TypeNextHop-7]
|
||||
_ = x[TypeUpdate-8]
|
||||
_ = x[TypeRouteRequest-9]
|
||||
_ = x[TypeSeqnoRequest-10]
|
||||
_ = x[TypeTSPC-11]
|
||||
_ = x[TypeHMAC-12]
|
||||
}
|
||||
|
||||
const _Type_name = "Pad1PadNAckReqAckHelloIHURouterIDNextHopUpdateRouteRequestSeqnoRequestTSPCHMAC"
|
||||
|
||||
var _Type_index = [...]uint8{0, 4, 8, 14, 17, 22, 25, 33, 40, 46, 58, 70, 74, 78}
|
||||
|
||||
func (i Type) String() string {
|
||||
if i >= Type(len(_Type_index)-1) {
|
||||
return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Type_name[_Type_index[i]:_Type_index[i+1]]
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
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