aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/mcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/mcast.c')
-rw-r--r--net/ipv6/mcast.c116
1 files changed, 78 insertions, 38 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 197ca390a15d..f2879056fab0 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -126,8 +126,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
126/* Big mc list lock for all the sockets */ 126/* Big mc list lock for all the sockets */
127static DEFINE_RWLOCK(ipv6_sk_mc_lock); 127static DEFINE_RWLOCK(ipv6_sk_mc_lock);
128 128
129static struct socket *igmp6_socket;
130
131int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); 129int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
132 130
133static void igmp6_join_group(struct ifmcaddr6 *ma); 131static void igmp6_join_group(struct ifmcaddr6 *ma);
@@ -183,6 +181,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
183 struct net_device *dev = NULL; 181 struct net_device *dev = NULL;
184 struct ipv6_mc_socklist *mc_lst; 182 struct ipv6_mc_socklist *mc_lst;
185 struct ipv6_pinfo *np = inet6_sk(sk); 183 struct ipv6_pinfo *np = inet6_sk(sk);
184 struct net *net = sk->sk_net;
186 int err; 185 int err;
187 186
188 if (!ipv6_addr_is_multicast(addr)) 187 if (!ipv6_addr_is_multicast(addr))
@@ -208,14 +207,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
208 207
209 if (ifindex == 0) { 208 if (ifindex == 0) {
210 struct rt6_info *rt; 209 struct rt6_info *rt;
211 rt = rt6_lookup(&init_net, addr, NULL, 0, 0); 210 rt = rt6_lookup(net, addr, NULL, 0, 0);
212 if (rt) { 211 if (rt) {
213 dev = rt->rt6i_dev; 212 dev = rt->rt6i_dev;
214 dev_hold(dev); 213 dev_hold(dev);
215 dst_release(&rt->u.dst); 214 dst_release(&rt->u.dst);
216 } 215 }
217 } else 216 } else
218 dev = dev_get_by_index(&init_net, ifindex); 217 dev = dev_get_by_index(net, ifindex);
219 218
220 if (dev == NULL) { 219 if (dev == NULL) {
221 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); 220 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
@@ -256,6 +255,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
256{ 255{
257 struct ipv6_pinfo *np = inet6_sk(sk); 256 struct ipv6_pinfo *np = inet6_sk(sk);
258 struct ipv6_mc_socklist *mc_lst, **lnk; 257 struct ipv6_mc_socklist *mc_lst, **lnk;
258 struct net *net = sk->sk_net;
259 259
260 write_lock_bh(&ipv6_sk_mc_lock); 260 write_lock_bh(&ipv6_sk_mc_lock);
261 for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) { 261 for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
@@ -266,7 +266,8 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
266 *lnk = mc_lst->next; 266 *lnk = mc_lst->next;
267 write_unlock_bh(&ipv6_sk_mc_lock); 267 write_unlock_bh(&ipv6_sk_mc_lock);
268 268
269 if ((dev = dev_get_by_index(&init_net, mc_lst->ifindex)) != NULL) { 269 dev = dev_get_by_index(net, mc_lst->ifindex);
270 if (dev != NULL) {
270 struct inet6_dev *idev = in6_dev_get(dev); 271 struct inet6_dev *idev = in6_dev_get(dev);
271 272
272 (void) ip6_mc_leave_src(sk, mc_lst, idev); 273 (void) ip6_mc_leave_src(sk, mc_lst, idev);
@@ -286,7 +287,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
286 return -EADDRNOTAVAIL; 287 return -EADDRNOTAVAIL;
287} 288}
288 289
289static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex) 290static struct inet6_dev *ip6_mc_find_dev(struct net *net,
291 struct in6_addr *group,
292 int ifindex)
290{ 293{
291 struct net_device *dev = NULL; 294 struct net_device *dev = NULL;
292 struct inet6_dev *idev = NULL; 295 struct inet6_dev *idev = NULL;
@@ -294,14 +297,14 @@ static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
294 if (ifindex == 0) { 297 if (ifindex == 0) {
295 struct rt6_info *rt; 298 struct rt6_info *rt;
296 299
297 rt = rt6_lookup(&init_net, group, NULL, 0, 0); 300 rt = rt6_lookup(net, group, NULL, 0, 0);
298 if (rt) { 301 if (rt) {
299 dev = rt->rt6i_dev; 302 dev = rt->rt6i_dev;
300 dev_hold(dev); 303 dev_hold(dev);
301 dst_release(&rt->u.dst); 304 dst_release(&rt->u.dst);
302 } 305 }
303 } else 306 } else
304 dev = dev_get_by_index(&init_net, ifindex); 307 dev = dev_get_by_index(net, ifindex);
305 308
306 if (!dev) 309 if (!dev)
307 return NULL; 310 return NULL;
@@ -324,6 +327,7 @@ void ipv6_sock_mc_close(struct sock *sk)
324{ 327{
325 struct ipv6_pinfo *np = inet6_sk(sk); 328 struct ipv6_pinfo *np = inet6_sk(sk);
326 struct ipv6_mc_socklist *mc_lst; 329 struct ipv6_mc_socklist *mc_lst;
330 struct net *net = sk->sk_net;
327 331
328 write_lock_bh(&ipv6_sk_mc_lock); 332 write_lock_bh(&ipv6_sk_mc_lock);
329 while ((mc_lst = np->ipv6_mc_list) != NULL) { 333 while ((mc_lst = np->ipv6_mc_list) != NULL) {
@@ -332,7 +336,7 @@ void ipv6_sock_mc_close(struct sock *sk)
332 np->ipv6_mc_list = mc_lst->next; 336 np->ipv6_mc_list = mc_lst->next;
333 write_unlock_bh(&ipv6_sk_mc_lock); 337 write_unlock_bh(&ipv6_sk_mc_lock);
334 338
335 dev = dev_get_by_index(&init_net, mc_lst->ifindex); 339 dev = dev_get_by_index(net, mc_lst->ifindex);
336 if (dev) { 340 if (dev) {
337 struct inet6_dev *idev = in6_dev_get(dev); 341 struct inet6_dev *idev = in6_dev_get(dev);
338 342
@@ -361,6 +365,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
361 struct inet6_dev *idev; 365 struct inet6_dev *idev;
362 struct ipv6_pinfo *inet6 = inet6_sk(sk); 366 struct ipv6_pinfo *inet6 = inet6_sk(sk);
363 struct ip6_sf_socklist *psl; 367 struct ip6_sf_socklist *psl;
368 struct net *net = sk->sk_net;
364 int i, j, rv; 369 int i, j, rv;
365 int leavegroup = 0; 370 int leavegroup = 0;
366 int pmclocked = 0; 371 int pmclocked = 0;
@@ -376,7 +381,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
376 if (!ipv6_addr_is_multicast(group)) 381 if (!ipv6_addr_is_multicast(group))
377 return -EINVAL; 382 return -EINVAL;
378 383
379 idev = ip6_mc_find_dev(group, pgsr->gsr_interface); 384 idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface);
380 if (!idev) 385 if (!idev)
381 return -ENODEV; 386 return -ENODEV;
382 dev = idev->dev; 387 dev = idev->dev;
@@ -500,6 +505,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
500 struct inet6_dev *idev; 505 struct inet6_dev *idev;
501 struct ipv6_pinfo *inet6 = inet6_sk(sk); 506 struct ipv6_pinfo *inet6 = inet6_sk(sk);
502 struct ip6_sf_socklist *newpsl, *psl; 507 struct ip6_sf_socklist *newpsl, *psl;
508 struct net *net = sk->sk_net;
503 int leavegroup = 0; 509 int leavegroup = 0;
504 int i, err; 510 int i, err;
505 511
@@ -511,7 +517,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
511 gsf->gf_fmode != MCAST_EXCLUDE) 517 gsf->gf_fmode != MCAST_EXCLUDE)
512 return -EINVAL; 518 return -EINVAL;
513 519
514 idev = ip6_mc_find_dev(group, gsf->gf_interface); 520 idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
515 521
516 if (!idev) 522 if (!idev)
517 return -ENODEV; 523 return -ENODEV;
@@ -592,13 +598,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
592 struct net_device *dev; 598 struct net_device *dev;
593 struct ipv6_pinfo *inet6 = inet6_sk(sk); 599 struct ipv6_pinfo *inet6 = inet6_sk(sk);
594 struct ip6_sf_socklist *psl; 600 struct ip6_sf_socklist *psl;
601 struct net *net = sk->sk_net;
595 602
596 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; 603 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
597 604
598 if (!ipv6_addr_is_multicast(group)) 605 if (!ipv6_addr_is_multicast(group))
599 return -EINVAL; 606 return -EINVAL;
600 607
601 idev = ip6_mc_find_dev(group, gsf->gf_interface); 608 idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
602 609
603 if (!idev) 610 if (!idev)
604 return -ENODEV; 611 return -ENODEV;
@@ -1393,7 +1400,8 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
1393 1400
1394static struct sk_buff *mld_newpack(struct net_device *dev, int size) 1401static struct sk_buff *mld_newpack(struct net_device *dev, int size)
1395{ 1402{
1396 struct sock *sk = igmp6_socket->sk; 1403 struct net *net = dev->nd_net;
1404 struct sock *sk = net->ipv6.igmp_sk;
1397 struct sk_buff *skb; 1405 struct sk_buff *skb;
1398 struct mld2_report *pmr; 1406 struct mld2_report *pmr;
1399 struct in6_addr addr_buf; 1407 struct in6_addr addr_buf;
@@ -1440,6 +1448,7 @@ static void mld_sendpack(struct sk_buff *skb)
1440 (struct mld2_report *)skb_transport_header(skb); 1448 (struct mld2_report *)skb_transport_header(skb);
1441 int payload_len, mldlen; 1449 int payload_len, mldlen;
1442 struct inet6_dev *idev = in6_dev_get(skb->dev); 1450 struct inet6_dev *idev = in6_dev_get(skb->dev);
1451 struct net *net = skb->dev->nd_net;
1443 int err; 1452 int err;
1444 struct flowi fl; 1453 struct flowi fl;
1445 1454
@@ -1459,7 +1468,7 @@ static void mld_sendpack(struct sk_buff *skb)
1459 goto err_out; 1468 goto err_out;
1460 } 1469 }
1461 1470
1462 icmpv6_flow_init(igmp6_socket->sk, &fl, ICMPV6_MLD2_REPORT, 1471 icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
1463 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 1472 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1464 skb->dev->ifindex); 1473 skb->dev->ifindex);
1465 1474
@@ -1753,7 +1762,8 @@ static void mld_send_cr(struct inet6_dev *idev)
1753 1762
1754static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) 1763static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1755{ 1764{
1756 struct sock *sk = igmp6_socket->sk; 1765 struct net *net = dev->nd_net;
1766 struct sock *sk = net->ipv6.igmp_sk;
1757 struct inet6_dev *idev; 1767 struct inet6_dev *idev;
1758 struct sk_buff *skb; 1768 struct sk_buff *skb;
1759 struct icmp6hdr *hdr; 1769 struct icmp6hdr *hdr;
@@ -1824,7 +1834,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1824 goto err_out; 1834 goto err_out;
1825 } 1835 }
1826 1836
1827 icmpv6_flow_init(igmp6_socket->sk, &fl, type, 1837 icmpv6_flow_init(sk, &fl, type,
1828 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 1838 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1829 skb->dev->ifindex); 1839 skb->dev->ifindex);
1830 1840
@@ -2334,6 +2344,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
2334 2344
2335#ifdef CONFIG_PROC_FS 2345#ifdef CONFIG_PROC_FS
2336struct igmp6_mc_iter_state { 2346struct igmp6_mc_iter_state {
2347 struct seq_net_private p;
2337 struct net_device *dev; 2348 struct net_device *dev;
2338 struct inet6_dev *idev; 2349 struct inet6_dev *idev;
2339}; 2350};
@@ -2344,9 +2355,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
2344{ 2355{
2345 struct ifmcaddr6 *im = NULL; 2356 struct ifmcaddr6 *im = NULL;
2346 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); 2357 struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2358 struct net *net = state->p.net;
2347 2359
2348 state->idev = NULL; 2360 state->idev = NULL;
2349 for_each_netdev(&init_net, state->dev) { 2361 for_each_netdev(net, state->dev) {
2350 struct inet6_dev *idev; 2362 struct inet6_dev *idev;
2351 idev = in6_dev_get(state->dev); 2363 idev = in6_dev_get(state->dev);
2352 if (!idev) 2364 if (!idev)
@@ -2448,8 +2460,8 @@ static const struct seq_operations igmp6_mc_seq_ops = {
2448 2460
2449static int igmp6_mc_seq_open(struct inode *inode, struct file *file) 2461static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
2450{ 2462{
2451 return seq_open_private(file, &igmp6_mc_seq_ops, 2463 return seq_open_net(inode, file, &igmp6_mc_seq_ops,
2452 sizeof(struct igmp6_mc_iter_state)); 2464 sizeof(struct igmp6_mc_iter_state));
2453} 2465}
2454 2466
2455static const struct file_operations igmp6_mc_seq_fops = { 2467static const struct file_operations igmp6_mc_seq_fops = {
@@ -2457,10 +2469,11 @@ static const struct file_operations igmp6_mc_seq_fops = {
2457 .open = igmp6_mc_seq_open, 2469 .open = igmp6_mc_seq_open,
2458 .read = seq_read, 2470 .read = seq_read,
2459 .llseek = seq_lseek, 2471 .llseek = seq_lseek,
2460 .release = seq_release_private, 2472 .release = seq_release_net,
2461}; 2473};
2462 2474
2463struct igmp6_mcf_iter_state { 2475struct igmp6_mcf_iter_state {
2476 struct seq_net_private p;
2464 struct net_device *dev; 2477 struct net_device *dev;
2465 struct inet6_dev *idev; 2478 struct inet6_dev *idev;
2466 struct ifmcaddr6 *im; 2479 struct ifmcaddr6 *im;
@@ -2473,10 +2486,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
2473 struct ip6_sf_list *psf = NULL; 2486 struct ip6_sf_list *psf = NULL;
2474 struct ifmcaddr6 *im = NULL; 2487 struct ifmcaddr6 *im = NULL;
2475 struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); 2488 struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2489 struct net *net = state->p.net;
2476 2490
2477 state->idev = NULL; 2491 state->idev = NULL;
2478 state->im = NULL; 2492 state->im = NULL;
2479 for_each_netdev(&init_net, state->dev) { 2493 for_each_netdev(net, state->dev) {
2480 struct inet6_dev *idev; 2494 struct inet6_dev *idev;
2481 idev = in6_dev_get(state->dev); 2495 idev = in6_dev_get(state->dev);
2482 if (unlikely(idev == NULL)) 2496 if (unlikely(idev == NULL))
@@ -2608,8 +2622,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = {
2608 2622
2609static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) 2623static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
2610{ 2624{
2611 return seq_open_private(file, &igmp6_mcf_seq_ops, 2625 return seq_open_net(inode, file, &igmp6_mcf_seq_ops,
2612 sizeof(struct igmp6_mcf_iter_state)); 2626 sizeof(struct igmp6_mcf_iter_state));
2613} 2627}
2614 2628
2615static const struct file_operations igmp6_mcf_seq_fops = { 2629static const struct file_operations igmp6_mcf_seq_fops = {
@@ -2617,26 +2631,27 @@ static const struct file_operations igmp6_mcf_seq_fops = {
2617 .open = igmp6_mcf_seq_open, 2631 .open = igmp6_mcf_seq_open,
2618 .read = seq_read, 2632 .read = seq_read,
2619 .llseek = seq_lseek, 2633 .llseek = seq_lseek,
2620 .release = seq_release_private, 2634 .release = seq_release_net,
2621}; 2635};
2622#endif 2636#endif
2623 2637
2624int __init igmp6_init(void) 2638static int igmp6_net_init(struct net *net)
2625{ 2639{
2626 struct ipv6_pinfo *np; 2640 struct ipv6_pinfo *np;
2641 struct socket *sock;
2627 struct sock *sk; 2642 struct sock *sk;
2628 int err; 2643 int err;
2629 2644
2630 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); 2645 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock);
2631 if (err < 0) { 2646 if (err < 0) {
2632 printk(KERN_ERR 2647 printk(KERN_ERR
2633 "Failed to initialize the IGMP6 control socket (err %d).\n", 2648 "Failed to initialize the IGMP6 control socket (err %d).\n",
2634 err); 2649 err);
2635 igmp6_socket = NULL; /* For safety. */ 2650 goto out;
2636 return err;
2637 } 2651 }
2638 2652
2639 sk = igmp6_socket->sk; 2653 net->ipv6.igmp_sk = sk = sock->sk;
2654 sk_change_net(sk, net);
2640 sk->sk_allocation = GFP_ATOMIC; 2655 sk->sk_allocation = GFP_ATOMIC;
2641 sk->sk_prot->unhash(sk); 2656 sk->sk_prot->unhash(sk);
2642 2657
@@ -2644,20 +2659,45 @@ int __init igmp6_init(void)
2644 np->hop_limit = 1; 2659 np->hop_limit = 1;
2645 2660
2646#ifdef CONFIG_PROC_FS 2661#ifdef CONFIG_PROC_FS
2647 proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops); 2662 err = -ENOMEM;
2648 proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops); 2663 if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops))
2664 goto out_sock_create;
2665 if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO,
2666 &igmp6_mcf_seq_fops)) {
2667 proc_net_remove(net, "igmp6");
2668 goto out_sock_create;
2669 }
2649#endif 2670#endif
2650 2671
2651 return 0; 2672 err = 0;
2673out:
2674 return err;
2675
2676out_sock_create:
2677 sk_release_kernel(net->ipv6.igmp_sk);
2678 goto out;
2652} 2679}
2653 2680
2654void igmp6_cleanup(void) 2681static void igmp6_net_exit(struct net *net)
2655{ 2682{
2656 sock_release(igmp6_socket); 2683 sk_release_kernel(net->ipv6.igmp_sk);
2657 igmp6_socket = NULL; /* for safety */
2658
2659#ifdef CONFIG_PROC_FS 2684#ifdef CONFIG_PROC_FS
2660 proc_net_remove(&init_net, "mcfilter6"); 2685 proc_net_remove(net, "mcfilter6");
2661 proc_net_remove(&init_net, "igmp6"); 2686 proc_net_remove(net, "igmp6");
2662#endif 2687#endif
2663} 2688}
2689
2690static struct pernet_operations igmp6_net_ops = {
2691 .init = igmp6_net_init,
2692 .exit = igmp6_net_exit,
2693};
2694
2695int __init igmp6_init(void)
2696{
2697 return register_pernet_subsys(&igmp6_net_ops);
2698}
2699
2700void igmp6_cleanup(void)
2701{
2702 unregister_pernet_subsys(&igmp6_net_ops);
2703}