add wildcard support for interface names
diff --git a/ebtables.8 b/ebtables.8
index 79014b6..b51e4c6 100644
--- a/ebtables.8
+++ b/ebtables.8
@@ -71,7 +71,9 @@
 what to do with that matching frame. The processing specification is
 called a 'target'. However, if the frame does not match the current
 rule in the chain, then the next rule in the chain is examined and so forth.
-The user can create new (user-defined) chains which can be used as the 'target' of a rule.
+The user can create new (user-defined) chains which can be used as the 'target'
+of a rule. User-defined chains are very useful to get better performance
+over the linear traversal of the rules.
 
 .SS TARGETS
 A firewall rule specifies criteria for an Ethernet frame and a frame
@@ -430,6 +432,8 @@
 chains). The flag
 .B --in-if
 is an alias for this option.
+If the interface name ends with '+', then
+any interface name that begins with this name will match.
 .TP
 .BR "--logical-in " "[!] \fIname\fP"
 The (logical) bridge interface via which a frame is received (for the
@@ -437,6 +441,8 @@
 .BR FORWARD ,
 .BR PREROUTING " and " BROUTING
 chains).
+If the interface name ends with '+', then
+any interface name that begins with this name will match.
 .TP
 .BR "-o, --out-interface " "[!] \fIname\fP"
 The interface via which a frame is going to be sent (for the
@@ -447,6 +453,8 @@
 chains). The flag
 .B --out-if
 is an alias for this option.
+If the interface name ends with '+', then
+any interface name that begins with this name will match.
 .TP
 .BR "--logical-out " "[!] \fIname\fP"
 The (logical) bridge interface via which a frame is going to be sent (for
@@ -456,6 +464,8 @@
 and
 .B POSTROUTING
 chains).
+If the interface name ends with '+', then
+any interface name that begins with this name will match.
 .TP
 .BR "-s, --source " "[!] \fIaddress\fP[/\fImask\fP]"
 The source mac address. Both mask and address are written as 6 hexadecimal
diff --git a/ebtables.c b/ebtables.c
index 58dad06..266ed8e 100644
--- a/ebtables.c
+++ b/ebtables.c
@@ -155,6 +155,19 @@
 	   (ebt_options, t->extra_ops, &(t->option_offset));
 }
 
+/* be backwards compatible, so don't use '+' in kernel */
+#define IF_WILDCARD 1
+static void print_iface(const char *iface)
+{
+	char *c;
+
+	if ((c = strchr(iface, IF_WILDCARD)))
+		*c = '+';
+	printf("%s ", iface);
+	if (c)
+		*c = IF_WILDCARD;
+}
+
 /*
  * we use replace.flags, so we can't use the following values:
  * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO
@@ -251,25 +264,25 @@
 			printf("-i ");
 			if (hlp->invflags & EBT_IIN)
 				printf("! ");
-			printf("%s ", hlp->in);
+			print_iface(hlp->in);
 		}
 		if (hlp->logical_in[0] != '\0') {
 			printf("--logical-in ");
 			if (hlp->invflags & EBT_ILOGICALIN)
 				printf("! ");
-			printf("%s ", hlp->logical_in);
+			print_iface(hlp->logical_in);
 		}
 		if (hlp->logical_out[0] != '\0') {
 			printf("--logical-out ");
 			if (hlp->invflags & EBT_ILOGICALOUT)
 				printf("! ");
-			printf("%s ", hlp->logical_out);
+			print_iface(hlp->logical_out);
 		}
 		if (hlp->out[0] != '\0') {
 			printf("-o ");
 			if (hlp->invflags & EBT_IOUT)
 				printf("! ");
-			printf("%s ", hlp->out);
+			print_iface(hlp->out);
 		}
 
 		m_l = hlp->m_list;
@@ -442,6 +455,19 @@
 	return 0;
 }
 
+static void parse_iface(char *iface, char *option)
+{
+	char *c;
+
+	if ((c = strchr(iface, '+'))) {
+		if (*(c + 1) != '\0') {
+			ebt_print_error("Spurious characters after '+' "
+			                "wildcard for %s", option);
+		} else
+			*c = IF_WILDCARD;
+	}
+}
+
 #define print_if_l_error ebt_print_error("Interface name length must be less " \
    "than %d", IFNAMSIZ)
 #define OPT_COMMAND	0x01
@@ -773,6 +799,7 @@
 				if (strlen(argv[optind - 1]) >= IFNAMSIZ)
 					print_if_l_error;
 				strcpy(new_entry->in, argv[optind - 1]);
+				parse_iface(new_entry->in, "-i");
 				break;
 			}
 			if (c == 2) {
@@ -792,6 +819,8 @@
 				if (strlen(argv[optind - 1]) >= IFNAMSIZ)
 					print_if_l_error;
 				strcpy(new_entry->logical_in, argv[optind - 1]);
+				parse_iface(new_entry->logical_in,
+				            "--logical-in");
 				break;
 			}
 			if (c == 'o') {
@@ -810,6 +839,7 @@
 				if (strlen(argv[optind - 1]) >= IFNAMSIZ)
 					print_if_l_error;
 				strcpy(new_entry->out, argv[optind - 1]);
+				parse_iface(new_entry->out, "-o");
 				break;
 			}
 			if (c == 3) {
@@ -831,6 +861,8 @@
 					print_if_l_error;
 				strcpy(new_entry->logical_out,
 				   argv[optind - 1]);
+				parse_iface(new_entry->logical_out,
+				         "--logical-out");
 				break;
 			}
 			if (c == 'j') {