summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packet/validate.go28
-rw-r--r--packet/validate_test.go217
2 files changed, 229 insertions, 16 deletions
diff --git a/packet/validate.go b/packet/validate.go
index 5711a91b..0b1effaf 100644
--- a/packet/validate.go
+++ b/packet/validate.go
@@ -2,6 +2,7 @@ package bgp
import (
"github.com/osrg/gobgp/config"
+ "net"
"strconv"
)
@@ -10,7 +11,6 @@ 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)
@@ -56,14 +56,6 @@ func ValidateUpdateMsg(m *BGPUpdate) (bool, error) {
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
}
@@ -80,12 +72,24 @@ func ValidateAttribute(a PathAttributeInterface) (bool, error) {
if v != config.BGP_ORIGIN_ATTR_TYPE_IGP &&
v != config.BGP_ORIGIN_ATTR_TYPE_EGP &&
v != config.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE {
+ data, _ := a.Serialize()
eMsg := "invalid origin attribute. value : " + strconv.Itoa(int(v))
- return false, NewMessageError(eCode, eSubCodeBadOrigin, nil, eMsg)
+ return false, NewMessageError(eCode, eSubCodeBadOrigin, data, eMsg)
}
case *PathAttributeNextHop:
- //check IP address syntax
- if p.Value.To4() == nil {
+
+ isZero := func(ip net.IP) bool {
+ res := ip[0] & 0xff
+ return res == 0x00
+ }
+
+ isClassDorE := func(ip net.IP) bool {
+ res := ip[0] & 0xe0
+ return res == 0xe0
+ }
+
+ //check IP address represents host address
+ if p.Value.IsLoopback() || isZero(p.Value) || isClassDorE(p.Value) {
eMsg := "invalid nexthop address"
data, _ := a.Serialize()
return false, NewMessageError(eCode, eSubCodeBadNextHop, data, eMsg)
diff --git a/packet/validate_test.go b/packet/validate_test.go
index 3bdb0949..801c3868 100644
--- a/packet/validate_test.go
+++ b/packet/validate_test.go
@@ -1,11 +1,13 @@
package bgp
import (
+ "encoding/binary"
"github.com/stretchr/testify/assert"
+ "net"
"testing"
)
-func update1() *BGPMessage {
+func bgpupdate() *BGPMessage {
aspath := []AsPathParamInterface{
NewAsPathParam(2, []uint16{65001}),
}
@@ -21,9 +23,216 @@ func update1() *BGPMessage {
}
func Test_Validate_OK(t *testing.T) {
- message := update1().Body.(*BGPUpdate)
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
res, err := ValidateUpdateMsg(message)
- assert.Equal(t, true, res)
- assert.NoError(t, err)
+ assert.Equal(true, res)
+ assert.NoError(err)
}
+
+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)
+ 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)
+ 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)
+ 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)
+ 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)
+ // duplicate origin path attribute
+ originBytes := []byte{pathAttrFlags[BGP_ATTR_TYPE_ORIGIN], 1, 1, 1}
+ origin := &PathAttributeOrigin{}
+ origin.DecodeFromBytes(originBytes)
+ message.PathAttributes = append(message.PathAttributes, 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_MALFORMED_ATTRIBUTE_LIST, e.SubTypeCode)
+ assert.Nil(e.Data)
+}
+
+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)
+ assert.Equal(false, res)
+ assert.Error(err)
+ e := err.(*MessageError)
+ assert.Equal(BGP_ERROR_UPDATE_MESSAGE_ERROR, e.TypeCode)
+ assert.Equal(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE, e.SubTypeCode)
+ missing, _ := binary.Uvarint(e.Data)
+ assert.Equal(1, missing)
+}
+
+func Test_Validate_invalid_origin(t *testing.T) {
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
+ // origin needs to be well-known
+ originBytes := []byte{pathAttrFlags[BGP_ATTR_TYPE_ORIGIN], 1, 1, 5}
+ 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_INVALID_ORIGIN_ATTRIBUTE, e.SubTypeCode)
+ assert.Equal(originBytes, e.Data)
+}
+
+func Test_Validate_invalid_nexthop_zero(t *testing.T) {
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
+
+ // invalid nexthop
+ addr := net.ParseIP("0.0.0.1").To4()
+ nexthopBytes := []byte{pathAttrFlags[BGP_ATTR_TYPE_NEXT_HOP], 3, 4}
+ nexthopBytes = append(nexthopBytes, addr...)
+ nexthop := &PathAttributeNextHop{}
+ nexthop.DecodeFromBytes(nexthopBytes)
+ message.PathAttributes[2] = nexthop
+
+ 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_INVALID_NEXT_HOP_ATTRIBUTE, e.SubTypeCode)
+ assert.Equal(nexthopBytes, e.Data)
+}
+
+func Test_Validate_invalid_nexthop_lo(t *testing.T) {
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
+
+ // invalid nexthop
+ addr := net.ParseIP("127.0.0.1").To4()
+ nexthopBytes := []byte{pathAttrFlags[BGP_ATTR_TYPE_NEXT_HOP], 3, 4}
+ nexthopBytes = append(nexthopBytes, addr...)
+ nexthop := &PathAttributeNextHop{}
+ nexthop.DecodeFromBytes(nexthopBytes)
+ message.PathAttributes[2] = nexthop
+
+ 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_INVALID_NEXT_HOP_ATTRIBUTE, e.SubTypeCode)
+ assert.Equal(nexthopBytes, e.Data)
+}
+
+func Test_Validate_invalid_nexthop_de(t *testing.T) {
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
+
+ // invalid nexthop
+ addr := net.ParseIP("224.0.0.1").To4()
+ nexthopBytes := []byte{pathAttrFlags[BGP_ATTR_TYPE_NEXT_HOP], 3, 4}
+ nexthopBytes = append(nexthopBytes, addr...)
+ nexthop := &PathAttributeNextHop{}
+ nexthop.DecodeFromBytes(nexthopBytes)
+ message.PathAttributes[2] = nexthop
+
+ 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_INVALID_NEXT_HOP_ATTRIBUTE, e.SubTypeCode)
+ assert.Equal(nexthopBytes, e.Data)
+
+}
+
+func Test_Validate_unrecognized_well_known(t *testing.T) {
+
+ assert := assert.New(t)
+ message := bgpupdate().Body.(*BGPUpdate)
+ f := BGP_ATTR_FLAG_TRANSITIVE
+ unknownBytes := []byte{byte(f), 30, 1, 1}
+ unknown := &PathAttributeUnknown{}
+ unknown.DecodeFromBytes(unknownBytes)
+ message.PathAttributes = append(message.PathAttributes, unknown)
+
+ 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_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE, e.SubTypeCode)
+ assert.Equal(unknownBytes, e.Data)
+}