diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-01-29 16:26:34 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-01-29 16:26:34 +0900 |
commit | 0e4fe0c5f3bacac5f056f481bd143b202a3b71db (patch) | |
tree | 123d34994365860a5b1e5401eb6198797de23630 | |
parent | 1462fdb4d240cd956b6c1189ac769be7e7b1bba4 (diff) |
server: verify update message
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | packet/validate.go | 60 | ||||
-rw-r--r-- | packet/validate_test.go | 178 | ||||
-rw-r--r-- | server/peer.go | 13 |
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() |