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 <f...@strlen.de>
---
 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 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;
 }
-- 
2.18.1

Reply via email to