diff options
-rw-r--r-- | doc/bird.conf.example2 | 10 | ||||
-rw-r--r-- | doc/bird.sgml | 3 | ||||
-rw-r--r-- | lib/flowspec.c | 25 | ||||
-rw-r--r-- | lib/flowspec.h | 1 |
4 files changed, 25 insertions, 14 deletions
diff --git a/doc/bird.conf.example2 b/doc/bird.conf.example2 index a4081f14..51fcfb64 100644 --- a/doc/bird.conf.example2 +++ b/doc/bird.conf.example2 @@ -105,27 +105,27 @@ protocol static flowstat4 { proto = 0x12; sport > 0x5678 && < 0x9abc || 0xdef0 || 0x1234,0x5678,0x9abc..0xdef0; dport = 50; - tcp flags 0xabcd/0xbbdd; + tcp flags 0x000/0xf00; }; route flow4 { dst 12.0.0.0/32; - tcp flags ! 0 / 0x9999; + tcp flags ! 0/0x999; }; route flow4 { dst 220.0.254.0/24; - tcp flags 0x99 / 0x9999; + tcp flags 0x99/0x999; }; route flow4 { dst 220.0.254.192/28; - tcp flags !0xffff / 0xFFFF; + tcp flags ! 0xfff/0xfff; }; route flow4 { dst 15.0.0.0/8; - tcp flags !0x9999/0x9999; + tcp flags ! 0x999/0x999; }; } diff --git a/doc/bird.sgml b/doc/bird.sgml index 0e072dd2..4bbcb871 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -768,7 +768,8 @@ logical operators <cf/&&/ or <cf/||/. Allowed relational operators are <cf/=/, <tag><label id="flow-tcp-flags">tcp flags <m/bitmask-match/</tag> Set a matching bitmask for TCP header flags (aka control bits) (e.g. - <cf>tcp flags 0x03/0x0f;</cf>). + <cf>tcp flags 0x03/0x0f;</cf>). The maximum length of mask is 12 bits + (0xfff). <tag><label id="flow-length">length <m/numbers-match/</tag> Set a matching packet length (e.g. <cf>length > 1500;</cf>) diff --git a/lib/flowspec.c b/lib/flowspec.c index 764b648e..0b863ed9 100644 --- a/lib/flowspec.c +++ b/lib/flowspec.c @@ -259,7 +259,8 @@ static const char* flow_validated_state_str_[] = { [FLOW_ST_BAD_TYPE_ORDER] = "Bad component order", [FLOW_ST_AND_BIT_SHOULD_BE_UNSET] = "The AND-bit should be unset", [FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED] = "The Zero-bit should be unset", - [FLOW_ST_DEST_PREFIX_REQUIRED] = "Destination prefix is required to define", + [FLOW_ST_DEST_PREFIX_REQUIRED] = "Destination prefix is missing", + [FLOW_ST_INVALID_TCP_FLAGS] = "TCP flags exceeding 0xfff", [FLOW_ST_CANNOT_USE_DONT_FRAGMENT] = "Cannot use Don't fragment flag in IPv6 flow" }; @@ -332,8 +333,11 @@ flow_check_cf_bmk_values(struct flow_builder *fb, u8 neg, u32 val, u32 mask) if (neg && !(val == 0 || val == mask)) cf_error("For negation, value must be zero or bitmask"); - if (fb->this_type == FLOW_TYPE_FRAGMENT && fb->ipv6 && (mask & 0x01)) - cf_error("Invalid mask 0x%x. Bit 0 must be 0", mask); + if ((fb->this_type == FLOW_TYPE_TCP_FLAGS) && (mask & 0xf000)) + cf_error("Invalid mask 0x%x, must not exceed 0xfff", mask); + + if ((fb->this_type == FLOW_TYPE_FRAGMENT) && fb->ipv6 && (mask & 0x01)) + cf_error("Invalid mask 0x%x, bit 0 must be 0", mask); if (val & ~mask) cf_error("Value 0x%x outside bitmask 0x%x", val, mask); @@ -456,15 +460,20 @@ flow_validate(const byte *nlri, uint len, int ipv6) return FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED; } - /* Bit-7 must be 0 [draft-ietf-idr-flow-spec-v6] */ - if (ipv6 && type == FLOW_TYPE_FRAGMENT && (*(pos+1) & 0x01)) - return FLOW_ST_CANNOT_USE_DONT_FRAGMENT; - /* XXX: Could be a fragment component encoded in 2-bytes? */ - /* Value length of operator */ uint len = get_value_length(pos); if (len > flow_max_value_length(type, ipv6)) return FLOW_ST_EXCEED_MAX_VALUE_LENGTH; + + /* TCP Flags component must not check highest nibble (just 12 valid bits) */ + if ((type == FLOW_TYPE_TCP_FLAGS) && (len == 2) && (pos[1] & 0xf0)) + return FLOW_ST_INVALID_TCP_FLAGS; + + /* Bit-7 must be 0 [draft-ietf-idr-flow-spec-v6] */ + if ((type == FLOW_TYPE_FRAGMENT) && ipv6 && (pos[1] & 0x01)) + return FLOW_ST_CANNOT_USE_DONT_FRAGMENT; + /* XXX: Could be a fragment component encoded in 2-bytes? */ + pos += 1+len; if (pos > end && !last) diff --git a/lib/flowspec.h b/lib/flowspec.h index 9150ca91..185d5a1c 100644 --- a/lib/flowspec.h +++ b/lib/flowspec.h @@ -115,6 +115,7 @@ enum flow_validated_state { FLOW_ST_AND_BIT_SHOULD_BE_UNSET, FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED, FLOW_ST_DEST_PREFIX_REQUIRED, + FLOW_ST_INVALID_TCP_FLAGS, FLOW_ST_CANNOT_USE_DONT_FRAGMENT }; |