]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: transform flag match expression to binop expression from parser
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 26 Mar 2025 20:54:08 +0000 (21:54 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 27 Mar 2025 20:39:03 +0000 (21:39 +0100)
Transform flagcmp expression to a relational with binop on the left hand
side, ie.

         relational
          /      \
       binop    value
       /   \
 payload  mask

Add list_expr_to_binop() to make this transformation.

Goal is two-fold:

- Allow -o/--optimize to pick up on this representation.
- Remove the flagcmp expression in a follow up patch.

This prepare for the removal of the flagcmp expression added by:

  c3d57114f119 ("parser_bison: add shortcut syntax for matching flags without binary operations")

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/expression.h
src/expression.c
src/parser_bison.y

index 6e8675b0cc1a1fbc86b6c2ac40735231d111672b..d48d8ed81d2b0ffaec8f3c7b623b5103e0824e9a 100644 (file)
@@ -519,6 +519,7 @@ extern void list_splice_sorted(struct list_head *list, struct list_head *head);
 extern struct expr *concat_expr_alloc(const struct location *loc);
 
 extern struct expr *list_expr_alloc(const struct location *loc);
+struct expr *list_expr_to_binop(struct expr *expr);
 
 extern struct expr *set_expr_alloc(const struct location *loc,
                                   const struct set *set);
index 52e4c7d187ac1435a05464648220cf53fc2e3079..ecdb8846a4f1f8db351bfa521f5db74794953290 100644 (file)
@@ -1263,6 +1263,29 @@ struct expr *list_expr_alloc(const struct location *loc)
        return compound_expr_alloc(loc, EXPR_LIST);
 }
 
+/* list is assumed to have two items at least, otherwise extend this! */
+struct expr *list_expr_to_binop(struct expr *expr)
+{
+       struct expr *first, *last, *i;
+
+       first = list_first_entry(&expr->expressions, struct expr, list);
+       i = first;
+
+       list_for_each_entry_continue(i, &expr->expressions, list) {
+               if (first) {
+                       last = binop_expr_alloc(&expr->location, OP_OR, first, i);
+                       first = NULL;
+               } else {
+                       last = binop_expr_alloc(&expr->location, OP_OR, i, last);
+               }
+       }
+       /* zap list expressions, they have been moved to binop expression. */
+       init_list_head(&expr->expressions);
+       expr_free(expr);
+
+       return last;
+}
+
 static const char *calculate_delim(const struct expr *expr, int *count,
                                   struct output_ctx *octx)
 {
index 5760ba479fc9d33bb81cdaf5c2dd12c370b83497..4b2b51d4275c7a223e2e5144f9e38703bb2a374a 100644 (file)
@@ -4917,19 +4917,33 @@ relational_expr         :       expr    /* implicit */  rhs_expr
                        }
                        |       expr    /* implicit */  basic_rhs_expr  SLASH   list_rhs_expr
                        {
-                               $$ = flagcmp_expr_alloc(&@$, OP_EQ, $1, $4, $2);
+                               struct expr *mask = list_expr_to_binop($4);
+                               struct expr *binop = binop_expr_alloc(&@$, OP_AND, $1, mask);
+
+                               $$ = relational_expr_alloc(&@$, OP_IMPLICIT, binop, $2);
                        }
                        |       expr    /* implicit */  list_rhs_expr   SLASH   list_rhs_expr
                        {
-                               $$ = flagcmp_expr_alloc(&@$, OP_EQ, $1, $4, $2);
+                               struct expr *value = list_expr_to_binop($2);
+                               struct expr *mask = list_expr_to_binop($4);
+                               struct expr *binop = binop_expr_alloc(&@$, OP_AND, $1, mask);
+
+                               $$ = relational_expr_alloc(&@$, OP_IMPLICIT, binop, value);
                        }
                        |       expr    relational_op   basic_rhs_expr  SLASH   list_rhs_expr
                        {
-                               $$ = flagcmp_expr_alloc(&@$, $2, $1, $5, $3);
+                               struct expr *mask = list_expr_to_binop($5);
+                               struct expr *binop = binop_expr_alloc(&@$, OP_AND, $1, mask);
+
+                               $$ = relational_expr_alloc(&@$, $2, binop, $3);
                        }
                        |       expr    relational_op   list_rhs_expr   SLASH   list_rhs_expr
                        {
-                               $$ = flagcmp_expr_alloc(&@$, $2, $1, $5, $3);
+                               struct expr *value = list_expr_to_binop($3);
+                               struct expr *mask = list_expr_to_binop($5);
+                               struct expr *binop = binop_expr_alloc(&@$, OP_AND, $1, mask);
+
+                               $$ = relational_expr_alloc(&@$, $2, binop, value);
                        }
                        |       expr    relational_op   rhs_expr
                        {