Commit 920a4611 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

udp: multicast packets need to check namespace

Current UDP multicast delivery is not namespace aware.
Signed-off-by: default avatarEric Dumazet <dada1@cosmosbay.com>
Acked-by: default avatarPavel Emelyanov <xemul@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d1a203ea
...@@ -284,7 +284,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, ...@@ -284,7 +284,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
} }
EXPORT_SYMBOL_GPL(udp4_lib_lookup); EXPORT_SYMBOL_GPL(udp4_lib_lookup);
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 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr, __be16 rmt_port, __be32 rmt_addr,
int dif) int dif)
...@@ -296,7 +296,8 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk, ...@@ -296,7 +296,8 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk,
sk_for_each_from(s, node) { sk_for_each_from(s, node) {
struct inet_sock *inet = inet_sk(s); 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->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) || (inet->dport != rmt_port && inet->dport) ||
(inet->rcv_saddr && inet->rcv_saddr != loc_addr) || (inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
...@@ -1079,15 +1080,16 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, ...@@ -1079,15 +1080,16 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]);
dif = skb->dev->ifindex; 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) { if (sk) {
struct sock *sknext = NULL; struct sock *sknext = NULL;
do { do {
struct sk_buff *skb1 = skb; struct sk_buff *skb1 = skb;
sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, sknext = udp_v4_mcast_next(net, sk_next(sk), uh->dest,
uh->source, saddr, dif); daddr, uh->source, saddr,
dif);
if (sknext) if (sknext)
skb1 = skb_clone(skb, GFP_ATOMIC); skb1 = skb_clone(skb, GFP_ATOMIC);
......
...@@ -328,7 +328,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) ...@@ -328,7 +328,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
return -1; 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 loc_port, struct in6_addr *loc_addr,
__be16 rmt_port, struct in6_addr *rmt_addr, __be16 rmt_port, struct in6_addr *rmt_addr,
int dif) int dif)
...@@ -340,7 +340,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, ...@@ -340,7 +340,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
sk_for_each_from(s, node) { sk_for_each_from(s, node) {
struct inet_sock *inet = inet_sk(s); struct inet_sock *inet = inet_sk(s);
if (sock_net(s) != sock_net(sk)) if (!net_eq(sock_net(s), net))
continue; continue;
if (s->sk_hash == num && s->sk_family == PF_INET6) { if (s->sk_hash == num && s->sk_family == PF_INET6) {
...@@ -383,14 +383,14 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, ...@@ -383,14 +383,14 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]);
dif = inet6_iif(skb); 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) { if (!sk) {
kfree_skb(skb); kfree_skb(skb);
goto out; goto out;
} }
sk2 = sk; 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))) { uh->source, saddr, dif))) {
struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
if (buff) { if (buff) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment