From d812b91bc6e010dcdd4ed039c3979a02fb57eb1c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 1 Oct 2019 15:09:55 +0200 Subject: nft: Extract cache routines into nft-cache.c The amount of code dealing with caching only is considerable and hence deserves an own source file. Signed-off-by: Phil Sutter Acked-by: Pablo Neira Ayuso --- iptables/nft.c | 360 +-------------------------------------------------------- 1 file changed, 4 insertions(+), 356 deletions(-) (limited to 'iptables/nft.c') diff --git a/iptables/nft.c b/iptables/nft.c index 3228842c..81de10d8 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -55,47 +55,12 @@ #include "nft.h" #include "xshared.h" /* proto_to_name */ +#include "nft-cache.h" #include "nft-shared.h" #include "nft-bridge.h" /* EBT_NOPROTO */ static void *nft_fn; -static int genid_cb(const struct nlmsghdr *nlh, void *data) -{ - uint32_t *genid = data; - struct nftnl_gen *gen; - - gen = nftnl_gen_alloc(); - if (!gen) - return MNL_CB_ERROR; - - if (nftnl_gen_nlmsg_parse(nlh, gen) < 0) - goto out; - - *genid = nftnl_gen_get_u32(gen, NFTNL_GEN_ID); - - nftnl_gen_free(gen); - return MNL_CB_STOP; -out: - nftnl_gen_free(gen); - return MNL_CB_ERROR; -} - -static void mnl_genid_get(struct nft_handle *h, uint32_t *genid) -{ - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - int ret; - - nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETGEN, 0, 0, h->seq); - ret = mnl_talk(h, nlh, genid_cb, genid); - if (ret == 0) - return; - - xtables_error(RESOURCE_PROBLEM, - "Could not fetch rule set generation id: %s\n", nft_strerror(errno)); -} - int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, int (*cb)(const struct nlmsghdr *nlh, void *data), void *data) @@ -791,7 +756,7 @@ static bool nft_chain_builtin(struct nftnl_chain *c) return nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM) != NULL; } -static int nft_restart(struct nft_handle *h) +int nft_restart(struct nft_handle *h) { mnl_socket_close(h->nl); @@ -830,67 +795,6 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t) return 0; } -static int __flush_rule_cache(struct nftnl_rule *r, void *data) -{ - nftnl_rule_list_del(r); - nftnl_rule_free(r); - - return 0; -} - -static void flush_rule_cache(struct nftnl_chain *c) -{ - nftnl_rule_foreach(c, __flush_rule_cache, NULL); -} - -static int __flush_chain_cache(struct nftnl_chain *c, void *data) -{ - nftnl_chain_list_del(c); - nftnl_chain_free(c); - - return 0; -} - -static int flush_cache(struct nft_handle *h, struct nft_cache *c, - const char *tablename) -{ - const struct builtin_table *table; - int i; - - if (tablename) { - table = nft_table_builtin_find(h, tablename); - if (!table || !c->table[table->type].chains) - return 0; - nftnl_chain_list_foreach(c->table[table->type].chains, - __flush_chain_cache, NULL); - return 0; - } - - for (i = 0; i < NFT_TABLE_MAX; i++) { - if (h->tables[i].name == NULL) - continue; - - if (!c->table[i].chains) - continue; - - nftnl_chain_list_free(c->table[i].chains); - c->table[i].chains = NULL; - } - nftnl_table_list_free(c->tables); - c->tables = NULL; - - return 1; -} - -static void flush_chain_cache(struct nft_handle *h, const char *tablename) -{ - if (!h->have_cache) - return; - - if (flush_cache(h, h->cache, tablename)) - h->have_cache = false; -} - void nft_fini(struct nft_handle *h) { flush_chain_cache(h, NULL); @@ -1337,104 +1241,6 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, ops->clear_cs(&cs); } -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 *c; - - c = nftnl_chain_alloc(); - if (c == NULL) - goto err; - - if (nftnl_chain_nlmsg_parse(nlh, c) < 0) - goto out; - - t = nft_table_builtin_find(h, - nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE)); - if (!t) - goto out; - - nftnl_chain_list_add_tail(c, h->cache->table[t->type].chains); - - return MNL_CB_OK; -out: - nftnl_chain_free(c); -err: - return MNL_CB_OK; -} - -static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nftnl_table *t; - struct nftnl_table_list *list = data; - - t = nftnl_table_alloc(); - if (t == NULL) - goto err; - - if (nftnl_table_nlmsg_parse(nlh, t) < 0) - goto out; - - nftnl_table_list_add_tail(t, list); - - return MNL_CB_OK; -out: - nftnl_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; - int ret; - - list = nftnl_table_list_alloc(); - if (list == NULL) - 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); - if (ret < 0 && errno == EINTR) - assert(nft_restart(h) >= 0); - - h->cache->tables = list; - - return 1; -} - -static int fetch_chain_cache(struct nft_handle *h) -{ - char buf[16536]; - struct nlmsghdr *nlh; - int i, ret; - - for (i = 0; i < NFT_TABLE_MAX; i++) { - enum nft_table_type type = h->tables[i].type; - - if (!h->tables[i].name) - continue; - - h->cache->table[type].chains = nftnl_chain_list_alloc(); - if (!h->cache->table[type].chains) - return -1; - } - - 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); - - return ret; -} - static bool nft_rule_is_policy_rule(struct nftnl_rule *r) { const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {}; @@ -1473,8 +1279,8 @@ static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c) return last; } -static void nft_bridge_chain_postprocess(struct nft_handle *h, - struct nftnl_chain *c) +void nft_bridge_chain_postprocess(struct nft_handle *h, + struct nftnl_chain *c) { struct nftnl_rule *last = nft_chain_last_rule(c); struct nftnl_expr_iter *iter; @@ -1515,156 +1321,6 @@ static void nft_bridge_chain_postprocess(struct nft_handle *h, out_iter: nftnl_expr_iter_destroy(iter); } - -static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nftnl_chain *c = data; - struct nftnl_rule *r; - - r = nftnl_rule_alloc(); - if (r == NULL) - return MNL_CB_OK; - - if (nftnl_rule_nlmsg_parse(nlh, r) < 0) { - nftnl_rule_free(r); - return MNL_CB_OK; - } - - nftnl_chain_rule_add_tail(r, c); - return MNL_CB_OK; -} - -static int nft_rule_list_update(struct nftnl_chain *c, void *data) -{ - struct nft_handle *h = data; - char buf[16536]; - struct nlmsghdr *nlh; - struct nftnl_rule *rule; - int ret; - - rule = nftnl_rule_alloc(); - if (!rule) - return -1; - - nftnl_rule_set_str(rule, NFTNL_RULE_TABLE, - nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE)); - nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN, - nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); - - nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family, - NLM_F_DUMP, h->seq); - nftnl_rule_nlmsg_build_payload(nlh, rule); - - ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c); - if (ret < 0 && errno == EINTR) - assert(nft_restart(h) >= 0); - - nftnl_rule_free(rule); - - if (h->family == NFPROTO_BRIDGE) - nft_bridge_chain_postprocess(h, c); - - return 0; -} - -static int fetch_rule_cache(struct nft_handle *h) -{ - int i; - - for (i = 0; i < NFT_TABLE_MAX; i++) { - enum nft_table_type type = h->tables[i].type; - - if (!h->tables[i].name) - continue; - - if (nftnl_chain_list_foreach(h->cache->table[type].chains, - nft_rule_list_update, h)) - return -1; - } - return 0; -} - -static void __nft_build_cache(struct nft_handle *h) -{ - uint32_t genid_start, genid_stop; - -retry: - mnl_genid_get(h, &genid_start); - fetch_table_cache(h); - fetch_chain_cache(h); - fetch_rule_cache(h); - h->have_cache = true; - mnl_genid_get(h, &genid_stop); - - if (genid_start != genid_stop) { - flush_chain_cache(h, NULL); - goto retry; - } - - h->nft_genid = genid_start; -} - -void nft_fake_cache(struct nft_handle *h) -{ - int i; - - fetch_table_cache(h); - for (i = 0; i < NFT_TABLE_MAX; i++) { - enum nft_table_type type = h->tables[i].type; - - if (!h->tables[i].name) - continue; - - h->cache->table[type].chains = nftnl_chain_list_alloc(); - } - h->have_cache = true; - mnl_genid_get(h, &h->nft_genid); -} - -void nft_build_cache(struct nft_handle *h) -{ - if (!h->have_cache) - __nft_build_cache(h); -} - -static void __nft_flush_cache(struct nft_handle *h) -{ - if (!h->cache_index) { - h->cache_index++; - h->cache = &h->__cache[h->cache_index]; - } else { - flush_chain_cache(h, NULL); - } -} - -static void nft_rebuild_cache(struct nft_handle *h) -{ - if (h->have_cache) - __nft_flush_cache(h); - - __nft_build_cache(h); -} - -static void nft_release_cache(struct nft_handle *h) -{ - if (h->cache_index) - flush_cache(h, &h->__cache[0], NULL); -} - -struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, - const char *table) -{ - const struct builtin_table *t; - - t = nft_table_builtin_find(h, table); - if (!t) - return NULL; - - nft_build_cache(h); - - return h->cache->table[t->type].chains; -} - static const char *policy_name[NF_ACCEPT+1] = { [NF_DROP] = "DROP", [NF_ACCEPT] = "ACCEPT", @@ -2054,14 +1710,6 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain, return ret == 0 ? 1 : 0; } -static struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) -{ - if (!h->cache->tables) - fetch_table_cache(h); - - return h->cache->tables; -} - bool nft_table_find(struct nft_handle *h, const char *tablename) { struct nftnl_table_list_iter *iter; -- cgit v1.2.3