]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: support for counter in set definition
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 17 Mar 2020 13:50:38 +0000 (14:50 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 20 Mar 2020 12:13:40 +0000 (13:13 +0100)
This patch allows you to turn on counter for each element in the set.

 table ip x {
set y {
typeof ip saddr
counter
elements = { 192.168.10.35, 192.168.10.101, 192.168.10.135 }
}

chain z {
type filter hook output priority filter; policy accept;
ip daddr @y
}
 }

This example shows how to turn on counters globally in the set 'y'.

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

index 224e68717bc73e6c5a170f1cc87bfbd581060ca6..70c8c4cf7b43f9e0eaa718012a03158bd6a97716 100644 (file)
@@ -308,6 +308,7 @@ struct set {
        struct expr             *init;
        struct expr             *rg_cache;
        uint32_t                policy;
+       struct stmt             *stmt;
        bool                    root;
        bool                    automerge;
        bool                    key_typeof_valid;
index d0e712dc02f02bb42408a890d0dae9400763b3e7..6325f52e49ffd8bba9e4573ee4db1c6963ee24c9 100644 (file)
@@ -1307,8 +1307,17 @@ static int expr_evaluate_list(struct eval_ctx *ctx, struct expr **expr)
 
 static int expr_evaluate_set_elem(struct eval_ctx *ctx, struct expr **expr)
 {
+       struct set *set = ctx->set;
        struct expr *elem = *expr;
 
+       if (elem->stmt && set->stmt && set->stmt->ops != elem->stmt->ops)
+               return stmt_binary_error(ctx, set->stmt, elem,
+                                        "statement mismatch, element expects %s, "
+                                        "%s has type %s",
+                                        elem->stmt->ops->name,
+                                        set_is_map(set->flags) ? "map" : "set",
+                                        set->stmt->ops->name);
+
        if (expr_evaluate(ctx, &elem->key) < 0)
                return -1;
 
index a517712c14eb21a1d8e5f56aa8a90b5905e27993..18a73e2878b608174f55e35cf535ae8d7fb5535b 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1026,6 +1026,11 @@ int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
                           nftnl_udata_buf_len(udbuf));
        nftnl_udata_buf_free(udbuf);
 
+       if (set->stmt) {
+               nftnl_set_set_data(nls, NFTNL_SET_EXPR,
+                                  netlink_gen_stmt_stateful(set->stmt), 0);
+       }
+
        netlink_dump_set(nls, ctx);
 
        nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
index e10af564bcaceeb6337f23f9056c975a7e851be3..b254753f7424b99bbf87dffacb8cca4ae5a5d0cf 100644 (file)
@@ -766,6 +766,13 @@ struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
        set->handle.set.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME));
        set->automerge     = automerge;
 
+       if (nftnl_set_is_set(nls, NFTNL_SET_EXPR)) {
+               const struct nftnl_expr *nle;
+
+               nle = nftnl_set_get(nls, NFTNL_SET_EXPR);
+               set->stmt = netlink_parse_set_expr(set, &ctx->nft->cache, nle);
+       }
+
        if (datatype) {
                dtype = set_datatype_alloc(datatype, databyteorder);
                klen = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE;
index 3d65d20816d6dffa8bca3d4992e9285d882760b1..e14118ca971e7b63eab1eac56de177235bee8ff0 100644 (file)
@@ -1733,6 +1733,11 @@ set_block                :       /* empty */     { $$ = $<set>-1; }
                                $1->gc_int = $3;
                                $$ = $1;
                        }
+                       |       set_block       COUNTER         stmt_separator
+                       {
+                               $1->stmt = counter_stmt_alloc(&@$);
+                               $$ = $1;
+                       }
                        |       set_block       ELEMENTS        '='             set_block_expr
                        {
                                $1->init = $4;
index 8e58526890916e2a0cad2d49ebe95fb95648e46e..ab99bbd22616cd9fbf130f02407d130560e1c767 100644 (file)
@@ -355,6 +355,7 @@ void set_free(struct set *set)
        if (set->init != NULL)
                expr_free(set->init);
        handle_free(&set->handle);
+       stmt_free(set->stmt);
        expr_free(set->key);
        expr_free(set->data);
        xfree(set);
@@ -544,6 +545,15 @@ static void set_print_declaration(const struct set *set,
                }
                nft_print(octx, "%s", opts->stmt_separator);
        }
+
+       if (set->stmt) {
+               nft_print(octx, "%s%s", opts->tab, opts->tab);
+               octx->flags |= NFT_CTX_OUTPUT_STATELESS;
+               stmt_print(set->stmt, octx);
+               octx->flags &= ~NFT_CTX_OUTPUT_STATELESS;
+               nft_print(octx, "%s", opts->stmt_separator);
+       }
+
        if (set->automerge)
                nft_print(octx, "%s%sauto-merge%s", opts->tab, opts->tab,
                          opts->stmt_separator);