netfilter: nft_fib_ipv6: skip ipv6 packets from any to link-local

The ip6tables rpfilter match has an extra check to skip packets with
"::" source address.

Extend this to ipv6 fib expression.  Else ipv6 duplicate address detection
packets will fail rpf route check -- lookup returns -ENETUNREACH.

While at it, extend the prerouting check to also cover the ingress hook.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1543
Fixes: f6d0cbcf09 ("netfilter: nf_tables: add fib expression")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2021-06-08 13:48:18 +02:00 committed by Pablo Neira Ayuso
parent 8294442124
commit 12f36e9bf6

View File

@ -135,6 +135,17 @@ void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
}
EXPORT_SYMBOL_GPL(nft_fib6_eval_type);
static bool nft_fib_v6_skip_icmpv6(const struct sk_buff *skb, u8 next, const struct ipv6hdr *iph)
{
if (likely(next != IPPROTO_ICMPV6))
return false;
if (ipv6_addr_type(&iph->saddr) != IPV6_ADDR_ANY)
return false;
return ipv6_addr_type(&iph->daddr) & IPV6_ADDR_LINKLOCAL;
}
void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
@ -163,10 +174,13 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
nft_fib_store_result(dest, priv, nft_in(pkt));
return;
if (nft_hook(pkt) == NF_INET_PRE_ROUTING ||
nft_hook(pkt) == NF_INET_INGRESS) {
if (nft_fib_is_loopback(pkt->skb, nft_in(pkt)) ||
nft_fib_v6_skip_icmpv6(pkt->skb, pkt->tprot, iph)) {
nft_fib_store_result(dest, priv, nft_in(pkt));
return;
}
}
*dest = 0;