From 922508e9156327ccb8e35243781cf85f5787ee40 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 19 Jul 2018 18:32:09 +0200 Subject: 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 Signed-off-by: Florian Westphal --- iptables/xtables-restore.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) (limited to 'iptables/xtables-restore.c') 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 #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; +} -- cgit v1.2.3