From 1601fd47cf7b4a78a8a008f8aaffd1041dbf6958 Mon Sep 17 00:00:00 2001 From: ISHIDA Wataru Date: Wed, 18 May 2016 05:14:40 +0000 Subject: packet/bgp: check flowspec nlri type ordering RFC5575 says, Flow specification components must follow strict type ordering. A given component type may or may not be present in the specification, but if present, it MUST precede any component of higher numeric type value. Signed-off-by: ISHIDA Wataru --- packet/bgp/validate.go | 37 ++++++++++++++++++++++++++++++------- packet/bgp/validate_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 7 deletions(-) (limited to 'packet') diff --git a/packet/bgp/validate.go b/packet/bgp/validate.go index 73697c4d..7173138b 100644 --- a/packet/bgp/validate.go +++ b/packet/bgp/validate.go @@ -66,14 +66,37 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool, doCon eSubCodeUnknown := uint8(BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE) eSubCodeMalformedAspath := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH) - checkPrefix := func(l []AddrPrefixInterface) bool { + checkPrefix := func(l []AddrPrefixInterface) error { for _, prefix := range l { rf := AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI()) if _, ok := rfs[rf]; !ok { - return false + return NewMessageError(0, 0, nil, fmt.Sprintf("Address-family %s not avalible for this session", rf)) + } + switch rf { + case RF_FS_IPv4_UC, RF_FS_IPv6_UC, RF_FS_IPv4_VPN, RF_FS_IPv6_VPN, RF_FS_L2_VPN: + t := BGPFlowSpecType(0) + value := make([]FlowSpecComponentInterface, 0) + switch rf { + case RF_FS_IPv4_UC: + value = prefix.(*FlowSpecIPv4Unicast).Value + case RF_FS_IPv6_UC: + value = prefix.(*FlowSpecIPv6Unicast).Value + case RF_FS_IPv4_VPN: + value = prefix.(*FlowSpecIPv6VPN).Value + case RF_FS_IPv6_VPN: + value = prefix.(*FlowSpecIPv4VPN).Value + case RF_FS_L2_VPN: + value = prefix.(*FlowSpecL2VPN).Value + } + for _, v := range value { + if v.Type() <= t { + return NewMessageError(0, 0, nil, fmt.Sprintf("%s nlri violate strict type ordering", rf)) + } + t = v.Type() + } } } - return true + return nil } switch p := a.(type) { @@ -82,16 +105,16 @@ func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool, doCon if _, ok := rfs[rf]; !ok { 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)) + if err := checkPrefix(p.Value); err != nil { + return false, err } case *PathAttributeMpReachNLRI: rf := AfiSafiToRouteFamily(p.AFI, p.SAFI) if _, ok := rfs[rf]; !ok { 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)) + if err := checkPrefix(p.Value); err != nil { + return false, err } case *PathAttributeOrigin: v := uint8(p.Value[0]) diff --git a/packet/bgp/validate_test.go b/packet/bgp/validate_test.go index 6309c74d..490c6402 100644 --- a/packet/bgp/validate_test.go +++ b/packet/bgp/validate_test.go @@ -341,3 +341,46 @@ func Test_Validate_aspath(t *testing.T) { assert.Equal(uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH), e.SubTypeCode) assert.Nil(e.Data) } + +func Test_Validate_flowspec(t *testing.T) { + assert := assert.New(t) + cmp := make([]FlowSpecComponentInterface, 0) + cmp = append(cmp, NewFlowSpecDestinationPrefix(NewIPAddrPrefix(24, "10.0.0.0"))) + cmp = append(cmp, NewFlowSpecSourcePrefix(NewIPAddrPrefix(24, "10.0.0.0"))) + eq := 0x1 + gt := 0x2 + lt := 0x4 + and := 0x40 + not := 0x2 + item1 := NewFlowSpecComponentItem(eq, TCP) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_IP_PROTO, []*FlowSpecComponentItem{item1})) + item2 := NewFlowSpecComponentItem(gt|eq, 20) + item3 := NewFlowSpecComponentItem(and|lt|eq, 30) + item4 := NewFlowSpecComponentItem(eq, 10) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_PORT, []*FlowSpecComponentItem{item2, item3, item4})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_DST_PORT, []*FlowSpecComponentItem{item2, item3, item4})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_SRC_PORT, []*FlowSpecComponentItem{item2, item3, item4})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_ICMP_TYPE, []*FlowSpecComponentItem{item2, item3, item4})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_ICMP_CODE, []*FlowSpecComponentItem{item2, item3, item4})) + item5 := NewFlowSpecComponentItem(0, TCP_FLAG_ACK) + item6 := NewFlowSpecComponentItem(and|not, TCP_FLAG_URGENT) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_TCP_FLAG, []*FlowSpecComponentItem{item5, item6})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_PKT_LEN, []*FlowSpecComponentItem{item2, item3, item4})) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_DSCP, []*FlowSpecComponentItem{item2, item3, item4})) + isFlagment := 0x02 + item7 := NewFlowSpecComponentItem(isFlagment, 0) + cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_FRAGMENT, []*FlowSpecComponentItem{item7})) + n1 := NewFlowSpecIPv4Unicast(cmp) + a := NewPathAttributeMpReachNLRI("", []AddrPrefixInterface{n1}) + m := map[RouteFamily]bool{RF_FS_IPv4_UC: true} + _, err := ValidateAttribute(a, m, false) + assert.Nil(err) + + cmp = make([]FlowSpecComponentInterface, 0) + cmp = append(cmp, NewFlowSpecSourcePrefix(NewIPAddrPrefix(24, "10.0.0.0"))) + cmp = append(cmp, NewFlowSpecDestinationPrefix(NewIPAddrPrefix(24, "10.0.0.0"))) + n1 = NewFlowSpecIPv4Unicast(cmp) + a = NewPathAttributeMpReachNLRI("", []AddrPrefixInterface{n1}) + _, err = ValidateAttribute(a, m, false) + assert.NotNil(err) +} -- cgit v1.2.3