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

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