From 583b27eabcad6588ef6c923551df444c4e30a210 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 12 Nov 2018 12:49:10 +0100 Subject: ebtables-save: add -c option, using xtables-style counters 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 --- iptables/nft-bridge.c | 38 +++++++++++++++++++++---------- iptables/xtables-save.c | 60 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index 92e3f3b6..8c69a236 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 87b299c5..28711720 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; } -- cgit v1.2.3