summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2018-05-04 22:33:35 +0200
committerFlorian Westphal <fw@strlen.de>2018-05-04 23:21:18 +0200
commit0ab58e397ca613a1996cb9767e221f71e752812e (patch)
treea20821c675167cfa61bc20800fbad2f18e725dce
parent734ad4020e6ff0c47c27b3b9096cbc996b5e1ee7 (diff)
xtables-compat: ebtables: handle mac masks properly
Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r--iptables/nft-bridge.c15
-rw-r--r--iptables/nft-shared.c2
-rw-r--r--iptables/nft-shared.h1
3 files changed, 17 insertions, 1 deletions
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 3fdac9cc..e1c82f03 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -184,6 +184,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
op = nft_invflags2cmp(fw->invflags, EBT_ISOURCE);
add_payload(r, offsetof(struct ethhdr, h_source), 6,
NFT_PAYLOAD_LL_HEADER);
+ add_bitwise(r, fw->sourcemsk, 6);
add_cmp_ptr(r, op, fw->sourcemac, 6);
}
@@ -192,6 +193,7 @@ static int nft_bridge_add(struct nftnl_rule *r, void *data)
op = nft_invflags2cmp(fw->invflags, EBT_IDEST);
add_payload(r, offsetof(struct ethhdr, h_dest), 6,
NFT_PAYLOAD_LL_HEADER);
+ add_bitwise(r, fw->destmsk, 6);
add_cmp_ptr(r, op, fw->destmac, 6);
}
@@ -291,6 +293,13 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
fw->destmac[i] = addr[i];
if (inv)
fw->invflags |= EBT_IDEST;
+
+ if (ctx->flags & NFT_XT_CTX_BITWISE) {
+ memcpy(fw->destmsk, ctx->bitwise.mask, ETH_ALEN);
+ ctx->flags &= ~NFT_XT_CTX_BITWISE;
+ } else {
+ memset(&fw->destmsk, 0xff, ETH_ALEN);
+ }
break;
case offsetof(struct ethhdr, h_source):
get_cmp_data(e, addr, sizeof(addr), &inv);
@@ -298,6 +307,12 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
fw->sourcemac[i] = addr[i];
if (inv)
fw->invflags |= EBT_ISOURCE;
+ if (ctx->flags & NFT_XT_CTX_BITWISE) {
+ memcpy(fw->sourcemsk, ctx->bitwise.mask, ETH_ALEN);
+ ctx->flags &= ~NFT_XT_CTX_BITWISE;
+ } else {
+ memset(&fw->sourcemsk, 0xff, ETH_ALEN);
+ }
break;
case offsetof(struct ethhdr, h_proto):
get_cmp_data(e, &ethproto, sizeof(ethproto), &inv);
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 68e5c55d..e2fc226c 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -83,7 +83,7 @@ void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor)
nftnl_rule_add_expr(r, expr);
}
-static void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len)
+void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len)
{
struct nftnl_expr *expr;
uint32_t xor[4] = { 0 };
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index e13a1a85..525f3f0e 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -107,6 +107,7 @@ struct nft_family_ops {
void add_meta(struct nftnl_rule *r, uint32_t key);
void add_payload(struct nftnl_rule *r, int offset, int len, uint32_t base);
+void add_bitwise(struct nftnl_rule *r, uint8_t *mask, size_t len);
void add_bitwise_u16(struct nftnl_rule *r, int mask, int xor);
void add_cmp_ptr(struct nftnl_rule *r, uint32_t op, void *data, size_t len);
void add_cmp_u8(struct nftnl_rule *r, uint8_t val, uint32_t op);