mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +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
|
#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);
|
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 (rt->rt_flags&RTCF_MULTICAST) {
|
||||||
if ((!sk || inet_sk(sk)->mc_loop)
|
if (sk_mc_loop(sk)
|
||||||
#ifdef CONFIG_IP_MROUTE
|
#ifdef CONFIG_IP_MROUTE
|
||||||
/* Small optimization: do not loopback not local frames,
|
/* Small optimization: do not loopback not local frames,
|
||||||
which returned after forwarding; they will be dropped
|
which returned after forwarding; they will be dropped
|
||||||
|
|
|
@ -121,10 +121,9 @@ static int ip6_output2(struct sk_buff *skb)
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
|
||||||
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
|
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));
|
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)) &&
|
((mroute6_socket(dev_net(dev)) &&
|
||||||
!(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
|
!(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
|
||||||
ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
|
ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
|
||||||
|
|
Loading…
Reference in a new issue