]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
iptables: replace libnftnl table list by linux list
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 23 Jul 2020 12:15:53 +0000 (14:15 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 27 Jul 2020 14:01:58 +0000 (16:01 +0200)
This patch removes the libnftnl table list by linux list. This comes
with an extra memory allocation to store the nft_table object. Probably,
there is no need to cache the entire nftnl_table in the near future.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
iptables/nft-cache.c
iptables/nft-cache.h
iptables/nft.c
iptables/nft.h

index 059f0a7f7891e850518ac939123ea54ad8167d9a..bf1fb346f28fdc2303c0258938d09a6f28dbee5a 100644 (file)
@@ -107,50 +107,78 @@ static void mnl_genid_get(struct nft_handle *h, uint32_t *genid)
                      "Could not fetch rule set generation id: %s\n", nft_strerror(errno));
 }
 
+static struct nft_table *nft_table_alloc(void)
+{
+       struct nftnl_table *nftnl;
+       struct nft_table *table;
+
+       table = malloc(sizeof(struct nft_table));
+       if (!table)
+               return NULL;
+
+       nftnl = nftnl_table_alloc();
+       if (!nftnl) {
+               free(table);
+               return NULL;
+       }
+       table->nftnl = nftnl;
+
+       return table;
+}
+
+static void nft_table_free(struct nft_table *table)
+{
+       nftnl_table_free(table->nftnl);
+       free(table);
+}
+
+static void nft_table_list_free(struct list_head *table_list)
+{
+       struct nft_table *table, *next;
+
+       list_for_each_entry_safe(table, next, table_list, list) {
+               list_del(&table->list);
+               nft_table_free(table);
+       }
+}
+
 static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
 {
-       struct nftnl_table *t;
-       struct nftnl_table_list *list = data;
+       struct list_head *list = data;
+       struct nft_table *t;
 
-       t = nftnl_table_alloc();
-       if (t == NULL)
+       t = nft_table_alloc();
+       if (!t)
                goto err;
 
-       if (nftnl_table_nlmsg_parse(nlh, t) < 0)
+       if (nftnl_table_nlmsg_parse(nlh, t->nftnl) < 0)
                goto out;
 
-       nftnl_table_list_add_tail(t, list);
+       list_add_tail(&t->list, list);
 
        return MNL_CB_OK;
 out:
-       nftnl_table_free(t);
+       nft_table_free(t);
 err:
        return MNL_CB_OK;
 }
 
 static int fetch_table_cache(struct nft_handle *h)
 {
-       char buf[16536];
        struct nlmsghdr *nlh;
-       struct nftnl_table_list *list;
+       char buf[16536];
        int i, ret;
 
-       if (h->cache->tables)
-               return 0;
-
-       list = nftnl_table_list_alloc();
-       if (list == NULL)
+       if (!list_empty(&h->cache->tables))
                return 0;
 
        nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
                                        NLM_F_DUMP, h->seq);
 
-       ret = mnl_talk(h, nlh, nftnl_table_list_cb, list);
+       ret = mnl_talk(h, nlh, nftnl_table_list_cb, &h->cache->tables);
        if (ret < 0 && errno == EINTR)
                assert(nft_restart(h) >= 0);
 
-       h->cache->tables = list;
-
        for (i = 0; i < NFT_TABLE_MAX; i++) {
                enum nft_table_type type = h->tables[i].type;
 
@@ -608,10 +636,8 @@ static int flush_cache(struct nft_handle *h, struct nft_cache *c,
                        c->table[i].sets = NULL;
                }
        }
-       if (c->tables) {
-               nftnl_table_list_free(c->tables);
-               c->tables = NULL;
-       }
+       if (!list_empty(&c->tables))
+               nft_table_list_free(&c->tables);
 
        return 1;
 }
@@ -684,9 +710,9 @@ void nft_release_cache(struct nft_handle *h)
        }
 }
 
-struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h)
+struct list_head *nft_table_list_get(struct nft_handle *h)
 {
-       return h->cache->tables;
+       return &h->cache->tables;
 }
 
 struct nftnl_set_list *
index f429118041be42d06556f0a04942576e3b1c39de..aeab4bdef904dc72aa508a4ff98fd8404aa706d0 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _NFT_CACHE_H_
 #define _NFT_CACHE_H_
 
+#include <libiptc/linux_list.h>
+
 struct nft_handle;
 struct nft_cmd;
 
@@ -17,6 +19,12 @@ struct nftnl_chain_list *
 nft_chain_list_get(struct nft_handle *h, const char *table, const char *chain);
 struct nftnl_set_list *
 nft_set_list_get(struct nft_handle *h, const char *table, const char *set);
-struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h);
+struct list_head *nft_table_list_get(struct nft_handle *h);
+
+struct nft_table {
+       struct list_head        list;
+       struct nftnl_table      *nftnl;
+};
+
 
 #endif /* _NFT_CACHE_H_ */
index cc1260dc627d03444baca36ad442d81a66a63c09..634d02fed25b1925f3fc20a8aff4d3f08e319950 100644 (file)
@@ -842,6 +842,8 @@ int nft_init(struct nft_handle *h, int family, const struct builtin_table *t)
        INIT_LIST_HEAD(&h->obj_list);
        INIT_LIST_HEAD(&h->err_list);
        INIT_LIST_HEAD(&h->cmd_list);
+       INIT_LIST_HEAD(&h->__cache[0].tables);
+       INIT_LIST_HEAD(&h->__cache[1].tables);
        INIT_LIST_HEAD(&h->cache_req.chain_list);
 
        return 0;
@@ -1941,35 +1943,22 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
 
 bool nft_table_find(struct nft_handle *h, const char *tablename)
 {
-       struct nftnl_table_list_iter *iter;
-       struct nftnl_table_list *list;
-       struct nftnl_table *t;
+       struct list_head *list;
+       struct nft_table *t;
        bool ret = false;
 
-       list = nftnl_table_list_get(h);
-       if (list == NULL)
-               goto err;
-
-       iter = nftnl_table_list_iter_create(list);
-       if (iter == NULL)
-               goto err;
+       list = nft_table_list_get(h);
 
-       t = nftnl_table_list_iter_next(iter);
-       while (t != NULL) {
+       list_for_each_entry(t, list, list) {
                const char *this_tablename =
-                       nftnl_table_get(t, NFTNL_TABLE_NAME);
+                       nftnl_table_get(t->nftnl, NFTNL_TABLE_NAME);
 
                if (strcmp(tablename, this_tablename) == 0) {
                        ret = true;
                        break;
                }
-
-               t = nftnl_table_list_iter_next(iter);
        }
 
-       nftnl_table_list_iter_destroy(iter);
-
-err:
        return ret;
 }
 
@@ -1977,29 +1966,18 @@ int nft_for_each_table(struct nft_handle *h,
                       int (*func)(struct nft_handle *h, const char *tablename, void *data),
                       void *data)
 {
-       struct nftnl_table_list *list;
-       struct nftnl_table_list_iter *iter;
-       struct nftnl_table *t;
-
-       list = nftnl_table_list_get(h);
-       if (list == NULL)
-               return -1;
+       struct list_head *list;
+       struct nft_table *t;
 
-       iter = nftnl_table_list_iter_create(list);
-       if (iter == NULL)
-               return -1;
+       list = nft_table_list_get(h);
 
-       t = nftnl_table_list_iter_next(iter);
-       while (t != NULL) {
+       list_for_each_entry(t, list, list) {
                const char *tablename =
-                       nftnl_table_get(t, NFTNL_TABLE_NAME);
+                       nftnl_table_get(t->nftnl, NFTNL_TABLE_NAME);
 
                func(h, tablename, data);
-
-               t = nftnl_table_list_iter_next(iter);
        }
 
-       nftnl_table_list_iter_destroy(iter);
        return 0;
 }
 
@@ -2035,43 +2013,27 @@ static int __nft_table_flush(struct nft_handle *h, const char *table, bool exist
 
 int nft_table_flush(struct nft_handle *h, const char *table)
 {
-       struct nftnl_table_list_iter *iter;
-       struct nftnl_table_list *list;
-       struct nftnl_table *t;
+       struct list_head *list;
+       struct nft_table *t;
        bool exists = false;
        int ret = 0;
 
        nft_fn = nft_table_flush;
 
-       list = nftnl_table_list_get(h);
-       if (list == NULL) {
-               ret = -1;
-               goto err_out;
-       }
-
-       iter = nftnl_table_list_iter_create(list);
-       if (iter == NULL) {
-               ret = -1;
-               goto err_table_list;
-       }
+       list = nft_table_list_get(h);
 
-       t = nftnl_table_list_iter_next(iter);
-       while (t != NULL) {
+       list_for_each_entry(t, list, list) {
                const char *table_name =
-                       nftnl_table_get_str(t, NFTNL_TABLE_NAME);
+                       nftnl_table_get_str(t->nftnl, NFTNL_TABLE_NAME);
 
                if (strcmp(table_name, table) == 0) {
                        exists = true;
                        break;
                }
-
-               t = nftnl_table_list_iter_next(iter);
        }
 
        ret = __nft_table_flush(h, table, exists);
-       nftnl_table_list_iter_destroy(iter);
-err_table_list:
-err_out:
+
        /* the core expects 1 for success and 0 for error */
        return ret == 0 ? 1 : 0;
 }
index 247255ac9e3c5340a590cf978cae8bb4462a0697..b2175958bfcd69357c56ce0754e93dc0cd82a364 100644 (file)
@@ -38,7 +38,7 @@ enum nft_cache_level {
 };
 
 struct nft_cache {
-       struct nftnl_table_list         *tables;
+       struct list_head                tables;
        struct {
                struct nftnl_chain_list *chains;
                struct nftnl_set_list   *sets;