[iptables PATCH] xtables: Fix for wrong counter format in -S output

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

 



Legacy iptables uses '-c PCNT BCNT' format in listed rules, nft-variant
used '[PCNT BCNT]' prefix like with iptables-save.

In order to pass the counter format preference along, FMT_C_COUNTS is
introduced and related 'format' checks adjusted.

Since legacy iptables prints the counters between matches and target,
this change affects save_matches_and_target() function. In order to get
access to the rule counters, it's declaration is adjusted to receive
iptables_command_state pointer instead of match, target and jumpto
pointers from the same object.

While being at it, integrate jump to user-defined chain into it as well
since the related code in both callers was almost identical. Though
since different rule flags are used between iptables and ip6tables, pass
a 'goto_flag' boolean instead of the actual 'flags' bitfield.

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 include/xtables.h                             |  1 +
 iptables/nft-ipv4.c                           | 10 +---
 iptables/nft-ipv6.c                           | 10 +---
 iptables/nft-shared.c                         | 29 +++++++----
 iptables/nft-shared.h                         |  7 ++-
 iptables/nft.c                                | 10 +++-
 .../testcases/iptables/0003-list-rules_0      | 48 +++++++++++++++++++
 7 files changed, 83 insertions(+), 32 deletions(-)
 create mode 100755 iptables/tests/shell/testcases/iptables/0003-list-rules_0

diff --git a/include/xtables.h b/include/xtables.h
index e4d235028deea..bf169b08186f5 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -537,6 +537,7 @@ extern void xtables_save_string(const char *value);
 #define FMT_NONEWLINE		0x0080
 #define FMT_LINENUMBERS		0x0100
 #define FMT_EBT_SAVE		0x0200
+#define FMT_C_COUNTS		0x0400
 
 #define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \
                         | FMT_NUMERIC | FMT_NOTABLE)
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index eaf861d1f76e7..4446a3276a9fa 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -358,14 +358,8 @@ static void nft_ipv4_save_rule(const void *data, unsigned int format)
 		printf("-f ");
 	}
 
-	save_matches_and_target(cs->matches, cs->target,
-				cs->jumpto, cs->fw.ip.flags, &cs->fw);
-
-	if (cs->target == NULL && strlen(cs->jumpto) > 0) {
-		printf("-%c %s", cs->fw.ip.flags & IPT_F_GOTO ? 'g' : 'j',
-		       cs->jumpto);
-	}
-	printf("\n");
+	save_matches_and_target(cs, cs->fw.ip.flags & IPT_F_GOTO,
+				&cs->fw, format);
 }
 
 static void nft_ipv4_proto_parse(struct iptables_command_state *cs,
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index fa5b8c89f3db6..dfdcc0515079d 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -296,14 +296,8 @@ static void nft_ipv6_save_rule(const void *data, unsigned int format)
 			  cs->fw6.ipv6.iniface, cs->fw6.ipv6.iniface_mask,
 			  cs->fw6.ipv6.outiface, cs->fw6.ipv6.outiface_mask);
 
-	save_matches_and_target(cs->matches, cs->target,
-				cs->jumpto, cs->fw6.ipv6.flags, &cs->fw6);
-
-	if (cs->target == NULL && strlen(cs->jumpto) > 0) {
-		printf("-%c %s", cs->fw6.ipv6.flags & IP6T_F_GOTO ? 'g' : 'j',
-		       cs->jumpto);
-	}
-	printf("\n");
+	save_matches_and_target(cs, cs->fw6.ipv6.flags & IP6T_F_GOTO,
+				&cs->fw6, format);
 }
 
 /* These are invalid numbers as upper layer protocol */
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 66db7ed1fa34f..5b55c7c0a7052 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -813,13 +813,13 @@ void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy)
 	       chain, policy ?: "-", pkts, bytes);
 }
 
-void save_matches_and_target(struct xtables_rule_match *m,
-			     struct xtables_target *target,
-			     const char *jumpto, uint8_t flags, const void *fw)
+void save_matches_and_target(const struct iptables_command_state *cs,
+			     bool goto_flag, const void *fw,
+			     unsigned int format)
 {
 	struct xtables_rule_match *matchp;
 
-	for (matchp = m; matchp; matchp = matchp->next) {
+	for (matchp = cs->matches; matchp; matchp = matchp->next) {
 		if (matchp->match->alias) {
 			printf("-m %s",
 			       matchp->match->alias(matchp->match->m));
@@ -833,15 +833,24 @@ void save_matches_and_target(struct xtables_rule_match *m,
 		printf(" ");
 	}
 
-	if (target != NULL) {
-		if (target->alias) {
-			printf("-j %s", target->alias(target->t));
+	if ((format & (FMT_NOCOUNTS | FMT_C_COUNTS)) == FMT_C_COUNTS)
+		printf("-c %llu %llu ",
+		       (unsigned long long)cs->counters.pcnt,
+		       (unsigned long long)cs->counters.bcnt);
+
+	if (cs->target != NULL) {
+		if (cs->target->alias) {
+			printf("-j %s", cs->target->alias(cs->target->t));
 		} else
-			printf("-j %s", jumpto);
+			printf("-j %s", cs->jumpto);
 
-		if (target->save != NULL)
-			target->save(fw, target->t);
+		if (cs->target->save != NULL)
+			cs->target->save(fw, cs->target->t);
+	} else if (strlen(cs->jumpto) > 0) {
+		printf("-%c %s", goto_flag ? 'g' : 'j', cs->jumpto);
 	}
+
+	printf("\n");
 }
 
 void print_matches_and_target(struct iptables_command_state *cs,
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 1f5c8a8130c69..49e2fa10fc828 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -166,10 +166,9 @@ void save_rule_details(const struct iptables_command_state *cs,
 		       unsigned const char *outiface_mask);
 void save_counters(const void *data);
 void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy);
-void save_matches_and_target(struct xtables_rule_match *m,
-			     struct xtables_target *target,
-			     const char *jumpto,
-			     uint8_t flags, const void *fw);
+void save_matches_and_target(const struct iptables_command_state *cs,
+			     bool goto_flag, const void *fw,
+			     unsigned int format);
 
 struct nft_family_ops *nft_family_ops_lookup(int family);
 
diff --git a/iptables/nft.c b/iptables/nft.c
index 1c076510962b3..7fd261c3d0e3a 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1201,7 +1201,7 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type,
 	ops = nft_family_ops_lookup(family);
 	ops->rule_to_cs(r, &cs);
 
-	if (!(format & FMT_NOCOUNTS) && ops->save_counters)
+	if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)) && ops->save_counters)
 		ops->save_counters(&cs);
 
 	/* print chain name */
@@ -2397,6 +2397,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
 	struct nftnl_chain_list *list;
 	struct nftnl_chain_list_iter *iter;
 	struct nftnl_chain *c;
+	unsigned int format;
 	int ret = 1;
 
 	list = nft_chain_dump(h);
@@ -2410,6 +2411,11 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
 	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_table =
@@ -2423,7 +2429,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain,
 			goto next;
 
 		ret = __nft_rule_list(h, chain_name, table, rulenum,
-				      counters ? 0 : FMT_NOCOUNTS, list_save);
+				      format, list_save);
 
 		/* we printed the chain we wanted, stop processing. */
 		if (chain)
diff --git a/iptables/tests/shell/testcases/iptables/0003-list-rules_0 b/iptables/tests/shell/testcases/iptables/0003-list-rules_0
new file mode 100755
index 0000000000000..2e87ce5a6aec0
--- /dev/null
+++ b/iptables/tests/shell/testcases/iptables/0003-list-rules_0
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+set -e
+
+$XT_MULTI iptables -N foo
+$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j ACCEPT
+$XT_MULTI iptables -A FORWARD -i eth42 -o eth23 -g foo
+$XT_MULTI iptables -t nat -A OUTPUT -o eth123 -m mark --mark 0x42 -j ACCEPT
+
+EXPECT='-P INPUT ACCEPT
+-P FORWARD ACCEPT
+-P OUTPUT ACCEPT
+-N foo
+-A FORWARD -i eth23 -o eth42 -j ACCEPT
+-A FORWARD -i eth42 -o eth23 -g foo'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -S)
+
+EXPECT='-P INPUT ACCEPT -c 0 0
+-P FORWARD ACCEPT -c 0 0
+-P OUTPUT ACCEPT -c 0 0
+-N foo
+-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT
+-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -S)
+
+EXPECT='-P FORWARD ACCEPT
+-A FORWARD -i eth23 -o eth42 -j ACCEPT
+-A FORWARD -i eth42 -o eth23 -g foo'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -S FORWARD)
+
+EXPECT='-P FORWARD ACCEPT -c 0 0
+-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT
+-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -S FORWARD)
+
+EXPECT='-P OUTPUT ACCEPT
+-A OUTPUT -o eth123 -m mark --mark 0x42 -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -t nat -S OUTPUT)
+
+EXPECT='-P OUTPUT ACCEPT -c 0 0
+-A OUTPUT -o eth123 -m mark --mark 0x42 -c 0 0 -j ACCEPT'
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -t nat -S OUTPUT)
-- 
2.18.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