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