diff options
author | Phil Sutter <phil@nwl.cc> | 2018-07-19 18:32:09 +0200 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2018-07-19 23:13:02 +0200 |
commit | 922508e9156327ccb8e35243781cf85f5787ee40 (patch) | |
tree | ba9f497f248cb16216ae69972b694f162d602424 /iptables/xtables-restore.c | |
parent | 25ef90814a991e80384d4369565c6decadfcd409 (diff) |
xtables: implement ebtables-{save,restore}
The code for ebtables-restore was derived from legacy code,
ebtables-save is actually a new implementation using the existing
infrastructure and trying to adhere to legacy perl script output
formatting as much as possible.
This introduces a new format flag (FMT_EBT_SAVE) to allow
nft_bridge_save_rule() to distinguish between ruleset listing (i.e.,
ebtables -L) and saving via ebtables-save - the two differ in how
counters are being formatted. Odd, but that's how it is.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'iptables/xtables-restore.c')
-rw-r--r-- | iptables/xtables-restore.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index f9392457..5c0ae98e 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -16,6 +16,7 @@ #include "libiptc/libiptc.h" #include "xtables-multi.h" #include "nft.h" +#include "nft-bridge.h" #include <libnftnl/chain.h> #ifdef DEBUG @@ -581,3 +582,116 @@ int xtables_ip6_restore_main(int argc, char *argv[]) return xtables_restore_main(NFPROTO_IPV6, "ip6tables-restore", argc, argv); } + +static const char *ebt_parse_table_name(const char *input) +{ + if (!strcmp(input, "broute")) + xtables_error(PARAMETER_PROBLEM, "broute table not supported"); + else if (!strcmp(input, "filter")) + return "filter"; + else if (!strcmp(input, "nat")) + return "nat"; + + xtables_error(PARAMETER_PROBLEM, "table '%s' not recognized", input); +} + +static const char *ebt_parse_policy_name(const char *input) +{ + int i; + + for (i = 0; i < NUM_STANDARD_TARGETS; i++) { + if (!strcmp(input, ebt_standard_targets[i])) { + int policy = -i - 1; + + if (policy == EBT_CONTINUE) + i = NUM_STANDARD_TARGETS; + break; + } + } + if (i == NUM_STANDARD_TARGETS) + xtables_error(PARAMETER_PROBLEM, "invalid policy specified"); + return ebt_standard_targets[i]; +} + +static const struct option ebt_restore_options[] = { + {.name = "noflush", .has_arg = 0, .val = 'n'}, + { 0 } +}; + +int xtables_eb_restore_main(int argc, char *argv[]) +{ + char buffer[10240]; + int i, ret, c, flush = 1; + const char *table = NULL; + struct nft_handle h; + + nft_init_eb(&h); + + while ((c = getopt_long(argc, argv, "n", + ebt_restore_options, NULL)) != -1) { + switch(c) { + case 'n': + flush = 0; + break; + default: + fprintf(stderr, + "Usage: ebtables-restore [ --noflush ]\n"); + exit(1); + break; + } + } + + while (fgets(buffer, sizeof(buffer), stdin)) { + if (buffer[0] == '#' || buffer[0] == '\n') + continue; + if (buffer[0] == '*') { + table = ebt_parse_table_name(buffer + 1); + if (flush) + nft_table_flush(&h, table); + continue; + } else if (!table) { + xtables_error(PARAMETER_PROBLEM, "no table specified"); + } + if (buffer[0] == ':') { + char *ch, *chain = buffer; + const char *policy; + + if (!(ch = strchr(buffer, ' '))) + xtables_error(PARAMETER_PROBLEM, "no policy specified"); + *ch = '\0'; + policy = ebt_parse_policy_name(ch + 1); + + /* No need to check chain name for consistency, since + * we're supposed to be reading an automatically generated + * file. */ + if (ebt_get_current_chain(chain) < 0) + nft_chain_user_add(&h, chain, table); + ret = nft_chain_set(&h, table, chain, policy, NULL); + if (ret < 0) + xtables_error(PARAMETER_PROBLEM, "Wrong policy"); + continue; + } + + newargc = 0; + add_argv("ebtables"); + add_argv("-t"); + add_argv(table); + add_param_to_argv(buffer); + + DEBUGP("calling do_commandeb(%u, argv, &%s, handle):\n", + newargc, table); + + for (i = 0; i < newargc; i++) + DEBUGP("argv[%u]: %s\n", i, newargv[i]); + + optind = 0; /* Setting optind = 1 causes serious annoyances */ + if (!do_commandeb(&h, newargc, newargv, &newargv[2])) + return 1; + } + + if (!nft_commit(&h)) { + fprintf(stderr, "%s\n", nft_strerror(errno)); + return 1; + } + return 0; +} |