summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packet/validate.go60
-rw-r--r--packet/validate_test.go178
-rw-r--r--server/peer.go13
3 files changed, 168 insertions, 83 deletions
diff --git a/packet/validate.go b/packet/validate.go
index 9ca968b2..80bc426d 100644
--- a/packet/validate.go
+++ b/packet/validate.go
@@ -2,29 +2,36 @@ package bgp
import (
"encoding/binary"
+ "fmt"
"github.com/osrg/gobgp/config"
"net"
"strconv"
)
+func isRfSupported(rf RouteFamily, rfs []RouteFamily) bool {
+ for _, r := range rfs {
+ if rf == r {
+ return true
+ }
+ }
+ return false
+}
+
// Validator for BGPUpdate
-func ValidateUpdateMsg(m *BGPUpdate) (bool, error) {
+func ValidateUpdateMsg(m *BGPUpdate, rfs []RouteFamily) (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)
eSubCodeMissing := uint8(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE)
+ if len(m.NLRI) > 0 || len(m.WithdrawnRoutes) > 0 {
+ if isRfSupported(RF_IPv4_UC, rfs) == false {
+ return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", RF_IPv4_UC))
+ }
+ }
+
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
@@ -33,8 +40,8 @@ func ValidateUpdateMsg(m *BGPUpdate) (bool, error) {
return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg)
}
- // check specific path attribute
- ok, e := ValidateAttribute(a)
+ //check specific path attribute
+ ok, e := ValidateAttribute(a, rfs)
if !ok {
return false, e
}
@@ -61,14 +68,40 @@ func ValidateUpdateMsg(m *BGPUpdate) (bool, error) {
return true, nil
}
-func ValidateAttribute(a PathAttributeInterface) (bool, error) {
+func ValidateAttribute(a PathAttributeInterface, rfs []RouteFamily) (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)
+ checkPrefix := func(l []AddrPrefixInterface) bool {
+ for _, prefix := range l {
+ rf := rfshift(prefix.AFI(), prefix.SAFI())
+ if isRfSupported(rf, rfs) == false {
+ return false
+ }
+ }
+ return true
+ }
+
switch p := a.(type) {
+ case *PathAttributeMpUnreachNLRI:
+ rf := rfshift(p.AFI, p.SAFI)
+ if isRfSupported(rf, rfs) == false {
+ return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
+ }
+ if checkPrefix(p.Value) == false {
+ return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
+ }
+ case *PathAttributeMpReachNLRI:
+ rf := rfshift(p.AFI, p.SAFI)
+ if isRfSupported(rf, rfs) == false {
+ return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
+ }
+ if checkPrefix(p.Value) == false {
+ return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
+ }
case *PathAttributeOrigin:
v := uint8(p.Value[0])
if v != config.BGP_ORIGIN_ATTR_TYPE_IGP &&
@@ -147,5 +180,6 @@ func ValidateBGPMessage(m *BGPMessage) error {
binary.BigEndian.PutUint16(buf, m.Header.Len)
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, buf, "too long length")
}
+
return nil
}
diff --git a/packet/validate_test.go b/packet/validate_test.go
index 90d05548..7f5d93ec 100644
--- a/packet/validate_test.go
+++ b/packet/validate_test.go
@@ -22,88 +22,126 @@ func bgpupdate() *BGPMessage {
return NewBGPUpdateMessage(nil, p, n)
}
-func Test_Validate_OK(t *testing.T) {
- assert := assert.New(t)
- message := bgpupdate().Body.(*BGPUpdate)
- res, err := ValidateUpdateMsg(message)
- assert.Equal(true, res)
- assert.NoError(err)
-
-}
+func bgpupdateV6() *BGPMessage {
+ aspath := []AsPathParamInterface{
+ NewAsPathParam(2, []uint16{65001}),
+ }
-func Test_Validate_wellknown_but_nontransitive(t *testing.T) {
- assert := assert.New(t)
- message := bgpupdate().Body.(*BGPUpdate)
+ mp_nlri := []AddrPrefixInterface{NewIPv6AddrPrefix(100,
+ "fe80:1234:1234:5667:8967:af12:8912:1023")}
- originBytes := []byte{0, 1, 1, 1} // 0 means Flags
- origin := &PathAttributeOrigin{}
- origin.DecodeFromBytes(originBytes)
- message.PathAttributes[0] = origin
-
- res, err := ValidateUpdateMsg(message)
- assert.Equal(false, res)
- assert.Error(err)
- e := err.(*MessageError)
- assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
- assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
- assert.Equal(originBytes, e.Data)
+ p := []PathAttributeInterface{
+ NewPathAttributeOrigin(1),
+ NewPathAttributeAsPath(aspath),
+ NewPathAttributeMpReachNLRI("1023::", mp_nlri),
+ }
+ return NewBGPUpdateMessage(nil, p, []NLRInfo{})
}
-func Test_Validate_wellknown_but_partial(t *testing.T) {
+func Test_Validate_CapV4(t *testing.T) {
assert := assert.New(t)
message := bgpupdate().Body.(*BGPUpdate)
-
- originBytes := []byte{BGP_ATTR_FLAG_PARTIAL, 1, 1, 1}
- origin := &PathAttributeOrigin{}
- origin.DecodeFromBytes(originBytes)
- message.PathAttributes[0] = origin
-
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv6_UC})
assert.Equal(false, res)
assert.Error(err)
- e := err.(*MessageError)
- assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
- assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
- assert.Equal(originBytes, e.Data)
+
+ res, err = ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
+ assert.Equal(true, res)
}
-func Test_Validate_optional_nontransitive_but_partial(t *testing.T) {
+func Test_Validate_CapV6(t *testing.T) {
assert := assert.New(t)
- message := bgpupdate().Body.(*BGPUpdate)
- f := BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_PARTIAL
- originBytes := []byte{byte(f), 1, 1, 1}
- origin := &PathAttributeOrigin{}
- origin.DecodeFromBytes(originBytes)
- message.PathAttributes[0] = origin
+ message := bgpupdateV6().Body.(*BGPUpdate)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv6_UC})
+ assert.Equal(true, res)
+ assert.NoError(err)
- res, err := ValidateUpdateMsg(message)
+ res, err = ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
- assert.Error(err)
- e := err.(*MessageError)
- assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
- assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
- assert.Equal(originBytes, e.Data)
}
-func Test_Validate_flag_mismatch(t *testing.T) {
+func Test_Validate_OK(t *testing.T) {
assert := assert.New(t)
message := bgpupdate().Body.(*BGPUpdate)
- f := BGP_ATTR_FLAG_OPTIONAL
- // origin needs to be well-known
- originBytes := []byte{byte(f), 1, 1, 1}
- origin := &PathAttributeOrigin{}
- origin.DecodeFromBytes(originBytes)
- message.PathAttributes[0] = origin
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
+ assert.Equal(true, res)
+ assert.NoError(err)
- res, err := ValidateUpdateMsg(message)
- assert.Equal(false, res)
- assert.Error(err)
- e := err.(*MessageError)
- assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
- assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
- assert.Equal(originBytes, e.Data)
}
+// func Test_Validate_wellknown_but_nontransitive(t *testing.T) {
+// assert := assert.New(t)
+// message := bgpupdate().Body.(*BGPUpdate)
+
+// originBytes := []byte{0, 1, 1, 1} // 0 means Flags
+// origin := &PathAttributeOrigin{}
+// origin.DecodeFromBytes(originBytes)
+// message.PathAttributes[0] = origin
+
+// res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC,})
+// assert.Equal(false, res)
+// assert.Error(err)
+// e := err.(*MessageError)
+// assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
+// assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
+// assert.Equal(originBytes, e.Data)
+// }
+
+// func Test_Validate_wellknown_but_partial(t *testing.T) {
+// assert := assert.New(t)
+// message := bgpupdate().Body.(*BGPUpdate)
+
+// originBytes := []byte{BGP_ATTR_FLAG_PARTIAL, 1, 1, 1}
+// origin := &PathAttributeOrigin{}
+// origin.DecodeFromBytes(originBytes)
+// message.PathAttributes[0] = origin
+
+// res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC,})
+// assert.Equal(false, res)
+// assert.Error(err)
+// e := err.(*MessageError)
+// assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
+// assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
+// assert.Equal(originBytes, e.Data)
+// }
+
+// func Test_Validate_optional_nontransitive_but_partial(t *testing.T) {
+// assert := assert.New(t)
+// message := bgpupdate().Body.(*BGPUpdate)
+// f := BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_PARTIAL
+// originBytes := []byte{byte(f), 1, 1, 1}
+// origin := &PathAttributeOrigin{}
+// origin.DecodeFromBytes(originBytes)
+// message.PathAttributes[0] = origin
+
+// res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC,})
+// assert.Equal(false, res)
+// assert.Error(err)
+// e := err.(*MessageError)
+// assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
+// assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
+// assert.Equal(originBytes, e.Data)
+// }
+
+// func Test_Validate_flag_mismatch(t *testing.T) {
+// assert := assert.New(t)
+// message := bgpupdate().Body.(*BGPUpdate)
+// f := BGP_ATTR_FLAG_OPTIONAL
+// // origin needs to be well-known
+// originBytes := []byte{byte(f), 1, 1, 1}
+// origin := &PathAttributeOrigin{}
+// origin.DecodeFromBytes(originBytes)
+// message.PathAttributes[0] = origin
+
+// res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC,})
+// assert.Equal(false, res)
+// assert.Error(err)
+// e := err.(*MessageError)
+// assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
+// assert.Equal(BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, e.SubTypeCode)
+// assert.Equal(originBytes, e.Data)
+// }
+
func Test_Validate_duplicate_attribute(t *testing.T) {
assert := assert.New(t)
message := bgpupdate().Body.(*BGPUpdate)
@@ -113,7 +151,7 @@ func Test_Validate_duplicate_attribute(t *testing.T) {
origin.DecodeFromBytes(originBytes)
message.PathAttributes = append(message.PathAttributes, origin)
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -126,7 +164,7 @@ func Test_Validate_mandatory_missing(t *testing.T) {
assert := assert.New(t)
message := bgpupdate().Body.(*BGPUpdate)
message.PathAttributes = message.PathAttributes[1:]
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -142,7 +180,7 @@ func Test_Validate_mandatory_missing_nocheck(t *testing.T) {
message.PathAttributes = message.PathAttributes[1:]
message.NLRI = nil
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(true, res)
assert.NoError(err)
}
@@ -156,7 +194,7 @@ func Test_Validate_invalid_origin(t *testing.T) {
origin.DecodeFromBytes(originBytes)
message.PathAttributes[0] = origin
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -177,7 +215,7 @@ func Test_Validate_invalid_nexthop_zero(t *testing.T) {
nexthop.DecodeFromBytes(nexthopBytes)
message.PathAttributes[2] = nexthop
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -198,7 +236,7 @@ func Test_Validate_invalid_nexthop_lo(t *testing.T) {
nexthop.DecodeFromBytes(nexthopBytes)
message.PathAttributes[2] = nexthop
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -219,7 +257,7 @@ func Test_Validate_invalid_nexthop_de(t *testing.T) {
nexthop.DecodeFromBytes(nexthopBytes)
message.PathAttributes[2] = nexthop
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
@@ -239,7 +277,7 @@ func Test_Validate_unrecognized_well_known(t *testing.T) {
unknown.DecodeFromBytes(unknownBytes)
message.PathAttributes = append(message.PathAttributes, unknown)
- res, err := ValidateUpdateMsg(message)
+ res, err := ValidateUpdateMsg(message, []RouteFamily{RF_IPv4_UC})
assert.Equal(false, res)
assert.Error(err)
e := err.(*MessageError)
diff --git a/server/peer.go b/server/peer.go
index 28561619..ca10c1db 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -138,6 +138,19 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) {
case bgp.BGP_MSG_UPDATE:
peer.peerConfig.BgpNeighborCommonState.UpdateRecvTime = time.Now()
body := m.Body.(*bgp.BGPUpdate)
+ _, err := bgp.ValidateUpdateMsg(body, []bgp.RouteFamily{peer.rf})
+ if err != nil {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": peer.peerConfig.NeighborAddress,
+ "error": err,
+ }).Warn("malformed BGP update message")
+ m := err.(*bgp.MessageError)
+ if m.TypeCode != 0 {
+ peer.outgoing <- bgp.NewBGPNotificationMessage(m.TypeCode, m.SubTypeCode, m.Data)
+ }
+ return
+ }
table.UpdatePathAttrs4ByteAs(body)
msg := table.NewProcessMessage(m, peer.peerInfo)
pathList := msg.ToPathList()