Blame SOURCES/0018-ebtables-among-Support-mixed-MAC-and-MAC-IP-entries.patch

fc8f74
From 654b2e2512630df07e3ea57f8d54e851e75b33f1 Mon Sep 17 00:00:00 2001
fc8f74
From: Phil Sutter <phil@nwl.cc>
fc8f74
Date: Thu, 13 Feb 2020 17:49:53 +0100
fc8f74
Subject: [PATCH] ebtables: among: Support mixed MAC and MAC/IP entries
fc8f74
fc8f74
Powered by Stefano's support for concatenated ranges, a full among match
fc8f74
replacement can be implemented. The trick is to add MAC-only elements as
fc8f74
a concatenation of MAC and zero-length prefix, i.e. a range from
fc8f74
0.0.0.0 till 255.255.255.255.
fc8f74
fc8f74
Although not quite needed, detection of pure MAC-only matches is left in
fc8f74
place. For those, no implicit 'meta protocol' match is added (which is
fc8f74
required otherwise at least to keep nft output correct) and no concat
fc8f74
type is used for the set.
fc8f74
fc8f74
Signed-off-by: Phil Sutter <phil@nwl.cc>
fc8f74
(cherry picked from commit c33bae9c6c7a49c8af16df846e6112fc4727e643)
fc8f74
Signed-off-by: Phil Sutter <psutter@redhat.com>
fc8f74
---
fc8f74
 extensions/libebt_among.c |  6 +-----
fc8f74
 extensions/libebt_among.t |  2 +-
fc8f74
 iptables/ebtables-nft.8   |  4 ----
fc8f74
 iptables/nft.c            | 20 +++++++++++++++++++-
fc8f74
 4 files changed, 21 insertions(+), 11 deletions(-)
fc8f74
fc8f74
diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
fc8f74
index 715d559f432c2..2b9a1b6566684 100644
fc8f74
--- a/extensions/libebt_among.c
fc8f74
+++ b/extensions/libebt_among.c
fc8f74
@@ -63,10 +63,6 @@ parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip)
fc8f74
 	char *sep = index(buf, '=');
fc8f74
 	struct ether_addr *ether;
fc8f74
 
fc8f74
-	if (have_ip ^ !!sep)
fc8f74
-		xtables_error(PARAMETER_PROBLEM,
fc8f74
-			      "among: Mixed MAC and MAC=IP not allowed.");
fc8f74
-
fc8f74
 	if (sep) {
fc8f74
 		*sep = '\0';
fc8f74
 
fc8f74
@@ -205,7 +201,7 @@ static void __bramong_print(struct nft_among_pair *pairs,
fc8f74
 		isep = ",";
fc8f74
 
fc8f74
 		printf("%s", ether_ntoa(&pairs[i].ether));
fc8f74
-		if (have_ip)
fc8f74
+		if (pairs[i].in.s_addr != INADDR_ANY)
fc8f74
 			printf("=%s", inet_ntoa(pairs[i].in));
fc8f74
 	}
fc8f74
 	printf(" ");
fc8f74
diff --git a/extensions/libebt_among.t b/extensions/libebt_among.t
fc8f74
index 56b299161ff31..a02206f391cde 100644
fc8f74
--- a/extensions/libebt_among.t
fc8f74
+++ b/extensions/libebt_among.t
fc8f74
@@ -13,4 +13,4 @@
fc8f74
 --among-src;=;FAIL
fc8f74
 --among-src 00:11=10.0.0.1;=;FAIL
fc8f74
 --among-src de:ad:0:be:ee:ff=10.256.0.1;=;FAIL
fc8f74
---among-src de:ad:0:be:ee:ff,c0:ff:ee:0:ba:be=192.168.1.1;=;FAIL
fc8f74
+--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff;=;OK
fc8f74
diff --git a/iptables/ebtables-nft.8 b/iptables/ebtables-nft.8
fc8f74
index a91f0c1aacb0f..1fa5ad9388cc0 100644
fc8f74
--- a/iptables/ebtables-nft.8
fc8f74
+++ b/iptables/ebtables-nft.8
fc8f74
@@ -551,10 +551,6 @@ Same as
fc8f74
 .BR "--among-src-file " "[!] \fIfile\fP"
fc8f74
 Same as
fc8f74
 .BR --among-src " but the list is read in from the specified file."
fc8f74
-.PP
fc8f74
-Note that in this implementation of ebtables, among lists uses must be
fc8f74
-internally homogeneous regarding whether IP addresses are present or not. Mixed
fc8f74
-use of MAC addresses and MAC/IP address pairs is not supported yet.
fc8f74
 .SS arp
fc8f74
 Specify (R)ARP fields. The protocol must be specified as
fc8f74
 .IR ARP " or " RARP .
fc8f74
diff --git a/iptables/nft.c b/iptables/nft.c
fc8f74
index 0287add3fb21f..4930b6de534d8 100644
fc8f74
--- a/iptables/nft.c
fc8f74
+++ b/iptables/nft.c
fc8f74
@@ -1029,19 +1029,28 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
fc8f74
 	};
fc8f74
 	struct nftnl_expr *e;
fc8f74
 	struct nftnl_set *s;
fc8f74
+	uint32_t flags = 0;
fc8f74
 	int idx = 0;
fc8f74
 
fc8f74
 	if (ip) {
fc8f74
 		type = type << CONCAT_TYPE_BITS | NFT_DATATYPE_IPADDR;
fc8f74
 		len += sizeof(struct in_addr) + NETLINK_ALIGN - 1;
fc8f74
 		len &= ~(NETLINK_ALIGN - 1);
fc8f74
+		flags = NFT_SET_INTERVAL;
fc8f74
 	}
fc8f74
 
fc8f74
-	s = add_anon_set(h, table, 0, type, len, cnt);
fc8f74
+	s = add_anon_set(h, table, flags, type, len, cnt);
fc8f74
 	if (!s)
fc8f74
 		return -ENOMEM;
fc8f74
 	set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);
fc8f74
 
fc8f74
+	if (ip) {
fc8f74
+		uint8_t field_len[2] = { ETH_ALEN, sizeof(struct in_addr) };
fc8f74
+
fc8f74
+		nftnl_set_set_data(s, NFTNL_SET_DESC_CONCAT,
fc8f74
+				   field_len, sizeof(field_len));
fc8f74
+	}
fc8f74
+
fc8f74
 	for (idx = 0; idx < cnt; idx++) {
fc8f74
 		struct nftnl_set_elem *elem = nftnl_set_elem_alloc();
fc8f74
 
fc8f74
@@ -1049,6 +1058,15 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
fc8f74
 			return -ENOMEM;
fc8f74
 		nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY,
fc8f74
 				   &pairs[idx], len);
fc8f74
+		if (ip) {
fc8f74
+			struct in_addr tmp = pairs[idx].in;
fc8f74
+
fc8f74
+			if (tmp.s_addr == INADDR_ANY)
fc8f74
+				pairs[idx].in.s_addr = INADDR_BROADCAST;
fc8f74
+			nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY_END,
fc8f74
+					   &pairs[idx], len);
fc8f74
+			pairs[idx].in = tmp;
fc8f74
+		}
fc8f74
 		nftnl_set_elem_add(s, elem);
fc8f74
 	}
fc8f74
 
fc8f74
-- 
fc8f74
2.26.2
fc8f74