From 3b73956a9c3b3401d9db200b6144134944f0b6f6 Mon Sep 17 00:00:00 2001 From: Ben Cartwright-Cox Date: Wed, 22 Feb 2023 15:17:26 +0000 Subject: [PATCH] Add PDU encode/decode support for ASPA --- lib/client_test.go | 27 ++++++++++++++++ lib/structs.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/lib/client_test.go b/lib/client_test.go index 3c67685..8832948 100644 --- a/lib/client_test.go +++ b/lib/client_test.go @@ -126,3 +126,30 @@ func TestRouterKeyEncodeDecode(t *testing.T) { t.FailNow() } } + +func TestASPAEncodeDecode(t *testing.T) { + p := &PDUASPA{ + Version: 1, + Flags: 1, + AFIFlags: 1, + ProviderASCount: 2, + CustomerASNumber: 64497, + ProviderASNumbers: []uint32{64498, 64499}, + } + + buf := bytes.NewBuffer(nil) + p.Write(buf) + + outputPdu, err := Decode(buf) + + if err != nil { + t.FailNow() + } + + orig := fmt.Sprintf("%#v", p) + decode := fmt.Sprintf("%#v", outputPdu) + if orig != decode { + t.Fatalf("%s\n is not\n%s", orig, decode) + t.FailNow() + } +} diff --git a/lib/structs.go b/lib/structs.go index 7f13107..bbecbbf 100644 --- a/lib/structs.go +++ b/lib/structs.go @@ -23,6 +23,7 @@ const ( PROTOCOL_VERSION_0 = 0 PROTOCOL_VERSION_1 = 1 + PROTOCOL_VERSION_2 = 2 PDU_ID_SERIAL_NOTIFY = 0 PDU_ID_SERIAL_QUERY = 1 @@ -34,6 +35,7 @@ const ( PDU_ID_CACHE_RESET = 8 PDU_ID_ROUTER_KEY = 9 PDU_ID_ERROR_REPORT = 10 + PDU_ID_ASPA = 11 FLAG_ADDED = 1 FLAG_REMOVED = 0 @@ -84,6 +86,8 @@ func TypeToString(t uint8) string { return "Router Key" case PDU_ID_ERROR_REPORT: return "Error Report" + case PDU_ID_ASPA: + return "ASPA PDU" default: return fmt.Sprintf("Unknown type %d", t) } @@ -509,6 +513,51 @@ func (pdu *PDUErrorReport) Write(wr io.Writer) { } } +type PDUASPA struct { + Version uint8 + Flags uint8 + AFIFlags uint8 + ProviderASCount uint16 + CustomerASNumber uint32 + ProviderASNumbers []uint32 +} + +func (pdu *PDUASPA) String() string { + return fmt.Sprintf("PDU ASPA v%d TODO", pdu.Version) // TODO +} + +func (pdu *PDUASPA) Bytes() []byte { + b := bytes.NewBuffer([]byte{}) + pdu.Write(b) + return b.Bytes() +} + +func (pdu *PDUASPA) SetVersion(version uint8) { + pdu.Version = version +} + +func (pdu *PDUASPA) GetVersion() uint8 { + return pdu.Version +} + +func (pdu *PDUASPA) GetType() uint8 { + return PDU_ID_ASPA +} + +func (pdu *PDUASPA) Write(wr io.Writer) { + binary.Write(wr, binary.BigEndian, uint8(pdu.Version)) + binary.Write(wr, binary.BigEndian, uint8(PDU_ID_ASPA)) + binary.Write(wr, binary.BigEndian, uint16(0)) + binary.Write(wr, binary.BigEndian, uint32(16+(len(pdu.ProviderASNumbers)*4))) + binary.Write(wr, binary.BigEndian, uint8(pdu.Flags)) + binary.Write(wr, binary.BigEndian, uint8(pdu.AFIFlags)) + binary.Write(wr, binary.BigEndian, uint16(pdu.ProviderASCount)) + binary.Write(wr, binary.BigEndian, uint32(pdu.CustomerASNumber)) + for _, pasn := range pdu.ProviderASNumbers { + binary.Write(wr, binary.BigEndian, uint32(pasn)) + } +} + func DecodeBytes(b []byte) (PDU, error) { buf := bytes.NewBuffer(b) return Decode(buf) @@ -694,6 +743,35 @@ func Decode(rdr io.Reader) (PDU, error) { PDUCopy: errPdu, ErrorMsg: errMsg, }, nil + case PDU_ID_ASPA: + if len(toread) < 8 { + return nil, fmt.Errorf("wrong length for ASPA PDU: %d < 16", len(toread)) + } + + aspaFlag := uint8(toread[0]) + aspaAFIFlag := uint8(toread[1]) + PASCount := binary.BigEndian.Uint16(toread[2:4]) + CASN := binary.BigEndian.Uint32(toread[4:8]) + + PASNs := make([]uint32, 0) + rbuf := bytes.NewReader(toread[8:]) + for i := 0; i < int(PASCount); i++ { + var asn uint32 + err := binary.Read(rbuf, binary.BigEndian, &asn) + if err != nil { + return nil, err + } + PASNs = append(PASNs, asn) + } + + return &PDUASPA{ + Version: pver, + Flags: aspaFlag, + AFIFlags: aspaAFIFlag, + ProviderASCount: PASCount, + CustomerASNumber: CASN, + ProviderASNumbers: PASNs, + }, nil default: return nil, errors.New("could not decode packet") }