From 407c54f712554d1055c43e8a7d731a765564c16b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 6 Aug 2020 12:52:00 +0200 Subject: src: cache gets out of sync in interactive mode Since 94a945ffa81b ("libnftables: Get rid of explicit cache flushes"), the cache logic checks for the generation number to refresh the cache. This breaks interactive mode when listing stateful objects though. This patch adds a new flag to force a cache refresh when the user requests a ruleset listing. Signed-off-by: Pablo Neira Ayuso --- include/cache.h | 1 + src/cache.c | 2 ++ src/rule.c | 8 +++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/cache.h b/include/cache.h index 86a7eff7..213a6eaf 100644 --- a/include/cache.h +++ b/include/cache.h @@ -30,6 +30,7 @@ enum cache_level_flags { NFT_CACHE_CHAIN_BIT | NFT_CACHE_RULE_BIT, NFT_CACHE_FULL = __NFT_CACHE_MAX_BIT - 1, + NFT_CACHE_REFRESH = (1 << 29), NFT_CACHE_UPDATE = (1 << 30), NFT_CACHE_FLUSHED = (1 << 31), }; diff --git a/src/cache.c b/src/cache.c index a45111a7..7797ff6b 100644 --- a/src/cache.c +++ b/src/cache.c @@ -143,6 +143,8 @@ unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds) break; case CMD_LIST: case CMD_EXPORT: + flags |= NFT_CACHE_FULL | NFT_CACHE_REFRESH; + break; case CMD_MONITOR: flags |= NFT_CACHE_FULL; break; diff --git a/src/rule.c b/src/rule.c index 6335aa21..8dc1792b 100644 --- a/src/rule.c +++ b/src/rule.c @@ -237,6 +237,11 @@ static bool cache_is_complete(struct nft_cache *cache, unsigned int flags) return (cache->flags & flags) == flags; } +static bool cache_needs_refresh(struct nft_cache *cache) +{ + return cache->flags & NFT_CACHE_REFRESH; +} + static bool cache_is_updated(struct nft_cache *cache, uint16_t genid) { return genid && genid == cache->genid; @@ -261,7 +266,8 @@ int cache_update(struct nft_ctx *nft, unsigned int flags, struct list_head *msgs replay: ctx.seqnum = cache->seqnum++; genid = mnl_genid_get(&ctx); - if (cache_is_complete(cache, flags) && + if (!cache_needs_refresh(cache) && + cache_is_complete(cache, flags) && cache_is_updated(cache, genid)) return 0; -- cgit v1.2.3