Blob Blame History Raw
From c9db6c26efce63e052b1a35ba1f4d529c2294c93 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:17 +0100
Subject: [PATCH] xtables: Optimize user-defined chain deletion

Make use of nftnl_chain_list_lookup_byname() if a chain name was given.
Move the actual chain deleting code into a callback suitable for passing
to nftnl_chain_list_foreach().

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit 0b950ed4549308ef23ffc7561567df86c90cfed9)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
 iptables/nft.c | 89 ++++++++++++++++++++++++++------------------------
 1 file changed, 46 insertions(+), 43 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 9951bf3212197..162d91e82115b 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1642,63 +1642,66 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
 #define NLM_F_NONREC	0x100	/* Do not delete recursively    */
 #endif
 
+struct chain_user_del_data {
+	struct nft_handle	*handle;
+	bool			verbose;
+	int			builtin_err;
+};
+
+static int __nft_chain_user_del(struct nftnl_chain *c, void *data)
+{
+	struct chain_user_del_data *d = data;
+	struct nft_handle *h = d->handle;
+	int ret;
+
+	/* don't delete built-in chain */
+	if (nft_chain_builtin(c))
+		return d->builtin_err;
+
+	if (d->verbose)
+		fprintf(stdout, "Deleting chain `%s'\n",
+			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
+
+	ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
+	if (ret)
+		return -1;
+
+	nftnl_chain_list_del(c);
+	return 0;
+}
+
 int nft_chain_user_del(struct nft_handle *h, const char *chain,
 		       const char *table, bool verbose)
 {
+	struct chain_user_del_data d = {
+		.handle = h,
+		.verbose = verbose,
+	};
 	struct nftnl_chain_list *list;
-	struct nftnl_chain_list_iter *iter;
 	struct nftnl_chain *c;
 	int ret = 0;
-	int deleted_ctr = 0;
 
 	nft_fn = nft_chain_user_del;
 
 	list = nft_chain_list_get(h, table);
 	if (list == NULL)
-		goto err;
-
-	iter = nftnl_chain_list_iter_create(list);
-	if (iter == NULL)
-		goto err;
-
-	c = nftnl_chain_list_iter_next(iter);
-	while (c != NULL) {
-		const char *chain_name =
-			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
-
-		/* don't delete built-in chain */
-		if (nft_chain_builtin(c))
-			goto next;
-
-		if (chain != NULL && strcmp(chain, chain_name) != 0)
-			goto next;
-
-		if (verbose)
-			fprintf(stdout, "Deleting chain `%s'\n", chain);
-
-		ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c);
-
-		if (ret < 0)
-			break;
-
-		deleted_ctr++;
-		nftnl_chain_list_del(c);
-
-		if (chain != NULL)
-			break;
-next:
-		c = nftnl_chain_list_iter_next(iter);
-	}
-
-	nftnl_chain_list_iter_destroy(iter);
-err:
+		return 0;
 
-	/* chain not found */
-	if (chain != NULL && deleted_ctr == 0) {
-		ret = -1;
-		errno = ENOENT;
+	if (chain) {
+		c = nftnl_chain_list_lookup_byname(list, chain);
+		if (!c) {
+			errno = ENOENT;
+			return 0;
+		}
+		d.builtin_err = -2;
+		ret = __nft_chain_user_del(c, &d);
+		if (ret == -2)
+			errno = EINVAL;
+		goto out;
 	}
 
+	ret = nftnl_chain_list_foreach(list, __nft_chain_user_del, &d);
+out:
 	/* the core expects 1 for success and 0 for error */
 	return ret == 0 ? 1 : 0;
 }
-- 
2.21.0