summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-05-18 14:40:38 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2023-05-18 17:02:28 +0200
commit5629f9c211fff71b72f2ba0c452801605b63cbfb (patch)
tree89f50a41fa2d2bc43e1e663d51b66c57ff5f9e2d
parentd486c9e626405e829221b82d7355558005b26d8a (diff)
evaluate: set NFT_SET_EVAL flag if dynamic set already exists
nft reports EEXIST when reading an existing set whose NFT_SET_EVAL has been previously inferred from the ruleset. # cat test.nft table ip test { set dlist { type ipv4_addr size 65535 } chain output { type filter hook output priority filter; policy accept; udp dport 1234 update @dlist { ip daddr } counter packets 0 bytes 0 } } # nft -f test.nft # nft -f test.nft test.nft:2:6-10: Error: Could not process rule: File exists set dlist { ^^^^^ Phil Sutter says: In the first call, the set lacking 'dynamic' flag does not exist and is therefore added to the cache. Consequently, both the 'add set' command and the set statement point at the same set object. In the second call, a set with same name exists already, so the object created for 'add set' command is not added to cache and consequently not updated with the missing flag. The kernel thus rejects the NEWSET request as the existing set differs from the new one. Set on the NFT_SET_EVAL flag if the existing set sets it on. Fixes: 8d443adfcc8c1 ("evaluate: attempt to set_eval flag if dynamic updates requested") Tested-by: Eric Garver <eric@garver.life> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--src/evaluate.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 08243220..17a437bd 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -4516,6 +4516,14 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
existing_set = set_cache_find(table, set->handle.set.name);
if (!existing_set)
set_cache_add(set_get(set), table);
+
+ if (existing_set && existing_set->flags & NFT_SET_EVAL) {
+ uint32_t existing_flags = existing_set->flags & ~NFT_SET_EVAL;
+ uint32_t new_flags = set->flags & ~NFT_SET_EVAL;
+
+ if (existing_flags == new_flags)
+ set->flags |= NFT_SET_EVAL;
+ }
}
if (!(set->flags & NFT_SET_INTERVAL) && set->automerge)