summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-12-20 16:09:08 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-12-27 19:29:43 +0100
commit402dac2190e6011d4f4ad81c2992b7126b3d79d9 (patch)
tree6591cfc8e5225f09147b139a0f1c6f93e1408a3d /iptables
parentd4b0d248cc057e39608c7c1c1203dd3f1ea96645 (diff)
nft: Simplify per table chain cache update
Previously, each table's chain cache was potentially unallocated until nftnl_chain_list_cb() saw a chain for it. This means such callback had to check the chain_cache pointer for each chain belonging to that table. In addition to the above, nft_chain_list_get() had to cover for the possibility that a given table didn't have any chains at all in kernel, so check requested table's chain cache once more and allocate it if NULL. Instead, simply iterate over all tables and preallocate their chain caches prior to requesting the chain list from kernel. The only caveat is to flush the chain cache completely before retrying in case of EINTR. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables')
-rw-r--r--iptables/nft.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 997d7bc5..7d08a088 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1286,12 +1286,6 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
if (!t)
goto out;
- if (!h->table[t->type].chain_cache) {
- h->table[t->type].chain_cache = nftnl_chain_list_alloc();
- if (!h->table[t->type].chain_cache)
- goto out;
- }
-
nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache);
return MNL_CB_OK;
@@ -1307,7 +1301,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
char buf[16536];
struct nlmsghdr *nlh;
const struct builtin_table *t;
- int ret;
+ int i, ret;
t = nft_table_builtin_find(h, table);
if (!t)
@@ -1316,18 +1310,27 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h,
if (h->table[t->type].chain_cache)
return h->table[t->type].chain_cache;
retry:
+ for (i = 0; i < NFT_TABLE_MAX; i++) {
+ enum nft_table_type type = h->tables[i].type;
+
+ if (!h->tables[i].name)
+ continue;
+
+ h->table[type].chain_cache = nftnl_chain_list_alloc();
+ if (!h->table[type].chain_cache)
+ return NULL;
+ }
+
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h);
if (ret < 0 && errno == EINTR) {
assert(nft_restart(h) >= 0);
+ flush_chain_cache(h, NULL);
goto retry;
}
- if (!h->table[t->type].chain_cache)
- h->table[t->type].chain_cache = nftnl_chain_list_alloc();
-
return h->table[t->type].chain_cache;
}