diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2008-11-02 00:22:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-02 00:22:23 -0400 |
commit | 920a46115ca3fa88990276d98520abab85495b2d (patch) | |
tree | a0960e925f2426da9766acfed2dbee144f30299c | |
parent | d1a203eac0ec13cd1c0ba610fe7a55c9bc40473b (diff) |
udp: multicast packets need to check namespace
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>
-rw-r--r-- | net/ipv4/udp.c | 12 | ||||
-rw-r--r-- | net/ipv6/udp.c | 8 |
2 files changed, 11 insertions, 9 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2095abc3cab..cf02701ced4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -284,7 +284,7 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, | |||
284 | } | 284 | } |
285 | EXPORT_SYMBOL_GPL(udp4_lib_lookup); | 285 | EXPORT_SYMBOL_GPL(udp4_lib_lookup); |
286 | 286 | ||
287 | static inline struct sock *udp_v4_mcast_next(struct sock *sk, | 287 | static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, |
288 | __be16 loc_port, __be32 loc_addr, | 288 | __be16 loc_port, __be32 loc_addr, |
289 | __be16 rmt_port, __be32 rmt_addr, | 289 | __be16 rmt_port, __be32 rmt_addr, |
290 | int dif) | 290 | int dif) |
@@ -296,7 +296,8 @@ static inline struct sock *udp_v4_mcast_next(struct sock *sk, | |||
296 | sk_for_each_from(s, node) { | 296 | sk_for_each_from(s, node) { |
297 | struct inet_sock *inet = inet_sk(s); | 297 | struct inet_sock *inet = inet_sk(s); |
298 | 298 | ||
299 | if (s->sk_hash != hnum || | 299 | if (!net_eq(sock_net(s), net) || |
300 | s->sk_hash != hnum || | ||
300 | (inet->daddr && inet->daddr != rmt_addr) || | 301 | (inet->daddr && inet->daddr != rmt_addr) || |
301 | (inet->dport != rmt_port && inet->dport) || | 302 | (inet->dport != rmt_port && inet->dport) || |
302 | (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || | 303 | (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 | read_lock(&udp_hash_lock); | 1080 | read_lock(&udp_hash_lock); |
1080 | sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); | 1081 | sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); |
1081 | dif = skb->dev->ifindex; | 1082 | dif = skb->dev->ifindex; |
1082 | sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); | 1083 | sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
1083 | if (sk) { | 1084 | if (sk) { |
1084 | struct sock *sknext = NULL; | 1085 | struct sock *sknext = NULL; |
1085 | 1086 | ||
1086 | do { | 1087 | do { |
1087 | struct sk_buff *skb1 = skb; | 1088 | struct sk_buff *skb1 = skb; |
1088 | 1089 | ||
1089 | sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr, | 1090 | sknext = udp_v4_mcast_next(net, sk_next(sk), uh->dest, |
1090 | uh->source, saddr, dif); | 1091 | daddr, uh->source, saddr, |
1092 | dif); | ||
1091 | if (sknext) | 1093 | if (sknext) |
1092 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1094 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1093 | 1095 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e51da8c092f..71e259e866a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -328,7 +328,7 @@ drop: | |||
328 | return -1; | 328 | return -1; |
329 | } | 329 | } |
330 | 330 | ||
331 | static struct sock *udp_v6_mcast_next(struct sock *sk, | 331 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, |
332 | __be16 loc_port, struct in6_addr *loc_addr, | 332 | __be16 loc_port, struct in6_addr *loc_addr, |
333 | __be16 rmt_port, struct in6_addr *rmt_addr, | 333 | __be16 rmt_port, struct in6_addr *rmt_addr, |
334 | int dif) | 334 | int dif) |
@@ -340,7 +340,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
340 | sk_for_each_from(s, node) { | 340 | sk_for_each_from(s, node) { |
341 | struct inet_sock *inet = inet_sk(s); | 341 | struct inet_sock *inet = inet_sk(s); |
342 | 342 | ||
343 | if (sock_net(s) != sock_net(sk)) | 343 | if (!net_eq(sock_net(s), net)) |
344 | continue; | 344 | continue; |
345 | 345 | ||
346 | if (s->sk_hash == num && s->sk_family == PF_INET6) { | 346 | 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 | read_lock(&udp_hash_lock); | 383 | read_lock(&udp_hash_lock); |
384 | sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); | 384 | sk = sk_head(&udptable[udp_hashfn(net, ntohs(uh->dest))]); |
385 | dif = inet6_iif(skb); | 385 | dif = inet6_iif(skb); |
386 | sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); | 386 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
387 | if (!sk) { | 387 | if (!sk) { |
388 | kfree_skb(skb); | 388 | kfree_skb(skb); |
389 | goto out; | 389 | goto out; |
390 | } | 390 | } |
391 | 391 | ||
392 | sk2 = sk; | 392 | sk2 = sk; |
393 | while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr, | 393 | while ((sk2 = udp_v6_mcast_next(net, sk_next(sk2), uh->dest, daddr, |
394 | uh->source, saddr, dif))) { | 394 | uh->source, saddr, dif))) { |
395 | struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); | 395 | struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); |
396 | if (buff) { | 396 | if (buff) { |