summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-11-05 10:44:20 +0100
committerFlorian Westphal <fw@strlen.de>2018-11-05 13:16:38 +0100
commitc59ba1b19b20c97e006fae7163ebb211b6f9098b (patch)
tree0eb3107de6aa1563cc84412b3d6ef105fe96d1e2
parent1bf4a13712f5229aa27a6a29db33c634ab12b28e (diff)
xtables-nft: make -Z option work
-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@strlen.de>
-rw-r--r--iptables/nft.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index f3a3d9d5..e2a49024 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);