The amount of code dealing with caching only is considerable and hence deserves an own source file. Signed-off-by: Phil Sutter <phil@xxxxxx> --- iptables/Makefile.am | 2 +- iptables/nft-cache.c | 376 +++++++++++++++++++++++++++++++++++++ iptables/nft-cache.h | 17 ++ iptables/nft.c | 360 +---------------------------------- iptables/nft.h | 8 +- iptables/xtables-restore.c | 1 + iptables/xtables-save.c | 1 + 7 files changed, 404 insertions(+), 361 deletions(-) create mode 100644 iptables/nft-cache.c create mode 100644 iptables/nft-cache.h diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 21ac7f08b7c1f..fc834e0f7b89e 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -36,7 +36,7 @@ xtables_nft_multi_CFLAGS += -DENABLE_NFTABLES -DENABLE_IPV4 -DENABLE_IPV6 xtables_nft_multi_SOURCES += xtables-save.c xtables-restore.c \ xtables-standalone.c xtables.c nft.c \ nft-shared.c nft-ipv4.c nft-ipv6.c nft-arp.c \ - xtables-monitor.c \ + xtables-monitor.c nft-cache.c \ xtables-arp-standalone.c xtables-arp.c \ nft-bridge.c \ xtables-eb-standalone.c xtables-eb.c \ diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c new file mode 100644 index 0000000000000..5444419a5cc3b --- /dev/null +++ b/iptables/nft-cache.c @@ -0,0 +1,376 @@ +/* + * (C) 2012 by Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This code has been sponsored by Sophos Astaro <http://www.sophos.com> + */ + +#include <assert.h> +#include <errno.h> +#include <xtables.h> + +#include <linux/netfilter/nf_tables.h> + +#include <libmnl/libmnl.h> +#include <libnftnl/gen.h> +#include <libnftnl/table.h> + +#include "nft.h" +#include "nft-cache.h" + +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)); +} + +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 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 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 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_build_cache(struct nft_handle *h) +{ + if (!h->have_cache) + __nft_build_cache(h); +} + +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); +} + +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 int __flush_rule_cache(struct nftnl_rule *r, void *data) +{ + nftnl_rule_list_del(r); + nftnl_rule_free(r); + + return 0; +} + +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; +} + +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_rebuild_cache(struct nft_handle *h) +{ + if (h->have_cache) + __nft_flush_cache(h); + + __nft_build_cache(h); +} + +void nft_release_cache(struct nft_handle *h) +{ + if (h->cache_index) + flush_cache(h, &h->__cache[0], NULL); +} + +struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h) +{ + if (!h->cache->tables) + fetch_table_cache(h); + + return h->cache->tables; +} + +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; +} + diff --git a/iptables/nft-cache.h b/iptables/nft-cache.h new file mode 100644 index 0000000000000..423c6516de9bb --- /dev/null +++ b/iptables/nft-cache.h @@ -0,0 +1,17 @@ +#ifndef _NFT_CACHE_H_ +#define _NFT_CACHE_H_ + +struct nft_handle; + +void nft_fake_cache(struct nft_handle *h); +void nft_build_cache(struct nft_handle *h); +void nft_rebuild_cache(struct nft_handle *h); +void nft_release_cache(struct nft_handle *h); +void flush_chain_cache(struct nft_handle *h, const char *tablename); +void flush_rule_cache(struct nftnl_chain *c); + +struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + const char *table); +struct nftnl_table_list *nftnl_table_list_get(struct nft_handle *h); + +#endif /* _NFT_CACHE_H_ */ diff --git a/iptables/nft.c b/iptables/nft.c index 3228842cd3c8b..81de10d8a0892 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; diff --git a/iptables/nft.h b/iptables/nft.h index bcac8e228c787..451c266016d8d 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -73,8 +73,7 @@ int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, void *data); int nft_init(struct nft_handle *h, const struct builtin_table *t); void nft_fini(struct nft_handle *h); -void nft_fake_cache(struct nft_handle *h); -void nft_build_cache(struct nft_handle *h); +int nft_restart(struct nft_handle *h); /* * Operations with tables. @@ -95,8 +94,6 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c struct nftnl_chain; int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); -struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, - const char *table); int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); @@ -105,6 +102,9 @@ int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *t int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose); const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain); bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain); +void nft_bridge_chain_postprocess(struct nft_handle *h, + struct nftnl_chain *c); + /* * Operations with rule-set. diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index 7f28a05c68619..7641955d1ce53 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -18,6 +18,7 @@ #include "xtables-multi.h" #include "nft.h" #include "nft-bridge.h" +#include "nft-cache.h" #include <libnftnl/chain.h> static int counters, verbose; diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c index 77b13f7ffbcdd..3741888f9af44 100644 --- a/iptables/xtables-save.c +++ b/iptables/xtables-save.c @@ -21,6 +21,7 @@ #include "iptables.h" #include "xtables-multi.h" #include "nft.h" +#include "nft-cache.h" #include <libnftnl/chain.h> -- 2.23.0