]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
ebtables: among: Support mixed MAC and MAC/IP entries
authorPhil Sutter <phil@nwl.cc>
Thu, 13 Feb 2020 16:49:53 +0000 (17:49 +0100)
committerPhil Sutter <phil@nwl.cc>
Tue, 18 Feb 2020 16:03:15 +0000 (17:03 +0100)
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
extensions/libebt_among.t
iptables/ebtables-nft.8
iptables/nft.c

index 715d559f432c222250ee3038c67529fc1ebf3c2e..2b9a1b6566684176e540fd431befd060ab52a23c 100644 (file)
@@ -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(" ");
index 56b299161ff3187b1240bb799478bbb4de477567..a02206f391cde400134ee78d016dcd0788113d10 100644 (file)
@@ -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
index a91f0c1aacb0f8ab23c5ba327906a8642527b710..1fa5ad9388cc0a70302535e5725fbfa94e83a934 100644 (file)
@@ -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 .
index 3f2a62ae12c07a9cabfd334a787b5a2b33f60c19..806b77fed462ba04aa7a4991fb368812f7acade4 100644 (file)
@@ -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);
        }