mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
ip: fix mc_loop checks for tunnels with multicast outer addresses
When we have L3 tunnels with different inner/outer families (i.e. IPV4/IPV6) which use a multicast address as the outer tunnel destination address, multicast packets will be loopbacked back to the sending socket even if IP*_MULTICAST_LOOP is set to disabled. The mc_loop flag is present in the family specific part of the socket (e.g. the IPv4 or IPv4 specific part). setsockopt sets the inner family mc_loop flag. When the packet is pushed through the L3 tunnel it will eventually be processed by the outer family which if different will check the flag in a different part of the socket then it was set. Signed-off-by: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
58933c643f
commit
7ad6848c7e
3 changed files with 18 additions and 3 deletions
|
@ -326,6 +326,22 @@ static __inline__ void inet_reset_saddr(struct sock *sk)
|
|||
|
||||
#endif
|
||||
|
||||
static inline int sk_mc_loop(struct sock *sk)
|
||||
{
|
||||
if (!sk)
|
||||
return 1;
|
||||
switch (sk->sk_family) {
|
||||
case AF_INET:
|
||||
return inet_sk(sk)->mc_loop;
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
case AF_INET6:
|
||||
return inet6_sk(sk)->mc_loop;
|
||||
#endif
|
||||
}
|
||||
__WARN();
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int ip_call_ra_chain(struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
|
|
|
@ -254,7 +254,7 @@ int ip_mc_output(struct sk_buff *skb)
|
|||
*/
|
||||
|
||||
if (rt->rt_flags&RTCF_MULTICAST) {
|
||||
if ((!sk || inet_sk(sk)->mc_loop)
|
||||
if (sk_mc_loop(sk)
|
||||
#ifdef CONFIG_IP_MROUTE
|
||||
/* Small optimization: do not loopback not local frames,
|
||||
which returned after forwarding; they will be dropped
|
||||
|
|
|
@ -121,10 +121,9 @@ static int ip6_output2(struct sk_buff *skb)
|
|||
skb->dev = dev;
|
||||
|
||||
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
|
||||
struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL;
|
||||
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
|
||||
|
||||
if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
|
||||
if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) &&
|
||||
((mroute6_socket(dev_net(dev)) &&
|
||||
!(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
|
||||
ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
|
||||
|
|
Loading…
Reference in a new issue