[PATCH xtables] xtables-nft: make -Z option work

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

 



-Z doesn't just zero base counters, it zeroes out all rule
counters, or, optionally, all counters of a chain (-Z FOO).

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1286
Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 iptables/nft.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 2 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index f3a3d9d5a2fc..e2a490244868 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2997,6 +2997,78 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename,
 	return h->config_done;
 }
 
+static void nft_chain_zero_rule_counters(struct nft_handle *h,
+					 struct nftnl_chain *c)
+{
+	struct nftnl_rule_list_iter *iter;
+	struct nftnl_rule_list *list;
+	const char *table_name;
+	const char *chain_name;
+	struct nftnl_rule *r;
+
+	list = nft_rule_list_get(h);
+	if (list == NULL)
+		return;
+	iter = nftnl_rule_list_iter_create(list);
+	if (iter == NULL)
+		return;
+
+	table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE);
+	chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME);
+
+	r = nftnl_rule_list_iter_next(iter);
+	while (r != NULL) {
+		struct nftnl_expr_iter *ei;
+		const char *table_chain;
+		const char *rule_chain;
+		struct nftnl_expr *e;
+		bool zero_needed;
+
+		table_chain = nftnl_rule_get_str(r, NFTNL_RULE_TABLE);
+		if (strcmp(table_chain, table_name))
+			goto next;
+
+		rule_chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
+		if (strcmp(rule_chain, chain_name))
+			goto next;
+
+		ei = nftnl_expr_iter_create(r);
+		if (!ei)
+			break;
+
+		e = nftnl_expr_iter_next(ei);
+	        zero_needed = false;
+		while (e != NULL) {
+			const char *en = nftnl_expr_get_str(e, NFTNL_EXPR_NAME);
+
+			if (strcmp(en, "counter") == 0 && (
+			    nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_PACKETS) ||
+			    nftnl_expr_get_u64(e, NFTNL_EXPR_CTR_BYTES))) {
+				nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_PACKETS, 0);
+				nftnl_expr_set_u64(e, NFTNL_EXPR_CTR_BYTES, 0);
+				zero_needed = true;
+			}
+
+			e = nftnl_expr_iter_next(ei);
+		}
+
+		nftnl_expr_iter_destroy(ei);
+
+		if (zero_needed) {
+			/*
+			 * Unset RULE_POSITION for older kernels, we want to replace
+			 * rule based on its handle only.
+			 */
+			nftnl_rule_unset(r, NFTNL_RULE_POSITION);
+			batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r);
+		}
+next:
+		r = nftnl_rule_list_iter_next(iter);
+	}
+
+	nftnl_rule_list_iter_destroy(iter);
+}
+
 int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
 			    const char *table, bool verbose)
 {
@@ -3029,8 +3101,13 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain,
 		if (verbose)
 			fprintf(stdout, "Zeroing chain `%s'\n", chain_name);
 
-		nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
-		nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
+		if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) {
+			/* zero base chain counters. */
+			nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0);
+			nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0);
+		}
+
+		nft_chain_zero_rule_counters(h, c);
 
 		nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
 
-- 
2.18.1




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

  Powered by Linux