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 748e36535f049ddb31955e8e86078aef209641cd..b2b8367c82e9e6f08ff09b893d953588aa4e77aa 100644 --- a/protocols/bgp/packet/path_attributes.go +++ b/protocols/bgp/packet/path_attributes.go @@ -368,28 +368,28 @@ func dumpNBytes(buf *bytes.Buffer, n uint16) error { return nil } -func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *Options) uint8 { - pathAttrLen := uint8(0) +func (pa *PathAttribute) serialize(buf *bytes.Buffer, opt *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) } @@ -548,21 +548,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 fbf1d4806e127b1b2e4b15255a11e018bd00bbaf..31f3c9f33b713c21bb31f9a7382faeaa42d7413c 100644 --- a/protocols/bgp/packet/path_attributes_test.go +++ b/protocols/bgp/packet/path_attributes_test.go @@ -1350,7 +1350,7 @@ func TestSerializeUnknownAttribute(t *testing.T) { name string input *PathAttribute expected []byte - expectedLen uint8 + expectedLen uint16 }{ { name: "Arbritary attribute", @@ -1367,6 +1367,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 {