Both implementations were very similar already. Differences were mostly
in which libiptc functions were called. Therefore introduce struct
iptables_save_cb to point to the right functions for each variant.

Signed-off-by: Phil Sutter <p...@nwl.cc>
---
 iptables/Makefile.am      |   8 +-
 iptables/ip6tables-save.c | 203 --------------------------------------
 iptables/iptables-save.c  | 179 +++++++++++++++++++++++----------
 3 files changed, 129 insertions(+), 261 deletions(-)
 delete mode 100644 iptables/ip6tables-save.c

diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index a21dadb7994f5..4d59c489908b1 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -13,18 +13,16 @@ if ENABLE_STATIC
 xtables_legacy_multi_CFLAGS  += -DALL_INCLUSIVE
 endif
 if ENABLE_IPV4
-xtables_legacy_multi_SOURCES += iptables-save.c \
-                         iptables-standalone.c iptables.c
+xtables_legacy_multi_SOURCES += iptables-standalone.c iptables.c
 xtables_legacy_multi_CFLAGS  += -DENABLE_IPV4
 xtables_legacy_multi_LDADD   += ../libiptc/libip4tc.la ../extensions/libext4.a
 endif
 if ENABLE_IPV6
-xtables_legacy_multi_SOURCES += ip6tables-save.c \
-                          ip6tables-standalone.c ip6tables.c
+xtables_legacy_multi_SOURCES += ip6tables-standalone.c ip6tables.c
 xtables_legacy_multi_CFLAGS  += -DENABLE_IPV6
 xtables_legacy_multi_LDADD   += ../libiptc/libip6tc.la ../extensions/libext6.a
 endif
-xtables_legacy_multi_SOURCES += xshared.c iptables-restore.c
+xtables_legacy_multi_SOURCES += xshared.c iptables-restore.c iptables-save.c
 xtables_legacy_multi_LDADD   += ../libxtables/libxtables.la -lm
 
 # iptables using nf_tables api
diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c
deleted file mode 100644
index 5085982bfc197..0000000000000
--- a/iptables/ip6tables-save.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* Code to save the ip6tables state, in human readable-form. */
-/* Author:  Andras Kis-Szabo <ki...@sch.bme.hu>
- * Original code: iptables-save
- * Authors: Paul 'Rusty' Russel <ru...@linuxcare.com.au> and
- *          Harald Welte <lafo...@gnumonks.org>
- * This code is distributed under the terms of GNU GPL v2
- */
-#include <getopt.h>
-#include <errno.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include "libiptc/libip6tc.h"
-#include "ip6tables.h"
-#include "ip6tables-multi.h"
-
-#define prog_name ip6tables_globals.program_name
-#define prog_vers ip6tables_globals.program_version
-
-static int show_counters;
-
-static const struct option options[] = {
-       {.name = "counters", .has_arg = false, .val = 'c'},
-       {.name = "dump",     .has_arg = false, .val = 'd'},
-       {.name = "table",    .has_arg = true,  .val = 't'},
-       {.name = "modprobe", .has_arg = true,  .val = 'M'},
-       {.name = "file",     .has_arg = true,  .val = 'f'},
-       {.name = "version",  .has_arg = false, .val = 'V'},
-       {NULL},
-};
-
-
-/* Debugging prototype. */
-static int for_each_table(int (*func)(const char *tablename))
-{
-       int ret = 1;
-       FILE *procfile = NULL;
-       char tablename[XT_TABLE_MAXNAMELEN+1];
-       static const char filename[] = "/proc/net/ip6_tables_names";
-
-       procfile = fopen(filename, "re");
-       if (!procfile) {
-               if (errno == ENOENT)
-                       return ret;
-               fprintf(stderr, "Failed to list table names in %s: %s\n",
-                       filename, strerror(errno));
-               exit(1);
-       }
-
-       while (fgets(tablename, sizeof(tablename), procfile)) {
-               if (tablename[strlen(tablename) - 1] != '\n')
-                       xtables_error(OTHER_PROBLEM,
-                                  "Badly formed tablename `%s'\n",
-                                  tablename);
-               tablename[strlen(tablename) - 1] = '\0';
-               ret &= func(tablename);
-       }
-
-       fclose(procfile);
-       return ret;
-}
-
-
-static int do_output(const char *tablename)
-{
-       struct xtc_handle *h;
-       const char *chain = NULL;
-
-       if (!tablename)
-               return for_each_table(&do_output);
-
-       h = ip6tc_init(tablename);
-       if (h == NULL) {
-               xtables_load_ko(xtables_modprobe_program, false);
-               h = ip6tc_init(tablename);
-       }
-       if (!h)
-               xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
-                          ip6tc_strerror(errno));
-
-       time_t now = time(NULL);
-
-       printf("# Generated by ip6tables-save v%s on %s",
-              IPTABLES_VERSION, ctime(&now));
-       printf("*%s\n", tablename);
-
-       /* Dump out chain names first,
-        * thereby preventing dependency conflicts */
-       for (chain = ip6tc_first_chain(h);
-            chain;
-            chain = ip6tc_next_chain(h)) {
-
-               printf(":%s ", chain);
-               if (ip6tc_builtin(chain, h)) {
-                       struct xt_counters count;
-                       printf("%s ",
-                              ip6tc_get_policy(chain, &count, h));
-                       printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, 
(unsigned long long)count.bcnt);
-               } else {
-                       printf("- [0:0]\n");
-               }
-       }
-
-       for (chain = ip6tc_first_chain(h);
-            chain;
-            chain = ip6tc_next_chain(h)) {
-               const struct ip6t_entry *e;
-
-               /* Dump out rules */
-               e = ip6tc_first_rule(chain, h);
-               while(e) {
-                       print_rule6(e, h, chain, show_counters);
-                       e = ip6tc_next_rule(e, h);
-               }
-       }
-
-       now = time(NULL);
-       printf("COMMIT\n");
-       printf("# Completed on %s", ctime(&now));
-       ip6tc_free(h);
-
-       return 1;
-}
-
-/* Format:
- * :Chain name POLICY packets bytes
- * rule
- */
-int ip6tables_save_main(int argc, char *argv[])
-{
-       const char *tablename = NULL;
-       FILE *file = NULL;
-       int ret, c;
-
-       ip6tables_globals.program_name = "ip6tables-save";
-       c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
-       if (c < 0) {
-               fprintf(stderr, "%s/%s Failed to initialize xtables\n",
-                               ip6tables_globals.program_name,
-                               ip6tables_globals.program_version);
-               exit(1);
-       }
-#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
-       init_extensions();
-       init_extensions6();
-#endif
-
-       while ((c = getopt_long(argc, argv, "bcdt:M:f:V", options, NULL)) != 
-1) {
-               switch (c) {
-               case 'b':
-                       fprintf(stderr, "-b/--binary option is not 
implemented\n");
-                       break;
-               case 'c':
-                       show_counters = 1;
-                       break;
-
-               case 't':
-                       /* Select specific table. */
-                       tablename = optarg;
-                       break;
-               case 'M':
-                       xtables_modprobe_program = optarg;
-                       break;
-               case 'f':
-                       file = fopen(optarg, "w");
-                       if (file == NULL) {
-                               fprintf(stderr, "Failed to open file, error: 
%s\n",
-                                       strerror(errno));
-                               exit(1);
-                       }
-                       ret = dup2(fileno(file), STDOUT_FILENO);
-                       if (ret == -1) {
-                               fprintf(stderr, "Failed to redirect stdout, 
error: %s\n",
-                                       strerror(errno));
-                               exit(1);
-                       }
-                       fclose(file);
-                       break;
-               case 'd':
-                       do_output(tablename);
-                       exit(0);
-               case 'V':
-                       printf("%s v%s (legacy)\n", prog_name, prog_vers);
-                       exit(0);
-               default:
-                       fprintf(stderr,
-                               "Look at manual page `ip6tables-save.8' for 
more information.\n");
-                       exit(1);
-               }
-       }
-
-       if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline\n");
-               exit(1);
-       }
-
-       return !do_output(tablename);
-}
diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c
index d694d212d7edf..826cb1e4f7b94 100644
--- a/iptables/iptables-save.c
+++ b/iptables/iptables-save.c
@@ -15,11 +15,12 @@
 #include <netdb.h>
 #include <unistd.h>
 #include "libiptc/libiptc.h"
+#include "libiptc/libip6tc.h"
 #include "iptables.h"
+#include "ip6tables.h"
 #include "iptables-multi.h"
-
-#define prog_name iptables_globals.program_name
-#define prog_vers iptables_globals.program_version
+#include "ip6tables-multi.h"
+#include "xshared.h"
 
 static int show_counters;
 
@@ -33,20 +34,26 @@ static const struct option options[] = {
        {NULL},
 };
 
-/* Debugging prototype. */
-static int for_each_table(int (*func)(const char *tablename))
+struct iptables_save_cb {
+       const struct xtc_ops *ops;
+
+       void (*dump_rules)(const char *chain, struct xtc_handle *handle);
+};
+
+static int
+for_each_table(int (*func)(struct iptables_save_cb *cb, const char *tablename),
+              struct iptables_save_cb *cb)
 {
        int ret = 1;
        FILE *procfile = NULL;
        char tablename[XT_TABLE_MAXNAMELEN+1];
-       static const char filename[] = "/proc/net/ip_tables_names";
 
-       procfile = fopen(filename, "re");
+       procfile = fopen(afinfo->proc_exists, "re");
        if (!procfile) {
                if (errno == ENOENT)
                        return ret;
                fprintf(stderr, "Failed to list table names in %s: %s\n",
-                       filename, strerror(errno));
+                       afinfo->proc_exists, strerror(errno));
                exit(1);
        }
 
@@ -56,71 +63,65 @@ static int for_each_table(int (*func)(const char 
*tablename))
                                   "Badly formed tablename `%s'\n",
                                   tablename);
                tablename[strlen(tablename) - 1] = '\0';
-               ret &= func(tablename);
+               ret &= func(cb, tablename);
        }
 
        fclose(procfile);
        return ret;
 }
 
-
-static int do_output(const char *tablename)
+static int do_output(struct iptables_save_cb *cb, const char *tablename)
 {
        struct xtc_handle *h;
        const char *chain = NULL;
 
        if (!tablename)
-               return for_each_table(&do_output);
+               return for_each_table(&do_output, cb);
 
-       h = iptc_init(tablename);
+       h = cb->ops->init(tablename);
        if (h == NULL) {
                xtables_load_ko(xtables_modprobe_program, false);
-               h = iptc_init(tablename);
+               h = cb->ops->init(tablename);
        }
        if (!h)
                xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
-                          iptc_strerror(errno));
+                             cb->ops->strerror(errno));
 
        time_t now = time(NULL);
 
-       printf("# Generated by iptables-save v%s on %s",
-              IPTABLES_VERSION, ctime(&now));
+       printf("# Generated by %s v%s on %s",
+              xt_params->program_name, IPTABLES_VERSION, ctime(&now));
        printf("*%s\n", tablename);
 
        /* Dump out chain names first,
         * thereby preventing dependency conflicts */
-       for (chain = iptc_first_chain(h);
+       for (chain = cb->ops->first_chain(h);
             chain;
-            chain = iptc_next_chain(h)) {
+            chain = cb->ops->next_chain(h)) {
 
                printf(":%s ", chain);
-               if (iptc_builtin(chain, h)) {
+               if (cb->ops->builtin(chain, h)) {
                        struct xt_counters count;
-                       printf("%s ",
-                              iptc_get_policy(chain, &count, h));
-                       printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, 
(unsigned long long)count.bcnt);
+
+                       printf("%s ", cb->ops->get_policy(chain, &count, h));
+                       printf("[%llu:%llu]\n",
+                              (unsigned long long)count.pcnt,
+                              (unsigned long long)count.bcnt);
                } else {
                        printf("- [0:0]\n");
                }
        }
 
-       for (chain = iptc_first_chain(h);
+       for (chain = cb->ops->first_chain(h);
             chain;
-            chain = iptc_next_chain(h)) {
-               const struct ipt_entry *e;
-
-               /* Dump out rules */
-               e = iptc_first_rule(chain, h);
-               while(e) {
-                       print_rule4(e, h, chain, show_counters);
-                       e = iptc_next_rule(e, h);
-               }
+            chain = cb->ops->next_chain(h)) {
+               cb->dump_rules(chain, h);
        }
 
        now = time(NULL);
        printf("COMMIT\n");
        printf("# Completed on %s", ctime(&now));
-       iptc_free(h);
+       cb->ops->free(h);
 
        return 1;
 }
@@ -129,26 +130,13 @@ static int do_output(const char *tablename)
  * :Chain name POLICY packets bytes
  * rule
  */
-int
-iptables_save_main(int argc, char *argv[])
+static int
+do_iptables_save(struct iptables_save_cb *cb, int argc, char *argv[])
 {
        const char *tablename = NULL;
        FILE *file = NULL;
        int ret, c;
 
-       iptables_globals.program_name = "iptables-save";
-       c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
-       if (c < 0) {
-               fprintf(stderr, "%s/%s Failed to initialize xtables\n",
-                               iptables_globals.program_name,
-                               iptables_globals.program_version);
-               exit(1);
-       }
-#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
-       init_extensions();
-       init_extensions4();
-#endif
-
        while ((c = getopt_long(argc, argv, "bcdt:M:f:V", options, NULL)) != 
-1) {
                switch (c) {
                case 'b':
@@ -181,14 +169,17 @@ iptables_save_main(int argc, char *argv[])
                        fclose(file);
                        break;
                case 'd':
-                       do_output(tablename);
+                       do_output(cb, tablename);
                        exit(0);
                case 'V':
-                       printf("%s v%s (legacy)\n", prog_name, prog_vers);
+                       printf("%s v%s (legacy)\n",
+                              xt_params->program_name,
+                              xt_params->program_version);
                        exit(0);
                default:
                        fprintf(stderr,
-                               "Look at manual page `iptables-save.8' for more 
information.\n");
+                               "Look at manual page `%s.8' for more 
information.\n",
+                               xt_params->program_name);
                        exit(1);
                }
        }
@@ -198,5 +189,87 @@ iptables_save_main(int argc, char *argv[])
                exit(1);
        }
 
-       return !do_output(tablename);
+       return !do_output(cb, tablename);
+}
+
+#ifdef ENABLE_IPV4
+static void iptables_dump_rules(const char *chain, struct xtc_handle *h)
+{
+       const struct ipt_entry *e;
+
+       /* Dump out rules */
+       e = iptc_first_rule(chain, h);
+       while(e) {
+               print_rule4(e, h, chain, show_counters);
+               e = iptc_next_rule(e, h);
+       }
+}
+
+struct iptables_save_cb ipt_save_cb = {
+       .ops            = &iptc_ops,
+       .dump_rules     = iptables_dump_rules,
+};
+
+/* Format:
+ * :Chain name POLICY packets bytes
+ * rule
+ */
+int
+iptables_save_main(int argc, char *argv[])
+{
+       iptables_globals.program_name = "iptables-save";
+       if (xtables_init_all(&iptables_globals, NFPROTO_IPV4) < 0) {
+               fprintf(stderr, "%s/%s Failed to initialize xtables\n",
+                               iptables_globals.program_name,
+                               iptables_globals.program_version);
+               exit(1);
+       }
+#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
+       init_extensions();
+       init_extensions4();
+#endif
+
+       return do_iptables_save(&ipt_save_cb, argc, argv);
+}
+#endif /* ENABLE_IPV4 */
+
+#ifdef ENABLE_IPV6
+static void ip6tables_dump_rules(const char *chain, struct xtc_handle *h)
+{
+       const struct ip6t_entry *e;
+
+       /* Dump out rules */
+       e = ip6tc_first_rule(chain, h);
+       while(e) {
+               print_rule6(e, h, chain, show_counters);
+               e = ip6tc_next_rule(e, h);
+       }
+}
+
+struct iptables_save_cb ip6t_save_cb = {
+       .ops            = &ip6tc_ops,
+       .dump_rules     = ip6tables_dump_rules,
+};
+
+/* Format:
+ * :Chain name POLICY packets bytes
+ * rule
+ */
+int
+ip6tables_save_main(int argc, char *argv[])
+{
+       ip6tables_globals.program_name = "ip6tables-save";
+       if (xtables_init_all(&ip6tables_globals, NFPROTO_IPV6) < 0) {
+               fprintf(stderr, "%s/%s Failed to initialize xtables\n",
+                               ip6tables_globals.program_name,
+                               ip6tables_globals.program_version);
+               exit(1);
+       }
+#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
+       init_extensions();
+       init_extensions6();
+#endif
+
+       return do_iptables_save(&ip6t_save_cb, argc, argv);
 }
+#endif /* ENABLE_IPV6 */
-- 
2.18.0

Reply via email to