[PATCH xtables 10/10] xtables-compat: ebtables: allow checking for zero-mac

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow checking for an all-zero mac address by replacing checks on the
address with a check on the option flag.

Its set when '-d' or '-s' appears on the command line and when seeing
a linklayer payload request for ether s/daddr.

Same for -p: s this flag gets removed during getopt when 'p' is encountered.

So, if its set, no need to check protocol type.

Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
---
 iptables/nft-bridge.c           | 73 ++++++++++++++++++++++-------------------
 iptables/nft-bridge.h           |  3 --
 iptables/xtables-eb-translate.c |  2 +-
 iptables/xtables-eb.c           |  1 +
 4 files changed, 42 insertions(+), 37 deletions(-)

diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 86601774498f..83410297139d 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -147,7 +147,6 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
 	struct ebt_match *iter;
 	struct ebt_entry *fw = &cs->eb;
 	uint32_t op;
-	char *addr;
 
 	if (fw->in[0] != '\0') {
 		op = nft_invflags2cmp(fw->invflags, EBT_IIN);
@@ -169,8 +168,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
 		add_logical_outiface(r, fw->logical_out, op);
 	}
 
-	addr = ether_ntoa((struct ether_addr *) fw->sourcemac);
-	if (strcmp(addr, "0:0:0:0:0:0") != 0) {
+	if (fw->bitmask & EBT_ISOURCE) {
 		op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
 		add_payload(r, offsetof(struct ethhdr, h_source), 6,
 			    NFT_PAYLOAD_LL_HEADER);
@@ -179,8 +177,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
 		add_cmp_ptr(r, op, fw->sourcemac, 6);
 	}
 
-	addr = ether_ntoa((struct ether_addr *) fw->destmac);
-	if (strcmp(addr, "0:0:0:0:0:0") != 0) {
+	if (fw->bitmask & EBT_IDEST) {
 		op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
 		add_payload(r, offsetof(struct ethhdr, h_dest), 6,
 			    NFT_PAYLOAD_LL_HEADER);
@@ -189,7 +186,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
 		add_cmp_ptr(r, op, fw->destmac, 6);
 	}
 
-	if (fw->ethproto != 0) {
+	if ((fw->bitmask & EBT_NOPROTO) == 0) {
 		op = nft_invflags2cmp(fw->invflags, EBT_IPROTO);
 		add_payload(r, offsetof(struct ethhdr, h_proto), 2,
 			    NFT_PAYLOAD_LL_HEADER);
@@ -277,6 +274,7 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                 } else {
                         memset(&fw->destmsk, 0xff, ETH_ALEN);
                 }
+		fw->bitmask |= EBT_IDEST;
 		break;
 	case offsetof(struct ethhdr, h_source):
 		get_cmp_data(e, addr, sizeof(addr), &inv);
@@ -290,12 +288,14 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
                 } else {
                         memset(&fw->sourcemsk, 0xff, ETH_ALEN);
                 }
+		fw->bitmask |= EBT_ISOURCE;
 		break;
 	case offsetof(struct ethhdr, h_proto):
 		get_cmp_data(e, &ethproto, sizeof(ethproto), &inv);
 		fw->ethproto = ethproto;
 		if (inv)
 			fw->invflags |= EBT_IPROTO;
+		fw->bitmask &= ~EBT_NOPROTO;
 		break;
 	}
 }
@@ -413,6 +413,30 @@ static void print_mac(char option, const unsigned char *mac,
 }
 
 
+static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
+{
+	struct ethertypeent *ent;
+
+	/* Dont print anything about the protocol if no protocol was
+	 * specified, obviously this means any protocol will do. */
+	if (bitmask & EBT_NOPROTO)
+		return;
+
+	printf("-p ");
+	if (invert)
+		printf("! ");
+
+	if (bitmask & EBT_802_3) {
+		printf("length ");
+		return;
+	}
+
+	ent = getethertypebynumber(ntohs(ethproto));
+	if (!ent)
+		printf("0x%x ", ntohs(ethproto));
+	else
+		printf("%s ", ent->e_name);
+}
 
 static void nft_bridge_print_firewall(struct nftnl_rule *r, unsigned int num,
 				      unsigned int format)
@@ -424,29 +448,13 @@ static void nft_bridge_print_firewall(struct nftnl_rule *r, unsigned int num,
 	if (format & FMT_LINENUMBERS)
 		printf("%d ", num);
 
-	/* Dont print anything about the protocol if no protocol was
-	 * specified, obviously this means any protocol will do. */
-	if (cs.eb.ethproto != 0) {
-		printf("-p ");
-		if (cs.eb.invflags & EBT_IPROTO)
-			printf("! ");
-		if (cs.eb.bitmask & EBT_802_3)
-			printf("Length ");
-		else {
-			struct ethertypeent *ent;
-
-			ent = getethertypebynumber(ntohs(cs.eb.ethproto));
-			if (!ent)
-				printf("0x%x ", ntohs(cs.eb.ethproto));
-			else
-				printf("%s ", ent->e_name);
-		}
-	}
-
-	print_mac('s', cs.eb.sourcemac, cs.eb.sourcemsk,
-	          cs.eb.invflags & EBT_ISOURCE);
-	print_mac('d', cs.eb.destmac, cs.eb.destmsk,
-	          cs.eb.invflags & EBT_IDEST);
+	print_protocol(cs.eb.ethproto, cs.eb.invflags & EBT_IPROTO, cs.eb.bitmask);
+	if (cs.eb.bitmask & EBT_ISOURCE)
+		print_mac('s', cs.eb.sourcemac, cs.eb.sourcemsk,
+		          cs.eb.invflags & EBT_ISOURCE);
+	if (cs.eb.bitmask & EBT_IDEST)
+		print_mac('d', cs.eb.destmac, cs.eb.destmsk,
+		          cs.eb.invflags & EBT_IDEST);
 
 	print_iface("-i", cs.eb.in, cs.eb.invflags & EBT_IIN);
 	print_iface("--logical-in", cs.eb.logical_in, cs.eb.invflags & EBT_ILOGICALIN);
@@ -628,7 +636,6 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
 {
 	const struct iptables_command_state *cs = data;
 	char one_msk[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-	char zero_msk[ETH_ALEN] = {};
 	const char *addr;
 	int ret;
 
@@ -651,7 +658,7 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
 	if (cs->eb.bitmask & EBT_802_3)
 		return 0;
 
-	if (memcmp(cs->eb.sourcemac, zero_msk, sizeof(cs->eb.sourcemac))) {
+	if (cs->eb.bitmask & EBT_ISOURCE) {
 		addr = ether_ntoa((struct ether_addr *) cs->eb.sourcemac);
 
 		xt_xlate_add(xl, "ether saddr %s%s ",
@@ -663,11 +670,11 @@ static int nft_bridge_xlate(const void *data, struct xt_xlate *xl)
 		}
 	}
 
-	if (memcmp(cs->eb.destmac, zero_msk, sizeof(cs->eb.destmac))) {
+	if (cs->eb.bitmask & EBT_IDEST) {
 		addr = ether_ntoa((struct ether_addr *) cs->eb.destmac);
 
 		xt_xlate_add(xl, "ether daddr %s %s ",
-			     cs->eb.invflags & EBT_ISOURCE ? "!= " : "", addr);
+			     cs->eb.invflags & EBT_IDEST ? "!= " : "", addr);
 
 		if (memcmp(cs->eb.destmsk, one_msk, sizeof(cs->eb.destmsk))) {
 			addr = ether_ntoa((struct ether_addr *) cs->eb.destmsk);
diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h
index 3ee04640f162..8dcb151f9e36 100644
--- a/iptables/nft-bridge.h
+++ b/iptables/nft-bridge.h
@@ -15,9 +15,6 @@
 #define LIST_X	  0x10
 #define LIST_MAC2 0x20
 
-/* Be backwards compatible, so don't use '+' in kernel */
-#define IF_WILDCARD 1
-
 extern unsigned char eb_mac_type_unicast[ETH_ALEN];
 extern unsigned char eb_msk_type_unicast[ETH_ALEN];
 extern unsigned char eb_mac_type_multicast[ETH_ALEN];
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
index 23d261e0a8ad..e54415a2f1ed 100644
--- a/iptables/xtables-eb-translate.c
+++ b/iptables/xtables-eb-translate.c
@@ -305,7 +305,6 @@ static void ebtables_parse_interface(const char *arg, char *vianame)
 		if (*(c + 1) != '\0')
 			xtables_error(PARAMETER_PROBLEM,
 				      "Spurious characters after '+' wildcard");
-		*c = IF_WILDCARD;
 	}
 }
 
@@ -392,6 +391,7 @@ static int do_commandeb_xlate(struct nft_handle *h, int argc, char *argv[], char
 
 	/* prevent getopt to spoil our error reporting */
 	opterr = false;
+	cs.eb.bitmask = EBT_NOPROTO;
 
 	printf("nft ");
 	/* Getopt saves the day */
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 5f8f0fb58569..ba26aca10182 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -790,6 +790,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
 
 	/* prevent getopt to spoil our error reporting */
 	opterr = false;
+	cs.eb.bitmask = EBT_NOPROTO;
 
 	/* Getopt saves the day */
 	while ((c = getopt_long(argc, argv,
-- 
2.16.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux