| From 3c4f56cc7fb45c3c97fa1fa7f54373f074417291 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <dada1@cosmosbay.com> |
| Date: Mon, 8 Dec 2008 02:12:16 -0800 |
| Subject: udp: multicast packets need to check namespace |
| |
| From: Eric Dumazet <dada1@cosmosbay.com> |
| |
| [ Upstream commit 920a46115ca3fa88990276d98520abab85495b2d ] |
| |
| Current UDP multicast delivery is not namespace aware. |
| |
| Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> |
| Acked-by: Pavel Emelyanov <xemul@openvz.org> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/ipv4/udp.c | 12 +++++++----- |
| net/ipv6/udp.c | 8 ++++---- |
| 2 files changed, 11 insertions(+), 9 deletions(-) |
| |
| --- a/net/ipv4/udp.c |
| +++ b/net/ipv4/udp.c |
| @@ -302,7 +302,7 @@ static struct sock *__udp4_lib_lookup(st |
| return result; |
| } |
| |
| -static inline struct sock *udp_v4_mcast_next(struct sock *sk, |
| +static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, |
| __be16 loc_port, __be32 loc_addr, |
| __be16 rmt_port, __be32 rmt_addr, |
| int dif) |
| @@ -314,7 +314,8 @@ static inline struct sock *udp_v4_mcast_ |
| sk_for_each_from(s, node) { |
| struct inet_sock *inet = inet_sk(s); |
| |
| - if (s->sk_hash != hnum || |
| + if (!net_eq(sock_net(s), net) || |
| + s->sk_hash != hnum || |
| (inet->daddr && inet->daddr != rmt_addr) || |
| (inet->dport != rmt_port && inet->dport) || |
| (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || |
| @@ -1097,15 +1098,16 @@ static int __udp4_lib_mcast_deliver(stru |
| read_lock(&udp_hash_lock); |
| sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); |
| dif = skb->dev->ifindex; |
| - sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); |
| + sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
| if (sk) { |
| struct sock *sknext = NULL; |
| |
| do { |
| struct sk_buff *skb1 = skb; |
| |
| - sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, |
| - uh->source, saddr, dif); |
| + sknext = udp_v4_mcast_next(net, sk_next(sk), uh->dest, |
| + daddr, uh->source, saddr, |
| + dif); |
| if (sknext) |
| skb1 = skb_clone(skb, GFP_ATOMIC); |
| |
| --- a/net/ipv6/udp.c |
| +++ b/net/ipv6/udp.c |
| @@ -313,7 +313,7 @@ drop: |
| return -1; |
| } |
| |
| -static struct sock *udp_v6_mcast_next(struct sock *sk, |
| +static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, |
| __be16 loc_port, struct in6_addr *loc_addr, |
| __be16 rmt_port, struct in6_addr *rmt_addr, |
| int dif) |
| @@ -325,7 +325,7 @@ static struct sock *udp_v6_mcast_next(st |
| sk_for_each_from(s, node) { |
| struct inet_sock *inet = inet_sk(s); |
| |
| - if (sock_net(s) != sock_net(sk)) |
| + if (!net_eq(sock_net(s), net)) |
| continue; |
| |
| if (s->sk_hash == num && s->sk_family == PF_INET6) { |
| @@ -368,14 +368,14 @@ static int __udp6_lib_mcast_deliver(stru |
| read_lock(&udp_hash_lock); |
| sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); |
| dif = inet6_iif(skb); |
| - sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); |
| + sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
| if (!sk) { |
| kfree_skb(skb); |
| goto out; |
| } |
| |
| sk2 = sk; |
| - while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr, |
| + while ((sk2 = udp_v6_mcast_next(net, sk_next(sk2), uh->dest, daddr, |
| uh->source, saddr, dif))) { |
| struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); |
| if (buff) { |