summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-09-06 19:33:20 +0200
committerFlorian Westphal <fw@strlen.de>2018-09-10 15:20:13 +0200
commit7345037e08a385e078350de1006f5ee2299cd2ef (patch)
treeda8d4db8777caf9d610aa10190c32478e0407e9e
parent7df11d1699ceaf4a841a46a42f446aec5593efd3 (diff)
xtables-restore: Fix flushing referenced custom chains
The logic to replicate 'iptables-restore --noflush' behaviour of flushing custom chains if listed in the dump was broken for chains being referenced. A minimal dump reproducing the issue is: | *filter | :foobar - [0:0] | -I INPUT -j foobar | -A foobar -j ACCEPT | COMMIT With --noflush, this can be restored just once in iptables-nft-restore. Consecutive attempts return an error since xtables tries to delete the referenced chain and recreate it instead of performing a real flush. Fix this by really flushing the custom chain in 'chain_user_flush' callback and running 'chain_user_add' callback only if the chain doesn't exist already. Fixes: df3d92bec6007 ("xtables-compat-restore: flush user-defined chains with -n") Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r--iptables/nft.c10
-rw-r--r--iptables/xtables-restore.c8
2 files changed, 8 insertions, 10 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index 7123060b..77ad38be 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1491,7 +1491,6 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
struct nft_handle *h = d->handle;
const char *table = d->table;
const char *chain = d->chain;
- int ret;
if (strcmp(table, table_name) != 0)
return 0;
@@ -1499,13 +1498,8 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *data)
if (strcmp(chain, chain_name) != 0)
return 0;
- if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_FLUSH, c);
- if (ret < 0)
- return ret;
-
- nftnl_chain_list_del(c);
- }
+ if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM))
+ __nft_rule_flush(h, table, chain);
return 0;
}
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index d2b79208..d187b129 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -182,6 +182,7 @@ void xtables_restore_parse(struct nft_handle *h,
/* New chain. */
char *policy, *chain = NULL;
struct xt_counters count = {};
+ bool chain_exists = false;
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
@@ -196,7 +197,9 @@ void xtables_restore_parse(struct nft_handle *h,
if (cb->chain_del)
cb->chain_del(chain_list, curtable->name,
chain);
- } else {
+ } else if (nft_chain_list_find(chain_list,
+ curtable->name, chain)) {
+ chain_exists = true;
/* Apparently -n still flushes existing user
* defined chains that are redefined. Otherwise,
* leave them as is.
@@ -246,7 +249,8 @@ void xtables_restore_parse(struct nft_handle *h,
ret = 1;
} else {
- if (cb->chain_user_add &&
+ if (!chain_exists &&
+ cb->chain_user_add &&
cb->chain_user_add(h, chain,
curtable->name) < 0) {
if (errno == EEXIST)