summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2020-03-17 14:50:38 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2020-03-20 13:13:40 +0100
commit6d80e0f154920b5d26aa764459ec0450a8a12b58 (patch)
tree97627d1a1935f051b83b8cb11751c92769261456
parent6c84577b0d23d1f3fdafb4d74fd5868e891cc6af (diff)
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 <pablo@netfilter.org>
-rw-r--r--include/rule.h1
-rw-r--r--src/evaluate.c9
-rw-r--r--src/mnl.c5
-rw-r--r--src/netlink.c7
-rw-r--r--src/parser_bison.y5
-rw-r--r--src/rule.c10
6 files changed, 37 insertions, 0 deletions
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 */ { $$ = $<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;
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);