All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH nft] netlink_delinearize: restore binop syntax when listing ruleset for flags
Date: Tue, 19 Mar 2024 12:03:37 +0100	[thread overview]
Message-ID: <20240319110337.42486-1-pablo@netfilter.org> (raw)

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 <pablo@netfilter.org>
---
 src/netlink_delinearize.c                     | 65 ++++++-------------
 tests/py/inet/tcp.t                           | 16 ++---
 .../testcases/nft-f/dumps/sample-ruleset.nft  |  4 +-
 tests/shell/testcases/packetpath/tcp_options  | 16 ++---
 4 files changed, 37 insertions(+), 64 deletions(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 1d30a78c3441..405a065bc98f 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2517,56 +2517,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 f51ebd36b503..913bf99e3480 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;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/shell/testcases/nft-f/dumps/sample-ruleset.nft b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
index 480b694a8989..1a9f4e7a4afa 100644
--- a/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
+++ b/tests/shell/testcases/nft-f/dumps/sample-ruleset.nft
@@ -73,7 +73,7 @@ table inet filter {
 
 	chain ct_new_pre {
 		jump rpfilter
-		tcp flags != syn / fin,syn,rst,ack counter packets 0 bytes 0 drop
+		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 }
 	}
 
@@ -131,7 +131,7 @@ table inet filter {
 		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 / syn,rst tcp option maxseg size set rt mtu
+			tcp flags & (syn | rst) == syn tcp option maxseg size set rt mtu
 		}
 	}
 
diff --git a/tests/shell/testcases/packetpath/tcp_options b/tests/shell/testcases/packetpath/tcp_options
index 1c9ee5329b26..88552226ee3a 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.30.2


             reply	other threads:[~2024-03-19 11:03 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-19 11:03 Pablo Neira Ayuso [this message]
2024-03-20 18:07 ` [PATCH nft] netlink_delinearize: restore binop syntax when listing ruleset for flags Pablo Neira Ayuso
2024-03-20 20:45   ` Phil Sutter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240319110337.42486-1-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.