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
117 for (pmc = rcu_dereference(np->ipv6_mc_list); \
119 pmc = rcu_dereference(pmc->next))
126 iv = idev->cnf.mldv1_unsolicited_report_interval; in unsolicited_report_interval()
128 iv = idev->cnf.mldv2_unsolicited_report_interval; in unsolicited_report_interval()
145 return -EINVAL; in __ipv6_sock_mc_join()
149 if ((ifindex == 0 || mc_lst->ifindex == ifindex) && in __ipv6_sock_mc_join()
150 ipv6_addr_equal(&mc_lst->addr, addr)) { in __ipv6_sock_mc_join()
152 return -EADDRINUSE; in __ipv6_sock_mc_join()
160 return -ENOMEM; in __ipv6_sock_mc_join()
162 mc_lst->next = NULL; in __ipv6_sock_mc_join()
163 mc_lst->addr = *addr; in __ipv6_sock_mc_join()
169 dev = rt->dst.dev; in __ipv6_sock_mc_join()
177 return -ENODEV; in __ipv6_sock_mc_join()
180 mc_lst->ifindex = dev->ifindex; in __ipv6_sock_mc_join()
181 mc_lst->sfmode = mode; in __ipv6_sock_mc_join()
182 rwlock_init(&mc_lst->sflock); in __ipv6_sock_mc_join()
183 mc_lst->sflist = NULL; in __ipv6_sock_mc_join()
196 mc_lst->next = np->ipv6_mc_list; in __ipv6_sock_mc_join()
197 rcu_assign_pointer(np->ipv6_mc_list, mc_lst); in __ipv6_sock_mc_join()
227 return -EINVAL; in ipv6_sock_mc_drop()
229 for (lnk = &np->ipv6_mc_list; in ipv6_sock_mc_drop()
231 lnk = &mc_lst->next) { in ipv6_sock_mc_drop()
232 if ((ifindex == 0 || mc_lst->ifindex == ifindex) && in ipv6_sock_mc_drop()
233 ipv6_addr_equal(&mc_lst->addr, addr)) { in ipv6_sock_mc_drop()
236 *lnk = mc_lst->next; in ipv6_sock_mc_drop()
238 dev = __dev_get_by_index(net, mc_lst->ifindex); in ipv6_sock_mc_drop()
244 __ipv6_dev_mc_dec(idev, &mc_lst->addr); in ipv6_sock_mc_drop()
248 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); in ipv6_sock_mc_drop()
254 return -EADDRNOTAVAIL; in ipv6_sock_mc_drop()
270 dev = rt->dst.dev; in ip6_mc_find_dev_rcu()
281 read_lock_bh(&idev->lock); in ip6_mc_find_dev_rcu()
282 if (idev->dead) { in ip6_mc_find_dev_rcu()
283 read_unlock_bh(&idev->lock); in ip6_mc_find_dev_rcu()
297 while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) { in __ipv6_sock_mc_close()
300 np->ipv6_mc_list = mc_lst->next; in __ipv6_sock_mc_close()
302 dev = __dev_get_by_index(net, mc_lst->ifindex); in __ipv6_sock_mc_close()
308 __ipv6_dev_mc_dec(idev, &mc_lst->addr); in __ipv6_sock_mc_close()
312 atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); in __ipv6_sock_mc_close()
321 if (!rcu_access_pointer(np->ipv6_mc_list)) in ipv6_sock_mc_close()
342 source = &((struct sockaddr_in6 *)&pgsr->gsr_source)->sin6_addr; in ip6_mc_source()
343 group = &((struct sockaddr_in6 *)&pgsr->gsr_group)->sin6_addr; in ip6_mc_source()
346 return -EINVAL; in ip6_mc_source()
349 idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface); in ip6_mc_source()
352 return -ENODEV; in ip6_mc_source()
355 err = -EADDRNOTAVAIL; in ip6_mc_source()
358 if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) in ip6_mc_source()
360 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_source()
364 err = -EINVAL; in ip6_mc_source()
368 if (pmc->sflist) { in ip6_mc_source()
369 if (pmc->sfmode != omode) { in ip6_mc_source()
370 err = -EINVAL; in ip6_mc_source()
373 } else if (pmc->sfmode != omode) { in ip6_mc_source()
374 /* allow mode switches for empty-set filters */ in ip6_mc_source()
376 ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_source()
377 pmc->sfmode = omode; in ip6_mc_source()
380 write_lock(&pmc->sflock); in ip6_mc_source()
383 psl = pmc->sflist; in ip6_mc_source()
386 goto done; /* err = -EADDRNOTAVAIL */ in ip6_mc_source()
388 for (i = 0; i < psl->sl_count; i++) { in ip6_mc_source()
389 rv = !ipv6_addr_equal(&psl->sl_addr[i], source); in ip6_mc_source()
394 goto done; /* err = -EADDRNOTAVAIL */ in ip6_mc_source()
396 /* special case - (INCLUDE, empty) == LEAVE_GROUP */ in ip6_mc_source()
397 if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { in ip6_mc_source()
405 for (j = i+1; j < psl->sl_count; j++) in ip6_mc_source()
406 psl->sl_addr[j-1] = psl->sl_addr[j]; in ip6_mc_source()
407 psl->sl_count--; in ip6_mc_source()
413 if (psl && psl->sl_count >= sysctl_mld_max_msf) { in ip6_mc_source()
414 err = -ENOBUFS; in ip6_mc_source()
417 if (!psl || psl->sl_count == psl->sl_max) { in ip6_mc_source()
422 count += psl->sl_max; in ip6_mc_source()
425 err = -ENOBUFS; in ip6_mc_source()
428 newpsl->sl_max = count; in ip6_mc_source()
429 newpsl->sl_count = count - IP6_SFBLOCK; in ip6_mc_source()
431 for (i = 0; i < psl->sl_count; i++) in ip6_mc_source()
432 newpsl->sl_addr[i] = psl->sl_addr[i]; in ip6_mc_source()
433 sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max)); in ip6_mc_source()
435 pmc->sflist = psl = newpsl; in ip6_mc_source()
438 for (i = 0; i < psl->sl_count; i++) { in ip6_mc_source()
439 rv = !ipv6_addr_equal(&psl->sl_addr[i], source); in ip6_mc_source()
443 for (j = psl->sl_count-1; j >= i; j--) in ip6_mc_source()
444 psl->sl_addr[j+1] = psl->sl_addr[j]; in ip6_mc_source()
445 psl->sl_addr[i] = *source; in ip6_mc_source()
446 psl->sl_count++; in ip6_mc_source()
452 write_unlock(&pmc->sflock); in ip6_mc_source()
453 read_unlock_bh(&idev->lock); in ip6_mc_source()
456 err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); in ip6_mc_source()
472 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; in ip6_mc_msfilter()
475 return -EINVAL; in ip6_mc_msfilter()
476 if (gsf->gf_fmode != MCAST_INCLUDE && in ip6_mc_msfilter()
477 gsf->gf_fmode != MCAST_EXCLUDE) in ip6_mc_msfilter()
478 return -EINVAL; in ip6_mc_msfilter()
481 idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); in ip6_mc_msfilter()
485 return -ENODEV; in ip6_mc_msfilter()
490 if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) { in ip6_mc_msfilter()
496 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfilter()
498 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_msfilter()
502 err = -EINVAL; in ip6_mc_msfilter()
505 if (gsf->gf_numsrc) { in ip6_mc_msfilter()
506 newpsl = sock_kmalloc(sk, IP6_SFLSIZE(gsf->gf_numsrc), in ip6_mc_msfilter()
509 err = -ENOBUFS; in ip6_mc_msfilter()
512 newpsl->sl_max = newpsl->sl_count = gsf->gf_numsrc; in ip6_mc_msfilter()
513 for (i = 0; i < newpsl->sl_count; ++i, ++list) { in ip6_mc_msfilter()
517 newpsl->sl_addr[i] = psin6->sin6_addr; in ip6_mc_msfilter()
519 err = ip6_mc_add_src(idev, group, gsf->gf_fmode, in ip6_mc_msfilter()
520 newpsl->sl_count, newpsl->sl_addr, 0); in ip6_mc_msfilter()
522 sock_kfree_s(sk, newpsl, IP6_SFLSIZE(newpsl->sl_max)); in ip6_mc_msfilter()
527 (void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0); in ip6_mc_msfilter()
530 write_lock(&pmc->sflock); in ip6_mc_msfilter()
531 psl = pmc->sflist; in ip6_mc_msfilter()
533 (void) ip6_mc_del_src(idev, group, pmc->sfmode, in ip6_mc_msfilter()
534 psl->sl_count, psl->sl_addr, 0); in ip6_mc_msfilter()
535 sock_kfree_s(sk, psl, IP6_SFLSIZE(psl->sl_max)); in ip6_mc_msfilter()
537 (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_msfilter()
538 pmc->sflist = newpsl; in ip6_mc_msfilter()
539 pmc->sfmode = gsf->gf_fmode; in ip6_mc_msfilter()
540 write_unlock(&pmc->sflock); in ip6_mc_msfilter()
543 read_unlock_bh(&idev->lock); in ip6_mc_msfilter()
546 err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group); in ip6_mc_msfilter()
561 group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr; in ip6_mc_msfget()
564 return -EINVAL; in ip6_mc_msfget()
567 idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface); in ip6_mc_msfget()
571 return -ENODEV; in ip6_mc_msfget()
574 err = -EADDRNOTAVAIL; in ip6_mc_msfget()
581 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfget()
583 if (ipv6_addr_equal(group, &pmc->addr)) in ip6_mc_msfget()
588 gsf->gf_fmode = pmc->sfmode; in ip6_mc_msfget()
589 psl = pmc->sflist; in ip6_mc_msfget()
590 count = psl ? psl->sl_count : 0; in ip6_mc_msfget()
591 read_unlock_bh(&idev->lock); in ip6_mc_msfget()
594 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; in ip6_mc_msfget()
595 gsf->gf_numsrc = count; in ip6_mc_msfget()
597 * on pmc->sflock. We have the socket lock so reading here is safe. in ip6_mc_msfget()
605 psin6->sin6_family = AF_INET6; in ip6_mc_msfget()
606 psin6->sin6_addr = psl->sl_addr[i]; in ip6_mc_msfget()
608 return -EFAULT; in ip6_mc_msfget()
612 read_unlock_bh(&idev->lock); in ip6_mc_msfget()
627 if (ipv6_addr_equal(&mc->addr, mc_addr)) in inet6_mc_check()
632 return np->mc_all; in inet6_mc_check()
634 read_lock(&mc->sflock); in inet6_mc_check()
635 psl = mc->sflist; in inet6_mc_check()
637 rv = mc->sfmode == MCAST_EXCLUDE; in inet6_mc_check()
641 for (i = 0; i < psl->sl_count; i++) { in inet6_mc_check()
642 if (ipv6_addr_equal(&psl->sl_addr[i], src_addr)) in inet6_mc_check()
645 if (mc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) in inet6_mc_check()
647 if (mc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) in inet6_mc_check()
650 read_unlock(&mc->sflock); in inet6_mc_check()
658 struct net_device *dev = mc->idev->dev; in igmp6_group_added()
661 if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < in igmp6_group_added()
665 spin_lock_bh(&mc->mca_lock); in igmp6_group_added()
666 if (!(mc->mca_flags&MAF_LOADED)) { in igmp6_group_added()
667 mc->mca_flags |= MAF_LOADED; in igmp6_group_added()
668 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) in igmp6_group_added()
671 spin_unlock_bh(&mc->mca_lock); in igmp6_group_added()
673 if (!(dev->flags & IFF_UP) || (mc->mca_flags & MAF_NOREPORT)) in igmp6_group_added()
676 if (mld_in_v1_mode(mc->idev)) { in igmp6_group_added()
683 * should not send filter-mode change record as the mode in igmp6_group_added()
686 if (mc->mca_sfmode == MCAST_EXCLUDE) in igmp6_group_added()
687 mc->mca_crcount = mc->idev->mc_qrv; in igmp6_group_added()
689 mld_ifc_event(mc->idev); in igmp6_group_added()
694 struct net_device *dev = mc->idev->dev; in igmp6_group_dropped()
697 if (IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < in igmp6_group_dropped()
701 spin_lock_bh(&mc->mca_lock); in igmp6_group_dropped()
702 if (mc->mca_flags&MAF_LOADED) { in igmp6_group_dropped()
703 mc->mca_flags &= ~MAF_LOADED; in igmp6_group_dropped()
704 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) in igmp6_group_dropped()
708 spin_unlock_bh(&mc->mca_lock); in igmp6_group_dropped()
709 if (mc->mca_flags & MAF_NOREPORT) in igmp6_group_dropped()
712 if (!mc->idev->dead) in igmp6_group_dropped()
715 spin_lock_bh(&mc->mca_lock); in igmp6_group_dropped()
716 if (del_timer(&mc->mca_timer)) in igmp6_group_dropped()
717 refcount_dec(&mc->mca_refcnt); in igmp6_group_dropped()
718 spin_unlock_bh(&mc->mca_lock); in igmp6_group_dropped()
724 static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) in mld_add_delrec() argument
732 * non-deleted or query-response MCA's. in mld_add_delrec()
738 spin_lock_bh(&im->mca_lock); in mld_add_delrec()
739 spin_lock_init(&pmc->mca_lock); in mld_add_delrec()
740 pmc->idev = im->idev; in mld_add_delrec()
742 pmc->mca_addr = im->mca_addr; in mld_add_delrec()
743 pmc->mca_crcount = idev->mc_qrv; in mld_add_delrec()
744 pmc->mca_sfmode = im->mca_sfmode; in mld_add_delrec()
745 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_add_delrec()
748 pmc->mca_tomb = im->mca_tomb; in mld_add_delrec()
749 pmc->mca_sources = im->mca_sources; in mld_add_delrec()
750 im->mca_tomb = im->mca_sources = NULL; in mld_add_delrec()
751 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) in mld_add_delrec()
752 psf->sf_crcount = pmc->mca_crcount; in mld_add_delrec()
754 spin_unlock_bh(&im->mca_lock); in mld_add_delrec()
756 spin_lock_bh(&idev->mc_lock); in mld_add_delrec()
757 pmc->next = idev->mc_tomb; in mld_add_delrec()
758 idev->mc_tomb = pmc; in mld_add_delrec()
759 spin_unlock_bh(&idev->mc_lock); in mld_add_delrec()
762 static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) in mld_del_delrec() argument
766 struct in6_addr *pmca = &im->mca_addr; in mld_del_delrec()
768 spin_lock_bh(&idev->mc_lock); in mld_del_delrec()
770 for (pmc = idev->mc_tomb; pmc; pmc = pmc->next) { in mld_del_delrec()
771 if (ipv6_addr_equal(&pmc->mca_addr, pmca)) in mld_del_delrec()
777 pmc_prev->next = pmc->next; in mld_del_delrec()
779 idev->mc_tomb = pmc->next; in mld_del_delrec()
781 spin_unlock_bh(&idev->mc_lock); in mld_del_delrec()
783 spin_lock_bh(&im->mca_lock); in mld_del_delrec()
785 im->idev = pmc->idev; in mld_del_delrec()
786 if (im->mca_sfmode == MCAST_INCLUDE) { in mld_del_delrec()
787 swap(im->mca_tomb, pmc->mca_tomb); in mld_del_delrec()
788 swap(im->mca_sources, pmc->mca_sources); in mld_del_delrec()
789 for (psf = im->mca_sources; psf; psf = psf->sf_next) in mld_del_delrec()
790 psf->sf_crcount = idev->mc_qrv; in mld_del_delrec()
792 im->mca_crcount = idev->mc_qrv; in mld_del_delrec()
794 in6_dev_put(pmc->idev); in mld_del_delrec()
798 spin_unlock_bh(&im->mca_lock); in mld_del_delrec()
805 spin_lock_bh(&idev->mc_lock); in mld_clear_delrec()
806 pmc = idev->mc_tomb; in mld_clear_delrec()
807 idev->mc_tomb = NULL; in mld_clear_delrec()
808 spin_unlock_bh(&idev->mc_lock); in mld_clear_delrec()
811 nextpmc = pmc->next; in mld_clear_delrec()
813 in6_dev_put(pmc->idev); in mld_clear_delrec()
818 read_lock_bh(&idev->lock); in mld_clear_delrec()
819 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in mld_clear_delrec()
822 spin_lock_bh(&pmc->mca_lock); in mld_clear_delrec()
823 psf = pmc->mca_tomb; in mld_clear_delrec()
824 pmc->mca_tomb = NULL; in mld_clear_delrec()
825 spin_unlock_bh(&pmc->mca_lock); in mld_clear_delrec()
827 psf_next = psf->sf_next; in mld_clear_delrec()
831 read_unlock_bh(&idev->lock); in mld_clear_delrec()
836 refcount_inc(&mc->mca_refcnt); in mca_get()
841 if (refcount_dec_and_test(&mc->mca_refcnt)) { in ma_put()
842 in6_dev_put(mc->idev); in ma_put()
857 timer_setup(&mc->mca_timer, igmp6_timer_handler, 0); in mca_alloc()
859 mc->mca_addr = *addr; in mca_alloc()
860 mc->idev = idev; /* reference taken by caller */ in mca_alloc()
861 mc->mca_users = 1; in mca_alloc()
863 mc->mca_cstamp = mc->mca_tstamp = jiffies; in mca_alloc()
864 refcount_set(&mc->mca_refcnt, 1); in mca_alloc()
865 spin_lock_init(&mc->mca_lock); in mca_alloc()
867 mc->mca_sfmode = mode; in mca_alloc()
868 mc->mca_sfcount[mode] = 1; in mca_alloc()
870 if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) || in mca_alloc()
871 IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) in mca_alloc()
872 mc->mca_flags |= MAF_NOREPORT; in mca_alloc()
892 return -EINVAL; in __ipv6_dev_mc_inc()
894 write_lock_bh(&idev->lock); in __ipv6_dev_mc_inc()
895 if (idev->dead) { in __ipv6_dev_mc_inc()
896 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_inc()
898 return -ENODEV; in __ipv6_dev_mc_inc()
901 for (mc = idev->mc_list; mc; mc = mc->next) { in __ipv6_dev_mc_inc()
902 if (ipv6_addr_equal(&mc->mca_addr, addr)) { in __ipv6_dev_mc_inc()
903 mc->mca_users++; in __ipv6_dev_mc_inc()
904 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_inc()
905 ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0); in __ipv6_dev_mc_inc()
913 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_inc()
915 return -ENOMEM; in __ipv6_dev_mc_inc()
918 mc->next = idev->mc_list; in __ipv6_dev_mc_inc()
919 idev->mc_list = mc; in __ipv6_dev_mc_inc()
922 * it is already exposed via idev->mc_list. in __ipv6_dev_mc_inc()
925 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_inc()
948 write_lock_bh(&idev->lock); in __ipv6_dev_mc_dec()
949 for (map = &idev->mc_list; (ma = *map) != NULL; map = &ma->next) { in __ipv6_dev_mc_dec()
950 if (ipv6_addr_equal(&ma->mca_addr, addr)) { in __ipv6_dev_mc_dec()
951 if (--ma->mca_users == 0) { in __ipv6_dev_mc_dec()
952 *map = ma->next; in __ipv6_dev_mc_dec()
953 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_dec()
961 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_dec()
965 write_unlock_bh(&idev->lock); in __ipv6_dev_mc_dec()
967 return -ENOENT; in __ipv6_dev_mc_dec()
979 err = -ENODEV; in ipv6_dev_mc_dec()
1000 read_lock_bh(&idev->lock); in ipv6_chk_mcast_addr()
1001 for (mc = idev->mc_list; mc; mc = mc->next) { in ipv6_chk_mcast_addr()
1002 if (ipv6_addr_equal(&mc->mca_addr, group)) in ipv6_chk_mcast_addr()
1009 spin_lock_bh(&mc->mca_lock); in ipv6_chk_mcast_addr()
1010 for (psf = mc->mca_sources; psf; psf = psf->sf_next) { in ipv6_chk_mcast_addr()
1011 if (ipv6_addr_equal(&psf->sf_addr, src_addr)) in ipv6_chk_mcast_addr()
1015 rv = psf->sf_count[MCAST_INCLUDE] || in ipv6_chk_mcast_addr()
1016 psf->sf_count[MCAST_EXCLUDE] != in ipv6_chk_mcast_addr()
1017 mc->mca_sfcount[MCAST_EXCLUDE]; in ipv6_chk_mcast_addr()
1019 rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0; in ipv6_chk_mcast_addr()
1020 spin_unlock_bh(&mc->mca_lock); in ipv6_chk_mcast_addr()
1024 read_unlock_bh(&idev->lock); in ipv6_chk_mcast_addr()
1032 unsigned long tv = prandom_u32() % idev->mc_maxdelay; in mld_gq_start_timer()
1034 idev->mc_gq_running = 1; in mld_gq_start_timer()
1035 if (!mod_timer(&idev->mc_gq_timer, jiffies+tv+2)) in mld_gq_start_timer()
1041 idev->mc_gq_running = 0; in mld_gq_stop_timer()
1042 if (del_timer(&idev->mc_gq_timer)) in mld_gq_stop_timer()
1050 if (!mod_timer(&idev->mc_ifc_timer, jiffies+tv+2)) in mld_ifc_start_timer()
1056 idev->mc_ifc_count = 0; in mld_ifc_stop_timer()
1057 if (del_timer(&idev->mc_ifc_timer)) in mld_ifc_stop_timer()
1065 if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2)) in mld_dad_start_timer()
1071 if (del_timer(&idev->mc_dad_timer)) in mld_dad_stop_timer()
1084 if (ipv6_addr_is_ll_all_nodes(&ma->mca_addr) || in igmp6_group_queried()
1085 IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) in igmp6_group_queried()
1088 if (del_timer(&ma->mca_timer)) { in igmp6_group_queried()
1089 refcount_dec(&ma->mca_refcnt); in igmp6_group_queried()
1090 delay = ma->mca_timer.expires - jiffies; in igmp6_group_queried()
1096 ma->mca_timer.expires = jiffies + delay; in igmp6_group_queried()
1097 if (!mod_timer(&ma->mca_timer, jiffies + delay)) in igmp6_group_queried()
1098 refcount_inc(&ma->mca_refcnt); in igmp6_group_queried()
1099 ma->mca_flags |= MAF_TIMER_RUNNING; in igmp6_group_queried()
1102 /* mark EXCLUDE-mode sources */
1110 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in mld_xmarksources()
1115 if (psf->sf_count[MCAST_INCLUDE] || in mld_xmarksources()
1116 pmc->mca_sfcount[MCAST_EXCLUDE] != in mld_xmarksources()
1117 psf->sf_count[MCAST_EXCLUDE]) in mld_xmarksources()
1119 if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { in mld_xmarksources()
1125 pmc->mca_flags &= ~MAF_GSQUERY; in mld_xmarksources()
1137 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_marksources()
1140 /* mark INCLUDE-mode sources */ in mld_marksources()
1143 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in mld_marksources()
1147 if (ipv6_addr_equal(&srcs[i], &psf->sf_addr)) { in mld_marksources()
1148 psf->sf_gsresp = 1; in mld_marksources()
1155 pmc->mca_flags &= ~MAF_GSQUERY; in mld_marksources()
1158 pmc->mca_flags |= MAF_GSQUERY; in mld_marksources()
1169 if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0) in mld_force_mld_version()
1170 return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version; in mld_force_mld_version()
1172 return idev->cnf.force_mld_version; in mld_force_mld_version()
1191 if (idev->mc_v1_seen && time_before(jiffies, idev->mc_v1_seen)) in mld_in_v1_mode()
1200 * - 9.1. Robustness Variable in mld_set_v1_mode()
1201 * - 9.2. Query Interval in mld_set_v1_mode()
1202 * - 9.3. Query Response Interval in mld_set_v1_mode()
1203 * - 9.12. Older Version Querier Present Timeout in mld_set_v1_mode()
1207 switchback = (idev->mc_qrv * idev->mc_qi) + idev->mc_qri; in mld_set_v1_mode()
1209 idev->mc_v1_seen = jiffies + switchback; in mld_set_v1_mode()
1216 * - 5.1.8. QRV (Querier's Robustness Variable) in mld_update_qrv()
1217 * - 9.1. Robustness Variable in mld_update_qrv()
1225 WARN_ON(idev->mc_qrv == 0); in mld_update_qrv()
1227 if (mlh2->mld2q_qrv > 0) in mld_update_qrv()
1228 idev->mc_qrv = mlh2->mld2q_qrv; in mld_update_qrv()
1230 if (unlikely(idev->mc_qrv < min_qrv)) { in mld_update_qrv()
1232 idev->mc_qrv, min_qrv); in mld_update_qrv()
1233 idev->mc_qrv = min_qrv; in mld_update_qrv()
1241 * - 5.1.9. QQIC (Querier's Query Interval Code) in mld_update_qi()
1242 * - 9.2. Query Interval in mld_update_qi()
1243 * - 9.12. Older Version Querier Present Timeout in mld_update_qi()
1248 if (mlh2->mld2q_qqic < 128) { in mld_update_qi()
1249 mc_qqi = mlh2->mld2q_qqic; in mld_update_qi()
1253 mc_exp = MLDV2_QQIC_EXP(mlh2->mld2q_qqic); in mld_update_qi()
1254 mc_man = MLDV2_QQIC_MAN(mlh2->mld2q_qqic); in mld_update_qi()
1259 idev->mc_qi = mc_qqi * HZ; in mld_update_qi()
1266 * - 5.1.3. Maximum Response Code in mld_update_qri()
1267 * - 9.3. Query Response Interval in mld_update_qri()
1269 idev->mc_qri = msecs_to_jiffies(mldv2_mrc(mlh2)); in mld_update_qri()
1279 return -EINVAL; in mld_process_v1()
1281 mldv1_md = ntohs(mld->mld_maxdelay); in mld_process_v1()
1283 /* When in MLDv1 fallback and a MLDv2 router start-up being in mld_process_v1()
1327 idev->mc_maxdelay = *max_delay; in mld_process_v2()
1346 return -EINVAL; in igmp6_event_query()
1349 len = ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr); in igmp6_event_query()
1350 len -= skb_network_header_len(skb); in igmp6_event_query()
1354 * checks if the source address of the message is a valid link-local in igmp6_event_query()
1356 * option is present in the Hop-By-Hop Options header of the IPv6 in igmp6_event_query()
1359 if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) || in igmp6_event_query()
1360 ipv6_hdr(skb)->hop_limit != 1 || in igmp6_event_query()
1361 !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) || in igmp6_event_query()
1362 IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD)) in igmp6_event_query()
1363 return -EINVAL; in igmp6_event_query()
1365 idev = __in6_dev_get(skb->dev); in igmp6_event_query()
1370 group = &mld->mld_mca; in igmp6_event_query()
1375 return -EINVAL; in igmp6_event_query()
1378 return -EINVAL; in igmp6_event_query()
1385 int srcs_offset = sizeof(struct mld2_query) - in igmp6_event_query()
1389 return -EINVAL; in igmp6_event_query()
1398 if (mlh2->mld2q_nsrcs) in igmp6_event_query()
1399 return -EINVAL; /* no sources allowed */ in igmp6_event_query()
1404 /* mark sources to include, if group & source-specific */ in igmp6_event_query()
1405 if (mlh2->mld2q_nsrcs != 0) { in igmp6_event_query()
1407 ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) in igmp6_event_query()
1408 return -EINVAL; in igmp6_event_query()
1414 return -EINVAL; in igmp6_event_query()
1417 read_lock_bh(&idev->lock); in igmp6_event_query()
1419 for (ma = idev->mc_list; ma; ma = ma->next) { in igmp6_event_query()
1420 spin_lock_bh(&ma->mca_lock); in igmp6_event_query()
1422 spin_unlock_bh(&ma->mca_lock); in igmp6_event_query()
1425 for (ma = idev->mc_list; ma; ma = ma->next) { in igmp6_event_query()
1426 if (!ipv6_addr_equal(group, &ma->mca_addr)) in igmp6_event_query()
1428 spin_lock_bh(&ma->mca_lock); in igmp6_event_query()
1429 if (ma->mca_flags & MAF_TIMER_RUNNING) { in igmp6_event_query()
1430 /* gsquery <- gsquery && mark */ in igmp6_event_query()
1432 ma->mca_flags &= ~MAF_GSQUERY; in igmp6_event_query()
1434 /* gsquery <- mark */ in igmp6_event_query()
1436 ma->mca_flags |= MAF_GSQUERY; in igmp6_event_query()
1438 ma->mca_flags &= ~MAF_GSQUERY; in igmp6_event_query()
1440 if (!(ma->mca_flags & MAF_GSQUERY) || in igmp6_event_query()
1441 mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) in igmp6_event_query()
1443 spin_unlock_bh(&ma->mca_lock); in igmp6_event_query()
1447 read_unlock_bh(&idev->lock); in igmp6_event_query()
1461 if (skb->pkt_type == PACKET_LOOPBACK) in igmp6_event_report()
1465 if (skb->pkt_type != PACKET_MULTICAST && in igmp6_event_report()
1466 skb->pkt_type != PACKET_BROADCAST) in igmp6_event_report()
1469 if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) in igmp6_event_report()
1470 return -EINVAL; in igmp6_event_report()
1475 addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); in igmp6_event_report()
1478 return -EINVAL; in igmp6_event_report()
1480 idev = __in6_dev_get(skb->dev); in igmp6_event_report()
1482 return -ENODEV; in igmp6_event_report()
1488 read_lock_bh(&idev->lock); in igmp6_event_report()
1489 for (ma = idev->mc_list; ma; ma = ma->next) { in igmp6_event_report()
1490 if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { in igmp6_event_report()
1491 spin_lock(&ma->mca_lock); in igmp6_event_report()
1492 if (del_timer(&ma->mca_timer)) in igmp6_event_report()
1493 refcount_dec(&ma->mca_refcnt); in igmp6_event_report()
1494 ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING); in igmp6_event_report()
1495 spin_unlock(&ma->mca_lock); in igmp6_event_report()
1499 read_unlock_bh(&idev->lock); in igmp6_event_report()
1511 if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) { in is_in()
1512 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1517 if (psf->sf_count[MCAST_INCLUDE]) in is_in()
1519 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1520 psf->sf_count[MCAST_EXCLUDE]; in is_in()
1526 return psf->sf_count[MCAST_INCLUDE] != 0; in is_in()
1530 if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 || in is_in()
1531 psf->sf_count[MCAST_INCLUDE]) in is_in()
1533 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1534 psf->sf_count[MCAST_EXCLUDE]; in is_in()
1536 if (gdeleted || !psf->sf_crcount) in is_in()
1538 return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted; in is_in()
1540 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1541 return gdeleted || (psf->sf_crcount && sdeleted); in is_in()
1542 return psf->sf_crcount && !gdeleted && !sdeleted; in is_in()
1553 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in mld_scount()
1569 skb->protocol = htons(ETH_P_IPV6); in ip6_mc_hdr()
1570 skb->dev = dev; in ip6_mc_hdr()
1578 hdr->payload_len = htons(len); in ip6_mc_hdr()
1579 hdr->nexthdr = proto; in ip6_mc_hdr()
1580 hdr->hop_limit = inet6_sk(sk)->hop_limit; in ip6_mc_hdr()
1582 hdr->saddr = *saddr; in ip6_mc_hdr()
1583 hdr->daddr = *daddr; in ip6_mc_hdr()
1588 struct net_device *dev = idev->dev; in mld_newpack()
1590 struct sock *sk = net->ipv6.igmp_sk; in mld_newpack()
1596 int tlen = dev->needed_tailroom; in mld_newpack()
1604 /* limit our allocations to order-0 page */ in mld_newpack()
1611 skb->priority = TC_PRIO_CONTROL; in mld_newpack()
1616 /* <draft-ietf-magma-mld-source-05.txt>: in mld_newpack()
1618 * when a valid link-local address is not available. in mld_newpack()
1628 skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); in mld_newpack()
1631 pmr->mld2r_type = ICMPV6_MLD2_REPORT; in mld_newpack()
1632 pmr->mld2r_resv1 = 0; in mld_newpack()
1633 pmr->mld2r_cksum = 0; in mld_newpack()
1634 pmr->mld2r_resv2 = 0; in mld_newpack()
1635 pmr->mld2r_ngrec = 0; in mld_newpack()
1646 struct net *net = dev_net(skb->dev); in mld_sendpack()
1652 idev = __in6_dev_get(skb->dev); in mld_sendpack()
1653 IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); in mld_sendpack()
1655 payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) - in mld_sendpack()
1657 mldlen = skb_tail_pointer(skb) - skb_transport_header(skb); in mld_sendpack()
1658 pip6->payload_len = htons(payload_len); in mld_sendpack()
1660 pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, in mld_sendpack()
1665 icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, in mld_sendpack()
1666 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, in mld_sendpack()
1667 skb->dev->ifindex); in mld_sendpack()
1668 dst = icmp6_dst_alloc(skb->dev, &fl6); in mld_sendpack()
1680 net, net->ipv6.igmp_sk, skb, NULL, skb->dev, in mld_sendpack()
1710 skb = mld_newpack(pmc->idev, mtu); in add_grhead()
1715 pgr->grec_type = type; in add_grhead()
1716 pgr->grec_auxwords = 0; in add_grhead()
1717 pgr->grec_nsrcs = 0; in add_grhead()
1718 pgr->grec_mca = pmc->mca_addr; /* structure copy */ in add_grhead()
1720 pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); in add_grhead()
1730 struct inet6_dev *idev = pmc->idev; in add_grec()
1731 struct net_device *dev = idev->dev; in add_grec()
1738 if (pmc->mca_flags & MAF_NOREPORT) in add_grec()
1741 mtu = READ_ONCE(dev->mtu); in add_grec()
1752 psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources; in add_grec()
1761 if (pmr && pmr->mld2r_ngrec && in add_grec()
1773 psf_next = psf->sf_next; in add_grec()
1780 /* Based on RFC3810 6.1. Should not send source-list change in add_grec()
1783 if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) || in add_grec()
1784 (!gdeleted && pmc->mca_crcount)) && in add_grec()
1786 type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) in add_grec()
1791 psf->sf_gsresp = 0; in add_grec()
1798 pgr->grec_nsrcs = htons(scount); in add_grec()
1812 *psrc = psf->sf_addr; in add_grec()
1815 type == MLD2_BLOCK_OLD_SOURCES) && psf->sf_crcount) { in add_grec()
1817 psf->sf_crcount--; in add_grec()
1818 if ((sdeleted || gdeleted) && psf->sf_crcount == 0) { in add_grec()
1820 psf_prev->sf_next = psf->sf_next; in add_grec()
1822 *psf_list = psf->sf_next; in add_grec()
1835 if (pmc->mca_crcount || isquery || crsend) { in add_grec()
1845 pgr->grec_nsrcs = htons(scount); in add_grec()
1848 pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */ in add_grec()
1857 read_lock_bh(&idev->lock); in mld_send_report()
1859 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in mld_send_report()
1860 if (pmc->mca_flags & MAF_NOREPORT) in mld_send_report()
1862 spin_lock_bh(&pmc->mca_lock); in mld_send_report()
1863 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
1868 spin_unlock_bh(&pmc->mca_lock); in mld_send_report()
1871 spin_lock_bh(&pmc->mca_lock); in mld_send_report()
1872 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
1877 spin_unlock_bh(&pmc->mca_lock); in mld_send_report()
1879 read_unlock_bh(&idev->lock); in mld_send_report()
1885 * remove zero-count source records from a source filter list
1893 psf_next = psf->sf_next; in mld_clear_zeros()
1894 if (psf->sf_crcount == 0) { in mld_clear_zeros()
1896 psf_prev->sf_next = psf->sf_next; in mld_clear_zeros()
1898 *ppsf = psf->sf_next; in mld_clear_zeros()
1911 read_lock_bh(&idev->lock); in mld_send_cr()
1912 spin_lock(&idev->mc_lock); in mld_send_cr()
1916 for (pmc = idev->mc_tomb; pmc; pmc = pmc_next) { in mld_send_cr()
1917 pmc_next = pmc->next; in mld_send_cr()
1918 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_send_cr()
1924 if (pmc->mca_crcount) { in mld_send_cr()
1925 if (pmc->mca_sfmode == MCAST_EXCLUDE) { in mld_send_cr()
1929 pmc->mca_crcount--; in mld_send_cr()
1930 if (pmc->mca_crcount == 0) { in mld_send_cr()
1931 mld_clear_zeros(&pmc->mca_tomb); in mld_send_cr()
1932 mld_clear_zeros(&pmc->mca_sources); in mld_send_cr()
1935 if (pmc->mca_crcount == 0 && !pmc->mca_tomb && in mld_send_cr()
1936 !pmc->mca_sources) { in mld_send_cr()
1938 pmc_prev->next = pmc_next; in mld_send_cr()
1940 idev->mc_tomb = pmc_next; in mld_send_cr()
1941 in6_dev_put(pmc->idev); in mld_send_cr()
1946 spin_unlock(&idev->mc_lock); in mld_send_cr()
1949 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in mld_send_cr()
1950 spin_lock_bh(&pmc->mca_lock); in mld_send_cr()
1951 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in mld_send_cr()
1962 if (pmc->mca_crcount) { in mld_send_cr()
1963 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_send_cr()
1968 pmc->mca_crcount--; in mld_send_cr()
1970 spin_unlock_bh(&pmc->mca_lock); in mld_send_cr()
1972 read_unlock_bh(&idev->lock); in mld_send_cr()
1981 struct sock *sk = net->ipv6.igmp_sk; in igmp6_send()
1988 int tlen = dev->needed_tailroom; in igmp6_send()
2019 skb->priority = TC_PRIO_CONTROL; in igmp6_send()
2023 /* <draft-ietf-magma-mld-source-05.txt>: in igmp6_send()
2025 * when a valid link-local address is not available. in igmp6_send()
2036 hdr->mld_type = type; in igmp6_send()
2037 hdr->mld_mca = *addr; in igmp6_send()
2039 hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, in igmp6_send()
2044 idev = __in6_dev_get(skb->dev); in igmp6_send()
2047 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, in igmp6_send()
2048 skb->dev->ifindex); in igmp6_send()
2049 dst = icmp6_dst_alloc(skb->dev, &fl6); in igmp6_send()
2057 net, sk, skb, NULL, skb->dev, in igmp6_send()
2084 read_lock_bh(&idev->lock); in mld_send_initial_cr()
2085 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in mld_send_initial_cr()
2086 spin_lock_bh(&pmc->mca_lock); in mld_send_initial_cr()
2087 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_initial_cr()
2092 spin_unlock_bh(&pmc->mca_lock); in mld_send_initial_cr()
2094 read_unlock_bh(&idev->lock); in mld_send_initial_cr()
2101 idev->mc_dad_count = idev->mc_qrv; in ipv6_mc_dad_complete()
2102 if (idev->mc_dad_count) { in ipv6_mc_dad_complete()
2104 idev->mc_dad_count--; in ipv6_mc_dad_complete()
2105 if (idev->mc_dad_count) in ipv6_mc_dad_complete()
2116 if (idev->mc_dad_count) { in mld_dad_timer_expire()
2117 idev->mc_dad_count--; in mld_dad_timer_expire()
2118 if (idev->mc_dad_count) in mld_dad_timer_expire()
2132 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in ip6_mc_del1_src()
2133 if (ipv6_addr_equal(&psf->sf_addr, psfsrc)) in ip6_mc_del1_src()
2137 if (!psf || psf->sf_count[sfmode] == 0) { in ip6_mc_del1_src()
2139 return -ESRCH; in ip6_mc_del1_src()
2141 psf->sf_count[sfmode]--; in ip6_mc_del1_src()
2142 if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) { in ip6_mc_del1_src()
2143 struct inet6_dev *idev = pmc->idev; in ip6_mc_del1_src()
2147 psf_prev->sf_next = psf->sf_next; in ip6_mc_del1_src()
2149 pmc->mca_sources = psf->sf_next; in ip6_mc_del1_src()
2150 if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) && in ip6_mc_del1_src()
2152 psf->sf_crcount = idev->mc_qrv; in ip6_mc_del1_src()
2153 psf->sf_next = pmc->mca_tomb; in ip6_mc_del1_src()
2154 pmc->mca_tomb = psf; in ip6_mc_del1_src()
2171 return -ENODEV; in ip6_mc_del_src()
2172 read_lock_bh(&idev->lock); in ip6_mc_del_src()
2173 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in ip6_mc_del_src()
2174 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_del_src()
2179 read_unlock_bh(&idev->lock); in ip6_mc_del_src()
2180 return -ESRCH; in ip6_mc_del_src()
2182 spin_lock_bh(&pmc->mca_lock); in ip6_mc_del_src()
2185 if (!pmc->mca_sfcount[sfmode]) { in ip6_mc_del_src()
2186 spin_unlock_bh(&pmc->mca_lock); in ip6_mc_del_src()
2187 read_unlock_bh(&idev->lock); in ip6_mc_del_src()
2188 return -EINVAL; in ip6_mc_del_src()
2190 pmc->mca_sfcount[sfmode]--; in ip6_mc_del_src()
2200 if (pmc->mca_sfmode == MCAST_EXCLUDE && in ip6_mc_del_src()
2201 pmc->mca_sfcount[MCAST_EXCLUDE] == 0 && in ip6_mc_del_src()
2202 pmc->mca_sfcount[MCAST_INCLUDE]) { in ip6_mc_del_src()
2206 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_del_src()
2207 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_del_src()
2208 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_del_src()
2209 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) in ip6_mc_del_src()
2210 psf->sf_crcount = 0; in ip6_mc_del_src()
2211 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2213 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2214 spin_unlock_bh(&pmc->mca_lock); in ip6_mc_del_src()
2215 read_unlock_bh(&idev->lock); in ip6_mc_del_src()
2220 * Add multicast single-source filter to the interface list
2228 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in ip6_mc_add1_src()
2229 if (ipv6_addr_equal(&psf->sf_addr, psfsrc)) in ip6_mc_add1_src()
2236 return -ENOBUFS; in ip6_mc_add1_src()
2238 psf->sf_addr = *psfsrc; in ip6_mc_add1_src()
2240 psf_prev->sf_next = psf; in ip6_mc_add1_src()
2242 pmc->mca_sources = psf; in ip6_mc_add1_src()
2244 psf->sf_count[sfmode]++; in ip6_mc_add1_src()
2251 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_markstate()
2253 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) in sf_markstate()
2254 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_markstate()
2255 psf->sf_oldin = mca_xcount == in sf_markstate()
2256 psf->sf_count[MCAST_EXCLUDE] && in sf_markstate()
2257 !psf->sf_count[MCAST_INCLUDE]; in sf_markstate()
2259 psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0; in sf_markstate()
2265 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_setstate()
2266 int qrv = pmc->idev->mc_qrv; in sf_setstate()
2270 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) { in sf_setstate()
2271 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_setstate()
2272 new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] && in sf_setstate()
2273 !psf->sf_count[MCAST_INCLUDE]; in sf_setstate()
2275 new_in = psf->sf_count[MCAST_INCLUDE] != 0; in sf_setstate()
2277 if (!psf->sf_oldin) { in sf_setstate()
2280 for (dpsf = pmc->mca_tomb; dpsf; in sf_setstate()
2281 dpsf = dpsf->sf_next) { in sf_setstate()
2282 if (ipv6_addr_equal(&dpsf->sf_addr, in sf_setstate()
2283 &psf->sf_addr)) in sf_setstate()
2289 prev->sf_next = dpsf->sf_next; in sf_setstate()
2291 pmc->mca_tomb = dpsf->sf_next; in sf_setstate()
2294 psf->sf_crcount = qrv; in sf_setstate()
2297 } else if (psf->sf_oldin) { in sf_setstate()
2298 psf->sf_crcount = 0; in sf_setstate()
2303 for (dpsf = pmc->mca_tomb; dpsf; dpsf = dpsf->sf_next) in sf_setstate()
2304 if (ipv6_addr_equal(&dpsf->sf_addr, in sf_setstate()
2305 &psf->sf_addr)) in sf_setstate()
2312 /* pmc->mca_lock held by callers */ in sf_setstate()
2313 dpsf->sf_next = pmc->mca_tomb; in sf_setstate()
2314 pmc->mca_tomb = dpsf; in sf_setstate()
2316 dpsf->sf_crcount = qrv; in sf_setstate()
2335 return -ENODEV; in ip6_mc_add_src()
2336 read_lock_bh(&idev->lock); in ip6_mc_add_src()
2337 for (pmc = idev->mc_list; pmc; pmc = pmc->next) { in ip6_mc_add_src()
2338 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_add_src()
2343 read_unlock_bh(&idev->lock); in ip6_mc_add_src()
2344 return -ESRCH; in ip6_mc_add_src()
2346 spin_lock_bh(&pmc->mca_lock); in ip6_mc_add_src()
2349 isexclude = pmc->mca_sfmode == MCAST_EXCLUDE; in ip6_mc_add_src()
2351 pmc->mca_sfcount[sfmode]++; in ip6_mc_add_src()
2362 pmc->mca_sfcount[sfmode]--; in ip6_mc_add_src()
2365 } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { in ip6_mc_add_src()
2369 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in ip6_mc_add_src()
2370 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_add_src()
2371 else if (pmc->mca_sfcount[MCAST_INCLUDE]) in ip6_mc_add_src()
2372 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_add_src()
2375 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_add_src()
2376 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_add_src()
2377 for (psf = pmc->mca_sources; psf; psf = psf->sf_next) in ip6_mc_add_src()
2378 psf->sf_crcount = 0; in ip6_mc_add_src()
2382 spin_unlock_bh(&pmc->mca_lock); in ip6_mc_add_src()
2383 read_unlock_bh(&idev->lock); in ip6_mc_add_src()
2391 for (psf = pmc->mca_tomb; psf; psf = nextpsf) { in ip6_mc_clear_src()
2392 nextpsf = psf->sf_next; in ip6_mc_clear_src()
2395 pmc->mca_tomb = NULL; in ip6_mc_clear_src()
2396 for (psf = pmc->mca_sources; psf; psf = nextpsf) { in ip6_mc_clear_src()
2397 nextpsf = psf->sf_next; in ip6_mc_clear_src()
2400 pmc->mca_sources = NULL; in ip6_mc_clear_src()
2401 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_clear_src()
2402 pmc->mca_sfcount[MCAST_INCLUDE] = 0; in ip6_mc_clear_src()
2403 pmc->mca_sfcount[MCAST_EXCLUDE] = 1; in ip6_mc_clear_src()
2411 if (ma->mca_flags & MAF_NOREPORT) in igmp6_join_group()
2414 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); in igmp6_join_group()
2416 delay = prandom_u32() % unsolicited_report_interval(ma->idev); in igmp6_join_group()
2418 spin_lock_bh(&ma->mca_lock); in igmp6_join_group()
2419 if (del_timer(&ma->mca_timer)) { in igmp6_join_group()
2420 refcount_dec(&ma->mca_refcnt); in igmp6_join_group()
2421 delay = ma->mca_timer.expires - jiffies; in igmp6_join_group()
2424 if (!mod_timer(&ma->mca_timer, jiffies + delay)) in igmp6_join_group()
2425 refcount_inc(&ma->mca_refcnt); in igmp6_join_group()
2426 ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER; in igmp6_join_group()
2427 spin_unlock_bh(&ma->mca_lock); in igmp6_join_group()
2435 write_lock_bh(&iml->sflock); in ip6_mc_leave_src()
2436 if (!iml->sflist) { in ip6_mc_leave_src()
2437 /* any-source empty exclude case */ in ip6_mc_leave_src()
2438 err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, 0, NULL, 0); in ip6_mc_leave_src()
2440 err = ip6_mc_del_src(idev, &iml->addr, iml->sfmode, in ip6_mc_leave_src()
2441 iml->sflist->sl_count, iml->sflist->sl_addr, 0); in ip6_mc_leave_src()
2442 sock_kfree_s(sk, iml->sflist, IP6_SFLSIZE(iml->sflist->sl_max)); in ip6_mc_leave_src()
2443 iml->sflist = NULL; in ip6_mc_leave_src()
2445 write_unlock_bh(&iml->sflock); in ip6_mc_leave_src()
2451 if (mld_in_v1_mode(ma->idev)) { in igmp6_leave_group()
2452 if (ma->mca_flags & MAF_LAST_REPORTER) in igmp6_leave_group()
2453 igmp6_send(&ma->mca_addr, ma->idev->dev, in igmp6_leave_group()
2456 mld_add_delrec(ma->idev, ma); in igmp6_leave_group()
2457 mld_ifc_event(ma->idev); in igmp6_leave_group()
2465 idev->mc_gq_running = 0; in mld_gq_timer_expire()
2475 if (idev->mc_ifc_count) { in mld_ifc_timer_expire()
2476 idev->mc_ifc_count--; in mld_ifc_timer_expire()
2477 if (idev->mc_ifc_count) in mld_ifc_timer_expire()
2488 idev->mc_ifc_count = idev->mc_qrv; in mld_ifc_event()
2496 if (mld_in_v1_mode(ma->idev)) in igmp6_timer_handler()
2497 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); in igmp6_timer_handler()
2499 mld_send_report(ma->idev, ma); in igmp6_timer_handler()
2501 spin_lock(&ma->mca_lock); in igmp6_timer_handler()
2502 ma->mca_flags |= MAF_LAST_REPORTER; in igmp6_timer_handler()
2503 ma->mca_flags &= ~MAF_TIMER_RUNNING; in igmp6_timer_handler()
2504 spin_unlock(&ma->mca_lock); in igmp6_timer_handler()
2514 /* Install multicast list, except for all-nodes (already installed) */ in ipv6_mc_unmap()
2516 read_lock_bh(&idev->lock); in ipv6_mc_unmap()
2517 for (i = idev->mc_list; i; i = i->next) in ipv6_mc_unmap()
2519 read_unlock_bh(&idev->lock); in ipv6_mc_unmap()
2535 read_lock_bh(&idev->lock); in ipv6_mc_down()
2537 for (i = idev->mc_list; i; i = i->next) in ipv6_mc_down()
2546 read_unlock_bh(&idev->lock); in ipv6_mc_down()
2551 idev->mc_qrv = sysctl_mld_qrv; in ipv6_mc_reset()
2552 idev->mc_qi = MLD_QI_DEFAULT; in ipv6_mc_reset()
2553 idev->mc_qri = MLD_QRI_DEFAULT; in ipv6_mc_reset()
2554 idev->mc_v1_seen = 0; in ipv6_mc_reset()
2555 idev->mc_maxdelay = unsolicited_report_interval(idev); in ipv6_mc_reset()
2564 /* Install multicast list, except for all-nodes (already installed) */ in ipv6_mc_up()
2566 read_lock_bh(&idev->lock); in ipv6_mc_up()
2568 for (i = idev->mc_list; i; i = i->next) { in ipv6_mc_up()
2572 read_unlock_bh(&idev->lock); in ipv6_mc_up()
2579 write_lock_bh(&idev->lock); in ipv6_mc_init_dev()
2580 spin_lock_init(&idev->mc_lock); in ipv6_mc_init_dev()
2581 idev->mc_gq_running = 0; in ipv6_mc_init_dev()
2582 timer_setup(&idev->mc_gq_timer, mld_gq_timer_expire, 0); in ipv6_mc_init_dev()
2583 idev->mc_tomb = NULL; in ipv6_mc_init_dev()
2584 idev->mc_ifc_count = 0; in ipv6_mc_init_dev()
2585 timer_setup(&idev->mc_ifc_timer, mld_ifc_timer_expire, 0); in ipv6_mc_init_dev()
2586 timer_setup(&idev->mc_dad_timer, mld_dad_timer_expire, 0); in ipv6_mc_init_dev()
2588 write_unlock_bh(&idev->lock); in ipv6_mc_init_dev()
2603 /* Delete all-nodes address. */ in ipv6_mc_destroy_dev()
2605 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will in ipv6_mc_destroy_dev()
2610 if (idev->cnf.forwarding) in ipv6_mc_destroy_dev()
2613 write_lock_bh(&idev->lock); in ipv6_mc_destroy_dev()
2614 while ((i = idev->mc_list) != NULL) { in ipv6_mc_destroy_dev()
2615 idev->mc_list = i->next; in ipv6_mc_destroy_dev()
2617 write_unlock_bh(&idev->lock); in ipv6_mc_destroy_dev()
2620 write_lock_bh(&idev->lock); in ipv6_mc_destroy_dev()
2622 write_unlock_bh(&idev->lock); in ipv6_mc_destroy_dev()
2632 read_lock_bh(&idev->lock); in ipv6_mc_rejoin_groups()
2633 for (pmc = idev->mc_list; pmc; pmc = pmc->next) in ipv6_mc_rejoin_groups()
2635 read_unlock_bh(&idev->lock); in ipv6_mc_rejoin_groups()
2670 #define igmp6_mc_seq_private(seq) ((struct igmp6_mc_iter_state *)(seq)->private)
2674 struct ifmcaddr6 *im = NULL; in igmp6_mc_get_first() local
2678 state->idev = NULL; in igmp6_mc_get_first()
2679 for_each_netdev_rcu(net, state->dev) { in igmp6_mc_get_first()
2681 idev = __in6_dev_get(state->dev); in igmp6_mc_get_first()
2684 read_lock_bh(&idev->lock); in igmp6_mc_get_first()
2685 im = idev->mc_list; in igmp6_mc_get_first()
2686 if (im) { in igmp6_mc_get_first()
2687 state->idev = idev; in igmp6_mc_get_first()
2690 read_unlock_bh(&idev->lock); in igmp6_mc_get_first()
2692 return im; in igmp6_mc_get_first()
2695 static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im) in igmp6_mc_get_next() argument
2699 im = im->next; in igmp6_mc_get_next()
2700 while (!im) { in igmp6_mc_get_next()
2701 if (likely(state->idev)) in igmp6_mc_get_next()
2702 read_unlock_bh(&state->idev->lock); in igmp6_mc_get_next()
2704 state->dev = next_net_device_rcu(state->dev); in igmp6_mc_get_next()
2705 if (!state->dev) { in igmp6_mc_get_next()
2706 state->idev = NULL; in igmp6_mc_get_next()
2709 state->idev = __in6_dev_get(state->dev); in igmp6_mc_get_next()
2710 if (!state->idev) in igmp6_mc_get_next()
2712 read_lock_bh(&state->idev->lock); in igmp6_mc_get_next()
2713 im = state->idev->mc_list; in igmp6_mc_get_next()
2715 return im; in igmp6_mc_get_next()
2720 struct ifmcaddr6 *im = igmp6_mc_get_first(seq); in igmp6_mc_get_idx() local
2721 if (im) in igmp6_mc_get_idx()
2722 while (pos && (im = igmp6_mc_get_next(seq, im)) != NULL) in igmp6_mc_get_idx()
2723 --pos; in igmp6_mc_get_idx()
2724 return pos ? NULL : im; in igmp6_mc_get_idx()
2736 struct ifmcaddr6 *im = igmp6_mc_get_next(seq, v); in igmp6_mc_seq_next() local
2739 return im; in igmp6_mc_seq_next()
2747 if (likely(state->idev)) { in igmp6_mc_seq_stop()
2748 read_unlock_bh(&state->idev->lock); in igmp6_mc_seq_stop()
2749 state->idev = NULL; in igmp6_mc_seq_stop()
2751 state->dev = NULL; in igmp6_mc_seq_stop()
2757 struct ifmcaddr6 *im = (struct ifmcaddr6 *)v; in igmp6_mc_seq_show() local
2761 "%-4d %-15s %pi6 %5d %08X %ld\n", in igmp6_mc_seq_show()
2762 state->dev->ifindex, state->dev->name, in igmp6_mc_seq_show()
2763 &im->mca_addr, in igmp6_mc_seq_show()
2764 im->mca_users, im->mca_flags, in igmp6_mc_seq_show()
2765 (im->mca_flags&MAF_TIMER_RUNNING) ? in igmp6_mc_seq_show()
2766 jiffies_to_clock_t(im->mca_timer.expires-jiffies) : 0); in igmp6_mc_seq_show()
2781 struct ifmcaddr6 *im; member
2784 #define igmp6_mcf_seq_private(seq) ((struct igmp6_mcf_iter_state *)(seq)->private)
2789 struct ifmcaddr6 *im = NULL; in igmp6_mcf_get_first() local
2793 state->idev = NULL; in igmp6_mcf_get_first()
2794 state->im = NULL; in igmp6_mcf_get_first()
2795 for_each_netdev_rcu(net, state->dev) { in igmp6_mcf_get_first()
2797 idev = __in6_dev_get(state->dev); in igmp6_mcf_get_first()
2800 read_lock_bh(&idev->lock); in igmp6_mcf_get_first()
2801 im = idev->mc_list; in igmp6_mcf_get_first()
2802 if (likely(im)) { in igmp6_mcf_get_first()
2803 spin_lock_bh(&im->mca_lock); in igmp6_mcf_get_first()
2804 psf = im->mca_sources; in igmp6_mcf_get_first()
2806 state->im = im; in igmp6_mcf_get_first()
2807 state->idev = idev; in igmp6_mcf_get_first()
2810 spin_unlock_bh(&im->mca_lock); in igmp6_mcf_get_first()
2812 read_unlock_bh(&idev->lock); in igmp6_mcf_get_first()
2821 psf = psf->sf_next; in igmp6_mcf_get_next()
2823 spin_unlock_bh(&state->im->mca_lock); in igmp6_mcf_get_next()
2824 state->im = state->im->next; in igmp6_mcf_get_next()
2825 while (!state->im) { in igmp6_mcf_get_next()
2826 if (likely(state->idev)) in igmp6_mcf_get_next()
2827 read_unlock_bh(&state->idev->lock); in igmp6_mcf_get_next()
2829 state->dev = next_net_device_rcu(state->dev); in igmp6_mcf_get_next()
2830 if (!state->dev) { in igmp6_mcf_get_next()
2831 state->idev = NULL; in igmp6_mcf_get_next()
2834 state->idev = __in6_dev_get(state->dev); in igmp6_mcf_get_next()
2835 if (!state->idev) in igmp6_mcf_get_next()
2837 read_lock_bh(&state->idev->lock); in igmp6_mcf_get_next()
2838 state->im = state->idev->mc_list; in igmp6_mcf_get_next()
2840 if (!state->im) in igmp6_mcf_get_next()
2842 spin_lock_bh(&state->im->mca_lock); in igmp6_mcf_get_next()
2843 psf = state->im->mca_sources; in igmp6_mcf_get_next()
2854 --pos; in igmp6_mcf_get_idx()
2862 return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in igmp6_mcf_seq_start()
2880 if (likely(state->im)) { in igmp6_mcf_seq_stop()
2881 spin_unlock_bh(&state->im->mca_lock); in igmp6_mcf_seq_stop()
2882 state->im = NULL; in igmp6_mcf_seq_stop()
2884 if (likely(state->idev)) { in igmp6_mcf_seq_stop()
2885 read_unlock_bh(&state->idev->lock); in igmp6_mcf_seq_stop()
2886 state->idev = NULL; in igmp6_mcf_seq_stop()
2888 state->dev = NULL; in igmp6_mcf_seq_stop()
2902 state->dev->ifindex, state->dev->name, in igmp6_mcf_seq_show()
2903 &state->im->mca_addr, in igmp6_mcf_seq_show()
2904 &psf->sf_addr, in igmp6_mcf_seq_show()
2905 psf->sf_count[MCAST_INCLUDE], in igmp6_mcf_seq_show()
2906 psf->sf_count[MCAST_EXCLUDE]); in igmp6_mcf_seq_show()
2922 err = -ENOMEM; in igmp6_proc_init()
2923 if (!proc_create_net("igmp6", 0444, net->proc_net, &igmp6_mc_seq_ops, in igmp6_proc_init()
2926 if (!proc_create_net("mcfilter6", 0444, net->proc_net, in igmp6_proc_init()
2936 remove_proc_entry("igmp6", net->proc_net); in igmp6_proc_init()
2942 remove_proc_entry("mcfilter6", net->proc_net); in igmp6_proc_exit()
2943 remove_proc_entry("igmp6", net->proc_net); in igmp6_proc_exit()
2959 err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6, in igmp6_net_init()
2967 inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1; in igmp6_net_init()
2969 err = inet_ctl_sock_create(&net->ipv6.mc_autojoin_sk, PF_INET6, in igmp6_net_init()
2984 inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk); in igmp6_net_init()
2986 inet_ctl_sock_destroy(net->ipv6.igmp_sk); in igmp6_net_init()
2993 inet_ctl_sock_destroy(net->ipv6.igmp_sk); in igmp6_net_exit()
2994 inet_ctl_sock_destroy(net->ipv6.mc_autojoin_sk); in igmp6_net_exit()