Commit a46c52d9 authored by wenxu's avatar wenxu Committed by Pablo Neira Ayuso

netfilter: nft_tunnel: Add NFTA_TUNNEL_MODE options

nft "tunnel" expr match both the tun_info of RX and TX. This patch
provide the NFTA_TUNNEL_MODE to individually match the tun_info of
RX or TX.
Signed-off-by: default avatarwenxu <wenxu@ucloud.cn>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 0604628b
......@@ -1727,10 +1727,19 @@ enum nft_tunnel_keys {
};
#define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1)
enum nft_tunnel_mode {
NFT_TUNNEL_MODE_NONE,
NFT_TUNNEL_MODE_RX,
NFT_TUNNEL_MODE_TX,
__NFT_TUNNEL_MODE_MAX
};
#define NFT_TUNNEL_MODE_MAX (__NFT_TUNNEL_MODE_MAX - 1)
enum nft_tunnel_attributes {
NFTA_TUNNEL_UNSPEC,
NFTA_TUNNEL_KEY,
NFTA_TUNNEL_DREG,
NFTA_TUNNEL_MODE,
__NFTA_TUNNEL_MAX
};
#define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1)
......
......@@ -15,6 +15,7 @@
struct nft_tunnel {
enum nft_tunnel_keys key:8;
enum nft_registers dreg:8;
enum nft_tunnel_mode mode:8;
};
static void nft_tunnel_get_eval(const struct nft_expr *expr,
......@@ -29,14 +30,32 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr,
switch (priv->key) {
case NFT_TUNNEL_PATH:
nft_reg_store8(dest, !!tun_info);
if (!tun_info) {
nft_reg_store8(dest, false);
return;
}
if (priv->mode == NFT_TUNNEL_MODE_NONE ||
(priv->mode == NFT_TUNNEL_MODE_RX &&
!(tun_info->mode & IP_TUNNEL_INFO_TX)) ||
(priv->mode == NFT_TUNNEL_MODE_TX &&
(tun_info->mode & IP_TUNNEL_INFO_TX)))
nft_reg_store8(dest, true);
else
nft_reg_store8(dest, false);
break;
case NFT_TUNNEL_ID:
if (!tun_info) {
regs->verdict.code = NFT_BREAK;
return;
}
*dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id));
if (priv->mode == NFT_TUNNEL_MODE_NONE ||
(priv->mode == NFT_TUNNEL_MODE_RX &&
!(tun_info->mode & IP_TUNNEL_INFO_TX)) ||
(priv->mode == NFT_TUNNEL_MODE_TX &&
(tun_info->mode & IP_TUNNEL_INFO_TX)))
*dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id));
else
regs->verdict.code = NFT_BREAK;
break;
default:
WARN_ON(1);
......@@ -47,6 +66,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr,
static const struct nla_policy nft_tunnel_policy[NFTA_TUNNEL_MAX + 1] = {
[NFTA_TUNNEL_KEY] = { .type = NLA_U32 },
[NFTA_TUNNEL_DREG] = { .type = NLA_U32 },
[NFTA_TUNNEL_MODE] = { .type = NLA_U32 },
};
static int nft_tunnel_get_init(const struct nft_ctx *ctx,
......@@ -74,6 +94,14 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx,
priv->dreg = nft_parse_register(tb[NFTA_TUNNEL_DREG]);
if (tb[NFTA_TUNNEL_MODE]) {
priv->mode = ntohl(nla_get_be32(tb[NFTA_TUNNEL_MODE]));
if (priv->mode > NFT_TUNNEL_MODE_MAX)
return -EOPNOTSUPP;
} else {
priv->mode = NFT_TUNNEL_MODE_NONE;
}
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
}
......@@ -87,6 +115,8 @@ static int nft_tunnel_get_dump(struct sk_buff *skb,
goto nla_put_failure;
if (nft_dump_register(skb, NFTA_TUNNEL_DREG, priv->dreg))
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_TUNNEL_MODE, htonl(priv->mode)))
goto nla_put_failure;
return 0;
nla_put_failure:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment