]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: ipv6: ip6mr: Fix in/out netdev to pass to the FORWARD chain
authorPetr Machata <petrm@nvidia.com>
Mon, 16 Jun 2025 22:44:15 +0000 (00:44 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Aug 2025 10:04:56 +0000 (12:04 +0200)
[ Upstream commit 3365afd3abda5f6a54f4a822dad5c9314e94c3fc ]

The netfilter hook is invoked with skb->dev for input netdevice, and
vif_dev for output netdevice. However at the point of invocation, skb->dev
is already set to vif_dev, and MR-forwarded packets are reported with
in=out:

 # ip6tables -A FORWARD -j LOG --log-prefix '[forw]'
 # cd tools/testing/selftests/net/forwarding
 # ./router_multicast.sh
 # dmesg | fgrep '[forw]'
 [ 1670.248245] [forw]IN=v5 OUT=v5 [...]

For reference, IPv4 MR code shows in and out as appropriate.
Fix by caching skb->dev and using the updated value for output netdev.

Fixes: 7bc570c8b4f7 ("[IPV6] MROUTE: Support multicast forwarding.")
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/3141ae8386fbe13fef4b793faa75e6bae58d798a.1750113335.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv6/ip6mr.c

index 138f6aee70afcc03725502a35e9e1eeb43d7256a..06f66531628fec0036f9f6e608cc39a6ce732b3b 100644 (file)
@@ -2045,6 +2045,7 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
                          struct sk_buff *skb, int vifi)
 {
        struct vif_device *vif = &mrt->vif_table[vifi];
+       struct net_device *indev = skb->dev;
        struct net_device *vif_dev;
        struct ipv6hdr *ipv6h;
        struct dst_entry *dst;
@@ -2107,7 +2108,7 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
        IP6CB(skb)->flags |= IP6SKB_FORWARDED;
 
        return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
-                      net, NULL, skb, skb->dev, vif_dev,
+                      net, NULL, skb, indev, skb->dev,
                       ip6mr_forward2_finish);
 
 out_free: