]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
json: Accept more than two operands in binary expressions
authorPhil Sutter <phil@nwl.cc>
Wed, 20 Mar 2024 14:54:54 +0000 (15:54 +0100)
committerPhil Sutter <phil@nwl.cc>
Fri, 12 Apr 2024 12:33:14 +0000 (14:33 +0200)
The most common use case is ORing flags like

| syn | ack | rst

but nft seems to be fine with less intuitive stuff like

| meta mark set ip dscp << 2 << 3

so support all of them.

Signed-off-by: Phil Sutter <phil@nwl.cc>
doc/libnftables-json.adoc
src/json.c
src/parser_json.c
tests/py/inet/tcp.t.json
tests/py/inet/tcp.t.json.output
tests/shell/testcases/nft-f/dumps/0012different_defines_0.json-nft
tests/shell/testcases/sets/dumps/0055tcpflags_0.json-nft

index 3948a0bad47c12d05366543f1ec43791b1e25540..e3b24cc4ed60de8c5e3100204d315d1f44352dd8 100644 (file)
@@ -1343,15 +1343,17 @@ Perform kernel Forwarding Information Base lookups.
 
 === BINARY OPERATION
 [verse]
-*{ "|": [* 'EXPRESSION'*,* 'EXPRESSION' *] }*
-*{ "^": [* 'EXPRESSION'*,* 'EXPRESSION' *] }*
-*{ "&": [* 'EXPRESSION'*,* 'EXPRESSION' *] }*
-*{ "+<<+": [* 'EXPRESSION'*,* 'EXPRESSION' *] }*
-*{ ">>": [* 'EXPRESSION'*,* 'EXPRESSION' *] }*
-
-All binary operations expect an array of exactly two expressions, of which the
+*{ "|": [* 'EXPRESSION'*,* 'EXPRESSIONS' *] }*
+*{ "^": [* 'EXPRESSION'*,* 'EXPRESSIONS' *] }*
+*{ "&": [* 'EXPRESSION'*,* 'EXPRESSIONS' *] }*
+*{ "+<<+": [* 'EXPRESSION'*,* 'EXPRESSIONS' *] }*
+*{ ">>": [* 'EXPRESSION'*,* 'EXPRESSIONS' *] }*
+'EXPRESSIONS' := 'EXPRESSION' | 'EXPRESSION'*,* 'EXPRESSIONS'
+
+All binary operations expect an array of at least two expressions, of which the
 first element denotes the left hand side and the second one the right hand
-side.
+side. Extra elements are accepted in the given array and appended to the term
+accordingly.
 
 === VERDICT
 [verse]
index 29fbd0cfdba28876b32b76ba38fe0b8ecf378429..3753017169930128c4c2547111058c093fe19a3b 100644 (file)
@@ -540,11 +540,24 @@ json_t *flagcmp_expr_json(const struct expr *expr, struct output_ctx *octx)
                         "right", expr_print_json(expr->flagcmp.value, octx));
 }
 
+static json_t *
+__binop_expr_json(int op, const struct expr *expr, struct output_ctx *octx)
+{
+       json_t *a = json_array();
+
+       if (expr->etype == EXPR_BINOP && expr->op == op) {
+               json_array_extend(a, __binop_expr_json(op, expr->left, octx));
+               json_array_extend(a, __binop_expr_json(op, expr->right, octx));
+       } else {
+               json_array_append_new(a, expr_print_json(expr, octx));
+       }
+       return a;
+}
+
 json_t *binop_expr_json(const struct expr *expr, struct output_ctx *octx)
 {
-       return json_pack("{s:[o, o]}", expr_op_symbols[expr->op],
-                        expr_print_json(expr->left, octx),
-                        expr_print_json(expr->right, octx));
+       return json_pack("{s:o}", expr_op_symbols[expr->op],
+                        __binop_expr_json(expr->op, expr, octx));
 }
 
 json_t *relational_expr_json(const struct expr *expr, struct output_ctx *octx)
index efe49494946044b453691e97e8e548c063f2ae62..418d4ad7f60779085bac1d6bfb1d0ca592d4da57 100644 (file)
@@ -1204,6 +1204,18 @@ static struct expr *json_parse_binop_expr(struct json_ctx *ctx,
                return NULL;
        }
 
+       if (json_array_size(root) > 2) {
+               left = json_parse_primary_expr(ctx, json_array_get(root, 0));
+               right = json_parse_primary_expr(ctx, json_array_get(root, 1));
+               left = binop_expr_alloc(int_loc, thisop, left, right);
+               for (i = 2; i < json_array_size(root); i++) {
+                       jright = json_array_get(root, i);
+                       right = json_parse_primary_expr(ctx, jright);
+                       left = binop_expr_alloc(int_loc, thisop, left, right);
+               }
+               return left;
+       }
+
        if (json_unpack_err(ctx, root, "[o, o!]", &jleft, &jright))
                return NULL;
 
index d3a846cf9a4006f81e0d598bfc7cd9c091f6c428..bd589cf0091fea4d7f386fc0980b678cf5125ea5 100644 (file)
                         }
                     },
                     {
-                        "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ]
+                        "|": [ "fin", "syn", "rst", "psh", "ack", "urg", "ecn", "cwr" ]
                     }
                 ]
             },
             "op": "==",
-            "right": { "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] }
+            "right": { "|": [ "fin", "syn", "rst", "psh", "ack", "urg", "ecn", "cwr" ] }
         }
     }
 ]
                             "protocol": "tcp"
                         }
                     },
-                    {
-                        "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            {
-                                                "|": [
-                                                    {
-                                                        "|": [
-                                                            "fin",
-                                                            "syn"
-                                                        ]
-                                                    },
-                                                    "rst"
-                                                ]
-                                            },
-                                            "psh"
-                                        ]
-                                    },
-                                    "ack"
-                                ]
-                            },
-                            "urg"
-                        ]
-                    }
+                    { "|": [ "fin", "syn", "rst", "psh", "ack", "urg" ] }
                 ]
             },
             "op": "==",
             "right": {
                 "set": [
-                    {
-                        "|": [
-                            {
-                                "|": [
-                                    "fin",
-                                    "psh"
-                                ]
-                            },
-                            "ack"
-                        ]
-                    },
+                    { "|": [ "fin", "psh", "ack" ] },
                     "fin",
-                    {
-                        "|": [
-                            "psh",
-                            "ack"
-                        ]
-                    },
+                    { "|": [ "psh", "ack" ] },
                     "ack"
                 ]
             }
                             "protocol": "tcp"
                         }
                     },
-                    {
-                        "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
-                            "ack"
-                        ]
-                    }
+                    { "|": [ "fin", "syn", "rst", "ack" ] }
                 ]
             },
             "op": "!=",
index e186e127fd6711c4caf43b65b8fa760e21179c6e..3f03c0ddd1586dc48d304b8610b08f7539222c26 100644 (file)
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            {
-                                                "|": [
-                                                    {
-                                                        "|": [
-                                                            "fin",
-                                                            "syn"
-                                                        ]
-                                                    },
-                                                    "rst"
-                                                ]
-                                            },
-                                            "psh"
-                                        ]
-                                    },
-                                    "ack"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
+                            "psh",
+                            "ack",
                             "urg"
                         ]
                     }
                     "fin",
                     {
                         "|": [
-                            {
-                                "|": [
-                                    "fin",
-                                    "psh"
-                                ]
-                            },
+                            "fin",
+                            "psh",
                             "ack"
                         ]
                     },
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
                             "ack"
                         ]
                     }
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
                             "ack"
                         ]
                     }
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
                             "ack"
                         ]
                     }
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
                             "ack"
                         ]
                     }
                     },
                     {
                         "|": [
-                            {
-                                "|": [
-                                    {
-                                        "|": [
-                                            "fin",
-                                            "syn"
-                                        ]
-                                    },
-                                    "rst"
-                                ]
-                            },
+                            "fin",
+                            "syn",
+                            "rst",
                             "ack"
                         ]
                     }
index 8f3f3a81a9bc86dac892678dbb8df3fc41917bda..1b2e342047f4b9c8b4871259a1eefa9505d9485e 100644 (file)
               },
               "right": {
                 "|": [
-                  {
-                    "|": [
-                      "established",
-                      "related"
-                    ]
-                  },
+                  "established",
+                  "related",
                   "new"
                 ]
               }
index cd39f0909e120850c354e34427c4c597d92d08e6..6a3511515f78513cc87799ba73782bb0020a4489 100644 (file)
         "elem": [
           {
             "|": [
-              {
-                "|": [
-                  {
-                    "|": [
-                      "fin",
-                      "psh"
-                    ]
-                  },
-                  "ack"
-                ]
-              },
+              "fin",
+              "psh",
+              "ack",
               "urg"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "fin",
-                  "psh"
-                ]
-              },
+              "fin",
+              "psh",
               "ack"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "fin",
-                  "ack"
-                ]
-              },
+              "fin",
+              "ack",
               "urg"
             ]
           },
           },
           {
             "|": [
-              {
-                "|": [
-                  {
-                    "|": [
-                      "syn",
-                      "psh"
-                    ]
-                  },
-                  "ack"
-                ]
-              },
+              "syn",
+              "psh",
+              "ack",
               "urg"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "syn",
-                  "psh"
-                ]
-              },
+              "syn",
+              "psh",
               "ack"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "syn",
-                  "ack"
-                ]
-              },
+              "syn",
+              "ack",
               "urg"
             ]
           },
           "syn",
           {
             "|": [
-              {
-                "|": [
-                  {
-                    "|": [
-                      "rst",
-                      "psh"
-                    ]
-                  },
-                  "ack"
-                ]
-              },
+              "rst",
+              "psh",
+              "ack",
               "urg"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "rst",
-                  "psh"
-                ]
-              },
+              "rst",
+              "psh",
               "ack"
             ]
           },
           {
             "|": [
-              {
-                "|": [
-                  "rst",
-                  "ack"
-                ]
-              },
+              "rst",
+              "ack",
               "urg"
             ]
           },
           "rst",
           {
             "|": [
-              {
-                "|": [
-                  "psh",
-                  "ack"
-                ]
-              },
+              "psh",
+              "ack",
               "urg"
             ]
           },