diff options
Diffstat (limited to 'packet/bgp')
-rw-r--r-- | packet/bgp/bgp.go | 43 | ||||
-rw-r--r-- | packet/bgp/validate.go | 56 |
2 files changed, 77 insertions, 22 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index c8050ab5..7e60b96e 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -7817,6 +7817,7 @@ type BGPUpdate struct { } func (msg *BGPUpdate) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + var strongestError error // cache error codes eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) @@ -7870,20 +7871,46 @@ func (msg *BGPUpdate) DecodeFromBytes(data []byte, options ...*MarshallingOption msg.PathAttributes = []PathAttributeInterface{} for pathlen := msg.TotalPathAttributeLen; pathlen > 0; { + var e error + if pathlen < 3 { + e = NewMessageErrorWithErrorHandling( + eCode, BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR, data, ERROR_HANDLING_TREAT_AS_WITHDRAW, nil, "insufficient data to decode") + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } + data = data[pathlen:] + break + } p, err := GetPathAttribute(data) if err != nil { return err } + err = p.DecodeFromBytes(data, options...) if err != nil { - return err + e = err.(*MessageError) + if e.(*MessageError).SubTypeCode == BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR { + e.(*MessageError).ErrorHandling = ERROR_HANDLING_TREAT_AS_WITHDRAW + } else { + e.(*MessageError).ErrorHandling = getErrorHandlingFromPathAttribute(p.GetType()) + e.(*MessageError).ErrorAttribute = &p + } + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } pathlen -= uint16(p.Len(options...)) if len(data) < p.Len(options...) { - return NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR, data, "attribute length is short") + e = NewMessageErrorWithErrorHandling( + eCode, BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR, data, ERROR_HANDLING_TREAT_AS_WITHDRAW, nil, "attribute length is short") + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } data = data[p.Len(options...):] - msg.PathAttributes = append(msg.PathAttributes, p) + if e == nil || e.(*MessageError).ErrorHandling != ERROR_HANDLING_ATTRIBUTE_DISCARD { + msg.PathAttributes = append(msg.PathAttributes, p) + } } msg.NLRI = make([]*IPAddrPrefix, 0) @@ -7897,11 +7924,14 @@ func (msg *BGPUpdate) DecodeFromBytes(data []byte, options ...*MarshallingOption if len(data) < n.Len(options...)+addpathLen { return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, nil, "NLRI length is short") } + if n.Len(options...) > 32 { + return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, nil, "NLRI length is too long") + } data = data[n.Len(options...)+addpathLen:] msg.NLRI = append(msg.NLRI, n) } - return nil + return strongestError } func (msg *BGPUpdate) Serialize(options ...*MarshallingOption) ([]byte, error) { @@ -8125,10 +8155,7 @@ func parseBody(h *BGPHeader, data []byte, options ...*MarshallingOption) (*BGPMe return nil, NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_TYPE, nil, "unknown message type") } err := msg.Body.DecodeFromBytes(data, options...) - if err != nil { - return nil, err - } - return msg, nil + return msg, err } func ParseBGPMessage(data []byte, options ...*MarshallingOption) (*BGPMessage, error) { diff --git a/packet/bgp/validate.go b/packet/bgp/validate.go index be44e605..eefb7afe 100644 --- a/packet/bgp/validate.go +++ b/packet/bgp/validate.go @@ -9,6 +9,8 @@ import ( // Validator for BGPUpdate func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, doConfedCheck bool) (bool, error) { + var strongestError error + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) eSubCodeAttrList := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) eSubCodeMissing := uint8(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE) @@ -20,22 +22,34 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, doConfe } seen := make(map[BGPAttrType]PathAttributeInterface) + newAttrs := make([]PathAttributeInterface, 0, len(seen)) // check path attribute for _, a := range m.PathAttributes { // check duplication if _, ok := seen[a.GetType()]; !ok { seen[a.GetType()] = a - } else { + newAttrs = append(newAttrs, a) + //check specific path attribute + ok, err := ValidateAttribute(a, rfs, doConfedCheck) + if !ok { + if err.(*MessageError).ErrorHandling == ERROR_HANDLING_SESSION_RESET { + return false, err + } else if err.(*MessageError).Stronger(strongestError) { + strongestError = err + } + } + } else if a.GetType() == BGP_ATTR_TYPE_MP_REACH_NLRI || a.GetType() == BGP_ATTR_TYPE_MP_UNREACH_NLRI { 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, rfs, doConfedCheck) - if !ok { - return false, e + } else { + eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType())) + e := NewMessageErrorWithErrorHandling(eCode, eSubCodeAttrList, nil, ERROR_HANDLING_ATTRIBUTE_DISCARD, nil, eMsg) + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } } + m.PathAttributes = newAttrs if _, ok := seen[BGP_ATTR_TYPE_MP_REACH_NLRI]; ok || len(m.NLRI) > 0 { // check the existence of well-known mandatory attributes @@ -55,13 +69,18 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]BGPAddPathMode, doConfe 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) + e := NewMessageErrorWithErrorHandling(eCode, eSubCodeMissing, data, ERROR_HANDLING_TREAT_AS_WITHDRAW, nil, eMsg) + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } } - return true, nil + + return strongestError == nil, strongestError } func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathMode, doConfedCheck bool) (bool, error) { + var strongestError error eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) eSubCodeBadOrigin := uint8(BGP_ERROR_SUB_INVALID_ORIGIN_ATTRIBUTE) @@ -126,7 +145,10 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM v != BGP_ORIGIN_ATTR_TYPE_INCOMPLETE { data, _ := a.Serialize() eMsg := "invalid origin attribute. value : " + strconv.Itoa(int(v)) - return false, NewMessageError(eCode, eSubCodeBadOrigin, data, eMsg) + e := NewMessageErrorWithErrorHandling(eCode, eSubCodeBadOrigin, data, getErrorHandlingFromPathAttribute(p.GetType()), nil, eMsg) + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } case *PathAttributeNextHop: @@ -144,7 +166,10 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM if p.Value.IsLoopback() || isZero(p.Value) || isClassDorE(p.Value) { eMsg := "invalid nexthop address" data, _ := a.Serialize() - return false, NewMessageError(eCode, eSubCodeBadNextHop, data, eMsg) + e := NewMessageErrorWithErrorHandling(eCode, eSubCodeBadNextHop, data, getErrorHandlingFromPathAttribute(p.GetType()), nil, eMsg) + if e.(*MessageError).Stronger(strongestError) { + strongestError = e + } } case *PathAttributeAsPath: if doConfedCheck { @@ -158,7 +183,11 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM } if segType == BGP_ASPATH_ATTR_TYPE_CONFED_SET || segType == BGP_ASPATH_ATTR_TYPE_CONFED_SEQ { - return false, NewMessageError(eCode, eSubCodeMalformedAspath, nil, fmt.Sprintf("segment type confederation(%d) found", segType)) + err := NewMessageErrorWithErrorHandling( + eCode, eSubCodeMalformedAspath, nil, getErrorHandlingFromPathAttribute(p.GetType()), nil, fmt.Sprintf("segment type confederation(%d) found", segType)) + if err.(*MessageError).Stronger(strongestError) { + strongestError = err + } } } } @@ -186,8 +215,7 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]BGPAddPathM } } - return true, nil - + return strongestError == nil, strongestError } // validator for PathAttribute |