diff options
Diffstat (limited to 'iptables/xtables-restore.c')
-rw-r--r-- | iptables/xtables-restore.c | 241 |
1 files changed, 77 insertions, 164 deletions
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index fb2ac8b5..23cd3498 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -61,11 +61,10 @@ static void print_usage(const char *name, const char *version) static const struct nft_xt_restore_cb restore_cb = { .commit = nft_commit, .abort = nft_abort, - .table_new = nft_table_new, - .table_flush = nft_table_flush, + .table_flush = nft_cmd_table_flush, .do_command = do_commandx, - .chain_set = nft_chain_set, - .chain_restore = nft_chain_restore, + .chain_set = nft_cmd_chain_set, + .chain_restore = nft_cmd_chain_restore, }; struct nft_xt_restore_state { @@ -85,8 +84,10 @@ static void xtables_restore_parse_line(struct nft_handle *h, if (buffer[0] == '\n') return; else if (buffer[0] == '#') { - if (verbose) + if (verbose) { fputs(buffer, stdout); + fflush(stdout); + } return; } else if (state->in_table && (strncmp(buffer, "COMMIT", 6) == 0) && @@ -114,22 +115,26 @@ static void xtables_restore_parse_line(struct nft_handle *h, 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); + "%s: line %u table name invalid", + xt_params->program_name, line); state->curtable = nft_table_builtin_find(h, table); if (!state->curtable) xtables_error(PARAMETER_PROBLEM, - "%s: line %u table name '%s' invalid\n", - xt_params->program_name, line, table); + "%s: line %u table name '%s' invalid", + xt_params->program_name, line, table); if (p->tablename && (strcmp(p->tablename, table) != 0)) return; + /* implicit commit if no explicit COMMIT supported */ + if (!p->commit) + cb->commit(h); + if (h->noflush == 0) { DEBUGP("Cleaning all chains of table '%s'\n", table); if (cb->table_flush) - cb->table_flush(h, table); + cb->table_flush(h, table, verbose); } ret = 1; @@ -147,37 +152,33 @@ static void xtables_restore_parse_line(struct nft_handle *h, 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); + "%s: line %u chain name invalid", + xt_params->program_name, line); - if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN) - xtables_error(PARAMETER_PROBLEM, - "Invalid chain name `%s' (%u chars max)", - chain, XT_EXTENSION_MAXNAMELEN - 1); + xtables_announce_chain(chain); + assert_valid_chain_name(chain); 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); + "%s: line %u policy invalid", + xt_params->program_name, line); if (nft_chain_builtin_find(state->curtable, chain)) { - if (counters) { - char *ctrs; - ctrs = strtok(NULL, " \t\n"); + char *ctrs = strtok(NULL, " \t\n"); - if (!ctrs || !parse_counters(ctrs, &count)) - xtables_error(PARAMETER_PROBLEM, - "invalid policy counters for chain '%s'\n", - chain); - - } + if ((!ctrs && counters) || + (ctrs && !parse_counters(ctrs, &count))) + xtables_error(PARAMETER_PROBLEM, + "invalid policy counters for chain '%s'", + chain); if (cb->chain_set && cb->chain_set(h, state->curtable->name, - chain, policy, &count) < 0) { + chain, policy, + counters ? &count : NULL) < 0) { xtables_error(OTHER_PROBLEM, - "Can't set policy `%s' on `%s' line %u: %s\n", + "Can't set policy `%s' on `%s' line %u: %s", policy, chain, line, strerror(errno)); } @@ -186,13 +187,13 @@ static void xtables_restore_parse_line(struct nft_handle *h, } else if (cb->chain_restore(h, chain, state->curtable->name) < 0 && errno != EEXIST) { xtables_error(PARAMETER_PROBLEM, - "cannot create chain '%s' (%s)\n", + "cannot create chain '%s' (%s)", chain, strerror(errno)); } else if (h->family == NFPROTO_BRIDGE && - !ebt_set_user_chain_policy(h, state->curtable->name, + !ebt_cmd_user_chain_policy(h, state->curtable->name, chain, policy)) { xtables_error(OTHER_PROBLEM, - "Can't set policy `%s' on `%s' line %u: %s\n", + "Can't set policy `%s' on `%s' line %u: %s", policy, chain, line, strerror(errno)); } @@ -201,11 +202,15 @@ static void xtables_restore_parse_line(struct nft_handle *h, char *pcnt = NULL; char *bcnt = NULL; char *parsestart = buffer; + int i; add_argv(&state->av_store, xt_params->program_name, 0); add_argv(&state->av_store, "-t", 0); add_argv(&state->av_store, state->curtable->name, 0); + for (i = 0; !h->noflush && i < verbose; i++) + add_argv(&state->av_store, "-v", 0); + tokenize_rule_counters(&parsestart, &pcnt, &bcnt, line); if (counters && pcnt && bcnt) { add_argv(&state->av_store, "--set-counters", 0); @@ -242,105 +247,25 @@ static void xtables_restore_parse_line(struct nft_handle *h, (strcmp(p->tablename, state->curtable->name) != 0)) return; if (!ret) { - fprintf(stderr, "%s: line %u failed\n", - xt_params->program_name, line); + fprintf(stderr, "%s: line %u failed", + xt_params->program_name, h->error.lineno); + if (errno) + fprintf(stderr, ": %s.", nft_strerror(errno)); + fprintf(stderr, "\n"); exit(1); } } -/* Return true if given iptables-restore line will require a full cache. - * Typically these are commands referring to an existing rule - * (either by number or content) or commands listing the ruleset. */ -static bool cmd_needs_full_cache(char *cmd) -{ - char c, chain[32]; - int rulenum, mcount; - - mcount = sscanf(cmd, "-%c %31s %d", &c, chain, &rulenum); - - if (mcount == 3) - return true; - if (mcount < 1) - return false; - - switch (c) { - case 'D': - case 'C': - case 'S': - case 'L': - case 'Z': - return true; - } - - return false; -} - -#define PREBUFSIZ 65536 - void xtables_restore_parse(struct nft_handle *h, const struct nft_xt_restore_parse *p) { struct nft_xt_restore_state state = {}; - char preload_buffer[PREBUFSIZ] = {}, buffer[10240] = {}, *ptr; + char buffer[10240] = {}; - if (!h->noflush) { - nft_fake_cache(h); - } else { - ssize_t pblen = sizeof(preload_buffer); - bool do_cache = false; - - ptr = preload_buffer; - while (fgets(buffer, sizeof(buffer), p->in)) { - size_t blen = strlen(buffer); - - /* Drop trailing newline; xtables_restore_parse_line() - * uses strtok() which replaces them by nul-characters, - * causing unpredictable string delimiting in - * preload_buffer. - * Unless this is an empty line which would fold into a - * spurious EoB indicator (double nul-char). */ - if (buffer[blen - 1] == '\n' && blen > 1) - buffer[blen - 1] = '\0'; - else - blen++; - - pblen -= blen; - if (pblen <= 0) { - /* buffer exhausted */ - do_cache = true; - break; - } - - if (cmd_needs_full_cache(buffer)) { - do_cache = true; - break; - } - - /* copy string including terminating nul-char */ - memcpy(ptr, buffer, blen); - ptr += blen; - buffer[0] = '\0'; - } - - if (do_cache) - nft_build_cache(h, NULL); - } + if (!verbose && !h->noflush) + nft_cache_level_set(h, NFT_CL_FAKE, NULL); line = 0; - ptr = preload_buffer; - while (*ptr) { - size_t len = strlen(ptr); - - h->error.lineno = ++line; - DEBUGP("%s: buffered line %d: '%s'\n", __func__, line, ptr); - xtables_restore_parse_line(h, p, &state, ptr); - ptr += len + 1; - } - if (*buffer) { - h->error.lineno = ++line; - DEBUGP("%s: overrun line %d: '%s'\n", __func__, line, buffer); - xtables_restore_parse_line(h, p, &state, buffer); - } while (fgets(buffer, sizeof(buffer), p->in)) { h->error.lineno = ++line; DEBUGP("%s: input line %d: '%s'\n", __func__, line, buffer); @@ -359,16 +284,13 @@ void xtables_restore_parse(struct nft_handle *h, static int xtables_restore_main(int family, const char *progname, int argc, char *argv[]) { - const struct builtin_table *tables; - struct nft_handle h = { - .family = family, - .restore = true, - }; - int c; struct nft_xt_restore_parse p = { .commit = true, .cb = &restore_cb, }; + bool noflush = false; + struct nft_handle h; + int c; line = 0; @@ -381,7 +303,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) exit(1); } - while ((c = getopt_long(argc, argv, "bcvVthnM:T:46wW", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "bcvVthnM:T:wW", options, NULL)) != -1) { switch (c) { case 'b': fprintf(stderr, "-b/--binary option is not implemented\n"); @@ -390,10 +312,10 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) counters = 1; break; case 'v': - verbose = 1; + verbose++; break; case 'V': - printf("%s v%s (nf_tables)\n", prog_name, prog_vers); + printf("%s v%s\n", prog_name, prog_vers); exit(0); case 't': p.testing = 1; @@ -402,7 +324,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) print_usage(prog_name, PACKAGE_VERSION); exit(0); case 'n': - h.noflush = 1; + noflush = true; break; case 'M': xtables_modprobe_program = optarg; @@ -410,13 +332,6 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) case 'T': p.tablename = optarg; break; - case '4': - h.family = AF_INET; - break; - case '6': - h.family = AF_INET6; - xtables_set_nfproto(AF_INET6); - break; case 'w': /* fallthrough. Ignored by xt-restore */ case 'W': if (!optarg && xs_has_arg(argc, argv)) @@ -444,37 +359,39 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) p.in = stdin; } + init_extensions(); switch (family) { case NFPROTO_IPV4: - case NFPROTO_IPV6: /* fallthough, same table */ - tables = xtables_ipv4; -#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) - init_extensions(); init_extensions4(); -#endif + break; + case NFPROTO_IPV6: + init_extensions6(); break; case NFPROTO_ARP: - tables = xtables_arp; + init_extensionsa(); break; case NFPROTO_BRIDGE: - tables = xtables_bridge; + init_extensionsb(); break; default: fprintf(stderr, "Unknown family %d\n", family); return 1; } - if (nft_init(&h, tables) < 0) { + if (nft_init(&h, family) < 0) { fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", xtables_globals.program_name, xtables_globals.program_version, strerror(errno)); exit(EXIT_FAILURE); } + h.noflush = noflush; + h.restore = true; xtables_restore_parse(&h, &p); nft_fini(&h); + xtables_fini(); fclose(p.in); return 0; } @@ -491,24 +408,17 @@ int xtables_ip6_restore_main(int argc, char *argv[]) argc, argv); } -static int ebt_table_flush(struct nft_handle *h, const char *table) -{ - /* drop any pending policy rule add/removal jobs */ - nft_abort_policy_rule(h, table); - return nft_table_flush(h, table); -} - static const struct nft_xt_restore_cb ebt_restore_cb = { .commit = nft_bridge_commit, - .table_new = nft_table_new, - .table_flush = ebt_table_flush, + .table_flush = nft_cmd_table_flush, .do_command = do_commandeb, - .chain_set = nft_chain_set, - .chain_restore = nft_chain_restore, + .chain_set = nft_cmd_chain_set, + .chain_restore = nft_cmd_chain_restore, }; static const struct option ebt_restore_options[] = { {.name = "noflush", .has_arg = 0, .val = 'n'}, + {.name = "verbose", .has_arg = 0, .val = 'v'}, { 0 } }; @@ -522,15 +432,18 @@ int xtables_eb_restore_main(int argc, char *argv[]) struct nft_handle h; int c; - while ((c = getopt_long(argc, argv, "n", + while ((c = getopt_long(argc, argv, "nv", ebt_restore_options, NULL)) != -1) { switch(c) { case 'n': noflush = 1; break; + case 'v': + verbose++; + break; default: fprintf(stderr, - "Usage: ebtables-restore [ --noflush ]\n"); + "Usage: ebtables-restore [ --verbose ] [ --noflush ]\n"); exit(1); break; } @@ -539,18 +452,17 @@ int xtables_eb_restore_main(int argc, char *argv[]) nft_init_eb(&h, "ebtables-restore"); h.noflush = noflush; xtables_restore_parse(&h, &p); - nft_fini(&h); + nft_fini_eb(&h); return 0; } static const struct nft_xt_restore_cb arp_restore_cb = { .commit = nft_commit, - .table_new = nft_table_new, - .table_flush = nft_table_flush, - .do_command = do_commandarp, - .chain_set = nft_chain_set, - .chain_restore = nft_chain_restore, + .table_flush = nft_cmd_table_flush, + .do_command = do_commandx, + .chain_set = nft_cmd_chain_set, + .chain_restore = nft_cmd_chain_restore, }; int xtables_arp_restore_main(int argc, char *argv[]) @@ -564,6 +476,7 @@ int xtables_arp_restore_main(int argc, char *argv[]) nft_init_arp(&h, "arptables-restore"); xtables_restore_parse(&h, &p); nft_fini(&h); + xtables_fini(); return 0; } |