summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/nft.c')
-rw-r--r--iptables/nft.c360
1 files changed, 4 insertions, 356 deletions
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;