summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp/validate.go
diff options
context:
space:
mode:
Diffstat (limited to 'packet/bgp/validate.go')
-rw-r--r--packet/bgp/validate.go61
1 files changed, 54 insertions, 7 deletions
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 {