Blob Blame History Raw
From 23ef58d88034cdd5c972b9392944a772cccd61f9 Mon Sep 17 00:00:00 2001
From: Phil Sutter <phil@nwl.cc>
Date: Thu, 20 Dec 2018 16:09:19 +0100
Subject: [PATCH] xtables: Optimize list rules command with given chain

If a chain name was given, make use of nftnl_chain_list_lookup_byname().

Likewise in nftnl_rule_list_chain_save(), but introduce
__nftnl_rule_list_chain_save() 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 6b1871914e4f3717c7e6324727b80cf1d5d985b1)
Signed-off-by: Phil Sutter <psutter@redhat.com>
---
 iptables/nft.c | 93 +++++++++++++++++++++++---------------------------
 1 file changed, 43 insertions(+), 50 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index e1c997836cb97..e0455eabda77a 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2339,46 +2339,44 @@ list_save(struct nftnl_rule *r, unsigned int num, unsigned int format)
 	nft_rule_print_save(r, NFT_RULE_APPEND, format);
 }
 
+static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data)
+{
+	const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+	uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
+	int *counters = data;
+
+	if (!nft_chain_builtin(c)) {
+		printf("-N %s\n", chain_name);
+		return 0;
+	}
+
+	/* this is a base chain */
+
+	printf("-P %s %s", chain_name, policy_name[policy]);
+	if (*counters)
+		printf(" -c %"PRIu64" %"PRIu64,
+		       nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
+		       nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
+	printf("\n");
+	return 0;
+}
+
 static int
 nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain,
 			   struct nftnl_chain_list *list, int counters)
 {
-	struct nftnl_chain_list_iter *iter;
 	struct nftnl_chain *c;
 
-	iter = nftnl_chain_list_iter_create(list);
-	if (iter == NULL)
-		return 0;
-
-	c = nftnl_chain_list_iter_next(iter);
-	while (c != NULL) {
-		const char *chain_name =
-			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
-		uint32_t policy =
-			nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY);
-
-		if (chain && strcmp(chain, chain_name) != 0)
-			goto next;
+	if (chain) {
+		c = nftnl_chain_list_lookup_byname(list, chain);
+		if (!c)
+			return 0;
 
-		/* this is a base chain */
-		if (nft_chain_builtin(c)) {
-			printf("-P %s %s", chain_name, policy_name[policy]);
-
-			if (counters) {
-				printf(" -c %"PRIu64" %"PRIu64"\n",
-					nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS),
-					nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES));
-			} else
-				printf("\n");
-		} else {
-			printf("-N %s\n", chain_name);
-		}
-next:
-		c = nftnl_chain_list_iter_next(iter);
+		__nftnl_rule_list_chain_save(c, &counters);
+		return 1;
 	}
 
-	nftnl_chain_list_iter_destroy(iter);
-
+	nftnl_chain_list_foreach(list, __nftnl_rule_list_chain_save, &counters);
 	return 1;
 }
 
@@ -2410,41 +2408,36 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
 
 	list = nft_chain_list_get(h, table);
 	if (!list)
-		goto err;
+		return 0;
 
 	/* Dump policies and custom chains first */
 	if (!rulenum)
 		nftnl_rule_list_chain_save(h, chain, list, counters);
 
-	/* Now dump out rules in this table */
-	iter = nftnl_chain_list_iter_create(list);
-	if (iter == NULL)
-		goto err;
-
 	if (counters < 0)
 		format = FMT_C_COUNTS;
 	else if (counters == 0)
 		format = FMT_NOCOUNTS;
 
-	c = nftnl_chain_list_iter_next(iter);
-	while (c != NULL) {
-		const char *chain_name =
-			nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+	if (chain) {
+		c = nftnl_chain_list_lookup_byname(list, chain);
+		if (!c)
+			return 0;
 
-		if (chain && strcmp(chain, chain_name) != 0)
-			goto next;
+		return __nft_rule_list(h, c, rulenum, format, list_save);
+	}
 
-		ret = __nft_rule_list(h, c, rulenum, format, list_save);
+	/* Now dump out rules in this table */
+	iter = nftnl_chain_list_iter_create(list);
+	if (iter == NULL)
+		return 0;
 
-		/* we printed the chain we wanted, stop processing. */
-		if (chain)
-			break;
-next:
+	c = nftnl_chain_list_iter_next(iter);
+	while (c != NULL) {
+		ret = __nft_rule_list(h, c, rulenum, format, list_save);
 		c = nftnl_chain_list_iter_next(iter);
 	}
-
 	nftnl_chain_list_iter_destroy(iter);
-err:
 	return ret;
 }
 
-- 
2.21.0