Skip to content

Commit b8ad0cb

Browse files
Daniel Lezcanodavem330
authored andcommitted
[NETNS][IPV6] mcast - handle several network namespace
This patch make use of the network namespace information at the right places to handle the multicast for several network namespaces. It makes the socket control to be per namespace too. Signed-off-by: Daniel Lezcano <[email protected]> Signed-off-by: Benjamin Thery <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e504799 commit b8ad0cb

File tree

3 files changed

+82
-38
lines changed

3 files changed

+82
-38
lines changed

include/net/netns/ipv6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,6 @@ struct netns_ipv6 {
5353
struct sock **icmp_sk;
5454
struct sock *ndisc_sk;
5555
struct sock *tcp_sk;
56+
struct sock *igmp_sk;
5657
};
5758
#endif

net/ipv6/mcast.c

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
126126
/* Big mc list lock for all the sockets */
127127
static DEFINE_RWLOCK(ipv6_sk_mc_lock);
128128

129-
static struct socket *igmp6_socket;
130-
131129
int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
132130

133131
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)
183181
struct net_device *dev = NULL;
184182
struct ipv6_mc_socklist *mc_lst;
185183
struct ipv6_pinfo *np = inet6_sk(sk);
184+
struct net *net = sk->sk_net;
186185
int err;
187186

188187
if (!ipv6_addr_is_multicast(addr))
@@ -208,14 +207,14 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
208207

209208
if (ifindex == 0) {
210209
struct rt6_info *rt;
211-
rt = rt6_lookup(&init_net, addr, NULL, 0, 0);
210+
rt = rt6_lookup(net, addr, NULL, 0, 0);
212211
if (rt) {
213212
dev = rt->rt6i_dev;
214213
dev_hold(dev);
215214
dst_release(&rt->u.dst);
216215
}
217216
} else
218-
dev = dev_get_by_index(&init_net, ifindex);
217+
dev = dev_get_by_index(net, ifindex);
219218

220219
if (dev == NULL) {
221220
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)
256255
{
257256
struct ipv6_pinfo *np = inet6_sk(sk);
258257
struct ipv6_mc_socklist *mc_lst, **lnk;
258+
struct net *net = sk->sk_net;
259259

260260
write_lock_bh(&ipv6_sk_mc_lock);
261261
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)
266266
*lnk = mc_lst->next;
267267
write_unlock_bh(&ipv6_sk_mc_lock);
268268

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) {
270271
struct inet6_dev *idev = in6_dev_get(dev);
271272

272273
(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)
286287
return -EADDRNOTAVAIL;
287288
}
288289

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)
290293
{
291294
struct net_device *dev = NULL;
292295
struct inet6_dev *idev = NULL;
293296

294297
if (ifindex == 0) {
295298
struct rt6_info *rt;
296299

297-
rt = rt6_lookup(&init_net, group, NULL, 0, 0);
300+
rt = rt6_lookup(net, group, NULL, 0, 0);
298301
if (rt) {
299302
dev = rt->rt6i_dev;
300303
dev_hold(dev);
301304
dst_release(&rt->u.dst);
302305
}
303306
} else
304-
dev = dev_get_by_index(&init_net, ifindex);
307+
dev = dev_get_by_index(net, ifindex);
305308

306309
if (!dev)
307310
return NULL;
@@ -324,6 +327,7 @@ void ipv6_sock_mc_close(struct sock *sk)
324327
{
325328
struct ipv6_pinfo *np = inet6_sk(sk);
326329
struct ipv6_mc_socklist *mc_lst;
330+
struct net *net = sk->sk_net;
327331

328332
write_lock_bh(&ipv6_sk_mc_lock);
329333
while ((mc_lst = np->ipv6_mc_list) != NULL) {
@@ -332,7 +336,7 @@ void ipv6_sock_mc_close(struct sock *sk)
332336
np->ipv6_mc_list = mc_lst->next;
333337
write_unlock_bh(&ipv6_sk_mc_lock);
334338

335-
dev = dev_get_by_index(&init_net, mc_lst->ifindex);
339+
dev = dev_get_by_index(net, mc_lst->ifindex);
336340
if (dev) {
337341
struct inet6_dev *idev = in6_dev_get(dev);
338342

@@ -361,6 +365,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
361365
struct inet6_dev *idev;
362366
struct ipv6_pinfo *inet6 = inet6_sk(sk);
363367
struct ip6_sf_socklist *psl;
368+
struct net *net = sk->sk_net;
364369
int i, j, rv;
365370
int leavegroup = 0;
366371
int pmclocked = 0;
@@ -376,7 +381,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
376381
if (!ipv6_addr_is_multicast(group))
377382
return -EINVAL;
378383

379-
idev = ip6_mc_find_dev(group, pgsr->gsr_interface);
384+
idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface);
380385
if (!idev)
381386
return -ENODEV;
382387
dev = idev->dev;
@@ -500,6 +505,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
500505
struct inet6_dev *idev;
501506
struct ipv6_pinfo *inet6 = inet6_sk(sk);
502507
struct ip6_sf_socklist *newpsl, *psl;
508+
struct net *net = sk->sk_net;
503509
int leavegroup = 0;
504510
int i, err;
505511

@@ -511,7 +517,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
511517
gsf->gf_fmode != MCAST_EXCLUDE)
512518
return -EINVAL;
513519

514-
idev = ip6_mc_find_dev(group, gsf->gf_interface);
520+
idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
515521

516522
if (!idev)
517523
return -ENODEV;
@@ -592,13 +598,14 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
592598
struct net_device *dev;
593599
struct ipv6_pinfo *inet6 = inet6_sk(sk);
594600
struct ip6_sf_socklist *psl;
601+
struct net *net = sk->sk_net;
595602

596603
group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
597604

598605
if (!ipv6_addr_is_multicast(group))
599606
return -EINVAL;
600607

601-
idev = ip6_mc_find_dev(group, gsf->gf_interface);
608+
idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
602609

603610
if (!idev)
604611
return -ENODEV;
@@ -1393,7 +1400,8 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
13931400

13941401
static struct sk_buff *mld_newpack(struct net_device *dev, int size)
13951402
{
1396-
struct sock *sk = igmp6_socket->sk;
1403+
struct net *net = dev->nd_net;
1404+
struct sock *sk = net->ipv6.igmp_sk;
13971405
struct sk_buff *skb;
13981406
struct mld2_report *pmr;
13991407
struct in6_addr addr_buf;
@@ -1440,6 +1448,7 @@ static void mld_sendpack(struct sk_buff *skb)
14401448
(struct mld2_report *)skb_transport_header(skb);
14411449
int payload_len, mldlen;
14421450
struct inet6_dev *idev = in6_dev_get(skb->dev);
1451+
struct net *net = skb->dev->nd_net;
14431452
int err;
14441453
struct flowi fl;
14451454

@@ -1459,7 +1468,7 @@ static void mld_sendpack(struct sk_buff *skb)
14591468
goto err_out;
14601469
}
14611470

1462-
icmpv6_flow_init(igmp6_socket->sk, &fl, ICMPV6_MLD2_REPORT,
1471+
icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
14631472
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
14641473
skb->dev->ifindex);
14651474

@@ -1753,7 +1762,8 @@ static void mld_send_cr(struct inet6_dev *idev)
17531762

17541763
static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
17551764
{
1756-
struct sock *sk = igmp6_socket->sk;
1765+
struct net *net = dev->nd_net;
1766+
struct sock *sk = net->ipv6.igmp_sk;
17571767
struct inet6_dev *idev;
17581768
struct sk_buff *skb;
17591769
struct icmp6hdr *hdr;
@@ -1824,7 +1834,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
18241834
goto err_out;
18251835
}
18261836

1827-
icmpv6_flow_init(igmp6_socket->sk, &fl, type,
1837+
icmpv6_flow_init(sk, &fl, type,
18281838
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
18291839
skb->dev->ifindex);
18301840

@@ -2334,6 +2344,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
23342344

23352345
#ifdef CONFIG_PROC_FS
23362346
struct igmp6_mc_iter_state {
2347+
struct seq_net_private p;
23372348
struct net_device *dev;
23382349
struct inet6_dev *idev;
23392350
};
@@ -2344,9 +2355,10 @@ static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
23442355
{
23452356
struct ifmcaddr6 *im = NULL;
23462357
struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2358+
struct net *net = state->p.net;
23472359

23482360
state->idev = NULL;
2349-
for_each_netdev(&init_net, state->dev) {
2361+
for_each_netdev(net, state->dev) {
23502362
struct inet6_dev *idev;
23512363
idev = in6_dev_get(state->dev);
23522364
if (!idev)
@@ -2448,19 +2460,20 @@ static const struct seq_operations igmp6_mc_seq_ops = {
24482460

24492461
static int igmp6_mc_seq_open(struct inode *inode, struct file *file)
24502462
{
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));
24532465
}
24542466

24552467
static const struct file_operations igmp6_mc_seq_fops = {
24562468
.owner = THIS_MODULE,
24572469
.open = igmp6_mc_seq_open,
24582470
.read = seq_read,
24592471
.llseek = seq_lseek,
2460-
.release = seq_release_private,
2472+
.release = seq_release_net,
24612473
};
24622474

24632475
struct igmp6_mcf_iter_state {
2476+
struct seq_net_private p;
24642477
struct net_device *dev;
24652478
struct inet6_dev *idev;
24662479
struct ifmcaddr6 *im;
@@ -2473,10 +2486,11 @@ static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
24732486
struct ip6_sf_list *psf = NULL;
24742487
struct ifmcaddr6 *im = NULL;
24752488
struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2489+
struct net *net = state->p.net;
24762490

24772491
state->idev = NULL;
24782492
state->im = NULL;
2479-
for_each_netdev(&init_net, state->dev) {
2493+
for_each_netdev(net, state->dev) {
24802494
struct inet6_dev *idev;
24812495
idev = in6_dev_get(state->dev);
24822496
if (unlikely(idev == NULL))
@@ -2608,56 +2622,82 @@ static const struct seq_operations igmp6_mcf_seq_ops = {
26082622

26092623
static int igmp6_mcf_seq_open(struct inode *inode, struct file *file)
26102624
{
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));
26132627
}
26142628

26152629
static const struct file_operations igmp6_mcf_seq_fops = {
26162630
.owner = THIS_MODULE,
26172631
.open = igmp6_mcf_seq_open,
26182632
.read = seq_read,
26192633
.llseek = seq_lseek,
2620-
.release = seq_release_private,
2634+
.release = seq_release_net,
26212635
};
26222636
#endif
26232637

2624-
int __init igmp6_init(void)
2638+
static int igmp6_net_init(struct net *net)
26252639
{
26262640
struct ipv6_pinfo *np;
2641+
struct socket *sock;
26272642
struct sock *sk;
26282643
int err;
26292644

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);
26312646
if (err < 0) {
26322647
printk(KERN_ERR
26332648
"Failed to initialize the IGMP6 control socket (err %d).\n",
26342649
err);
2635-
igmp6_socket = NULL; /* For safety. */
2636-
return err;
2650+
goto out;
26372651
}
26382652

2639-
sk = igmp6_socket->sk;
2653+
net->ipv6.igmp_sk = sk = sock->sk;
2654+
sk_change_net(sk, net);
26402655
sk->sk_allocation = GFP_ATOMIC;
26412656
sk->sk_prot->unhash(sk);
26422657

26432658
np = inet6_sk(sk);
26442659
np->hop_limit = 1;
26452660

26462661
#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+
}
26492670
#endif
26502671

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;
26522679
}
26532680

2654-
void igmp6_cleanup(void)
2681+
static void igmp6_net_exit(struct net *net)
26552682
{
2656-
sock_release(igmp6_socket);
2657-
igmp6_socket = NULL; /* for safety */
2658-
2683+
sk_release_kernel(net->ipv6.igmp_sk);
26592684
#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");
26622687
#endif
26632688
}
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+
}

net/ipv6/udp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
323323
sk_for_each_from(s, node) {
324324
struct inet_sock *inet = inet_sk(s);
325325

326+
if (s->sk_net != sk->sk_net)
327+
continue;
328+
326329
if (s->sk_hash == num && s->sk_family == PF_INET6) {
327330
struct ipv6_pinfo *np = inet6_sk(s);
328331
if (inet->dport) {

0 commit comments

Comments
 (0)