[iptables PATCH 10/23] xtables: Implement arptables-{save,restore}

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux