diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-01-13 20:17:57 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-01-16 18:18:20 +0900 |
commit | fe0cd1532c9fa6a967392e96833fd25071569fa8 (patch) | |
tree | fa170f48831424b57bd566c045788d065361a26c /packet/validate.go | |
parent | 0df994639ebbe69b9be015d07fb93e36379eec5a (diff) |
packet: add ValidateUpdateMsg
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'packet/validate.go')
-rw-r--r-- | packet/validate.go | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/packet/validate.go b/packet/validate.go index e3ddf58b..5711a91b 100644 --- a/packet/validate.go +++ b/packet/validate.go @@ -1,9 +1,107 @@ package bgp import ( + "github.com/osrg/gobgp/config" "strconv" ) +// Validator for BGPUpdate +func ValidateUpdateMsg(m *BGPUpdate) (bool, error) { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCodeAttrList := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + eSubCodeFlagsError := uint8(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR) + eSubCodeInvalidNetField := uint8(BGP_ERROR_SUB_INVALID_NETWORK_FIELD) + eSubCodeMissing := uint8(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE) + + seen := make(map[BGPAttrType]PathAttributeInterface) + // check path attribute + for _, a := range m.PathAttributes { + + // check attribute flags + ok, eMsg := ValidateFlags(a.getType(), a.getFlags()) + if !ok { + data, _ := a.Serialize() + return false, NewMessageError(eCode, eSubCodeFlagsError, data, eMsg) + } + + // check duplication + if _, ok := seen[a.getType()]; !ok { + seen[a.getType()] = a + } else { + eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.getType())) + return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg) + } + + // check specific path attribute + ok, e := ValidateAttribute(a) + if !ok { + return false, e + } + } + + // check the existence of well-known mandatory attributes + exist := func(attrs []BGPAttrType) (bool, BGPAttrType) { + for _, attr := range attrs { + _, ok := seen[attr] + if !ok { + return false, attr + } + } + return true, 0 + } + mandatory := []BGPAttrType{BGP_ATTR_TYPE_ORIGIN, BGP_ATTR_TYPE_AS_PATH, BGP_ATTR_TYPE_NEXT_HOP} + if ok, t := exist(mandatory); !ok { + eMsg := "well-known mandatory attributes are not present. type : " + strconv.Itoa(int(t)) + data := []byte{byte(t)} + return false, NewMessageError(eCode, eSubCodeMissing, data, eMsg) + } + + // check NLRI + for _, n := range m.NLRI { + if n.Prefix.To4() == nil { + eMsg := "invalid nlri" + return false, NewMessageError(eCode, eSubCodeInvalidNetField, nil, eMsg) + } + } + + return true, nil +} + +func ValidateAttribute(a PathAttributeInterface) (bool, error) { + + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCodeBadOrigin := uint8(BGP_ERROR_SUB_INVALID_ORIGIN_ATTRIBUTE) + eSubCodeBadNextHop := uint8(BGP_ERROR_SUB_INVALID_NEXT_HOP_ATTRIBUTE) + eSubCodeUnknown := uint8(BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE) + + switch p := a.(type) { + case *PathAttributeOrigin: + v := uint8(p.Value[0]) + if v != config.BGP_ORIGIN_ATTR_TYPE_IGP && + v != config.BGP_ORIGIN_ATTR_TYPE_EGP && + v != config.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE { + eMsg := "invalid origin attribute. value : " + strconv.Itoa(int(v)) + return false, NewMessageError(eCode, eSubCodeBadOrigin, nil, eMsg) + } + case *PathAttributeNextHop: + //check IP address syntax + if p.Value.To4() == nil { + eMsg := "invalid nexthop address" + data, _ := a.Serialize() + return false, NewMessageError(eCode, eSubCodeBadNextHop, data, eMsg) + } + case *PathAttributeUnknown: + if p.getFlags()&BGP_ATTR_FLAG_OPTIONAL == 0 { + eMsg := "unrecognized well-known attribute" + data, _ := a.Serialize() + return false, NewMessageError(eCode, eSubCodeUnknown, data, eMsg) + } + } + + return true, nil + +} + // validator for PathAttribute func ValidateFlags(t BGPAttrType, flags uint8) (bool, string) { @@ -28,7 +126,6 @@ func ValidateFlags(t BGPAttrType, flags uint8) (bool, string) { } // check flags are correct - if f, ok := pathAttrFlags[t]; ok { if f != flags { eMsg := "flags are invalid. attribtue type : " + strconv.Itoa(int(t)) |