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.c207
1 files changed, 147 insertions, 60 deletions
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index ab228d1ea114..957ac7e9e929 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(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(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;
@@ -1433,25 +1441,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
1433 return skb; 1441 return skb;
1434} 1442}
1435 1443
1436static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
1437{
1438 struct net_device *dev = skb->dev;
1439 unsigned char ha[MAX_ADDR_LEN];
1440
1441 ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1);
1442 if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) {
1443 kfree_skb(skb);
1444 return -EINVAL;
1445 }
1446 return dev_queue_xmit(skb);
1447}
1448
1449static inline int mld_dev_queue_xmit(struct sk_buff *skb)
1450{
1451 return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
1452 mld_dev_queue_xmit2);
1453}
1454
1455static void mld_sendpack(struct sk_buff *skb) 1444static void mld_sendpack(struct sk_buff *skb)
1456{ 1445{
1457 struct ipv6hdr *pip6 = ipv6_hdr(skb); 1446 struct ipv6hdr *pip6 = ipv6_hdr(skb);
@@ -1459,7 +1448,9 @@ static void mld_sendpack(struct sk_buff *skb)
1459 (struct mld2_report *)skb_transport_header(skb); 1448 (struct mld2_report *)skb_transport_header(skb);
1460 int payload_len, mldlen; 1449 int payload_len, mldlen;
1461 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;
1462 int err; 1452 int err;
1453 struct flowi fl;
1463 1454
1464 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); 1455 IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
1465 payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); 1456 payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
@@ -1469,8 +1460,25 @@ static void mld_sendpack(struct sk_buff *skb)
1469 pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, 1460 pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
1470 IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), 1461 IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
1471 mldlen, 0)); 1462 mldlen, 0));
1463
1464 skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
1465
1466 if (!skb->dst) {
1467 err = -ENOMEM;
1468 goto err_out;
1469 }
1470
1471 icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
1472 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1473 skb->dev->ifindex);
1474
1475 err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
1476 if (err)
1477 goto err_out;
1478
1472 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, 1479 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
1473 mld_dev_queue_xmit); 1480 dst_output);
1481out:
1474 if (!err) { 1482 if (!err) {
1475 ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT); 1483 ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
1476 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); 1484 ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
@@ -1480,6 +1488,11 @@ static void mld_sendpack(struct sk_buff *skb)
1480 1488
1481 if (likely(idev != NULL)) 1489 if (likely(idev != NULL))
1482 in6_dev_put(idev); 1490 in6_dev_put(idev);
1491 return;
1492
1493err_out:
1494 kfree_skb(skb);
1495 goto out;
1483} 1496}
1484 1497
1485static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) 1498static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
@@ -1749,7 +1762,8 @@ static void mld_send_cr(struct inet6_dev *idev)
1749 1762
1750static 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)
1751{ 1764{
1752 struct sock *sk = igmp6_socket->sk; 1765 struct net *net = dev->nd_net;
1766 struct sock *sk = net->ipv6.igmp_sk;
1753 struct inet6_dev *idev; 1767 struct inet6_dev *idev;
1754 struct sk_buff *skb; 1768 struct sk_buff *skb;
1755 struct icmp6hdr *hdr; 1769 struct icmp6hdr *hdr;
@@ -1761,6 +1775,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1761 u8 ra[8] = { IPPROTO_ICMPV6, 0, 1775 u8 ra[8] = { IPPROTO_ICMPV6, 0,
1762 IPV6_TLV_ROUTERALERT, 2, 0, 0, 1776 IPV6_TLV_ROUTERALERT, 2, 0, 0,
1763 IPV6_TLV_PADN, 0 }; 1777 IPV6_TLV_PADN, 0 };
1778 struct flowi fl;
1764 1779
1765 rcu_read_lock(); 1780 rcu_read_lock();
1766 IP6_INC_STATS(__in6_dev_get(dev), 1781 IP6_INC_STATS(__in6_dev_get(dev),
@@ -1813,8 +1828,23 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1813 1828
1814 idev = in6_dev_get(skb->dev); 1829 idev = in6_dev_get(skb->dev);
1815 1830
1831 skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
1832 if (!skb->dst) {
1833 err = -ENOMEM;
1834 goto err_out;
1835 }
1836
1837 icmpv6_flow_init(sk, &fl, type,
1838 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1839 skb->dev->ifindex);
1840
1841 err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
1842 if (err)
1843 goto err_out;
1844
1816 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, 1845 err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
1817 mld_dev_queue_xmit); 1846 dst_output);
1847out:
1818 if (!err) { 1848 if (!err) {
1819 ICMP6MSGOUT_INC_STATS(idev, type); 1849 ICMP6MSGOUT_INC_STATS(idev, type);
1820 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); 1850 ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
@@ -1825,6 +1855,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1825 if (likely(idev != NULL)) 1855 if (likely(idev != NULL))
1826 in6_dev_put(idev); 1856 in6_dev_put(idev);
1827 return; 1857 return;
1858
1859err_out:
1860 kfree_skb(skb);
1861 goto out;
1828} 1862}
1829 1863
1830static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, 1864static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
@@ -2310,6 +2344,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
2310 2344
2311#ifdef CONFIG_PROC_FS 2345#ifdef CONFIG_PROC_FS
2312struct igmp6_mc_iter_state { 2346struct igmp6_mc_iter_state {
2347 struct seq_net_private p;
2313 struct net_device *dev; 2348 struct net_device *dev;
2314 struct inet6_dev *idev; 2349 struct inet6_dev *idev;
2315}; 2350};
@@ -2320,9 +2355,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
2320{ 2355{
2321 struct ifmcaddr6 *im = NULL; 2356 struct ifmcaddr6 *im = NULL;
2322 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;
2323 2359
2324 state->idev = NULL; 2360 state->idev = NULL;
2325 for_each_netdev(&init_net, state->dev) { 2361 for_each_netdev(net, state->dev) {
2326 struct inet6_dev *idev; 2362 struct inet6_dev *idev;
2327 idev = in6_dev_get(state->dev); 2363 idev = in6_dev_get(state->dev);
2328 if (!idev) 2364 if (!idev)
@@ -2424,8 +2460,8 @@ static const struct seq_operations igmp6_mc_seq_ops = {
2424 2460
2425static int igmp6_mc_seq_open(struct inode *inode, struct file *file) 2461static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
2426{ 2462{
2427 return seq_open_private(file, &igmp6_mc_seq_ops, 2463 return seq_open_net(inode, file, &igmp6_mc_seq_ops,
2428 sizeof(struct igmp6_mc_iter_state)); 2464 sizeof(struct igmp6_mc_iter_state));
2429} 2465}
2430 2466
2431static const struct file_operations igmp6_mc_seq_fops = { 2467static const struct file_operations igmp6_mc_seq_fops = {
@@ -2433,10 +2469,11 @@ static const struct file_operations igmp6_mc_seq_fops = {
2433 .open = igmp6_mc_seq_open, 2469 .open = igmp6_mc_seq_open,
2434 .read = seq_read, 2470 .read = seq_read,
2435 .llseek = seq_lseek, 2471 .llseek = seq_lseek,
2436 .release = seq_release_private, 2472 .release = seq_release_net,
2437}; 2473};
2438 2474
2439struct igmp6_mcf_iter_state { 2475struct igmp6_mcf_iter_state {
2476 struct seq_net_private p;
2440 struct net_device *dev; 2477 struct net_device *dev;
2441 struct inet6_dev *idev; 2478 struct inet6_dev *idev;
2442 struct ifmcaddr6 *im; 2479 struct ifmcaddr6 *im;
@@ -2449,10 +2486,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
2449 struct ip6_sf_list *psf = NULL; 2486 struct ip6_sf_list *psf = NULL;
2450 struct ifmcaddr6 *im = NULL; 2487 struct ifmcaddr6 *im = NULL;
2451 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;
2452 2490
2453 state->idev = NULL; 2491 state->idev = NULL;
2454 state->im = NULL; 2492 state->im = NULL;
2455 for_each_netdev(&init_net, state->dev) { 2493 for_each_netdev(net, state->dev) {
2456 struct inet6_dev *idev; 2494 struct inet6_dev *idev;
2457 idev = in6_dev_get(state->dev); 2495 idev = in6_dev_get(state->dev);
2458 if (unlikely(idev == NULL)) 2496 if (unlikely(idev == NULL))
@@ -2584,8 +2622,8 @@ static const struct seq_operations igmp6_mcf_seq_ops = {
2584 2622
2585static int igmp6_mcf_seq_open(struct inode *inode, struct file *file) 2623static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
2586{ 2624{
2587 return seq_open_private(file, &igmp6_mcf_seq_ops, 2625 return seq_open_net(inode, file, &igmp6_mcf_seq_ops,
2588 sizeof(struct igmp6_mcf_iter_state)); 2626 sizeof(struct igmp6_mcf_iter_state));
2589} 2627}
2590 2628
2591static const struct file_operations igmp6_mcf_seq_fops = { 2629static const struct file_operations igmp6_mcf_seq_fops = {
@@ -2593,47 +2631,96 @@ static const struct file_operations igmp6_mcf_seq_fops = {
2593 .open = igmp6_mcf_seq_open, 2631 .open = igmp6_mcf_seq_open,
2594 .read = seq_read, 2632 .read = seq_read,
2595 .llseek = seq_lseek, 2633 .llseek = seq_lseek,
2596 .release = seq_release_private, 2634 .release = seq_release_net,
2597}; 2635};
2636
2637static int igmp6_proc_init(struct net *net)
2638{
2639 int err;
2640
2641 err = -ENOMEM;
2642 if (!proc_net_fops_create(net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops))
2643 goto out;
2644 if (!proc_net_fops_create(net, "mcfilter6", S_IRUGO,
2645 &igmp6_mcf_seq_fops))
2646 goto out_proc_net_igmp6;
2647
2648 err = 0;
2649out:
2650 return err;
2651
2652out_proc_net_igmp6:
2653 proc_net_remove(net, "igmp6");
2654 goto out;
2655}
2656
2657static void igmp6_proc_exit(struct net *net)
2658{
2659 proc_net_remove(net, "mcfilter6");
2660 proc_net_remove(net, "igmp6");
2661}
2662#else
2663static int igmp6_proc_init(struct net *net)
2664{
2665 return 0;
2666}
2667static void igmp6_proc_exit(struct net *net)
2668{
2669 ;
2670}
2598#endif 2671#endif
2599 2672
2600int __init igmp6_init(struct net_proto_family *ops) 2673static int igmp6_net_init(struct net *net)
2601{ 2674{
2602 struct ipv6_pinfo *np; 2675 struct ipv6_pinfo *np;
2676 struct socket *sock;
2603 struct sock *sk; 2677 struct sock *sk;
2604 int err; 2678 int err;
2605 2679
2606 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); 2680 err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock);
2607 if (err < 0) { 2681 if (err < 0) {
2608 printk(KERN_ERR 2682 printk(KERN_ERR
2609 "Failed to initialize the IGMP6 control socket (err %d).\n", 2683 "Failed to initialize the IGMP6 control socket (err %d).\n",
2610 err); 2684 err);
2611 igmp6_socket = NULL; /* For safety. */ 2685 goto out;
2612 return err;
2613 } 2686 }
2614 2687
2615 sk = igmp6_socket->sk; 2688 net->ipv6.igmp_sk = sk = sock->sk;
2689 sk_change_net(sk, net);
2616 sk->sk_allocation = GFP_ATOMIC; 2690 sk->sk_allocation = GFP_ATOMIC;
2617 sk->sk_prot->unhash(sk); 2691 sk->sk_prot->unhash(sk);
2618 2692
2619 np = inet6_sk(sk); 2693 np = inet6_sk(sk);
2620 np->hop_limit = 1; 2694 np->hop_limit = 1;
2621 2695
2622#ifdef CONFIG_PROC_FS 2696 err = igmp6_proc_init(net);
2623 proc_net_fops_create(&init_net, "igmp6", S_IRUGO, &igmp6_mc_seq_fops); 2697 if (err)
2624 proc_net_fops_create(&init_net, "mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops); 2698 goto out_sock_create;
2625#endif 2699out:
2700 return err;
2626 2701
2627 return 0; 2702out_sock_create:
2703 sk_release_kernel(net->ipv6.igmp_sk);
2704 goto out;
2628} 2705}
2629 2706
2630void igmp6_cleanup(void) 2707static void igmp6_net_exit(struct net *net)
2631{ 2708{
2632 sock_release(igmp6_socket); 2709 sk_release_kernel(net->ipv6.igmp_sk);
2633 igmp6_socket = NULL; /* for safety */ 2710 igmp6_proc_exit(net);
2711}
2634 2712
2635#ifdef CONFIG_PROC_FS 2713static struct pernet_operations igmp6_net_ops = {
2636 proc_net_remove(&init_net, "mcfilter6"); 2714 .init = igmp6_net_init,
2637 proc_net_remove(&init_net, "igmp6"); 2715 .exit = igmp6_net_exit,
2638#endif 2716};
2717
2718int __init igmp6_init(void)
2719{
2720 return register_pernet_subsys(&igmp6_net_ops);
2721}
2722
2723void igmp6_cleanup(void)
2724{
2725 unregister_pernet_subsys(&igmp6_net_ops);
2639} 2726}