]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
extensions: libxt_conntrack: use bitops for status negation
authorAlexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Thu, 1 Apr 2021 13:47:08 +0000 (16:47 +0300)
committerFlorian Westphal <fw@strlen.de>
Fri, 2 Apr 2021 15:04:55 +0000 (17:04 +0200)
At the moment, status_xlate_print function prints statusmask as comma-separated
sequence of enabled statusmask flags. But if we have inverted conntrack ctstatus
condition then we have to use more complex expression (if more than one flag enabled)
because nft not supports syntax like "ct status != expected,assured".

Examples:
! --ctstatus CONFIRMED,ASSURED
should be translated as
ct status & (assured|confirmed) == 0

! --ctstatus CONFIRMED
can be translated as
ct status & confirmed == 0

See also netfilter/xt_conntrack.c (conntrack_mt() function as a reference).

Reproducer:
$ iptables -A INPUT -d 127.0.0.1/32 -p tcp -m conntrack ! --ctstatus expected,assured -j DROP
$ nft list ruleset
...
meta l4proto tcp ip daddr 127.0.0.1 ct status != expected,assured counter packets 0 bytes 0 drop
...

it will fail if we try to load this rule:
$ nft -f nft_test
../nft_test:6:97-97: Error: syntax error, unexpected comma, expecting newline or semicolon

Cc: Florian Westphal <fw@strlen.de>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
extensions/libxt_conntrack.c
extensions/libxt_conntrack.txlate

index 91f9e4aa994f811ca6c7fa3b5842a8f9c64582d0..7f7b45ee1f822dc6a41a80626fc337f57794ee6b 100644 (file)
@@ -1200,26 +1200,39 @@ static int state_xlate(struct xt_xlate *xl,
        return 1;
 }
 
-static void status_xlate_print(struct xt_xlate *xl, unsigned int statusmask)
+static void status_xlate_print(struct xt_xlate *xl, unsigned int statusmask, int inverted)
 {
        const char *sep = "";
+       int one_flag_set;
+
+       one_flag_set = !(statusmask & (statusmask - 1));
+
+       if (inverted && !one_flag_set)
+               xt_xlate_add(xl, "& (");
+       else if (inverted)
+               xt_xlate_add(xl, "& ");
 
        if (statusmask & IPS_EXPECTED) {
                xt_xlate_add(xl, "%s%s", sep, "expected");
-               sep = ",";
+               sep = inverted && !one_flag_set ? "|" : ",";
        }
        if (statusmask & IPS_SEEN_REPLY) {
                xt_xlate_add(xl, "%s%s", sep, "seen-reply");
-               sep = ",";
+               sep = inverted && !one_flag_set ? "|" : ",";
        }
        if (statusmask & IPS_ASSURED) {
                xt_xlate_add(xl, "%s%s", sep, "assured");
-               sep = ",";
+               sep = inverted && !one_flag_set ? "|" : ",";
        }
        if (statusmask & IPS_CONFIRMED) {
                xt_xlate_add(xl, "%s%s", sep, "confirmed");
-               sep = ",";
+               sep = inverted && !one_flag_set ? "|" : ",";
        }
+
+       if (inverted && !one_flag_set)
+               xt_xlate_add(xl, ") == 0");
+       else if (inverted)
+               xt_xlate_add(xl, " == 0");
 }
 
 static void addr_xlate_print(struct xt_xlate *xl,
@@ -1277,10 +1290,9 @@ static int _conntrack3_mt_xlate(struct xt_xlate *xl,
        }
 
        if (sinfo->match_flags & XT_CONNTRACK_STATUS) {
-               xt_xlate_add(xl, "%sct status %s", space,
-                            sinfo->invert_flags & XT_CONNTRACK_STATUS ?
-                            "!= " : "");
-               status_xlate_print(xl, sinfo->status_mask);
+               xt_xlate_add(xl, "%sct status ", space);
+               status_xlate_print(xl, sinfo->status_mask,
+                                  sinfo->invert_flags & XT_CONNTRACK_STATUS);
                space = " ";
        }
 
index 5ab85b177c3963374676e97ded218627cd1304e9..8cc7c504ab4b413837dcd42317e89da8a28bef79 100644 (file)
@@ -35,7 +35,13 @@ iptables-translate -t filter -A INPUT -m conntrack --ctstatus EXPECTED -j ACCEPT
 nft add rule ip filter INPUT ct status expected counter accept
 
 iptables-translate -t filter -A INPUT -m conntrack ! --ctstatus CONFIRMED -j ACCEPT
-nft add rule ip filter INPUT ct status != confirmed counter accept
+nft add rule ip filter INPUT ct status & confirmed == 0 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack ! --ctstatus CONFIRMED,ASSURED -j ACCEPT
+nft add rule ip filter INPUT ct status & (assured|confirmed) == 0 counter accept
+
+iptables-translate -t filter -A INPUT -m conntrack --ctstatus CONFIRMED,ASSURED -j ACCEPT
+nft add rule ip filter INPUT ct status assured,confirmed counter accept
 
 iptables-translate -t filter -A INPUT -m conntrack --ctexpire 3 -j ACCEPT
 nft add rule ip filter INPUT ct expiration 3 counter accept