]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: add and use `set_is_meter` helper
authorJeremy Sowden <jeremy@azazel.net>
Tue, 5 Nov 2019 21:40:26 +0000 (21:40 +0000)
committerFlorian Westphal <fw@strlen.de>
Wed, 6 Nov 2019 14:36:09 +0000 (15:36 +0100)
The sets constructed for meters are flagged as anonymous and dynamic.
However, in some places there are only checks that they are dynamic,
which can lead to normal sets being classified as meters.

For example:

  # nft add table t
  # nft add set t s { type ipv4_addr; size 256; flags dynamic,timeout; }
  # nft add chain t c
  # nft add rule t c tcp dport 80 meter m size 128 { ip saddr limit rate 10/second }
  # nft list meters
  table ip t {
          set s {
                  type ipv4_addr
                  size 256
                  flags dynamic,timeout
          }
          meter m {
                  type ipv4_addr
                  size 128
                  flags dynamic
          }
  }
  # nft list meter t m
  table ip t {
          meter m {
                  type ipv4_addr
                  size 128
                  flags dynamic
          }
  }
  # nft list meter t s
  Error: No such file or directory
  list meter t s
               ^

Add a new helper `set_is_meter` and use it wherever there are checks for
meters.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/rule.h
src/evaluate.c
src/expression.c
src/json.c
src/rule.c
tests/shell/testcases/sets/0038meter_list_0 [new file with mode: 0755]

index a718923b14a36d7f818b54a2e67cf157232d3dc7..48b5ba5009657f4d4ee3bb32e76133ac239f293b 100644 (file)
@@ -356,6 +356,11 @@ static inline bool map_is_literal(uint32_t set_flags)
        return !(set_is_anonymous(set_flags) || !set_is_map(set_flags));
 }
 
+static inline bool set_is_meter(uint32_t set_flags)
+{
+       return set_is_anonymous(set_flags) && (set_flags & NFT_SET_EVAL);
+}
+
 #include <statement.h>
 
 struct counter {
index 81230fc7f4be41fe4939c2605428ce76777f264e..e54eaf1a711080e9d0e1d3c2d5a64f606d5dc3b1 100644 (file)
@@ -3888,8 +3888,7 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
                if (set == NULL)
                        return set_not_found(ctx, &ctx->cmd->handle.set.location,
                                             ctx->cmd->handle.set.name);
-               else if (!(set->flags & NFT_SET_EVAL) ||
-                        !(set->flags & NFT_SET_ANONYMOUS))
+               else if (!set_is_meter(set->flags))
                        return cmd_error(ctx, &ctx->cmd->handle.set.location,
                                         "%s", strerror(ENOENT));
 
@@ -4037,8 +4036,7 @@ static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
                if (set == NULL)
                        return set_not_found(ctx, &ctx->cmd->handle.set.location,
                                             ctx->cmd->handle.set.name);
-               else if (!(set->flags & NFT_SET_EVAL) ||
-                        !(set->flags & NFT_SET_ANONYMOUS))
+               else if (!set_is_meter(set->flags))
                        return cmd_error(ctx, &ctx->cmd->handle.set.location,
                                         "%s", strerror(ENOENT));
 
index e456010ff8b0fc909726292348f4b6837b74d785..5070b1014392cc16eb103ee953f3d1c64bdbf4dc 100644 (file)
@@ -1051,14 +1051,12 @@ struct expr *map_expr_alloc(const struct location *loc, struct expr *arg,
 
 static void set_ref_expr_print(const struct expr *expr, struct output_ctx *octx)
 {
-       if (set_is_anonymous(expr->set->flags)) {
-               if (expr->set->flags & NFT_SET_EVAL)
-                       nft_print(octx, "%s", expr->set->handle.set.name);
-               else
-                       expr_print(expr->set->init, octx);
-       } else {
+       if (set_is_meter(expr->set->flags))
+               nft_print(octx, "%s", expr->set->handle.set.name);
+       else if (set_is_anonymous(expr->set->flags))
+               expr_print(expr->set->init, octx);
+       else
                nft_print(octx, "@%s", expr->set->handle.set.name);
-       }
 }
 
 static void set_ref_expr_clone(struct expr *new, const struct expr *expr)
index f0a70117745411953e7bf752137ad3bcd1d15e43..3498e24db363fe153b83536e2752e2f42522e651 100644 (file)
@@ -86,7 +86,7 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
        } else if (set_is_objmap(set->flags)) {
                type = "map";
                datatype_ext = obj_type_name(set->objtype);
-       } else if (set->flags & NFT_SET_EVAL) {
+       } else if (set_is_meter(set->flags)) {
                type = "meter";
        } else {
                type = "set";
@@ -1684,7 +1684,7 @@ static json_t *do_list_sets_json(struct netlink_ctx *ctx, struct cmd *cmd)
                            !set_is_literal(set->flags))
                                continue;
                        if (cmd->obj == CMD_OBJ_METERS &&
-                           !(set->flags & NFT_SET_EVAL))
+                           !set_is_meter(set->flags))
                                continue;
                        if (cmd->obj == CMD_OBJ_MAPS &&
                            !map_is_literal(set->flags))
index ff9e8e6c0e57c9ede43468af8fcfde023e668227..552b3c6b303a36f0d696f6158ac0a9203b15d569 100644 (file)
@@ -446,8 +446,7 @@ static void set_print_declaration(const struct set *set,
        const char *type;
        uint32_t flags;
 
-       if ((set->flags & (NFT_SET_EVAL | NFT_SET_ANONYMOUS)) ==
-                               (NFT_SET_EVAL | NFT_SET_ANONYMOUS))
+       if (set_is_meter(set->flags))
                type = "meter";
        else if (set_is_map(set->flags))
                type = "map";
@@ -534,11 +533,11 @@ static void set_print_declaration(const struct set *set,
 }
 
 static void do_set_print(const struct set *set, struct print_fmt_options *opts,
-                         struct output_ctx *octx)
+                        struct output_ctx *octx)
 {
        set_print_declaration(set, opts, octx);
 
-       if ((set->flags & NFT_SET_EVAL && nft_output_stateless(octx)) ||
+       if ((set_is_meter(set->flags) && nft_output_stateless(octx)) ||
            nft_output_terse(octx)) {
                nft_print(octx, "%s}%s", opts->tab, opts->nl);
                return;
@@ -1691,7 +1690,7 @@ static int do_list_sets(struct netlink_ctx *ctx, struct cmd *cmd)
                            !set_is_literal(set->flags))
                                continue;
                        if (cmd->obj == CMD_OBJ_METERS &&
-                           !(set->flags & NFT_SET_EVAL))
+                           !set_is_meter(set->flags))
                                continue;
                        if (cmd->obj == CMD_OBJ_MAPS &&
                            !map_is_literal(set->flags))
diff --git a/tests/shell/testcases/sets/0038meter_list_0 b/tests/shell/testcases/sets/0038meter_list_0
new file mode 100755 (executable)
index 0000000..e9e0f6f
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#
+# Listing meters should not include dynamic sets in the output
+#
+
+set -e
+
+RULESET="
+  add table t
+  add set t s { type ipv4_addr; size 256; flags dynamic,timeout; }
+  add chain t c
+  add rule t c tcp dport 80 meter m size 128 { ip saddr limit rate 10/second }
+"
+
+expected_output="table ip t {
+       meter m {
+               type ipv4_addr
+               size 128
+               flags dynamic
+       }
+}"
+
+$NFT -f - <<< "$RULESET"
+
+test_output=$($NFT list meters)
+
+test "$test_output" = "$expected_output"
+