[PATCH xtables-compat,v3 2/3] xtables-compat-restore: flush user-defined chains with -n

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-n still flushes user-defined chains and its content, the following snippet:

 iptables-compat -N FOO
 iptables-compat -I INPUT
 iptables-compat -I FOO
 iptables-compat -I FOO
 iptables-compat-save > A
 iptables-compat-restore < A
 iptables-compat -N BAR
 iptables-compat -A BAR
 iptables-compat-restore -n < A

results in:

 iptables-compat-save
 # Generated by xtables-save v1.6.2 on Mon May  7 17:18:44 2018
 *filter
 :INPUT ACCEPT [0:0]
 :FORWARD ACCEPT [0:0]
 :OUTPUT ACCEPT [0:0]
 :BAR - [0:0]
 :FOO - [0:0]
 -A INPUT
 -A INPUT
 -A BAR
 -A FOO
 -A FOO
 COMMIT
 # Completed on Mon May  7 17:18:44 2018

Still, user-defined chains that are not re-defined, such as BAR, are
left in place.

Reported-by: Florian Westphal <fw@xxxxxxxxx>
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 iptables/nft-shared.h      |  3 +++
 iptables/nft.c             | 55 ++++++++++++++++++++++++++++++++++++++++++++++
 iptables/nft.h             |  2 ++
 iptables/xtables-restore.c | 16 ++++++++++++--
 4 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 56b270e5a4b7..34027af931ec 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -248,6 +248,9 @@ struct nft_xt_restore_cb {
 	struct nftnl_chain_list *(*chain_list)(struct nft_handle *h);
 	void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable,
 			  const char *chain);
+	int (*chain_user_flush)(struct nft_handle *h,
+				struct nftnl_chain_list *clist,
+				const char *table, const char *chain);
 	int (*chain_set)(struct nft_handle *h, const char *table,
 			 const char *chain, const char *policy,
 			 const struct xt_counters *counters);
diff --git a/iptables/nft.c b/iptables/nft.c
index 543e44d792b1..093ebfffe0ef 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -255,6 +255,7 @@ enum obj_update_type {
 	NFT_COMPAT_CHAIN_ADD,
 	NFT_COMPAT_CHAIN_USER_ADD,
 	NFT_COMPAT_CHAIN_USER_DEL,
+	NFT_COMPAT_CHAIN_USER_FLUSH,
 	NFT_COMPAT_CHAIN_UPDATE,
 	NFT_COMPAT_CHAIN_RENAME,
 	NFT_COMPAT_RULE_APPEND,
@@ -1361,6 +1362,55 @@ err:
 	return ret == 0 ? 1 : 0;
 }
 
+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;
+	int ret;
+
+	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)) {
+		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_FLUSH, c);
+		if (ret < 0)
+			return ret;
+
+		nftnl_chain_list_del(c);
+	}
+
+	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_del;
+
+	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)
 {
 	int ret;
@@ -2275,6 +2325,11 @@ static int nft_action(struct nft_handle *h, int action)
 						   NLM_F_NONREC, seq++,
 						   n->chain);
 			break;
+		case NFT_COMPAT_CHAIN_USER_FLUSH:
+			nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
+						   0, seq++,
+						   n->chain);
+			break;
 		case NFT_COMPAT_CHAIN_UPDATE:
 			nft_compat_chain_batch_add(h, NFT_MSG_NEWCHAIN,
 						   h->restore ?
diff --git a/iptables/nft.h b/iptables/nft.h
index 2d5c37e5b502..0c4beb998de8 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -71,6 +71,8 @@ struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const cha
 int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table);
 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);
+int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
+			 const char *chain, const char *table);
 int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname);
 int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table);
 
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 6e7652ff7668..ac753c43bc91 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -196,6 +196,7 @@ struct nft_xt_restore_cb restore_cb = {
 	.commit		= nft_commit,
 	.abort		= nft_abort,
 	.table_flush	= nft_table_flush,
+	.chain_user_flush = nft_chain_user_flush,
 	.chain_del	= chain_delete,
 	.do_command	= do_commandx,
 	.chain_set	= nft_chain_set,
@@ -294,8 +295,19 @@ void xtables_restore_parse(struct nft_handle *h,
 				exit(1);
 			}
 
-			if (cb->chain_del)
-				cb->chain_del(chain_list, curtable, chain);
+			if (noflush == 0) {
+				if (cb->chain_del)
+					cb->chain_del(chain_list, curtable,
+						      chain);
+			} else {
+				/* Apparently -n still flushes existing user
+				 * defined chains that are redefined. Otherwise,
+				 * leave them as is.
+				 */
+				if (cb->chain_user_flush)
+					cb->chain_user_flush(h, chain_list,
+							     curtable, chain);
+			}
 
 			if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
 				xtables_error(PARAMETER_PROBLEM,
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux