Lines Matching +full:im +full:-

1 // SPDX-License-Identifier: GPL-2.0-or-later
14 * yoshfuji : fix format of router-alert option
17 * <draft-ietf-magma-mld-source-05.txt>.
19 * - Ignore Queries for invalid addresses.
20 * - MLD for link-local addresses.
22 * - MLDv2 support
112 rcu_dereference_protected(e, lockdep_is_held(&(idev)->mc_lock))
118 for (pmc = sock_dereference((np)->ipv6_mc_list, sk); \
120 pmc = sock_dereference(pmc->next, sk))
123 for (pmc = rcu_dereference((np)->ipv6_mc_list); \
125 pmc = rcu_dereference(pmc->next))
128 for (psf = mc_dereference((mc)->mca_sources, mc->idev); \
130 psf = mc_dereference(psf->sf_next, mc->idev))
133 for (psf = rcu_dereference((mc)->mca_sources); \
135 psf = rcu_dereference(psf->sf_next))
138 for (psf = mc_dereference((mc)->mca_tomb, mc->idev); \
140 psf = mc_dereference(psf->sf_next, mc->idev))
143 for (mc = mc_dereference((idev)->mc_list, idev); \
145 mc = mc_dereference(mc->next, idev))
148 for (mc = rcu_dereference((idev)->mc_list); \
150 mc = rcu_dereference(mc->next))
153 for (mc = mc_dereference((idev)->mc_tomb, idev); \
155 mc = mc_dereference(mc->next, idev))
162 iv = idev->cnf.mldv1_unsolicited_report_interval; in unsolicited_report_interval()
164 iv = idev->cnf.mldv2_unsolicited_report_interval; in unsolicited_report_interval()
181 return -EINVAL; in __ipv6_sock_mc_join()
184 if ((ifindex == 0 || mc_lst->ifindex == ifindex) && in __ipv6_sock_mc_join()
185 ipv6_addr_equal(&mc_lst->addr, addr)) in __ipv6_sock_mc_join()
186 return -EADDRINUSE; in __ipv6_sock_mc_join()
192 return -ENOMEM; in __ipv6_sock_mc_join()
194 mc_lst->next = NULL; in __ipv6_sock_mc_join()
195 mc_lst->addr = *addr; in __ipv6_sock_mc_join()
201 dev = rt->dst.dev; in __ipv6_sock_mc_join()
209 return -ENODEV; in __ipv6_sock_mc_join()
212 mc_lst->ifindex = dev->ifindex; in __ipv6_sock_mc_join()
213 mc_lst->sfmode = mode; in __ipv6_sock_mc_join()
214 RCU_INIT_POINTER(mc_lst->sflist, NULL); in __ipv6_sock_mc_join()
227 mc_lst->next = np->ipv6_mc_list; in __ipv6_sock_mc_join()
228 rcu_assign_pointer(np->ipv6_mc_list, mc_lst); in __ipv6_sock_mc_join()
258 return -EINVAL; in ipv6_sock_mc_drop()
260 for (lnk = &np->ipv6_mc_list; in ipv6_sock_mc_drop()
262 lnk = &mc_lst->next) { in ipv6_sock_mc_drop()
263 if ((ifindex == 0 || mc_lst->ifindex == ifindex) && in ipv6_sock_mc_drop()
264 ipv6_addr_equal(&mc_lst->addr, addr)) { in ipv6_sock_mc_drop()
267 *lnk = mc_lst->next; in ipv6_sock_mc_drop()
269 dev = __dev_get_by_index(net, mc_lst->ifindex); in ipv6_sock_mc_drop()
275 __ipv6_dev_mc_dec(idev, &mc_lst->addr); in ipv6_sock_mc_drop()
280 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); in ipv6_sock_mc_drop()
286 return -EADDRNOTAVAIL; in ipv6_sock_mc_drop()
301 dev = rt->dst.dev; in ip6_mc_find_dev_rtnl()
313 if (idev->dead) in ip6_mc_find_dev_rtnl()
326 while ((mc_lst = sock_dereference(np->ipv6_mc_list, sk)) != NULL) { in __ipv6_sock_mc_close()
329 np->ipv6_mc_list = mc_lst->next; in __ipv6_sock_mc_close()
331 dev = __dev_get_by_index(net, mc_lst->ifindex); in __ipv6_sock_mc_close()
337 __ipv6_dev_mc_dec(idev, &mc_lst->addr); in __ipv6_sock_mc_close()
342 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); in __ipv6_sock_mc_close()
351 if (!rcu_access_pointer(np->ipv6_mc_list)) in ipv6_sock_mc_close()
374 source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr; in ip6_mc_source()
375 group = &((struct sockaddr_in6 *)&pgsr->gsr_group)->sin6_addr; in ip6_mc_source()
378 return -EINVAL; in ip6_mc_source()
380 idev = ip6_mc_find_dev_rtnl(net, group, pgsr->gsr_interface); in ip6_mc_source()
382 return -ENODEV; in ip6_mc_source()
384 err = -EADDRNOTAVAIL; in ip6_mc_source()
386 mutex_lock(&idev->mc_lock); in ip6_mc_source()
388 if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) in ip6_mc_source()
390 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_source()
394 err = -EINVAL; in ip6_mc_source()
398 if (rcu_access_pointer(pmc->sflist)) { in ip6_mc_source()
399 if (pmc->sfmode != omode) { in ip6_mc_source()
400 err = -EINVAL; in ip6_mc_source()
403 } else if (pmc->sfmode != omode) { in ip6_mc_source()
404 /* allow mode switches for empty-set filters */ in ip6_mc_source()
406 ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_source()
407 pmc->sfmode = omode; in ip6_mc_source()
410 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_source()
413 goto done; /* err = -EADDRNOTAVAIL */ in ip6_mc_source()
415 for (i = 0; i < psl->sl_count; i++) { in ip6_mc_source()
416 rv = !ipv6_addr_equal(&psl->sl_addr[i], source); in ip6_mc_source()
421 goto done; /* err = -EADDRNOTAVAIL */ in ip6_mc_source()
423 /* special case - (INCLUDE, empty) == LEAVE_GROUP */ in ip6_mc_source()
424 if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { in ip6_mc_source()
432 for (j = i+1; j < psl->sl_count; j++) in ip6_mc_source()
433 psl->sl_addr[j-1] = psl->sl_addr[j]; in ip6_mc_source()
434 psl->sl_count--; in ip6_mc_source()
440 if (psl && psl->sl_count >= sysctl_mld_max_msf) { in ip6_mc_source()
441 err = -ENOBUFS; in ip6_mc_source()
444 if (!psl || psl->sl_count == psl->sl_max) { in ip6_mc_source()
449 count += psl->sl_max; in ip6_mc_source()
453 err = -ENOBUFS; in ip6_mc_source()
456 newpsl->sl_max = count; in ip6_mc_source()
457 newpsl->sl_count = count - IP6_SFBLOCK; in ip6_mc_source()
459 for (i = 0; i < psl->sl_count; i++) in ip6_mc_source()
460 newpsl->sl_addr[i] = psl->sl_addr[i]; in ip6_mc_source()
461 atomic_sub(struct_size(psl, sl_addr, psl->sl_max), in ip6_mc_source()
462 &sk->sk_omem_alloc); in ip6_mc_source()
464 rcu_assign_pointer(pmc->sflist, newpsl); in ip6_mc_source()
469 for (i = 0; i < psl->sl_count; i++) { in ip6_mc_source()
470 rv = !ipv6_addr_equal(&psl->sl_addr[i], source); in ip6_mc_source()
474 for (j = psl->sl_count-1; j >= i; j--) in ip6_mc_source()
475 psl->sl_addr[j+1] = psl->sl_addr[j]; in ip6_mc_source()
476 psl->sl_addr[i] = *source; in ip6_mc_source()
477 psl->sl_count++; in ip6_mc_source()
482 mutex_unlock(&idev->mc_lock); in ip6_mc_source()
484 err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); in ip6_mc_source()
500 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; in ip6_mc_msfilter()
503 return -EINVAL; in ip6_mc_msfilter()
504 if (gsf->gf_fmode != MCAST_INCLUDE && in ip6_mc_msfilter()
505 gsf->gf_fmode != MCAST_EXCLUDE) in ip6_mc_msfilter()
506 return -EINVAL; in ip6_mc_msfilter()
508 idev = ip6_mc_find_dev_rtnl(net, group, gsf->gf_interface); in ip6_mc_msfilter()
510 return -ENODEV; in ip6_mc_msfilter()
514 if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { in ip6_mc_msfilter()
520 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfilter()
522 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_msfilter()
526 err = -EINVAL; in ip6_mc_msfilter()
529 if (gsf->gf_numsrc) { in ip6_mc_msfilter()
531 gsf->gf_numsrc), in ip6_mc_msfilter()
534 err = -ENOBUFS; in ip6_mc_msfilter()
537 newpsl->sl_max = newpsl->sl_count = gsf->gf_numsrc; in ip6_mc_msfilter()
538 for (i = 0; i < newpsl->sl_count; ++i, ++list) { in ip6_mc_msfilter()
542 newpsl->sl_addr[i] = psin6->sin6_addr; in ip6_mc_msfilter()
544 mutex_lock(&idev->mc_lock); in ip6_mc_msfilter()
545 err = ip6_mc_add_src(idev, group, gsf->gf_fmode, in ip6_mc_msfilter()
546 newpsl->sl_count, newpsl->sl_addr, 0); in ip6_mc_msfilter()
548 mutex_unlock(&idev->mc_lock); in ip6_mc_msfilter()
550 newpsl->sl_max)); in ip6_mc_msfilter()
553 mutex_unlock(&idev->mc_lock); in ip6_mc_msfilter()
556 mutex_lock(&idev->mc_lock); in ip6_mc_msfilter()
557 ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); in ip6_mc_msfilter()
558 mutex_unlock(&idev->mc_lock); in ip6_mc_msfilter()
561 mutex_lock(&idev->mc_lock); in ip6_mc_msfilter()
562 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_msfilter()
564 ip6_mc_del_src(idev, group, pmc->sfmode, in ip6_mc_msfilter()
565 psl->sl_count, psl->sl_addr, 0); in ip6_mc_msfilter()
566 atomic_sub(struct_size(psl, sl_addr, psl->sl_max), in ip6_mc_msfilter()
567 &sk->sk_omem_alloc); in ip6_mc_msfilter()
569 ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_msfilter()
571 rcu_assign_pointer(pmc->sflist, newpsl); in ip6_mc_msfilter()
572 mutex_unlock(&idev->mc_lock); in ip6_mc_msfilter()
574 pmc->sfmode = gsf->gf_fmode; in ip6_mc_msfilter()
578 err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); in ip6_mc_msfilter()
591 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; in ip6_mc_msfget()
594 return -EINVAL; in ip6_mc_msfget()
601 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfget()
603 if (ipv6_addr_equal(group, &pmc->addr)) in ip6_mc_msfget()
607 return -EADDRNOTAVAIL; in ip6_mc_msfget()
609 gsf->gf_fmode = pmc->sfmode; in ip6_mc_msfget()
610 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_msfget()
611 count = psl ? psl->sl_count : 0; in ip6_mc_msfget()
613 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; in ip6_mc_msfget()
614 gsf->gf_numsrc = count; in ip6_mc_msfget()
621 psin6->sin6_family = AF_INET6; in ip6_mc_msfget()
622 psin6->sin6_addr = psl->sl_addr[i]; in ip6_mc_msfget()
624 return -EFAULT; in ip6_mc_msfget()
640 if (ipv6_addr_equal(&mc->addr, mc_addr)) in inet6_mc_check()
645 return np->mc_all; in inet6_mc_check()
647 psl = rcu_dereference(mc->sflist); in inet6_mc_check()
649 rv = mc->sfmode == MCAST_EXCLUDE; in inet6_mc_check()
653 for (i = 0; i < psl->sl_count; i++) { in inet6_mc_check()
654 if (ipv6_addr_equal(&psl->sl_addr[i], src_addr)) in inet6_mc_check()
657 if (mc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) in inet6_mc_check()
659 if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) in inet6_mc_check()
670 struct net_device *dev = mc->idev->dev; in igmp6_group_added()
673 if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < in igmp6_group_added()
677 if (!(mc->mca_flags&MAF_LOADED)) { in igmp6_group_added()
678 mc->mca_flags |= MAF_LOADED; in igmp6_group_added()
679 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) in igmp6_group_added()
683 if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT)) in igmp6_group_added()
686 if (mld_in_v1_mode(mc->idev)) { in igmp6_group_added()
693 * should not send filter-mode change record as the mode in igmp6_group_added()
696 if (mc->mca_sfmode == MCAST_EXCLUDE) in igmp6_group_added()
697 mc->mca_crcount = mc->idev->mc_qrv; in igmp6_group_added()
699 mld_ifc_event(mc->idev); in igmp6_group_added()
705 struct net_device *dev = mc->idev->dev; in igmp6_group_dropped()
708 if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < in igmp6_group_dropped()
712 if (mc->mca_flags&MAF_LOADED) { in igmp6_group_dropped()
713 mc->mca_flags &= ~MAF_LOADED; in igmp6_group_dropped()
714 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) in igmp6_group_dropped()
718 if (mc->mca_flags & MAF_NOREPORT) in igmp6_group_dropped()
721 if (!mc->idev->dead) in igmp6_group_dropped()
724 if (cancel_delayed_work(&mc->mca_work)) in igmp6_group_dropped()
725 refcount_dec(&mc->mca_refcnt); in igmp6_group_dropped()
732 static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) in mld_add_delrec() argument
740 * non-deleted or query-response MCA's. in mld_add_delrec()
746 pmc->idev = im->idev; in mld_add_delrec()
748 pmc->mca_addr = im->mca_addr; in mld_add_delrec()
749 pmc->mca_crcount = idev->mc_qrv; in mld_add_delrec()
750 pmc->mca_sfmode = im->mca_sfmode; in mld_add_delrec()
751 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_add_delrec()
754 rcu_assign_pointer(pmc->mca_tomb, in mld_add_delrec()
755 mc_dereference(im->mca_tomb, idev)); in mld_add_delrec()
756 rcu_assign_pointer(pmc->mca_sources, in mld_add_delrec()
757 mc_dereference(im->mca_sources, idev)); in mld_add_delrec()
758 RCU_INIT_POINTER(im->mca_tomb, NULL); in mld_add_delrec()
759 RCU_INIT_POINTER(im->mca_sources, NULL); in mld_add_delrec()
762 psf->sf_crcount = pmc->mca_crcount; in mld_add_delrec()
765 rcu_assign_pointer(pmc->next, idev->mc_tomb); in mld_add_delrec()
766 rcu_assign_pointer(idev->mc_tomb, pmc); in mld_add_delrec()
770 static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) in mld_del_delrec() argument
773 struct in6_addr *pmca = &im->mca_addr; in mld_del_delrec()
778 if (ipv6_addr_equal(&pmc->mca_addr, pmca)) in mld_del_delrec()
784 rcu_assign_pointer(pmc_prev->next, pmc->next); in mld_del_delrec()
786 rcu_assign_pointer(idev->mc_tomb, pmc->next); in mld_del_delrec()
790 im->idev = pmc->idev; in mld_del_delrec()
791 if (im->mca_sfmode == MCAST_INCLUDE) { in mld_del_delrec()
792 tomb = rcu_replace_pointer(im->mca_tomb, in mld_del_delrec()
793 mc_dereference(pmc->mca_tomb, pmc->idev), in mld_del_delrec()
794 lockdep_is_held(&im->idev->mc_lock)); in mld_del_delrec()
795 rcu_assign_pointer(pmc->mca_tomb, tomb); in mld_del_delrec()
797 sources = rcu_replace_pointer(im->mca_sources, in mld_del_delrec()
798 mc_dereference(pmc->mca_sources, pmc->idev), in mld_del_delrec()
799 lockdep_is_held(&im->idev->mc_lock)); in mld_del_delrec()
800 rcu_assign_pointer(pmc->mca_sources, sources); in mld_del_delrec()
801 for_each_psf_mclock(im, psf) in mld_del_delrec()
802 psf->sf_crcount = idev->mc_qrv; in mld_del_delrec()
804 im->mca_crcount = idev->mc_qrv; in mld_del_delrec()
806 in6_dev_put(pmc->idev); in mld_del_delrec()
817 pmc = mc_dereference(idev->mc_tomb, idev); in mld_clear_delrec()
818 RCU_INIT_POINTER(idev->mc_tomb, NULL); in mld_clear_delrec()
821 nextpmc = mc_dereference(pmc->next, idev); in mld_clear_delrec()
823 in6_dev_put(pmc->idev); in mld_clear_delrec()
831 psf = mc_dereference(pmc->mca_tomb, idev); in mld_clear_delrec()
832 RCU_INIT_POINTER(pmc->mca_tomb, NULL); in mld_clear_delrec()
834 psf_next = mc_dereference(psf->sf_next, idev); in mld_clear_delrec()
844 spin_lock_bh(&idev->mc_query_lock); in mld_clear_query()
845 while ((skb = __skb_dequeue(&idev->mc_query_queue))) in mld_clear_query()
847 spin_unlock_bh(&idev->mc_query_lock); in mld_clear_query()
854 spin_lock_bh(&idev->mc_report_lock); in mld_clear_report()
855 while ((skb = __skb_dequeue(&idev->mc_report_queue))) in mld_clear_report()
857 spin_unlock_bh(&idev->mc_report_lock); in mld_clear_report()
862 refcount_inc(&mc->mca_refcnt); in mca_get()
867 if (refcount_dec_and_test(&mc->mca_refcnt)) { in ma_put()
868 in6_dev_put(mc->idev); in ma_put()
884 INIT_DELAYED_WORK(&mc->mca_work, mld_mca_work); in mca_alloc()
886 mc->mca_addr = *addr; in mca_alloc()
887 mc->idev = idev; /* reference taken by caller */ in mca_alloc()
888 mc->mca_users = 1; in mca_alloc()
890 mc->mca_cstamp = mc->mca_tstamp = jiffies; in mca_alloc()
891 refcount_set(&mc->mca_refcnt, 1); in mca_alloc()
893 mc->mca_sfmode = mode; in mca_alloc()
894 mc->mca_sfcount[mode] = 1; in mca_alloc()
896 if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) || in mca_alloc()
897 IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) in mca_alloc()
898 mc->mca_flags |= MAF_NOREPORT; in mca_alloc()
918 return -EINVAL; in __ipv6_dev_mc_inc()
920 if (idev->dead) { in __ipv6_dev_mc_inc()
922 return -ENODEV; in __ipv6_dev_mc_inc()
925 mutex_lock(&idev->mc_lock); in __ipv6_dev_mc_inc()
927 if (ipv6_addr_equal(&mc->mca_addr, addr)) { in __ipv6_dev_mc_inc()
928 mc->mca_users++; in __ipv6_dev_mc_inc()
929 ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0); in __ipv6_dev_mc_inc()
930 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_inc()
938 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_inc()
940 return -ENOMEM; in __ipv6_dev_mc_inc()
943 rcu_assign_pointer(mc->next, idev->mc_list); in __ipv6_dev_mc_inc()
944 rcu_assign_pointer(idev->mc_list, mc); in __ipv6_dev_mc_inc()
950 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_inc()
970 mutex_lock(&idev->mc_lock); in __ipv6_dev_mc_dec()
971 for (map = &idev->mc_list; in __ipv6_dev_mc_dec()
973 map = &ma->next) { in __ipv6_dev_mc_dec()
974 if (ipv6_addr_equal(&ma->mca_addr, addr)) { in __ipv6_dev_mc_dec()
975 if (--ma->mca_users == 0) { in __ipv6_dev_mc_dec()
976 *map = ma->next; in __ipv6_dev_mc_dec()
980 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_dec()
985 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_dec()
990 mutex_unlock(&idev->mc_lock); in __ipv6_dev_mc_dec()
991 return -ENOENT; in __ipv6_dev_mc_dec()
1003 err = -ENODEV; in ipv6_dev_mc_dec()
1025 if (ipv6_addr_equal(&mc->mca_addr, group)) in ipv6_chk_mcast_addr()
1033 if (ipv6_addr_equal(&psf->sf_addr, src_addr)) in ipv6_chk_mcast_addr()
1037 rv = psf->sf_count[MCAST_INCLUDE] || in ipv6_chk_mcast_addr()
1038 psf->sf_count[MCAST_EXCLUDE] != in ipv6_chk_mcast_addr()
1039 mc->mca_sfcount[MCAST_EXCLUDE]; in ipv6_chk_mcast_addr()
1041 rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0; in ipv6_chk_mcast_addr()
1053 unsigned long tv = prandom_u32_max(idev->mc_maxdelay); in mld_gq_start_work()
1055 idev->mc_gq_running = 1; in mld_gq_start_work()
1056 if (!mod_delayed_work(mld_wq, &idev->mc_gq_work, tv + 2)) in mld_gq_start_work()
1063 idev->mc_gq_running = 0; in mld_gq_stop_work()
1064 if (cancel_delayed_work(&idev->mc_gq_work)) in mld_gq_stop_work()
1073 if (!mod_delayed_work(mld_wq, &idev->mc_ifc_work, tv + 2)) in mld_ifc_start_work()
1080 idev->mc_ifc_count = 0; in mld_ifc_stop_work()
1081 if (cancel_delayed_work(&idev->mc_ifc_work)) in mld_ifc_stop_work()
1090 if (!mod_delayed_work(mld_wq, &idev->mc_dad_work, tv + 2)) in mld_dad_start_work()
1096 if (cancel_delayed_work(&idev->mc_dad_work)) in mld_dad_stop_work()
1102 spin_lock_bh(&idev->mc_query_lock); in mld_query_stop_work()
1103 if (cancel_delayed_work(&idev->mc_query_work)) in mld_query_stop_work()
1105 spin_unlock_bh(&idev->mc_query_lock); in mld_query_stop_work()
1110 if (cancel_delayed_work_sync(&idev->mc_report_work)) in mld_report_stop_work()
1123 if (ipv6_addr_is_ll_all_nodes(&ma->mca_addr) || in igmp6_group_queried()
1124 IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) in igmp6_group_queried()
1127 if (cancel_delayed_work(&ma->mca_work)) { in igmp6_group_queried()
1128 refcount_dec(&ma->mca_refcnt); in igmp6_group_queried()
1129 delay = ma->mca_work.timer.expires - jiffies; in igmp6_group_queried()
1135 if (!mod_delayed_work(mld_wq, &ma->mca_work, delay)) in igmp6_group_queried()
1136 refcount_inc(&ma->mca_refcnt); in igmp6_group_queried()
1137 ma->mca_flags |= MAF_TIMER_RUNNING; in igmp6_group_queried()
1140 /* mark EXCLUDE-mode sources
1155 if (psf->sf_count[MCAST_INCLUDE] || in mld_xmarksources()
1156 pmc->mca_sfcount[MCAST_EXCLUDE] != in mld_xmarksources()
1157 psf->sf_count[MCAST_EXCLUDE]) in mld_xmarksources()
1159 if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { in mld_xmarksources()
1165 pmc->mca_flags &= ~MAF_GSQUERY; in mld_xmarksources()
1178 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_marksources()
1181 /* mark INCLUDE-mode sources */ in mld_marksources()
1188 if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { in mld_marksources()
1189 psf->sf_gsresp = 1; in mld_marksources()
1196 pmc->mca_flags &= ~MAF_GSQUERY; in mld_marksources()
1199 pmc->mca_flags |= MAF_GSQUERY; in mld_marksources()
1210 if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0) in mld_force_mld_version()
1211 return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version; in mld_force_mld_version()
1213 return idev->cnf.force_mld_version; in mld_force_mld_version()
1232 if (idev->mc_v1_seen && time_before(jiffies, idev->mc_v1_seen)) in mld_in_v1_mode()
1241 * - 9.1. Robustness Variable in mld_set_v1_mode()
1242 * - 9.2. Query Interval in mld_set_v1_mode()
1243 * - 9.3. Query Response Interval in mld_set_v1_mode()
1244 * - 9.12. Older Version Querier Present Timeout in mld_set_v1_mode()
1248 switchback = (idev->mc_qrv * idev->mc_qi) + idev->mc_qri; in mld_set_v1_mode()
1250 idev->mc_v1_seen = jiffies + switchback; in mld_set_v1_mode()
1257 * - 5.1.8. QRV (Querier's Robustness Variable) in mld_update_qrv()
1258 * - 9.1. Robustness Variable in mld_update_qrv()
1266 WARN_ON(idev->mc_qrv == 0); in mld_update_qrv()
1268 if (mlh2->mld2q_qrv > 0) in mld_update_qrv()
1269 idev->mc_qrv = mlh2->mld2q_qrv; in mld_update_qrv()
1271 if (unlikely(idev->mc_qrv < min_qrv)) { in mld_update_qrv()
1273 idev->mc_qrv, min_qrv); in mld_update_qrv()
1274 idev->mc_qrv = min_qrv; in mld_update_qrv()
1282 * - 5.1.9. QQIC (Querier's Query Interval Code) in mld_update_qi()
1283 * - 9.2. Query Interval in mld_update_qi()
1284 * - 9.12. Older Version Querier Present Timeout in mld_update_qi()
1289 if (mlh2->mld2q_qqic < 128) { in mld_update_qi()
1290 mc_qqi = mlh2->mld2q_qqic; in mld_update_qi()
1294 mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic); in mld_update_qi()
1295 mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic); in mld_update_qi()
1300 idev->mc_qi = mc_qqi * HZ; in mld_update_qi()
1307 * - 5.1.3. Maximum Response Code in mld_update_qri()
1308 * - 9.3. Query Response Interval in mld_update_qri()
1310 idev->mc_qri = msecs_to_jiffies(mldv2_mrc(mlh2)); in mld_update_qri()
1320 return -EINVAL; in mld_process_v1()
1322 mldv1_md = ntohs(mld->mld_maxdelay); in mld_process_v1()
1324 /* When in MLDv1 fallback and a MLDv2 router start-up being in mld_process_v1()
1368 idev->mc_maxdelay = *max_delay; in mld_process_v2()
1376 struct inet6_dev *idev = __in6_dev_get(skb->dev); in igmp6_event_query()
1378 if (!idev || idev->dead) in igmp6_event_query()
1381 spin_lock_bh(&idev->mc_query_lock); in igmp6_event_query()
1382 if (skb_queue_len(&idev->mc_query_queue) < MLD_MAX_SKBS) { in igmp6_event_query()
1383 __skb_queue_tail(&idev->mc_query_queue, skb); in igmp6_event_query()
1384 if (!mod_delayed_work(mld_wq, &idev->mc_query_work, 0)) in igmp6_event_query()
1388 spin_unlock_bh(&idev->mc_query_lock); in igmp6_event_query()
1409 len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr); in __mld_query_work()
1410 len -= skb_network_header_len(skb); in __mld_query_work()
1414 * checks if the source address of the message is a valid link-local in __mld_query_work()
1416 * option is present in the Hop-By-Hop Options header of the IPv6 in __mld_query_work()
1419 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) || in __mld_query_work()
1420 ipv6_hdr(skb)->hop_limit != 1 || in __mld_query_work()
1421 !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) || in __mld_query_work()
1422 IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD)) in __mld_query_work()
1425 idev = in6_dev_get(skb->dev); in __mld_query_work()
1430 group = &mld->mld_mca; in __mld_query_work()
1445 int srcs_offset = sizeof(struct mld2_query) - in __mld_query_work()
1456 if (mlh2->mld2q_nsrcs) in __mld_query_work()
1462 /* mark sources to include, if group & source-specific */ in __mld_query_work()
1463 if (mlh2->mld2q_nsrcs != 0) { in __mld_query_work()
1465 ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) in __mld_query_work()
1481 if (!ipv6_addr_equal(group, &ma->mca_addr)) in __mld_query_work()
1483 if (ma->mca_flags & MAF_TIMER_RUNNING) { in __mld_query_work()
1484 /* gsquery <- gsquery && mark */ in __mld_query_work()
1486 ma->mca_flags &= ~MAF_GSQUERY; in __mld_query_work()
1488 /* gsquery <- mark */ in __mld_query_work()
1490 ma->mca_flags |= MAF_GSQUERY; in __mld_query_work()
1492 ma->mca_flags &= ~MAF_GSQUERY; in __mld_query_work()
1494 if (!(ma->mca_flags & MAF_GSQUERY) || in __mld_query_work()
1495 mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) in __mld_query_work()
1519 spin_lock_bh(&idev->mc_query_lock); in mld_query_work()
1520 while ((skb = __skb_dequeue(&idev->mc_query_queue))) { in mld_query_work()
1528 spin_unlock_bh(&idev->mc_query_lock); in mld_query_work()
1530 mutex_lock(&idev->mc_lock); in mld_query_work()
1533 mutex_unlock(&idev->mc_lock); in mld_query_work()
1535 if (rework && queue_delayed_work(mld_wq, &idev->mc_query_work, 0)) in mld_query_work()
1544 struct inet6_dev *idev = __in6_dev_get(skb->dev); in igmp6_event_report()
1546 if (!idev || idev->dead) in igmp6_event_report()
1549 spin_lock_bh(&idev->mc_report_lock); in igmp6_event_report()
1550 if (skb_queue_len(&idev->mc_report_queue) < MLD_MAX_SKBS) { in igmp6_event_report()
1551 __skb_queue_tail(&idev->mc_report_queue, skb); in igmp6_event_report()
1552 if (!mod_delayed_work(mld_wq, &idev->mc_report_work, 0)) in igmp6_event_report()
1556 spin_unlock_bh(&idev->mc_report_lock); in igmp6_event_report()
1569 if (skb->pkt_type == PACKET_LOOPBACK) in __mld_report_work()
1573 if (skb->pkt_type != PACKET_MULTICAST && in __mld_report_work()
1574 skb->pkt_type != PACKET_BROADCAST) in __mld_report_work()
1577 if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) in __mld_report_work()
1583 addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); in __mld_report_work()
1588 idev = in6_dev_get(skb->dev); in __mld_report_work()
1597 if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { in __mld_report_work()
1598 if (cancel_delayed_work(&ma->mca_work)) in __mld_report_work()
1599 refcount_dec(&ma->mca_refcnt); in __mld_report_work()
1600 ma->mca_flags &= ~(MAF_LAST_REPORTER | in __mld_report_work()
1622 spin_lock_bh(&idev->mc_report_lock); in mld_report_work()
1623 while ((skb = __skb_dequeue(&idev->mc_report_queue))) { in mld_report_work()
1631 spin_unlock_bh(&idev->mc_report_lock); in mld_report_work()
1633 mutex_lock(&idev->mc_lock); in mld_report_work()
1636 mutex_unlock(&idev->mc_lock); in mld_report_work()
1638 if (rework && queue_delayed_work(mld_wq, &idev->mc_report_work, 0)) in mld_report_work()
1652 if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) { in is_in()
1653 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1658 if (psf->sf_count[MCAST_INCLUDE]) in is_in()
1660 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1661 psf->sf_count[MCAST_EXCLUDE]; in is_in()
1667 return psf->sf_count[MCAST_INCLUDE] != 0; in is_in()
1671 if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 || in is_in()
1672 psf->sf_count[MCAST_INCLUDE]) in is_in()
1674 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1675 psf->sf_count[MCAST_EXCLUDE]; in is_in()
1677 if (gdeleted || !psf->sf_crcount) in is_in()
1679 return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted; in is_in()
1681 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1682 return gdeleted || (psf->sf_crcount && sdeleted); in is_in()
1683 return psf->sf_crcount && !gdeleted && !sdeleted; in is_in()
1710 skb->protocol = htons(ETH_P_IPV6); in ip6_mc_hdr()
1711 skb->dev = dev; in ip6_mc_hdr()
1719 hdr->payload_len = htons(len); in ip6_mc_hdr()
1720 hdr->nexthdr = proto; in ip6_mc_hdr()
1721 hdr->hop_limit = inet6_sk(sk)->hop_limit; in ip6_mc_hdr()
1723 hdr->saddr = *saddr; in ip6_mc_hdr()
1724 hdr->daddr = *daddr; in ip6_mc_hdr()
1731 struct net_device *dev = idev->dev; in mld_newpack()
1733 int tlen = dev->needed_tailroom; in mld_newpack()
1743 sk = net->ipv6.igmp_sk; in mld_newpack()
1745 * Also try to not allocate high-order pages for big MTU in mld_newpack()
1752 skb->priority = TC_PRIO_CONTROL; in mld_newpack()
1757 /* <draft-ietf-magma-mld-source-05.txt>: in mld_newpack()
1759 * when a valid link-local address is not available. in mld_newpack()
1769 skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); in mld_newpack()
1772 pmr->mld2r_type = ICMPV6_MLD2_REPORT; in mld_newpack()
1773 pmr->mld2r_resv1 = 0; in mld_newpack()
1774 pmr->mld2r_cksum = 0; in mld_newpack()
1775 pmr->mld2r_resv2 = 0; in mld_newpack()
1776 pmr->mld2r_ngrec = 0; in mld_newpack()
1787 struct net *net = dev_net(skb->dev); in mld_sendpack()
1793 idev = __in6_dev_get(skb->dev); in mld_sendpack()
1794 IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); in mld_sendpack()
1796 payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) - in mld_sendpack()
1798 mldlen = skb_tail_pointer(skb) - skb_transport_header(skb); in mld_sendpack()
1799 pip6->payload_len = htons(payload_len); in mld_sendpack()
1801 pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, in mld_sendpack()
1806 icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, in mld_sendpack()
1807 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, in mld_sendpack()
1808 skb->dev->ifindex); in mld_sendpack()
1809 dst = icmp6_dst_alloc(skb->dev, &fl6); in mld_sendpack()
1821 net, net->ipv6.igmp_sk, skb, NULL, skb->dev, in mld_sendpack()
1851 skb = mld_newpack(pmc->idev, mtu); in add_grhead()
1856 pgr->grec_type = type; in add_grhead()
1857 pgr->grec_auxwords = 0; in add_grhead()
1858 pgr->grec_nsrcs = 0; in add_grhead()
1859 pgr->grec_mca = pmc->mca_addr; /* structure copy */ in add_grhead()
1861 pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); in add_grhead()
1876 struct inet6_dev *idev = pmc->idev; in add_grec()
1877 struct net_device *dev = idev->dev; in add_grec()
1882 if (pmc->mca_flags & MAF_NOREPORT) in add_grec()
1885 mtu = READ_ONCE(dev->mtu); in add_grec()
1896 psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources; in add_grec()
1905 if (pmr && pmr->mld2r_ngrec && in add_grec()
1919 psf_next = mc_dereference(psf->sf_next, idev); in add_grec()
1926 /* Based on RFC3810 6.1. Should not send source-list change in add_grec()
1929 if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) || in add_grec()
1930 (!gdeleted && pmc->mca_crcount)) && in add_grec()
1932 type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) in add_grec()
1937 psf->sf_gsresp = 0; in add_grec()
1944 pgr->grec_nsrcs = htons(scount); in add_grec()
1958 *psrc = psf->sf_addr; in add_grec()
1961 type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) { in add_grec()
1963 psf->sf_crcount--; in add_grec()
1964 if ((sdeleted || gdeleted) && psf->sf_crcount == 0) { in add_grec()
1966 rcu_assign_pointer(psf_prev->sf_next, in add_grec()
1967 mc_dereference(psf->sf_next, idev)); in add_grec()
1970 mc_dereference(psf->sf_next, idev)); in add_grec()
1983 if (pmc->mca_crcount || isquery || crsend) { in add_grec()
1993 pgr->grec_nsrcs = htons(scount); in add_grec()
1996 pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */ in add_grec()
2008 if (pmc->mca_flags & MAF_NOREPORT) in mld_send_report()
2010 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
2017 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
2028 * remove zero-count source records from a source filter list
2039 psf_next = mc_dereference(psf->sf_next, idev); in mld_clear_zeros()
2040 if (psf->sf_crcount == 0) { in mld_clear_zeros()
2042 rcu_assign_pointer(psf_prev->sf_next, in mld_clear_zeros()
2043 mc_dereference(psf->sf_next, idev)); in mld_clear_zeros()
2046 mc_dereference(psf->sf_next, idev)); in mld_clear_zeros()
2063 for (pmc = mc_dereference(idev->mc_tomb, idev); in mld_send_cr()
2066 pmc_next = mc_dereference(pmc->next, idev); in mld_send_cr()
2067 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_send_cr()
2073 if (pmc->mca_crcount) { in mld_send_cr()
2074 if (pmc->mca_sfmode == MCAST_EXCLUDE) { in mld_send_cr()
2078 pmc->mca_crcount--; in mld_send_cr()
2079 if (pmc->mca_crcount == 0) { in mld_send_cr()
2080 mld_clear_zeros(&pmc->mca_tomb, idev); in mld_send_cr()
2081 mld_clear_zeros(&pmc->mca_sources, idev); in mld_send_cr()
2084 if (pmc->mca_crcount == 0 && in mld_send_cr()
2085 !rcu_access_pointer(pmc->mca_tomb) && in mld_send_cr()
2086 !rcu_access_pointer(pmc->mca_sources)) { in mld_send_cr()
2088 rcu_assign_pointer(pmc_prev->next, pmc_next); in mld_send_cr()
2090 rcu_assign_pointer(idev->mc_tomb, pmc_next); in mld_send_cr()
2091 in6_dev_put(pmc->idev); in mld_send_cr()
2099 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in mld_send_cr()
2110 if (pmc->mca_crcount) { in mld_send_cr()
2111 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_send_cr()
2116 pmc->mca_crcount--; in mld_send_cr()
2127 struct sock *sk = net->ipv6.igmp_sk; in igmp6_send()
2134 int tlen = dev->needed_tailroom; in igmp6_send()
2165 skb->priority = TC_PRIO_CONTROL; in igmp6_send()
2169 /* <draft-ietf-magma-mld-source-05.txt>: in igmp6_send()
2171 * when a valid link-local address is not available. in igmp6_send()
2182 hdr->mld_type = type; in igmp6_send()
2183 hdr->mld_mca = *addr; in igmp6_send()
2185 hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, in igmp6_send()
2190 idev = __in6_dev_get(skb->dev); in igmp6_send()
2193 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, in igmp6_send()
2194 skb->dev->ifindex); in igmp6_send()
2195 dst = icmp6_dst_alloc(skb->dev, &fl6); in igmp6_send()
2203 net, sk, skb, NULL, skb->dev, in igmp6_send()
2232 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_initial_cr()
2244 mutex_lock(&idev->mc_lock); in ipv6_mc_dad_complete()
2245 idev->mc_dad_count = idev->mc_qrv; in ipv6_mc_dad_complete()
2246 if (idev->mc_dad_count) { in ipv6_mc_dad_complete()
2248 idev->mc_dad_count--; in ipv6_mc_dad_complete()
2249 if (idev->mc_dad_count) in ipv6_mc_dad_complete()
2253 mutex_unlock(&idev->mc_lock); in ipv6_mc_dad_complete()
2261 mutex_lock(&idev->mc_lock); in mld_dad_work()
2263 if (idev->mc_dad_count) { in mld_dad_work()
2264 idev->mc_dad_count--; in mld_dad_work()
2265 if (idev->mc_dad_count) in mld_dad_work()
2269 mutex_unlock(&idev->mc_lock); in mld_dad_work()
2282 if (ipv6_addr_equal(&psf->sf_addr, psfsrc)) in ip6_mc_del1_src()
2286 if (!psf || psf->sf_count[sfmode] == 0) { in ip6_mc_del1_src()
2288 return -ESRCH; in ip6_mc_del1_src()
2290 psf->sf_count[sfmode]--; in ip6_mc_del1_src()
2291 if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) { in ip6_mc_del1_src()
2292 struct inet6_dev *idev = pmc->idev; in ip6_mc_del1_src()
2296 rcu_assign_pointer(psf_prev->sf_next, in ip6_mc_del1_src()
2297 mc_dereference(psf->sf_next, idev)); in ip6_mc_del1_src()
2299 rcu_assign_pointer(pmc->mca_sources, in ip6_mc_del1_src()
2300 mc_dereference(psf->sf_next, idev)); in ip6_mc_del1_src()
2302 if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) && in ip6_mc_del1_src()
2304 psf->sf_crcount = idev->mc_qrv; in ip6_mc_del1_src()
2305 rcu_assign_pointer(psf->sf_next, in ip6_mc_del1_src()
2306 mc_dereference(pmc->mca_tomb, idev)); in ip6_mc_del1_src()
2307 rcu_assign_pointer(pmc->mca_tomb, psf); in ip6_mc_del1_src()
2326 return -ENODEV; in ip6_mc_del_src()
2329 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_del_src()
2333 return -ESRCH; in ip6_mc_del_src()
2337 if (!pmc->mca_sfcount[sfmode]) in ip6_mc_del_src()
2338 return -EINVAL; in ip6_mc_del_src()
2340 pmc->mca_sfcount[sfmode]--; in ip6_mc_del_src()
2350 if (pmc->mca_sfmode == MCAST_EXCLUDE && in ip6_mc_del_src()
2351 pmc->mca_sfcount[MCAST_EXCLUDE] == 0 && in ip6_mc_del_src()
2352 pmc->mca_sfcount[MCAST_INCLUDE]) { in ip6_mc_del_src()
2356 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_del_src()
2357 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_del_src()
2358 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_del_src()
2360 psf->sf_crcount = 0; in ip6_mc_del_src()
2361 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2363 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2370 * Add multicast single-source filter to the interface list
2380 if (ipv6_addr_equal(&psf->sf_addr, psfsrc)) in ip6_mc_add1_src()
2387 return -ENOBUFS; in ip6_mc_add1_src()
2389 psf->sf_addr = *psfsrc; in ip6_mc_add1_src()
2391 rcu_assign_pointer(psf_prev->sf_next, psf); in ip6_mc_add1_src()
2393 rcu_assign_pointer(pmc->mca_sources, psf); in ip6_mc_add1_src()
2396 psf->sf_count[sfmode]++; in ip6_mc_add1_src()
2404 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_markstate()
2407 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_markstate()
2408 psf->sf_oldin = mca_xcount == in sf_markstate()
2409 psf->sf_count[MCAST_EXCLUDE] && in sf_markstate()
2410 !psf->sf_count[MCAST_INCLUDE]; in sf_markstate()
2412 psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0; in sf_markstate()
2421 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_setstate()
2422 int qrv = pmc->idev->mc_qrv; in sf_setstate()
2427 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_setstate()
2428 new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] && in sf_setstate()
2429 !psf->sf_count[MCAST_INCLUDE]; in sf_setstate()
2431 new_in = psf->sf_count[MCAST_INCLUDE] != 0; in sf_setstate()
2433 if (!psf->sf_oldin) { in sf_setstate()
2437 if (ipv6_addr_equal(&dpsf->sf_addr, in sf_setstate()
2438 &psf->sf_addr)) in sf_setstate()
2444 rcu_assign_pointer(prev->sf_next, in sf_setstate()
2445 mc_dereference(dpsf->sf_next, in sf_setstate()
2446 pmc->idev)); in sf_setstate()
2448 rcu_assign_pointer(pmc->mca_tomb, in sf_setstate()
2449 mc_dereference(dpsf->sf_next, in sf_setstate()
2450 pmc->idev)); in sf_setstate()
2453 psf->sf_crcount = qrv; in sf_setstate()
2456 } else if (psf->sf_oldin) { in sf_setstate()
2457 psf->sf_crcount = 0; in sf_setstate()
2464 if (ipv6_addr_equal(&dpsf->sf_addr, in sf_setstate()
2465 &psf->sf_addr)) in sf_setstate()
2472 rcu_assign_pointer(dpsf->sf_next, in sf_setstate()
2473 mc_dereference(pmc->mca_tomb, pmc->idev)); in sf_setstate()
2474 rcu_assign_pointer(pmc->mca_tomb, dpsf); in sf_setstate()
2476 dpsf->sf_crcount = qrv; in sf_setstate()
2496 return -ENODEV; in ip6_mc_add_src()
2499 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_add_src()
2503 return -ESRCH; in ip6_mc_add_src()
2506 isexclude = pmc->mca_sfmode == MCAST_EXCLUDE; in ip6_mc_add_src()
2508 pmc->mca_sfcount[sfmode]++; in ip6_mc_add_src()
2519 pmc->mca_sfcount[sfmode]--; in ip6_mc_add_src()
2522 } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { in ip6_mc_add_src()
2526 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in ip6_mc_add_src()
2527 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_add_src()
2528 else if (pmc->mca_sfcount[MCAST_INCLUDE]) in ip6_mc_add_src()
2529 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_add_src()
2532 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_add_src()
2533 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_add_src()
2535 psf->sf_crcount = 0; in ip6_mc_add_src()
2548 for (psf = mc_dereference(pmc->mca_tomb, pmc->idev); in ip6_mc_clear_src()
2551 nextpsf = mc_dereference(psf->sf_next, pmc->idev); in ip6_mc_clear_src()
2554 RCU_INIT_POINTER(pmc->mca_tomb, NULL); in ip6_mc_clear_src()
2555 for (psf = mc_dereference(pmc->mca_sources, pmc->idev); in ip6_mc_clear_src()
2558 nextpsf = mc_dereference(psf->sf_next, pmc->idev); in ip6_mc_clear_src()
2561 RCU_INIT_POINTER(pmc->mca_sources, NULL); in ip6_mc_clear_src()
2562 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_clear_src()
2563 pmc->mca_sfcount[MCAST_INCLUDE] = 0; in ip6_mc_clear_src()
2564 pmc->mca_sfcount[MCAST_EXCLUDE] = 1; in ip6_mc_clear_src()
2572 if (ma->mca_flags & MAF_NOREPORT) in igmp6_join_group()
2575 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); in igmp6_join_group()
2577 delay = prandom_u32_max(unsolicited_report_interval(ma->idev)); in igmp6_join_group()
2579 if (cancel_delayed_work(&ma->mca_work)) { in igmp6_join_group()
2580 refcount_dec(&ma->mca_refcnt); in igmp6_join_group()
2581 delay = ma->mca_work.timer.expires - jiffies; in igmp6_join_group()
2584 if (!mod_delayed_work(mld_wq, &ma->mca_work, delay)) in igmp6_join_group()
2585 refcount_inc(&ma->mca_refcnt); in igmp6_join_group()
2586 ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER; in igmp6_join_group()
2595 psl = sock_dereference(iml->sflist, sk); in ip6_mc_leave_src()
2598 mutex_lock(&idev->mc_lock); in ip6_mc_leave_src()
2601 /* any-source empty exclude case */ in ip6_mc_leave_src()
2602 err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0); in ip6_mc_leave_src()
2604 err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, in ip6_mc_leave_src()
2605 psl->sl_count, psl->sl_addr, 0); in ip6_mc_leave_src()
2606 RCU_INIT_POINTER(iml->sflist, NULL); in ip6_mc_leave_src()
2607 atomic_sub(struct_size(psl, sl_addr, psl->sl_max), in ip6_mc_leave_src()
2608 &sk->sk_omem_alloc); in ip6_mc_leave_src()
2613 mutex_unlock(&idev->mc_lock); in ip6_mc_leave_src()
2621 if (mld_in_v1_mode(ma->idev)) { in igmp6_leave_group()
2622 if (ma->mca_flags & MAF_LAST_REPORTER) { in igmp6_leave_group()
2623 igmp6_send(&ma->mca_addr, ma->idev->dev, in igmp6_leave_group()
2627 mld_add_delrec(ma->idev, ma); in igmp6_leave_group()
2628 mld_ifc_event(ma->idev); in igmp6_leave_group()
2638 mutex_lock(&idev->mc_lock); in mld_gq_work()
2640 idev->mc_gq_running = 0; in mld_gq_work()
2641 mutex_unlock(&idev->mc_lock); in mld_gq_work()
2652 mutex_lock(&idev->mc_lock); in mld_ifc_work()
2655 if (idev->mc_ifc_count) { in mld_ifc_work()
2656 idev->mc_ifc_count--; in mld_ifc_work()
2657 if (idev->mc_ifc_count) in mld_ifc_work()
2661 mutex_unlock(&idev->mc_lock); in mld_ifc_work()
2671 idev->mc_ifc_count = idev->mc_qrv; in mld_ifc_event()
2680 mutex_lock(&ma->idev->mc_lock); in mld_mca_work()
2681 if (mld_in_v1_mode(ma->idev)) in mld_mca_work()
2682 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); in mld_mca_work()
2684 mld_send_report(ma->idev, ma); in mld_mca_work()
2685 ma->mca_flags |= MAF_LAST_REPORTER; in mld_mca_work()
2686 ma->mca_flags &= ~MAF_TIMER_RUNNING; in mld_mca_work()
2687 mutex_unlock(&ma->idev->mc_lock); in mld_mca_work()
2698 /* Install multicast list, except for all-nodes (already installed) */ in ipv6_mc_unmap()
2700 mutex_lock(&idev->mc_lock); in ipv6_mc_unmap()
2703 mutex_unlock(&idev->mc_lock); in ipv6_mc_unmap()
2716 mutex_lock(&idev->mc_lock); in ipv6_mc_down()
2720 mutex_unlock(&idev->mc_lock); in ipv6_mc_down()
2735 idev->mc_qrv = sysctl_mld_qrv; in ipv6_mc_reset()
2736 idev->mc_qi = MLD_QI_DEFAULT; in ipv6_mc_reset()
2737 idev->mc_qri = MLD_QRI_DEFAULT; in ipv6_mc_reset()
2738 idev->mc_v1_seen = 0; in ipv6_mc_reset()
2739 idev->mc_maxdelay = unsolicited_report_interval(idev); in ipv6_mc_reset()
2748 /* Install multicast list, except for all-nodes (already installed) */ in ipv6_mc_up()
2751 mutex_lock(&idev->mc_lock); in ipv6_mc_up()
2756 mutex_unlock(&idev->mc_lock); in ipv6_mc_up()
2763 idev->mc_gq_running = 0; in ipv6_mc_init_dev()
2764 INIT_DELAYED_WORK(&idev->mc_gq_work, mld_gq_work); in ipv6_mc_init_dev()
2765 RCU_INIT_POINTER(idev->mc_tomb, NULL); in ipv6_mc_init_dev()
2766 idev->mc_ifc_count = 0; in ipv6_mc_init_dev()
2767 INIT_DELAYED_WORK(&idev->mc_ifc_work, mld_ifc_work); in ipv6_mc_init_dev()
2768 INIT_DELAYED_WORK(&idev->mc_dad_work, mld_dad_work); in ipv6_mc_init_dev()
2769 INIT_DELAYED_WORK(&idev->mc_query_work, mld_query_work); in ipv6_mc_init_dev()
2770 INIT_DELAYED_WORK(&idev->mc_report_work, mld_report_work); in ipv6_mc_init_dev()
2771 skb_queue_head_init(&idev->mc_query_queue); in ipv6_mc_init_dev()
2772 skb_queue_head_init(&idev->mc_report_queue); in ipv6_mc_init_dev()
2773 spin_lock_init(&idev->mc_query_lock); in ipv6_mc_init_dev()
2774 spin_lock_init(&idev->mc_report_lock); in ipv6_mc_init_dev()
2775 mutex_init(&idev->mc_lock); in ipv6_mc_init_dev()
2789 mutex_lock(&idev->mc_lock); in ipv6_mc_destroy_dev()
2791 mutex_unlock(&idev->mc_lock); in ipv6_mc_destroy_dev()
2795 /* Delete all-nodes address. */ in ipv6_mc_destroy_dev()
2797 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will in ipv6_mc_destroy_dev()
2802 if (idev->cnf.forwarding) in ipv6_mc_destroy_dev()
2805 mutex_lock(&idev->mc_lock); in ipv6_mc_destroy_dev()
2806 while ((i = mc_dereference(idev->mc_list, idev))) { in ipv6_mc_destroy_dev()
2807 rcu_assign_pointer(idev->mc_list, mc_dereference(i->next, idev)); in ipv6_mc_destroy_dev()
2812 mutex_unlock(&idev->mc_lock); in ipv6_mc_destroy_dev()
2821 mutex_lock(&idev->mc_lock); in ipv6_mc_rejoin_groups()
2828 mutex_unlock(&idev->mc_lock); in ipv6_mc_rejoin_groups()
2861 #define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)(seq)->private)
2865 struct ifmcaddr6 *im = NULL; in igmp6_mc_get_first() local
2869 state->idev = NULL; in igmp6_mc_get_first()
2870 for_each_netdev_rcu(net, state->dev) { in igmp6_mc_get_first()
2872 idev = __in6_dev_get(state->dev); in igmp6_mc_get_first()
2876 im = rcu_dereference(idev->mc_list); in igmp6_mc_get_first()
2877 if (im) { in igmp6_mc_get_first()
2878 state->idev = idev; in igmp6_mc_get_first()
2882 return im; in igmp6_mc_get_first()
2885 static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im) in igmp6_mc_get_next() argument
2889 im = rcu_dereference(im->next); in igmp6_mc_get_next()
2890 while (!im) { in igmp6_mc_get_next()
2891 state->dev = next_net_device_rcu(state->dev); in igmp6_mc_get_next()
2892 if (!state->dev) { in igmp6_mc_get_next()
2893 state->idev = NULL; in igmp6_mc_get_next()
2896 state->idev = __in6_dev_get(state->dev); in igmp6_mc_get_next()
2897 if (!state->idev) in igmp6_mc_get_next()
2899 im = rcu_dereference(state->idev->mc_list); in igmp6_mc_get_next()
2901 return im; in igmp6_mc_get_next()
2906 struct ifmcaddr6 *im = igmp6_mc_get_first(seq); in igmp6_mc_get_idx() local
2907 if (im) in igmp6_mc_get_idx()
2908 while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL) in igmp6_mc_get_idx()
2909 --pos; in igmp6_mc_get_idx()
2910 return pos ? NULL : im; in igmp6_mc_get_idx()
2922 struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v); in igmp6_mc_seq_next() local
2925 return im; in igmp6_mc_seq_next()
2933 if (likely(state->idev)) in igmp6_mc_seq_stop()
2934 state->idev = NULL; in igmp6_mc_seq_stop()
2935 state->dev = NULL; in igmp6_mc_seq_stop()
2941 struct ifmcaddr6 *im = (struct ifmcaddr6 *)v; in igmp6_mc_seq_show() local
2945 "%-4d %-15s %pi6 %5d %08X %ld\n", in igmp6_mc_seq_show()
2946 state->dev->ifindex, state->dev->name, in igmp6_mc_seq_show()
2947 &im->mca_addr, in igmp6_mc_seq_show()
2948 im->mca_users, im->mca_flags, in igmp6_mc_seq_show()
2949 (im->mca_flags & MAF_TIMER_RUNNING) ? in igmp6_mc_seq_show()
2950 jiffies_to_clock_t(im->mca_work.timer.expires - jiffies) : 0); in igmp6_mc_seq_show()
2965 struct ifmcaddr6 *im; member
2968 #define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)(seq)->private)
2973 struct ifmcaddr6 *im = NULL; in igmp6_mcf_get_first() local
2977 state->idev = NULL; in igmp6_mcf_get_first()
2978 state->im = NULL; in igmp6_mcf_get_first()
2979 for_each_netdev_rcu(net, state->dev) { in igmp6_mcf_get_first()
2981 idev = __in6_dev_get(state->dev); in igmp6_mcf_get_first()
2985 im = rcu_dereference(idev->mc_list); in igmp6_mcf_get_first()
2986 if (likely(im)) { in igmp6_mcf_get_first()
2987 psf = rcu_dereference(im->mca_sources); in igmp6_mcf_get_first()
2989 state->im = im; in igmp6_mcf_get_first()
2990 state->idev = idev; in igmp6_mcf_get_first()
3002 psf = rcu_dereference(psf->sf_next); in igmp6_mcf_get_next()
3004 state->im = rcu_dereference(state->im->next); in igmp6_mcf_get_next()
3005 while (!state->im) { in igmp6_mcf_get_next()
3006 state->dev = next_net_device_rcu(state->dev); in igmp6_mcf_get_next()
3007 if (!state->dev) { in igmp6_mcf_get_next()
3008 state->idev = NULL; in igmp6_mcf_get_next()
3011 state->idev = __in6_dev_get(state->dev); in igmp6_mcf_get_next()
3012 if (!state->idev) in igmp6_mcf_get_next()
3014 state->im = rcu_dereference(state->idev->mc_list); in igmp6_mcf_get_next()
3016 if (!state->im) in igmp6_mcf_get_next()
3018 psf = rcu_dereference(state->im->mca_sources); in igmp6_mcf_get_next()
3029 --pos; in igmp6_mcf_get_idx()
3037 return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in igmp6_mcf_seq_start()
3056 if (likely(state->im)) in igmp6_mcf_seq_stop()
3057 state->im = NULL; in igmp6_mcf_seq_stop()
3058 if (likely(state->idev)) in igmp6_mcf_seq_stop()
3059 state->idev = NULL; in igmp6_mcf_seq_stop()
3061 state->dev = NULL; in igmp6_mcf_seq_stop()
3075 state->dev->ifindex, state->dev->name, in igmp6_mcf_seq_show()
3076 &state->im->mca_addr, in igmp6_mcf_seq_show()
3077 &psf->sf_addr, in igmp6_mcf_seq_show()
3078 psf->sf_count[MCAST_INCLUDE], in igmp6_mcf_seq_show()
3079 psf->sf_count[MCAST_EXCLUDE]); in igmp6_mcf_seq_show()
3095 err = -ENOMEM; in igmp6_proc_init()
3096 if (!proc_create_net("igmp6", 0444, net->proc_net, &igmp6_mc_seq_ops, in igmp6_proc_init()
3099 if (!proc_create_net("mcfilter6", 0444, net->proc_net, in igmp6_proc_init()
3109 remove_proc_entry("igmp6", net->proc_net); in igmp6_proc_init()
3115 remove_proc_entry("mcfilter6", net->proc_net); in igmp6_proc_exit()
3116 remove_proc_entry("igmp6", net->proc_net); in igmp6_proc_exit()
3132 err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6, in igmp6_net_init()
3140 inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1; in igmp6_net_init()
3141 net->ipv6.igmp_sk->sk_allocation = GFP_KERNEL; in igmp6_net_init()
3143 err = inet_ctl_sock_create(&net->ipv6.mc_autojoin_sk, PF_INET6, in igmp6_net_init()
3158 inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk); in igmp6_net_init()
3160 inet_ctl_sock_destroy(net->ipv6.igmp_sk); in igmp6_net_init()
3167 inet_ctl_sock_destroy(net->ipv6.igmp_sk); in igmp6_net_exit()
3168 inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk); in igmp6_net_exit()
3188 return -ENOMEM; in igmp6_init()