diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index e66e834a199abde91d7c5d6d27003977d782c998..748e36535f049ddb31955e8e86078aef209641cd 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -390,6 +390,8 @@ func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *Options) uint8 { pathAttrLen = pa.serializeCommunities(buf) case LargeCommunitiesAttr: pathAttrLen = pa.serializeLargeCommunities(buf) + default: + pathAttrLen = pa.serializeUnknownAttribute(buf) } return pathAttrLen @@ -546,6 +548,23 @@ func (pa *PathAttribute) serializeLargeCommunities(buf *bytes.Buffer) uint8 { return length } +func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint8 { + attrFlags := uint8(0) + if pa.Optional { + attrFlags = setOptional(attrFlags) + } + attrFlags = setTransitive(attrFlags) + + buf.WriteByte(attrFlags) + buf.WriteByte(pa.TypeCode) + + b := pa.Value.([]byte) + buf.WriteByte(uint8(len(b))) + buf.Write(b) + + return uint8(len(b) + 2) +} + func fourBytesToUint32(address [4]byte) uint32 { return uint32(address[0])<<24 + uint32(address[1])<<16 + uint32(address[2])<<8 + uint32(address[3]) } diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index 96200f4dc8f355da9b640388b097a3a2a9cc5062..fbf1d4806e127b1b2e4b15255a11e018bd00bbaf 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -1345,6 +1345,41 @@ func TestSerializeCommunities(t *testing.T) { } } +func TestSerializeUnknownAttribute(t *testing.T) { + tests := []struct { + name string + input *PathAttribute + expected []byte + expectedLen uint8 + }{ + { + name: "Arbritary attribute", + input: &PathAttribute{ + TypeCode: 200, + Value: []byte{1, 2, 3, 4}, + Transitive: true, + }, + expected: []byte{ + 64, // Attribute flags + 200, // Type + 4, // Length + 1, 2, 3, 4, // Payload + }, + expectedLen: 6, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + buf := bytes.NewBuffer(nil) + n := test.input.serializeUnknownAttribute(buf) + + assert.Equal(t, test.expectedLen, n) + assert.Equal(t, test.expected, buf.Bytes()) + }) + } +} + func TestSerialize(t *testing.T) { tests := []struct { name string