From 6d80e0f154920b5d26aa764459ec0450a8a12b58 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 17 Mar 2020 14:50:38 +0100 Subject: src: support for counter in set definition 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 --- include/rule.h | 1 + src/evaluate.c | 9 +++++++++ src/mnl.c | 5 +++++ src/netlink.c | 7 +++++++ src/parser_bison.y | 5 +++++ src/rule.c | 10 ++++++++++ 6 files changed, 37 insertions(+) diff --git a/include/rule.h b/include/rule.h index 224e6871..70c8c4cf 100644 --- a/include/rule.h +++ b/include/rule.h @@ -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; diff --git a/src/evaluate.c b/src/evaluate.c index d0e712dc..6325f52e 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -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; diff --git a/src/mnl.c b/src/mnl.c index a517712c..18a73e28 100644 --- 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), diff --git a/src/netlink.c b/src/netlink.c index e10af564..b254753f 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -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; diff --git a/src/parser_bison.y b/src/parser_bison.y index 3d65d208..e14118ca 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -1733,6 +1733,11 @@ set_block : /* empty */ { $$ = $-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; diff --git a/src/rule.c b/src/rule.c index 8e585268..ab99bbd2 100644 --- a/src/rule.c +++ b/src/rule.c @@ -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); -- cgit v1.2.3