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 calling 'chain_user_add' callback only if 'noflush' is not
set.
Fixes: df3d92bec6007 ("xtables-compat-restore: flush user-defined chains with
-n")
Signed-off-by: Phil Sutter <[email protected]>
---
iptables/nft.c | 10 ++--------
iptables/xtables-restore.c | 3 ++-
2 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7123060b34ef5..77ad38bea5211 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 3274543677329..5e22e74bb190f 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -246,7 +246,8 @@ void xtables_restore_parse(struct nft_handle *h,
ret = 1;
} else {
- if (cb->chain_user_add &&
+ if (noflush == 0 &&
+ cb->chain_user_add &&
cb->chain_user_add(h, chain,
curtable->name) < 0) {
if (errno == EEXIST)
--
2.18.0