Commit c14ceb0e authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: nft_meta: add support for slave device ifindex matching

Allow to match on vrf slave ifindex or name.

In case there was no slave interface involved, store 0 in the
destination register just like existing iif/oif matching.

sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
as it depends on ip(6) stack parsing/storing info in skb->cb[].

Cc: Martin Willi <martin@strongswan.org>
Cc: David Ahern <dsahern@kernel.org>
Cc: Shrijeet Mukherjee <shrijeet@gmail.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 01a0fc82
...@@ -805,6 +805,8 @@ enum nft_exthdr_attributes { ...@@ -805,6 +805,8 @@ enum nft_exthdr_attributes {
* @NFT_META_TIME_NS: time since epoch (in nanoseconds) * @NFT_META_TIME_NS: time since epoch (in nanoseconds)
* @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday) * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
* @NFT_META_TIME_HOUR: hour of day (in seconds) * @NFT_META_TIME_HOUR: hour of day (in seconds)
* @NFT_META_SDIF: slave device interface index
* @NFT_META_SDIFNAME: slave device interface name
*/ */
enum nft_meta_keys { enum nft_meta_keys {
NFT_META_LEN, NFT_META_LEN,
...@@ -840,6 +842,8 @@ enum nft_meta_keys { ...@@ -840,6 +842,8 @@ enum nft_meta_keys {
NFT_META_TIME_NS, NFT_META_TIME_NS,
NFT_META_TIME_DAY, NFT_META_TIME_DAY,
NFT_META_TIME_HOUR, NFT_META_TIME_HOUR,
NFT_META_SDIF,
NFT_META_SDIFNAME,
}; };
/** /**
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/static_key.h> #include <linux/static_key.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/ip.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/tcp_states.h> /* for TCP_TIME_WAIT */ #include <net/tcp_states.h> /* for TCP_TIME_WAIT */
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
...@@ -287,6 +288,28 @@ nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest) ...@@ -287,6 +288,28 @@ nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
} }
#endif #endif
static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
{
switch (nft_pf(pkt)) {
case NFPROTO_IPV4:
return inet_sdif(pkt->skb);
case NFPROTO_IPV6:
return inet6_sdif(pkt->skb);
}
return 0;
}
static noinline void
nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
{
u32 sdif = nft_meta_get_eval_sdif(pkt);
const struct net_device *dev;
dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
nft_meta_store_ifname(dest, dev);
}
void nft_meta_get_eval(const struct nft_expr *expr, void nft_meta_get_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
...@@ -379,6 +402,12 @@ void nft_meta_get_eval(const struct nft_expr *expr, ...@@ -379,6 +402,12 @@ void nft_meta_get_eval(const struct nft_expr *expr,
case NFT_META_TIME_HOUR: case NFT_META_TIME_HOUR:
nft_meta_get_eval_time(priv->key, dest); nft_meta_get_eval_time(priv->key, dest);
break; break;
case NFT_META_SDIF:
*dest = nft_meta_get_eval_sdif(pkt);
break;
case NFT_META_SDIFNAME:
nft_meta_get_eval_sdifname(dest, pkt);
break;
default: default:
WARN_ON(1); WARN_ON(1);
goto err; goto err;
...@@ -459,6 +488,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, ...@@ -459,6 +488,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
case NFT_META_MARK: case NFT_META_MARK:
case NFT_META_IIF: case NFT_META_IIF:
case NFT_META_OIF: case NFT_META_OIF:
case NFT_META_SDIF:
case NFT_META_SKUID: case NFT_META_SKUID:
case NFT_META_SKGID: case NFT_META_SKGID:
#ifdef CONFIG_IP_ROUTE_CLASSID #ifdef CONFIG_IP_ROUTE_CLASSID
...@@ -480,6 +510,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx, ...@@ -480,6 +510,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
case NFT_META_OIFNAME: case NFT_META_OIFNAME:
case NFT_META_IIFKIND: case NFT_META_IIFKIND:
case NFT_META_OIFKIND: case NFT_META_OIFKIND:
case NFT_META_SDIFNAME:
len = IFNAMSIZ; len = IFNAMSIZ;
break; break;
case NFT_META_PRANDOM: case NFT_META_PRANDOM:
...@@ -510,16 +541,28 @@ int nft_meta_get_init(const struct nft_ctx *ctx, ...@@ -510,16 +541,28 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
} }
EXPORT_SYMBOL_GPL(nft_meta_get_init); EXPORT_SYMBOL_GPL(nft_meta_get_init);
static int nft_meta_get_validate(const struct nft_ctx *ctx, static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
const struct nft_expr *expr,
const struct nft_data **data)
{ {
#ifdef CONFIG_XFRM
const struct nft_meta *priv = nft_expr_priv(expr);
unsigned int hooks; unsigned int hooks;
if (priv->key != NFT_META_SECPATH) switch (ctx->family) {
return 0; case NFPROTO_IPV4:
case NFPROTO_IPV6:
case NFPROTO_INET:
hooks = (1 << NF_INET_LOCAL_IN) |
(1 << NF_INET_FORWARD);
break;
default:
return -EOPNOTSUPP;
}
return nft_chain_validate_hooks(ctx->chain, hooks);
}
static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
{
#ifdef CONFIG_XFRM
unsigned int hooks;
switch (ctx->family) { switch (ctx->family) {
case NFPROTO_NETDEV: case NFPROTO_NETDEV:
...@@ -542,6 +585,25 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx, ...@@ -542,6 +585,25 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx,
#endif #endif
} }
static int nft_meta_get_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data)
{
const struct nft_meta *priv = nft_expr_priv(expr);
switch (priv->key) {
case NFT_META_SECPATH:
return nft_meta_get_validate_xfrm(ctx);
case NFT_META_SDIF:
case NFT_META_SDIFNAME:
return nft_meta_get_validate_sdif(ctx);
default:
break;
}
return 0;
}
int nft_meta_set_validate(const struct nft_ctx *ctx, int nft_meta_set_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nft_data **data) const struct nft_data **data)
......
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