]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: cache gets out of sync in interactive mode
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 6 Aug 2020 10:52:00 +0000 (12:52 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 6 Aug 2020 11:05:13 +0000 (13:05 +0200)
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 <pablo@netfilter.org>
include/cache.h
src/cache.c
src/rule.c

index 86a7eff78055115ddad8c50e9cd63c7053e7ce9f..213a6eaf9104b1b9e9195fc97572a883342150b8 100644 (file)
@@ -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),
 };
index a45111a7920e57fd9dbc8b4fef42c7593bc254f3..7797ff6b046086c6ba0cfc3767f2e2105e5bb8f5 100644 (file)
@@ -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;
index 6335aa2189adcce00e66f8de3c7b036e8396b301..8dc1792b4e5a235b838959474098c8a71ae849d5 100644 (file)
@@ -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;