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

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