allow checking for --xxxx--target RETURN rules on base chains
diff --git a/ebtables.c b/ebtables.c
index b45c51a..8128525 100644
--- a/ebtables.c
+++ b/ebtables.c
@@ -703,7 +703,9 @@
 		if (!(replace.valid_hooks & (1 << i)))
 			continue;
 		entries = nr_to_chain(i);
-		entries->hook_mask = (1 << i);
+		// (1 << NF_BR_NUMHOOKS) implies it's a standard chain
+		// (usefull in the final_check() funtions)
+		entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
 		chain_nr = i;
 
 		e = entries->entries;
diff --git a/extensions/ebt_mark.c b/extensions/ebt_mark.c
index 318e2b6..d3c0cd3 100644
--- a/extensions/ebt_mark.c
+++ b/extensions/ebt_mark.c
@@ -9,6 +9,8 @@
 
 extern char *standard_targets[NUM_STANDARD_TARGETS];
 
+int mark_supplied;
+
 #define MARK_TARGET '1'
 #define MARK_SETMARK '2'
 static struct option opts[] =
@@ -23,7 +25,7 @@
 	printf(
 	"mark target options:\n"
 	" --set-mark value   : Set nfmark value\n"
-	" --mark-target target   : ACCEPT, DROP or CONTINUE\n");
+	" --mark-target target   : ACCEPT, DROP, RETURN or CONTINUE\n");
 }
 
 static void init(struct ebt_entry_target *target)
@@ -33,6 +35,7 @@
 
 	markinfo->target = EBT_ACCEPT;
 	markinfo->mark = 0;
+	mark_supplied = 0;
 	return;
 }
 
@@ -62,7 +65,8 @@
 		check_option(flags, OPT_MARK_SETMARK);
 		markinfo->mark = strtoul(optarg, &end, 0);
 		if (*end != '\0' || end == optarg)
-			print_error("Bad MARK value `%s'", optarg);
+			print_error("Bad MARK value '%s'", optarg);
+		mark_supplied = 1;
                 break;
 	 default:
 		return 0;
@@ -74,6 +78,13 @@
    const struct ebt_entry_target *target, const char *name,
    unsigned int hook_mask, unsigned int time)
 {
+	struct ebt_mark_t_info *markinfo =
+	   (struct ebt_mark_t_info *)target->data;
+
+	if (time == 0 && mark_supplied == 0)
+		print_error("No mark value supplied");
+	if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && markinfo->target == EBT_RETURN)
+		print_error("--mark-target RETURN not allowed on base chain");
 }
 
 static void print(const struct ebt_u_entry *entry,
@@ -97,8 +108,8 @@
 	struct ebt_mark_t_info *markinfo2 =
 	   (struct ebt_mark_t_info *)t2->data;
 
-	return (markinfo1->target == markinfo2->target && 
-	   markinfo1->mark == markinfo2->mark);
+	return markinfo1->target == markinfo2->target &&
+	   markinfo1->mark == markinfo2->mark;
 }
 
 static struct ebt_u_target mark_target =
diff --git a/extensions/ebt_nat.c b/extensions/ebt_nat.c
index d94763a..25b12ca 100644
--- a/extensions/ebt_nat.c
+++ b/extensions/ebt_nat.c
@@ -37,7 +37,7 @@
 	printf(
 	"snat options:\n"
 	" --to-src address       : MAC address to map source to\n"
-	" --snat-target target   : ACCEPT, DROP or CONTINUE\n");
+	" --snat-target target   : ACCEPT, DROP, RETURN or CONTINUE\n");
 }
 
 static void print_help_d()
@@ -45,7 +45,7 @@
 	printf(
 	"dnat options:\n"
 	" --to-dst address       : MAC address to map destination to\n"
-	" --dnat-target target   : ACCEPT, DROP or CONTINUE\n");
+	" --dnat-target target   : ACCEPT, DROP, RETURN or CONTINUE\n");
 }
 
 static void init_s(struct ebt_entry_target *target)
@@ -81,7 +81,7 @@
 		check_option(flags, OPT_SNAT);
 		to_source_supplied = 1;
 		if (!(addr = ether_aton(optarg)))
-			print_error("Problem with specified to-source mac");
+			print_error("Problem with specified --to-source mac");
 		memcpy(natinfo->mac, addr, ETH_ALEN);
 		break;
 	case NAT_S_TARGET:
@@ -116,7 +116,7 @@
 		to_dest_supplied = 1;
 		if (!(addr = ether_aton(optarg)))
 			print_error("Problem with specified "
-			            "to-destination mac");
+			            "--to-destination mac");
 		memcpy(natinfo->mac, addr, ETH_ALEN);
 		break;
 	case NAT_D_TARGET:
@@ -139,6 +139,11 @@
    const struct ebt_entry_target *target, const char *name,
    unsigned int hook_mask, unsigned int time)
 {
+	struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
+
+	if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN)
+		print_error("--snat-target RETURN not allowed on base chain");
+	hook_mask &= ~(1 << NF_BR_NUMHOOKS);
 	if (!(hook_mask & (1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat"))
 		print_error("Wrong chain for snat");
 	if (time == 0 && to_source_supplied == 0)
@@ -149,6 +154,11 @@
    const struct ebt_entry_target *target, const char *name,
    unsigned int hook_mask, unsigned int time)
 {
+	struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
+
+	if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN)
+		print_error("--dnat-target RETURN not allowed on base chain");
+	hook_mask &= ~(1 << NF_BR_NUMHOOKS);
 	if (((hook_mask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT))) ||
 	   strcmp(name, "nat")) &&
 	   ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")))
diff --git a/extensions/ebt_redirect.c b/extensions/ebt_redirect.c
index ea0a504..6e07d06 100644
--- a/extensions/ebt_redirect.c
+++ b/extensions/ebt_redirect.c
@@ -12,7 +12,7 @@
 #define REDIRECT_TARGET '1'
 static struct option opts[] =
 {
-	{ "redirect-target"    , required_argument, 0, REDIRECT_TARGET },
+	{ "redirect-target", required_argument, 0, REDIRECT_TARGET },
 	{ 0 }
 };
 
@@ -20,7 +20,7 @@
 {
 	printf(
 	"redirect option:\n"
-	" --redirect-target target   : ACCEPT, DROP or CONTINUE\n");
+	" --redirect-target target   : ACCEPT, DROP, RETURN or CONTINUE\n");
 }
 
 static void init(struct ebt_entry_target *target)
@@ -62,6 +62,13 @@
    const struct ebt_entry_target *target, const char *name,
    unsigned int hook_mask, unsigned int time)
 {
+	struct ebt_redirect_info *redirectinfo =
+	   (struct ebt_redirect_info *)target->data;
+
+	if ((hook_mask & (1 << NF_BR_NUMHOOKS)) &&
+	   redirectinfo->target == EBT_RETURN)
+		print_error("--redirect-target RETURN not allowed on base chain");
+	hook_mask &= ~(1 << NF_BR_NUMHOOKS);
 	if ( ((hook_mask & ~(1 << NF_BR_PRE_ROUTING)) || strcmp(name, "nat")) &&
 	   ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")) )
 		print_error("Wrong chain for redirect");