]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
ip6tables-restore: Merge into iptables-restore.c
authorPhil Sutter <phil@nwl.cc>
Wed, 19 Sep 2018 14:25:57 +0000 (16:25 +0200)
committerFlorian Westphal <fw@strlen.de>
Tue, 13 Nov 2018 11:12:49 +0000 (12:12 +0100)
Introduce struct iptables_restore_cb and merge ip6tables-restore with
iptables-restore.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/Makefile.am
iptables/ip6tables-restore.c [deleted file]
iptables/iptables-restore.c

index 581dc32ba846b9b1ab4278631f7adb591ba77039..a21dadb7994f57575dc3cb2d9431dbfe7b008b39 100644 (file)
@@ -13,18 +13,18 @@ if ENABLE_STATIC
 xtables_legacy_multi_CFLAGS  += -DALL_INCLUSIVE
 endif
 if ENABLE_IPV4
-xtables_legacy_multi_SOURCES += iptables-save.c iptables-restore.c \
+xtables_legacy_multi_SOURCES += iptables-save.c \
                          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-restore.c \
+xtables_legacy_multi_SOURCES += ip6tables-save.c \
                           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
+xtables_legacy_multi_SOURCES += xshared.c iptables-restore.c
 xtables_legacy_multi_LDADD   += ../libxtables/libxtables.la -lm
 
 # iptables using nf_tables api
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
deleted file mode 100644 (file)
index 3706b98..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-/* Code to restore the iptables state, from file by ip6tables-save.
- * Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
- *
- * based on iptables-restore
- * Authors:
- *      Harald Welte <laforge@gnumonks.org>
- *      Rusty Russell <rusty@linuxcare.com.au>
- * This code is distributed under the terms of GNU GPL v2
- */
-
-#include <getopt.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "ip6tables.h"
-#include "xshared.h"
-#include "xtables.h"
-#include "libiptc/libip6tc.h"
-#include "ip6tables-multi.h"
-
-static int counters, verbose, noflush, wait;
-
-static struct timeval wait_interval = {
-       .tv_sec = 1,
-};
-
-/* Keeping track of external matches and targets.  */
-static const struct option options[] = {
-       {.name = "counters",      .has_arg = 0, .val = 'c'},
-       {.name = "verbose",       .has_arg = 0, .val = 'v'},
-       {.name = "version",       .has_arg = 0, .val = 'V'},
-       {.name = "test",          .has_arg = 0, .val = 't'},
-       {.name = "help",          .has_arg = 0, .val = 'h'},
-       {.name = "noflush",       .has_arg = 0, .val = 'n'},
-       {.name = "modprobe",      .has_arg = 1, .val = 'M'},
-       {.name = "table",         .has_arg = 1, .val = 'T'},
-       {.name = "wait",          .has_arg = 2, .val = 'w'},
-       {.name = "wait-interval", .has_arg = 2, .val = 'W'},
-       {NULL},
-};
-
-#define prog_name ip6tables_globals.program_name
-#define prog_vers ip6tables_globals.program_version
-
-static void print_usage(const char *name, const char *version)
-{
-       fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
-                       "          [ --counters ]\n"
-                       "          [ --verbose ]\n"
-                       "          [ --version]\n"
-                       "          [ --test ]\n"
-                       "          [ --help ]\n"
-                       "          [ --noflush ]\n"
-                       "          [ --wait=<seconds>\n"
-                       "          [ --wait-interval=<usecs>\n"
-                       "          [ --table=<TABLE> ]\n"
-                       "          [ --modprobe=<command> ]\n", name);
-}
-
-static struct xtc_handle *create_handle(const char *tablename)
-{
-       struct xtc_handle *handle;
-
-       handle = ip6tc_init(tablename);
-
-       if (!handle) {
-               /* try to insmod the module if iptc_init failed */
-               xtables_load_ko(xtables_modprobe_program, false);
-               handle = ip6tc_init(tablename);
-       }
-
-       if (!handle) {
-               xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
-                       "table '%s'\n", prog_name, tablename);
-               exit(1);
-       }
-       return handle;
-}
-
-int ip6tables_restore_main(int argc, char *argv[])
-{
-       struct xtc_handle *handle = NULL;
-       char buffer[10240];
-       int c, lock;
-       char curtable[XT_TABLE_MAXNAMELEN + 1] = {};
-       FILE *in;
-       int in_table = 0, testing = 0;
-       const char *tablename = NULL;
-       const struct xtc_ops *ops = &ip6tc_ops;
-
-       line = 0;
-       lock = XT_LOCK_NOT_ACQUIRED;
-
-       ip6tables_globals.program_name = "ip6tables-restore";
-       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, "bcvVthnwWM:T:", options, NULL)) != -1) {
-               switch (c) {
-                       case 'b':
-                               fprintf(stderr, "-b/--binary option is not implemented\n");
-                               break;
-                       case 'c':
-                               counters = 1;
-                               break;
-                       case 'v':
-                               verbose = 1;
-                               break;
-                       case 'V':
-                               printf("%s v%s (legacy)\n", prog_name, prog_vers);
-                               exit(0);
-                       case 't':
-                               testing = 1;
-                               break;
-                       case 'h':
-                               print_usage("ip6tables-restore",
-                                           IPTABLES_VERSION);
-                               exit(0);
-                       case 'n':
-                               noflush = 1;
-                               break;
-                       case 'w':
-                               wait = parse_wait_time(argc, argv);
-                               break;
-                       case 'W':
-                               parse_wait_interval(argc, argv, &wait_interval);
-                               break;
-                       case 'M':
-                               xtables_modprobe_program = optarg;
-                               break;
-                       case 'T':
-                               tablename = optarg;
-                               break;
-                       default:
-                               fprintf(stderr,
-                                       "Try `ip6tables-restore -h' for more information.\n");
-                               exit(1);
-               }
-       }
-
-       if (optind == argc - 1) {
-               in = fopen(argv[optind], "re");
-               if (!in) {
-                       fprintf(stderr, "Can't open %s: %s\n", argv[optind],
-                               strerror(errno));
-                       exit(1);
-               }
-       }
-       else if (optind < argc) {
-               fprintf(stderr, "Unknown arguments found on commandline\n");
-               exit(1);
-       }
-       else in = stdin;
-
-       if (!wait_interval.tv_sec && !wait) {
-               fprintf(stderr, "Option --wait-interval requires option --wait\n");
-               exit(1);
-       }
-
-       /* Grab standard input. */
-       while (fgets(buffer, sizeof(buffer), in)) {
-               int ret = 0;
-
-               line++;
-               if (buffer[0] == '\n')
-                       continue;
-               else if (buffer[0] == '#') {
-                       if (verbose)
-                               fputs(buffer, stdout);
-                       continue;
-               } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
-                       if (!testing) {
-                               DEBUGP("Calling commit\n");
-                               ret = ops->commit(handle);
-                               ops->free(handle);
-                               handle = NULL;
-                       } else {
-                               DEBUGP("Not calling commit, testing\n");
-                               ret = 1;
-                       }
-
-                       /* Done with the current table, release the lock. */
-                       if (lock >= 0) {
-                               xtables_unlock(lock);
-                               lock = XT_LOCK_NOT_ACQUIRED;
-                       }
-
-                       in_table = 0;
-               } else if ((buffer[0] == '*') && (!in_table)) {
-                       /* Acquire a lock before we create a new table handle */
-                       lock = xtables_lock_or_exit(wait, &wait_interval);
-
-                       /* New table */
-                       char *table;
-
-                       table = strtok(buffer+1, " \t\n");
-                       DEBUGP("line %u, table '%s'\n", line, table);
-                       if (!table) {
-                               xtables_error(PARAMETER_PROBLEM,
-                                       "%s: line %u table name invalid\n",
-                                       xt_params->program_name, line);
-                               exit(1);
-                       }
-                       strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
-                       curtable[XT_TABLE_MAXNAMELEN] = '\0';
-
-                       if (tablename != NULL && strcmp(tablename, table) != 0) {
-                               if (lock >= 0) {
-                                       xtables_unlock(lock);
-                                       lock = XT_LOCK_NOT_ACQUIRED;
-                               }
-                               continue;
-                       }
-                       if (handle)
-                               ops->free(handle);
-
-                       handle = create_handle(table);
-                       if (noflush == 0) {
-                               DEBUGP("Cleaning all chains of table '%s'\n",
-                                       table);
-                               for_each_chain6(flush_entries6, verbose, 1,
-                                               handle);
-
-                               DEBUGP("Deleting all user-defined chains "
-                                      "of table '%s'\n", table);
-                               for_each_chain6(delete_chain6, verbose, 0,
-                                               handle);
-                       }
-
-                       ret = 1;
-                       in_table = 1;
-
-               } else if ((buffer[0] == ':') && (in_table)) {
-                       /* New chain. */
-                       char *policy, *chain;
-
-                       chain = strtok(buffer+1, " \t\n");
-                       DEBUGP("line %u, chain '%s'\n", line, chain);
-                       if (!chain) {
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "%s: line %u chain name invalid\n",
-                                          xt_params->program_name, line);
-                               exit(1);
-                       }
-
-                       if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "Invalid chain name `%s' "
-                                          "(%u chars max)",
-                                          chain, XT_EXTENSION_MAXNAMELEN - 1);
-
-                       if (ops->builtin(chain, handle) <= 0) {
-                               if (noflush && ops->is_chain(chain, handle)) {
-                                       DEBUGP("Flushing existing user defined chain '%s'\n", chain);
-                                       if (!ops->flush_entries(chain, handle))
-                                               xtables_error(PARAMETER_PROBLEM,
-                                                          "error flushing chain "
-                                                          "'%s':%s\n", chain,
-                                                          strerror(errno));
-                               } else {
-                                       DEBUGP("Creating new chain '%s'\n", chain);
-                                       if (!ops->create_chain(chain, handle))
-                                               xtables_error(PARAMETER_PROBLEM,
-                                                          "error creating chain "
-                                                          "'%s':%s\n", chain,
-                                                          strerror(errno));
-                               }
-                       }
-
-                       policy = strtok(NULL, " \t\n");
-                       DEBUGP("line %u, policy '%s'\n", line, policy);
-                       if (!policy) {
-                               xtables_error(PARAMETER_PROBLEM,
-                                          "%s: line %u policy invalid\n",
-                                          xt_params->program_name, line);
-                               exit(1);
-                       }
-
-                       if (strcmp(policy, "-") != 0) {
-                               struct xt_counters count = {};
-
-                               if (counters) {
-                                       char *ctrs;
-                                       ctrs = strtok(NULL, " \t\n");
-
-                                       if (!ctrs || !parse_counters(ctrs, &count))
-                                               xtables_error(PARAMETER_PROBLEM,
-                                                         "invalid policy counters "
-                                                         "for chain '%s'\n", chain);
-                               }
-
-                               DEBUGP("Setting policy of chain %s to %s\n",
-                                       chain, policy);
-
-                               if (!ops->set_policy(chain, policy, &count,
-                                                    handle))
-                                       xtables_error(OTHER_PROBLEM,
-                                               "Can't set policy `%s'"
-                                               " on `%s' line %u: %s\n",
-                                               policy, chain, line,
-                                               ops->strerror(errno));
-                       }
-
-                       ret = 1;
-
-               } else if (in_table) {
-                       int a;
-                       char *pcnt = NULL;
-                       char *bcnt = NULL;
-                       char *parsestart;
-
-                       if (buffer[0] == '[') {
-                               /* we have counters in our input */
-                               char *ptr = strchr(buffer, ']');
-
-                               if (!ptr)
-                                       xtables_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need ]\n",
-                                                  line);
-
-                               pcnt = strtok(buffer+1, ":");
-                               if (!pcnt)
-                                       xtables_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need :\n",
-                                                  line);
-
-                               bcnt = strtok(NULL, "]");
-                               if (!bcnt)
-                                       xtables_error(PARAMETER_PROBLEM,
-                                                  "Bad line %u: need ]\n",
-                                                  line);
-
-                               /* start command parsing after counter */
-                               parsestart = ptr + 1;
-                       } else {
-                               /* start command parsing at start of line */
-                               parsestart = buffer;
-                       }
-
-                       add_argv(argv[0], 0);
-                       add_argv("-t", 0);
-                       add_argv(curtable, 0);
-
-                       if (counters && pcnt && bcnt) {
-                               add_argv("--set-counters", 0);
-                               add_argv((char *) pcnt, 0);
-                               add_argv((char *) bcnt, 0);
-                       }
-
-                       add_param_to_argv(parsestart, line);
-
-                       DEBUGP("calling do_command6(%u, argv, &%s, handle):\n",
-                               newargc, curtable);
-
-                       for (a = 0; a < newargc; a++)
-                               DEBUGP("argv[%u]: %s\n", a, newargv[a]);
-
-                       ret = do_command6(newargc, newargv,
-                                        &newargv[2], &handle, true);
-
-                       free_argv();
-                       fflush(stdout);
-               }
-               if (tablename != NULL && strcmp(tablename, curtable) != 0)
-                       continue;
-               if (!ret) {
-                       fprintf(stderr, "%s: line %u failed\n",
-                                       xt_params->program_name, line);
-                       exit(1);
-               }
-       }
-       if (in_table) {
-               fprintf(stderr, "%s: COMMIT expected at line %u\n",
-                               xt_params->program_name, line + 1);
-               exit(1);
-       }
-
-       fclose(in);
-       return 0;
-}
index daee5fd99564a632fc0ea5ea79113098b587336b..575e619cc30db2620bd4fbbfd2798feb77147fa9 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include "iptables.h"
+#include "ip6tables.h"
 #include "xshared.h"
 #include "xtables.h"
 #include "libiptc/libiptc.h"
+#include "libiptc/libip6tc.h"
 #include "iptables-multi.h"
+#include "ip6tables-multi.h"
 
 static int counters, verbose, noflush, wait;
 
@@ -38,9 +41,6 @@ static const struct option options[] = {
        {NULL},
 };
 
-#define prog_name iptables_globals.program_name
-#define prog_vers iptables_globals.program_version
-
 static void print_usage(const char *name, const char *version)
 {
        fprintf(stderr, "Usage: %s [-c] [-v] [-V] [-t] [-h] [-n] [-w secs] [-W usecs] [-T table] [-M command]\n"
@@ -56,28 +56,42 @@ static void print_usage(const char *name, const char *version)
                        "          [ --modprobe=<command> ]\n", name);
 }
 
-static struct xtc_handle *create_handle(const char *tablename)
+struct iptables_restore_cb {
+       const struct xtc_ops *ops;
+
+       int (*for_each_chain)(int (*fn)(const xt_chainlabel,
+                                       int, struct xtc_handle *),
+                             int verbose, int builtinstoo,
+                             struct xtc_handle *handle);
+       int (*flush_entries)(const xt_chainlabel, int, struct xtc_handle *);
+       int (*delete_chain)(const xt_chainlabel, int, struct xtc_handle *);
+       int (*do_command)(int argc, char *argv[], char **table,
+                         struct xtc_handle **handle, bool restore);
+};
+
+static struct xtc_handle *
+create_handle(struct iptables_restore_cb *cb, const char *tablename)
 {
        struct xtc_handle *handle;
 
-       handle = iptc_init(tablename);
+       handle = cb->ops->init(tablename);
 
        if (!handle) {
                /* try to insmod the module if iptc_init failed */
                xtables_load_ko(xtables_modprobe_program, false);
-               handle = iptc_init(tablename);
+               handle = cb->ops->init(tablename);
        }
 
        if (!handle) {
                xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
-                       "table '%s'\n", prog_name, tablename);
+                       "table '%s'\n", xt_params->program_name, tablename);
                exit(1);
        }
        return handle;
 }
 
-int
-iptables_restore_main(int argc, char *argv[])
+static int
+ip46tables_restore_main(struct iptables_restore_cb *cb, int argc, char *argv[])
 {
        struct xtc_handle *handle = NULL;
        char buffer[10240];
@@ -86,24 +100,10 @@ iptables_restore_main(int argc, char *argv[])
        FILE *in;
        int in_table = 0, testing = 0;
        const char *tablename = NULL;
-       const struct xtc_ops *ops = &iptc_ops;
 
        line = 0;
        lock = XT_LOCK_NOT_ACQUIRED;
 
-       iptables_globals.program_name = "iptables-restore";
-       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, "bcvVthnwWM:T:", options, NULL)) != -1) {
                switch (c) {
                        case 'b':
@@ -116,13 +116,15 @@ iptables_restore_main(int argc, char *argv[])
                                verbose = 1;
                                break;
                        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);
                        case 't':
                                testing = 1;
                                break;
                        case 'h':
-                               print_usage("iptables-restore",
+                               print_usage(xt_params->program_name,
                                            IPTABLES_VERSION);
                                exit(0);
                        case 'n':
@@ -142,7 +144,8 @@ iptables_restore_main(int argc, char *argv[])
                                break;
                        default:
                                fprintf(stderr,
-                                       "Try `iptables-restore -h' for more information.\n");
+                                       "Try `%s -h' for more information.\n",
+                                       xt_params->program_name);
                                exit(1);
                }
        }
@@ -180,8 +183,8 @@ iptables_restore_main(int argc, char *argv[])
                } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
                        if (!testing) {
                                DEBUGP("Calling commit\n");
-                               ret = ops->commit(handle);
-                               ops->free(handle);
+                               ret = cb->ops->commit(handle);
+                               cb->ops->free(handle);
                                handle = NULL;
                        } else {
                                DEBUGP("Not calling commit, testing\n");
@@ -213,7 +216,7 @@ iptables_restore_main(int argc, char *argv[])
                        strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
                        curtable[XT_TABLE_MAXNAMELEN] = '\0';
 
-                       if (tablename && (strcmp(tablename, table) != 0)) {
+                       if (tablename && strcmp(tablename, table) != 0) {
                                if (lock >= 0) {
                                        xtables_unlock(lock);
                                        lock = XT_LOCK_NOT_ACQUIRED;
@@ -221,18 +224,18 @@ iptables_restore_main(int argc, char *argv[])
                                continue;
                        }
                        if (handle)
-                               ops->free(handle);
+                               cb->ops->free(handle);
 
-                       handle = create_handle(table);
+                       handle = create_handle(cb, table);
                        if (noflush == 0) {
                                DEBUGP("Cleaning all chains of table '%s'\n",
                                        table);
-                               for_each_chain4(flush_entries4, verbose, 1,
+                               cb->for_each_chain(cb->flush_entries, verbose, 1,
                                                handle);
 
                                DEBUGP("Deleting all user-defined chains "
                                       "of table '%s'\n", table);
-                               for_each_chain4(delete_chain4, verbose, 0,
+                               cb->for_each_chain(cb->delete_chain, verbose, 0,
                                                handle);
                        }
 
@@ -258,17 +261,17 @@ iptables_restore_main(int argc, char *argv[])
                                           "(%u chars max)",
                                           chain, XT_EXTENSION_MAXNAMELEN - 1);
 
-                       if (ops->builtin(chain, handle) <= 0) {
-                               if (noflush && ops->is_chain(chain, handle)) {
+                       if (cb->ops->builtin(chain, handle) <= 0) {
+                               if (noflush && cb->ops->is_chain(chain, handle)) {
                                        DEBUGP("Flushing existing user defined chain '%s'\n", chain);
-                                       if (!ops->flush_entries(chain, handle))
+                                       if (!cb->ops->flush_entries(chain, handle))
                                                xtables_error(PARAMETER_PROBLEM,
                                                           "error flushing chain "
                                                           "'%s':%s\n", chain,
                                                           strerror(errno));
                                } else {
                                        DEBUGP("Creating new chain '%s'\n", chain);
-                                       if (!ops->create_chain(chain, handle))
+                                       if (!cb->ops->create_chain(chain, handle))
                                                xtables_error(PARAMETER_PROBLEM,
                                                           "error creating chain "
                                                           "'%s':%s\n", chain,
@@ -294,20 +297,20 @@ iptables_restore_main(int argc, char *argv[])
 
                                        if (!ctrs || !parse_counters(ctrs, &count))
                                                xtables_error(PARAMETER_PROBLEM,
-                                                          "invalid policy counters "
-                                                          "for chain '%s'\n", chain);
+                                                         "invalid policy counters "
+                                                         "for chain '%s'\n", chain);
                                }
 
                                DEBUGP("Setting policy of chain %s to %s\n",
                                        chain, policy);
 
-                               if (!ops->set_policy(chain, policy, &count,
+                               if (!cb->ops->set_policy(chain, policy, &count,
                                                     handle))
                                        xtables_error(OTHER_PROBLEM,
                                                "Can't set policy `%s'"
                                                " on `%s' line %u: %s\n",
                                                policy, chain, line,
-                                               ops->strerror(errno));
+                                               cb->ops->strerror(errno));
                        }
 
                        ret = 1;
@@ -358,19 +361,19 @@ iptables_restore_main(int argc, char *argv[])
 
                        add_param_to_argv(parsestart, line);
 
-                       DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
+                       DEBUGP("calling do_command(%u, argv, &%s, handle):\n",
                                newargc, curtable);
 
                        for (a = 0; a < newargc; a++)
                                DEBUGP("argv[%u]: %s\n", a, newargv[a]);
 
-                       ret = do_command4(newargc, newargv,
+                       ret = cb->do_command(newargc, newargv,
                                         &newargv[2], &handle, true);
 
                        free_argv();
                        fflush(stdout);
                }
-               if (tablename && (strcmp(tablename, curtable) != 0))
+               if (tablename && strcmp(tablename, curtable) != 0)
                        continue;
                if (!ret) {
                        fprintf(stderr, "%s: line %u failed\n",
@@ -387,3 +390,66 @@ iptables_restore_main(int argc, char *argv[])
        fclose(in);
        return 0;
 }
+
+
+#if defined ENABLE_IPV4
+struct iptables_restore_cb ipt_restore_cb = {
+       .ops            = &iptc_ops,
+       .for_each_chain = for_each_chain4,
+       .flush_entries  = flush_entries4,
+       .delete_chain   = delete_chain4,
+       .do_command     = do_command4,
+};
+
+int
+iptables_restore_main(int argc, char *argv[])
+{
+       int c;
+
+       iptables_globals.program_name = "iptables-restore";
+       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
+
+       return ip46tables_restore_main(&ipt_restore_cb, argc, argv);
+}
+#endif
+
+#if defined ENABLE_IPV6
+struct iptables_restore_cb ip6t_restore_cb = {
+       .ops            = &ip6tc_ops,
+       .for_each_chain = for_each_chain6,
+       .flush_entries  = flush_entries6,
+       .delete_chain   = delete_chain6,
+       .do_command     = do_command6,
+};
+
+int
+ip6tables_restore_main(int argc, char *argv[])
+{
+       int c;
+
+       ip6tables_globals.program_name = "ip6tables-restore";
+       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
+
+       return ip46tables_restore_main(&ip6t_restore_cb, argc, argv);
+}
+#endif