From: Anders K. Pedersen <akp@xxxxxxxxxxxx> Add meta support for IPv4 nexthop and IPv6 nexthop6 (i.e. the directly connected IP address that an outgoing packet is sent to), which can be used either for matching or accounting, eg. # nft add rule filter postrouting \ ip daddr 192.168.1.0/24 meta nexthop != 192.168.0.1 drop This will drop any traffic to 192.168.1.0/24 that is not routed via 192.168.0.1. # nft add rule filter postrouting \ flow table acct { meta nexthop timeout 600s counter } # nft add rule ip6 filter postrouting \ flow table acct { meta nexthop6 timeout 600s counter } These rules count outgoing traffic per nexthop. Note that the timeout releases an entry if no traffic is seen for this nexthop within 10 minutes. Signed-off-by: Anders K. Pedersen <akp@xxxxxxxxxxxx> --- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_meta.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 24161e2..6ef8ac9 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -721,6 +721,8 @@ enum nft_meta_keys { NFT_META_OIFGROUP, NFT_META_CGROUP, NFT_META_PRANDOM, + NFT_META_NEXTHOP, + NFT_META_NEXTHOP6, }; /** diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 2863f34..a283c80 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -20,6 +20,8 @@ #include <linux/smp.h> #include <linux/static_key.h> #include <net/dst.h> +#include <net/ip6_route.h> +#include <net/route.h> #include <net/sock.h> #include <net/tcp_states.h> /* for TCP_TIME_WAIT */ #include <net/netfilter/nf_tables.h> @@ -188,6 +190,23 @@ void nft_meta_get_eval(const struct nft_expr *expr, *dest = prandom_u32_state(state); break; } + case NFT_META_NEXTHOP: { + const struct rtable *rt = skb_rtable(skb); + + if (pkt->pf != NFPROTO_IPV4 || !rt) + goto err; + *dest = rt_nexthop(rt, ip_hdr(skb)->daddr); + break; + } + case NFT_META_NEXTHOP6: { + struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); + + if (pkt->pf != NFPROTO_IPV6 || !rt) + goto err; + memcpy(dest, rt6_nexthop(rt, &ipv6_hdr(skb)->daddr), + sizeof(struct in6_addr)); + break; + } default: WARN_ON(1); goto err; @@ -271,8 +290,12 @@ int nft_meta_get_init(const struct nft_ctx *ctx, #ifdef CONFIG_CGROUP_NET_CLASSID case NFT_META_CGROUP: #endif + case NFT_META_NEXTHOP: len = sizeof(u32); break; + case NFT_META_NEXTHOP6: + len = sizeof(struct in6_addr); + break; case NFT_META_IIFNAME: case NFT_META_OIFNAME: len = IFNAMSIZ;��.n��������+%������w��{.n����z�����n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�