mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
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 <[email protected]>
This commit is contained in:
+30
-7
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user