diff mbox series

[xtables,1/2] ebtables-save: add -c option, using xtables-style counters

Message ID 20181112114911.15926-1-fw@strlen.de
State Accepted
Headers show
Series [xtables,1/2] ebtables-save: add -c option, using xtables-style counters | expand

Commit Message

Florian Westphal Nov. 12, 2018, 11:49 a.m. UTC
The 'original' ebtables-save was a perl script that supported no option.
Add minimal options, like ip(6)tables save.

Retain the old way of formatiing counters via environment variable,
but allow overriding this using the -c option.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 iptables/nft-bridge.c   | 38 +++++++++++++++++---------
 iptables/xtables-save.c | 60 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 81 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 92e3f3b6f97f..8c69a23616fb 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -21,6 +21,8 @@ 
 #include "nft-bridge.h"
 #include "nft.h"
 
+static bool ebt_legacy_counter_fmt;
+
 void ebt_cs_clean(struct iptables_command_state *cs)
 {
 	struct ebt_match *m, *nm;
@@ -410,6 +412,22 @@  static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
 		printf("%s ", ent->e_name);
 }
 
+static void nft_bridge_save_counters(const void *data)
+{
+	const char *ctr;
+
+	if (ebt_legacy_counter_fmt)
+		return;
+
+	ctr = getenv("EBTABLES_SAVE_COUNTER");
+	if (ctr) {
+		ebt_legacy_counter_fmt = true;
+		return;
+	}
+
+	save_counters(data);
+}
+
 static void nft_bridge_save_rule(const void *data, unsigned int format)
 {
 	const struct iptables_command_state *cs = data;
@@ -446,18 +464,10 @@  static void nft_bridge_save_rule(const void *data, unsigned int format)
 		cs->target->print(&cs->fw, cs->target->t, format & FMT_NUMERIC);
 	}
 
-	if (!(format & FMT_NOCOUNTS)) {
-		const char *counter_fmt;
-
-		if (format & FMT_EBT_SAVE)
-			counter_fmt = " -c %"PRIu64" %"PRIu64"";
-		else
-			counter_fmt = " , pcnt = %"PRIu64" -- bcnt = %"PRIu64"";
-
-		printf(counter_fmt,
+	if (format & FMT_EBT_SAVE)
+		printf(" -c %"PRIu64" %"PRIu64"",
 		       (uint64_t)cs->counters.pcnt,
 		       (uint64_t)cs->counters.bcnt);
-	}
 
 	if (!(format & FMT_NONEWLINE))
 		fputc('\n', stdout);
@@ -472,7 +482,11 @@  static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num,
 		printf("%d ", num);
 
 	nft_rule_to_ebtables_command_state(r, &cs);
-	nft_bridge_save_rule(&cs, format);
+	nft_bridge_save_rule(&cs, format & ~FMT_EBT_SAVE);
+	if (!(format & FMT_NOCOUNTS))
+		printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"",
+		       (uint64_t)cs.counters.pcnt,
+		       (uint64_t)cs.counters.bcnt);
 	ebt_cs_clean(&cs);
 }
 
@@ -734,7 +748,7 @@  struct nft_family_ops nft_family_ops_bridge = {
 	.print_header		= nft_bridge_print_header,
 	.print_rule		= nft_bridge_print_rule,
 	.save_rule		= nft_bridge_save_rule,
-	.save_counters		= NULL,
+	.save_counters		= nft_bridge_save_counters,
 	.save_chain		= nft_bridge_save_chain,
 	.post_parse		= NULL,
 	.rule_to_cs		= nft_rule_to_ebtables_command_state,
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index 53ce4b87febf..ca94c6621e51 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -43,6 +43,16 @@  static const struct option options[] = {
 	{NULL},
 };
 
+static const struct option ebt_save_options[] = {
+	{.name = "counters", .has_arg = false, .val = 'c'},
+	{.name = "version",  .has_arg = false, .val = 'V'},
+	{.name = "table",    .has_arg = true,  .val = 't'},
+	{.name = "modprobe", .has_arg = true,  .val = 'M'},
+	{NULL},
+};
+
+static bool ebt_legacy_counter_format;
+
 static int
 __do_output(struct nft_handle *h, const char *tablename, bool counters)
 {
@@ -226,6 +236,7 @@  int xtables_ip6_save_main(int argc, char *argv[])
 static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters)
 {
 	struct nftnl_chain_list *chain_list;
+	unsigned int format = FMT_NOCOUNTS;
 	static bool first = true;
 	time_t now;
 
@@ -249,25 +260,40 @@  static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters
 	}
 	printf("*%s\n", tablename);
 
+	if (counters)
+		format = ebt_legacy_counter_format ? FMT_EBT_SAVE : 0;
+
 	/* Dump out chain names first,
 	 * thereby preventing dependency conflicts */
 	nft_chain_save(h, chain_list, tablename);
-	nft_rule_save(h, tablename,
-		      FMT_EBT_SAVE | (counters ? 0 : FMT_NOCOUNTS));
+	nft_rule_save(h, tablename, format);
 	printf("\n");
 	return 0;
 }
 
+static int ebt_save(struct nft_handle *h, const char *tablename, bool counters)
+{
+	if (!tablename)
+		return nft_for_each_table(h, __ebt_save, counters);
+
+	return __ebt_save(h, tablename, counters);
+}
+
 int xtables_eb_save_main(int argc_, char *argv_[])
 {
 	const char *ctr = getenv("EBTABLES_SAVE_COUNTER");
+	const char *tablename = NULL;
 	struct nft_handle h = {
 		.family	= NFPROTO_BRIDGE,
 	};
 	int c;
 
-	if (ctr && strcmp(ctr, "yes"))
-		ctr = NULL;
+	if (ctr) {
+		if (strcmp(ctr, "yes") == 0) {
+			ebt_legacy_counter_format = true;
+			show_counters = true;
+		}
+	}
 
 	xtables_globals.program_name = "ebtables-save";
 	c = xtables_init_all(&xtables_globals, h.family);
@@ -278,6 +304,30 @@  int xtables_eb_save_main(int argc_, char *argv_[])
 		exit(1);
 	}
 
+	while ((c = getopt_long(argc_, argv_, "ct:M:V", ebt_save_options, NULL)) != -1) {
+		switch (c) {
+		case 'c':
+			unsetenv("EBTABLES_SAVE_COUNTER");
+			show_counters = true;
+			ebt_legacy_counter_format = false;
+			break;
+		case 't':
+			/* Select specific table. */
+			tablename = optarg;
+			break;
+		case 'M':
+			xtables_modprobe_program = optarg;
+			break;
+		case 'V':
+			printf("%s v%s (nf_tables)\n", prog_name, prog_vers);
+			exit(0);
+		default:
+			fprintf(stderr,
+				"Look at manual page `xtables-save.8' for more information.\n");
+			exit(1);
+		}
+	}
+
 	if (nft_init(&h, xtables_bridge) < 0) {
 		fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
 				xtables_globals.program_name,
@@ -286,7 +336,7 @@  int xtables_eb_save_main(int argc_, char *argv_[])
 		exit(EXIT_FAILURE);
 	}
 
-	nft_for_each_table(&h, __ebt_save, !!ctr);
+	ebt_save(&h, tablename, show_counters);
 	nft_fini(&h);
 	return 0;
 }