diff --git a/.gitignore b/.gitignore index 4732630cb517f763bfc35f781811cf2176e72c2a..bb99a56915e4f0f56746244dbb3affd0ee20712a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ # IDE specific files .idea/ *.iml +.vscode # 'go build' binary bio-rd diff --git a/protocols/bgp/packet/path_attributes.go b/protocols/bgp/packet/path_attributes.go index efb3e1ec581630abb166f62ac21608d3ef5be9dc..000f0d8e95fe82ca67c8d57e9601dc090e58ca6f 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -373,28 +373,28 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error { } // Serialize serializes a path attribute -func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint8 { - pathAttrLen := uint8(0) +func (pa *PathAttribute) Serialize(buf *bytes.Buffer, opt *types.Options) uint16 { + pathAttrLen := uint16(0) switch pa.TypeCode { case OriginAttr: - pathAttrLen = pa.serializeOrigin(buf) + pathAttrLen = uint16(pa.serializeOrigin(buf)) case ASPathAttr: - pathAttrLen = pa.serializeASPath(buf, opt) + pathAttrLen = uint16(pa.serializeASPath(buf, opt)) case NextHopAttr: - pathAttrLen = pa.serializeNextHop(buf) + pathAttrLen = uint16(pa.serializeNextHop(buf)) case MEDAttr: - pathAttrLen = pa.serializeMED(buf) + pathAttrLen = uint16(pa.serializeMED(buf)) case LocalPrefAttr: - pathAttrLen = pa.serializeLocalpref(buf) + pathAttrLen = uint16(pa.serializeLocalpref(buf)) case AtomicAggrAttr: - pathAttrLen = pa.serializeAtomicAggregate(buf) + pathAttrLen = uint16(pa.serializeAtomicAggregate(buf)) case AggregatorAttr: - pathAttrLen = pa.serializeAggregator(buf) + pathAttrLen = uint16(pa.serializeAggregator(buf)) case CommunitiesAttr: - pathAttrLen = pa.serializeCommunities(buf) + pathAttrLen = uint16(pa.serializeCommunities(buf)) case LargeCommunitiesAttr: - pathAttrLen = pa.serializeLargeCommunities(buf) + pathAttrLen = uint16(pa.serializeLargeCommunities(buf)) default: pathAttrLen = pa.serializeUnknownAttribute(buf) } @@ -552,21 +552,30 @@ func (pa *PathAttribute) serializeLargeCommunities(buf *bytes.Buffer) uint8 { return length } -func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint8 { +func (pa *PathAttribute) serializeUnknownAttribute(buf *bytes.Buffer) uint16 { attrFlags := uint8(0) if pa.Optional { attrFlags = setOptional(attrFlags) } + if pa.ExtendedLength { + attrFlags = setExtendedLength(attrFlags) + } attrFlags = setTransitive(attrFlags) buf.WriteByte(attrFlags) buf.WriteByte(pa.TypeCode) b := pa.Value.([]byte) - buf.WriteByte(uint8(len(b))) + if pa.ExtendedLength { + l := len(b) + buf.WriteByte(uint8(l >> 8)) + buf.WriteByte(uint8(l & 0x0000FFFF)) + } else { + buf.WriteByte(uint8(len(b))) + } buf.Write(b) - return uint8(len(b) + 2) + return uint16(len(b) + 2) } func fourBytesToUint32(address [4]byte) uint32 { diff --git a/protocols/bgp/packet/path_attributes_test.go b/protocols/bgp/packet/path_attributes_test.go index ec1b80758faf3e226e1b1f209b6680bfddd05807..93a0b2e515f0dfb9f0a0dde543085a37fb3c52c3 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -1348,7 +1348,7 @@ func TestSerializeUnknownAttribute(t *testing.T) { name string input *PathAttribute expected []byte - expectedLen uint8 + expectedLen uint16 }{ { name: "Arbritary attribute", @@ -1365,6 +1365,36 @@ func TestSerializeUnknownAttribute(t *testing.T) { }, expectedLen: 6, }, + { + name: "Extended length", + input: &PathAttribute{ + TypeCode: 200, + Value: make([]byte, 256), + Transitive: true, + ExtendedLength: true, + }, + expected: []byte{ + 80, // Attribute flags + 200, // Type + 1, 0, // Length + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Payload + }, + expectedLen: 258, + }, } for _, test := range tests { diff --git a/route/bgp_path.go b/route/bgp_path.go index 2c56c9681676d7290c88b2b5450366417b243bb6..9945739b62a2318dca4e7553a2487f9527c70b2e 100644 --- a/route/bgp_path.go +++ b/route/bgp_path.go @@ -255,8 +255,8 @@ func (b *BGPPath) insertNewASSequence() { pa := make(types.ASPath, len(b.ASPath)+1) copy(pa[1:], b.ASPath) pa[0] = types.ASPathSegment{ - ASNs: make([]uint32, 0), - Type: packet.ASSequence, + ASNs: make([]uint32, 0), + Type: types.ASSequence, } b.ASPath = pa