From c61e1ef0dd82200ca067b5150b2cae72a7e921ad Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 18 Mar 2024 13:10:55 +0100 Subject: [PATCH] netlink_delinearize: restore binop syntax when listing ruleset for flags commit b11b6c68e61ea294eb4c313705ccfe3e7b0eda87 upstream. c3d57114f119 ("parser_bison: add shortcut syntax for matching flags without binary operations") provides a similar syntax to iptables using a prefix representation for flag matching. Restore original representation using binop when listing the ruleset. The parser still accepts the prefix notation for backward compatibility. Signed-off-by: Pablo Neira Ayuso --- src/netlink_delinearize.c | 65 ++-- tests/py/inet/tcp.t | 16 +- tests/py/inet/tcp.t.json | 42 ++- tests/py/inet/tcp.t.json.output | 279 ++++++++++++++++++ tests/py/inet/tcp.t.payload | 6 +- .../testcases/nft-f/dumps/sample-ruleset.nft | 239 +++++++++++++++ tests/shell/testcases/packetpath/tcp_options | 16 +- 7 files changed, 583 insertions(+), 80 deletions(-) create mode 100644 tests/shell/testcases/nft-f/dumps/sample-ruleset.nft diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 273669a3b..1726101bf 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -2365,56 +2365,29 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) && right->dtype->basetype && - right->dtype->basetype->type == TYPE_BITMASK) { - switch (right->etype) { - case EXPR_VALUE: - if (!mpz_cmp_ui(right->value, 0)) { - /* Flag comparison: data & flags != 0 - * - * Split the flags into a list of flag values and convert the - * op to OP_EQ. - */ - expr_free(right); - - expr->left = expr_get(binop->left); - expr->right = binop_tree_to_list(NULL, binop->right); - switch (expr->op) { - case OP_NEQ: - expr->op = OP_IMPLICIT; - break; - case OP_EQ: - expr->op = OP_NEG; - break; - default: - BUG("unknown operation type %d\n", expr->op); - } - expr_free(binop); - } else if (binop->right->etype == EXPR_VALUE && - right->etype == EXPR_VALUE && - !mpz_cmp(right->value, binop->right->value)) { - /* Skip flag / flag representation for: - * data & flag == flag - * data & flag != flag - */ - ; - } else { - *exprp = flagcmp_expr_alloc(&expr->location, expr->op, - expr_get(binop->left), - binop_tree_to_list(NULL, binop->right), - expr_get(right)); - expr_free(expr); - } + right->dtype->basetype->type == TYPE_BITMASK && + right->etype == EXPR_VALUE && + !mpz_cmp_ui(right->value, 0)) { + /* Flag comparison: data & flags != 0 + * + * Split the flags into a list of flag values and convert the + * op to OP_EQ. + */ + expr_free(right); + + expr->left = expr_get(binop->left); + expr->right = binop_tree_to_list(NULL, binop->right); + switch (expr->op) { + case OP_NEQ: + expr->op = OP_IMPLICIT; break; - case EXPR_BINOP: - *exprp = flagcmp_expr_alloc(&expr->location, expr->op, - expr_get(binop->left), - binop_tree_to_list(NULL, binop->right), - binop_tree_to_list(NULL, right)); - expr_free(expr); + case OP_EQ: + expr->op = OP_NEG; break; default: - break; + BUG("unknown operation type %d\n", expr->op); } + expr_free(binop); } else if (binop->left->dtype->flags & DTYPE_F_PREFIX && binop->op == OP_AND && expr->right->etype == EXPR_VALUE && expr_mask_is_prefix(binop->right)) { diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t index f51ebd36b..f4bdac177 100644 --- a/tests/py/inet/tcp.t +++ b/tests/py/inet/tcp.t @@ -68,8 +68,8 @@ tcp flags != { fin, urg, ecn, cwr} drop;ok tcp flags cwr;ok tcp flags != cwr;ok tcp flags == syn;ok -tcp flags fin,syn / fin,syn;ok -tcp flags != syn / fin,syn;ok +tcp flags fin,syn / fin,syn;ok;tcp flags & (fin | syn) == fin | syn +tcp flags != syn / fin,syn;ok;tcp flags & (fin | syn) != syn tcp flags & syn != 0;ok;tcp flags syn tcp flags & syn == 0;ok;tcp flags ! syn tcp flags & (syn | ack) != 0;ok;tcp flags syn,ack @@ -77,12 +77,12 @@ tcp flags & (syn | ack) == 0;ok;tcp flags ! syn,ack # it should be possible to transform this to: tcp flags syn tcp flags & syn == syn;ok tcp flags & syn != syn;ok -tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags syn / fin,syn,rst,ack -tcp flags & (fin | syn | rst | ack) == syn;ok;tcp flags syn / fin,syn,rst,ack -tcp flags & (fin | syn | rst | ack) != syn;ok;tcp flags != syn / fin,syn,rst,ack -tcp flags & (fin | syn | rst | ack) == (syn | ack);ok;tcp flags syn,ack / fin,syn,rst,ack -tcp flags & (fin | syn | rst | ack) != (syn | ack);ok;tcp flags != syn,ack / fin,syn,rst,ack -tcp flags & (syn | ack) == (syn | ack);ok;tcp flags syn,ack / syn,ack +tcp flags & (fin | syn | rst | ack) syn;ok;tcp flags & (fin | syn | rst | ack) == syn +tcp flags & (fin | syn | rst | ack) == syn;ok +tcp flags & (fin | syn | rst | ack) != syn;ok +tcp flags & (fin | syn | rst | ack) == syn | ack;ok +tcp flags & (fin | syn | rst | ack) != syn | ack;ok +tcp flags & (syn | ack) == syn | ack;ok tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff tcp flags { syn, syn | ack };ok tcp flags & (fin | syn | rst | psh | ack | urg) == { fin, ack, psh | ack, fin | psh | ack };ok diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json index 8439c2b59..d3a846cf9 100644 --- a/tests/py/inet/tcp.t.json +++ b/tests/py/inet/tcp.t.json @@ -1712,7 +1712,7 @@ } ] -# tcp flags & (fin | syn | rst | ack) == (syn | ack) +# tcp flags & (fin | syn | rst | ack) == syn | ack [ { "match": { @@ -1741,7 +1741,7 @@ } ] -# tcp flags & (fin | syn | rst | ack) != (syn | ack) +# tcp flags & (syn | ack) == syn | ack [ { "match": { @@ -1754,14 +1754,12 @@ } }, [ - "fin", "syn", - "rst", "ack" ] ] }, - "op": "!=", + "op": "==", "right": [ "syn", "ack" @@ -1770,7 +1768,7 @@ } ] -# tcp flags & (syn | ack) == (syn | ack) +# tcp flags & (fin | syn | rst | ack) != syn | ack [ { "match": { @@ -1782,17 +1780,31 @@ "protocol": "tcp" } }, - [ - "syn", - "ack" - ] + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } ] }, - "op": "==", - "right": [ - "syn", - "ack" - ] + "op": "!=", + "right": { + "|": [ + "syn", + "ack" + ] + } } } ] diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output index c471e8d8d..e186e127f 100644 --- a/tests/py/inet/tcp.t.json.output +++ b/tests/py/inet/tcp.t.json.output @@ -208,3 +208,282 @@ } } ] + +# tcp flags fin,syn / fin,syn +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + "fin", + "syn" + ] + } + ] + }, + "op": "==", + "right": { + "|": [ + "fin", + "syn" + ] + } + } + } +] + +# tcp flags != syn / fin,syn +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + "fin", + "syn" + ] + } + ] + }, + "op": "!=", + "right": "syn" + } + } +] + +# tcp flags & (fin | syn | rst | ack) syn +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } + ] + }, + "op": "==", + "right": "syn" + } + } +] + +# tcp flags & (fin | syn | rst | ack) == syn +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } + ] + }, + "op": "==", + "right": "syn" + } + } +] + +# tcp flags & (fin | syn | rst | ack) != syn +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } + ] + }, + "op": "!=", + "right": "syn" + } + } +] + +# tcp flags & (fin | syn | rst | ack) == syn | ack +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } + ] + }, + "op": "==", + "right": { + "|": [ + "syn", + "ack" + ] + } + } + } +] + +# tcp flags & (fin | syn | rst | ack) != syn | ack +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + { + "|": [ + { + "|": [ + "fin", + "syn" + ] + }, + "rst" + ] + }, + "ack" + ] + } + ] + }, + "op": "!=", + "right": { + "|": [ + "syn", + "ack" + ] + } + } + } +] + +# tcp flags & (syn | ack) == syn | ack +[ + { + "match": { + "left": { + "&": [ + { + "payload": { + "field": "flags", + "protocol": "tcp" + } + }, + { + "|": [ + "syn", + "ack" + ] + } + ] + }, + "op": "==", + "right": { + "|": [ + "syn", + "ack" + ] + } + } + } +] + diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload index 1cfe500bf..bc6bb989a 100644 --- a/tests/py/inet/tcp.t.payload +++ b/tests/py/inet/tcp.t.payload @@ -442,7 +442,7 @@ inet test-inet input [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ] [ cmp neq reg 1 0x00000002 ] -# tcp flags & (fin | syn | rst | ack) == (syn | ack) +# tcp flags & (fin | syn | rst | ack) == syn | ack inet test-inet input [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] @@ -450,7 +450,7 @@ inet test-inet input [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ] [ cmp eq reg 1 0x00000012 ] -# tcp flags & (fin | syn | rst | ack) != (syn | ack) +# tcp flags & (fin | syn | rst | ack) != syn | ack inet test-inet input [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] @@ -458,7 +458,7 @@ inet test-inet input [ bitwise reg 1 = ( reg 1 & 0x00000017 ) ^ 0x00000000 ] [ cmp neq reg 1 0x00000012 ] -# tcp flags & (syn | ack) == (syn | ack) +# tcp flags & (syn | ack) == syn | ack inet test-inet input [ meta load l4proto => reg 1 ] [ cmp eq reg 1 0x00000006 ] diff --git a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft new file mode 100644 index 000000000..1a9f4e7a4 --- /dev/null +++ b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft @@ -0,0 +1,239 @@ +table inet filter { + map if_input { + type ifname : verdict + elements = { "eth0" : jump public_input, + "eth1" : jump home_input, + "eth2.10" : jump home_input, + "eth2.20" : jump home_input } + } + + map if_forward { + type ifname : verdict + elements = { "eth0" : jump public_forward, + "eth1" : jump trusted_forward, + "eth2.10" : jump voip_forward, + "eth2.20" : jump guest_forward } + } + + map if_output { + type ifname : verdict + elements = { "eth0" : jump public_output, + "eth1" : jump home_output, + "eth2.10" : jump home_output, + "eth2.20" : jump home_output } + } + + set ipv4_blacklist { + type ipv4_addr + flags interval + auto-merge + } + + set ipv6_blacklist { + type ipv6_addr + flags interval + auto-merge + } + + set limit_src_ip { + type ipv4_addr + size 1024 + flags dynamic,timeout + } + + set limit_src_ip6 { + type ipv6_addr + size 1024 + flags dynamic,timeout + } + + chain PREROUTING_RAW { + type filter hook prerouting priority raw; policy accept; + meta l4proto != { icmp, tcp, udp, ipv6-icmp } counter packets 0 bytes 0 drop + tcp flags syn jump { + tcp option maxseg size 1-500 counter packets 0 bytes 0 drop + tcp sport 0 counter packets 0 bytes 0 drop + } + rt type 0 counter packets 0 bytes 0 drop + } + + chain PREROUTING_MANGLE { + type filter hook prerouting priority mangle; policy accept; + ct state vmap { invalid : jump ct_invalid_pre, related : jump rpfilter, new : jump ct_new_pre, untracked : jump ct_untracked_pre } + } + + chain ct_invalid_pre { + counter packets 0 bytes 0 drop + } + + chain ct_untracked_pre { + icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return + counter packets 0 bytes 0 drop + } + + chain ct_new_pre { + jump rpfilter + tcp flags & (fin | syn | rst | ack) != syn counter packets 0 bytes 0 drop + iifname "eth0" meta nfproto vmap { ipv4 : jump blacklist_input_ipv4, ipv6 : jump blacklist_input_ipv6 } + } + + chain rpfilter { + ip saddr 0.0.0.0 ip daddr 255.255.255.255 udp sport 68 udp dport 67 return + ip6 saddr :: ip6 daddr . icmpv6 type { ff02::1:ff00:0/104 . nd-neighbor-solicit, ff02::16 . mld2-listener-report } return + fib saddr . iif oif 0 counter packets 0 bytes 0 drop + } + + chain blacklist_input_ipv4 { + ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } counter packets 0 bytes 0 drop + ip saddr @ipv4_blacklist counter packets 0 bytes 0 drop + } + + chain blacklist_input_ipv6 { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 return + udp sport 547 ip6 saddr fe80::/64 return + ip6 saddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } counter packets 0 bytes 0 drop + ip6 saddr @ipv6_blacklist counter packets 0 bytes 0 drop + } + + chain INPUT { + type filter hook input priority filter; policy drop; + iif "lo" accept + ct state established,related accept + iifname vmap @if_input + log prefix "NFT REJECT IN " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain public_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 saddr fe80::/64 ip6 hoplimit 255 accept + udp sport 547 udp dport 546 ip6 saddr fe80::/64 accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + counter packets 0 bytes 0 drop + } + + chain home_input { + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp sport 68 udp dport 67 accept + udp sport 546 udp dport 547 iifname { "eth1", "eth2.10", "eth2.20" } accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + icmp type echo-request accept + icmpv6 type echo-request accept + tcp dport 22 iifname "eth1" accept + meta l4proto { tcp, udp } th dport 53 jump { + ip6 saddr != { fd00::/8, fe80::/64 } counter packets 0 bytes 0 reject with icmpv6 port-unreachable + accept + } + udp dport 123 accept + tcp dport 8443 accept + } + + chain FORWARD_MANGLE { + type filter hook forward priority mangle; policy accept; + oifname "eth0" jump { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu + } + } + + chain blacklist_output_ipv4 { + ip daddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/3 } goto log_blacklist + ip daddr @ipv4_blacklist goto log_blacklist + } + + chain blacklist_output_ipv6 { + icmpv6 type . ip6 daddr { nd-router-solicit . ff02::2, nd-neighbor-solicit . ff02::1:ff00:0/104, nd-neighbor-advert . fe80::/64, nd-neighbor-advert . ff02::1, nd-neighbor-advert . ff02::1:ff00:0/104, mld2-listener-report . ff02::16 } return + udp dport 547 ip6 daddr ff02::1:2 return + ip6 daddr { ::/3, 2001::/32, 2001:2::/48, 2001:3::/32, 2001:10::-2001:2f:ffff:ffff:ffff:ffff:ffff:ffff, 2001:db8::/32, 2002::/16, 3000::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff } goto log_blacklist + ip6 daddr @ipv6_blacklist goto log_blacklist + } + + chain log_blacklist { + log prefix "NFT BLACKLIST " flags ip options flags ether limit rate 5/minute burst 10 packets drop + counter packets 0 bytes 0 drop + } + + chain FORWARD { + type filter hook forward priority filter; policy drop; + ct state established,related accept + fib daddr type { broadcast, anycast, multicast } counter packets 0 bytes 0 drop + iifname vmap @if_forward + log prefix "NFT REJECT FWD " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain public_forward { + udp dport { 5060, 7078-7097 } oifname "eth2.10" jump { + ip6 saddr { 2001:db8::1-2001:db8::2 } accept + meta nfproto ipv6 log prefix "NFT DROP SIP " flags ip options flags ether limit rate 5/second burst 10 packets drop + } + counter packets 0 bytes 0 drop + } + + chain trusted_forward { + oifname "eth0" accept + icmp type echo-request accept + icmpv6 type echo-request accept + ip daddr { 192.168.3.30, 192.168.4.40 } tcp dport vmap { 22 : accept, 80 : drop, 443 : accept } + ip daddr 192.168.2.20 jump { + tcp dport { 80, 443, 515, 631, 9100 } accept + udp dport 161 accept + } + } + + chain voip_forward { + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } oifname "eth0" accept + ip6 daddr { 2001:db8::1-2001:db8::2 } jump { + udp dport { 3478, 5060 } accept + udp sport 7078-7097 accept + tcp dport 5061 accept + } + tcp dport 587 ip daddr 10.0.0.1 accept + tcp dport 80 oifname "eth0" counter packets 0 bytes 0 reject + } + + chain guest_forward { + oifname "eth0" accept + } + + chain OUTPUT { + type filter hook output priority filter; policy drop; + oif "lo" accept + ct state vmap { invalid : jump ct_invalid_out, established : accept, related : accept, untracked : jump ct_untracked_out } + oifname vmap @if_output + log prefix "NFT REJECT OUT " flags ip options flags ether limit rate 5/second burst 10 packets reject + } + + chain ct_invalid_out { + counter packets 0 bytes 0 drop + } + + chain ct_untracked_out { + icmpv6 type { mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, mld2-listener-report } return + counter packets 0 bytes 0 drop + } + + chain public_output { + ct state new meta nfproto vmap { ipv4 : jump blacklist_output_ipv4, ipv6 : jump blacklist_output_ipv6 } + icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp dport 547 ip6 saddr fe80::/64 ip6 daddr ff02::1:2 accept + udp dport { 53, 123 } accept + tcp dport { 443, 587, 853 } accept + } + + chain home_output { + icmp type { destination-unreachable, echo-request, time-exceeded, parameter-problem } accept + icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request } accept + icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } ip6 hoplimit 255 accept + icmpv6 type { mld-listener-query, mld2-listener-report } ip6 hoplimit 1 accept + udp sport 547 udp dport 546 ip6 saddr fe80::/64 oifname { "eth1", "eth2.10", "eth2.20" } accept + udp sport 67 udp dport 68 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept + tcp dport 22 ip daddr 192.168.1.10 accept + } + + chain POSTROUTING_SRCNAT { + type nat hook postrouting priority srcnat; policy accept; + ip saddr { 192.168.1.0-192.168.4.255 } oifname "eth0" masquerade + } +} diff --git a/tests/shell/testcases/packetpath/tcp_options b/tests/shell/testcases/packetpath/tcp_options index 1c9ee5329..88552226e 100755 --- a/tests/shell/testcases/packetpath/tcp_options +++ b/tests/shell/testcases/packetpath/tcp_options @@ -15,14 +15,14 @@ table inet t { chain c { type filter hook output priority 0; tcp dport != 22345 accept - tcp flags syn / fin,syn,rst,ack tcp option 254 length ge 4 counter name nomatchc drop - tcp flags syn / fin,syn,rst,ack tcp option fastopen length ge 2 reset tcp option fastopen counter name nomatchc - tcp flags syn / fin,syn,rst,ack tcp option sack-perm missing counter name nomatchc - tcp flags syn / fin,syn,rst,ack tcp option sack-perm exists counter name sackpermc - tcp flags syn / fin,syn,rst,ack tcp option maxseg size gt 1400 counter name maxsegc - tcp flags syn / fin,syn,rst,ack tcp option nop missing counter name nomatchc - tcp flags syn / fin,syn,rst,ack tcp option nop exists counter name nopc - tcp flags syn / fin,syn,rst,ack drop + tcp flags & (fin | syn | rst | ack ) == syn tcp option 254 length ge 4 counter name nomatchc drop + tcp flags & (fin | syn | rst | ack ) == syn tcp option fastopen length ge 2 reset tcp option fastopen counter name nomatchc + tcp flags & (fin | syn | rst | ack ) == syn tcp option sack-perm missing counter name nomatchc + tcp flags & (fin | syn | rst | ack) == syn tcp option sack-perm exists counter name sackpermc + tcp flags & (fin | syn | rst | ack) == syn tcp option maxseg size gt 1400 counter name maxsegc + tcp flags & (fin | syn | rst | ack) == syn tcp option nop missing counter name nomatchc + tcp flags & (fin | syn | rst | ack) == syn tcp option nop exists counter name nopc + tcp flags & (fin | syn | rst | ack) == syn drop } } EOF -- 2.47.3