Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Multicast support for IPv6
4 : : * Linux INET6 implementation
5 : : *
6 : : * Authors:
7 : : * Pedro Roque <roque@di.fc.ul.pt>
8 : : *
9 : : * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
10 : : */
11 : :
12 : : /* Changes:
13 : : *
14 : : * yoshfuji : fix format of router-alert option
15 : : * YOSHIFUJI Hideaki @USAGI:
16 : : * Fixed source address for MLD message based on
17 : : * <draft-ietf-magma-mld-source-05.txt>.
18 : : * YOSHIFUJI Hideaki @USAGI:
19 : : * - Ignore Queries for invalid addresses.
20 : : * - MLD for link-local addresses.
21 : : * David L Stevens <dlstevens@us.ibm.com>:
22 : : * - MLDv2 support
23 : : */
24 : :
25 : : #include <linux/module.h>
26 : : #include <linux/errno.h>
27 : : #include <linux/types.h>
28 : : #include <linux/string.h>
29 : : #include <linux/socket.h>
30 : : #include <linux/sockios.h>
31 : : #include <linux/jiffies.h>
32 : : #include <linux/times.h>
33 : : #include <linux/net.h>
34 : : #include <linux/in.h>
35 : : #include <linux/in6.h>
36 : : #include <linux/netdevice.h>
37 : : #include <linux/if_arp.h>
38 : : #include <linux/route.h>
39 : : #include <linux/init.h>
40 : : #include <linux/proc_fs.h>
41 : : #include <linux/seq_file.h>
42 : : #include <linux/slab.h>
43 : : #include <linux/pkt_sched.h>
44 : : #include <net/mld.h>
45 : :
46 : : #include <linux/netfilter.h>
47 : : #include <linux/netfilter_ipv6.h>
48 : :
49 : : #include <net/net_namespace.h>
50 : : #include <net/sock.h>
51 : : #include <net/snmp.h>
52 : :
53 : : #include <net/ipv6.h>
54 : : #include <net/protocol.h>
55 : : #include <net/if_inet6.h>
56 : : #include <net/ndisc.h>
57 : : #include <net/addrconf.h>
58 : : #include <net/ip6_route.h>
59 : : #include <net/inet_common.h>
60 : :
61 : : #include <net/ip6_checksum.h>
62 : :
63 : : /* Ensure that we have struct in6_addr aligned on 32bit word. */
64 : : static int __mld2_query_bugs[] __attribute__((__unused__)) = {
65 : : BUILD_BUG_ON_ZERO(offsetof(struct mld2_query, mld2q_srcs) % 4),
66 : : BUILD_BUG_ON_ZERO(offsetof(struct mld2_report, mld2r_grec) % 4),
67 : : BUILD_BUG_ON_ZERO(offsetof(struct mld2_grec, grec_mca) % 4)
68 : : };
69 : :
70 : : static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT;
71 : :
72 : : static void igmp6_join_group(struct ifmcaddr6 *ma);
73 : : static void igmp6_leave_group(struct ifmcaddr6 *ma);
74 : : static void igmp6_timer_handler(struct timer_list *t);
75 : :
76 : : static void mld_gq_timer_expire(struct timer_list *t);
77 : : static void mld_ifc_timer_expire(struct timer_list *t);
78 : : static void mld_ifc_event(struct inet6_dev *idev);
79 : : static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
80 : : static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
81 : : static void mld_clear_delrec(struct inet6_dev *idev);
82 : : static bool mld_in_v1_mode(const struct inet6_dev *idev);
83 : : static int sf_setstate(struct ifmcaddr6 *pmc);
84 : : static void sf_markstate(struct ifmcaddr6 *pmc);
85 : : static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
86 : : static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
87 : : int sfmode, int sfcount, const struct in6_addr *psfsrc,
88 : : int delta);
89 : : static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
90 : : int sfmode, int sfcount, const struct in6_addr *psfsrc,
91 : : int delta);
92 : : static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
93 : : struct inet6_dev *idev);
94 : : static int __ipv6_dev_mc_inc(struct net_device *dev,
95 : : const struct in6_addr *addr, unsigned int mode);
96 : :
97 : : #define MLD_QRV_DEFAULT 2
98 : : /* RFC3810, 9.2. Query Interval */
99 : : #define MLD_QI_DEFAULT (125 * HZ)
100 : : /* RFC3810, 9.3. Query Response Interval */
101 : : #define MLD_QRI_DEFAULT (10 * HZ)
102 : :
103 : : /* RFC3810, 8.1 Query Version Distinctions */
104 : : #define MLD_V1_QUERY_LEN 24
105 : : #define MLD_V2_QUERY_LEN_MIN 28
106 : :
107 : : #define IPV6_MLD_MAX_MSF 64
108 : :
109 : : int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF;
110 : : int sysctl_mld_qrv __read_mostly = MLD_QRV_DEFAULT;
111 : :
112 : : /*
113 : : * socket join on multicast group
114 : : */
115 : :
116 : : #define for_each_pmc_rcu(np, pmc) \
117 : : for (pmc = rcu_dereference(np->ipv6_mc_list); \
118 : : pmc != NULL; \
119 : : pmc = rcu_dereference(pmc->next))
120 : :
121 : 351 : static int unsolicited_report_interval(struct inet6_dev *idev)
122 : : {
123 : 351 : int iv;
124 : :
125 : 351 : if (mld_in_v1_mode(idev))
126 : 0 : iv = idev->cnf.mldv1_unsolicited_report_interval;
127 : : else
128 : 351 : iv = idev->cnf.mldv2_unsolicited_report_interval;
129 : :
130 : 351 : return iv > 0 ? iv : 1;
131 : : }
132 : :
133 : 0 : static int __ipv6_sock_mc_join(struct sock *sk, int ifindex,
134 : : const struct in6_addr *addr, unsigned int mode)
135 : : {
136 : 0 : struct net_device *dev = NULL;
137 : 0 : struct ipv6_mc_socklist *mc_lst;
138 [ # # ]: 0 : struct ipv6_pinfo *np = inet6_sk(sk);
139 : 0 : struct net *net = sock_net(sk);
140 : 0 : int err;
141 : :
142 [ # # # # ]: 0 : ASSERT_RTNL();
143 : :
144 [ # # ]: 0 : if (!ipv6_addr_is_multicast(addr))
145 : : return -EINVAL;
146 : :
147 : 0 : rcu_read_lock();
148 [ # # ]: 0 : for_each_pmc_rcu(np, mc_lst) {
149 [ # # # # : 0 : if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
# # ]
150 : : ipv6_addr_equal(&mc_lst->addr, addr)) {
151 : 0 : rcu_read_unlock();
152 : 0 : return -EADDRINUSE;
153 : : }
154 : : }
155 : 0 : rcu_read_unlock();
156 : :
157 : 0 : mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);
158 : :
159 [ # # ]: 0 : if (!mc_lst)
160 : : return -ENOMEM;
161 : :
162 : 0 : mc_lst->next = NULL;
163 : 0 : mc_lst->addr = *addr;
164 : :
165 [ # # ]: 0 : if (ifindex == 0) {
166 : 0 : struct rt6_info *rt;
167 : 0 : rt = rt6_lookup(net, addr, NULL, 0, NULL, 0);
168 [ # # ]: 0 : if (rt) {
169 : 0 : dev = rt->dst.dev;
170 : 0 : ip6_rt_put(rt);
171 : : }
172 : : } else
173 : 0 : dev = __dev_get_by_index(net, ifindex);
174 : :
175 [ # # ]: 0 : if (!dev) {
176 : 0 : sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
177 : 0 : return -ENODEV;
178 : : }
179 : :
180 : 0 : mc_lst->ifindex = dev->ifindex;
181 : 0 : mc_lst->sfmode = mode;
182 : 0 : rwlock_init(&mc_lst->sflock);
183 : 0 : mc_lst->sflist = NULL;
184 : :
185 : : /*
186 : : * now add/increase the group membership on the device
187 : : */
188 : :
189 : 0 : err = __ipv6_dev_mc_inc(dev, addr, mode);
190 : :
191 [ # # ]: 0 : if (err) {
192 : 0 : sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
193 : 0 : return err;
194 : : }
195 : :
196 : 0 : mc_lst->next = np->ipv6_mc_list;
197 : 0 : rcu_assign_pointer(np->ipv6_mc_list, mc_lst);
198 : :
199 : 0 : return 0;
200 : : }
201 : :
202 : 0 : int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
203 : : {
204 : 0 : return __ipv6_sock_mc_join(sk, ifindex, addr, MCAST_EXCLUDE);
205 : : }
206 : : EXPORT_SYMBOL(ipv6_sock_mc_join);
207 : :
208 : 0 : int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
209 : : const struct in6_addr *addr, unsigned int mode)
210 : : {
211 : 0 : return __ipv6_sock_mc_join(sk, ifindex, addr, mode);
212 : : }
213 : :
214 : : /*
215 : : * socket leave on multicast group
216 : : */
217 : 0 : int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
218 : : {
219 [ # # ]: 0 : struct ipv6_pinfo *np = inet6_sk(sk);
220 : 0 : struct ipv6_mc_socklist *mc_lst;
221 : 0 : struct ipv6_mc_socklist __rcu **lnk;
222 : 0 : struct net *net = sock_net(sk);
223 : :
224 [ # # # # ]: 0 : ASSERT_RTNL();
225 : :
226 [ # # ]: 0 : if (!ipv6_addr_is_multicast(addr))
227 : : return -EINVAL;
228 : :
229 : 0 : for (lnk = &np->ipv6_mc_list;
230 [ # # ]: 0 : (mc_lst = rtnl_dereference(*lnk)) != NULL;
231 : 0 : lnk = &mc_lst->next) {
232 [ # # # # : 0 : if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
# # ]
233 : : ipv6_addr_equal(&mc_lst->addr, addr)) {
234 : 0 : struct net_device *dev;
235 : :
236 : 0 : *lnk = mc_lst->next;
237 : :
238 : 0 : dev = __dev_get_by_index(net, mc_lst->ifindex);
239 [ # # ]: 0 : if (dev) {
240 : 0 : struct inet6_dev *idev = __in6_dev_get(dev);
241 : :
242 : 0 : (void) ip6_mc_leave_src(sk, mc_lst, idev);
243 [ # # ]: 0 : if (idev)
244 : 0 : __ipv6_dev_mc_dec(idev, &mc_lst->addr);
245 : : } else
246 : 0 : (void) ip6_mc_leave_src(sk, mc_lst, NULL);
247 : :
248 : 0 : atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
249 : 0 : kfree_rcu(mc_lst, rcu);
250 : 0 : return 0;
251 : : }
252 : : }
253 : :
254 : : return -EADDRNOTAVAIL;
255 : : }
256 : : EXPORT_SYMBOL(ipv6_sock_mc_drop);
257 : :
258 : : /* called with rcu_read_lock() */
259 : 0 : static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
260 : : const struct in6_addr *group,
261 : : int ifindex)
262 : : {
263 : 0 : struct net_device *dev = NULL;
264 : 0 : struct inet6_dev *idev = NULL;
265 : :
266 [ # # ]: 0 : if (ifindex == 0) {
267 : 0 : struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, NULL, 0);
268 : :
269 [ # # ]: 0 : if (rt) {
270 : 0 : dev = rt->dst.dev;
271 : 0 : ip6_rt_put(rt);
272 : : }
273 : : } else
274 : 0 : dev = dev_get_by_index_rcu(net, ifindex);
275 : :
276 [ # # ]: 0 : if (!dev)
277 : 0 : return NULL;
278 [ # # ]: 0 : idev = __in6_dev_get(dev);
279 [ # # ]: 0 : if (!idev)
280 : : return NULL;
281 : 0 : read_lock_bh(&idev->lock);
282 [ # # ]: 0 : if (idev->dead) {
283 : 0 : read_unlock_bh(&idev->lock);
284 : 0 : return NULL;
285 : : }
286 : : return idev;
287 : : }
288 : :
289 : 0 : void __ipv6_sock_mc_close(struct sock *sk)
290 : : {
291 [ # # ]: 0 : struct ipv6_pinfo *np = inet6_sk(sk);
292 : 0 : struct ipv6_mc_socklist *mc_lst;
293 : 0 : struct net *net = sock_net(sk);
294 : :
295 [ # # # # ]: 0 : ASSERT_RTNL();
296 : :
297 : 0 : while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) {
298 : 0 : struct net_device *dev;
299 : :
300 : 0 : np->ipv6_mc_list = mc_lst->next;
301 : :
302 : 0 : dev = __dev_get_by_index(net, mc_lst->ifindex);
303 [ # # ]: 0 : if (dev) {
304 : 0 : struct inet6_dev *idev = __in6_dev_get(dev);
305 : :
306 : 0 : (void) ip6_mc_leave_src(sk, mc_lst, idev);
307 [ # # ]: 0 : if (idev)
308 : 0 : __ipv6_dev_mc_dec(idev, &mc_lst->addr);
309 : : } else
310 : 0 : (void) ip6_mc_leave_src(sk, mc_lst, NULL);
311 : :
312 : 0 : atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
313 [ # # ]: 0 : kfree_rcu(mc_lst, rcu);
314 : : }
315 : 0 : }
316 : :
317 : 156 : void ipv6_sock_mc_close(struct sock *sk)
318 : : {
319 [ + - ]: 156 : struct ipv6_pinfo *np = inet6_sk(sk);
320 : :
321 [ - + ]: 156 : if (!rcu_access_pointer(np->ipv6_mc_list))
322 : : return;
323 : 0 : rtnl_lock();
324 : 0 : __ipv6_sock_mc_close(sk);
325 : 0 : rtnl_unlock();
326 : : }
327 : :
328 : 0 : int ip6_mc_source(int add, int omode, struct sock *sk,
329 : : struct group_source_req *pgsr)
330 : : {
331 : 0 : struct in6_addr *source, *group;
332 : 0 : struct ipv6_mc_socklist *pmc;
333 : 0 : struct inet6_dev *idev;
334 [ # # ]: 0 : struct ipv6_pinfo *inet6 = inet6_sk(sk);
335 : 0 : struct ip6_sf_socklist *psl;
336 [ # # ]: 0 : struct net *net = sock_net(sk);
337 : 0 : int i, j, rv;
338 : 0 : int leavegroup = 0;
339 : 0 : int pmclocked = 0;
340 : 0 : int err;
341 : :
342 : 0 : source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr;
343 : 0 : group = &((struct sockaddr_in6 *)&pgsr->gsr_group)->sin6_addr;
344 : :
345 [ # # ]: 0 : if (!ipv6_addr_is_multicast(group))
346 : : return -EINVAL;
347 : :
348 : 0 : rcu_read_lock();
349 : 0 : idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface);
350 [ # # ]: 0 : if (!idev) {
351 : 0 : rcu_read_unlock();
352 : 0 : return -ENODEV;
353 : : }
354 : :
355 : 0 : err = -EADDRNOTAVAIL;
356 : :
357 [ # # ]: 0 : for_each_pmc_rcu(inet6, pmc) {
358 [ # # # # ]: 0 : if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
359 : 0 : continue;
360 [ # # ]: 0 : if (ipv6_addr_equal(&pmc->addr, group))
361 : : break;
362 : : }
363 [ # # ]: 0 : if (!pmc) { /* must have a prior join */
364 : 0 : err = -EINVAL;
365 : 0 : goto done;
366 : : }
367 : : /* if a source filter was set, must be the same mode as before */
368 [ # # ]: 0 : if (pmc->sflist) {
369 [ # # ]: 0 : if (pmc->sfmode != omode) {
370 : 0 : err = -EINVAL;
371 : 0 : goto done;
372 : : }
373 [ # # ]: 0 : } else if (pmc->sfmode != omode) {
374 : : /* allow mode switches for empty-set filters */
375 : 0 : ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
376 : 0 : ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
377 : 0 : pmc->sfmode = omode;
378 : : }
379 : :
380 : 0 : write_lock(&pmc->sflock);
381 : 0 : pmclocked = 1;
382 : :
383 : 0 : psl = pmc->sflist;
384 [ # # ]: 0 : if (!add) {
385 [ # # ]: 0 : if (!psl)
386 : 0 : goto done; /* err = -EADDRNOTAVAIL */
387 : : rv = !0;
388 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
389 [ # # ]: 0 : rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
390 [ # # ]: 0 : if (rv == 0)
391 : : break;
392 : : }
393 [ # # ]: 0 : if (rv) /* source not found */
394 : 0 : goto done; /* err = -EADDRNOTAVAIL */
395 : :
396 : : /* special case - (INCLUDE, empty) == LEAVE_GROUP */
397 [ # # # # ]: 0 : if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
398 : 0 : leavegroup = 1;
399 : 0 : goto done;
400 : : }
401 : :
402 : : /* update the interface filter */
403 : 0 : ip6_mc_del_src(idev, group, omode, 1, source, 1);
404 : :
405 [ # # ]: 0 : for (j = i+1; j < psl->sl_count; j++)
406 : 0 : psl->sl_addr[j-1] = psl->sl_addr[j];
407 : 0 : psl->sl_count--;
408 : 0 : err = 0;
409 : 0 : goto done;
410 : : }
411 : : /* else, add a new source to the filter */
412 : :
413 [ # # # # ]: 0 : if (psl && psl->sl_count >= sysctl_mld_max_msf) {
414 : 0 : err = -ENOBUFS;
415 : 0 : goto done;
416 : : }
417 [ # # # # ]: 0 : if (!psl || psl->sl_count == psl->sl_max) {
418 : 0 : struct ip6_sf_socklist *newpsl;
419 : 0 : int count = IP6_SFBLOCK;
420 : :
421 [ # # ]: 0 : if (psl)
422 : 0 : count += psl->sl_max;
423 : 0 : newpsl = sock_kmalloc(sk, IP6_SFLSIZE(count), GFP_ATOMIC);
424 [ # # ]: 0 : if (!newpsl) {
425 : 0 : err = -ENOBUFS;
426 : 0 : goto done;
427 : : }
428 : 0 : newpsl->sl_max = count;
429 : 0 : newpsl->sl_count = count - IP6_SFBLOCK;
430 [ # # ]: 0 : if (psl) {
431 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++)
432 : 0 : newpsl->sl_addr[i] = psl->sl_addr[i];
433 : 0 : sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
434 : : }
435 : 0 : pmc->sflist = psl = newpsl;
436 : : }
437 : 0 : rv = 1; /* > 0 for insert logic below if sl_count is 0 */
438 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
439 [ # # ]: 0 : rv = !ipv6_addr_equal(&psl->sl_addr[i], source);
440 [ # # ]: 0 : if (rv == 0) /* There is an error in the address. */
441 : 0 : goto done;
442 : : }
443 [ # # ]: 0 : for (j = psl->sl_count-1; j >= i; j--)
444 : 0 : psl->sl_addr[j+1] = psl->sl_addr[j];
445 : 0 : psl->sl_addr[i] = *source;
446 : 0 : psl->sl_count++;
447 : 0 : err = 0;
448 : : /* update the interface list */
449 : 0 : ip6_mc_add_src(idev, group, omode, 1, source, 1);
450 : 0 : done:
451 [ # # ]: 0 : if (pmclocked)
452 : 0 : write_unlock(&pmc->sflock);
453 : 0 : read_unlock_bh(&idev->lock);
454 : 0 : rcu_read_unlock();
455 [ # # ]: 0 : if (leavegroup)
456 : 0 : err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
457 : : return err;
458 : : }
459 : :
460 : 0 : int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
461 : : {
462 : 0 : const struct in6_addr *group;
463 : 0 : struct ipv6_mc_socklist *pmc;
464 : 0 : struct inet6_dev *idev;
465 [ # # ]: 0 : struct ipv6_pinfo *inet6 = inet6_sk(sk);
466 : 0 : struct ip6_sf_socklist *newpsl, *psl;
467 [ # # ]: 0 : struct net *net = sock_net(sk);
468 : 0 : int leavegroup = 0;
469 : 0 : int i, err;
470 : :
471 : 0 : group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
472 : :
473 [ # # ]: 0 : if (!ipv6_addr_is_multicast(group))
474 : : return -EINVAL;
475 [ # # ]: 0 : if (gsf->gf_fmode != MCAST_INCLUDE &&
476 : : gsf->gf_fmode != MCAST_EXCLUDE)
477 : : return -EINVAL;
478 : :
479 : 0 : rcu_read_lock();
480 : 0 : idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
481 : :
482 [ # # ]: 0 : if (!idev) {
483 : 0 : rcu_read_unlock();
484 : 0 : return -ENODEV;
485 : : }
486 : :
487 : 0 : err = 0;
488 : :
489 [ # # ]: 0 : if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) {
490 : 0 : leavegroup = 1;
491 : 0 : goto done;
492 : : }
493 : :
494 [ # # ]: 0 : for_each_pmc_rcu(inet6, pmc) {
495 [ # # ]: 0 : if (pmc->ifindex != gsf->gf_interface)
496 : 0 : continue;
497 [ # # ]: 0 : if (ipv6_addr_equal(&pmc->addr, group))
498 : : break;
499 : : }
500 [ # # ]: 0 : if (!pmc) { /* must have a prior join */
501 : 0 : err = -EINVAL;
502 : 0 : goto done;
503 : : }
504 [ # # ]: 0 : if (gsf->gf_numsrc) {
505 : 0 : newpsl = sock_kmalloc(sk, IP6_SFLSIZE(gsf->gf_numsrc),
506 : : GFP_ATOMIC);
507 [ # # ]: 0 : if (!newpsl) {
508 : 0 : err = -ENOBUFS;
509 : 0 : goto done;
510 : : }
511 : 0 : newpsl->sl_max = newpsl->sl_count = gsf->gf_numsrc;
512 [ # # ]: 0 : for (i = 0; i < newpsl->sl_count; ++i) {
513 : 0 : struct sockaddr_in6 *psin6;
514 : :
515 : 0 : psin6 = (struct sockaddr_in6 *)&gsf->gf_slist[i];
516 : 0 : newpsl->sl_addr[i] = psin6->sin6_addr;
517 : : }
518 : 0 : err = ip6_mc_add_src(idev, group, gsf->gf_fmode,
519 : 0 : newpsl->sl_count, newpsl->sl_addr, 0);
520 [ # # ]: 0 : if (err) {
521 : 0 : sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max));
522 : 0 : goto done;
523 : : }
524 : : } else {
525 : 0 : newpsl = NULL;
526 : 0 : (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
527 : : }
528 : :
529 : 0 : write_lock(&pmc->sflock);
530 : 0 : psl = pmc->sflist;
531 [ # # ]: 0 : if (psl) {
532 : 0 : (void) ip6_mc_del_src(idev, group, pmc->sfmode,
533 : 0 : psl->sl_count, psl->sl_addr, 0);
534 : 0 : sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max));
535 : : } else
536 : 0 : (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
537 : 0 : pmc->sflist = newpsl;
538 : 0 : pmc->sfmode = gsf->gf_fmode;
539 : 0 : write_unlock(&pmc->sflock);
540 : 0 : err = 0;
541 : 0 : done:
542 : 0 : read_unlock_bh(&idev->lock);
543 : 0 : rcu_read_unlock();
544 [ # # ]: 0 : if (leavegroup)
545 : 0 : err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
546 : : return err;
547 : : }
548 : :
549 : 0 : int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
550 : : struct group_filter __user *optval, int __user *optlen)
551 : : {
552 : 0 : int err, i, count, copycount;
553 : 0 : const struct in6_addr *group;
554 : 0 : struct ipv6_mc_socklist *pmc;
555 : 0 : struct inet6_dev *idev;
556 [ # # ]: 0 : struct ipv6_pinfo *inet6 = inet6_sk(sk);
557 : 0 : struct ip6_sf_socklist *psl;
558 [ # # ]: 0 : struct net *net = sock_net(sk);
559 : :
560 : 0 : group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
561 : :
562 [ # # ]: 0 : if (!ipv6_addr_is_multicast(group))
563 : : return -EINVAL;
564 : :
565 : 0 : rcu_read_lock();
566 : 0 : idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
567 : :
568 [ # # ]: 0 : if (!idev) {
569 : 0 : rcu_read_unlock();
570 : 0 : return -ENODEV;
571 : : }
572 : :
573 : 0 : err = -EADDRNOTAVAIL;
574 : : /* changes to the ipv6_mc_list require the socket lock and
575 : : * rtnl lock. We have the socket lock and rcu read lock,
576 : : * so reading the list is safe.
577 : : */
578 : :
579 [ # # ]: 0 : for_each_pmc_rcu(inet6, pmc) {
580 [ # # ]: 0 : if (pmc->ifindex != gsf->gf_interface)
581 : 0 : continue;
582 [ # # ]: 0 : if (ipv6_addr_equal(group, &pmc->addr))
583 : : break;
584 : : }
585 [ # # ]: 0 : if (!pmc) /* must have a prior join */
586 : 0 : goto done;
587 : 0 : gsf->gf_fmode = pmc->sfmode;
588 : 0 : psl = pmc->sflist;
589 [ # # ]: 0 : count = psl ? psl->sl_count : 0;
590 : 0 : read_unlock_bh(&idev->lock);
591 : 0 : rcu_read_unlock();
592 : :
593 : 0 : copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
594 : 0 : gsf->gf_numsrc = count;
595 [ # # # # ]: 0 : if (put_user(GROUP_FILTER_SIZE(copycount), optlen) ||
596 : : copy_to_user(optval, gsf, GROUP_FILTER_SIZE(0))) {
597 : 0 : return -EFAULT;
598 : : }
599 : : /* changes to psl require the socket lock, and a write lock
600 : : * on pmc->sflock. We have the socket lock so reading here is safe.
601 : : */
602 [ # # ]: 0 : for (i = 0; i < copycount; i++) {
603 : 0 : struct sockaddr_in6 *psin6;
604 : 0 : struct sockaddr_storage ss;
605 : :
606 : 0 : psin6 = (struct sockaddr_in6 *)&ss;
607 : 0 : memset(&ss, 0, sizeof(ss));
608 : 0 : psin6->sin6_family = AF_INET6;
609 : 0 : psin6->sin6_addr = psl->sl_addr[i];
610 [ # # ]: 0 : if (copy_to_user(&optval->gf_slist[i], &ss, sizeof(ss)))
611 : 0 : return -EFAULT;
612 : : }
613 : : return 0;
614 : : done:
615 : 0 : read_unlock_bh(&idev->lock);
616 : 0 : rcu_read_unlock();
617 : 0 : return err;
618 : : }
619 : :
620 : 0 : bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
621 : : const struct in6_addr *src_addr)
622 : : {
623 [ # # ]: 0 : struct ipv6_pinfo *np = inet6_sk(sk);
624 : 0 : struct ipv6_mc_socklist *mc;
625 : 0 : struct ip6_sf_socklist *psl;
626 : 0 : bool rv = true;
627 : :
628 : 0 : rcu_read_lock();
629 [ # # ]: 0 : for_each_pmc_rcu(np, mc) {
630 [ # # ]: 0 : if (ipv6_addr_equal(&mc->addr, mc_addr))
631 : : break;
632 : : }
633 [ # # ]: 0 : if (!mc) {
634 : 0 : rcu_read_unlock();
635 : 0 : return np->mc_all;
636 : : }
637 : 0 : read_lock(&mc->sflock);
638 : 0 : psl = mc->sflist;
639 [ # # ]: 0 : if (!psl) {
640 : 0 : rv = mc->sfmode == MCAST_EXCLUDE;
641 : : } else {
642 : : int i;
643 : :
644 [ # # ]: 0 : for (i = 0; i < psl->sl_count; i++) {
645 [ # # ]: 0 : if (ipv6_addr_equal(&psl->sl_addr[i], src_addr))
646 : : break;
647 : : }
648 [ # # # # ]: 0 : if (mc->sfmode == MCAST_INCLUDE && i >= psl->sl_count)
649 : 0 : rv = false;
650 [ # # # # ]: 0 : if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count)
651 : 0 : rv = false;
652 : : }
653 : 0 : read_unlock(&mc->sflock);
654 : 0 : rcu_read_unlock();
655 : :
656 : 0 : return rv;
657 : : }
658 : :
659 : 618 : static void igmp6_group_added(struct ifmcaddr6 *mc)
660 : : {
661 : 618 : struct net_device *dev = mc->idev->dev;
662 : 618 : char buf[MAX_ADDR_LEN];
663 : :
664 [ + + ]: 618 : if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
665 : : IPV6_ADDR_SCOPE_LINKLOCAL)
666 : 590 : return;
667 : :
668 : 323 : spin_lock_bh(&mc->mca_lock);
669 [ + + ]: 323 : if (!(mc->mca_flags&MAF_LOADED)) {
670 : 217 : mc->mca_flags |= MAF_LOADED;
671 [ + + ]: 217 : if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
672 : 61 : dev_mc_add(dev, buf);
673 : : }
674 : 323 : spin_unlock_bh(&mc->mca_lock);
675 : :
676 [ + + + + ]: 323 : if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT))
677 : : return;
678 : :
679 : 28 : if (mld_in_v1_mode(mc->idev)) {
680 : 0 : igmp6_join_group(mc);
681 : 0 : return;
682 : : }
683 : : /* else v2 */
684 : :
685 : : /* Based on RFC3810 6.1, for newly added INCLUDE SSM, we
686 : : * should not send filter-mode change record as the mode
687 : : * should be from IN() to IN(A).
688 : : */
689 [ + - ]: 28 : if (mc->mca_sfmode == MCAST_EXCLUDE)
690 : 28 : mc->mca_crcount = mc->idev->mc_qrv;
691 : :
692 : 28 : mld_ifc_event(mc->idev);
693 : : }
694 : :
695 : 0 : static void igmp6_group_dropped(struct ifmcaddr6 *mc)
696 : : {
697 : 0 : struct net_device *dev = mc->idev->dev;
698 : 0 : char buf[MAX_ADDR_LEN];
699 : :
700 [ # # ]: 0 : if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) <
701 : : IPV6_ADDR_SCOPE_LINKLOCAL)
702 : 0 : return;
703 : :
704 : 0 : spin_lock_bh(&mc->mca_lock);
705 [ # # ]: 0 : if (mc->mca_flags&MAF_LOADED) {
706 : 0 : mc->mca_flags &= ~MAF_LOADED;
707 [ # # ]: 0 : if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
708 : 0 : dev_mc_del(dev, buf);
709 : : }
710 : :
711 : 0 : spin_unlock_bh(&mc->mca_lock);
712 [ # # ]: 0 : if (mc->mca_flags & MAF_NOREPORT)
713 : : return;
714 : :
715 [ # # ]: 0 : if (!mc->idev->dead)
716 : 0 : igmp6_leave_group(mc);
717 : :
718 : 0 : spin_lock_bh(&mc->mca_lock);
719 [ # # ]: 0 : if (del_timer(&mc->mca_timer))
720 : 0 : refcount_dec(&mc->mca_refcnt);
721 : 0 : spin_unlock_bh(&mc->mca_lock);
722 : : }
723 : :
724 : : /*
725 : : * deleted ifmcaddr6 manipulation
726 : : */
727 : 0 : static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
728 : : {
729 : 0 : struct ifmcaddr6 *pmc;
730 : :
731 : : /* this is an "ifmcaddr6" for convenience; only the fields below
732 : : * are actually used. In particular, the refcnt and users are not
733 : : * used for management of the delete list. Using the same structure
734 : : * for deleted items allows change reports to use common code with
735 : : * non-deleted or query-response MCA's.
736 : : */
737 : 0 : pmc = kzalloc(sizeof(*pmc), GFP_ATOMIC);
738 [ # # ]: 0 : if (!pmc)
739 : : return;
740 : :
741 : 0 : spin_lock_bh(&im->mca_lock);
742 : 0 : spin_lock_init(&pmc->mca_lock);
743 : 0 : pmc->idev = im->idev;
744 : 0 : in6_dev_hold(idev);
745 : 0 : pmc->mca_addr = im->mca_addr;
746 : 0 : pmc->mca_crcount = idev->mc_qrv;
747 : 0 : pmc->mca_sfmode = im->mca_sfmode;
748 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_INCLUDE) {
749 : 0 : struct ip6_sf_list *psf;
750 : :
751 : 0 : pmc->mca_tomb = im->mca_tomb;
752 : 0 : pmc->mca_sources = im->mca_sources;
753 : 0 : im->mca_tomb = im->mca_sources = NULL;
754 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
755 : 0 : psf->sf_crcount = pmc->mca_crcount;
756 : : }
757 : 0 : spin_unlock_bh(&im->mca_lock);
758 : :
759 : 0 : spin_lock_bh(&idev->mc_lock);
760 : 0 : pmc->next = idev->mc_tomb;
761 : 0 : idev->mc_tomb = pmc;
762 : 0 : spin_unlock_bh(&idev->mc_lock);
763 : : }
764 : :
765 : 618 : static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
766 : : {
767 : 618 : struct ifmcaddr6 *pmc, *pmc_prev;
768 : 618 : struct ip6_sf_list *psf;
769 : 618 : struct in6_addr *pmca = &im->mca_addr;
770 : :
771 : 618 : spin_lock_bh(&idev->mc_lock);
772 : 618 : pmc_prev = NULL;
773 [ - + ]: 618 : for (pmc = idev->mc_tomb; pmc; pmc = pmc->next) {
774 [ # # ]: 0 : if (ipv6_addr_equal(&pmc->mca_addr, pmca))
775 : : break;
776 : 0 : pmc_prev = pmc;
777 : : }
778 [ - + ]: 618 : if (pmc) {
779 [ # # ]: 0 : if (pmc_prev)
780 : 0 : pmc_prev->next = pmc->next;
781 : : else
782 : 0 : idev->mc_tomb = pmc->next;
783 : : }
784 : 618 : spin_unlock_bh(&idev->mc_lock);
785 : :
786 : 618 : spin_lock_bh(&im->mca_lock);
787 [ - + ]: 618 : if (pmc) {
788 : 0 : im->idev = pmc->idev;
789 [ # # ]: 0 : if (im->mca_sfmode == MCAST_INCLUDE) {
790 : 0 : swap(im->mca_tomb, pmc->mca_tomb);
791 : 0 : swap(im->mca_sources, pmc->mca_sources);
792 [ # # ]: 0 : for (psf = im->mca_sources; psf; psf = psf->sf_next)
793 : 0 : psf->sf_crcount = idev->mc_qrv;
794 : : } else {
795 : 0 : im->mca_crcount = idev->mc_qrv;
796 : : }
797 : 0 : in6_dev_put(pmc->idev);
798 : 0 : ip6_mc_clear_src(pmc);
799 : 0 : kfree(pmc);
800 : : }
801 : 618 : spin_unlock_bh(&im->mca_lock);
802 : 618 : }
803 : :
804 : 0 : static void mld_clear_delrec(struct inet6_dev *idev)
805 : : {
806 : 0 : struct ifmcaddr6 *pmc, *nextpmc;
807 : :
808 : 0 : spin_lock_bh(&idev->mc_lock);
809 : 0 : pmc = idev->mc_tomb;
810 : 0 : idev->mc_tomb = NULL;
811 : 0 : spin_unlock_bh(&idev->mc_lock);
812 : :
813 [ # # ]: 0 : for (; pmc; pmc = nextpmc) {
814 : 0 : nextpmc = pmc->next;
815 : 0 : ip6_mc_clear_src(pmc);
816 : 0 : in6_dev_put(pmc->idev);
817 : 0 : kfree(pmc);
818 : : }
819 : :
820 : : /* clear dead sources, too */
821 : 0 : read_lock_bh(&idev->lock);
822 [ # # ]: 0 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
823 : 0 : struct ip6_sf_list *psf, *psf_next;
824 : :
825 : 0 : spin_lock_bh(&pmc->mca_lock);
826 : 0 : psf = pmc->mca_tomb;
827 : 0 : pmc->mca_tomb = NULL;
828 : 0 : spin_unlock_bh(&pmc->mca_lock);
829 [ # # ]: 0 : for (; psf; psf = psf_next) {
830 : 0 : psf_next = psf->sf_next;
831 : 0 : kfree(psf);
832 : : }
833 : : }
834 : 0 : read_unlock_bh(&idev->lock);
835 : 0 : }
836 : :
837 : 406 : static void mca_get(struct ifmcaddr6 *mc)
838 : : {
839 : 406 : refcount_inc(&mc->mca_refcnt);
840 : : }
841 : :
842 : 406 : static void ma_put(struct ifmcaddr6 *mc)
843 : : {
844 [ - + ]: 406 : if (refcount_dec_and_test(&mc->mca_refcnt)) {
845 : 0 : in6_dev_put(mc->idev);
846 : 0 : kfree(mc);
847 : : }
848 : 406 : }
849 : :
850 : : static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
851 : : const struct in6_addr *addr,
852 : : unsigned int mode)
853 : : {
854 : : struct ifmcaddr6 *mc;
855 : :
856 : : mc = kzalloc(sizeof(*mc), GFP_ATOMIC);
857 : : if (!mc)
858 : : return NULL;
859 : :
860 : : timer_setup(&mc->mca_timer, igmp6_timer_handler, 0);
861 : :
862 : : mc->mca_addr = *addr;
863 : : mc->idev = idev; /* reference taken by caller */
864 : : mc->mca_users = 1;
865 : : /* mca_stamp should be updated upon changes */
866 : : mc->mca_cstamp = mc->mca_tstamp = jiffies;
867 : : refcount_set(&mc->mca_refcnt, 1);
868 : : spin_lock_init(&mc->mca_lock);
869 : :
870 : : mc->mca_sfmode = mode;
871 : : mc->mca_sfcount[mode] = 1;
872 : :
873 : : if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) ||
874 : : IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
875 : : mc->mca_flags |= MAF_NOREPORT;
876 : :
877 : : return mc;
878 : : }
879 : :
880 : : /*
881 : : * device multicast group inc (add if not found)
882 : : */
883 : 406 : static int __ipv6_dev_mc_inc(struct net_device *dev,
884 : : const struct in6_addr *addr, unsigned int mode)
885 : : {
886 : 406 : struct ifmcaddr6 *mc;
887 : 406 : struct inet6_dev *idev;
888 : :
889 [ - + - - ]: 406 : ASSERT_RTNL();
890 : :
891 : : /* we need to take a reference on idev */
892 : 406 : idev = in6_dev_get(dev);
893 : :
894 [ + - ]: 406 : if (!idev)
895 : : return -EINVAL;
896 : :
897 : 406 : write_lock_bh(&idev->lock);
898 [ - + ]: 406 : if (idev->dead) {
899 : 0 : write_unlock_bh(&idev->lock);
900 : 0 : in6_dev_put(idev);
901 : 0 : return -ENODEV;
902 : : }
903 : :
904 [ + + ]: 651 : for (mc = idev->mc_list; mc; mc = mc->next) {
905 [ - + ]: 245 : if (ipv6_addr_equal(&mc->mca_addr, addr)) {
906 : 0 : mc->mca_users++;
907 : 0 : write_unlock_bh(&idev->lock);
908 : 0 : ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0);
909 : 0 : in6_dev_put(idev);
910 : 0 : return 0;
911 : : }
912 : : }
913 : :
914 : 406 : mc = mca_alloc(idev, addr, mode);
915 [ - + ]: 406 : if (!mc) {
916 : 0 : write_unlock_bh(&idev->lock);
917 : 0 : in6_dev_put(idev);
918 : 0 : return -ENOMEM;
919 : : }
920 : :
921 : 406 : mc->next = idev->mc_list;
922 : 406 : idev->mc_list = mc;
923 : :
924 : : /* Hold this for the code below before we unlock,
925 : : * it is already exposed via idev->mc_list.
926 : : */
927 : 406 : mca_get(mc);
928 : 406 : write_unlock_bh(&idev->lock);
929 : :
930 : 406 : mld_del_delrec(idev, mc);
931 : 406 : igmp6_group_added(mc);
932 : 406 : ma_put(mc);
933 : 406 : return 0;
934 : : }
935 : :
936 : 406 : int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
937 : : {
938 : 406 : return __ipv6_dev_mc_inc(dev, addr, MCAST_EXCLUDE);
939 : : }
940 : : EXPORT_SYMBOL(ipv6_dev_mc_inc);
941 : :
942 : : /*
943 : : * device multicast group del
944 : : */
945 : 0 : int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
946 : : {
947 : 0 : struct ifmcaddr6 *ma, **map;
948 : :
949 [ # # # # ]: 0 : ASSERT_RTNL();
950 : :
951 : 0 : write_lock_bh(&idev->lock);
952 [ # # ]: 0 : for (map = &idev->mc_list; (ma = *map) != NULL; map = &ma->next) {
953 [ # # ]: 0 : if (ipv6_addr_equal(&ma->mca_addr, addr)) {
954 [ # # ]: 0 : if (--ma->mca_users == 0) {
955 : 0 : *map = ma->next;
956 : 0 : write_unlock_bh(&idev->lock);
957 : :
958 : 0 : igmp6_group_dropped(ma);
959 : 0 : ip6_mc_clear_src(ma);
960 : :
961 : 0 : ma_put(ma);
962 : 0 : return 0;
963 : : }
964 : 0 : write_unlock_bh(&idev->lock);
965 : 0 : return 0;
966 : : }
967 : : }
968 : 0 : write_unlock_bh(&idev->lock);
969 : :
970 : 0 : return -ENOENT;
971 : : }
972 : :
973 : 0 : int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
974 : : {
975 : 0 : struct inet6_dev *idev;
976 : 0 : int err;
977 : :
978 [ # # # # ]: 0 : ASSERT_RTNL();
979 : :
980 [ # # ]: 0 : idev = __in6_dev_get(dev);
981 [ # # ]: 0 : if (!idev)
982 : : err = -ENODEV;
983 : : else
984 : 0 : err = __ipv6_dev_mc_dec(idev, addr);
985 : :
986 : 0 : return err;
987 : : }
988 : : EXPORT_SYMBOL(ipv6_dev_mc_dec);
989 : :
990 : : /*
991 : : * check if the interface/address pair is valid
992 : : */
993 : 110 : bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
994 : : const struct in6_addr *src_addr)
995 : : {
996 : 110 : struct inet6_dev *idev;
997 : 110 : struct ifmcaddr6 *mc;
998 : 110 : bool rv = false;
999 : :
1000 : 110 : rcu_read_lock();
1001 [ + - ]: 110 : idev = __in6_dev_get(dev);
1002 [ + - ]: 110 : if (idev) {
1003 : 110 : read_lock_bh(&idev->lock);
1004 [ + + ]: 440 : for (mc = idev->mc_list; mc; mc = mc->next) {
1005 [ + - ]: 330 : if (ipv6_addr_equal(&mc->mca_addr, group))
1006 : : break;
1007 : : }
1008 [ - + ]: 110 : if (mc) {
1009 [ # # # # ]: 0 : if (src_addr && !ipv6_addr_any(src_addr)) {
1010 : 0 : struct ip6_sf_list *psf;
1011 : :
1012 : 0 : spin_lock_bh(&mc->mca_lock);
1013 [ # # ]: 0 : for (psf = mc->mca_sources; psf; psf = psf->sf_next) {
1014 [ # # ]: 0 : if (ipv6_addr_equal(&psf->sf_addr, src_addr))
1015 : : break;
1016 : : }
1017 [ # # ]: 0 : if (psf)
1018 [ # # ]: 0 : rv = psf->sf_count[MCAST_INCLUDE] ||
1019 : 0 : psf->sf_count[MCAST_EXCLUDE] !=
1020 [ # # ]: 0 : mc->mca_sfcount[MCAST_EXCLUDE];
1021 : : else
1022 : 0 : rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0;
1023 : 0 : spin_unlock_bh(&mc->mca_lock);
1024 : : } else
1025 : : rv = true; /* don't filter unspecified source */
1026 : : }
1027 : 110 : read_unlock_bh(&idev->lock);
1028 : : }
1029 : 110 : rcu_read_unlock();
1030 : 110 : return rv;
1031 : : }
1032 : :
1033 : 0 : static void mld_gq_start_timer(struct inet6_dev *idev)
1034 : : {
1035 : 0 : unsigned long tv = prandom_u32() % idev->mc_maxdelay;
1036 : :
1037 : 0 : idev->mc_gq_running = 1;
1038 [ # # ]: 0 : if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2))
1039 : 0 : in6_dev_hold(idev);
1040 : 0 : }
1041 : :
1042 : 0 : static void mld_gq_stop_timer(struct inet6_dev *idev)
1043 : : {
1044 : 0 : idev->mc_gq_running = 0;
1045 [ # # ]: 0 : if (del_timer(&idev->mc_gq_timer))
1046 : 0 : __in6_dev_put(idev);
1047 : 0 : }
1048 : :
1049 : 56 : static void mld_ifc_start_timer(struct inet6_dev *idev, unsigned long delay)
1050 : : {
1051 : 56 : unsigned long tv = prandom_u32() % delay;
1052 : :
1053 [ + - ]: 56 : if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2))
1054 : 56 : in6_dev_hold(idev);
1055 : 56 : }
1056 : :
1057 : 0 : static void mld_ifc_stop_timer(struct inet6_dev *idev)
1058 : : {
1059 : 0 : idev->mc_ifc_count = 0;
1060 [ # # ]: 0 : if (del_timer(&idev->mc_ifc_timer))
1061 : 0 : __in6_dev_put(idev);
1062 : 0 : }
1063 : :
1064 : 28 : static void mld_dad_start_timer(struct inet6_dev *idev, unsigned long delay)
1065 : : {
1066 : 28 : unsigned long tv = prandom_u32() % delay;
1067 : :
1068 [ + - ]: 28 : if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2))
1069 : 28 : in6_dev_hold(idev);
1070 : 28 : }
1071 : :
1072 : 0 : static void mld_dad_stop_timer(struct inet6_dev *idev)
1073 : : {
1074 [ # # ]: 0 : if (del_timer(&idev->mc_dad_timer))
1075 : 0 : __in6_dev_put(idev);
1076 : 0 : }
1077 : :
1078 : : /*
1079 : : * IGMP handling (alias multicast ICMPv6 messages)
1080 : : */
1081 : :
1082 : 0 : static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
1083 : : {
1084 : 0 : unsigned long delay = resptime;
1085 : :
1086 : : /* Do not start timer for these addresses */
1087 [ # # ]: 0 : if (ipv6_addr_is_ll_all_nodes(&ma->mca_addr) ||
1088 [ # # ]: 0 : IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL)
1089 : : return;
1090 : :
1091 [ # # ]: 0 : if (del_timer(&ma->mca_timer)) {
1092 : 0 : refcount_dec(&ma->mca_refcnt);
1093 : 0 : delay = ma->mca_timer.expires - jiffies;
1094 : : }
1095 : :
1096 [ # # ]: 0 : if (delay >= resptime)
1097 : 0 : delay = prandom_u32() % resptime;
1098 : :
1099 : 0 : ma->mca_timer.expires = jiffies + delay;
1100 [ # # ]: 0 : if (!mod_timer(&ma->mca_timer, jiffies + delay))
1101 : 0 : refcount_inc(&ma->mca_refcnt);
1102 : 0 : ma->mca_flags |= MAF_TIMER_RUNNING;
1103 : : }
1104 : :
1105 : : /* mark EXCLUDE-mode sources */
1106 : 0 : static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
1107 : : const struct in6_addr *srcs)
1108 : : {
1109 : 0 : struct ip6_sf_list *psf;
1110 : 0 : int i, scount;
1111 : :
1112 : 0 : scount = 0;
1113 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
1114 [ # # ]: 0 : if (scount == nsrcs)
1115 : : break;
1116 [ # # ]: 0 : for (i = 0; i < nsrcs; i++) {
1117 : : /* skip inactive filters */
1118 [ # # ]: 0 : if (psf->sf_count[MCAST_INCLUDE] ||
1119 : 0 : pmc->mca_sfcount[MCAST_EXCLUDE] !=
1120 [ # # ]: 0 : psf->sf_count[MCAST_EXCLUDE])
1121 : : break;
1122 [ # # ]: 0 : if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) {
1123 : 0 : scount++;
1124 : 0 : break;
1125 : : }
1126 : : }
1127 : : }
1128 : 0 : pmc->mca_flags &= ~MAF_GSQUERY;
1129 [ # # ]: 0 : if (scount == nsrcs) /* all sources excluded */
1130 : 0 : return false;
1131 : : return true;
1132 : : }
1133 : :
1134 : 0 : static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
1135 : : const struct in6_addr *srcs)
1136 : : {
1137 : 0 : struct ip6_sf_list *psf;
1138 : 0 : int i, scount;
1139 : :
1140 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_EXCLUDE)
1141 : 0 : return mld_xmarksources(pmc, nsrcs, srcs);
1142 : :
1143 : : /* mark INCLUDE-mode sources */
1144 : :
1145 : 0 : scount = 0;
1146 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
1147 [ # # ]: 0 : if (scount == nsrcs)
1148 : : break;
1149 [ # # ]: 0 : for (i = 0; i < nsrcs; i++) {
1150 [ # # ]: 0 : if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) {
1151 : 0 : psf->sf_gsresp = 1;
1152 : 0 : scount++;
1153 : 0 : break;
1154 : : }
1155 : : }
1156 : : }
1157 [ # # ]: 0 : if (!scount) {
1158 : 0 : pmc->mca_flags &= ~MAF_GSQUERY;
1159 : 0 : return false;
1160 : : }
1161 : 0 : pmc->mca_flags |= MAF_GSQUERY;
1162 : 0 : return true;
1163 : : }
1164 : :
1165 : 922 : static int mld_force_mld_version(const struct inet6_dev *idev)
1166 : : {
1167 : : /* Normally, both are 0 here. If enforcement to a particular is
1168 : : * being used, individual device enforcement will have a lower
1169 : : * precedence over 'all' device (.../conf/all/force_mld_version).
1170 : : */
1171 : :
1172 : 922 : if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
1173 : : return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
1174 : : else
1175 : 461 : return idev->cnf.force_mld_version;
1176 : : }
1177 : :
1178 : 461 : static bool mld_in_v2_mode_only(const struct inet6_dev *idev)
1179 : : {
1180 : 461 : return mld_force_mld_version(idev) == 2;
1181 : : }
1182 : :
1183 : 461 : static bool mld_in_v1_mode_only(const struct inet6_dev *idev)
1184 : : {
1185 : 461 : return mld_force_mld_version(idev) == 1;
1186 : : }
1187 : :
1188 : 461 : static bool mld_in_v1_mode(const struct inet6_dev *idev)
1189 : : {
1190 [ - - - - : 840 : if (mld_in_v2_mode_only(idev))
+ - - - -
- - - + -
- - - - +
- + - + -
+ - ]
1191 : : return false;
1192 [ - - - - : 461 : if (mld_in_v1_mode_only(idev))
+ - - - -
- + - - -
+ - + - ]
1193 : : return true;
1194 [ - - - - : 461 : if (idev->mc_v1_seen && time_before(jiffies, idev->mc_v1_seen))
- - - - -
+ - - - -
- - - - -
- - + - -
- - - - -
+ - - - +
- - ]
1195 : : return true;
1196 : :
1197 : : return false;
1198 : : }
1199 : :
1200 : 0 : static void mld_set_v1_mode(struct inet6_dev *idev)
1201 : : {
1202 : : /* RFC3810, relevant sections:
1203 : : * - 9.1. Robustness Variable
1204 : : * - 9.2. Query Interval
1205 : : * - 9.3. Query Response Interval
1206 : : * - 9.12. Older Version Querier Present Timeout
1207 : : */
1208 : 0 : unsigned long switchback;
1209 : :
1210 : 0 : switchback = (idev->mc_qrv * idev->mc_qi) + idev->mc_qri;
1211 : :
1212 : 0 : idev->mc_v1_seen = jiffies + switchback;
1213 : 0 : }
1214 : :
1215 : : static void mld_update_qrv(struct inet6_dev *idev,
1216 : : const struct mld2_query *mlh2)
1217 : : {
1218 : : /* RFC3810, relevant sections:
1219 : : * - 5.1.8. QRV (Querier's Robustness Variable)
1220 : : * - 9.1. Robustness Variable
1221 : : */
1222 : :
1223 : : /* The value of the Robustness Variable MUST NOT be zero,
1224 : : * and SHOULD NOT be one. Catch this here if we ever run
1225 : : * into such a case in future.
1226 : : */
1227 : : const int min_qrv = min(MLD_QRV_DEFAULT, sysctl_mld_qrv);
1228 : : WARN_ON(idev->mc_qrv == 0);
1229 : :
1230 : : if (mlh2->mld2q_qrv > 0)
1231 : : idev->mc_qrv = mlh2->mld2q_qrv;
1232 : :
1233 : : if (unlikely(idev->mc_qrv < min_qrv)) {
1234 : : net_warn_ratelimited("IPv6: MLD: clamping QRV from %u to %u!\n",
1235 : : idev->mc_qrv, min_qrv);
1236 : : idev->mc_qrv = min_qrv;
1237 : : }
1238 : : }
1239 : :
1240 : 0 : static void mld_update_qi(struct inet6_dev *idev,
1241 : : const struct mld2_query *mlh2)
1242 : : {
1243 : : /* RFC3810, relevant sections:
1244 : : * - 5.1.9. QQIC (Querier's Query Interval Code)
1245 : : * - 9.2. Query Interval
1246 : : * - 9.12. Older Version Querier Present Timeout
1247 : : * (the [Query Interval] in the last Query received)
1248 : : */
1249 : 0 : unsigned long mc_qqi;
1250 : :
1251 : 0 : if (mlh2->mld2q_qqic < 128) {
1252 : 0 : mc_qqi = mlh2->mld2q_qqic;
1253 : : } else {
1254 : 0 : unsigned long mc_man, mc_exp;
1255 : :
1256 : 0 : mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic);
1257 : 0 : mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic);
1258 : :
1259 : 0 : mc_qqi = (mc_man | 0x10) << (mc_exp + 3);
1260 : : }
1261 : :
1262 : 0 : idev->mc_qi = mc_qqi * HZ;
1263 : : }
1264 : :
1265 : : static void mld_update_qri(struct inet6_dev *idev,
1266 : : const struct mld2_query *mlh2)
1267 : : {
1268 : : /* RFC3810, relevant sections:
1269 : : * - 5.1.3. Maximum Response Code
1270 : : * - 9.3. Query Response Interval
1271 : : */
1272 : : idev->mc_qri = msecs_to_jiffies(mldv2_mrc(mlh2));
1273 : : }
1274 : :
1275 : 0 : static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
1276 : : unsigned long *max_delay, bool v1_query)
1277 : : {
1278 : 0 : unsigned long mldv1_md;
1279 : :
1280 : : /* Ignore v1 queries */
1281 [ # # # # ]: 0 : if (mld_in_v2_mode_only(idev))
1282 : : return -EINVAL;
1283 : :
1284 : 0 : mldv1_md = ntohs(mld->mld_maxdelay);
1285 : :
1286 : : /* When in MLDv1 fallback and a MLDv2 router start-up being
1287 : : * unaware of current MLDv1 operation, the MRC == MRD mapping
1288 : : * only works when the exponential algorithm is not being
1289 : : * used (as MLDv1 is unaware of such things).
1290 : : *
1291 : : * According to the RFC author, the MLDv2 implementations
1292 : : * he's aware of all use a MRC < 32768 on start up queries.
1293 : : *
1294 : : * Thus, should we *ever* encounter something else larger
1295 : : * than that, just assume the maximum possible within our
1296 : : * reach.
1297 : : */
1298 [ # # ]: 0 : if (!v1_query)
1299 : 0 : mldv1_md = min(mldv1_md, MLDV1_MRD_MAX_COMPAT);
1300 : :
1301 [ # # ]: 0 : *max_delay = max(msecs_to_jiffies(mldv1_md), 1UL);
1302 : :
1303 : : /* MLDv1 router present: we need to go into v1 mode *only*
1304 : : * when an MLDv1 query is received as per section 9.12. of
1305 : : * RFC3810! And we know from RFC2710 section 3.7 that MLDv1
1306 : : * queries MUST be of exactly 24 octets.
1307 : : */
1308 [ # # ]: 0 : if (v1_query)
1309 : 0 : mld_set_v1_mode(idev);
1310 : :
1311 : : /* cancel MLDv2 report timer */
1312 : 0 : mld_gq_stop_timer(idev);
1313 : : /* cancel the interface change timer */
1314 : 0 : mld_ifc_stop_timer(idev);
1315 : : /* clear deleted report items */
1316 : 0 : mld_clear_delrec(idev);
1317 : :
1318 : 0 : return 0;
1319 : : }
1320 : :
1321 : 0 : static int mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
1322 : : unsigned long *max_delay)
1323 : : {
1324 [ # # # # ]: 0 : *max_delay = max(msecs_to_jiffies(mldv2_mrc(mld)), 1UL);
1325 : :
1326 : 0 : mld_update_qrv(idev, mld);
1327 [ # # ]: 0 : mld_update_qi(idev, mld);
1328 : 0 : mld_update_qri(idev, mld);
1329 : :
1330 : 0 : idev->mc_maxdelay = *max_delay;
1331 : :
1332 : 0 : return 0;
1333 : : }
1334 : :
1335 : : /* called with rcu_read_lock() */
1336 : 0 : int igmp6_event_query(struct sk_buff *skb)
1337 : : {
1338 : 0 : struct mld2_query *mlh2 = NULL;
1339 : 0 : struct ifmcaddr6 *ma;
1340 : 0 : const struct in6_addr *group;
1341 : 0 : unsigned long max_delay;
1342 : 0 : struct inet6_dev *idev;
1343 : 0 : struct mld_msg *mld;
1344 : 0 : int group_type;
1345 : 0 : int mark = 0;
1346 : 0 : int len, err;
1347 : :
1348 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
1349 : : return -EINVAL;
1350 : :
1351 : : /* compute payload length excluding extension headers */
1352 : 0 : len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr);
1353 : 0 : len -= skb_network_header_len(skb);
1354 : :
1355 : : /* RFC3810 6.2
1356 : : * Upon reception of an MLD message that contains a Query, the node
1357 : : * checks if the source address of the message is a valid link-local
1358 : : * address, if the Hop Limit is set to 1, and if the Router Alert
1359 : : * option is present in the Hop-By-Hop Options header of the IPv6
1360 : : * packet. If any of these checks fails, the packet is dropped.
1361 : : */
1362 [ # # ]: 0 : if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) ||
1363 [ # # ]: 0 : ipv6_hdr(skb)->hop_limit != 1 ||
1364 [ # # ]: 0 : !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) ||
1365 [ # # ]: 0 : IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD))
1366 : : return -EINVAL;
1367 : :
1368 [ # # ]: 0 : idev = __in6_dev_get(skb->dev);
1369 [ # # ]: 0 : if (!idev)
1370 : : return 0;
1371 : :
1372 : 0 : mld = (struct mld_msg *)icmp6_hdr(skb);
1373 : 0 : group = &mld->mld_mca;
1374 : 0 : group_type = ipv6_addr_type(group);
1375 : :
1376 [ # # ]: 0 : if (group_type != IPV6_ADDR_ANY &&
1377 [ # # ]: 0 : !(group_type&IPV6_ADDR_MULTICAST))
1378 : : return -EINVAL;
1379 : :
1380 [ # # ]: 0 : if (len < MLD_V1_QUERY_LEN) {
1381 : : return -EINVAL;
1382 [ # # ]: 0 : } else if (len == MLD_V1_QUERY_LEN || mld_in_v1_mode(idev)) {
1383 : 0 : err = mld_process_v1(idev, mld, &max_delay,
1384 : : len == MLD_V1_QUERY_LEN);
1385 [ # # ]: 0 : if (err < 0)
1386 : : return err;
1387 [ # # ]: 0 : } else if (len >= MLD_V2_QUERY_LEN_MIN) {
1388 : 0 : int srcs_offset = sizeof(struct mld2_query) -
1389 : : sizeof(struct icmp6hdr);
1390 : :
1391 [ # # ]: 0 : if (!pskb_may_pull(skb, srcs_offset))
1392 : : return -EINVAL;
1393 : :
1394 : 0 : mlh2 = (struct mld2_query *)skb_transport_header(skb);
1395 : :
1396 : 0 : err = mld_process_v2(idev, mlh2, &max_delay);
1397 [ # # ]: 0 : if (err < 0)
1398 : : return err;
1399 : :
1400 [ # # ]: 0 : if (group_type == IPV6_ADDR_ANY) { /* general query */
1401 [ # # ]: 0 : if (mlh2->mld2q_nsrcs)
1402 : : return -EINVAL; /* no sources allowed */
1403 : :
1404 : 0 : mld_gq_start_timer(idev);
1405 : 0 : return 0;
1406 : : }
1407 : : /* mark sources to include, if group & source-specific */
1408 [ # # ]: 0 : if (mlh2->mld2q_nsrcs != 0) {
1409 [ # # ]: 0 : if (!pskb_may_pull(skb, srcs_offset +
1410 : 0 : ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr)))
1411 : : return -EINVAL;
1412 : :
1413 : 0 : mlh2 = (struct mld2_query *)skb_transport_header(skb);
1414 : 0 : mark = 1;
1415 : : }
1416 : : } else {
1417 : : return -EINVAL;
1418 : : }
1419 : :
1420 : 0 : read_lock_bh(&idev->lock);
1421 [ # # ]: 0 : if (group_type == IPV6_ADDR_ANY) {
1422 [ # # ]: 0 : for (ma = idev->mc_list; ma; ma = ma->next) {
1423 : 0 : spin_lock_bh(&ma->mca_lock);
1424 : 0 : igmp6_group_queried(ma, max_delay);
1425 : 0 : spin_unlock_bh(&ma->mca_lock);
1426 : : }
1427 : : } else {
1428 [ # # ]: 0 : for (ma = idev->mc_list; ma; ma = ma->next) {
1429 [ # # ]: 0 : if (!ipv6_addr_equal(group, &ma->mca_addr))
1430 : 0 : continue;
1431 : 0 : spin_lock_bh(&ma->mca_lock);
1432 [ # # ]: 0 : if (ma->mca_flags & MAF_TIMER_RUNNING) {
1433 : : /* gsquery <- gsquery && mark */
1434 [ # # ]: 0 : if (!mark)
1435 : 0 : ma->mca_flags &= ~MAF_GSQUERY;
1436 : : } else {
1437 : : /* gsquery <- mark */
1438 [ # # ]: 0 : if (mark)
1439 : 0 : ma->mca_flags |= MAF_GSQUERY;
1440 : : else
1441 : 0 : ma->mca_flags &= ~MAF_GSQUERY;
1442 : : }
1443 [ # # # # ]: 0 : if (!(ma->mca_flags & MAF_GSQUERY) ||
1444 : 0 : mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs))
1445 : 0 : igmp6_group_queried(ma, max_delay);
1446 : 0 : spin_unlock_bh(&ma->mca_lock);
1447 : : break;
1448 : : }
1449 : : }
1450 : 0 : read_unlock_bh(&idev->lock);
1451 : :
1452 : 0 : return 0;
1453 : : }
1454 : :
1455 : : /* called with rcu_read_lock() */
1456 : 0 : int igmp6_event_report(struct sk_buff *skb)
1457 : : {
1458 : 0 : struct ifmcaddr6 *ma;
1459 : 0 : struct inet6_dev *idev;
1460 : 0 : struct mld_msg *mld;
1461 : 0 : int addr_type;
1462 : :
1463 : : /* Our own report looped back. Ignore it. */
1464 [ # # ]: 0 : if (skb->pkt_type == PACKET_LOOPBACK)
1465 : : return 0;
1466 : :
1467 : : /* send our report if the MC router may not have heard this report */
1468 [ # # ]: 0 : if (skb->pkt_type != PACKET_MULTICAST &&
1469 : : skb->pkt_type != PACKET_BROADCAST)
1470 : : return 0;
1471 : :
1472 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr)))
1473 : : return -EINVAL;
1474 : :
1475 : 0 : mld = (struct mld_msg *)icmp6_hdr(skb);
1476 : :
1477 : : /* Drop reports with not link local source */
1478 : 0 : addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr);
1479 [ # # ]: 0 : if (addr_type != IPV6_ADDR_ANY &&
1480 [ # # ]: 0 : !(addr_type&IPV6_ADDR_LINKLOCAL))
1481 : : return -EINVAL;
1482 : :
1483 [ # # ]: 0 : idev = __in6_dev_get(skb->dev);
1484 [ # # ]: 0 : if (!idev)
1485 : : return -ENODEV;
1486 : :
1487 : : /*
1488 : : * Cancel the timer for this group
1489 : : */
1490 : :
1491 : 0 : read_lock_bh(&idev->lock);
1492 [ # # ]: 0 : for (ma = idev->mc_list; ma; ma = ma->next) {
1493 [ # # ]: 0 : if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) {
1494 : 0 : spin_lock(&ma->mca_lock);
1495 [ # # ]: 0 : if (del_timer(&ma->mca_timer))
1496 : 0 : refcount_dec(&ma->mca_refcnt);
1497 : 0 : ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
1498 : 0 : spin_unlock(&ma->mca_lock);
1499 : : break;
1500 : : }
1501 : : }
1502 : 0 : read_unlock_bh(&idev->lock);
1503 : 0 : return 0;
1504 : : }
1505 : :
1506 : 0 : static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
1507 : : int gdeleted, int sdeleted)
1508 : : {
1509 [ # # # # : 0 : switch (type) {
# # ]
1510 : 0 : case MLD2_MODE_IS_INCLUDE:
1511 : : case MLD2_MODE_IS_EXCLUDE:
1512 [ # # ]: 0 : if (gdeleted || sdeleted)
1513 : : return false;
1514 [ # # # # ]: 0 : if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) {
1515 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_INCLUDE)
1516 : : return true;
1517 : : /* don't include if this source is excluded
1518 : : * in all filters
1519 : : */
1520 [ # # ]: 0 : if (psf->sf_count[MCAST_INCLUDE])
1521 : 0 : return type == MLD2_MODE_IS_INCLUDE;
1522 : 0 : return pmc->mca_sfcount[MCAST_EXCLUDE] ==
1523 : 0 : psf->sf_count[MCAST_EXCLUDE];
1524 : : }
1525 : : return false;
1526 : 0 : case MLD2_CHANGE_TO_INCLUDE:
1527 [ # # ]: 0 : if (gdeleted || sdeleted)
1528 : : return false;
1529 : 0 : return psf->sf_count[MCAST_INCLUDE] != 0;
1530 : 0 : case MLD2_CHANGE_TO_EXCLUDE:
1531 [ # # ]: 0 : if (gdeleted || sdeleted)
1532 : : return false;
1533 [ # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 ||
1534 [ # # ]: 0 : psf->sf_count[MCAST_INCLUDE])
1535 : : return false;
1536 : 0 : return pmc->mca_sfcount[MCAST_EXCLUDE] ==
1537 : 0 : psf->sf_count[MCAST_EXCLUDE];
1538 : 0 : case MLD2_ALLOW_NEW_SOURCES:
1539 [ # # # # ]: 0 : if (gdeleted || !psf->sf_crcount)
1540 : : return false;
1541 : 0 : return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted;
1542 : 0 : case MLD2_BLOCK_OLD_SOURCES:
1543 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_INCLUDE)
1544 [ # # # # : 0 : return gdeleted || (psf->sf_crcount && sdeleted);
# # ]
1545 [ # # # # ]: 0 : return psf->sf_crcount && !gdeleted && !sdeleted;
1546 : : }
1547 : : return false;
1548 : : }
1549 : :
1550 : : static int
1551 : 0 : mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
1552 : : {
1553 : 0 : struct ip6_sf_list *psf;
1554 : 0 : int scount = 0;
1555 : :
1556 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
1557 [ # # ]: 0 : if (!is_in(pmc, psf, type, gdeleted, sdeleted))
1558 : 0 : continue;
1559 : 0 : scount++;
1560 : : }
1561 : 0 : return scount;
1562 : : }
1563 : :
1564 : : static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb,
1565 : : struct net_device *dev,
1566 : : const struct in6_addr *saddr,
1567 : : const struct in6_addr *daddr,
1568 : : int proto, int len)
1569 : : {
1570 : : struct ipv6hdr *hdr;
1571 : :
1572 : : skb->protocol = htons(ETH_P_IPV6);
1573 : : skb->dev = dev;
1574 : :
1575 : : skb_reset_network_header(skb);
1576 : : skb_put(skb, sizeof(struct ipv6hdr));
1577 : : hdr = ipv6_hdr(skb);
1578 : :
1579 : : ip6_flow_hdr(hdr, 0, 0);
1580 : :
1581 : : hdr->payload_len = htons(len);
1582 : : hdr->nexthdr = proto;
1583 : : hdr->hop_limit = inet6_sk(sk)->hop_limit;
1584 : :
1585 : : hdr->saddr = *saddr;
1586 : : hdr->daddr = *daddr;
1587 : : }
1588 : :
1589 : 110 : static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
1590 : : {
1591 : 110 : struct net_device *dev = idev->dev;
1592 : 110 : struct net *net = dev_net(dev);
1593 : 110 : struct sock *sk = net->ipv6.igmp_sk;
1594 : 110 : struct sk_buff *skb;
1595 : 110 : struct mld2_report *pmr;
1596 : 110 : struct in6_addr addr_buf;
1597 : 110 : const struct in6_addr *saddr;
1598 : 110 : int hlen = LL_RESERVED_SPACE(dev);
1599 : 110 : int tlen = dev->needed_tailroom;
1600 : 110 : unsigned int size = mtu + hlen + tlen;
1601 : 110 : int err;
1602 : 110 : u8 ra[8] = { IPPROTO_ICMPV6, 0,
1603 : : IPV6_TLV_ROUTERALERT, 2, 0, 0,
1604 : : IPV6_TLV_PADN, 0 };
1605 : :
1606 : : /* we assume size > sizeof(ra) here */
1607 : : /* limit our allocations to order-0 page */
1608 : 110 : size = min_t(int, size, SKB_MAX_ORDER(0, 0));
1609 : 110 : skb = sock_alloc_send_skb(sk, size, 1, &err);
1610 : :
1611 [ + - ]: 110 : if (!skb)
1612 : : return NULL;
1613 : :
1614 : 110 : skb->priority = TC_PRIO_CONTROL;
1615 : 110 : skb_reserve(skb, hlen);
1616 : 110 : skb_tailroom_reserve(skb, mtu, tlen);
1617 : :
1618 [ + + ]: 110 : if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
1619 : : /* <draft-ietf-magma-mld-source-05.txt>:
1620 : : * use unspecified address as the source address
1621 : : * when a valid link-local address is not available.
1622 : : */
1623 : : saddr = &in6addr_any;
1624 : : } else
1625 : 54 : saddr = &addr_buf;
1626 : :
1627 : 110 : ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
1628 : :
1629 : 110 : skb_put_data(skb, ra, sizeof(ra));
1630 : :
1631 : 110 : skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);
1632 : 110 : skb_put(skb, sizeof(*pmr));
1633 : 110 : pmr = (struct mld2_report *)skb_transport_header(skb);
1634 : 110 : pmr->mld2r_type = ICMPV6_MLD2_REPORT;
1635 : 110 : pmr->mld2r_resv1 = 0;
1636 : 110 : pmr->mld2r_cksum = 0;
1637 : 110 : pmr->mld2r_resv2 = 0;
1638 : 110 : pmr->mld2r_ngrec = 0;
1639 : 110 : return skb;
1640 : : }
1641 : :
1642 : 110 : static void mld_sendpack(struct sk_buff *skb)
1643 : : {
1644 : 110 : struct ipv6hdr *pip6 = ipv6_hdr(skb);
1645 : 110 : struct mld2_report *pmr =
1646 : 110 : (struct mld2_report *)skb_transport_header(skb);
1647 : 110 : int payload_len, mldlen;
1648 : 110 : struct inet6_dev *idev;
1649 : 110 : struct net *net = dev_net(skb->dev);
1650 : 110 : int err;
1651 : 110 : struct flowi6 fl6;
1652 : 110 : struct dst_entry *dst;
1653 : :
1654 : 110 : rcu_read_lock();
1655 [ + - ]: 110 : idev = __in6_dev_get(skb->dev);
1656 [ + - - + : 110 : IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
- - - - -
+ - + - -
- - - + ]
1657 : :
1658 : 110 : payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
1659 : : sizeof(*pip6);
1660 : 110 : mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
1661 : 110 : pip6->payload_len = htons(payload_len);
1662 : :
1663 : 110 : pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
1664 : : IPPROTO_ICMPV6,
1665 : 110 : csum_partial(skb_transport_header(skb),
1666 : : mldlen, 0));
1667 : :
1668 : 110 : icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT,
1669 : 110 : &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
1670 : 110 : skb->dev->ifindex);
1671 : 110 : dst = icmp6_dst_alloc(skb->dev, &fl6);
1672 : :
1673 : 110 : err = 0;
1674 [ - + ]: 110 : if (IS_ERR(dst)) {
1675 : 0 : err = PTR_ERR(dst);
1676 : 0 : dst = NULL;
1677 : : }
1678 [ - + ]: 110 : skb_dst_set(skb, dst);
1679 [ - + ]: 110 : if (err)
1680 : 0 : goto err_out;
1681 : :
1682 : 110 : err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
1683 : : net, net->ipv6.igmp_sk, skb, NULL, skb->dev,
1684 : : dst_output);
1685 : 110 : out:
1686 [ + - ]: 110 : if (!err) {
1687 [ + - ]: 220 : ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
1688 [ + - ]: 220 : ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
1689 : : } else {
1690 [ # # ]: 0 : IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
1691 : : }
1692 : :
1693 : 110 : rcu_read_unlock();
1694 : 110 : return;
1695 : :
1696 : : err_out:
1697 : 0 : kfree_skb(skb);
1698 : 0 : goto out;
1699 : : }
1700 : :
1701 : 0 : static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
1702 : : {
1703 : 0 : return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel);
1704 : : }
1705 : :
1706 : : static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1707 : : int type, struct mld2_grec **ppgr, unsigned int mtu)
1708 : : {
1709 : : struct mld2_report *pmr;
1710 : : struct mld2_grec *pgr;
1711 : :
1712 : : if (!skb) {
1713 : : skb = mld_newpack(pmc->idev, mtu);
1714 : : if (!skb)
1715 : : return NULL;
1716 : : }
1717 : : pgr = skb_put(skb, sizeof(struct mld2_grec));
1718 : : pgr->grec_type = type;
1719 : : pgr->grec_auxwords = 0;
1720 : : pgr->grec_nsrcs = 0;
1721 : : pgr->grec_mca = pmc->mca_addr; /* structure copy */
1722 : : pmr = (struct mld2_report *)skb_transport_header(skb);
1723 : : pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1);
1724 : : *ppgr = pgr;
1725 : : return skb;
1726 : : }
1727 : :
1728 : : #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0)
1729 : :
1730 : 554 : static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1731 : : int type, int gdeleted, int sdeleted, int crsend)
1732 : : {
1733 : 554 : struct inet6_dev *idev = pmc->idev;
1734 : 554 : struct net_device *dev = idev->dev;
1735 : 554 : struct mld2_report *pmr;
1736 : 554 : struct mld2_grec *pgr = NULL;
1737 : 554 : struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
1738 : 554 : int scount, stotal, first, isquery, truncate;
1739 : 554 : unsigned int mtu;
1740 : :
1741 [ + + ]: 554 : if (pmc->mca_flags & MAF_NOREPORT)
1742 : : return skb;
1743 : :
1744 [ + - ]: 222 : mtu = READ_ONCE(dev->mtu);
1745 [ + - ]: 222 : if (mtu < IPV6_MIN_MTU)
1746 : : return skb;
1747 : :
1748 : 222 : isquery = type == MLD2_MODE_IS_INCLUDE ||
1749 : : type == MLD2_MODE_IS_EXCLUDE;
1750 : 222 : truncate = type == MLD2_MODE_IS_EXCLUDE ||
1751 : 222 : type == MLD2_CHANGE_TO_EXCLUDE;
1752 : :
1753 : 222 : stotal = scount = 0;
1754 : :
1755 [ + + ]: 222 : psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources;
1756 : :
1757 [ + - ]: 222 : if (!*psf_list)
1758 : 222 : goto empty_source;
1759 : :
1760 [ # # ]: 0 : pmr = skb ? (struct mld2_report *)skb_transport_header(skb) : NULL;
1761 : :
1762 : : /* EX and TO_EX get a fresh packet, if needed */
1763 [ # # ]: 0 : if (truncate) {
1764 [ # # # # : 0 : if (pmr && pmr->mld2r_ngrec &&
# # ]
1765 [ # # ]: 0 : AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
1766 [ # # ]: 0 : if (skb)
1767 : 0 : mld_sendpack(skb);
1768 : 0 : skb = mld_newpack(idev, mtu);
1769 : : }
1770 : : }
1771 : 0 : first = 1;
1772 : 0 : psf_prev = NULL;
1773 [ # # ]: 0 : for (psf = *psf_list; psf; psf = psf_next) {
1774 : 0 : struct in6_addr *psrc;
1775 : :
1776 : 0 : psf_next = psf->sf_next;
1777 : :
1778 [ # # # # ]: 0 : if (!is_in(pmc, psf, type, gdeleted, sdeleted) && !crsend) {
1779 : 0 : psf_prev = psf;
1780 : 0 : continue;
1781 : : }
1782 : :
1783 : : /* Based on RFC3810 6.1. Should not send source-list change
1784 : : * records when there is a filter mode change.
1785 : : */
1786 [ # # # # : 0 : if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) ||
# # ]
1787 [ # # ]: 0 : (!gdeleted && pmc->mca_crcount)) &&
1788 [ # # ]: 0 : (type == MLD2_ALLOW_NEW_SOURCES ||
1789 [ # # ]: 0 : type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount)
1790 : 0 : goto decrease_sf_crcount;
1791 : :
1792 : : /* clear marks on query responses */
1793 [ # # ]: 0 : if (isquery)
1794 : 0 : psf->sf_gsresp = 0;
1795 : :
1796 [ # # ]: 0 : if (AVAILABLE(skb) < sizeof(*psrc) +
1797 [ # # ]: 0 : first*sizeof(struct mld2_grec)) {
1798 [ # # ]: 0 : if (truncate && !first)
1799 : : break; /* truncate these */
1800 [ # # ]: 0 : if (pgr)
1801 : 0 : pgr->grec_nsrcs = htons(scount);
1802 [ # # ]: 0 : if (skb)
1803 : 0 : mld_sendpack(skb);
1804 : 0 : skb = mld_newpack(idev, mtu);
1805 : 0 : first = 1;
1806 : 0 : scount = 0;
1807 : : }
1808 [ # # ]: 0 : if (first) {
1809 : 0 : skb = add_grhead(skb, pmc, type, &pgr, mtu);
1810 : 0 : first = 0;
1811 : : }
1812 [ # # ]: 0 : if (!skb)
1813 : : return NULL;
1814 : 0 : psrc = skb_put(skb, sizeof(*psrc));
1815 : 0 : *psrc = psf->sf_addr;
1816 : 0 : scount++; stotal++;
1817 [ # # ]: 0 : if ((type == MLD2_ALLOW_NEW_SOURCES ||
1818 [ # # ]: 0 : type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
1819 : 0 : decrease_sf_crcount:
1820 : 0 : psf->sf_crcount--;
1821 [ # # # # ]: 0 : if ((sdeleted || gdeleted) && psf->sf_crcount == 0) {
1822 [ # # ]: 0 : if (psf_prev)
1823 : 0 : psf_prev->sf_next = psf->sf_next;
1824 : : else
1825 : 0 : *psf_list = psf->sf_next;
1826 : 0 : kfree(psf);
1827 : 0 : continue;
1828 : : }
1829 : : }
1830 : : psf_prev = psf;
1831 : : }
1832 : :
1833 : 0 : empty_source:
1834 [ + - ]: 222 : if (!stotal) {
1835 [ + + ]: 222 : if (type == MLD2_ALLOW_NEW_SOURCES ||
1836 : : type == MLD2_BLOCK_OLD_SOURCES)
1837 : : return skb;
1838 [ + + + - ]: 110 : if (pmc->mca_crcount || isquery || crsend) {
1839 : : /* make sure we have room for group header */
1840 [ - + - - ]: 110 : if (skb && AVAILABLE(skb) < sizeof(struct mld2_grec)) {
1841 : 0 : mld_sendpack(skb);
1842 : 0 : skb = NULL; /* add_grhead will get a new one */
1843 : : }
1844 : 110 : skb = add_grhead(skb, pmc, type, &pgr, mtu);
1845 : : }
1846 : : }
1847 [ + - ]: 110 : if (pgr)
1848 : 110 : pgr->grec_nsrcs = htons(scount);
1849 : :
1850 [ - + ]: 110 : if (isquery)
1851 : 0 : pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */
1852 : : return skb;
1853 : : }
1854 : :
1855 : 0 : static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
1856 : : {
1857 : 0 : struct sk_buff *skb = NULL;
1858 : 0 : int type;
1859 : :
1860 : 0 : read_lock_bh(&idev->lock);
1861 [ # # ]: 0 : if (!pmc) {
1862 [ # # ]: 0 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
1863 [ # # ]: 0 : if (pmc->mca_flags & MAF_NOREPORT)
1864 : 0 : continue;
1865 : 0 : spin_lock_bh(&pmc->mca_lock);
1866 [ # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE])
1867 : : type = MLD2_MODE_IS_EXCLUDE;
1868 : : else
1869 : 0 : type = MLD2_MODE_IS_INCLUDE;
1870 : 0 : skb = add_grec(skb, pmc, type, 0, 0, 0);
1871 : 0 : spin_unlock_bh(&pmc->mca_lock);
1872 : : }
1873 : : } else {
1874 : 0 : spin_lock_bh(&pmc->mca_lock);
1875 [ # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE])
1876 : : type = MLD2_MODE_IS_EXCLUDE;
1877 : : else
1878 : 0 : type = MLD2_MODE_IS_INCLUDE;
1879 : 0 : skb = add_grec(skb, pmc, type, 0, 0, 0);
1880 : 0 : spin_unlock_bh(&pmc->mca_lock);
1881 : : }
1882 : 0 : read_unlock_bh(&idev->lock);
1883 [ # # ]: 0 : if (skb)
1884 : 0 : mld_sendpack(skb);
1885 : 0 : }
1886 : :
1887 : : /*
1888 : : * remove zero-count source records from a source filter list
1889 : : */
1890 : 0 : static void mld_clear_zeros(struct ip6_sf_list **ppsf)
1891 : : {
1892 : 0 : struct ip6_sf_list *psf_prev, *psf_next, *psf;
1893 : :
1894 : 0 : psf_prev = NULL;
1895 [ # # ]: 0 : for (psf = *ppsf; psf; psf = psf_next) {
1896 : 0 : psf_next = psf->sf_next;
1897 [ # # ]: 0 : if (psf->sf_crcount == 0) {
1898 [ # # ]: 0 : if (psf_prev)
1899 : 0 : psf_prev->sf_next = psf->sf_next;
1900 : : else
1901 : 0 : *ppsf = psf->sf_next;
1902 : 0 : kfree(psf);
1903 : : } else
1904 : : psf_prev = psf;
1905 : : }
1906 : 0 : }
1907 : :
1908 : 56 : static void mld_send_cr(struct inet6_dev *idev)
1909 : : {
1910 : 56 : struct ifmcaddr6 *pmc, *pmc_prev, *pmc_next;
1911 : 56 : struct sk_buff *skb = NULL;
1912 : 56 : int type, dtype;
1913 : :
1914 : 56 : read_lock_bh(&idev->lock);
1915 : 56 : spin_lock(&idev->mc_lock);
1916 : :
1917 : : /* deleted MCA's */
1918 : 56 : pmc_prev = NULL;
1919 [ - + ]: 56 : for (pmc = idev->mc_tomb; pmc; pmc = pmc_next) {
1920 : 0 : pmc_next = pmc->next;
1921 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_INCLUDE) {
1922 : 0 : type = MLD2_BLOCK_OLD_SOURCES;
1923 : 0 : dtype = MLD2_BLOCK_OLD_SOURCES;
1924 : 0 : skb = add_grec(skb, pmc, type, 1, 0, 0);
1925 : 0 : skb = add_grec(skb, pmc, dtype, 1, 1, 0);
1926 : : }
1927 [ # # ]: 0 : if (pmc->mca_crcount) {
1928 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_EXCLUDE) {
1929 : 0 : type = MLD2_CHANGE_TO_INCLUDE;
1930 : 0 : skb = add_grec(skb, pmc, type, 1, 0, 0);
1931 : : }
1932 : 0 : pmc->mca_crcount--;
1933 [ # # ]: 0 : if (pmc->mca_crcount == 0) {
1934 : 0 : mld_clear_zeros(&pmc->mca_tomb);
1935 : 0 : mld_clear_zeros(&pmc->mca_sources);
1936 : : }
1937 : : }
1938 [ # # # # ]: 0 : if (pmc->mca_crcount == 0 && !pmc->mca_tomb &&
1939 [ # # ]: 0 : !pmc->mca_sources) {
1940 [ # # ]: 0 : if (pmc_prev)
1941 : 0 : pmc_prev->next = pmc_next;
1942 : : else
1943 : 0 : idev->mc_tomb = pmc_next;
1944 : 0 : in6_dev_put(pmc->idev);
1945 : 0 : kfree(pmc);
1946 : : } else
1947 : : pmc_prev = pmc;
1948 : : }
1949 : 56 : spin_unlock(&idev->mc_lock);
1950 : :
1951 : : /* change recs */
1952 [ + + ]: 224 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
1953 : 168 : spin_lock_bh(&pmc->mca_lock);
1954 [ - + ]: 168 : if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
1955 : : type = MLD2_BLOCK_OLD_SOURCES;
1956 : : dtype = MLD2_ALLOW_NEW_SOURCES;
1957 : : } else {
1958 : 0 : type = MLD2_ALLOW_NEW_SOURCES;
1959 : 0 : dtype = MLD2_BLOCK_OLD_SOURCES;
1960 : : }
1961 : 168 : skb = add_grec(skb, pmc, type, 0, 0, 0);
1962 : 168 : skb = add_grec(skb, pmc, dtype, 0, 1, 0); /* deleted sources */
1963 : :
1964 : : /* filter mode changes */
1965 [ + + ]: 168 : if (pmc->mca_crcount) {
1966 [ - + ]: 56 : if (pmc->mca_sfmode == MCAST_EXCLUDE)
1967 : : type = MLD2_CHANGE_TO_EXCLUDE;
1968 : : else
1969 : 0 : type = MLD2_CHANGE_TO_INCLUDE;
1970 : 56 : skb = add_grec(skb, pmc, type, 0, 0, 0);
1971 : 56 : pmc->mca_crcount--;
1972 : : }
1973 : 168 : spin_unlock_bh(&pmc->mca_lock);
1974 : : }
1975 : 56 : read_unlock_bh(&idev->lock);
1976 [ + - ]: 56 : if (!skb)
1977 : : return;
1978 : 56 : (void) mld_sendpack(skb);
1979 : : }
1980 : :
1981 : 0 : static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
1982 : : {
1983 [ # # ]: 0 : struct net *net = dev_net(dev);
1984 : 0 : struct sock *sk = net->ipv6.igmp_sk;
1985 : 0 : struct inet6_dev *idev;
1986 : 0 : struct sk_buff *skb;
1987 : 0 : struct mld_msg *hdr;
1988 : 0 : const struct in6_addr *snd_addr, *saddr;
1989 : 0 : struct in6_addr addr_buf;
1990 : 0 : int hlen = LL_RESERVED_SPACE(dev);
1991 : 0 : int tlen = dev->needed_tailroom;
1992 : 0 : int err, len, payload_len, full_len;
1993 : 0 : u8 ra[8] = { IPPROTO_ICMPV6, 0,
1994 : : IPV6_TLV_ROUTERALERT, 2, 0, 0,
1995 : : IPV6_TLV_PADN, 0 };
1996 : 0 : struct flowi6 fl6;
1997 : 0 : struct dst_entry *dst;
1998 : :
1999 [ # # ]: 0 : if (type == ICMPV6_MGM_REDUCTION)
2000 : : snd_addr = &in6addr_linklocal_allrouters;
2001 : : else
2002 : 0 : snd_addr = addr;
2003 : :
2004 : 0 : len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
2005 : 0 : payload_len = len + sizeof(ra);
2006 : 0 : full_len = sizeof(struct ipv6hdr) + payload_len;
2007 : :
2008 : 0 : rcu_read_lock();
2009 [ # # ]: 0 : IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
2010 : : IPSTATS_MIB_OUT, full_len);
2011 : 0 : rcu_read_unlock();
2012 : :
2013 : 0 : skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err);
2014 : :
2015 [ # # ]: 0 : if (!skb) {
2016 : 0 : rcu_read_lock();
2017 [ # # ]: 0 : IP6_INC_STATS(net, __in6_dev_get(dev),
2018 : : IPSTATS_MIB_OUTDISCARDS);
2019 : 0 : rcu_read_unlock();
2020 : 0 : return;
2021 : : }
2022 : 0 : skb->priority = TC_PRIO_CONTROL;
2023 : 0 : skb_reserve(skb, hlen);
2024 : :
2025 [ # # ]: 0 : if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
2026 : : /* <draft-ietf-magma-mld-source-05.txt>:
2027 : : * use unspecified address as the source address
2028 : : * when a valid link-local address is not available.
2029 : : */
2030 : : saddr = &in6addr_any;
2031 : : } else
2032 : 0 : saddr = &addr_buf;
2033 : :
2034 : 0 : ip6_mc_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
2035 : :
2036 : 0 : skb_put_data(skb, ra, sizeof(ra));
2037 : :
2038 : 0 : hdr = skb_put_zero(skb, sizeof(struct mld_msg));
2039 : 0 : hdr->mld_type = type;
2040 : 0 : hdr->mld_mca = *addr;
2041 : :
2042 : 0 : hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len,
2043 : : IPPROTO_ICMPV6,
2044 : : csum_partial(hdr, len, 0));
2045 : :
2046 : 0 : rcu_read_lock();
2047 : 0 : idev = __in6_dev_get(skb->dev);
2048 : :
2049 : 0 : icmpv6_flow_init(sk, &fl6, type,
2050 : 0 : &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
2051 : : skb->dev->ifindex);
2052 : 0 : dst = icmp6_dst_alloc(skb->dev, &fl6);
2053 [ # # ]: 0 : if (IS_ERR(dst)) {
2054 : 0 : err = PTR_ERR(dst);
2055 : 0 : goto err_out;
2056 : : }
2057 : :
2058 : 0 : skb_dst_set(skb, dst);
2059 : 0 : err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
2060 : : net, sk, skb, NULL, skb->dev,
2061 : : dst_output);
2062 : 0 : out:
2063 [ # # ]: 0 : if (!err) {
2064 [ # # ]: 0 : ICMP6MSGOUT_INC_STATS(net, idev, type);
2065 [ # # ]: 0 : ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
2066 : : } else
2067 [ # # ]: 0 : IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
2068 : :
2069 : 0 : rcu_read_unlock();
2070 : : return;
2071 : :
2072 : : err_out:
2073 : 0 : kfree_skb(skb);
2074 : 0 : goto out;
2075 : : }
2076 : :
2077 : 54 : static void mld_send_initial_cr(struct inet6_dev *idev)
2078 : : {
2079 : 54 : struct sk_buff *skb;
2080 : 54 : struct ifmcaddr6 *pmc;
2081 : 54 : int type;
2082 : :
2083 [ + - ]: 54 : if (mld_in_v1_mode(idev))
2084 : : return;
2085 : :
2086 : 54 : skb = NULL;
2087 : 54 : read_lock_bh(&idev->lock);
2088 [ + + ]: 216 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
2089 : 162 : spin_lock_bh(&pmc->mca_lock);
2090 [ - + ]: 162 : if (pmc->mca_sfcount[MCAST_EXCLUDE])
2091 : : type = MLD2_CHANGE_TO_EXCLUDE;
2092 : : else
2093 : 0 : type = MLD2_ALLOW_NEW_SOURCES;
2094 : 162 : skb = add_grec(skb, pmc, type, 0, 0, 1);
2095 : 162 : spin_unlock_bh(&pmc->mca_lock);
2096 : : }
2097 : 54 : read_unlock_bh(&idev->lock);
2098 [ + - ]: 54 : if (skb)
2099 : 54 : mld_sendpack(skb);
2100 : : }
2101 : :
2102 : 28 : void ipv6_mc_dad_complete(struct inet6_dev *idev)
2103 : : {
2104 : 28 : idev->mc_dad_count = idev->mc_qrv;
2105 [ + - ]: 28 : if (idev->mc_dad_count) {
2106 : 28 : mld_send_initial_cr(idev);
2107 : 28 : idev->mc_dad_count--;
2108 [ + - ]: 28 : if (idev->mc_dad_count)
2109 : 28 : mld_dad_start_timer(idev,
2110 : 28 : unsolicited_report_interval(idev));
2111 : : }
2112 : 28 : }
2113 : :
2114 : 26 : static void mld_dad_timer_expire(struct timer_list *t)
2115 : : {
2116 : 26 : struct inet6_dev *idev = from_timer(idev, t, mc_dad_timer);
2117 : :
2118 : 26 : mld_send_initial_cr(idev);
2119 [ + - ]: 26 : if (idev->mc_dad_count) {
2120 : 26 : idev->mc_dad_count--;
2121 [ - + ]: 26 : if (idev->mc_dad_count)
2122 : 0 : mld_dad_start_timer(idev,
2123 : 0 : unsolicited_report_interval(idev));
2124 : : }
2125 : 26 : in6_dev_put(idev);
2126 : 26 : }
2127 : :
2128 : 0 : static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
2129 : : const struct in6_addr *psfsrc)
2130 : : {
2131 : 0 : struct ip6_sf_list *psf, *psf_prev;
2132 : 0 : int rv = 0;
2133 : :
2134 : 0 : psf_prev = NULL;
2135 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
2136 [ # # ]: 0 : if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
2137 : : break;
2138 : 0 : psf_prev = psf;
2139 : : }
2140 [ # # # # ]: 0 : if (!psf || psf->sf_count[sfmode] == 0) {
2141 : : /* source filter not found, or count wrong => bug */
2142 : : return -ESRCH;
2143 : : }
2144 : 0 : psf->sf_count[sfmode]--;
2145 [ # # # # ]: 0 : if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {
2146 : 0 : struct inet6_dev *idev = pmc->idev;
2147 : :
2148 : : /* no more filters for this source */
2149 [ # # ]: 0 : if (psf_prev)
2150 : 0 : psf_prev->sf_next = psf->sf_next;
2151 : : else
2152 : 0 : pmc->mca_sources = psf->sf_next;
2153 [ # # # # ]: 0 : if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) &&
2154 : : !mld_in_v1_mode(idev)) {
2155 : 0 : psf->sf_crcount = idev->mc_qrv;
2156 : 0 : psf->sf_next = pmc->mca_tomb;
2157 : 0 : pmc->mca_tomb = psf;
2158 : 0 : rv = 1;
2159 : : } else
2160 : 0 : kfree(psf);
2161 : : }
2162 : : return rv;
2163 : : }
2164 : :
2165 : 0 : static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
2166 : : int sfmode, int sfcount, const struct in6_addr *psfsrc,
2167 : : int delta)
2168 : : {
2169 : 0 : struct ifmcaddr6 *pmc;
2170 : 0 : int changerec = 0;
2171 : 0 : int i, err;
2172 : :
2173 [ # # ]: 0 : if (!idev)
2174 : : return -ENODEV;
2175 : 0 : read_lock_bh(&idev->lock);
2176 [ # # ]: 0 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
2177 [ # # ]: 0 : if (ipv6_addr_equal(pmca, &pmc->mca_addr))
2178 : : break;
2179 : : }
2180 [ # # ]: 0 : if (!pmc) {
2181 : : /* MCA not found?? bug */
2182 : 0 : read_unlock_bh(&idev->lock);
2183 : 0 : return -ESRCH;
2184 : : }
2185 : 0 : spin_lock_bh(&pmc->mca_lock);
2186 : 0 : sf_markstate(pmc);
2187 [ # # ]: 0 : if (!delta) {
2188 [ # # ]: 0 : if (!pmc->mca_sfcount[sfmode]) {
2189 : 0 : spin_unlock_bh(&pmc->mca_lock);
2190 : 0 : read_unlock_bh(&idev->lock);
2191 : 0 : return -EINVAL;
2192 : : }
2193 : 0 : pmc->mca_sfcount[sfmode]--;
2194 : : }
2195 : : err = 0;
2196 [ # # ]: 0 : for (i = 0; i < sfcount; i++) {
2197 : 0 : int rv = ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
2198 : :
2199 : 0 : changerec |= rv > 0;
2200 [ # # ]: 0 : if (!err && rv < 0)
2201 : 0 : err = rv;
2202 : : }
2203 [ # # ]: 0 : if (pmc->mca_sfmode == MCAST_EXCLUDE &&
2204 [ # # ]: 0 : pmc->mca_sfcount[MCAST_EXCLUDE] == 0 &&
2205 [ # # ]: 0 : pmc->mca_sfcount[MCAST_INCLUDE]) {
2206 : 0 : struct ip6_sf_list *psf;
2207 : :
2208 : : /* filter mode change */
2209 : 0 : pmc->mca_sfmode = MCAST_INCLUDE;
2210 : 0 : pmc->mca_crcount = idev->mc_qrv;
2211 : 0 : idev->mc_ifc_count = pmc->mca_crcount;
2212 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
2213 : 0 : psf->sf_crcount = 0;
2214 : 0 : mld_ifc_event(pmc->idev);
2215 [ # # # # ]: 0 : } else if (sf_setstate(pmc) || changerec)
2216 : 0 : mld_ifc_event(pmc->idev);
2217 : 0 : spin_unlock_bh(&pmc->mca_lock);
2218 : 0 : read_unlock_bh(&idev->lock);
2219 : 0 : return err;
2220 : : }
2221 : :
2222 : : /*
2223 : : * Add multicast single-source filter to the interface list
2224 : : */
2225 : : static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
2226 : : const struct in6_addr *psfsrc)
2227 : : {
2228 : : struct ip6_sf_list *psf, *psf_prev;
2229 : :
2230 : : psf_prev = NULL;
2231 : : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
2232 : : if (ipv6_addr_equal(&psf->sf_addr, psfsrc))
2233 : : break;
2234 : : psf_prev = psf;
2235 : : }
2236 : : if (!psf) {
2237 : : psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
2238 : : if (!psf)
2239 : : return -ENOBUFS;
2240 : :
2241 : : psf->sf_addr = *psfsrc;
2242 : : if (psf_prev) {
2243 : : psf_prev->sf_next = psf;
2244 : : } else
2245 : : pmc->mca_sources = psf;
2246 : : }
2247 : : psf->sf_count[sfmode]++;
2248 : : return 0;
2249 : : }
2250 : :
2251 : 0 : static void sf_markstate(struct ifmcaddr6 *pmc)
2252 : : {
2253 : 0 : struct ip6_sf_list *psf;
2254 : 0 : int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
2255 : :
2256 [ # # # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
2257 [ # # # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
2258 : 0 : psf->sf_oldin = mca_xcount ==
2259 [ # # # # ]: 0 : psf->sf_count[MCAST_EXCLUDE] &&
2260 [ # # # # ]: 0 : !psf->sf_count[MCAST_INCLUDE];
2261 : : } else
2262 : 0 : psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0;
2263 : : }
2264 : :
2265 : 0 : static int sf_setstate(struct ifmcaddr6 *pmc)
2266 : : {
2267 : 0 : struct ip6_sf_list *psf, *dpsf;
2268 : 0 : int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE];
2269 : 0 : int qrv = pmc->idev->mc_qrv;
2270 : 0 : int new_in, rv;
2271 : :
2272 : 0 : rv = 0;
2273 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next) {
2274 [ # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE]) {
2275 [ # # ]: 0 : new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] &&
2276 [ # # ]: 0 : !psf->sf_count[MCAST_INCLUDE];
2277 : : } else
2278 : 0 : new_in = psf->sf_count[MCAST_INCLUDE] != 0;
2279 [ # # ]: 0 : if (new_in) {
2280 [ # # ]: 0 : if (!psf->sf_oldin) {
2281 : 0 : struct ip6_sf_list *prev = NULL;
2282 : :
2283 [ # # ]: 0 : for (dpsf = pmc->mca_tomb; dpsf;
2284 : 0 : dpsf = dpsf->sf_next) {
2285 [ # # ]: 0 : if (ipv6_addr_equal(&dpsf->sf_addr,
2286 : : &psf->sf_addr))
2287 : : break;
2288 : 0 : prev = dpsf;
2289 : : }
2290 [ # # ]: 0 : if (dpsf) {
2291 [ # # ]: 0 : if (prev)
2292 : 0 : prev->sf_next = dpsf->sf_next;
2293 : : else
2294 : 0 : pmc->mca_tomb = dpsf->sf_next;
2295 : 0 : kfree(dpsf);
2296 : : }
2297 : 0 : psf->sf_crcount = qrv;
2298 : 0 : rv++;
2299 : : }
2300 [ # # ]: 0 : } else if (psf->sf_oldin) {
2301 : 0 : psf->sf_crcount = 0;
2302 : : /*
2303 : : * add or update "delete" records if an active filter
2304 : : * is now inactive
2305 : : */
2306 [ # # ]: 0 : for (dpsf = pmc->mca_tomb; dpsf; dpsf = dpsf->sf_next)
2307 [ # # ]: 0 : if (ipv6_addr_equal(&dpsf->sf_addr,
2308 : : &psf->sf_addr))
2309 : : break;
2310 [ # # ]: 0 : if (!dpsf) {
2311 : 0 : dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC);
2312 [ # # ]: 0 : if (!dpsf)
2313 : 0 : continue;
2314 : 0 : *dpsf = *psf;
2315 : : /* pmc->mca_lock held by callers */
2316 : 0 : dpsf->sf_next = pmc->mca_tomb;
2317 : 0 : pmc->mca_tomb = dpsf;
2318 : : }
2319 : 0 : dpsf->sf_crcount = qrv;
2320 : 0 : rv++;
2321 : : }
2322 : : }
2323 : 0 : return rv;
2324 : : }
2325 : :
2326 : : /*
2327 : : * Add multicast source filter list to the interface list
2328 : : */
2329 : 0 : static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
2330 : : int sfmode, int sfcount, const struct in6_addr *psfsrc,
2331 : : int delta)
2332 : : {
2333 : 0 : struct ifmcaddr6 *pmc;
2334 : 0 : int isexclude;
2335 : 0 : int i, err;
2336 : :
2337 [ # # ]: 0 : if (!idev)
2338 : : return -ENODEV;
2339 : 0 : read_lock_bh(&idev->lock);
2340 [ # # ]: 0 : for (pmc = idev->mc_list; pmc; pmc = pmc->next) {
2341 [ # # ]: 0 : if (ipv6_addr_equal(pmca, &pmc->mca_addr))
2342 : : break;
2343 : : }
2344 [ # # ]: 0 : if (!pmc) {
2345 : : /* MCA not found?? bug */
2346 : 0 : read_unlock_bh(&idev->lock);
2347 : 0 : return -ESRCH;
2348 : : }
2349 : 0 : spin_lock_bh(&pmc->mca_lock);
2350 : :
2351 : 0 : sf_markstate(pmc);
2352 : 0 : isexclude = pmc->mca_sfmode == MCAST_EXCLUDE;
2353 [ # # ]: 0 : if (!delta)
2354 : 0 : pmc->mca_sfcount[sfmode]++;
2355 : : err = 0;
2356 [ # # ]: 0 : for (i = 0; i < sfcount; i++) {
2357 : 0 : err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]);
2358 [ # # ]: 0 : if (err)
2359 : : break;
2360 : : }
2361 [ # # ]: 0 : if (err) {
2362 : 0 : int j;
2363 : :
2364 [ # # ]: 0 : if (!delta)
2365 : 0 : pmc->mca_sfcount[sfmode]--;
2366 [ # # ]: 0 : for (j = 0; j < i; j++)
2367 : 0 : ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
2368 [ # # ]: 0 : } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
2369 : 0 : struct ip6_sf_list *psf;
2370 : :
2371 : : /* filter mode change */
2372 [ # # ]: 0 : if (pmc->mca_sfcount[MCAST_EXCLUDE])
2373 : 0 : pmc->mca_sfmode = MCAST_EXCLUDE;
2374 [ # # ]: 0 : else if (pmc->mca_sfcount[MCAST_INCLUDE])
2375 : 0 : pmc->mca_sfmode = MCAST_INCLUDE;
2376 : : /* else no filters; keep old mode for reports */
2377 : :
2378 : 0 : pmc->mca_crcount = idev->mc_qrv;
2379 : 0 : idev->mc_ifc_count = pmc->mca_crcount;
2380 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = psf->sf_next)
2381 : 0 : psf->sf_crcount = 0;
2382 : 0 : mld_ifc_event(idev);
2383 [ # # ]: 0 : } else if (sf_setstate(pmc))
2384 : 0 : mld_ifc_event(idev);
2385 : 0 : spin_unlock_bh(&pmc->mca_lock);
2386 : 0 : read_unlock_bh(&idev->lock);
2387 : 0 : return err;
2388 : : }
2389 : :
2390 : 0 : static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
2391 : : {
2392 : 0 : struct ip6_sf_list *psf, *nextpsf;
2393 : :
2394 [ # # ]: 0 : for (psf = pmc->mca_tomb; psf; psf = nextpsf) {
2395 : 0 : nextpsf = psf->sf_next;
2396 : 0 : kfree(psf);
2397 : : }
2398 : 0 : pmc->mca_tomb = NULL;
2399 [ # # ]: 0 : for (psf = pmc->mca_sources; psf; psf = nextpsf) {
2400 : 0 : nextpsf = psf->sf_next;
2401 : 0 : kfree(psf);
2402 : : }
2403 : 0 : pmc->mca_sources = NULL;
2404 : 0 : pmc->mca_sfmode = MCAST_EXCLUDE;
2405 : 0 : pmc->mca_sfcount[MCAST_INCLUDE] = 0;
2406 : 0 : pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
2407 : 0 : }
2408 : :
2409 : :
2410 : 0 : static void igmp6_join_group(struct ifmcaddr6 *ma)
2411 : : {
2412 : 0 : unsigned long delay;
2413 : :
2414 [ # # ]: 0 : if (ma->mca_flags & MAF_NOREPORT)
2415 : : return;
2416 : :
2417 : 0 : igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
2418 : :
2419 : 0 : delay = prandom_u32() % unsolicited_report_interval(ma->idev);
2420 : :
2421 : 0 : spin_lock_bh(&ma->mca_lock);
2422 [ # # ]: 0 : if (del_timer(&ma->mca_timer)) {
2423 : 0 : refcount_dec(&ma->mca_refcnt);
2424 : 0 : delay = ma->mca_timer.expires - jiffies;
2425 : : }
2426 : :
2427 [ # # ]: 0 : if (!mod_timer(&ma->mca_timer, jiffies + delay))
2428 : 0 : refcount_inc(&ma->mca_refcnt);
2429 : 0 : ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
2430 : 0 : spin_unlock_bh(&ma->mca_lock);
2431 : : }
2432 : :
2433 : 0 : static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
2434 : : struct inet6_dev *idev)
2435 : : {
2436 : 0 : int err;
2437 : :
2438 : 0 : write_lock_bh(&iml->sflock);
2439 [ # # ]: 0 : if (!iml->sflist) {
2440 : : /* any-source empty exclude case */
2441 : 0 : err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0);
2442 : : } else {
2443 : 0 : err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode,
2444 : 0 : iml->sflist->sl_count, iml->sflist->sl_addr, 0);
2445 : 0 : sock_kfree_s(sk, iml->sflist, IP6_SFLSIZE(iml->sflist->sl_max));
2446 : 0 : iml->sflist = NULL;
2447 : : }
2448 : 0 : write_unlock_bh(&iml->sflock);
2449 : 0 : return err;
2450 : : }
2451 : :
2452 : 0 : static void igmp6_leave_group(struct ifmcaddr6 *ma)
2453 : : {
2454 [ # # ]: 0 : if (mld_in_v1_mode(ma->idev)) {
2455 [ # # ]: 0 : if (ma->mca_flags & MAF_LAST_REPORTER)
2456 : 0 : igmp6_send(&ma->mca_addr, ma->idev->dev,
2457 : : ICMPV6_MGM_REDUCTION);
2458 : : } else {
2459 : 0 : mld_add_delrec(ma->idev, ma);
2460 : 0 : mld_ifc_event(ma->idev);
2461 : : }
2462 : 0 : }
2463 : :
2464 : 0 : static void mld_gq_timer_expire(struct timer_list *t)
2465 : : {
2466 : 0 : struct inet6_dev *idev = from_timer(idev, t, mc_gq_timer);
2467 : :
2468 : 0 : idev->mc_gq_running = 0;
2469 : 0 : mld_send_report(idev, NULL);
2470 : 0 : in6_dev_put(idev);
2471 : 0 : }
2472 : :
2473 : 56 : static void mld_ifc_timer_expire(struct timer_list *t)
2474 : : {
2475 : 56 : struct inet6_dev *idev = from_timer(idev, t, mc_ifc_timer);
2476 : :
2477 : 56 : mld_send_cr(idev);
2478 [ + - ]: 56 : if (idev->mc_ifc_count) {
2479 : 56 : idev->mc_ifc_count--;
2480 [ + + ]: 56 : if (idev->mc_ifc_count)
2481 : 28 : mld_ifc_start_timer(idev,
2482 : 28 : unsolicited_report_interval(idev));
2483 : : }
2484 : 56 : in6_dev_put(idev);
2485 : 56 : }
2486 : :
2487 : 28 : static void mld_ifc_event(struct inet6_dev *idev)
2488 : : {
2489 [ + - ]: 28 : if (mld_in_v1_mode(idev))
2490 : : return;
2491 : 28 : idev->mc_ifc_count = idev->mc_qrv;
2492 : 28 : mld_ifc_start_timer(idev, 1);
2493 : : }
2494 : :
2495 : 0 : static void igmp6_timer_handler(struct timer_list *t)
2496 : : {
2497 : 0 : struct ifmcaddr6 *ma = from_timer(ma, t, mca_timer);
2498 : :
2499 [ # # ]: 0 : if (mld_in_v1_mode(ma->idev))
2500 : 0 : igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
2501 : : else
2502 : 0 : mld_send_report(ma->idev, ma);
2503 : :
2504 : 0 : spin_lock(&ma->mca_lock);
2505 : 0 : ma->mca_flags |= MAF_LAST_REPORTER;
2506 : 0 : ma->mca_flags &= ~MAF_TIMER_RUNNING;
2507 : 0 : spin_unlock(&ma->mca_lock);
2508 : 0 : ma_put(ma);
2509 : 0 : }
2510 : :
2511 : : /* Device changing type */
2512 : :
2513 : 0 : void ipv6_mc_unmap(struct inet6_dev *idev)
2514 : : {
2515 : 0 : struct ifmcaddr6 *i;
2516 : :
2517 : : /* Install multicast list, except for all-nodes (already installed) */
2518 : :
2519 : 0 : read_lock_bh(&idev->lock);
2520 [ # # ]: 0 : for (i = idev->mc_list; i; i = i->next)
2521 : 0 : igmp6_group_dropped(i);
2522 : 0 : read_unlock_bh(&idev->lock);
2523 : 0 : }
2524 : :
2525 : 0 : void ipv6_mc_remap(struct inet6_dev *idev)
2526 : : {
2527 : 0 : ipv6_mc_up(idev);
2528 : 0 : }
2529 : :
2530 : : /* Device going down */
2531 : :
2532 : 0 : void ipv6_mc_down(struct inet6_dev *idev)
2533 : : {
2534 : 0 : struct ifmcaddr6 *i;
2535 : :
2536 : : /* Withdraw multicast list */
2537 : :
2538 : 0 : read_lock_bh(&idev->lock);
2539 : :
2540 [ # # ]: 0 : for (i = idev->mc_list; i; i = i->next)
2541 : 0 : igmp6_group_dropped(i);
2542 : :
2543 : : /* Should stop timer after group drop. or we will
2544 : : * start timer again in mld_ifc_event()
2545 : : */
2546 : 0 : mld_ifc_stop_timer(idev);
2547 : 0 : mld_gq_stop_timer(idev);
2548 : 0 : mld_dad_stop_timer(idev);
2549 : 0 : read_unlock_bh(&idev->lock);
2550 : 0 : }
2551 : :
2552 : 295 : static void ipv6_mc_reset(struct inet6_dev *idev)
2553 : : {
2554 : 295 : idev->mc_qrv = sysctl_mld_qrv;
2555 : 295 : idev->mc_qi = MLD_QI_DEFAULT;
2556 : 295 : idev->mc_qri = MLD_QRI_DEFAULT;
2557 : 295 : idev->mc_v1_seen = 0;
2558 : 590 : idev->mc_maxdelay = unsolicited_report_interval(idev);
2559 : : }
2560 : :
2561 : : /* Device going up */
2562 : :
2563 : 106 : void ipv6_mc_up(struct inet6_dev *idev)
2564 : : {
2565 : 106 : struct ifmcaddr6 *i;
2566 : :
2567 : : /* Install multicast list, except for all-nodes (already installed) */
2568 : :
2569 : 106 : read_lock_bh(&idev->lock);
2570 : 106 : ipv6_mc_reset(idev);
2571 [ + + ]: 318 : for (i = idev->mc_list; i; i = i->next) {
2572 : 212 : mld_del_delrec(idev, i);
2573 : 212 : igmp6_group_added(i);
2574 : : }
2575 : 106 : read_unlock_bh(&idev->lock);
2576 : 106 : }
2577 : :
2578 : : /* IPv6 device initialization. */
2579 : :
2580 : 189 : void ipv6_mc_init_dev(struct inet6_dev *idev)
2581 : : {
2582 : 189 : write_lock_bh(&idev->lock);
2583 : 189 : spin_lock_init(&idev->mc_lock);
2584 : 189 : idev->mc_gq_running = 0;
2585 : 189 : timer_setup(&idev->mc_gq_timer, mld_gq_timer_expire, 0);
2586 : 189 : idev->mc_tomb = NULL;
2587 : 189 : idev->mc_ifc_count = 0;
2588 : 189 : timer_setup(&idev->mc_ifc_timer, mld_ifc_timer_expire, 0);
2589 : 189 : timer_setup(&idev->mc_dad_timer, mld_dad_timer_expire, 0);
2590 : 189 : ipv6_mc_reset(idev);
2591 : 189 : write_unlock_bh(&idev->lock);
2592 : 189 : }
2593 : :
2594 : : /*
2595 : : * Device is about to be destroyed: clean up.
2596 : : */
2597 : :
2598 : 0 : void ipv6_mc_destroy_dev(struct inet6_dev *idev)
2599 : : {
2600 : 0 : struct ifmcaddr6 *i;
2601 : :
2602 : : /* Deactivate timers */
2603 : 0 : ipv6_mc_down(idev);
2604 : 0 : mld_clear_delrec(idev);
2605 : :
2606 : : /* Delete all-nodes address. */
2607 : : /* We cannot call ipv6_dev_mc_dec() directly, our caller in
2608 : : * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
2609 : : * fail.
2610 : : */
2611 : 0 : __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
2612 : :
2613 [ # # ]: 0 : if (idev->cnf.forwarding)
2614 : 0 : __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
2615 : :
2616 : 0 : write_lock_bh(&idev->lock);
2617 [ # # ]: 0 : while ((i = idev->mc_list) != NULL) {
2618 : 0 : idev->mc_list = i->next;
2619 : :
2620 : 0 : write_unlock_bh(&idev->lock);
2621 : 0 : ma_put(i);
2622 : 0 : write_lock_bh(&idev->lock);
2623 : : }
2624 : 0 : write_unlock_bh(&idev->lock);
2625 : 0 : }
2626 : :
2627 : 0 : static void ipv6_mc_rejoin_groups(struct inet6_dev *idev)
2628 : : {
2629 : 0 : struct ifmcaddr6 *pmc;
2630 : :
2631 [ # # # # ]: 0 : ASSERT_RTNL();
2632 : :
2633 [ # # ]: 0 : if (mld_in_v1_mode(idev)) {
2634 : 0 : read_lock_bh(&idev->lock);
2635 [ # # ]: 0 : for (pmc = idev->mc_list; pmc; pmc = pmc->next)
2636 : 0 : igmp6_join_group(pmc);
2637 : 0 : read_unlock_bh(&idev->lock);
2638 : : } else
2639 : 0 : mld_send_report(idev, NULL);
2640 : 0 : }
2641 : :
2642 : 550 : static int ipv6_mc_netdev_event(struct notifier_block *this,
2643 : : unsigned long event,
2644 : : void *ptr)
2645 : : {
2646 [ - + ]: 550 : struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2647 [ - + ]: 550 : struct inet6_dev *idev = __in6_dev_get(dev);
2648 : :
2649 [ - + ]: 550 : switch (event) {
2650 : 0 : case NETDEV_RESEND_IGMP:
2651 [ # # ]: 0 : if (idev)
2652 : 0 : ipv6_mc_rejoin_groups(idev);
2653 : : break;
2654 : : default:
2655 : : break;
2656 : : }
2657 : :
2658 : 550 : return NOTIFY_DONE;
2659 : : }
2660 : :
2661 : : static struct notifier_block igmp6_netdev_notifier = {
2662 : : .notifier_call = ipv6_mc_netdev_event,
2663 : : };
2664 : :
2665 : : #ifdef CONFIG_PROC_FS
2666 : : struct igmp6_mc_iter_state {
2667 : : struct seq_net_private p;
2668 : : struct net_device *dev;
2669 : : struct inet6_dev *idev;
2670 : : };
2671 : :
2672 : : #define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)(seq)->private)
2673 : :
2674 : : static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
2675 : : {
2676 : : struct ifmcaddr6 *im = NULL;
2677 : : struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2678 : : struct net *net = seq_file_net(seq);
2679 : :
2680 : : state->idev = NULL;
2681 : : for_each_netdev_rcu(net, state->dev) {
2682 : : struct inet6_dev *idev;
2683 : : idev = __in6_dev_get(state->dev);
2684 : : if (!idev)
2685 : : continue;
2686 : : read_lock_bh(&idev->lock);
2687 : : im = idev->mc_list;
2688 : : if (im) {
2689 : : state->idev = idev;
2690 : : break;
2691 : : }
2692 : : read_unlock_bh(&idev->lock);
2693 : : }
2694 : : return im;
2695 : : }
2696 : :
2697 : : static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im)
2698 : : {
2699 : : struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2700 : :
2701 : : im = im->next;
2702 : : while (!im) {
2703 : : if (likely(state->idev))
2704 : : read_unlock_bh(&state->idev->lock);
2705 : :
2706 : : state->dev = next_net_device_rcu(state->dev);
2707 : : if (!state->dev) {
2708 : : state->idev = NULL;
2709 : : break;
2710 : : }
2711 : : state->idev = __in6_dev_get(state->dev);
2712 : : if (!state->idev)
2713 : : continue;
2714 : : read_lock_bh(&state->idev->lock);
2715 : : im = state->idev->mc_list;
2716 : : }
2717 : : return im;
2718 : : }
2719 : :
2720 : 0 : static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos)
2721 : : {
2722 : 0 : struct ifmcaddr6 *im = igmp6_mc_get_first(seq);
2723 [ # # ]: 0 : if (im)
2724 [ # # # # ]: 0 : while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL)
2725 : 0 : --pos;
2726 [ # # ]: 0 : return pos ? NULL : im;
2727 : : }
2728 : :
2729 : 0 : static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos)
2730 : : __acquires(RCU)
2731 : : {
2732 : 0 : rcu_read_lock();
2733 : 0 : return igmp6_mc_get_idx(seq, *pos);
2734 : : }
2735 : :
2736 : 0 : static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2737 : : {
2738 : 0 : struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v);
2739 : :
2740 : 0 : ++*pos;
2741 : 0 : return im;
2742 : : }
2743 : :
2744 : 0 : static void igmp6_mc_seq_stop(struct seq_file *seq, void *v)
2745 : : __releases(RCU)
2746 : : {
2747 : 0 : struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2748 : :
2749 [ # # ]: 0 : if (likely(state->idev)) {
2750 : 0 : read_unlock_bh(&state->idev->lock);
2751 : 0 : state->idev = NULL;
2752 : : }
2753 : 0 : state->dev = NULL;
2754 : 0 : rcu_read_unlock();
2755 : 0 : }
2756 : :
2757 : 0 : static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
2758 : : {
2759 : 0 : struct ifmcaddr6 *im = (struct ifmcaddr6 *)v;
2760 : 0 : struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
2761 : :
2762 : 0 : seq_printf(seq,
2763 : : "%-4d %-15s %pi6 %5d %08X %ld\n",
2764 : 0 : state->dev->ifindex, state->dev->name,
2765 : : &im->mca_addr,
2766 : : im->mca_users, im->mca_flags,
2767 [ # # ]: 0 : (im->mca_flags&MAF_TIMER_RUNNING) ?
2768 : 0 : jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0);
2769 : 0 : return 0;
2770 : : }
2771 : :
2772 : : static const struct seq_operations igmp6_mc_seq_ops = {
2773 : : .start = igmp6_mc_seq_start,
2774 : : .next = igmp6_mc_seq_next,
2775 : : .stop = igmp6_mc_seq_stop,
2776 : : .show = igmp6_mc_seq_show,
2777 : : };
2778 : :
2779 : : struct igmp6_mcf_iter_state {
2780 : : struct seq_net_private p;
2781 : : struct net_device *dev;
2782 : : struct inet6_dev *idev;
2783 : : struct ifmcaddr6 *im;
2784 : : };
2785 : :
2786 : : #define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)(seq)->private)
2787 : :
2788 : : static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
2789 : : {
2790 : : struct ip6_sf_list *psf = NULL;
2791 : : struct ifmcaddr6 *im = NULL;
2792 : : struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2793 : : struct net *net = seq_file_net(seq);
2794 : :
2795 : : state->idev = NULL;
2796 : : state->im = NULL;
2797 : : for_each_netdev_rcu(net, state->dev) {
2798 : : struct inet6_dev *idev;
2799 : : idev = __in6_dev_get(state->dev);
2800 : : if (unlikely(idev == NULL))
2801 : : continue;
2802 : : read_lock_bh(&idev->lock);
2803 : : im = idev->mc_list;
2804 : : if (likely(im)) {
2805 : : spin_lock_bh(&im->mca_lock);
2806 : : psf = im->mca_sources;
2807 : : if (likely(psf)) {
2808 : : state->im = im;
2809 : : state->idev = idev;
2810 : : break;
2811 : : }
2812 : : spin_unlock_bh(&im->mca_lock);
2813 : : }
2814 : : read_unlock_bh(&idev->lock);
2815 : : }
2816 : : return psf;
2817 : : }
2818 : :
2819 : : static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_sf_list *psf)
2820 : : {
2821 : : struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2822 : :
2823 : : psf = psf->sf_next;
2824 : : while (!psf) {
2825 : : spin_unlock_bh(&state->im->mca_lock);
2826 : : state->im = state->im->next;
2827 : : while (!state->im) {
2828 : : if (likely(state->idev))
2829 : : read_unlock_bh(&state->idev->lock);
2830 : :
2831 : : state->dev = next_net_device_rcu(state->dev);
2832 : : if (!state->dev) {
2833 : : state->idev = NULL;
2834 : : goto out;
2835 : : }
2836 : : state->idev = __in6_dev_get(state->dev);
2837 : : if (!state->idev)
2838 : : continue;
2839 : : read_lock_bh(&state->idev->lock);
2840 : : state->im = state->idev->mc_list;
2841 : : }
2842 : : if (!state->im)
2843 : : break;
2844 : : spin_lock_bh(&state->im->mca_lock);
2845 : : psf = state->im->mca_sources;
2846 : : }
2847 : : out:
2848 : : return psf;
2849 : : }
2850 : :
2851 : 0 : static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
2852 : : {
2853 : 0 : struct ip6_sf_list *psf = igmp6_mcf_get_first(seq);
2854 [ # # ]: 0 : if (psf)
2855 [ # # # # ]: 0 : while (pos && (psf = igmp6_mcf_get_next(seq, psf)) != NULL)
2856 : 0 : --pos;
2857 [ # # ]: 0 : return pos ? NULL : psf;
2858 : : }
2859 : :
2860 : 0 : static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos)
2861 : : __acquires(RCU)
2862 : : {
2863 : 0 : rcu_read_lock();
2864 [ # # ]: 0 : return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
2865 : : }
2866 : :
2867 : 0 : static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2868 : : {
2869 : 0 : struct ip6_sf_list *psf;
2870 [ # # ]: 0 : if (v == SEQ_START_TOKEN)
2871 : 0 : psf = igmp6_mcf_get_first(seq);
2872 : : else
2873 : 0 : psf = igmp6_mcf_get_next(seq, v);
2874 : 0 : ++*pos;
2875 : 0 : return psf;
2876 : : }
2877 : :
2878 : 0 : static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v)
2879 : : __releases(RCU)
2880 : : {
2881 : 0 : struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2882 [ # # ]: 0 : if (likely(state->im)) {
2883 : 0 : spin_unlock_bh(&state->im->mca_lock);
2884 : 0 : state->im = NULL;
2885 : : }
2886 [ # # ]: 0 : if (likely(state->idev)) {
2887 : 0 : read_unlock_bh(&state->idev->lock);
2888 : 0 : state->idev = NULL;
2889 : : }
2890 : 0 : state->dev = NULL;
2891 : 0 : rcu_read_unlock();
2892 : 0 : }
2893 : :
2894 : 0 : static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
2895 : : {
2896 : 0 : struct ip6_sf_list *psf = (struct ip6_sf_list *)v;
2897 : 0 : struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq);
2898 : :
2899 [ # # ]: 0 : if (v == SEQ_START_TOKEN) {
2900 : 0 : seq_puts(seq, "Idx Device Multicast Address Source Address INC EXC\n");
2901 : : } else {
2902 : 0 : seq_printf(seq,
2903 : : "%3d %6.6s %pi6 %pi6 %6lu %6lu\n",
2904 : 0 : state->dev->ifindex, state->dev->name,
2905 : 0 : &state->im->mca_addr,
2906 : : &psf->sf_addr,
2907 : : psf->sf_count[MCAST_INCLUDE],
2908 : : psf->sf_count[MCAST_EXCLUDE]);
2909 : : }
2910 : 0 : return 0;
2911 : : }
2912 : :
2913 : : static const struct seq_operations igmp6_mcf_seq_ops = {
2914 : : .start = igmp6_mcf_seq_start,
2915 : : .next = igmp6_mcf_seq_next,
2916 : : .stop = igmp6_mcf_seq_stop,
2917 : : .show = igmp6_mcf_seq_show,
2918 : : };
2919 : :
2920 : : static int __net_init igmp6_proc_init(struct net *net)
2921 : : {
2922 : : int err;
2923 : :
2924 : : err = -ENOMEM;
2925 : : if (!proc_create_net("igmp6", 0444, net->proc_net, &igmp6_mc_seq_ops,
2926 : : sizeof(struct igmp6_mc_iter_state)))
2927 : : goto out;
2928 : : if (!proc_create_net("mcfilter6", 0444, net->proc_net,
2929 : : &igmp6_mcf_seq_ops,
2930 : : sizeof(struct igmp6_mcf_iter_state)))
2931 : : goto out_proc_net_igmp6;
2932 : :
2933 : : err = 0;
2934 : : out:
2935 : : return err;
2936 : :
2937 : : out_proc_net_igmp6:
2938 : : remove_proc_entry("igmp6", net->proc_net);
2939 : : goto out;
2940 : : }
2941 : :
2942 : : static void __net_exit igmp6_proc_exit(struct net *net)
2943 : : {
2944 : : remove_proc_entry("mcfilter6", net->proc_net);
2945 : : remove_proc_entry("igmp6", net->proc_net);
2946 : : }
2947 : : #else
2948 : : static inline int igmp6_proc_init(struct net *net)
2949 : : {
2950 : : return 0;
2951 : : }
2952 : : static inline void igmp6_proc_exit(struct net *net)
2953 : : {
2954 : : }
2955 : : #endif
2956 : :
2957 : 78 : static int __net_init igmp6_net_init(struct net *net)
2958 : : {
2959 : 78 : int err;
2960 : :
2961 : 78 : err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6,
2962 : : SOCK_RAW, IPPROTO_ICMPV6, net);
2963 [ - + ]: 78 : if (err < 0) {
2964 : 0 : pr_err("Failed to initialize the IGMP6 control socket (err %d)\n",
2965 : : err);
2966 : 0 : goto out;
2967 : : }
2968 : :
2969 [ + - ]: 78 : inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1;
2970 : :
2971 : 78 : err = inet_ctl_sock_create(&net->ipv6.mc_autojoin_sk, PF_INET6,
2972 : : SOCK_RAW, IPPROTO_ICMPV6, net);
2973 [ - + ]: 78 : if (err < 0) {
2974 : 0 : pr_err("Failed to initialize the IGMP6 autojoin socket (err %d)\n",
2975 : : err);
2976 : 0 : goto out_sock_create;
2977 : : }
2978 : :
2979 : 78 : err = igmp6_proc_init(net);
2980 [ - + ]: 78 : if (err)
2981 : 0 : goto out_sock_create_autojoin;
2982 : :
2983 : : return 0;
2984 : :
2985 : : out_sock_create_autojoin:
2986 [ # # ]: 0 : inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk);
2987 : 0 : out_sock_create:
2988 [ # # ]: 0 : inet_ctl_sock_destroy(net->ipv6.igmp_sk);
2989 : : out:
2990 : : return err;
2991 : : }
2992 : :
2993 : 0 : static void __net_exit igmp6_net_exit(struct net *net)
2994 : : {
2995 [ # # ]: 0 : inet_ctl_sock_destroy(net->ipv6.igmp_sk);
2996 [ # # ]: 0 : inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk);
2997 : 0 : igmp6_proc_exit(net);
2998 : 0 : }
2999 : :
3000 : : static struct pernet_operations igmp6_net_ops = {
3001 : : .init = igmp6_net_init,
3002 : : .exit = igmp6_net_exit,
3003 : : };
3004 : :
3005 : 78 : int __init igmp6_init(void)
3006 : : {
3007 : 78 : return register_pernet_subsys(&igmp6_net_ops);
3008 : : }
3009 : :
3010 : 78 : int __init igmp6_late_init(void)
3011 : : {
3012 : 78 : return register_netdevice_notifier(&igmp6_netdev_notifier);
3013 : : }
3014 : :
3015 : 0 : void igmp6_cleanup(void)
3016 : : {
3017 : 0 : unregister_pernet_subsys(&igmp6_net_ops);
3018 : 0 : }
3019 : :
3020 : 0 : void igmp6_late_cleanup(void)
3021 : : {
3022 : 0 : unregister_netdevice_notifier(&igmp6_netdev_notifier);
3023 : 0 : }
|