This adds C implementations for arptables-save and -restore in compat layer based on the two perl scripts in legacy arptables repository. To share common code, introduce nft_init_arp() analogous to nft_init_eb() introduced earlier. Signed-off-by: Phil Sutter <phil@xxxxxx> --- iptables/Makefile.am | 2 + iptables/nft-arp.c | 49 +++++++++----- iptables/nft.h | 1 + iptables/xtables-arp-standalone.c | 17 +---- iptables/xtables-arp.c | 36 ++++++++--- iptables/xtables-multi.h | 2 + iptables/xtables-nft-multi.c | 4 ++ iptables/xtables-restore.c | 104 ++++++++++++++++++++++++++++++ iptables/xtables-save.c | 39 +++++++++++ 9 files changed, 214 insertions(+), 40 deletions(-) diff --git a/iptables/Makefile.am b/iptables/Makefile.am index 2cbd586128140..d0218ddc80487 100644 --- a/iptables/Makefile.am +++ b/iptables/Makefile.am @@ -81,6 +81,8 @@ x_sbin_links = iptables-nft iptables-nft-restore iptables-nft-save \ iptables-translate ip6tables-translate \ iptables-restore-translate ip6tables-restore-translate \ arptables-nft arptables \ + arptables-nft-restore arptables-restore \ + arptables-nft-save arptables-save \ ebtables-nft ebtables \ ebtables-nft-restore ebtables-restore \ ebtables-nft-save ebtables-save \ diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c index 5cabb93e4a9bc..f5b05f864963a 100644 --- a/iptables/nft-arp.c +++ b/iptables/nft-arp.c @@ -436,7 +436,7 @@ static void nft_arp_print_header(unsigned int format, const char *chain, } } -static void nft_arp_print_rule_details(struct arpt_entry *fw, +static void nft_arp_print_rule_details(const struct arpt_entry *fw, unsigned int format) { char buf[BUFSIZ]; @@ -579,35 +579,42 @@ after_devdst: } static void -nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) +nft_arp_save_rule(const void *data, unsigned int format) { - struct iptables_command_state cs = {}; - - nft_arp_rule_to_cs(r, &cs); - - if (format & FMT_LINENUMBERS) - printf("%u ", num); + const struct iptables_command_state *cs = data; - nft_arp_print_rule_details(&cs.arp, format); + nft_arp_print_rule_details(&cs->arp, format); - if (cs.jumpto != NULL && strcmp(cs.jumpto, "") != 0) { - printf("-j %s", cs.jumpto); - } else if (cs.target) { - printf("-j %s", cs.target->name); - cs.target->print(&cs.arp, cs.target->t, format & FMT_NUMERIC); + if (cs->jumpto != NULL && strcmp(cs->jumpto, "") != 0) { + printf("-j %s", cs->jumpto); + } else if (cs->target) { + printf("-j %s", cs->target->name); + cs->target->print(&cs->arp, cs->target->t, format & FMT_NUMERIC); } if (!(format & FMT_NOCOUNTS)) { printf(", pcnt="); - xtables_print_num(cs.arp.counters.pcnt, format); + xtables_print_num(cs->arp.counters.pcnt, format); printf("-- bcnt="); - xtables_print_num(cs.arp.counters.bcnt, format); + xtables_print_num(cs->arp.counters.bcnt, format); } if (!(format & FMT_NONEWLINE)) fputc('\n', stdout); } +static void +nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) +{ + struct iptables_command_state cs = {}; + + if (format & FMT_LINENUMBERS) + printf("%u ", num); + + nft_arp_rule_to_cs(r, &cs); + nft_arp_save_rule(&cs, format); +} + static bool nft_arp_is_same(const void *data_a, const void *data_b) { @@ -655,6 +662,13 @@ static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r, return true; } +static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy) +{ + const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + + printf(":%s %s\n", chain, policy ?: "-"); +} + struct nft_family_ops nft_family_ops_arp = { .add = nft_arp_add, .is_same = nft_arp_is_same, @@ -664,8 +678,9 @@ struct nft_family_ops nft_family_ops_arp = { .parse_immediate = nft_arp_parse_immediate, .print_header = nft_arp_print_header, .print_rule = nft_arp_print_rule, - .save_rule = NULL, + .save_rule = nft_arp_save_rule, .save_counters = NULL, + .save_chain = nft_arp_save_chain, .post_parse = NULL, .rule_to_cs = nft_arp_rule_to_cs, .clear_cs = NULL, diff --git a/iptables/nft.h b/iptables/nft.h index a479cf072089d..491076081adf3 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -143,6 +143,7 @@ const char *nft_strerror(int err); /* For xtables.c */ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, bool restore); /* For xtables-arptables.c */ +int nft_init_arp(struct nft_handle *h); int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table); /* For xtables-eb.c */ int nft_init_eb(struct nft_handle *h); diff --git a/iptables/xtables-arp-standalone.c b/iptables/xtables-arp-standalone.c index 6553d28f6d95d..b3ade3eaaebec 100644 --- a/iptables/xtables-arp-standalone.c +++ b/iptables/xtables-arp-standalone.c @@ -47,22 +47,9 @@ int xtables_arp_main(int argc, char *argv[]) { int ret; char *table = "filter"; - struct nft_handle h = { - .family = NFPROTO_ARP, - }; + struct nft_handle h; - arptables_globals.program_name = "arptables"; - ret = xtables_init_all(&arptables_globals, NFPROTO_ARP); - if (ret < 0) { - fprintf(stderr, "%s/%s Failed to initialize arptables-compat\n", - arptables_globals.program_name, - arptables_globals.program_version); - exit(1); - } - -#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) - init_extensionsa(); -#endif + nft_init_arp(&h); ret = do_commandarp(&h, argc, argv, &table); if (ret) diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c index ce9e618b7049b..d73856f5c66b1 100644 --- a/iptables/xtables-arp.c +++ b/iptables/xtables-arp.c @@ -929,6 +929,34 @@ delete_entry(const char *chain, return ret; } +int nft_init_arp(struct nft_handle *h) +{ + arptables_globals.program_name = "arptables"; + if (xtables_init_all(&arptables_globals, NFPROTO_ARP) < 0) { + fprintf(stderr, "%s/%s Failed to initialize arptables-compat\n", + arptables_globals.program_name, + arptables_globals.program_version); + exit(1); + } + +#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) + init_extensionsa(); +#endif + + memset(h, 0, sizeof(*h)); + h->family = NFPROTO_ARP; + + if (nft_init(h, xtables_arp) < 0) + xtables_error(OTHER_PROBLEM, + "Could not initialize nftables layer."); + + h->ops = nft_family_ops_lookup(h->family); + if (h->ops == NULL) + xtables_error(PARAMETER_PROBLEM, "Unknown family"); + + return 0; +} + int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) { struct iptables_command_state cs = { @@ -1361,14 +1389,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) "chain name `%s' too long (must be under %i chars)", chain, ARPT_FUNCTION_MAXNAMELEN); - if (nft_init(h, xtables_arp) < 0) - xtables_error(OTHER_PROBLEM, - "Could not initialize nftables layer."); - - h->ops = nft_family_ops_lookup(h->family); - if (h->ops == NULL) - xtables_error(PARAMETER_PROBLEM, "Unknown family"); - if (command == CMD_APPEND || command == CMD_DELETE || command == CMD_INSERT diff --git a/iptables/xtables-multi.h b/iptables/xtables-multi.h index 8445761849aa1..0fedb430e1a28 100644 --- a/iptables/xtables-multi.h +++ b/iptables/xtables-multi.h @@ -15,6 +15,8 @@ extern int xtables_eb_xlate_main(int, char **); extern int xtables_ip4_xlate_restore_main(int, char **); extern int xtables_ip6_xlate_restore_main(int, char **); extern int xtables_arp_main(int, char **); +extern int xtables_arp_restore_main(int, char **); +extern int xtables_arp_save_main(int, char **); extern int xtables_eb_main(int, char **); extern int xtables_eb_restore_main(int, char **); extern int xtables_eb_save_main(int, char **); diff --git a/iptables/xtables-nft-multi.c b/iptables/xtables-nft-multi.c index d9cca088f27a8..e2b7c641f85dd 100644 --- a/iptables/xtables-nft-multi.c +++ b/iptables/xtables-nft-multi.c @@ -32,6 +32,10 @@ static const struct subcommand multi_subcommands[] = { {"ip6tables-restore-translate", xtables_ip6_xlate_restore_main}, {"arptables", xtables_arp_main}, {"arptables-nft", xtables_arp_main}, + {"arptables-restore", xtables_arp_restore_main}, + {"arptables-nft-restore", xtables_arp_restore_main}, + {"arptables-save", xtables_arp_save_main}, + {"arptables-nft-save", xtables_arp_save_main}, {"ebtables-translate", xtables_eb_xlate_main}, {"ebtables", xtables_eb_main}, {"ebtables-restore", xtables_eb_restore_main}, diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index ead61842bc360..17d4bc75e92de 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -710,3 +710,107 @@ int xtables_eb_restore_main(int argc, char *argv[]) fprintf(stderr, "%s\n", nft_strerror(errno)); return !ret; } + +static const char *arp_parse_policy_name(const char *input) +{ + const char *policy_names[] = { + "ACCEPT", + "DROP", + "RETURN", + "-", + NULL, + }; + int i; + + for (i = 0; policy_names[i]; i++) { + if (!strcmp(input, policy_names[i])) + return policy_names[i]; + } + xtables_error(PARAMETER_PROBLEM, "invalid policy '%s'", input); +} + +int xtables_arp_restore_main(int argc, char *argv[]) +{ + const char *table = NULL; + struct nft_handle h; + char buffer[10240]; + int i, ret = 1; + + nft_init_arp(&h); + + if (!nft_table_flush(&h, "filter") || !nft_commit(&h)) { + xtables_error(OTHER_PROBLEM, "initial table flush failed"); + goto out; + } + + while (fgets(buffer, sizeof(buffer), stdin)) { + if (buffer[0] == '#' || buffer[0] == '\n') + continue; + if (buffer[0] == '*') { + *strchr(buffer, '\n') = '\0'; + if (strcmp(buffer + 1, "filter")) + xtables_error(PARAMETER_PROBLEM, + "table '%s' not recognized", + buffer + 1); + table = "filter"; + /* this is strictly not necessary, but ensures default + * chains are created before later attempts are made to + * change policies */ + nft_table_new(&h, table); + continue; + } else if (!table) { + xtables_error(PARAMETER_PROBLEM, "no table specified"); + } + if (buffer[0] == ':') { + char *ch, *chain = buffer + 1; + const char *policy; + + if (!(ch = strchr(buffer, ' '))) + xtables_error(PARAMETER_PROBLEM, + "no policy specified"); + *ch = '\0'; + *strchr(ch + 1, '\n') = '\0'; + policy = arp_parse_policy_name(ch + 1); + + if (!strcmp(policy, "-")) { + nft_chain_user_add(&h, chain, table); + } else { + ret = nft_chain_set(&h, table, + chain, policy, NULL); + if (ret < 0) + xtables_error(PARAMETER_PROBLEM, + "Wrong policy"); + } + continue; + } + + newargc = 0; + add_argv("arptables"); + add_argv("-t"); + add_argv(table); + add_param_to_argv(buffer); + + DEBUGP("calling do_commandarp(handle, %u, argv, &%s):\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 */ + ret = do_commandarp(&h, newargc, newargv, &newargv[2]); + + free_argv(); + + if (!ret) + break; + } + + if (ret) + ret = nft_commit(&h); +out: + nft_fini(&h); + + if (!ret) + fprintf(stderr, "%s\n", nft_strerror(errno)); + return !ret; +} diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c index c9df51d55327f..fc51fcfeb5815 100644 --- a/iptables/xtables-save.c +++ b/iptables/xtables-save.c @@ -287,3 +287,42 @@ int xtables_eb_save_main(int argc_, char *argv_[]) nft_for_each_table(&h, __ebt_save, !!ctr); return 0; } + +int xtables_arp_save_main(int argc, char **argv) +{ + struct nft_handle h = { + .family = NFPROTO_ARP, + }; + int c; + + xtables_globals.program_name = "arptables-save"; + c = xtables_init_all(&xtables_globals, h.family); + if (c < 0) { + fprintf(stderr, "%s/%s Failed to initialize xtables\n", + xtables_globals.program_name, + xtables_globals.program_version); + exit(1); + } + + if (nft_init(&h, xtables_arp) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!nft_table_find(&h, "filter")) + return 0; + + if (!nft_is_table_compatible(&h, "filter")) { + printf("# Table `filter' is incompatible, use 'nft' tool.\n"); + return 0; + } + + printf("*filter\n"); + nft_chain_save(&h, nft_chain_dump(&h), "filter"); + nft_rule_save(&h, "filter", FMT_NOCOUNTS); + printf("\n"); + return 0; +} -- 2.18.0 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html