2021-12-13 06:55:52 +01:00
|
|
|
//go:generate stringer -type=Type -trimprefix Type
|
|
|
|
//go:generate stringer -type=SubType -trimprefix SubType
|
2021-12-14 05:46:54 +01:00
|
|
|
//go:generate stringer -type=AEType -trimprefix AE
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// Package tlv implements a parser for TLV encoded babel messages defined in rfc8966
|
|
|
|
//
|
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4
|
|
|
|
// https://datatracker.ietf.org/doc/html/draft-ietf-babel-source-specific-07#section-7
|
2021-12-08 11:41:29 +01:00
|
|
|
package tlv
|
|
|
|
|
2021-12-13 06:55:52 +01:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2023-03-07 01:59:19 +01:00
|
|
|
"net/netip"
|
2021-12-13 06:55:52 +01:00
|
|
|
)
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Type encodes the type of TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
type Type uint8
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Type TLV constants
|
2021-12-13 06:55:52 +01:00
|
|
|
const (
|
|
|
|
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)
|
|
|
|
)
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// TLV holds a single TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
type TLV interface {
|
|
|
|
T() Type
|
|
|
|
L() uint8
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// SubType encodes the type of Sub-TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
type SubType uint8
|
2021-12-08 11:41:29 +01:00
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// IsMandatory checks if a Sub-TLV is mandatory
|
2021-12-14 05:47:41 +01:00
|
|
|
func (s SubType) IsMandatory() bool {
|
|
|
|
return s >= 128
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// SubType Sub-TLV constants
|
2021-12-08 11:41:29 +01:00
|
|
|
const (
|
2021-12-13 06:55:52 +01:00
|
|
|
SubTypePad1 = SubType(0)
|
|
|
|
SubTypePadN = SubType(1)
|
|
|
|
SubTypeDiversity = SubType(2)
|
|
|
|
SubTypeTimestamp = SubType(3)
|
|
|
|
SubTypeSourcePrefix = SubType(128)
|
2021-12-08 11:41:29 +01:00
|
|
|
)
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// SubTLV holds a single Sub-TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
type SubTLV interface {
|
|
|
|
T() SubType
|
|
|
|
L() uint8
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// AEType encodes the AE field in TLVs
|
2021-12-14 05:46:54 +01:00
|
|
|
type AEType uint8
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// AEType AE constants
|
2021-12-14 05:46:54 +01:00
|
|
|
const (
|
|
|
|
AEWildcard = AEType(0)
|
|
|
|
AEIPv4 = AEType(1)
|
|
|
|
AEIPv6 = AEType(2)
|
|
|
|
AEIPv6LL = AEType(3)
|
|
|
|
AEIPv4oIPv6 = AEType(4)
|
|
|
|
)
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// AEFromPrefix returns the address encoding of a prefix:
|
2023-03-07 01:59:19 +01:00
|
|
|
func AEFromPrefix(p netip.Prefix) AEType {
|
|
|
|
return AEFromIP(p.Addr())
|
2021-12-14 05:46:54 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// AEFromIP returns the address encoding of an address.
|
2023-03-07 01:59:19 +01:00
|
|
|
func AEFromIP(p netip.Addr) AEType {
|
2021-12-14 05:46:54 +01:00
|
|
|
switch {
|
2023-03-07 01:59:19 +01:00
|
|
|
case p.IsUnspecified():
|
2021-12-14 05:46:54 +01:00
|
|
|
return AEWildcard
|
|
|
|
case p.Is4():
|
|
|
|
return AEIPv4
|
|
|
|
case p.IsLinkLocalUnicast():
|
|
|
|
return AEIPv6LL
|
|
|
|
case p.Is6():
|
|
|
|
return AEIPv6
|
|
|
|
}
|
|
|
|
panic("unknown AE")
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Scanner splits bytes into TLV tokens.
|
2021-12-08 11:41:29 +01:00
|
|
|
type Scanner struct {
|
|
|
|
buf []byte
|
|
|
|
err error
|
2021-12-13 06:55:52 +01:00
|
|
|
t Type
|
2021-12-08 11:41:29 +01:00
|
|
|
l uint8
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Reset resets a scanner state and sets a new byte slice to work on.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (ts *Scanner) Reset(buf []byte) {
|
|
|
|
*ts = Scanner{}
|
|
|
|
ts.buf = buf
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Scan scans for the next TLV
|
|
|
|
//
|
|
|
|
// Returns true if a TLV is found, or false on error or no more TLVs are found.
|
2021-12-08 11:41:29 +01:00
|
|
|
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:]
|
2021-12-13 06:55:52 +01:00
|
|
|
ts.t, ts.l = Type(ts.buf[0]), 0
|
2021-12-08 11:41:29 +01:00
|
|
|
|
|
|
|
switch ts.t {
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypePad1:
|
2021-12-08 11:41:29 +01:00
|
|
|
ts.buf = ts.buf[1:]
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypePadN,
|
|
|
|
TypeAckReq,
|
|
|
|
TypeAck,
|
|
|
|
TypeHello,
|
|
|
|
TypeIHU,
|
|
|
|
TypeRouterID,
|
|
|
|
TypeNextHop,
|
|
|
|
TypeUpdate,
|
|
|
|
TypeRouteRequest,
|
|
|
|
TypeSeqnoRequest,
|
|
|
|
TypeTSPC,
|
|
|
|
TypeHMAC:
|
2021-12-08 11:41:29 +01:00
|
|
|
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:]
|
2021-12-13 06:55:52 +01:00
|
|
|
default:
|
|
|
|
panic("unknown type")
|
2021-12-08 11:41:29 +01:00
|
|
|
}
|
2021-12-13 06:55:52 +01:00
|
|
|
|
2021-12-08 11:41:29 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Err returns the first error that occured during scanning.
|
2021-12-08 11:41:29 +01:00
|
|
|
func (ts *Scanner) Err() error {
|
|
|
|
return ts.err
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Raw returns an unparsed TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
func (ts *Scanner) Raw() Raw {
|
|
|
|
return Raw{ts.t, ts.l, ts.buf[:ts.l:ts.l]}
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// PacketDecoder splits a packet into TLVs and parses their content
|
2021-12-13 06:55:52 +01:00
|
|
|
type PacketDecoder struct {
|
|
|
|
tlvscanner Scanner
|
|
|
|
|
|
|
|
// parser state
|
|
|
|
routerID RouterID
|
2023-03-07 01:59:19 +01:00
|
|
|
nexthopv6 netip.Addr
|
|
|
|
nexthopv4 netip.Addr
|
2021-12-13 06:55:52 +01:00
|
|
|
v6 [16]byte
|
|
|
|
v4 [4]byte
|
|
|
|
|
|
|
|
tlv TLV
|
|
|
|
subtlv []byte
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Reset clears the parser state and sets a new byte slice to work on.
|
2023-03-07 01:59:19 +01:00
|
|
|
func (s *PacketDecoder) Reset(b []byte, nexthop netip.Addr, ifindex int) {
|
2021-12-13 06:55:52 +01:00
|
|
|
*s = PacketDecoder{}
|
|
|
|
s.tlvscanner.Reset(b)
|
|
|
|
switch {
|
|
|
|
case nexthop.Is6():
|
|
|
|
s.nexthopv6 = nexthop
|
|
|
|
case nexthop.Is4():
|
|
|
|
s.nexthopv4 = nexthop
|
|
|
|
}
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// Scan parses the next TLV.
|
|
|
|
// Returns true on success or false on error and when no more TLVs can be found.
|
2021-12-13 06:55:52 +01:00
|
|
|
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:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = pad1FromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypePadN:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = padNFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeAckReq:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = ackReqFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeAck:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = ackFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeHello:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = helloFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeIHU:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = ihuFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeRouterID:
|
|
|
|
var rid RouterID
|
2021-12-14 07:02:01 +01:00
|
|
|
rid, s.subtlv, s.err = routerIDFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
if s.err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
s.tlv = rid
|
|
|
|
s.routerID = rid
|
|
|
|
case TypeNextHop:
|
|
|
|
var nh NextHop
|
2021-12-14 07:02:01 +01:00
|
|
|
nh, s.subtlv, s.err = nextHopFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
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:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = s.updateFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeRouteRequest:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = routeRequestFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
case TypeSeqnoRequest:
|
2021-12-14 07:02:01 +01:00
|
|
|
s.tlv, s.subtlv, s.err = seqnoRequestFromBytes(raw.V())
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// TLV returns the last successfully parsed TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
func (s *PacketDecoder) TLV() TLV {
|
|
|
|
if s.err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return s.tlv
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// SubTLV returns the last successfully parsed Sub-TLV
|
2021-12-14 05:47:41 +01:00
|
|
|
func (s *PacketDecoder) SubTLV() []byte {
|
|
|
|
if s.err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return s.subtlv
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// Err returns the first error that occured during parsing.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (s *PacketDecoder) Err() error {
|
|
|
|
return s.err
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Raw holds an unparsed TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
type Raw struct {
|
|
|
|
t Type
|
|
|
|
l uint8
|
|
|
|
v []byte
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns the Type of a Raw TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
func (t Raw) T() Type {
|
|
|
|
return t.t
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// L returns the value of the length field in a TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
func (t Raw) L() uint8 {
|
|
|
|
return t.l
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// V returns the message body of a TLV
|
2021-12-13 06:55:52 +01:00
|
|
|
func (t Raw) V() []byte {
|
|
|
|
return t.v
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// ErrTLVLength is used to inform about invalid length fields in TLVs
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// ErrSubTLVLength is used to inform about invalid length fields in Sub-TLVs
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Pad1 TLV
|
|
|
|
//
|
|
|
|
// 1 byte padding that is silently ignored.
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.1
|
2021-12-13 06:55:52 +01:00
|
|
|
type Pad1 struct{}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypePad1.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Pad1) T() Type {
|
|
|
|
return TypePad1
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L returns 0 message body length.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Pad1) L() uint8 {
|
2021-12-14 07:02:01 +01:00
|
|
|
return 0
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
func pad1FromBytes(b []byte) (Pad1, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if err := assertLengthGreater(b, TypePad1, 0); err != nil {
|
|
|
|
return Pad1{}, b, err
|
|
|
|
}
|
|
|
|
return Pad1{}, b[1:], nil
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// PadN TLV
|
|
|
|
//
|
|
|
|
// Multi byte padding that is silently ignored.
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.2
|
2021-12-13 06:55:52 +01:00
|
|
|
type PadN uint8
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypePadN.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (PadN) T() Type {
|
|
|
|
return TypePadN
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L returns the length of the padding.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (p PadN) L() uint8 {
|
2021-12-14 07:02:01 +01:00
|
|
|
return uint8(p)
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
func padNFromBytes(b []byte) (PadN, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if err := assertLengthGreater(b, TypePadN, 0); err != nil {
|
|
|
|
return PadN(0), b, err
|
|
|
|
}
|
|
|
|
return PadN(b[1]), b[1:], nil
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// AckReq - Acknowledgment Request TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.3
|
2021-12-13 06:55:52 +01:00
|
|
|
type AckReq struct {
|
|
|
|
Opaque [2]byte
|
|
|
|
Interval uint16
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypePadReq.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (AckReq) T() Type {
|
|
|
|
return TypeAckReq
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L 8.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (a AckReq) L() uint8 {
|
|
|
|
return 8
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func ackReqFromBytes(b []byte) (AckReq, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Ack - Acknowledgment TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.4
|
2021-12-13 06:55:52 +01:00
|
|
|
type Ack struct {
|
|
|
|
Opaque uint16
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeAck.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Ack) T() Type {
|
|
|
|
return TypeAck
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L is 4.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Ack) L() uint8 {
|
|
|
|
return 4
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func ackFromBytes(b []byte) (Ack, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if err := assertLengthGreater(b, TypeAck, 2); err != nil {
|
|
|
|
return Ack{}, b, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ack{uint16(b[0])<<8 | uint16(b[1])}, b[4:], nil
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Hello TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.5
|
2021-12-13 06:55:52 +01:00
|
|
|
type Hello struct {
|
|
|
|
Flags uint16
|
|
|
|
Seqno uint16
|
|
|
|
Interval uint16
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeHello.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Hello) T() Type {
|
|
|
|
return TypeHello
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L is 8.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Hello) L() uint8 {
|
|
|
|
return 8
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func helloFromBytes(b []byte) (Hello, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// IHU - I Heard You TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.6
|
2021-12-13 06:55:52 +01:00
|
|
|
type IHU struct {
|
|
|
|
// AE uint8
|
|
|
|
// reserved uint8
|
|
|
|
Rxcost uint16
|
|
|
|
Interval uint16
|
2023-03-07 01:59:19 +01:00
|
|
|
Address netip.Addr
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeIHU.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (IHU) T() Type {
|
|
|
|
return TypeIHU
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// AE returns the address encofing
|
2021-12-14 05:46:54 +01:00
|
|
|
func (i IHU) AE() AEType {
|
2021-12-13 06:55:52 +01:00
|
|
|
return AEFromIP(i.Address)
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the address enoding, but is at least 6 bytes.
|
2021-12-13 06:55:52 +01:00
|
|
|
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")
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func ihuFromBytes(b []byte) (IHU, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if err := assertLengthGreater(b, TypeIHU, 6); err != nil {
|
|
|
|
return IHU{}, b, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var ihu IHU
|
|
|
|
var err error
|
|
|
|
|
2021-12-14 05:46:54 +01:00
|
|
|
ae := AEType(b[0])
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// RouterID TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.7
|
2021-12-13 06:55:52 +01:00
|
|
|
type RouterID [8]byte
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Errors specific to RouterID.
|
2021-12-13 06:55:52 +01:00
|
|
|
var (
|
|
|
|
ErrRouterIDZeros = errors.New("Invalid RouterID: consists of all zeros")
|
|
|
|
ErrRouterIDOnes = errors.New("Invalid RouterID: consists of all ones")
|
|
|
|
)
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
func routerIDFromBytes(b []byte) (RouterID, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// T returns TypeRouterID.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (RouterID) T() Type {
|
|
|
|
return TypeRouterID
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L is 8.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (RouterID) L() uint8 {
|
|
|
|
return 8
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// String formats a Routerid in EUI-64
|
2021-12-13 06:55:52 +01:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// NextHop TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.8
|
2021-12-13 06:55:52 +01:00
|
|
|
type NextHop struct {
|
|
|
|
// AE uint8
|
|
|
|
// reserved uint8
|
2023-03-07 01:59:19 +01:00
|
|
|
Address netip.Addr
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeNextHop.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (NextHop) T() Type {
|
|
|
|
return TypeNextHop
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the address encoding, at least 2.
|
2021-12-13 06:55:52 +01:00
|
|
|
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")
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func nextHopFromBytes(b []byte) (NextHop, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if err := assertLengthGreater(b, TypeNextHop, 6); err != nil {
|
|
|
|
return NextHop{}, b, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var nh NextHop
|
|
|
|
var err error
|
2021-12-14 05:46:54 +01:00
|
|
|
ae := AEType(b[0])
|
2021-12-13 06:55:52 +01:00
|
|
|
nh.Address, b, err = ipFromBytes(ae, b[2:])
|
|
|
|
return nh, b, err
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// Update TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.9
|
2021-12-13 06:55:52 +01:00
|
|
|
type Update struct {
|
|
|
|
// AE uint8
|
|
|
|
Flags uint8
|
|
|
|
// Plen uint8
|
|
|
|
Omitted uint8
|
|
|
|
Interval uint16
|
|
|
|
Seqno uint16
|
|
|
|
Metric uint16
|
2021-12-13 08:45:58 +01:00
|
|
|
RouterID RouterID
|
2023-03-07 01:59:19 +01:00
|
|
|
Prefix netip.Prefix
|
|
|
|
NextHop netip.Addr
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeUpdate.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (Update) T() Type {
|
|
|
|
return TypeUpdate
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the anounced prefix, at least 10.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (u Update) L() uint8 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return 10 + psizeFromPlen(uint8(u.Prefix.Bits()))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// FormatHeader returns a string of the most important fields except the prefix
|
2021-12-13 06:55:52 +01:00
|
|
|
func (u Update) FormatHeader() string {
|
2021-12-13 08:45:58 +01:00
|
|
|
return fmt.Sprintf("Flags 0x%02x Omitted %2d Interval %4d Seqno %5d Metric %5d RouterID %s",
|
|
|
|
u.Flags, u.Omitted, u.Interval, u.Seqno, u.Metric, u.RouterID,
|
2021-12-13 06:55:52 +01:00
|
|
|
)
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func (s *PacketDecoder) updateFromBytes(b []byte) (Update, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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 {
|
2023-03-07 01:59:19 +01:00
|
|
|
s.v4 = u.Prefix.Addr().As4()
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
u.NextHop = s.nexthopv4
|
|
|
|
case 2:
|
|
|
|
u.Prefix, b, err = prefixV6Default(s.v6, plen, u.Omitted, b)
|
|
|
|
if u.Flags&0x80 > 0 {
|
2023-03-07 01:59:19 +01:00
|
|
|
s.v6 = u.Prefix.Addr().As16()
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
u.NextHop = s.nexthopv6
|
|
|
|
case 3:
|
|
|
|
u.Prefix, b, err = prefixV6LL(b)
|
|
|
|
u.NextHop = s.nexthopv6
|
|
|
|
}
|
|
|
|
|
2021-12-13 08:45:58 +01:00
|
|
|
if u.Flags&0x40 > 0 {
|
2023-03-07 01:59:19 +01:00
|
|
|
addr := u.Prefix.Addr()
|
2021-12-13 08:45:58 +01:00
|
|
|
switch {
|
|
|
|
case addr.Is6():
|
|
|
|
v6 := addr.As16()
|
|
|
|
copy(s.routerID[:], v6[8:])
|
|
|
|
case addr.Is4():
|
|
|
|
s.routerID = RouterID{}
|
|
|
|
v4 := addr.As4()
|
|
|
|
copy(s.routerID[4:], v4[:])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u.RouterID = s.routerID
|
|
|
|
|
2021-12-13 06:55:52 +01:00
|
|
|
return u, b, err
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// RouteRequest TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.10
|
2021-12-13 06:55:52 +01:00
|
|
|
type RouteRequest struct {
|
|
|
|
// AE uint8
|
|
|
|
// plen uint8
|
2023-03-07 01:59:19 +01:00
|
|
|
Prefix netip.Prefix
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// AE returns the address encoding of the requested prefix
|
2021-12-14 05:46:54 +01:00
|
|
|
func (r RouteRequest) AE() AEType {
|
2021-12-13 06:55:52 +01:00
|
|
|
return AEFromPrefix(r.Prefix)
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// T returns TypeRouteRequest.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (RouteRequest) T() Type {
|
|
|
|
return TypeRouteRequest
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the requested prefix, at least 4.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (r RouteRequest) L() uint8 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return 4 + psizeFromPlen(uint8(r.Prefix.Bits()))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func routeRequestFromBytes(b []byte) (RouteRequest, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// SeqnoRequest TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/rfc8966#section-4.6.11
|
2021-12-13 06:55:52 +01:00
|
|
|
type SeqnoRequest struct {
|
|
|
|
// AE uint8
|
|
|
|
// Plen uint8
|
|
|
|
Seqno uint16
|
|
|
|
HopCount uint8
|
|
|
|
RouterID RouterID
|
2023-03-07 01:59:19 +01:00
|
|
|
Prefix netip.Prefix
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns TypeSeqnoRequest.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (SeqnoRequest) T() Type {
|
|
|
|
return TypeSeqnoRequest
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the requested prefix, at least 14.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (r SeqnoRequest) L() uint8 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return 14 + psizeFromPlen(uint8(r.Prefix.Bits()))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
func seqnoRequestFromBytes(b []byte) (SeqnoRequest, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// SourcePrefix Sub-TLV
|
|
|
|
//
|
2021-12-14 05:57:58 +01:00
|
|
|
// https://datatracker.ietf.org/doc/html/draft-ietf-babel-source-specific-07#section-7.1
|
2021-12-13 06:55:52 +01:00
|
|
|
type SourcePrefix struct {
|
2023-03-07 01:59:19 +01:00
|
|
|
netip.Prefix
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2021-12-14 07:02:01 +01:00
|
|
|
// T returns SubTypeSourcePrefix.
|
2021-12-13 06:55:52 +01:00
|
|
|
func (SourcePrefix) T() SubType {
|
|
|
|
return SubTypeSourcePrefix
|
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// L depends on the encoded prefix
|
2021-12-13 06:55:52 +01:00
|
|
|
func (s SourcePrefix) L() uint8 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return psizeFromPlen(uint8(s.Bits()))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2021-12-14 07:02:01 +01:00
|
|
|
|
|
|
|
// SourcePrefixFromBytes parses a SourcePrefix SubTLV
|
2021-12-13 06:55:52 +01:00
|
|
|
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)
|
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixUncompressed(ae uint8, plen uint8, b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
if len(b) < int(psizeFromPlen(plen)) {
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Prefix{}, b, fmt.Errorf("plen too large")
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
switch ae {
|
|
|
|
case 0:
|
|
|
|
return prefixWildcard()
|
|
|
|
case 1:
|
|
|
|
return prefixV4(plen, b)
|
|
|
|
case 2:
|
|
|
|
return prefixV6(plen, b)
|
|
|
|
case 3:
|
|
|
|
return prefixV6LL(b)
|
|
|
|
default:
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Prefix{}, b, fmt.Errorf("Invalid AE %d", ae)
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixWildcard() (netip.Prefix, []byte, error) {
|
|
|
|
return netip.Prefix{}, nil, nil
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixV4(plen uint8, b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
return prefixV4Default([4]byte{}, plen, 0, b)
|
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixV4Default(ip4default [4]byte, plen uint8, omit uint8, b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
var ip4 [4]byte
|
|
|
|
psize := psizeFromPlen(plen) - omit
|
|
|
|
copy(ip4[:], ip4default[:omit])
|
|
|
|
copy(ip4[omit:], b[:psize])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.PrefixFrom(netip.AddrFrom4(ip4), int(plen)), b[psize:], nil
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixV6(plen uint8, b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
return prefixV6Default([16]byte{}, plen, 0, b)
|
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixV6Default(ip6default [16]byte, plen uint8, omit uint8, b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
var ip6 [16]byte
|
|
|
|
psize := psizeFromPlen(plen) - omit
|
|
|
|
copy(ip6[:], ip6default[:omit])
|
|
|
|
copy(ip6[omit:], b[:psize])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.PrefixFrom(netip.AddrFrom16(ip6), int(plen)), b[psize:], nil
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func prefixV6LL(b []byte) (netip.Prefix, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
var ip6ll [16]byte
|
|
|
|
ip6ll[0] = 0xfe
|
|
|
|
ip6ll[1] = 0x80
|
|
|
|
copy(ip6ll[8:], b[:8])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.PrefixFrom(netip.AddrFrom16(ip6ll), 8), b[8:], nil
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2023-03-07 01:59:19 +01:00
|
|
|
func ipFromBytes(ae AEType, b []byte) (netip.Addr, []byte, error) {
|
2021-12-13 06:55:52 +01:00
|
|
|
switch ae {
|
2021-12-14 05:46:54 +01:00
|
|
|
case AEWildcard:
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, nil
|
2021-12-14 05:46:54 +01:00
|
|
|
case AEIPv4:
|
2021-12-13 06:55:52 +01:00
|
|
|
if len(b) < 4 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, fmt.Errorf("Not enough bytes for v4 address: %d", len(b))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
2023-03-09 09:09:53 +01:00
|
|
|
//var ip4 [4]byte
|
|
|
|
//copy(ip4[:], b[:4])
|
|
|
|
ip4 := [4]byte(b[:4])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.AddrFrom4(ip4), b[4:], nil
|
2021-12-14 05:46:54 +01:00
|
|
|
case AEIPv6:
|
2021-12-13 06:55:52 +01:00
|
|
|
if len(b) < 16 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, fmt.Errorf("Not enough bytes for v6 address: %d", len(b))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
var ip6 [16]byte
|
|
|
|
copy(ip6[:], b[:16])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.AddrFrom16(ip6), b[16:], nil
|
2021-12-14 05:46:54 +01:00
|
|
|
case AEIPv6LL:
|
2021-12-13 06:55:52 +01:00
|
|
|
if len(b) < 8 {
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, fmt.Errorf("Not enough bytes for v6ll address: %d", len(b))
|
2021-12-13 06:55:52 +01:00
|
|
|
}
|
|
|
|
var ip6ll [16]byte
|
|
|
|
ip6ll[0] = 0xfe
|
|
|
|
ip6ll[1] = 0x80
|
|
|
|
copy(ip6ll[8:], b[:8])
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.AddrFrom16(ip6ll), b[8:], nil
|
2021-12-14 05:46:54 +01:00
|
|
|
case AEIPv4oIPv6:
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, fmt.Errorf("Not implemented AE Type %s", ae)
|
2021-12-13 06:55:52 +01:00
|
|
|
default:
|
2023-03-07 01:59:19 +01:00
|
|
|
return netip.Addr{}, b, fmt.Errorf("Invalid AE %d", ae)
|
2021-12-08 11:41:29 +01:00
|
|
|
}
|
|
|
|
}
|