xtables-restore: Unbreak *tables-restore

Commit 3dc433b55bbfa ("xtables-restore: Fix --table parameter check")
installed an error check which evaluated true in all cases as all
callers of do_command callbacks pass a pointer to a table name already.
Attached test case passed as it tested error condition only.

Fix the whole mess by introducing a boolean to indicate whether a table
parameter was seen already. Extend the test case to cover positive as
well as negative behaviour and to test ebtables-restore and
ip6tables-restore as well. Also add the required checking code to the
latter since the original commit missed it.

Fixes: 3dc433b55bbfa ("xtables-restore: Fix --table parameter check")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index 57b0f9f..c160a2d 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -1228,6 +1228,7 @@
 	struct xtables_rule_match *matchp;
 	struct xtables_target *t;
 	unsigned long long cnt;
+	bool table_set = false;
 
 	/* re-set optind to 0 in case do_command6 gets called
 	 * a second time */
@@ -1508,7 +1509,12 @@
 			if (cs.invert)
 				xtables_error(PARAMETER_PROBLEM,
 					   "unexpected ! flag before --table");
+			if (restore && table_set)
+				xtables_error(PARAMETER_PROBLEM,
+					      "The -t option (seen in line %u) cannot be used in %s.\n",
+					      line, xt_params->program_name);
 			*table = optarg;
+			table_set = true;
 			break;
 
 		case 'x':
diff --git a/iptables/iptables.c b/iptables/iptables.c
index d7a4132..544e875 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1217,6 +1217,7 @@
 	struct xtables_rule_match *matchp;
 	struct xtables_target *t;
 	unsigned long long cnt;
+	bool table_set = false;
 
 	/* re-set optind to 0 in case do_command4 gets called
 	 * a second time */
@@ -1494,11 +1495,12 @@
 			if (cs.invert)
 				xtables_error(PARAMETER_PROBLEM,
 					   "unexpected ! flag before --table");
-			if (restore && *table)
+			if (restore && table_set)
 				xtables_error(PARAMETER_PROBLEM,
 					      "The -t option (seen in line %u) cannot be used in %s.\n",
 					      line, xt_params->program_name);
 			*table = optarg;
+			table_set = true;
 			break;
 
 		case 'x':
diff --git a/iptables/tests/shell/testcases/ipt-restore/0009-table-name-comment_0 b/iptables/tests/shell/testcases/ipt-restore/0009-table-name-comment_0
index 4e2202d..e961407 100755
--- a/iptables/tests/shell/testcases/ipt-restore/0009-table-name-comment_0
+++ b/iptables/tests/shell/testcases/ipt-restore/0009-table-name-comment_0
@@ -4,10 +4,27 @@
 # '-t <tablename>' so standard rule parsing routines may be used. This means
 # that it has to detect and reject rules which already contain a table option.
 
-$XT_MULTI iptables-restore <<EOF
+families="ip ip6"
+[[ $(basename $XT_MULTI) == xtables-nft-multi ]] && families+=" eb"
+
+for fam in $families; do
+	$XT_MULTI ${fam}tables-restore <<EOF
 *filter
 -t nat -A FORWARD -j ACCEPT
 COMMIT
 EOF
+	[[ $? != 0 ]] || {
+		echo "${fam}tables-restore did not fail when it should have"
+		exit 1
+	}
 
-[[ $? != 0 ]] || exit 1
+	$XT_MULTI ${fam}tables-restore <<EOF
+*filter
+-A FORWARD -j ACCEPT
+COMMIT
+EOF
+	[[ $? == 0 ]] || {
+		echo "${fam}tables-restore failed when it should not have"
+		exit 1
+	}
+done
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index aa754d7..fd7d601 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -780,6 +780,7 @@
 	int selected_chain = -1;
 	struct xtables_rule_match *xtrm_i;
 	struct ebt_match *match;
+	bool table_set = false;
 
 	/* prevent getopt to spoil our error reporting */
 	optind = 0;
@@ -947,7 +948,7 @@
 			break;
 		case 't': /* Table */
 			ebt_check_option2(&flags, OPT_TABLE);
-			if (restore && *table)
+			if (restore && table_set)
 				xtables_error(PARAMETER_PROBLEM,
 					      "The -t option (seen in line %u) cannot be used in %s.\n",
 					      line, xt_params->program_name);
@@ -956,6 +957,7 @@
 					      "Table name length cannot exceed %d characters",
 					      EBT_TABLE_MAXNAMELEN - 1);
 			*table = optarg;
+			table_set = true;
 			break;
 		case 'i': /* Input interface */
 		case 2  : /* Logical input interface */
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 89f3271..8a9e0ed 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -590,6 +590,7 @@
 	bool wait_interval_set = false;
 	struct timeval wait_interval;
 	struct xtables_target *t;
+	bool table_set = false;
 	int wait = 0;
 
 	memset(cs, 0, sizeof(*cs));
@@ -879,7 +880,7 @@
 			if (cs->invert)
 				xtables_error(PARAMETER_PROBLEM,
 					   "unexpected ! flag before --table");
-			if (p->restore && p->table)
+			if (p->restore && table_set)
 				xtables_error(PARAMETER_PROBLEM,
 					      "The -t option (seen in line %u) cannot be used in %s.\n",
 					      line, xt_params->program_name);
@@ -888,6 +889,7 @@
 					      "table '%s' does not exist",
 					      optarg);
 			p->table = optarg;
+			table_set = true;
 			break;
 
 		case 'x':