From 7345037e08a385e078350de1006f5ee2299cd2ef Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 6 Sep 2018 19:33:20 +0200 Subject: 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 Signed-off-by: Florian Westphal --- iptables/xtables-restore.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'iptables/xtables-restore.c') 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) -- cgit v1.2.3