diff --git a/protocols/bgp/packet/bgp.go b/protocols/bgp/packet/bgp.go index c3a80b93aa666e18525e702d12530d66381c36c9..dc3dfc1451df2d865a8d50dc92c2fb1f67f3d639 100644 --- a/protocols/bgp/packet/bgp.go +++ b/protocols/bgp/packet/bgp.go @@ -60,6 +60,9 @@ const ( AggregatorAttr = 7 CommunitiesAttr = 8 + AS4PathAttr = 17 + AS4AggregatorAttr = 18 + // ORIGIN values IGP = 0 EGP = 1 diff --git a/protocols/bgp/packet/decoder_test.go b/protocols/bgp/packet/decoder_test.go index c2222e6da95735a9faeedbb5db8cc12fbe34fb74..19a83a960c956378415d2c1792abce344dbb76dc 100644 --- a/protocols/bgp/packet/decoder_test.go +++ b/protocols/bgp/packet/decoder_test.go @@ -1347,6 +1347,84 @@ func TestDecodeUpdateMsg(t *testing.T) { wantFail: true, expected: nil, }, + { + // 2 withdraws with four path attributes (Communities + AS4Path +AS4Aggregator + Origin), valid update + testNum: 19, + input: []byte{0, 5, 8, 10, 16, 192, 168, + 0, 30, // Total Path Attribute Length + + 0, // Attribute flags + 8, // Attribute Type code (Community) + 8, // Length + 0, 0, 1, 0, // Arbitrary Community + 0, 0, 1, 1, // Arbitrary Community + + 128, // Attribute flags + 17, // Attribute Type code (AS4Path) + 4, // Length + 0, 0, 2, 3, // Arbitrary Bytes + + 128, // Attribute flags + 18, // Attribute Type code (AS4Aggregator) + 4, // Length + 0, 0, 2, 3, // Arbitrary Bytes + + 255, // Attribute flags + 1, // Attribute Type code (ORIGIN) + 0, 1, // Length + 2, // INCOMPLETE + + }, + wantFail: false, + expected: &BGPUpdate{ + WithdrawnRoutesLen: 5, + WithdrawnRoutes: &NLRI{ + IP: strAddr("10.0.0.0"), + Pfxlen: 8, + Next: &NLRI{ + IP: strAddr("192.168.0.0"), + Pfxlen: 16, + }, + }, + TotalPathAttrLen: 30, + PathAttributes: &PathAttribute{ + Optional: false, + Transitive: false, + Partial: false, + ExtendedLength: false, + Length: 8, + TypeCode: 8, + Value: []uint32{256, 257}, + Next: &PathAttribute{ + Optional: true, + Transitive: false, + Partial: false, + ExtendedLength: false, + Length: 4, + TypeCode: 17, + Value: uint32(515), + Next: &PathAttribute{ + Optional: true, + Transitive: false, + Partial: false, + ExtendedLength: false, + Length: 4, + TypeCode: 18, + Value: uint32(515), + Next: &PathAttribute{ + Optional: true, + Transitive: true, + Partial: true, + ExtendedLength: true, + Length: 1, + TypeCode: 1, + Value: uint8(2), + }, + }, + }, + }, + }, + }, } for _, test := range tests { diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index 846767989f400f1ede2fcf1e2c9202f33ad10974..753395d2c67a844863e067f27ec45bed1a29cda2 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -88,6 +88,14 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err if err := pa.decodeCommunities(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err) } + case AS4PathAttr: + if err := pa.decodeAS4Path(buf); err != nil { + return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Path: %v", err) + } + case AS4AggregatorAttr: + if err := pa.decodeAS4Aggregator(buf); err != nil { + return nil, consumed, fmt.Errorf("Failed to skip not supported AS4Aggregator: %v", err) + } default: if err := pa.decodeUnknown(buf); err != nil { return nil, consumed, fmt.Errorf("Failed to decode unknown attribute: %v", err) @@ -252,6 +260,26 @@ func (pa *PathAttribute) decodeCommunities(buf *bytes.Buffer) error { return nil } +func (pa *PathAttribute) decodeAS4Path(buf *bytes.Buffer) error { + as4Path, err := pa.decodeUint32(buf) + if err != nil { + return fmt.Errorf("Unable to decode AS4Path: %v", err) + } + + pa.Value = as4Path + return nil +} + +func (pa *PathAttribute) decodeAS4Aggregator(buf *bytes.Buffer) error { + as4Aggregator, err := pa.decodeUint32(buf) + if err != nil { + return fmt.Errorf("Unable to decode AS4Aggregator: %v", err) + } + + pa.Value = as4Aggregator + return nil +} + func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) { bytesRead := 0 if pa.ExtendedLength {