diff options
author | Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> | 2015-07-01 17:43:18 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-07-01 21:33:39 +0900 |
commit | d43b77e0ec0f3f51cff9317db312d97a98f1df8f (patch) | |
tree | 2e05a95be9cd4b116e53bbf418fe7437c5787517 | |
parent | 1db97a53022a02ff3bf355909b54eb6be8dc286e (diff) |
packet: add AS_PATH validator
-rw-r--r-- | packet/validate.go | 24 | ||||
-rw-r--r-- | packet/validate_test.go | 82 | ||||
-rw-r--r-- | server/peer.go | 16 |
3 files changed, 105 insertions, 17 deletions
diff --git a/packet/validate.go b/packet/validate.go index 2afd53c4..e82113ee 100644 --- a/packet/validate.go +++ b/packet/validate.go @@ -8,7 +8,7 @@ import ( ) // Validator for BGPUpdate -func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]bool) (bool, error) { +func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]bool, doConfedCheck bool) (bool, 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) @@ -31,7 +31,7 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]bool) (bool, error) { } //check specific path attribute - ok, e := ValidateAttribute(a, rfs) + ok, e := ValidateAttribute(a, rfs, doConfedCheck) if !ok { return false, e } @@ -58,12 +58,13 @@ func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]bool) (bool, error) { return true, nil } -func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool) (bool, error) { +func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool, doConfedCheck bool) (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) + eSubCodeMalformedAspath := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH) checkPrefix := func(l []AddrPrefixInterface) bool { for _, prefix := range l { @@ -119,6 +120,23 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool) (bool data, _ := a.Serialize() return false, NewMessageError(eCode, eSubCodeBadNextHop, data, eMsg) } + case *PathAttributeAsPath: + if doConfedCheck { + for _, paramIf := range p.Value { + var segType uint8 + asParam, y := paramIf.(*As4PathParam) + if y { + segType = asParam.Type + } else { + segType = paramIf.(*AsPathParam).Type + } + + 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)) + } + } + } + case *PathAttributeUnknown: if p.getFlags()&BGP_ATTR_FLAG_OPTIONAL == 0 { eMsg := "unrecognized well-known attribute" diff --git a/packet/validate_test.go b/packet/validate_test.go index 311ae031..2f007c44 100644 --- a/packet/validate_test.go +++ b/packet/validate_test.go @@ -41,29 +41,29 @@ func bgpupdateV6() *BGPMessage { func Test_Validate_CapV4(t *testing.T) { assert := assert.New(t) message := bgpupdate().Body.(*BGPUpdate) - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv6_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv6_UC: true}, false) assert.Equal(false, res) assert.Error(err) - res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(true, res) } func Test_Validate_CapV6(t *testing.T) { assert := assert.New(t) message := bgpupdateV6().Body.(*BGPUpdate) - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv6_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv6_UC: true}, false) assert.Equal(true, res) assert.NoError(err) - res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) } func Test_Validate_OK(t *testing.T) { assert := assert.New(t) message := bgpupdate().Body.(*BGPUpdate) - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(true, res) assert.NoError(err) @@ -151,7 +151,7 @@ func Test_Validate_duplicate_attribute(t *testing.T) { origin.DecodeFromBytes(originBytes) message.PathAttributes = append(message.PathAttributes, origin) - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -164,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, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -180,7 +180,7 @@ func Test_Validate_mandatory_missing_nocheck(t *testing.T) { message.PathAttributes = message.PathAttributes[1:] message.NLRI = nil - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(true, res) assert.NoError(err) } @@ -194,7 +194,7 @@ func Test_Validate_invalid_origin(t *testing.T) { origin.DecodeFromBytes(originBytes) message.PathAttributes[0] = origin - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -215,7 +215,7 @@ func Test_Validate_invalid_nexthop_zero(t *testing.T) { nexthop.DecodeFromBytes(nexthopBytes) message.PathAttributes[2] = nexthop - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -236,7 +236,7 @@ func Test_Validate_invalid_nexthop_lo(t *testing.T) { nexthop.DecodeFromBytes(nexthopBytes) message.PathAttributes[2] = nexthop - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -257,7 +257,7 @@ func Test_Validate_invalid_nexthop_de(t *testing.T) { nexthop.DecodeFromBytes(nexthopBytes) message.PathAttributes[2] = nexthop - res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -277,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, map[RouteFamily]bool{RF_IPv4_UC: true}) + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, false) assert.Equal(false, res) assert.Error(err) e := err.(*MessageError) @@ -285,3 +285,59 @@ func Test_Validate_unrecognized_well_known(t *testing.T) { assert.Equal(uint8(BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE), e.SubTypeCode) assert.Equal(unknownBytes, e.Data) } + +func Test_Validate_aspath(t *testing.T) { + + assert := assert.New(t) + message := bgpupdate().Body.(*BGPUpdate) + + // VALID AS_PATH + res, err := ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, true) + assert.Equal(true, res) + + // CONFED_SET + newAttrs := make([]PathAttributeInterface, 0) + attrs := message.PathAttributes + for _, attr := range attrs { + if _, y := attr.(*PathAttributeAsPath); y { + aspath := []AsPathParamInterface{ + NewAsPathParam(BGP_ASPATH_ATTR_TYPE_CONFED_SET, []uint16{65001}), + } + newAttrs = append(newAttrs, NewPathAttributeAsPath(aspath)) + } else { + newAttrs = append(newAttrs, attr) + } + } + + message.PathAttributes = newAttrs + res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, true) + assert.Equal(false, res) + assert.Error(err) + e := err.(*MessageError) + assert.Equal(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), e.TypeCode) + assert.Equal(uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH), e.SubTypeCode) + assert.Nil(e.Data) + + // CONFED_SEQ + newAttrs = make([]PathAttributeInterface, 0) + attrs = message.PathAttributes + for _, attr := range attrs { + if _, y := attr.(*PathAttributeAsPath); y { + aspath := []AsPathParamInterface{ + NewAsPathParam(BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint16{65001}), + } + newAttrs = append(newAttrs, NewPathAttributeAsPath(aspath)) + } else { + newAttrs = append(newAttrs, attr) + } + } + + message.PathAttributes = newAttrs + res, err = ValidateUpdateMsg(message, map[RouteFamily]bool{RF_IPv4_UC: true}, true) + assert.Equal(false, res) + assert.Error(err) + e = err.(*MessageError) + assert.Equal(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), e.TypeCode) + assert.Equal(uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH), e.SubTypeCode) + assert.Nil(e.Data) +} diff --git a/server/peer.go b/server/peer.go index 3e5888f0..fd41563a 100644 --- a/server/peer.go +++ b/server/peer.go @@ -43,6 +43,8 @@ type Peer struct { outgoing chan *bgp.BGPMessage distPolicies []*policy.Policy defaultDistributePolicy config.DefaultPolicyType + isConfederationMember bool + isEBGP bool } func NewPeer(g config.Global, config config.Neighbor) *Peer { @@ -66,6 +68,17 @@ func NewPeer(g config.Global, config config.Neighbor) *Peer { } peer.adjRib = table.NewAdjRib(peer.configuredRFlist()) peer.fsm = NewFSM(&g, &config) + + if config.PeerAs != g.As { + peer.isEBGP = true + for _, member := range g.Confederation.MemberAs { + if member == config.PeerAs { + peer.isConfederationMember = true + break + } + } + } + return peer } @@ -158,7 +171,8 @@ func (peer *Peer) handleBGPmessage(m *bgp.BGPMessage) ([]*table.Path, bool, []*b update = true peer.config.BgpNeighborCommonState.UpdateRecvTime = time.Now().Unix() body := m.Body.(*bgp.BGPUpdate) - _, err := bgp.ValidateUpdateMsg(body, peer.rfMap) + confedCheckRequired := !peer.isConfederationMember && peer.isEBGP + _, err := bgp.ValidateUpdateMsg(body, peer.rfMap, confedCheckRequired) if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", |