summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-04-23 15:16:20 +0200
committerFlorian Westphal <fw@strlen.de>2019-04-27 01:08:08 +0200
commit0baa08fed43fa318eaa6ffe02673289343ac9cc0 (patch)
tree3060ebde032b213641fe62211ae9bf4f02d91785 /iptables/nft.c
parent31dd3780a64935e3bcf83efb1a4354eed41f59ee (diff)
xtables: unify user chain add/flush for restore case
The idea here is to move the 'flush' decision into the core, rather than have the decision in the frontend. This will be required later when "generation id" is passed to kernel. In this case, we might have to add the flush when re-trying the transaction. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'iptables/nft.c')
-rw-r--r--iptables/nft.c82
1 files changed, 39 insertions, 43 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index a297d985..16d7b795 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1621,49 +1621,6 @@ __nft_rule_flush(struct nft_handle *h, const char *table,
nftnl_rule_free(r);
}
-struct chain_user_flush_data {
- struct nft_handle *handle;
- const char *table;
- const char *chain;
-};
-
-static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
-{
- const char *table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
- const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
- struct chain_user_flush_data *d = data;
- struct nft_handle *h = d->handle;
- const char *table = d->table;
- const char *chain = d->chain;
-
- if (strcmp(table, table_name) != 0)
- return 0;
-
- if (strcmp(chain, chain_name) != 0)
- return 0;
-
- if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
- __nft_rule_flush(h, table, chain, false);
-
- return 0;
-}
-
-int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
- const char *table, const char *chain)
-{
- struct chain_user_flush_data d = {
- .handle = h,
- .table = table,
- .chain = chain,
- };
-
- nft_fn = nft_chain_user_flush;
-
- nftnl_chain_list_foreach(list, __nft_chain_user_flush, &d);
-
- return 1;
-}
-
int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table,
bool verbose)
{
@@ -1750,6 +1707,45 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
return ret == 0 ? 1 : 0;
}
+int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table)
+{
+ struct nftnl_chain_list *list;
+ struct nftnl_chain *c;
+ bool created = false;
+ int ret;
+
+ c = nft_chain_find(h, table, chain);
+ if (c) {
+ /* Apparently -n still flushes existing user defined
+ * chains that are redefined.
+ */
+ if (h->noflush)
+ __nft_rule_flush(h, table, chain, false);
+ } else {
+ c = nftnl_chain_alloc();
+ if (!c)
+ return -1;
+
+ nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table);
+ nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain);
+ created = true;
+ }
+
+ if (h->family == NFPROTO_BRIDGE)
+ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT);
+
+ if (!created)
+ return 0;
+
+ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c);
+
+ list = nft_chain_list_get(h, table);
+ if (list)
+ nftnl_chain_list_add(c, list);
+
+ return ret;
+}
+
/* From linux/netlink.h */
#ifndef NLM_F_NONREC
#define NLM_F_NONREC 0x100 /* Do not delete recursively */