xtables-restore: Improve user-defined chain detection

Legacy ebtables-save does not use a policy string of '-' to denote
user-defined chains but instead lists them with a policy of ACCEPT.

In order to use ebtables_restore_parse() for ebtables-save
implementation, make use of builtin table definitions to decide whether
a given chain is a builtin one or not.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
diff --git a/iptables/nft.c b/iptables/nft.c
index ea58495..b893859 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -630,7 +630,7 @@
 }
 
 /* find if built-in table already exists */
-static struct builtin_table *
+struct builtin_table *
 nft_table_builtin_find(struct nft_handle *h, const char *table)
 {
 	int i;
@@ -651,7 +651,7 @@
 }
 
 /* find if built-in chain already exists */
-static struct builtin_chain *
+struct builtin_chain *
 nft_chain_builtin_find(struct builtin_table *t, const char *chain)
 {
 	int i;
diff --git a/iptables/nft.h b/iptables/nft.h
index 5febb9f..942cb6a 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -68,6 +68,7 @@
 int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
 int nft_table_flush(struct nft_handle *h, const char *table);
 void nft_table_new(struct nft_handle *h, const char *table);
+struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
 
 /*
  * Operations with chains.
@@ -84,6 +85,7 @@
 			 const char *chain, const char *table);
 int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname);
 int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose);
+struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain);
 
 /*
  * Operations with rule-set.
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 4e46b62..9a014cc 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -106,7 +106,7 @@
 {
 	char buffer[10240];
 	int in_table = 0;
-	char curtable[XT_TABLE_MAXNAMELEN + 1];
+	struct builtin_table *curtable = NULL;
 	const struct xtc_ops *ops = &xtc_ops;
 	struct nftnl_chain_list *chain_list = NULL;
 
@@ -156,8 +156,11 @@
 					xt_params->program_name, line);
 				exit(1);
 			}
-			strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
-			curtable[XT_TABLE_MAXNAMELEN] = '\0';
+			curtable = nft_table_builtin_find(h, table);
+			if (!curtable)
+				xtables_error(PARAMETER_PROBLEM,
+					"%s: line %u table name '%s' invalid\n",
+					xt_params->program_name, line, table);
 
 			if (p->tablename && (strcmp(p->tablename, table) != 0))
 				continue;
@@ -191,7 +194,7 @@
 
 			if (noflush == 0) {
 				if (cb->chain_del)
-					cb->chain_del(chain_list, curtable,
+					cb->chain_del(chain_list, curtable->name,
 						      chain);
 			} else {
 				/* Apparently -n still flushes existing user
@@ -200,7 +203,7 @@
 				 */
 				if (cb->chain_user_flush)
 					cb->chain_user_flush(h, chain_list,
-							     curtable, chain);
+							     curtable->name, chain);
 			}
 
 			if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
@@ -218,7 +221,7 @@
 				exit(1);
 			}
 
-			if (strcmp(policy, "-") != 0) {
+			if (nft_chain_builtin_find(curtable, chain)) {
 				if (counters) {
 					char *ctrs;
 					ctrs = strtok(NULL, " \t\n");
@@ -230,7 +233,8 @@
 
 				}
 				if (cb->chain_set &&
-				    cb->chain_set(h, curtable, chain, policy, &count) < 0) {
+				    cb->chain_set(h, curtable->name,
+					          chain, policy, &count) < 0) {
 					xtables_error(OTHER_PROBLEM,
 						      "Can't set policy `%s'"
 						      " on `%s' line %u: %s\n",
@@ -243,7 +247,8 @@
 
 			} else {
 				if (cb->chain_user_add &&
-				    cb->chain_user_add(h, chain, curtable) < 0) {
+				    cb->chain_user_add(h, chain,
+						       curtable->name) < 0) {
 					if (errno == EEXIST)
 						continue;
 
@@ -294,7 +299,7 @@
 
 			add_argv(argv[0], 0);
 			add_argv("-t", 0);
-			add_argv(curtable, 0);
+			add_argv(curtable->name, 0);
 
 			if (counters && pcnt && bcnt) {
 				add_argv("--set-counters", 0);
@@ -305,7 +310,7 @@
 			add_param_to_argv(parsestart, line);
 
 			DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
-				newargc, curtable);
+				newargc, curtable->name);
 
 			for (a = 0; a < newargc; a++)
 				DEBUGP("argv[%u]: %s\n", a, newargv[a]);
@@ -328,7 +333,8 @@
 			free_argv();
 			fflush(stdout);
 		}
-		if (p->tablename && (strcmp(p->tablename, curtable) != 0))
+		if (p->tablename && curtable &&
+		    (strcmp(p->tablename, curtable->name) != 0))
 			continue;
 		if (!ret) {
 			fprintf(stderr, "%s: line %u failed\n",