*** empty log message ***
diff --git a/ebtables.c b/ebtables.c
index d4c6a6b..c58c0c6 100644
--- a/ebtables.c
+++ b/ebtables.c
@@ -1451,6 +1451,33 @@
 	return 0;
 }
 
+void do_final_checks(struct ebt_u_entry *e, struct ebt_u_entries *entries)
+{
+	struct ebt_u_match_list *m_l;
+	struct ebt_u_watcher_list *w_l;
+	struct ebt_u_target *t;
+	struct ebt_u_match *m;
+	struct ebt_u_watcher *w;
+
+	m_l = e->m_list;
+	w_l = e->w_list;
+	while (m_l) {
+		m = find_match(m_l->m->u.name);
+		m->final_check(e, m_l->m, replace.name,
+		   entries->hook_mask, 1);
+		m_l = m_l->next;
+	}
+	while (w_l) {
+		w = find_watcher(w_l->w->u.name);
+		w->final_check(e, w_l->w, replace.name,
+		   entries->hook_mask, 1);
+		w_l = w_l->next;
+	}
+	t = find_target(e->t->u.name);
+	t->final_check(e, e->t, replace.name,
+	   entries->hook_mask, 1);
+}
+
 int check_inverse(const char option[])
 {
 	if (strcmp(option, "!") == 0) {
@@ -1490,9 +1517,9 @@
 	struct ebt_u_target *t;
 	struct ebt_u_match *m;
 	struct ebt_u_watcher *w;
-	struct ebt_u_match_list *m_l;
+ 	struct ebt_u_match_list *m_l;
 	struct ebt_u_watcher_list *w_l;
-	struct ebt_u_entries *entries;
+ 	struct ebt_u_entries *entries;
 	const char *modprobe = NULL;
 
 	// initialize the table name, OPT_ flags, selected hook and command
@@ -1850,6 +1877,8 @@
 						print_error("Return target"
 						" only for user defined chains");
 				}
+				if (i != NUM_STANDARD_TARGETS)
+					break;
 				if ((i = get_hooknr(optarg)) != -1) {
 						if (i < NF_BR_NUMHOOKS)
 							print_error("don't jump"
@@ -2003,19 +2032,18 @@
 		while (m_l) {
 			m = (struct ebt_u_match *)(m_l->m);
 			m->final_check(new_entry, m->m, replace.name,
-			   entries->hook_mask);
+			   entries->hook_mask, 0);
 			m_l = m_l->next;
 		}
 		while (w_l) {
 			w = (struct ebt_u_watcher *)(w_l->w);
 			w->final_check(new_entry, w->w, replace.name,
-			   entries->hook_mask);
+			   entries->hook_mask, 0);
 			w_l = w_l->next;
 		}
 		t->final_check(new_entry, t->t, replace.name,
-		   entries->hook_mask);
+		   entries->hook_mask, 0);
 	}
-	
 	// so, the extensions can work with the host endian
 	// the kernel does not have to do this ofcourse
 	new_entry->ethproto = htons(new_entry->ethproto);
@@ -2037,6 +2065,29 @@
 	} else if (replace.command == 'A' || replace.command == 'I') {
 		add_rule(rule_nr);
 		check_for_loops();
+		// do the final_check(), for all entries
+		// needed when adding a rule that has a chain target
+		i = -1;
+		while (1) {
+			struct ebt_u_entry *e;
+
+			i++;
+			entries = nr_to_chain(i);
+			if (!entries) {
+				if (i < NF_BR_NUMHOOKS)
+					continue;
+				else
+					break;
+			}
+			e = entries->entries;
+			while (e) {
+				// userspace extensions use host endian
+				e->ethproto = ntohs(e->ethproto);
+				do_final_checks(e, entries);
+				e->ethproto = htons(e->ethproto);
+				e = e->next;
+			}
+		}
 	} else if (replace.command == 'D')
 		delete_rule(rule_nr);
 	// commands -N, -E, -X fall through
@@ -2048,6 +2099,5 @@
 
 	if (counterchanges)
 		deliver_counters(&replace, counterchanges);
-//	list_rules();
 	return 0;
 }
diff --git a/extensions/ebt_arp.c b/extensions/ebt_arp.c
index d094b68..d088563 100644
--- a/extensions/ebt_arp.c
+++ b/extensions/ebt_arp.c
@@ -75,9 +75,8 @@
 #define OPT_PTYPE  0x04
 #define OPT_IP_S   0x08
 #define OPT_IP_D   0x10
-static int parse(int c, char **argv, int argc,
-	        const struct ebt_u_entry *entry, unsigned int *flags,
-	        struct ebt_entry_match **match)
+static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
+   unsigned int *flags, struct ebt_entry_match **match)
 {
 	struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
 	int i;
@@ -177,7 +176,8 @@
 }
 
 static void final_check(const struct ebt_u_entry *entry,
-const struct ebt_entry_match *match, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_match *match, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 ||
 	   (entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP))
diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c
index cb425f9..71d7f30 100644
--- a/extensions/ebt_ip.c
+++ b/extensions/ebt_ip.c
@@ -218,7 +218,8 @@
 }
 
 static void final_check(const struct ebt_u_entry *entry,
-   const struct ebt_entry_match *match, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_match *match, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 ||
 	   entry->ethproto != ETH_P_IP)
diff --git a/extensions/ebt_log.c b/extensions/ebt_log.c
index 1dca3ad..b6e62eb 100644
--- a/extensions/ebt_log.c
+++ b/extensions/ebt_log.c
@@ -142,7 +142,8 @@
 }
 
 static void final_check(const struct ebt_u_entry *entry,
-   const struct ebt_entry_watcher *watcher, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_watcher *watcher, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	return;
 }
diff --git a/extensions/ebt_nat.c b/extensions/ebt_nat.c
index fe7cd1a..d94763a 100644
--- a/extensions/ebt_nat.c
+++ b/extensions/ebt_nat.c
@@ -136,22 +136,24 @@
 }
 
 static void final_check_s(const struct ebt_u_entry *entry,
-   const struct ebt_entry_target *target, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_target *target, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	if (!(hook_mask & (1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat"))
 		print_error("Wrong chain for snat");
-	if (to_source_supplied == 0)
+	if (time == 0 && to_source_supplied == 0)
 		print_error("No snat address supplied");
 }
 
 static void final_check_d(const struct ebt_u_entry *entry,
-   const struct ebt_entry_target *target, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_target *target, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	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")))
 		print_error("Wrong chain for dnat");
-	if (to_dest_supplied == 0)
+	if (time == 0 && to_dest_supplied == 0)
 		print_error("No dnat address supplied");
 }
 
diff --git a/extensions/ebt_redirect.c b/extensions/ebt_redirect.c
index 5d329e7..ea0a504 100644
--- a/extensions/ebt_redirect.c
+++ b/extensions/ebt_redirect.c
@@ -59,7 +59,8 @@
 }
 
 static void final_check(const struct ebt_u_entry *entry,
-   const struct ebt_entry_target *target, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_target *target, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 	if ( ((hook_mask & ~(1 << NF_BR_PRE_ROUTING)) || strcmp(name, "nat")) &&
 	   ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")) )
diff --git a/extensions/ebt_standard.c b/extensions/ebt_standard.c
index 726a1ab..95e00a5 100644
--- a/extensions/ebt_standard.c
+++ b/extensions/ebt_standard.c
@@ -26,7 +26,8 @@
 }
 
 static void final_check(const struct ebt_u_entry *entry,
-   const struct ebt_entry_target *target, const char *name, unsigned int hook_mask)
+   const struct ebt_entry_target *target, const char *name,
+   unsigned int hook_mask, unsigned int time)
 {
 }
 
diff --git a/extensions/ebt_vlan.c b/extensions/ebt_vlan.c
index 05ee992..f74b26f 100644
--- a/extensions/ebt_vlan.c
+++ b/extensions/ebt_vlan.c
@@ -193,7 +193,7 @@
 static void
 final_check (const struct ebt_u_entry *entry,
 	     const struct ebt_entry_match *match,
-	     const char *name, unsigned int hook_mask)
+	     const char *name, unsigned int hook_mask, unsigned int time)
 {
 	/*
 	 * Is any proto supplied there? Or specified proto isn't 802.1Q?
diff --git a/include/ebtables_u.h b/include/ebtables_u.h
index 4c4168b..d86a7c7 100644
--- a/include/ebtables_u.h
+++ b/include/ebtables_u.h
@@ -119,7 +119,7 @@
 	        struct ebt_entry_match **match);
 	void (*final_check)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_match *match,
-	   const char *name, unsigned int hook_mask);
+	   const char *name, unsigned int hook_mask, unsigned int time);
 	void (*print)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_match *match);
 	int (*compare)(const struct ebt_entry_match *m1,
@@ -146,7 +146,7 @@
 	   struct ebt_entry_watcher **watcher);
 	void (*final_check)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_watcher *watch, const char *name,
-	   unsigned int hook_mask);
+	   unsigned int hook_mask, unsigned int time);
 	void (*print)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_watcher *watcher);
 	int (*compare)(const struct ebt_entry_watcher *w1,
@@ -170,7 +170,7 @@
 	   struct ebt_entry_target **target);
 	void (*final_check)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_target *target, const char *name,
-	   unsigned int hook_mask);
+	   unsigned int hook_mask, unsigned int time);
 	void (*print)(const struct ebt_u_entry *entry,
 	   const struct ebt_entry_target *target);
 	int (*compare)(const struct ebt_entry_target *t1,