Introduce struct iptables_restore_cb and merge ip6tables-restore with iptables-restore. Signed-off-by: Phil Sutter <phil@xxxxxx> --- iptables/Makefile.am | 6 +- iptables/ip6tables-restore.c | 391 ----------------------------------- iptables/iptables-restore.c | 154 ++++++++++---- 3 files changed, 113 insertions(+), 438 deletions(-) delete mode 100644 iptables/ip6tables-restore.c diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 581dc32ba846b..a21dadb7994f5 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -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 index 3706b981a806a..0000000000000 --- a/iptables/ip6tables-restore.c +++ /dev/null @@ -1,391 +0,0 @@ -/* Code to restore the iptables state, from file by ip6tables-save. - * Author: Andras Kis-Szabo <kisza@xxxxxxxxxx> - * - * based on iptables-restore - * Authors: - * Harald Welte <laforge@xxxxxxxxxxxx> - * Rusty Russell <rusty@xxxxxxxxxxxxxxxx> - * 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; -} diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c index daee5fd99564a..575e619cc30db 100644 --- a/iptables/iptables-restore.c +++ b/iptables/iptables-restore.c @@ -12,10 +12,13 @@ #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 -- 2.18.0