128 lines
4.2 KiB
Diff
128 lines
4.2 KiB
Diff
|
From 654b2e2512630df07e3ea57f8d54e851e75b33f1 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <phil@nwl.cc>
|
||
|
Date: Thu, 13 Feb 2020 17:49:53 +0100
|
||
|
Subject: [PATCH] ebtables: among: Support mixed MAC and MAC/IP entries
|
||
|
|
||
|
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>
|
||
|
(cherry picked from commit c33bae9c6c7a49c8af16df846e6112fc4727e643)
|
||
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
||
|
---
|
||
|
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(-)
|
||
|
|
||
|
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 0287add3fb21f..4930b6de534d8 100644
|
||
|
--- a/iptables/nft.c
|
||
|
+++ b/iptables/nft.c
|
||
|
@@ -1029,19 +1029,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();
|
||
|
|
||
|
@@ -1049,6 +1058,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);
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.26.2
|
||
|
|