diff options
-rw-r--r-- | iptables-save.c | 155 |
1 files changed, 102 insertions, 53 deletions
diff --git a/iptables-save.c b/iptables-save.c index 2a86718..00da8df 100644 --- a/iptables-save.c +++ b/iptables-save.c @@ -7,11 +7,13 @@ #include "packet-match/userspace/libiptc/libiptc.h" #include "packet-match/userspace/iptables.h" -/* Keeping track of external matches and targets. */ +static int binary = 0, counters = 0; + static struct option options[] = { - { "binary", 1, 0, 'b' }, - { "counters", 1, 0, 'c' }, - { "dump", 1, 0, 'd' }, + { "binary", 0, 0, 'b' }, + { "counters", 0, 0, 'c' }, + { "dump", 0, 0, 'd' }, + { "table", 1, 0, 't' }, { 0 } }; @@ -164,52 +166,56 @@ static void print_rule(const struct ipt_entry *e, int counters) /* Debugging prototype. */ extern void dump_entries(iptc_handle_t handle); -/* Format: - * :Chain name POLICY packets bytes - * rule - */ -int main(int argc, char *argv[]) +static int for_each_table(int (*func)(const char *tablename)) { - iptc_handle_t h; - const char *chain = NULL; - int c; - int binary = 0, counters = 0; + int ret = 1; + FILE *procfile; + char tablename[IPT_TABLE_MAXNAMELEN+1]; + + procfile = fopen("/proc/net/ip_tables_names", O_RDONLY); + if (!procfile) + return 0; + + while (fgets(tablename, sizeof(tablename), procfile)) { + if (tablename[strlen(tablename) - 1] != '\n') + exit_error(OTHER_PROBLEM, + "Badly formed tablename `%s'\n", + tablename); + tablename[strlen(tablename) - 1] = '\0'; + ret &= func(tablename); + } - program_name = "iptables-save"; - program_version = NETFILTER_VERSION; + return ret; +} + - while ((c = getopt_long(argc, argv, "bc", options, NULL)) != -1) { - switch (c) { - case 'b': - binary = 1; - break; +static int dump_table(const char *tablename) +{ + iptc_handle_t h; - case 'c': - counters = 1; - break; + if (!tablename) + return for_each_table(&dump_table); - case 'd': - /* Debugging dump. */ - h = iptc_init(); - if (!h) - exit_error(OTHER_PROBLEM, "iptc_init: %s\n", - iptc_strerror(errno)); - dump_entries(h); - exit(0); - } - } + /* Debugging dump. */ + h = iptc_init(tablename); + if (!h) + exit_error(OTHER_PROBLEM, "iptc_init: %s\n", + iptc_strerror(errno)); + dump_entries(h); +} + +static int do_output(const char *tablename) +{ + iptc_handle_t h; + const char *chain = NULL; - if (optind < argc) { - fprintf(stderr, "Unknown arguments found on commandline"); - exit(1); - } + if (!tablename) + return for_each_table(&do_output); - h = iptc_init(); - if (!h) { - fprintf(stderr, "Can't initialize: %s\n", - iptc_strerror(errno)); - exit(1); - } + h = iptc_init(tablename); + if (!h) + exit_error(OTHER_PROBLEM, "Can't initialize: %s\n", + iptc_strerror(errno)); if (!binary) { time_t now = time(NULL); @@ -218,7 +224,9 @@ int main(int argc, char *argv[]) NETFILTER_VERSION, ctime(&now)); /* Dump out chain names */ - while ((chain = iptc_next_chain(chain, &h)) != NULL) { + for (chain = iptc_first_chain(&h); + chain; + chain = iptc_next_chain(&h)) { printf(":%s ", chain); if (iptc_builtin(chain, &h)) { struct ipt_counters count; @@ -231,19 +239,21 @@ int main(int argc, char *argv[]) } /* Dump out rules */ - while ((chain = iptc_next_chain(chain, &h)) != NULL) { + for (chain = iptc_first_chain(&h); + chain; + chain = iptc_next_chain(&h)) { unsigned int i; for (i = 0; i < iptc_num_rules(chain, &h); i++) { const struct ipt_entry *e = iptc_get_rule(chain, i, &h); - if (!e) { - fprintf(stderr, - "Can't read rule %u of chain %s: %s\n", - i, chain, iptc_strerror(errno)); - exit(1); - } + if (!e) + exit_error(OTHER_PROBLEM, + "Can't read rule %u" + " of chain %s: %s\n", + i, chain, + iptc_strerror(errno)); print_rule(e, counters); } } @@ -253,9 +263,48 @@ int main(int argc, char *argv[]) printf("# Completed on %s", ctime(&now)); } else { /* Binary, huh? OK. */ - fprintf(stderr, "Binary NYI\n"); + exit_error(OTHER_PROBLEM, "Binary NYI\n"); + } + + return 1; +} + +/* Format: + * :Chain name POLICY packets bytes + * rule + */ +int main(int argc, char *argv[]) +{ + const char *tablename = NULL; + int c; + + program_name = "iptables-save"; + program_version = NETFILTER_VERSION; + + while ((c = getopt_long(argc, argv, "bc", options, NULL)) != -1) { + switch (c) { + case 'b': + binary = 1; + break; + + case 'c': + counters = 1; + break; + + case 't': + /* Select specific table. */ + tablename = optarg; + break; + case 'd': + dump_table(tablename); + exit(0); + } + } + + if (optind < argc) { + fprintf(stderr, "Unknown arguments found on commandline"); exit(1); } - return 0; + return !do_output(tablename); } |