summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'packet/bgp')
-rw-r--r--packet/bgp/bgp.go536
-rw-r--r--packet/bgp/helper.go2
-rw-r--r--packet/bgp/validate.go61
3 files changed, 310 insertions, 289 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index 2128289b..d585133e 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -72,9 +72,9 @@ const (
)
const (
- BGP_ORIGIN_ATTR_TYPE_IGP = 0
- BGP_ORIGIN_ATTR_TYPE_EGP = 1
- BGP_ORIGIN_ATTR_TYPE_INCOMPLETE = 2
+ BGP_ORIGIN_ATTR_TYPE_IGP uint8 = 0
+ BGP_ORIGIN_ATTR_TYPE_EGP uint8 = 1
+ BGP_ORIGIN_ATTR_TYPE_INCOMPLETE uint8 = 2
)
const (
@@ -4875,21 +4875,14 @@ type PathAttributeInterface interface {
type PathAttribute struct {
Flags BGPAttrFlag
Type BGPAttrType
- Length uint16
- Value []byte
+ Length uint16 // length of Value
}
func (p *PathAttribute) Len(options ...*MarshallingOption) int {
- if p.Length == 0 {
- p.Length = uint16(len(p.Value))
- }
- l := 2 + p.Length
if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 {
- l += 2
- } else {
- l += 1
+ return 4 + int(p.Length)
}
- return int(l)
+ return 3 + int(p.Length)
}
func (p *PathAttribute) GetFlags() BGPAttrFlag {
@@ -4900,84 +4893,96 @@ func (p *PathAttribute) GetType() BGPAttrType {
return p.Type
}
-func (p *PathAttribute) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- odata := data
+func (p *PathAttribute) DecodeFromBytes(data []byte, options ...*MarshallingOption) (value []byte, err error) {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
if len(data) < 2 {
- return NewMessageError(eCode, eSubCode, data, "attribute header length is short")
+ return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short")
}
p.Flags = BGPAttrFlag(data[0])
p.Type = BGPAttrType(data[1])
+ if eMsg := validatePathAttributeFlags(p.Type, p.Flags); eMsg != "" {
+ return nil, NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data, eMsg)
+ }
if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 {
if len(data) < 4 {
- return NewMessageError(eCode, eSubCode, data, "attribute header length is short")
+ return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short")
}
p.Length = binary.BigEndian.Uint16(data[2:4])
data = data[4:]
} else {
if len(data) < 3 {
- return NewMessageError(eCode, eSubCode, data, "attribute header length is short")
+ return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short")
}
p.Length = uint16(data[2])
data = data[3:]
}
if len(data) < int(p.Length) {
- return NewMessageError(eCode, eSubCode, data, "attribute value length is short")
- }
- if len(data[:p.Length]) > 0 {
- p.Value = data[:p.Length]
+ return nil, NewMessageError(eCode, eSubCode, data, "attribute value length is short")
}
- ok, eMsg := ValidateFlags(p.Type, p.Flags)
- if !ok {
- return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, odata[:p.Len(options...)], eMsg)
- }
- return nil
+ return data[:p.Length], nil
}
-func (p *PathAttribute) Serialize(options ...*MarshallingOption) ([]byte, error) {
- p.Length = uint16(len(p.Value))
- if p.Length > 255 {
+func (p *PathAttribute) Serialize(value []byte, options ...*MarshallingOption) ([]byte, error) {
+ p.Length = uint16(len(value))
+ if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH == 0 && p.Length > 255 {
p.Flags |= BGP_ATTR_FLAG_EXTENDED_LENGTH
- } else {
- p.Flags &^= BGP_ATTR_FLAG_EXTENDED_LENGTH
}
- buf := make([]byte, p.Len(options...))
- buf[0] = uint8(p.Flags)
- buf[1] = uint8(p.Type)
+ var buf []byte
if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 {
+ buf = append(make([]byte, 4), value...)
binary.BigEndian.PutUint16(buf[2:4], p.Length)
- copy(buf[4:], p.Value)
} else {
+ buf = append(make([]byte, 3), value...)
buf[2] = byte(p.Length)
- copy(buf[3:], p.Value)
}
+ buf[0] = uint8(p.Flags)
+ buf[1] = uint8(p.Type)
return buf, nil
}
func (p *PathAttribute) String() string {
- return fmt.Sprintf("%s %s %s", p.Type.String(), p.Flags, []byte(p.Value))
+ return fmt.Sprintf("{Type: %s, Flags: %s}", p.Type, p.Flags)
}
func (p *PathAttribute) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type BGPAttrType `json:"type"`
- Value []byte `json:"value"`
+ Flags BGPAttrFlag `json:"flags"`
}{
Type: p.GetType(),
- Value: p.Value,
+ Flags: p.Flags,
})
}
type PathAttributeOrigin struct {
PathAttribute
+ Value uint8
+}
+
+func (p *PathAttributeOrigin) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
+ if err != nil {
+ return err
+ }
+ if p.Length != 1 {
+ eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
+ eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
+ return NewMessageError(eCode, eSubCode, nil, "Origin attribute length is incorrect")
+ }
+ p.Value = value[0]
+ return nil
+}
+
+func (p *PathAttributeOrigin) Serialize(options ...*MarshallingOption) ([]byte, error) {
+ return p.PathAttribute.Serialize([]byte{p.Value}, options...)
}
func (p *PathAttributeOrigin) String() string {
typ := "-"
- switch p.Value[0] {
+ switch p.Value {
case BGP_ORIGIN_ATTR_TYPE_IGP:
typ = "i"
case BGP_ORIGIN_ATTR_TYPE_EGP:
@@ -4994,19 +4999,18 @@ func (p *PathAttributeOrigin) MarshalJSON() ([]byte, error) {
Value uint8 `json:"value"`
}{
Type: p.GetType(),
- Value: p.Value[0],
+ Value: p.Value,
})
}
func NewPathAttributeOrigin(value uint8) *PathAttributeOrigin {
t := BGP_ATTR_TYPE_ORIGIN
return &PathAttributeOrigin{
-
PathAttribute: PathAttribute{
Flags: PathAttrFlags[t],
Type: t,
- Value: []byte{byte(value)},
},
+ Value: value,
}
}
@@ -5206,92 +5210,41 @@ func NewAs4PathParam(segType uint8, as []uint32) *As4PathParam {
}
}
-type DefaultAsPath struct {
-}
-
-func (p *DefaultAsPath) isValidAspath(data []byte) (bool, error) {
- eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
- eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH)
- if len(data)%2 != 0 {
- return false, NewMessageError(eCode, eSubCode, nil, "AS PATH length is not odd")
- }
-
- tryParse := func(data []byte, use4byte bool) (bool, error) {
- for len(data) > 0 {
- if len(data) < 2 {
- return false, NewMessageError(eCode, eSubCode, nil, "AS PATH header is short")
- }
- segType := data[0]
- if segType == 0 || segType > 4 {
- return false, NewMessageError(eCode, eSubCode, nil, "unknown AS_PATH seg type")
- }
- asNum := data[1]
- data = data[2:]
- if asNum == 0 || int(asNum) > math.MaxUint8 {
- return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect")
- }
- segLength := int(asNum)
- if use4byte == true {
- segLength *= 4
- } else {
- segLength *= 2
- }
- if int(segLength) > len(data) {
- return false, NewMessageError(eCode, eSubCode, nil, "seg length is short")
- }
- data = data[segLength:]
- }
- return true, nil
- }
- _, err := tryParse(data, true)
- if err == nil {
- return true, nil
- }
-
- _, err = tryParse(data, false)
- if err == nil {
- return false, nil
- }
- return false, NewMessageError(eCode, eSubCode, nil, "can't parse AS_PATH")
-}
-
type PathAttributeAsPath struct {
- DefaultAsPath
PathAttribute
Value []AsPathParamInterface
}
func (p *PathAttributeAsPath) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if p.PathAttribute.Length == 0 {
+ if p.Length == 0 {
// ibgp or something
return nil
}
- as4Bytes, err := p.DefaultAsPath.isValidAspath(p.PathAttribute.Value)
+ isAs4, err := validateAsPathValueBytes(value)
if err != nil {
- err.(*MessageError).Data = data[:p.Len(options...)]
+ err.(*MessageError).Data, _ = p.PathAttribute.Serialize(value, options...)
return err
}
- v := p.PathAttribute.Value
- for len(v) > 0 {
+ for len(value) > 0 {
var tuple AsPathParamInterface
- if as4Bytes == true {
+ if isAs4 == true {
tuple = &As4PathParam{}
} else {
tuple = &AsPathParam{}
}
- err := tuple.DecodeFromBytes(v)
+ err := tuple.DecodeFromBytes(value)
if err != nil {
return err
}
p.Value = append(p.Value, tuple)
- if tuple.Len() > len(v) {
+ if tuple.Len() > len(value) {
}
- v = v[tuple.Len():]
+ value = value[tuple.Len():]
}
return nil
}
@@ -5305,8 +5258,7 @@ func (p *PathAttributeAsPath) Serialize(options ...*MarshallingOption) ([]byte,
}
buf = append(buf, vbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeAsPath) String() string {
@@ -5344,22 +5296,21 @@ type PathAttributeNextHop struct {
}
func (p *PathAttributeNextHop) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 4 && len(p.PathAttribute.Value) != 16 {
+ if p.Length != 4 && p.Length != 16 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "nexthop length isn't correct")
}
- p.Value = p.PathAttribute.Value
+ p.Value = value
return nil
}
func (p *PathAttributeNextHop) Serialize(options ...*MarshallingOption) ([]byte, error) {
- p.PathAttribute.Value = p.Value
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(p.Value, options...)
}
func (p *PathAttributeNextHop) String() string {
@@ -5397,24 +5348,23 @@ type PathAttributeMultiExitDisc struct {
}
func (p *PathAttributeMultiExitDisc) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 4 {
+ if p.Length != 4 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "med length isn't correct")
}
- p.Value = binary.BigEndian.Uint32(p.PathAttribute.Value)
+ p.Value = binary.BigEndian.Uint32(value)
return nil
}
func (p *PathAttributeMultiExitDisc) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, p.Value)
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeMultiExitDisc) String() string {
@@ -5448,24 +5398,23 @@ type PathAttributeLocalPref struct {
}
func (p *PathAttributeLocalPref) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 4 {
+ if p.Length != 4 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "local pref length isn't correct")
}
- p.Value = binary.BigEndian.Uint32(p.PathAttribute.Value)
+ p.Value = binary.BigEndian.Uint32(value)
return nil
}
func (p *PathAttributeLocalPref) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, p.Value)
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeLocalPref) String() string {
@@ -5497,6 +5446,23 @@ type PathAttributeAtomicAggregate struct {
PathAttribute
}
+func (p *PathAttributeAtomicAggregate) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
+ _, err := p.PathAttribute.DecodeFromBytes(data, options...)
+ if err != nil {
+ return err
+ }
+ if p.Length != 0 {
+ eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
+ eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
+ return NewMessageError(eCode, eSubCode, nil, "atomic aggregate should have no value")
+ }
+ return nil
+}
+
+func (p *PathAttributeAtomicAggregate) Serialize(options ...*MarshallingOption) ([]byte, error) {
+ return p.PathAttribute.Serialize(nil, options...)
+}
+
func (p *PathAttributeAtomicAggregate) String() string {
return "{AtomicAggregate}"
}
@@ -5531,24 +5497,24 @@ type PathAttributeAggregator struct {
}
func (p *PathAttributeAggregator) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 6 && len(p.PathAttribute.Value) != 8 {
+ switch p.Length {
+ case 6:
+ p.Value.Askind = reflect.Uint16
+ p.Value.AS = uint32(binary.BigEndian.Uint16(value[0:2]))
+ p.Value.Address = value[2:]
+ case 8:
+ p.Value.Askind = reflect.Uint32
+ p.Value.AS = binary.BigEndian.Uint32(value[0:4])
+ p.Value.Address = value[4:]
+ default:
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "aggregator length isn't correct")
}
- if len(p.PathAttribute.Value) == 6 {
- p.Value.AS = uint32(binary.BigEndian.Uint16(p.PathAttribute.Value[0:2]))
- p.Value.Address = p.PathAttribute.Value[2:]
- p.Value.Askind = reflect.Uint16
- } else {
- p.Value.AS = binary.BigEndian.Uint32(p.PathAttribute.Value[0:4])
- p.Value.Address = p.PathAttribute.Value[4:]
- p.Value.Askind = reflect.Uint32
- }
return nil
}
@@ -5564,9 +5530,7 @@ func (p *PathAttributeAggregator) Serialize(options ...*MarshallingOption) ([]by
binary.BigEndian.PutUint32(buf, p.Value.AS)
copy(buf[4:], p.Value.Address)
}
-
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeAggregator) String() string {
@@ -5607,16 +5571,15 @@ type PathAttributeCommunities struct {
}
func (p *PathAttributeCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value)%4 != 0 {
+ if p.Length%4 != 0 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "communities length isn't correct")
}
- value := p.PathAttribute.Value
for len(value) >= 4 {
p.Value = append(p.Value, binary.BigEndian.Uint32(value))
value = value[4:]
@@ -5629,8 +5592,7 @@ func (p *PathAttributeCommunities) Serialize(options ...*MarshallingOption) ([]b
for i, v := range p.Value {
binary.BigEndian.PutUint32(buf[i*4:], v)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
type WellKnownCommunity uint32
@@ -5712,12 +5674,11 @@ func (p *PathAttributeCommunities) MarshalJSON() ([]byte, error) {
func NewPathAttributeCommunities(value []uint32) *PathAttributeCommunities {
t := BGP_ATTR_TYPE_COMMUNITIES
return &PathAttributeCommunities{
- PathAttribute{
- Flags: PathAttrFlags[t],
- Type: t,
- Length: 0,
- Value: nil},
- value,
+ PathAttribute: PathAttribute{
+ Flags: PathAttrFlags[t],
+ Type: t,
+ },
+ Value: value,
}
}
@@ -5727,16 +5688,16 @@ type PathAttributeOriginatorId struct {
}
func (p *PathAttributeOriginatorId) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 4 && len(p.PathAttribute.Value) != 16 {
+ if p.Length != 4 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
- return NewMessageError(eCode, eSubCode, nil, "originatorid length isn't correct")
+ return NewMessageError(eCode, eSubCode, nil, "originator id length isn't correct")
}
- p.Value = p.PathAttribute.Value
+ p.Value = value
return nil
}
@@ -5755,21 +5716,19 @@ func (p *PathAttributeOriginatorId) MarshalJSON() ([]byte, error) {
}
func (p *PathAttributeOriginatorId) Serialize(options ...*MarshallingOption) ([]byte, error) {
- buf := make([]byte, 4)
+ buf := make([]byte, 4, 4)
copy(buf, p.Value)
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func NewPathAttributeOriginatorId(value string) *PathAttributeOriginatorId {
t := BGP_ATTR_TYPE_ORIGINATOR_ID
return &PathAttributeOriginatorId{
- PathAttribute{
- Flags: PathAttrFlags[t],
- Type: t,
- Length: 0,
- Value: nil},
- net.ParseIP(value).To4(),
+ PathAttribute: PathAttribute{
+ Flags: PathAttrFlags[t],
+ Type: t,
+ },
+ Value: net.ParseIP(value).To4(),
}
}
@@ -5779,12 +5738,11 @@ type PathAttributeClusterList struct {
}
func (p *PathAttributeClusterList) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- value := p.PathAttribute.Value
- if len(p.PathAttribute.Value)%4 != 0 {
+ if p.Length%4 != 0 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "clusterlist length isn't correct")
@@ -5801,8 +5759,7 @@ func (p *PathAttributeClusterList) Serialize(options ...*MarshallingOption) ([]b
for i, v := range p.Value {
copy(buf[i*4:], v)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeClusterList) String() string {
@@ -5830,12 +5787,11 @@ func NewPathAttributeClusterList(value []string) *PathAttributeClusterList {
}
t := BGP_ATTR_TYPE_CLUSTER_LIST
return &PathAttributeClusterList{
- PathAttribute{
- Flags: PathAttrFlags[t],
- Type: t,
- Length: 0,
- Value: nil},
- l,
+ PathAttribute: PathAttribute{
+ Flags: PathAttrFlags[t],
+ Type: t,
+ },
+ Value: l,
}
}
@@ -5849,14 +5805,14 @@ type PathAttributeMpReachNLRI struct {
}
func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
- value := p.PathAttribute.Value
- if len(value) < 3 {
+ eData, _ := p.PathAttribute.Serialize(value, options...)
+ if p.Length < 3 {
return NewMessageError(eCode, eSubCode, value, "mpreach header length is short")
}
afi := binary.BigEndian.Uint16(value[0:2])
@@ -5865,7 +5821,7 @@ func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte, options ...*Mars
p.SAFI = safi
_, err = NewPrefixFromRouteFamily(afi, safi)
if err != nil {
- return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data[:p.PathAttribute.Len(options...)], err.Error())
+ return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error())
}
nexthoplen := int(value[3])
if len(value) < 4+nexthoplen {
@@ -5904,7 +5860,7 @@ func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte, options ...*Mars
for len(value) > 0 {
prefix, err := NewPrefixFromRouteFamily(afi, safi)
if err != nil {
- return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data[:p.PathAttribute.Len(options...)], err.Error())
+ return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error())
}
err = prefix.DecodeFromBytes(value, options...)
if err != nil {
@@ -5959,8 +5915,7 @@ func (p *PathAttributeMpReachNLRI) Serialize(options ...*MarshallingOption) ([]b
}
buf = append(buf, pbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeMpReachNLRI) MarshalJSON() ([]byte, error) {
@@ -6023,22 +5978,21 @@ type PathAttributeMpUnreachNLRI struct {
}
func (p *PathAttributeMpUnreachNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
-
- value := p.PathAttribute.Value
- if len(value) < 3 {
+ eData, _ := p.PathAttribute.Serialize(value, options...)
+ if p.Length < 3 {
return NewMessageError(eCode, eSubCode, value, "unreach header length is incorrect")
}
afi := binary.BigEndian.Uint16(value[0:2])
safi := value[2]
_, err = NewPrefixFromRouteFamily(afi, safi)
if err != nil {
- return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data[:p.PathAttribute.Len(options...)], err.Error())
+ return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error())
}
value = value[3:]
p.AFI = afi
@@ -6050,14 +6004,14 @@ func (p *PathAttributeMpUnreachNLRI) DecodeFromBytes(data []byte, options ...*Ma
for len(value) > 0 {
prefix, err := NewPrefixFromRouteFamily(afi, safi)
if err != nil {
- return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data[:p.PathAttribute.Len(options...)], err.Error())
+ return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error())
}
err = prefix.DecodeFromBytes(value, options...)
if err != nil {
return err
}
if prefix.Len(options...)+addpathLen > len(value) {
- return NewMessageError(eCode, eSubCode, data[:p.PathAttribute.Len(options...)], "prefix length is incorrect")
+ return NewMessageError(eCode, eSubCode, eData, "prefix length is incorrect")
}
value = value[prefix.Len(options...)+addpathLen:]
p.Value = append(p.Value, prefix)
@@ -6076,8 +6030,7 @@ func (p *PathAttributeMpUnreachNLRI) Serialize(options ...*MarshallingOption) ([
}
buf = append(buf, pbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeMpUnreachNLRI) MarshalJSON() ([]byte, error) {
@@ -6105,9 +6058,8 @@ func NewPathAttributeMpUnreachNLRI(nlri []AddrPrefixInterface) *PathAttributeMpU
t := BGP_ATTR_TYPE_MP_UNREACH_NLRI
p := &PathAttributeMpUnreachNLRI{
PathAttribute: PathAttribute{
- Flags: PathAttrFlags[t],
- Type: t,
- Length: 0,
+ Flags: PathAttrFlags[t],
+ Type: t,
},
Value: nlri,
}
@@ -6886,7 +6838,10 @@ func (e *TrafficRateExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCom
}
func NewTrafficRateExtended(as uint16, rate float32) *TrafficRateExtended {
- return &TrafficRateExtended{as, rate}
+ return &TrafficRateExtended{
+ AS: as,
+ Rate: rate,
+ }
}
type TrafficActionExtended struct {
@@ -6933,7 +6888,10 @@ func (e *TrafficActionExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedC
}
func NewTrafficActionExtended(terminal bool, sample bool) *TrafficActionExtended {
- return &TrafficActionExtended{terminal, sample}
+ return &TrafficActionExtended{
+ Terminal: terminal,
+ Sample: sample,
+ }
}
type RedirectTwoOctetAsSpecificExtended struct {
@@ -7094,7 +7052,9 @@ func (e *TrafficRemarkExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedC
}
func NewTrafficRemarkExtended(dscp uint8) *TrafficRemarkExtended {
- return &TrafficRemarkExtended{dscp}
+ return &TrafficRemarkExtended{
+ DSCP: dscp,
+ }
}
func parseFlowSpecExtended(data []byte) (ExtendedCommunityInterface, error) {
@@ -7256,16 +7216,15 @@ func ParseExtended(data []byte) (ExtendedCommunityInterface, error) {
}
func (p *PathAttributeExtendedCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value)%8 != 0 {
+ if p.Length%8 != 0 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "extendedcommunities length isn't correct")
}
- value := p.PathAttribute.Value
for len(value) >= 8 {
e, err := ParseExtended(value)
if err != nil {
@@ -7286,8 +7245,7 @@ func (p *PathAttributeExtendedCommunities) Serialize(options ...*MarshallingOpti
}
buf = append(buf, ebuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeExtendedCommunities) String() string {
@@ -7327,32 +7285,30 @@ func NewPathAttributeExtendedCommunities(value []ExtendedCommunityInterface) *Pa
type PathAttributeAs4Path struct {
PathAttribute
Value []*As4PathParam
- DefaultAsPath
}
func (p *PathAttributeAs4Path) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
- v := p.PathAttribute.Value
- as4Bytes, err := p.DefaultAsPath.isValidAspath(p.PathAttribute.Value)
+ isAs4, err := validateAsPathValueBytes(value)
if err != nil {
return err
}
- if as4Bytes == false {
+ if isAs4 == false {
return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed")
}
- for len(v) > 0 {
+ for len(value) > 0 {
tuple := &As4PathParam{}
- tuple.DecodeFromBytes(v)
+ tuple.DecodeFromBytes(value)
p.Value = append(p.Value, tuple)
- if len(v) < tuple.Len() {
+ if len(value) < tuple.Len() {
return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed")
}
- v = v[tuple.Len():]
+ value = value[tuple.Len():]
}
return nil
}
@@ -7366,8 +7322,7 @@ func (p *PathAttributeAs4Path) Serialize(options ...*MarshallingOption) ([]byte,
}
buf = append(buf, vbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeAs4Path) String() string {
@@ -7395,17 +7350,17 @@ type PathAttributeAs4Aggregator struct {
}
func (p *PathAttributeAs4Aggregator) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) != 8 {
+ if p.Length != 8 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
return NewMessageError(eCode, eSubCode, nil, "AS4 Aggregator length is incorrect")
}
- p.Value.AS = binary.BigEndian.Uint32(p.PathAttribute.Value[0:4])
- p.Value.Address = p.PathAttribute.Value[4:]
+ p.Value.AS = binary.BigEndian.Uint32(value[0:4])
+ p.Value.Address = value[4:]
return nil
}
@@ -7413,8 +7368,7 @@ func (p *PathAttributeAs4Aggregator) Serialize(options ...*MarshallingOption) ([
buf := make([]byte, 8)
binary.BigEndian.PutUint32(buf[0:], p.Value.AS)
copy(buf[4:], p.Value.Address.To4())
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func NewPathAttributeAs4Aggregator(as uint32, address string) *PathAttributeAs4Aggregator {
@@ -7576,22 +7530,22 @@ type PathAttributeTunnelEncap struct {
}
func (p *PathAttributeTunnelEncap) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
curr := 0
for {
- if len(p.PathAttribute.Value) < curr+4 {
+ if len(value) < curr+4 {
break
}
- t := binary.BigEndian.Uint16(p.PathAttribute.Value[curr : curr+2])
+ t := binary.BigEndian.Uint16(value[curr : curr+2])
tunnelType := TunnelType(t)
- l := int(binary.BigEndian.Uint16(p.PathAttribute.Value[curr+2 : curr+4]))
- if len(p.PathAttribute.Value) < curr+4+l {
- return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Not all TunnelEncapTLV bytes available. %d < %d", len(p.PathAttribute.Value), curr+4+l))
+ l := int(binary.BigEndian.Uint16(value[curr+2 : curr+4]))
+ if len(value) < curr+4+l {
+ return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Not all TunnelEncapTLV bytes available. %d < %d", len(value), curr+4+l))
}
- v := p.PathAttribute.Value[curr+4 : curr+4+l]
+ v := value[curr+4 : curr+4+l]
tlv := &TunnelEncapTLV{
Type: tunnelType,
Len: l,
@@ -7615,8 +7569,7 @@ func (p *PathAttributeTunnelEncap) Serialize(options ...*MarshallingOption) ([]b
}
buf = append(buf, bbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func NewPathAttributeTunnelEncap(value []*TunnelEncapTLV) *PathAttributeTunnelEncap {
@@ -7671,29 +7624,29 @@ type PathAttributePmsiTunnel struct {
}
func (p *PathAttributePmsiTunnel) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
- if len(p.PathAttribute.Value) < 5 {
+ if p.Length < 5 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
return NewMessageError(eCode, eSubCode, nil, "PMSI Tunnel length is incorrect")
}
- if (p.PathAttribute.Value[0] & 0x01) > 0 {
+ if (value[0] & 0x01) > 0 {
p.IsLeafInfoRequired = true
}
- p.TunnelType = PmsiTunnelType(p.PathAttribute.Value[1])
- if p.Label, err = labelDecode(p.PathAttribute.Value[2:5]); err != nil {
+ p.TunnelType = PmsiTunnelType(value[1])
+ if p.Label, err = labelDecode(value[2:5]); err != nil {
return err
}
switch p.TunnelType {
case PMSI_TUNNEL_TYPE_INGRESS_REPL:
- p.TunnelID = &IngressReplTunnelID{net.IP(p.PathAttribute.Value[5:])}
+ p.TunnelID = &IngressReplTunnelID{net.IP(value[5:])}
default:
- p.TunnelID = &DefaultPmsiTunnelID{p.PathAttribute.Value[5:]}
+ p.TunnelID = &DefaultPmsiTunnelID{value[5:]}
}
return nil
}
@@ -7714,8 +7667,7 @@ func (p *PathAttributePmsiTunnel) Serialize(options ...*MarshallingOption) ([]by
return nil, err
}
buf = append(buf, tbuf...)
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributePmsiTunnel) String() string {
@@ -7870,16 +7822,15 @@ func ParseIP6Extended(data []byte) (ExtendedCommunityInterface, error) {
}
func (p *PathAttributeIP6ExtendedCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data)
+ value, err := p.PathAttribute.DecodeFromBytes(data)
if err != nil {
return err
}
- if len(p.PathAttribute.Value)%20 != 0 {
+ if p.Length%20 != 0 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "extendedcommunities length isn't correct")
}
- value := p.PathAttribute.Value
for len(value) >= 20 {
e, err := ParseIP6Extended(value)
if err != nil {
@@ -7900,8 +7851,7 @@ func (p *PathAttributeIP6ExtendedCommunities) Serialize(options ...*MarshallingO
}
buf = append(buf, ebuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize()
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeIP6ExtendedCommunities) String() string {
@@ -7939,43 +7889,35 @@ type PathAttributeAigp struct {
}
func (p *PathAttributeAigp) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data, options...)
+ value, err := p.PathAttribute.DecodeFromBytes(data, options...)
if err != nil {
return err
}
-
- rest := p.PathAttribute.Value
- values := make([]AigpTLV, 0)
-
- for {
- if len(rest) < 3 {
- break
- }
- typ := rest[0]
- length := binary.BigEndian.Uint16(rest[1:3])
- if len(rest) < int(length) {
+ for len(value) > 3 {
+ typ := value[0]
+ length := binary.BigEndian.Uint16(value[1:3])
+ if len(value) < int(length) {
break
}
- v := rest[3:length]
+ v := value[3:length]
switch AigpTLVType(typ) {
case AIGP_TLV_IGP_METRIC:
if len(v) < 8 {
break
}
metric := binary.BigEndian.Uint64(v)
- values = append(values, NewAigpTLVIgpMetric(metric))
+ p.Values = append(p.Values, NewAigpTLVIgpMetric(metric))
default:
- values = append(values, &AigpTLVDefault{AigpTLVType(typ), v})
- }
- rest = rest[length:]
- if len(rest) == 0 {
- p.Values = values
- return nil
+ p.Values = append(p.Values, &AigpTLVDefault{AigpTLVType(typ), v})
}
+ value = value[length:]
}
- eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
- eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
- return NewMessageError(eCode, eSubCode, nil, "Aigp length is incorrect")
+ if len(value) != 0 {
+ eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
+ eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
+ return NewMessageError(eCode, eSubCode, nil, "Aigp length is incorrect")
+ }
+ return nil
}
func (p *PathAttributeAigp) Serialize(options ...*MarshallingOption) ([]byte, error) {
@@ -7987,8 +7929,7 @@ func (p *PathAttributeAigp) Serialize(options ...*MarshallingOption) ([]byte, er
}
buf = append(buf, bbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize(options...)
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeAigp) String() string {
@@ -8070,33 +8011,28 @@ type PathAttributeLargeCommunities struct {
}
func (p *PathAttributeLargeCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
- err := p.PathAttribute.DecodeFromBytes(data)
+ value, err := p.PathAttribute.DecodeFromBytes(data)
if err != nil {
return err
}
-
- rest := p.PathAttribute.Value
-
- if len(rest)%12 != 0 {
+ if p.Length%12 != 0 {
eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR)
return NewMessageError(eCode, eSubCode, nil, "large communities length isn't correct")
}
-
- p.Values = make([]*LargeCommunity, 0, len(rest)/12)
-
- for len(rest) >= 12 {
- asn := binary.BigEndian.Uint32(rest[:4])
- data1 := binary.BigEndian.Uint32(rest[4:8])
- data2 := binary.BigEndian.Uint32(rest[8:12])
+ p.Values = make([]*LargeCommunity, 0, p.Length/12)
+ for len(value) >= 12 {
+ asn := binary.BigEndian.Uint32(value[:4])
+ data1 := binary.BigEndian.Uint32(value[4:8])
+ data2 := binary.BigEndian.Uint32(value[8:12])
p.Values = append(p.Values, NewLargeCommunity(asn, data1, data2))
- rest = rest[12:]
+ value = value[12:]
}
return nil
}
func (p *PathAttributeLargeCommunities) Serialize(options ...*MarshallingOption) ([]byte, error) {
- buf := make([]byte, 0)
+ buf := make([]byte, 0, len(p.Values)*12)
for _, t := range p.Values {
bbuf, err := t.Serialize()
if err != nil {
@@ -8104,8 +8040,7 @@ func (p *PathAttributeLargeCommunities) Serialize(options ...*MarshallingOption)
}
buf = append(buf, bbuf...)
}
- p.PathAttribute.Value = buf
- return p.PathAttribute.Serialize()
+ return p.PathAttribute.Serialize(buf, options...)
}
func (p *PathAttributeLargeCommunities) String() string {
@@ -8143,6 +8078,46 @@ func NewPathAttributeLargeCommunities(values []*LargeCommunity) *PathAttributeLa
type PathAttributeUnknown struct {
PathAttribute
+ Value []byte
+}
+
+func (p *PathAttributeUnknown) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
+ value, err := p.PathAttribute.DecodeFromBytes(data)
+ if err != nil {
+ return err
+ }
+ p.Value = value
+ return nil
+}
+
+func (p *PathAttributeUnknown) Serialize(options ...*MarshallingOption) ([]byte, error) {
+ return p.PathAttribute.Serialize(p.Value, options...)
+}
+
+func (p *PathAttributeUnknown) String() string {
+ return fmt.Sprintf("{Flags: %s, Type: %s, Value: %s}", p.Flags, p.Type, p.Value)
+}
+
+func (p *PathAttributeUnknown) MarshalJSON() ([]byte, error) {
+ return json.Marshal(struct {
+ Flags BGPAttrFlag `json:"flags"`
+ Type BGPAttrType `json:"type"`
+ Value []byte `json:"value"`
+ }{
+ Flags: p.GetFlags(),
+ Type: p.GetType(),
+ Value: p.Value,
+ })
+}
+
+func NewPathAttributeUnknown(flags BGPAttrFlag, typ BGPAttrType, value []byte) *PathAttributeUnknown {
+ return &PathAttributeUnknown{
+ PathAttribute: PathAttribute{
+ Flags: flags,
+ Type: typ,
+ },
+ Value: value,
+ }
}
func GetPathAttribute(data []byte) (PathAttributeInterface, error) {
@@ -8410,9 +8385,8 @@ func NewEndOfRib(family RouteFamily) *BGPMessage {
t := BGP_ATTR_TYPE_MP_UNREACH_NLRI
unreach := &PathAttributeMpUnreachNLRI{
PathAttribute: PathAttribute{
- Flags: PathAttrFlags[t],
- Type: t,
- Length: 3,
+ Flags: PathAttrFlags[t],
+ Type: t,
},
AFI: afi,
SAFI: safi,
diff --git a/packet/bgp/helper.go b/packet/bgp/helper.go
index 1061d915..79229d92 100644
--- a/packet/bgp/helper.go
+++ b/packet/bgp/helper.go
@@ -141,8 +141,8 @@ func NewTestBGPUpdateMessage() *BGPMessage {
PathAttribute: PathAttribute{
Flags: BGP_ATTR_FLAG_TRANSITIVE,
Type: 100,
- Value: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
+ Value: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
},
}
n := []*IPAddrPrefix{NewIPAddrPrefix(24, "13.2.3.1")}
diff --git a/packet/bgp/validate.go b/packet/bgp/validate.go
index 424047a5..ecc67067 100644
--- a/packet/bgp/validate.go
+++ b/packet/bgp/validate.go
@@ -3,6 +3,7 @@ package bgp
import (
"encoding/binary"
"fmt"
+ "math"
"net"
"strconv"
)
@@ -139,7 +140,7 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
return false, err
}
case *PathAttributeOrigin:
- v := uint8(p.Value[0])
+ v := uint8(p.Value)
if v != BGP_ORIGIN_ATTR_TYPE_IGP &&
v != BGP_ORIGIN_ATTR_TYPE_EGP &&
v != BGP_ORIGIN_ATTR_TYPE_INCOMPLETE {
@@ -226,14 +227,14 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM
}
// validator for PathAttribute
-func ValidateFlags(t BGPAttrType, flags BGPAttrFlag) (bool, string) {
+func validatePathAttributeFlags(t BGPAttrType, flags BGPAttrFlag) string {
/*
* RFC 4271 P.17 For well-known attributes, the Transitive bit MUST be set to 1.
*/
if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 {
eMsg := fmt.Sprintf("well-known attribute %s must have transitive flag 1", t)
- return false, eMsg
+ return eMsg
}
/*
* RFC 4271 P.17 For well-known attributes and for optional non-transitive attributes,
@@ -241,21 +242,67 @@ func ValidateFlags(t BGPAttrType, flags BGPAttrFlag) (bool, string) {
*/
if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
eMsg := fmt.Sprintf("well-known attribute %s must have partial bit 0", t)
- return false, eMsg
+ return eMsg
}
if flags&BGP_ATTR_FLAG_OPTIONAL != 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
eMsg := fmt.Sprintf("optional non-transitive attribute %s must have partial bit 0", t)
- return false, eMsg
+ return eMsg
}
// check flags are correct
if f, ok := PathAttrFlags[t]; ok {
if f != flags & ^BGP_ATTR_FLAG_EXTENDED_LENGTH & ^BGP_ATTR_FLAG_PARTIAL {
eMsg := fmt.Sprintf("flags are invalid. attribute type: %s, expect: %s, actual: %s", t, f, flags)
- return false, eMsg
+ return eMsg
}
}
- return true, ""
+ return ""
+}
+
+func validateAsPathValueBytes(data []byte) (bool, error) {
+ eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
+ eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH)
+ if len(data)%2 != 0 {
+ return false, NewMessageError(eCode, eSubCode, nil, "AS PATH length is not odd")
+ }
+
+ tryParse := func(data []byte, use4byte bool) (bool, error) {
+ for len(data) > 0 {
+ if len(data) < 2 {
+ return false, NewMessageError(eCode, eSubCode, nil, "AS PATH header is short")
+ }
+ segType := data[0]
+ if segType == 0 || segType > 4 {
+ return false, NewMessageError(eCode, eSubCode, nil, "unknown AS_PATH seg type")
+ }
+ asNum := data[1]
+ data = data[2:]
+ if asNum == 0 || int(asNum) > math.MaxUint8 {
+ return false, NewMessageError(eCode, eSubCode, nil, "AS PATH the number of AS is incorrect")
+ }
+ segLength := int(asNum)
+ if use4byte == true {
+ segLength *= 4
+ } else {
+ segLength *= 2
+ }
+ if int(segLength) > len(data) {
+ return false, NewMessageError(eCode, eSubCode, nil, "seg length is short")
+ }
+ data = data[segLength:]
+ }
+ return true, nil
+ }
+ _, err := tryParse(data, true)
+ if err == nil {
+ return true, nil
+ }
+
+ _, err = tryParse(data, false)
+ if err == nil {
+ return false, nil
+ }
+ return false, NewMessageError(eCode, eSubCode, nil, "can't parse AS_PATH")
}
func ValidateBGPMessage(m *BGPMessage) error {