diff options
author | Marc Boucher <marc@mbsi.ca> | 2000-03-20 06:03:29 +0000 |
---|---|---|
committer | Marc Boucher <marc@mbsi.ca> | 2000-03-20 06:03:29 +0000 |
commit | e6869a8f59d779ff4d5a0984c86d80db70784962 (patch) | |
tree | cbaf2a4e3f8249de3967b959a214c27ff5fdee2a /iptables-restore.c |
reorganized tree after kernel merge
Diffstat (limited to 'iptables-restore.c')
-rw-r--r-- | iptables-restore.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/iptables-restore.c b/iptables-restore.c new file mode 100644 index 00000000..9b4ece29 --- /dev/null +++ b/iptables-restore.c @@ -0,0 +1,154 @@ +/* Code to restore the iptables state, from file by iptables-save. */ +#include <getopt.h> +#include <sys/errno.h> +#include <string.h> +#include <stdio.h> +#include "packet-filter/userspace/iptables.h" +#include "packet-filter/userspace/libiptc/libiptc.h" + +/* Keeping track of external matches and targets. */ +static struct option options[] = { + { "binary", 1, 0, 'b' }, + { "counters", 1, 0, 'c' }, + { "verbose", 1, 0, 'v' }, + { "help", 1, 0, 'h' }, + { 0 } +}; + +static void print_usage(const char *name, const char *version) __attribute__((noreturn)); + +static void print_usage(const char *name, const char *version) +{ + fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n", name); + exit(1); +} + +static int clean_slate(iptc_handle_t *handle) +{ + /* Skip over builtins. */ + const char *i, *last = IPTC_LABEL_OUTPUT; + + /* Be careful iterating: it isn't safe during delete. */ + /* Re-iterate after each delete successful */ + while ((i = iptc_next_chain(last, handle)) != NULL) { + if (!iptc_flush_entries(i, handle) + || !iptc_delete_chain(i, handle)) + return 0; + } + return 1; +} + +int main(int argc, char *argv[]) +{ + iptc_handle_t handle; + char buffer[10240]; + int counters = 0, binary = 0, verbose = 0; + unsigned int line = 0; + int c; + const char *chain; + FILE *in; + + program_name = "iptables-restore"; + program_version = NETFILTER_VERSION; + + /* Don't use getopt here; it would interfere 8-(. */ + if (optind == argc - 1) { + in = fopen(argv[optind], "r"); + if (!in) { + fprintf(stderr, "Can't open %s: %s", argv[optind], + strerror(errno)); + exit(1); + } + } + else if (optind < argc) { + fprintf(stderr, "Unknown arguments found on commandline"); + exit(1); + } + else in = stdin; + + handle = iptc_init(); + if (!handle) + exit_error(VERSION_PROBLEM, + "can't initialize iptables-restore: %s", + iptc_strerror(errno)); + + if (!clean_slate(&handle)) + exit_error(OTHER_PROBLEM, "Deleting old chains: %s", + iptc_strerror(errno)); + + /* Grab standard input. */ + while (fgets(buffer, sizeof(buffer), in)) { + int ret; + + line++; + if (buffer[0] == '\n') continue; + else if (buffer[0] == '#') { + if (verbose) fputs(buffer, stdout); + continue; + } else if (strcmp(buffer, "COMMIT\n") == 0) + ret = iptc_commit(&handle); + else if (buffer[0] == ':') { + /* New chain. */ + char *chain, *policy; + + /* FIXME: Don't ignore counters. */ + chain = strtok(buffer+1, " \t\n"); + if (!chain) { + exit_error(PARAMETER_PROBLEM, + "%s: line %u chain name invalid\n", + program_name, line); + exit(1); + } + policy = strtok(NULL, " \t\n"); + if (!policy) { + exit_error(PARAMETER_PROBLEM, + "%s: line %u policy invalid\n", + program_name, line); + exit(1); + } + if (strcmp(policy, "-") != 0 + && !iptc_set_policy(chain, policy, &handle)) + exit_error(OTHER_PROBLEM, + "Can't set policy `%s'" + " on `%s' line %u: %s\n", + chain, policy, line, + iptc_strerror(errno)); + } else { + char *newargv[1024]; + int i; + char *ptr = buffer; + + /* FIXME: Don't ignore counters. */ + if (buffer[0] == '[') { + ptr = strchr(buffer, ']'); + if (!ptr) + exit_error(PARAMETER_PROBLEM, + "Bad line %u: need ]\n", + line); + } + + /* strtok: a function only a coder could love */ + newargv[0] = argv[0]; + for (i = 1; i < sizeof(newargv)/sizeof(char *); i++) { + if (!(newargv[i] = strtok(ptr, " \t\n"))) + break; + ptr = NULL; + } + if (i == sizeof(newargv)/sizeof(char *)) { + fprintf(stderr, + "%s: line %u too many arguments\n", + program_name, line); + exit(1); + } + + ret = do_command(i, newargv, &handle); + } + if (!ret) { + fprintf(stderr, "%s: line %u failed\n", + program_name, line); + exit(1); + } + } + + return 0; +} |