diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c index 715d559..2b9a1b6 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 56b2991..a02206f 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 a91f0c1..1fa5ad9 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 0287add..4930b6d 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); }