Allow to pass a builtin_table for which to fetch chains. If given,
initialize only that table's chain list in cache and pass the table
along to nftnl_chain_list_cb() which will filter received chains by
table name.

Signed-off-by: Phil Sutter <p...@nwl.cc>
---
 iptables/nft.c | 55 +++++++++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 729b88d990f9f..6ed05e77008c4 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1352,11 +1352,18 @@ nft_rule_print_save(const struct nftnl_rule *r, enum 
nft_rule_print type,
                ops->clear_cs(&cs);
 }
 
+struct nftnl_chain_list_cb_data {
+       struct nft_handle *h;
+       const struct builtin_table *t;
+};
+
 static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data)
 {
-       struct nft_handle *h = data;
-       const struct builtin_table *t;
+       struct nftnl_chain_list_cb_data *d = data;
+       const struct builtin_table *t = d->t;
+       struct nft_handle *h = d->h;
        struct nftnl_chain *c;
+       const char *tname;
 
        c = nftnl_chain_alloc();
        if (c == NULL)
@@ -1365,8 +1372,13 @@ static int nftnl_chain_list_cb(const struct nlmsghdr 
*nlh, void *data)
        if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
                goto out;
 
-       t = nft_table_builtin_find(h,
-                       nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE));
+       tname = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
+
+       if (!t)
+               t = nft_table_builtin_find(h, tname);
+       else if (strcmp(t->name, tname))
+               goto out;
+
        if (!t)
                goto out;
 
@@ -1423,29 +1435,40 @@ static int fetch_table_cache(struct nft_handle *h)
        return 1;
 }
 
-static int fetch_chain_cache(struct nft_handle *h)
+static int fetch_chain_cache(struct nft_handle *h,
+                            const struct builtin_table *t)
 {
+       struct nftnl_chain_list_cb_data d = {
+               .h = h,
+               .t = t,
+       };
        char buf[16536];
        struct nlmsghdr *nlh;
        int i, ret;
 
-       fetch_table_cache(h);
+       if (!t) {
+               fetch_table_cache(h);
 
-       for (i = 0; i < NFT_TABLE_MAX; i++) {
-               enum nft_table_type type = h->tables[i].type;
+               for (i = 0; i < NFT_TABLE_MAX; i++) {
+                       enum nft_table_type type = h->tables[i].type;
 
-               if (!h->tables[i].name)
-                       continue;
+                       if (!h->tables[i].name)
+                               continue;
 
-               h->cache->table[type].chains = nftnl_chain_list_alloc();
-               if (!h->cache->table[type].chains)
-                       return -1;
+                       h->cache->table[type].chains = nftnl_chain_list_alloc();
+                       if (!h->cache->table[type].chains)
+                               return -1;
+               }
+       } else if (!h->cache->table[t->type].chains) {
+               h->cache->table[t->type].chains = nftnl_chain_list_alloc();
+       } else {
+               return 0;
        }
 
        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);
+       ret = mnl_talk(h, nlh, nftnl_chain_list_cb, &d);
        if (ret < 0 && errno == EINTR)
                assert(nft_restart(h) >= 0);
 
@@ -1616,7 +1639,7 @@ static void __nft_build_cache(struct nft_handle *h)
 
 retry:
        mnl_genid_get(h, &genid_start);
-       fetch_chain_cache(h);
+       fetch_chain_cache(h, NULL);
        fetch_rule_cache(h, NULL);
        h->have_cache = true;
        mnl_genid_get(h, &genid_stop);
@@ -1686,7 +1709,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct 
nft_handle *h,
                return NULL;
 
        if (!h->have_cache && !h->cache->table[t->type].chains)
-               fetch_chain_cache(h);
+               fetch_chain_cache(h, t);
 
        return h->cache->table[t->type].chains;
 }
-- 
2.23.0

Reply via email to