diff mbox series

[iptables] ebtables: among: Support mixed MAC and MAC/IP entries

Message ID 20200214104910.21196-1-phil@nwl.cc
State Accepted
Delegated to: Pablo Neira
Headers show
Series [iptables] ebtables: among: Support mixed MAC and MAC/IP entries | expand

Commit Message

Phil Sutter Feb. 14, 2020, 10:49 a.m. UTC
Powered by Stefano's support for concatenated ranges, a full among match
replacement can be implemented. The trick is to add MAC-only elements as
a concatenation of MAC and zero-length prefix, i.e. a range from
0.0.0.0 till 255.255.255.255.

Although not quite needed, detection of pure MAC-only matches is left in
place. For those, no implicit 'meta protocol' match is added (which is
required otherwise at least to keep nft output correct) and no concat
type is used for the set.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 extensions/libebt_among.c |  6 +-----
 extensions/libebt_among.t |  2 +-
 iptables/ebtables-nft.8   |  4 ----
 iptables/nft.c            | 20 +++++++++++++++++++-
 4 files changed, 21 insertions(+), 11 deletions(-)

Comments

Pablo Neira Ayuso Feb. 18, 2020, 1:56 p.m. UTC | #1
On Fri, Feb 14, 2020 at 11:49:10AM +0100, Phil Sutter wrote:
> Powered by Stefano's support for concatenated ranges, a full among match
> replacement can be implemented. The trick is to add MAC-only elements as
> a concatenation of MAC and zero-length prefix, i.e. a range from
> 0.0.0.0 till 255.255.255.255.
> 
> Although not quite needed, detection of pure MAC-only matches is left in
> place. For those, no implicit 'meta protocol' match is added (which is
> required otherwise at least to keep nft output correct) and no concat
> type is used for the set.

I'm glad to see this, thanks Phil.

Is ebt among is now complete?

Thanks.
Phil Sutter Feb. 18, 2020, 3:42 p.m. UTC | #2
Hi Pablo,

On Tue, Feb 18, 2020 at 02:56:51PM +0100, Pablo Neira Ayuso wrote:
> On Fri, Feb 14, 2020 at 11:49:10AM +0100, Phil Sutter wrote:
> > Powered by Stefano's support for concatenated ranges, a full among match
> > replacement can be implemented. The trick is to add MAC-only elements as
> > a concatenation of MAC and zero-length prefix, i.e. a range from
> > 0.0.0.0 till 255.255.255.255.
> > 
> > Although not quite needed, detection of pure MAC-only matches is left in
> > place. For those, no implicit 'meta protocol' match is added (which is
> > required otherwise at least to keep nft output correct) and no concat
> > type is used for the set.
> 
> I'm glad to see this, thanks Phil.

You're welcome. I was surprised how quick this was to implement. :)

> Is ebt among is now complete?

Yes, I think we're feature-complete with ebtables-legacy now. The only
question would be whether we want to support IPv6 as well, but I don't
think it's worth the effort.

Cheers, Phil
diff mbox series

Patch

diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
index 715d559f432c2..2b9a1b6566684 100644
--- a/extensions/libebt_among.c
+++ b/extensions/libebt_among.c
@@ -63,10 +63,6 @@  parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip)
 	char *sep = index(buf, '=');
 	struct ether_addr *ether;
 
-	if (have_ip ^ !!sep)
-		xtables_error(PARAMETER_PROBLEM,
-			      "among: Mixed MAC and MAC=IP not allowed.");
-
 	if (sep) {
 		*sep = '\0';
 
@@ -205,7 +201,7 @@  static void __bramong_print(struct nft_among_pair *pairs,
 		isep = ",";
 
 		printf("%s", ether_ntoa(&pairs[i].ether));
-		if (have_ip)
+		if (pairs[i].in.s_addr != INADDR_ANY)
 			printf("=%s", inet_ntoa(pairs[i].in));
 	}
 	printf(" ");
diff --git a/extensions/libebt_among.t b/extensions/libebt_among.t
index 56b299161ff31..a02206f391cde 100644
--- a/extensions/libebt_among.t
+++ b/extensions/libebt_among.t
@@ -13,4 +13,4 @@ 
 --among-src;=;FAIL
 --among-src 00:11=10.0.0.1;=;FAIL
 --among-src de:ad:0:be:ee:ff=10.256.0.1;=;FAIL
---among-src de:ad:0:be:ee:ff,c0:ff:ee:0:ba:be=192.168.1.1;=;FAIL
+--among-src c0:ff:ee:0:ba:be=192.168.1.1,de:ad:0:be:ee:ff;=;OK
diff --git a/iptables/ebtables-nft.8 b/iptables/ebtables-nft.8
index a91f0c1aacb0f..1fa5ad9388cc0 100644
--- a/iptables/ebtables-nft.8
+++ b/iptables/ebtables-nft.8
@@ -551,10 +551,6 @@  Same as
 .BR "--among-src-file " "[!] \fIfile\fP"
 Same as
 .BR --among-src " but the list is read in from the specified file."
-.PP
-Note that in this implementation of ebtables, among lists uses must be
-internally homogeneous regarding whether IP addresses are present or not. Mixed
-use of MAC addresses and MAC/IP address pairs is not supported yet.
 .SS arp
 Specify (R)ARP fields. The protocol must be specified as
 .IR ARP " or " RARP .
diff --git a/iptables/nft.c b/iptables/nft.c
index 3f2a62ae12c07..806b77fed462b 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1022,19 +1022,28 @@  static int __add_nft_among(struct nft_handle *h, const char *table,
 	};
 	struct nftnl_expr *e;
 	struct nftnl_set *s;
+	uint32_t flags = 0;
 	int idx = 0;
 
 	if (ip) {
 		type = type << CONCAT_TYPE_BITS | NFT_DATATYPE_IPADDR;
 		len += sizeof(struct in_addr) + NETLINK_ALIGN - 1;
 		len &= ~(NETLINK_ALIGN - 1);
+		flags = NFT_SET_INTERVAL;
 	}
 
-	s = add_anon_set(h, table, 0, type, len, cnt);
+	s = add_anon_set(h, table, flags, type, len, cnt);
 	if (!s)
 		return -ENOMEM;
 	set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);
 
+	if (ip) {
+		uint8_t field_len[2] = { ETH_ALEN, sizeof(struct in_addr) };
+
+		nftnl_set_set_data(s, NFTNL_SET_DESC_CONCAT,
+				   field_len, sizeof(field_len));
+	}
+
 	for (idx = 0; idx < cnt; idx++) {
 		struct nftnl_set_elem *elem = nftnl_set_elem_alloc();
 
@@ -1042,6 +1051,15 @@  static int __add_nft_among(struct nft_handle *h, const char *table,
 			return -ENOMEM;
 		nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY,
 				   &pairs[idx], len);
+		if (ip) {
+			struct in_addr tmp = pairs[idx].in;
+
+			if (tmp.s_addr == INADDR_ANY)
+				pairs[idx].in.s_addr = INADDR_BROADCAST;
+			nftnl_set_elem_set(elem, NFTNL_SET_ELEM_KEY_END,
+					   &pairs[idx], len);
+			pairs[idx].in = tmp;
+		}
 		nftnl_set_elem_add(s, elem);
 	}