Lines Matching +full:im +full:-

1 // SPDX-License-Identifier: GPL-2.0-or-later
30 * Chih-Jen Chang : Tried to revise IGMP to Version 2
31 * Tsu-Sheng Tsao E-mail: chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
33 * ipmulti-3.5 source code.
34 * Chih-Jen Chang : Added the igmp_get_mrouter_info and
35 * Tsu-Sheng Tsao igmp_set_mrouter_info to keep track of
37 * Chih-Jen Chang : Added the max_resp_time parameter to
38 * Tsu-Sheng Tsao igmp_heard_query(). Using this parameter
41 * Chih-Jen Chang : Added a timer to revert to IGMP V2 router
42 * Tsu-Sheng Tsao if the specified time expired.
53 * igmp_timer_expire if tm->running is
64 * Alexey Kuznetsov: Accordance to igmp-v2-06 draft.
111 /* Parameter names and values are taken from igmp-v2-06 draft */
126 (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
128 ((in_dev)->mr_v1_seen && \
129 time_before(jiffies, (in_dev)->mr_v1_seen)))
131 (IPV4_DEVCONF_ALL_RO(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 2 || \
133 ((in_dev)->mr_v2_seen && \
134 time_before(jiffies, (in_dev)->mr_v2_seen)))
159 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im,
161 static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im);
170 static void ip_ma_put(struct ip_mc_list *im) in ip_ma_put() argument
172 if (refcount_dec_and_test(&im->refcnt)) { in ip_ma_put()
173 in_dev_put(im->interface); in ip_ma_put()
174 kfree_rcu(im, rcu); in ip_ma_put()
179 for (pmc = rcu_dereference(in_dev->mc_list); \
181 pmc = rcu_dereference(pmc->next_rcu))
184 for (pmc = rtnl_dereference(in_dev->mc_list); \
186 pmc = rtnl_dereference(pmc->next_rcu))
193 next = psf->sf_next; in ip_sf_list_clear_all()
205 static void igmp_stop_timer(struct ip_mc_list *im) in igmp_stop_timer() argument
207 spin_lock_bh(&im->lock); in igmp_stop_timer()
208 if (timer_delete(&im->timer)) in igmp_stop_timer()
209 refcount_dec(&im->refcnt); in igmp_stop_timer()
210 im->tm_running = 0; in igmp_stop_timer()
211 im->reporter = 0; in igmp_stop_timer()
212 im->unsolicit_count = 0; in igmp_stop_timer()
213 spin_unlock_bh(&im->lock); in igmp_stop_timer()
216 /* It must be called with locked im->lock */
217 static void igmp_start_timer(struct ip_mc_list *im, int max_delay) in igmp_start_timer() argument
221 im->tm_running = 1; in igmp_start_timer()
222 if (refcount_inc_not_zero(&im->refcnt)) { in igmp_start_timer()
223 if (mod_timer(&im->timer, jiffies + tv + 2)) in igmp_start_timer()
224 ip_ma_put(im); in igmp_start_timer()
230 int tv = get_random_u32_below(in_dev->mr_maxdelay); in igmp_gq_start_timer()
233 if (in_dev->mr_gq_running && in igmp_gq_start_timer()
234 time_after_eq(exp, (in_dev->mr_gq_timer).expires)) in igmp_gq_start_timer()
237 in_dev->mr_gq_running = 1; in igmp_gq_start_timer()
238 if (!mod_timer(&in_dev->mr_gq_timer, exp)) in igmp_gq_start_timer()
246 if (!mod_timer(&in_dev->mr_ifc_timer, jiffies+tv+2)) in igmp_ifc_start_timer()
250 static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) in igmp_mod_timer() argument
252 spin_lock_bh(&im->lock); in igmp_mod_timer()
253 im->unsolicit_count = 0; in igmp_mod_timer()
254 if (timer_delete(&im->timer)) { in igmp_mod_timer()
255 if ((long)(im->timer.expires-jiffies) < max_delay) { in igmp_mod_timer()
256 add_timer(&im->timer); in igmp_mod_timer()
257 im->tm_running = 1; in igmp_mod_timer()
258 spin_unlock_bh(&im->lock); in igmp_mod_timer()
261 refcount_dec(&im->refcnt); in igmp_mod_timer()
263 igmp_start_timer(im, max_delay); in igmp_mod_timer()
264 spin_unlock_bh(&im->lock); in igmp_mod_timer()
283 if (!(pmc->gsquery && !psf->sf_gsresp)) { in is_in()
284 if (pmc->sfmode == MCAST_INCLUDE) in is_in()
289 if (psf->sf_count[MCAST_INCLUDE]) in is_in()
291 return pmc->sfcount[MCAST_EXCLUDE] == in is_in()
292 psf->sf_count[MCAST_EXCLUDE]; in is_in()
298 return psf->sf_count[MCAST_INCLUDE] != 0; in is_in()
302 if (pmc->sfcount[MCAST_EXCLUDE] == 0 || in is_in()
303 psf->sf_count[MCAST_INCLUDE]) in is_in()
305 return pmc->sfcount[MCAST_EXCLUDE] == in is_in()
306 psf->sf_count[MCAST_EXCLUDE]; in is_in()
308 if (gdeleted || !psf->sf_crcount) in is_in()
310 return (pmc->sfmode == MCAST_INCLUDE) ^ sdeleted; in is_in()
312 if (pmc->sfmode == MCAST_INCLUDE) in is_in()
313 return gdeleted || (psf->sf_crcount && sdeleted); in is_in()
314 return psf->sf_crcount && !gdeleted && !sdeleted; in is_in()
325 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_scount()
344 if (fl4->saddr == ifa->ifa_local) in igmpv3_get_srcaddr()
345 return fl4->saddr; in igmpv3_get_srcaddr()
360 int tlen = dev->needed_tailroom; in igmpv3_newpack()
373 skb->priority = TC_PRIO_CONTROL; in igmpv3_newpack()
377 IPPROTO_IGMP, 0, dev->ifindex); in igmpv3_newpack()
383 skb_dst_set(skb, &rt->dst); in igmpv3_newpack()
384 skb->dev = dev; in igmpv3_newpack()
393 pip->version = 4; in igmpv3_newpack()
394 pip->ihl = (sizeof(struct iphdr)+4)>>2; in igmpv3_newpack()
395 pip->tos = 0xc0; in igmpv3_newpack()
396 pip->frag_off = htons(IP_DF); in igmpv3_newpack()
397 pip->ttl = 1; in igmpv3_newpack()
398 pip->daddr = fl4.daddr; in igmpv3_newpack()
401 pip->saddr = igmpv3_get_srcaddr(dev, &fl4); in igmpv3_newpack()
404 pip->protocol = IPPROTO_IGMP; in igmpv3_newpack()
405 pip->tot_len = 0; /* filled in later */ in igmpv3_newpack()
412 skb->transport_header = skb->network_header + sizeof(struct iphdr) + 4; in igmpv3_newpack()
415 pig->type = IGMPV3_HOST_MEMBERSHIP_REPORT; in igmpv3_newpack()
416 pig->resv1 = 0; in igmpv3_newpack()
417 pig->csum = 0; in igmpv3_newpack()
418 pig->resv2 = 0; in igmpv3_newpack()
419 pig->ngrec = 0; in igmpv3_newpack()
426 const int igmplen = skb_tail_pointer(skb) - skb_transport_header(skb); in igmpv3_sendpack()
428 pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen); in igmpv3_sendpack()
430 return ip_local_out(skb_dst_dev_net(skb), skb->sk, skb); in igmpv3_sendpack()
441 struct net_device *dev = pmc->interface->dev; in add_grhead()
451 pgr->grec_type = type; in add_grhead()
452 pgr->grec_auxwords = 0; in add_grhead()
453 pgr->grec_nsrcs = 0; in add_grhead()
454 pgr->grec_mca = pmc->multiaddr; in add_grhead()
456 pih->ngrec = htons(ntohs(pih->ngrec)+1); in add_grhead()
466 struct net_device *dev = pmc->interface->dev; in add_grec()
474 if (pmc->multiaddr == IGMP_ALL_HOSTS) in add_grec()
476 if (ipv4_is_local_multicast(pmc->multiaddr) && in add_grec()
477 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in add_grec()
480 mtu = READ_ONCE(dev->mtu); in add_grec()
491 psf_list = sdeleted ? &pmc->tomb : &pmc->sources; in add_grec()
500 if (pih && pih->ngrec && in add_grec()
512 psf_next = psf->sf_next; in add_grec()
519 /* Based on RFC3376 5.1. Should not send source-list change in add_grec()
522 if (((gdeleted && pmc->sfmode == MCAST_EXCLUDE) || in add_grec()
523 (!gdeleted && pmc->crcount)) && in add_grec()
525 type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) in add_grec()
530 psf->sf_gsresp = 0; in add_grec()
537 pgr->grec_nsrcs = htons(scount); in add_grec()
551 *psrc = psf->sf_inaddr; in add_grec()
554 type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) { in add_grec()
556 psf->sf_crcount--; in add_grec()
557 if ((sdeleted || gdeleted) && psf->sf_crcount == 0) { in add_grec()
559 psf_prev->sf_next = psf->sf_next; in add_grec()
561 *psf_list = psf->sf_next; in add_grec()
574 if (pmc->crcount || isquery) { in add_grec()
584 pgr->grec_nsrcs = htons(scount); in add_grec()
587 pmc->gsquery = 0; /* clear query state on report */ in add_grec()
594 struct net *net = dev_net(in_dev->dev); in igmpv3_send_report()
600 if (pmc->multiaddr == IGMP_ALL_HOSTS) in igmpv3_send_report()
602 if (ipv4_is_local_multicast(pmc->multiaddr) && in igmpv3_send_report()
603 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in igmpv3_send_report()
605 spin_lock_bh(&pmc->lock); in igmpv3_send_report()
606 if (pmc->sfcount[MCAST_EXCLUDE]) in igmpv3_send_report()
611 spin_unlock_bh(&pmc->lock); in igmpv3_send_report()
615 spin_lock_bh(&pmc->lock); in igmpv3_send_report()
616 if (pmc->sfcount[MCAST_EXCLUDE]) in igmpv3_send_report()
621 spin_unlock_bh(&pmc->lock); in igmpv3_send_report()
629 * remove zero-count source records from a source filter list
637 psf_next = psf->sf_next; in igmpv3_clear_zeros()
638 if (psf->sf_crcount == 0) { in igmpv3_clear_zeros()
640 psf_prev->sf_next = psf->sf_next; in igmpv3_clear_zeros()
642 *ppsf = psf->sf_next; in igmpv3_clear_zeros()
651 ip_sf_list_clear_all(pmc->sources); in kfree_pmc()
652 ip_sf_list_clear_all(pmc->tomb); in kfree_pmc()
663 spin_lock_bh(&in_dev->mc_tomb_lock); in igmpv3_send_cr()
667 for (pmc = in_dev->mc_tomb; pmc; pmc = pmc_next) { in igmpv3_send_cr()
668 pmc_next = pmc->next; in igmpv3_send_cr()
669 if (pmc->sfmode == MCAST_INCLUDE) { in igmpv3_send_cr()
675 if (pmc->crcount) { in igmpv3_send_cr()
676 if (pmc->sfmode == MCAST_EXCLUDE) { in igmpv3_send_cr()
680 pmc->crcount--; in igmpv3_send_cr()
681 if (pmc->crcount == 0) { in igmpv3_send_cr()
682 igmpv3_clear_zeros(&pmc->tomb); in igmpv3_send_cr()
683 igmpv3_clear_zeros(&pmc->sources); in igmpv3_send_cr()
686 if (pmc->crcount == 0 && !pmc->tomb && !pmc->sources) { in igmpv3_send_cr()
688 pmc_prev->next = pmc_next; in igmpv3_send_cr()
690 in_dev->mc_tomb = pmc_next; in igmpv3_send_cr()
691 in_dev_put(pmc->interface); in igmpv3_send_cr()
696 spin_unlock_bh(&in_dev->mc_tomb_lock); in igmpv3_send_cr()
700 spin_lock_bh(&pmc->lock); in igmpv3_send_cr()
701 if (pmc->sfcount[MCAST_EXCLUDE]) { in igmpv3_send_cr()
712 if (pmc->crcount) { in igmpv3_send_cr()
713 if (pmc->sfmode == MCAST_EXCLUDE) in igmpv3_send_cr()
718 pmc->crcount--; in igmpv3_send_cr()
720 spin_unlock_bh(&pmc->lock); in igmpv3_send_cr()
736 struct net_device *dev = in_dev->dev; in igmp_send_report()
738 __be32 group = pmc ? pmc->multiaddr : 0; in igmp_send_report()
747 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in igmp_send_report()
757 IPPROTO_IGMP, 0, dev->ifindex); in igmp_send_report()
759 return -1; in igmp_send_report()
762 tlen = dev->needed_tailroom; in igmp_send_report()
766 return -1; in igmp_send_report()
768 skb->priority = TC_PRIO_CONTROL; in igmp_send_report()
770 skb_dst_set(skb, &rt->dst); in igmp_send_report()
778 iph->version = 4; in igmp_send_report()
779 iph->ihl = (sizeof(struct iphdr)+4)>>2; in igmp_send_report()
780 iph->tos = 0xc0; in igmp_send_report()
781 iph->frag_off = htons(IP_DF); in igmp_send_report()
782 iph->ttl = 1; in igmp_send_report()
783 iph->daddr = dst; in igmp_send_report()
784 iph->saddr = fl4.saddr; in igmp_send_report()
785 iph->protocol = IPPROTO_IGMP; in igmp_send_report()
793 ih->type = type; in igmp_send_report()
794 ih->code = 0; in igmp_send_report()
795 ih->csum = 0; in igmp_send_report()
796 ih->group = group; in igmp_send_report()
797 ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr)); in igmp_send_report()
799 return ip_local_out(net, skb->sk, skb); in igmp_send_report()
806 in_dev->mr_gq_running = 0; in igmp_gq_timer_expire()
818 mr_ifc_count = READ_ONCE(in_dev->mr_ifc_count); in igmp_ifc_timer_expire()
821 if (cmpxchg(&in_dev->mr_ifc_count, in igmp_ifc_timer_expire()
823 mr_ifc_count - 1) != mr_ifc_count) in igmp_ifc_timer_expire()
833 struct net *net = dev_net(in_dev->dev); in igmp_ifc_event()
836 WRITE_ONCE(in_dev->mr_ifc_count, in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv)); in igmp_ifc_event()
843 struct ip_mc_list *im = timer_container_of(im, t, timer); in igmp_timer_expire() local
844 struct in_device *in_dev = im->interface; in igmp_timer_expire()
846 spin_lock(&im->lock); in igmp_timer_expire()
847 im->tm_running = 0; in igmp_timer_expire()
849 if (im->unsolicit_count && --im->unsolicit_count) in igmp_timer_expire()
850 igmp_start_timer(im, unsolicited_report_interval(in_dev)); in igmp_timer_expire()
852 im->reporter = 1; in igmp_timer_expire()
853 spin_unlock(&im->lock); in igmp_timer_expire()
856 igmp_send_report(in_dev, im, IGMP_HOST_MEMBERSHIP_REPORT); in igmp_timer_expire()
858 igmp_send_report(in_dev, im, IGMPV2_HOST_MEMBERSHIP_REPORT); in igmp_timer_expire()
860 igmp_send_report(in_dev, im, IGMPV3_HOST_MEMBERSHIP_REPORT); in igmp_timer_expire()
862 ip_ma_put(im); in igmp_timer_expire()
865 /* mark EXCLUDE-mode sources */
872 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_xmarksources()
877 if (psf->sf_count[MCAST_INCLUDE] || in igmp_xmarksources()
878 pmc->sfcount[MCAST_EXCLUDE] != in igmp_xmarksources()
879 psf->sf_count[MCAST_EXCLUDE]) in igmp_xmarksources()
881 if (srcs[i] == psf->sf_inaddr) { in igmp_xmarksources()
887 pmc->gsquery = 0; in igmp_xmarksources()
898 if (pmc->sfmode == MCAST_EXCLUDE) in igmp_marksources()
901 /* mark INCLUDE-mode sources */ in igmp_marksources()
903 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_marksources()
907 if (srcs[i] == psf->sf_inaddr) { in igmp_marksources()
908 psf->sf_gsresp = 1; in igmp_marksources()
914 pmc->gsquery = 0; in igmp_marksources()
917 pmc->gsquery = 1; in igmp_marksources()
924 struct ip_mc_list *im; in igmp_heard_report() local
925 struct net *net = dev_net(in_dev->dev); in igmp_heard_report()
927 /* Timers are only set for non-local groups */ in igmp_heard_report()
932 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in igmp_heard_report()
936 for_each_pmc_rcu(in_dev, im) { in igmp_heard_report()
937 if (im->multiaddr == group) { in igmp_heard_report()
938 igmp_stop_timer(im); in igmp_heard_report()
952 struct ip_mc_list *im; in igmp_heard_query() local
953 __be32 group = ih->group; in igmp_heard_query()
956 struct net *net = dev_net(in_dev->dev); in igmp_heard_query()
960 if (ih->code == 0) { in igmp_heard_query()
964 in_dev->mr_v1_seen = jiffies + in igmp_heard_query()
965 (in_dev->mr_qrv * in_dev->mr_qi) + in igmp_heard_query()
966 in_dev->mr_qri; in igmp_heard_query()
970 max_delay = ih->code*(HZ/IGMP_TIMER_SCALE); in igmp_heard_query()
971 in_dev->mr_v2_seen = jiffies + in igmp_heard_query()
972 (in_dev->mr_qrv * in_dev->mr_qi) + in igmp_heard_query()
973 in_dev->mr_qri; in igmp_heard_query()
976 WRITE_ONCE(in_dev->mr_ifc_count, 0); in igmp_heard_query()
977 if (timer_delete(&in_dev->mr_ifc_timer)) in igmp_heard_query()
994 max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); in igmp_heard_query()
1002 if (ih3->nsrcs) { in igmp_heard_query()
1004 + ntohs(ih3->nsrcs)*sizeof(__be32))) in igmp_heard_query()
1009 max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); in igmp_heard_query()
1012 in_dev->mr_maxdelay = max_delay; in igmp_heard_query()
1018 in_dev->mr_qrv = ih3->qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmp_heard_query()
1019 in_dev->mr_qi = IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL; in igmp_heard_query()
1025 if (in_dev->mr_qri >= in_dev->mr_qi) in igmp_heard_query()
1026 in_dev->mr_qri = (in_dev->mr_qi/HZ - 1)*HZ; in igmp_heard_query()
1029 if (ih3->nsrcs) in igmp_heard_query()
1034 /* mark sources to include, if group & source-specific */ in igmp_heard_query()
1035 mark = ih3->nsrcs != 0; in igmp_heard_query()
1039 * - Start the timers in all of our membership records in igmp_heard_query()
1043 * - For timers already running check if they need to in igmp_heard_query()
1045 * - Use the igmp->igmp_code field as the maximum in igmp_heard_query()
1049 for_each_pmc_rcu(in_dev, im) { in igmp_heard_query()
1052 if (group && group != im->multiaddr) in igmp_heard_query()
1054 if (im->multiaddr == IGMP_ALL_HOSTS) in igmp_heard_query()
1056 if (ipv4_is_local_multicast(im->multiaddr) && in igmp_heard_query()
1057 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in igmp_heard_query()
1059 spin_lock_bh(&im->lock); in igmp_heard_query()
1060 if (im->tm_running) in igmp_heard_query()
1061 im->gsquery = im->gsquery && mark; in igmp_heard_query()
1063 im->gsquery = mark; in igmp_heard_query()
1064 changed = !im->gsquery || in igmp_heard_query()
1065 igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs); in igmp_heard_query()
1066 spin_unlock_bh(&im->lock); in igmp_heard_query()
1068 igmp_mod_timer(im, max_delay); in igmp_heard_query()
1077 /* This basically follows the spec line by line -- see RFC1112 */ in igmp_rcv()
1079 struct net_device *dev = skb->dev; in igmp_rcv()
1081 int len = skb->len; in igmp_rcv()
1085 dev = dev_get_by_index_rcu(dev_net(dev), IPCB(skb)->iif); in igmp_rcv()
1101 switch (ih->type) { in igmp_rcv()
1111 if (skb->pkt_type == PACKET_MULTICAST || in igmp_rcv()
1112 skb->pkt_type == PACKET_BROADCAST) in igmp_rcv()
1113 dropped = igmp_heard_report(in_dev, ih->group); in igmp_rcv()
1148 struct net_device *dev = in_dev->dev; in ip_mc_filter_add()
1150 /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG. in ip_mc_filter_add()
1154 if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; } in ip_mc_filter_add()
1155 --ANK in ip_mc_filter_add()
1168 struct net_device *dev = in_dev->dev; in ip_mc_filter_del()
1178 static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im, in igmpv3_add_delrec() argument
1182 struct net *net = dev_net(in_dev->dev); in igmpv3_add_delrec()
1188 * non-deleted or query-response MCA's. in igmpv3_add_delrec()
1193 spin_lock_init(&pmc->lock); in igmpv3_add_delrec()
1194 spin_lock_bh(&im->lock); in igmpv3_add_delrec()
1195 pmc->interface = im->interface; in igmpv3_add_delrec()
1197 pmc->multiaddr = im->multiaddr; in igmpv3_add_delrec()
1198 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmpv3_add_delrec()
1199 pmc->sfmode = im->sfmode; in igmpv3_add_delrec()
1200 if (pmc->sfmode == MCAST_INCLUDE) { in igmpv3_add_delrec()
1203 pmc->tomb = im->tomb; in igmpv3_add_delrec()
1204 pmc->sources = im->sources; in igmpv3_add_delrec()
1205 im->tomb = im->sources = NULL; in igmpv3_add_delrec()
1206 for (psf = pmc->sources; psf; psf = psf->sf_next) in igmpv3_add_delrec()
1207 psf->sf_crcount = pmc->crcount; in igmpv3_add_delrec()
1209 spin_unlock_bh(&im->lock); in igmpv3_add_delrec()
1211 spin_lock_bh(&in_dev->mc_tomb_lock); in igmpv3_add_delrec()
1212 pmc->next = in_dev->mc_tomb; in igmpv3_add_delrec()
1213 in_dev->mc_tomb = pmc; in igmpv3_add_delrec()
1214 spin_unlock_bh(&in_dev->mc_tomb_lock); in igmpv3_add_delrec()
1220 static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im) in igmpv3_del_delrec() argument
1224 struct net *net = dev_net(in_dev->dev); in igmpv3_del_delrec()
1225 __be32 multiaddr = im->multiaddr; in igmpv3_del_delrec()
1227 spin_lock_bh(&in_dev->mc_tomb_lock); in igmpv3_del_delrec()
1229 for (pmc = in_dev->mc_tomb; pmc; pmc = pmc->next) { in igmpv3_del_delrec()
1230 if (pmc->multiaddr == multiaddr) in igmpv3_del_delrec()
1236 pmc_prev->next = pmc->next; in igmpv3_del_delrec()
1238 in_dev->mc_tomb = pmc->next; in igmpv3_del_delrec()
1240 spin_unlock_bh(&in_dev->mc_tomb_lock); in igmpv3_del_delrec()
1242 spin_lock_bh(&im->lock); in igmpv3_del_delrec()
1244 im->interface = pmc->interface; in igmpv3_del_delrec()
1245 if (im->sfmode == MCAST_INCLUDE) { in igmpv3_del_delrec()
1246 swap(im->tomb, pmc->tomb); in igmpv3_del_delrec()
1247 swap(im->sources, pmc->sources); in igmpv3_del_delrec()
1248 for (psf = im->sources; psf; psf = psf->sf_next) in igmpv3_del_delrec()
1249 psf->sf_crcount = in_dev->mr_qrv ?: in igmpv3_del_delrec()
1250 READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmpv3_del_delrec()
1252 im->crcount = in_dev->mr_qrv ?: in igmpv3_del_delrec()
1253 READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmpv3_del_delrec()
1255 in_dev_put(pmc->interface); in igmpv3_del_delrec()
1258 spin_unlock_bh(&im->lock); in igmpv3_del_delrec()
1268 spin_lock_bh(&in_dev->mc_tomb_lock); in igmpv3_clear_delrec()
1269 pmc = in_dev->mc_tomb; in igmpv3_clear_delrec()
1270 in_dev->mc_tomb = NULL; in igmpv3_clear_delrec()
1271 spin_unlock_bh(&in_dev->mc_tomb_lock); in igmpv3_clear_delrec()
1274 nextpmc = pmc->next; in igmpv3_clear_delrec()
1276 in_dev_put(pmc->interface); in igmpv3_clear_delrec()
1284 spin_lock_bh(&pmc->lock); in igmpv3_clear_delrec()
1285 psf = pmc->tomb; in igmpv3_clear_delrec()
1286 pmc->tomb = NULL; in igmpv3_clear_delrec()
1287 spin_unlock_bh(&pmc->lock); in igmpv3_clear_delrec()
1294 static void __igmp_group_dropped(struct ip_mc_list *im, gfp_t gfp) in __igmp_group_dropped() argument
1296 struct in_device *in_dev = im->interface; in __igmp_group_dropped()
1298 struct net *net = dev_net(in_dev->dev); in __igmp_group_dropped()
1302 if (im->loaded) { in __igmp_group_dropped()
1303 im->loaded = 0; in __igmp_group_dropped()
1304 ip_mc_filter_del(in_dev, im->multiaddr); in __igmp_group_dropped()
1308 if (im->multiaddr == IGMP_ALL_HOSTS) in __igmp_group_dropped()
1310 if (ipv4_is_local_multicast(im->multiaddr) && in __igmp_group_dropped()
1311 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in __igmp_group_dropped()
1314 reporter = im->reporter; in __igmp_group_dropped()
1315 igmp_stop_timer(im); in __igmp_group_dropped()
1317 if (!in_dev->dead) { in __igmp_group_dropped()
1322 igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE); in __igmp_group_dropped()
1326 igmpv3_add_delrec(in_dev, im, gfp); in __igmp_group_dropped()
1333 static void igmp_group_dropped(struct ip_mc_list *im) in igmp_group_dropped() argument
1335 __igmp_group_dropped(im, GFP_KERNEL); in igmp_group_dropped()
1338 static void igmp_group_added(struct ip_mc_list *im) in igmp_group_added() argument
1340 struct in_device *in_dev = im->interface; in igmp_group_added()
1342 struct net *net = dev_net(in_dev->dev); in igmp_group_added()
1345 if (im->loaded == 0) { in igmp_group_added()
1346 im->loaded = 1; in igmp_group_added()
1347 ip_mc_filter_add(in_dev, im->multiaddr); in igmp_group_added()
1351 if (im->multiaddr == IGMP_ALL_HOSTS) in igmp_group_added()
1353 if (ipv4_is_local_multicast(im->multiaddr) && in igmp_group_added()
1354 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in igmp_group_added()
1357 if (in_dev->dead) in igmp_group_added()
1360 im->unsolicit_count = READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmp_group_added()
1362 spin_lock_bh(&im->lock); in igmp_group_added()
1363 igmp_start_timer(im, IGMP_INITIAL_REPORT_DELAY); in igmp_group_added()
1364 spin_unlock_bh(&im->lock); in igmp_group_added()
1370 * not send filter-mode change record as the mode should be from in igmp_group_added()
1373 if (im->sfmode == MCAST_EXCLUDE) in igmp_group_added()
1374 im->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmp_group_added()
1385 static u32 ip_mc_hash(const struct ip_mc_list *im) in ip_mc_hash() argument
1387 return hash_32((__force u32)im->multiaddr, MC_HASH_SZ_LOG); in ip_mc_hash()
1391 struct ip_mc_list *im) in ip_mc_hash_add() argument
1396 mc_hash = rtnl_dereference(in_dev->mc_hash); in ip_mc_hash_add()
1398 hash = ip_mc_hash(im); in ip_mc_hash_add()
1399 im->next_hash = mc_hash[hash]; in ip_mc_hash_add()
1400 rcu_assign_pointer(mc_hash[hash], im); in ip_mc_hash_add()
1405 if (in_dev->mc_count < 4) in ip_mc_hash_add()
1413 for_each_pmc_rtnl(in_dev, im) { in ip_mc_hash_add()
1414 hash = ip_mc_hash(im); in ip_mc_hash_add()
1415 im->next_hash = mc_hash[hash]; in ip_mc_hash_add()
1416 RCU_INIT_POINTER(mc_hash[hash], im); in ip_mc_hash_add()
1419 rcu_assign_pointer(in_dev->mc_hash, mc_hash); in ip_mc_hash_add()
1423 struct ip_mc_list *im) in ip_mc_hash_remove() argument
1425 struct ip_mc_list __rcu **mc_hash = rtnl_dereference(in_dev->mc_hash); in ip_mc_hash_remove()
1430 mc_hash += ip_mc_hash(im); in ip_mc_hash_remove()
1431 while ((aux = rtnl_dereference(*mc_hash)) != im) in ip_mc_hash_remove()
1432 mc_hash = &aux->next_hash; in ip_mc_hash_remove()
1433 *mc_hash = im->next_hash; in ip_mc_hash_remove()
1437 const struct ip_mc_list *im, in inet_fill_ifmcaddr() argument
1444 nlh = nlmsg_put(skb, args->portid, args->seq, args->event, in inet_fill_ifmcaddr()
1445 sizeof(struct ifaddrmsg), args->flags); in inet_fill_ifmcaddr()
1447 return -EMSGSIZE; in inet_fill_ifmcaddr()
1450 ifm->ifa_family = AF_INET; in inet_fill_ifmcaddr()
1451 ifm->ifa_prefixlen = 32; in inet_fill_ifmcaddr()
1452 ifm->ifa_flags = IFA_F_PERMANENT; in inet_fill_ifmcaddr()
1453 ifm->ifa_scope = RT_SCOPE_UNIVERSE; in inet_fill_ifmcaddr()
1454 ifm->ifa_index = dev->ifindex; in inet_fill_ifmcaddr()
1456 ci.cstamp = (READ_ONCE(im->mca_cstamp) - INITIAL_JIFFIES) * 100UL / HZ; in inet_fill_ifmcaddr()
1461 if (nla_put_in_addr(skb, IFA_MULTICAST, im->multiaddr) < 0 || in inet_fill_ifmcaddr()
1464 return -EMSGSIZE; in inet_fill_ifmcaddr()
1472 const struct ip_mc_list *im, int event) in inet_ifmcaddr_notify() argument
1479 int err = -ENOMEM; in inet_ifmcaddr_notify()
1488 err = inet_fill_ifmcaddr(skb, dev, im, &fillargs); in inet_ifmcaddr_notify()
1490 WARN_ON_ONCE(err == -EMSGSIZE); in inet_ifmcaddr_notify()
1508 struct ip_mc_list *im; in ____ip_mc_inc_group() local
1512 mc_hash = rtnl_dereference(in_dev->mc_hash); in ____ip_mc_inc_group()
1516 for (im = rtnl_dereference(mc_hash[hash]); in ____ip_mc_inc_group()
1517 im; in ____ip_mc_inc_group()
1518 im = rtnl_dereference(im->next_hash)) { in ____ip_mc_inc_group()
1519 if (im->multiaddr == addr) in ____ip_mc_inc_group()
1523 for_each_pmc_rtnl(in_dev, im) { in ____ip_mc_inc_group()
1524 if (im->multiaddr == addr) in ____ip_mc_inc_group()
1529 if (im) { in ____ip_mc_inc_group()
1530 im->users++; in ____ip_mc_inc_group()
1535 im = kzalloc(sizeof(*im), gfp); in ____ip_mc_inc_group()
1536 if (!im) in ____ip_mc_inc_group()
1539 im->users = 1; in ____ip_mc_inc_group()
1540 im->interface = in_dev; in ____ip_mc_inc_group()
1542 im->multiaddr = addr; in ____ip_mc_inc_group()
1543 im->mca_cstamp = jiffies; in ____ip_mc_inc_group()
1544 im->mca_tstamp = im->mca_cstamp; in ____ip_mc_inc_group()
1546 im->sfmode = mode; in ____ip_mc_inc_group()
1547 im->sfcount[mode] = 1; in ____ip_mc_inc_group()
1548 refcount_set(&im->refcnt, 1); in ____ip_mc_inc_group()
1549 spin_lock_init(&im->lock); in ____ip_mc_inc_group()
1551 timer_setup(&im->timer, igmp_timer_expire, 0); in ____ip_mc_inc_group()
1554 im->next_rcu = in_dev->mc_list; in ____ip_mc_inc_group()
1555 in_dev->mc_count++; in ____ip_mc_inc_group()
1556 rcu_assign_pointer(in_dev->mc_list, im); in ____ip_mc_inc_group()
1558 ip_mc_hash_add(in_dev, im); in ____ip_mc_inc_group()
1561 igmpv3_del_delrec(in_dev, im); in ____ip_mc_inc_group()
1563 igmp_group_added(im); in ____ip_mc_inc_group()
1564 inet_ifmcaddr_notify(in_dev->dev, im, RTM_NEWMULTICAST); in ____ip_mc_inc_group()
1565 if (!in_dev->dead) in ____ip_mc_inc_group()
1590 return -EINVAL; in ip_mc_check_iphdr()
1594 if (iph->version != 4 || ip_hdrlen(skb) < sizeof(*iph)) in ip_mc_check_iphdr()
1595 return -EINVAL; in ip_mc_check_iphdr()
1597 offset += ip_hdrlen(skb) - sizeof(*iph); in ip_mc_check_iphdr()
1600 return -EINVAL; in ip_mc_check_iphdr()
1604 if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) in ip_mc_check_iphdr()
1605 return -EINVAL; in ip_mc_check_iphdr()
1607 len = skb_network_offset(skb) + ntohs(iph->tot_len); in ip_mc_check_iphdr()
1608 if (skb->len < len || len < offset) in ip_mc_check_iphdr()
1609 return -EINVAL; in ip_mc_check_iphdr()
1622 return ip_mc_may_pull(skb, len) ? 0 : -EINVAL; in ip_mc_check_igmp_reportv3()
1634 return -EINVAL; in ip_mc_check_igmp_query()
1638 return -EINVAL; in ip_mc_check_igmp_query()
1642 * all-systems destination addresses (224.0.0.1) for general queries in ip_mc_check_igmp_query()
1644 if (!igmp_hdr(skb)->group && in ip_mc_check_igmp_query()
1645 ip_hdr(skb)->daddr != htonl(INADDR_ALLHOSTS_GROUP)) in ip_mc_check_igmp_query()
1646 return -EINVAL; in ip_mc_check_igmp_query()
1653 switch (igmp_hdr(skb)->type) { in ip_mc_check_igmp_msg()
1663 return -ENOMSG; in ip_mc_check_igmp_msg()
1679 return -EINVAL; in ip_mc_check_igmp_csum()
1684 return -EINVAL; in ip_mc_check_igmp_csum()
1693 * ip_mc_check_igmp - checks whether this is a sane IGMP packet
1699 * -EINVAL: A broken packet was detected, i.e. it violates some internet
1701 * -ENOMSG: IP header validation succeeded but it is not an IGMP packet.
1702 * -ENOMEM: A memory allocation failure happened.
1714 if (ip_hdr(skb)->protocol != IPPROTO_IGMP) in ip_mc_check_igmp()
1715 return -ENOMSG; in ip_mc_check_igmp()
1731 struct ip_mc_list *im; in ip_mc_rejoin_groups() local
1733 struct net *net = dev_net(in_dev->dev); in ip_mc_rejoin_groups()
1737 for_each_pmc_rtnl(in_dev, im) { in ip_mc_rejoin_groups()
1738 if (im->multiaddr == IGMP_ALL_HOSTS) in ip_mc_rejoin_groups()
1740 if (ipv4_is_local_multicast(im->multiaddr) && in ip_mc_rejoin_groups()
1741 !READ_ONCE(net->ipv4.sysctl_igmp_llm_reports)) in ip_mc_rejoin_groups()
1753 igmp_send_report(in_dev, im, type); in ip_mc_rejoin_groups()
1769 for (ip = &in_dev->mc_list; in __ip_mc_dec_group()
1771 ip = &i->next_rcu) { in __ip_mc_dec_group()
1772 if (i->multiaddr == addr) { in __ip_mc_dec_group()
1773 if (--i->users == 0) { in __ip_mc_dec_group()
1775 *ip = i->next_rcu; in __ip_mc_dec_group()
1776 in_dev->mc_count--; in __ip_mc_dec_group()
1778 inet_ifmcaddr_notify(in_dev->dev, i, in __ip_mc_dec_group()
1782 if (!in_dev->dead) in __ip_mc_dec_group()
1832 WRITE_ONCE(in_dev->mr_ifc_count, 0); in ip_mc_down()
1833 if (timer_delete(&in_dev->mr_ifc_timer)) in ip_mc_down()
1835 in_dev->mr_gq_running = 0; in ip_mc_down()
1836 if (timer_delete(&in_dev->mr_gq_timer)) in ip_mc_down()
1846 struct net *net = dev_net(in_dev->dev); in ip_mc_reset()
1848 in_dev->mr_qi = IGMP_QUERY_INTERVAL; in ip_mc_reset()
1849 in_dev->mr_qri = IGMP_QUERY_RESPONSE_INTERVAL; in ip_mc_reset()
1850 in_dev->mr_qrv = READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_reset()
1863 timer_setup(&in_dev->mr_gq_timer, igmp_gq_timer_expire, 0); in ip_mc_init_dev()
1864 timer_setup(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, 0); in ip_mc_init_dev()
1868 spin_lock_init(&in_dev->mc_tomb_lock); in ip_mc_init_dev()
1906 while ((i = rtnl_dereference(in_dev->mc_list)) != NULL) { in ip_mc_destroy_dev()
1907 in_dev->mc_list = i->next_rcu; in ip_mc_destroy_dev()
1908 in_dev->mc_count--; in ip_mc_destroy_dev()
1920 if (imr->imr_ifindex) { in ip_mc_find_dev()
1921 idev = inetdev_by_index(net, imr->imr_ifindex); in ip_mc_find_dev()
1924 if (imr->imr_address.s_addr) { in ip_mc_find_dev()
1925 dev = __ip_dev_find(net, imr->imr_address.s_addr, false); in ip_mc_find_dev()
1932 imr->imr_multiaddr.s_addr, in ip_mc_find_dev()
1936 dev = rt->dst.dev; in ip_mc_find_dev()
1941 imr->imr_ifindex = dev->ifindex; in ip_mc_find_dev()
1958 for (psf = pmc->sources; psf; psf = psf->sf_next) { in ip_mc_del1_src()
1959 if (psf->sf_inaddr == *psfsrc) in ip_mc_del1_src()
1963 if (!psf || psf->sf_count[sfmode] == 0) { in ip_mc_del1_src()
1965 return -ESRCH; in ip_mc_del1_src()
1967 psf->sf_count[sfmode]--; in ip_mc_del1_src()
1968 if (psf->sf_count[sfmode] == 0) { in ip_mc_del1_src()
1969 ip_rt_multicast_event(pmc->interface); in ip_mc_del1_src()
1971 if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) { in ip_mc_del1_src()
1973 struct in_device *in_dev = pmc->interface; in ip_mc_del1_src()
1974 struct net *net = dev_net(in_dev->dev); in ip_mc_del1_src()
1979 psf_prev->sf_next = psf->sf_next; in ip_mc_del1_src()
1981 pmc->sources = psf->sf_next; in ip_mc_del1_src()
1983 if (psf->sf_oldin && in ip_mc_del1_src()
1985 psf->sf_crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_del1_src()
1986 psf->sf_next = pmc->tomb; in ip_mc_del1_src()
1987 pmc->tomb = psf; in ip_mc_del1_src()
2008 return -ENODEV; in ip_mc_del_src()
2011 if (*pmca == pmc->multiaddr) in ip_mc_del_src()
2017 return -ESRCH; in ip_mc_del_src()
2019 spin_lock_bh(&pmc->lock); in ip_mc_del_src()
2025 err = -EINVAL; in ip_mc_del_src()
2026 if (!pmc->sfcount[sfmode]) in ip_mc_del_src()
2028 pmc->sfcount[sfmode]--; in ip_mc_del_src()
2038 if (pmc->sfmode == MCAST_EXCLUDE && in ip_mc_del_src()
2039 pmc->sfcount[MCAST_EXCLUDE] == 0 && in ip_mc_del_src()
2040 pmc->sfcount[MCAST_INCLUDE]) { in ip_mc_del_src()
2043 struct net *net = dev_net(in_dev->dev); in ip_mc_del_src()
2047 pmc->sfmode = MCAST_INCLUDE; in ip_mc_del_src()
2049 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_del_src()
2050 WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount); in ip_mc_del_src()
2051 for (psf = pmc->sources; psf; psf = psf->sf_next) in ip_mc_del_src()
2052 psf->sf_crcount = 0; in ip_mc_del_src()
2053 igmp_ifc_event(pmc->interface); in ip_mc_del_src()
2055 igmp_ifc_event(pmc->interface); in ip_mc_del_src()
2059 spin_unlock_bh(&pmc->lock); in ip_mc_del_src()
2064 * Add multicast single-source filter to the interface list
2072 for (psf = pmc->sources; psf; psf = psf->sf_next) { in ip_mc_add1_src()
2073 if (psf->sf_inaddr == *psfsrc) in ip_mc_add1_src()
2080 return -ENOBUFS; in ip_mc_add1_src()
2081 psf->sf_inaddr = *psfsrc; in ip_mc_add1_src()
2083 psf_prev->sf_next = psf; in ip_mc_add1_src()
2085 pmc->sources = psf; in ip_mc_add1_src()
2087 psf->sf_count[sfmode]++; in ip_mc_add1_src()
2088 if (psf->sf_count[sfmode] == 1) { in ip_mc_add1_src()
2089 ip_rt_multicast_event(pmc->interface); in ip_mc_add1_src()
2098 int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; in sf_markstate()
2100 for (psf = pmc->sources; psf; psf = psf->sf_next) in sf_markstate()
2101 if (pmc->sfcount[MCAST_EXCLUDE]) { in sf_markstate()
2102 psf->sf_oldin = mca_xcount == in sf_markstate()
2103 psf->sf_count[MCAST_EXCLUDE] && in sf_markstate()
2104 !psf->sf_count[MCAST_INCLUDE]; in sf_markstate()
2106 psf->sf_oldin = psf->sf_count[MCAST_INCLUDE] != 0; in sf_markstate()
2112 int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; in sf_setstate()
2113 int qrv = pmc->interface->mr_qrv; in sf_setstate()
2117 for (psf = pmc->sources; psf; psf = psf->sf_next) { in sf_setstate()
2118 if (pmc->sfcount[MCAST_EXCLUDE]) { in sf_setstate()
2119 new_in = mca_xcount == psf->sf_count[MCAST_EXCLUDE] && in sf_setstate()
2120 !psf->sf_count[MCAST_INCLUDE]; in sf_setstate()
2122 new_in = psf->sf_count[MCAST_INCLUDE] != 0; in sf_setstate()
2124 if (!psf->sf_oldin) { in sf_setstate()
2127 for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) { in sf_setstate()
2128 if (dpsf->sf_inaddr == psf->sf_inaddr) in sf_setstate()
2134 prev->sf_next = dpsf->sf_next; in sf_setstate()
2136 pmc->tomb = dpsf->sf_next; in sf_setstate()
2139 psf->sf_crcount = qrv; in sf_setstate()
2142 } else if (psf->sf_oldin) { in sf_setstate()
2144 psf->sf_crcount = 0; in sf_setstate()
2149 for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) in sf_setstate()
2150 if (dpsf->sf_inaddr == psf->sf_inaddr) in sf_setstate()
2157 /* pmc->lock held by callers */ in sf_setstate()
2158 dpsf->sf_next = pmc->tomb; in sf_setstate()
2159 pmc->tomb = dpsf; in sf_setstate()
2161 dpsf->sf_crcount = qrv; in sf_setstate()
2180 return -ENODEV; in ip_mc_add_src()
2183 if (*pmca == pmc->multiaddr) in ip_mc_add_src()
2189 return -ESRCH; in ip_mc_add_src()
2191 spin_lock_bh(&pmc->lock); in ip_mc_add_src()
2197 isexclude = pmc->sfmode == MCAST_EXCLUDE; in ip_mc_add_src()
2199 pmc->sfcount[sfmode]++; in ip_mc_add_src()
2210 pmc->sfcount[sfmode]--; in ip_mc_add_src()
2213 } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) { in ip_mc_add_src()
2216 struct net *net = dev_net(pmc->interface->dev); in ip_mc_add_src()
2217 in_dev = pmc->interface; in ip_mc_add_src()
2221 if (pmc->sfcount[MCAST_EXCLUDE]) in ip_mc_add_src()
2222 pmc->sfmode = MCAST_EXCLUDE; in ip_mc_add_src()
2223 else if (pmc->sfcount[MCAST_INCLUDE]) in ip_mc_add_src()
2224 pmc->sfmode = MCAST_INCLUDE; in ip_mc_add_src()
2228 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_add_src()
2229 WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount); in ip_mc_add_src()
2230 for (psf = pmc->sources; psf; psf = psf->sf_next) in ip_mc_add_src()
2231 psf->sf_crcount = 0; in ip_mc_add_src()
2237 spin_unlock_bh(&pmc->lock); in ip_mc_add_src()
2245 spin_lock_bh(&pmc->lock); in ip_mc_clear_src()
2246 tomb = pmc->tomb; in ip_mc_clear_src()
2247 pmc->tomb = NULL; in ip_mc_clear_src()
2248 sources = pmc->sources; in ip_mc_clear_src()
2249 pmc->sources = NULL; in ip_mc_clear_src()
2250 pmc->sfmode = MCAST_EXCLUDE; in ip_mc_clear_src()
2251 pmc->sfcount[MCAST_INCLUDE] = 0; in ip_mc_clear_src()
2252 pmc->sfcount[MCAST_EXCLUDE] = 1; in ip_mc_clear_src()
2253 spin_unlock_bh(&pmc->lock); in ip_mc_clear_src()
2264 __be32 addr = imr->imr_multiaddr.s_addr; in __ip_mc_join_group()
2276 return -EINVAL; in __ip_mc_join_group()
2281 err = -ENODEV; in __ip_mc_join_group()
2285 err = -EADDRINUSE; in __ip_mc_join_group()
2286 ifindex = imr->imr_ifindex; in __ip_mc_join_group()
2288 if (i->multi.imr_multiaddr.s_addr == addr && in __ip_mc_join_group()
2289 i->multi.imr_ifindex == ifindex) in __ip_mc_join_group()
2293 err = -ENOBUFS; in __ip_mc_join_group()
2294 if (count >= READ_ONCE(net->ipv4.sysctl_igmp_max_memberships)) in __ip_mc_join_group()
2300 memcpy(&iml->multi, imr, sizeof(*imr)); in __ip_mc_join_group()
2301 iml->next_rcu = inet->mc_list; in __ip_mc_join_group()
2302 iml->sflist = NULL; in __ip_mc_join_group()
2303 iml->sfmode = mode; in __ip_mc_join_group()
2304 rcu_assign_pointer(inet->mc_list, iml); in __ip_mc_join_group()
2311 /* Join ASM (Any-Source Multicast) group
2319 /* Join SSM (Source-Specific Multicast) group
2330 struct ip_sf_socklist *psf = rtnl_dereference(iml->sflist); in ip_mc_leave_src()
2334 /* any-source empty exclude case */ in ip_mc_leave_src()
2335 return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, in ip_mc_leave_src()
2336 iml->sfmode, 0, NULL, 0); in ip_mc_leave_src()
2338 err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, in ip_mc_leave_src()
2339 iml->sfmode, psf->sl_count, psf->sl_addr, 0); in ip_mc_leave_src()
2340 RCU_INIT_POINTER(iml->sflist, NULL); in ip_mc_leave_src()
2342 atomic_sub(struct_size(psf, sl_addr, psf->sl_max), &sk->sk_omem_alloc); in ip_mc_leave_src()
2354 __be32 group = imr->imr_multiaddr.s_addr; in ip_mc_leave_group()
2356 int ret = -EADDRNOTAVAIL; in ip_mc_leave_group()
2361 if (!imr->imr_ifindex && !imr->imr_address.s_addr && !in_dev) { in ip_mc_leave_group()
2362 ret = -ENODEV; in ip_mc_leave_group()
2365 ifindex = imr->imr_ifindex; in ip_mc_leave_group()
2366 for (imlp = &inet->mc_list; in ip_mc_leave_group()
2368 imlp = &iml->next_rcu) { in ip_mc_leave_group()
2369 if (iml->multi.imr_multiaddr.s_addr != group) in ip_mc_leave_group()
2372 if (iml->multi.imr_ifindex != ifindex) in ip_mc_leave_group()
2374 } else if (imr->imr_address.s_addr && imr->imr_address.s_addr != in ip_mc_leave_group()
2375 iml->multi.imr_address.s_addr) in ip_mc_leave_group()
2380 *imlp = iml->next_rcu; in ip_mc_leave_group()
2386 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); in ip_mc_leave_group()
2400 __be32 addr = mreqs->imr_multiaddr; in ip_mc_source()
2410 return -EINVAL; in ip_mc_source()
2414 imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr; in ip_mc_source()
2415 imr.imr_address.s_addr = mreqs->imr_interface; in ip_mc_source()
2420 err = -ENODEV; in ip_mc_source()
2423 err = -EADDRNOTAVAIL; in ip_mc_source()
2426 if ((pmc->multi.imr_multiaddr.s_addr == in ip_mc_source()
2428 (pmc->multi.imr_ifindex == imr.imr_ifindex)) in ip_mc_source()
2432 err = -EINVAL; in ip_mc_source()
2436 if (pmc->sflist) { in ip_mc_source()
2437 if (pmc->sfmode != omode) { in ip_mc_source()
2438 err = -EINVAL; in ip_mc_source()
2441 } else if (pmc->sfmode != omode) { in ip_mc_source()
2442 /* allow mode switches for empty-set filters */ in ip_mc_source()
2443 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0); in ip_mc_source()
2444 ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0, in ip_mc_source()
2446 pmc->sfmode = omode; in ip_mc_source()
2449 psl = rtnl_dereference(pmc->sflist); in ip_mc_source()
2452 goto done; /* err = -EADDRNOTAVAIL */ in ip_mc_source()
2454 for (i = 0; i < psl->sl_count; i++) { in ip_mc_source()
2455 rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, in ip_mc_source()
2461 goto done; /* err = -EADDRNOTAVAIL */ in ip_mc_source()
2463 /* special case - (INCLUDE, empty) == LEAVE_GROUP */ in ip_mc_source()
2464 if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { in ip_mc_source()
2470 ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, in ip_mc_source()
2471 &mreqs->imr_sourceaddr, 1); in ip_mc_source()
2473 for (j = i+1; j < psl->sl_count; j++) in ip_mc_source()
2474 psl->sl_addr[j-1] = psl->sl_addr[j]; in ip_mc_source()
2475 psl->sl_count--; in ip_mc_source()
2481 if (psl && psl->sl_count >= READ_ONCE(net->ipv4.sysctl_igmp_max_msf)) { in ip_mc_source()
2482 err = -ENOBUFS; in ip_mc_source()
2485 if (!psl || psl->sl_count == psl->sl_max) { in ip_mc_source()
2490 count += psl->sl_max; in ip_mc_source()
2494 err = -ENOBUFS; in ip_mc_source()
2497 newpsl->sl_max = count; in ip_mc_source()
2498 newpsl->sl_count = count - IP_SFBLOCK; in ip_mc_source()
2500 for (i = 0; i < psl->sl_count; i++) in ip_mc_source()
2501 newpsl->sl_addr[i] = psl->sl_addr[i]; in ip_mc_source()
2503 atomic_sub(struct_size(psl, sl_addr, psl->sl_max), in ip_mc_source()
2504 &sk->sk_omem_alloc); in ip_mc_source()
2506 rcu_assign_pointer(pmc->sflist, newpsl); in ip_mc_source()
2512 for (i = 0; i < psl->sl_count; i++) { in ip_mc_source()
2513 rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, in ip_mc_source()
2520 for (j = psl->sl_count-1; j >= i; j--) in ip_mc_source()
2521 psl->sl_addr[j+1] = psl->sl_addr[j]; in ip_mc_source()
2522 psl->sl_addr[i] = mreqs->imr_sourceaddr; in ip_mc_source()
2523 psl->sl_count++; in ip_mc_source()
2526 ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1, in ip_mc_source()
2527 &mreqs->imr_sourceaddr, 1); in ip_mc_source()
2538 __be32 addr = msf->imsf_multiaddr; in ip_mc_msfilter()
2547 return -EINVAL; in ip_mc_msfilter()
2548 if (msf->imsf_fmode != MCAST_INCLUDE && in ip_mc_msfilter()
2549 msf->imsf_fmode != MCAST_EXCLUDE) in ip_mc_msfilter()
2550 return -EINVAL; in ip_mc_msfilter()
2554 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; in ip_mc_msfilter()
2555 imr.imr_address.s_addr = msf->imsf_interface; in ip_mc_msfilter()
2560 err = -ENODEV; in ip_mc_msfilter()
2564 /* special case - (INCLUDE, empty) == LEAVE_GROUP */ in ip_mc_msfilter()
2565 if (msf->imsf_fmode == MCAST_INCLUDE && msf->imsf_numsrc == 0) { in ip_mc_msfilter()
2571 if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && in ip_mc_msfilter()
2572 pmc->multi.imr_ifindex == imr.imr_ifindex) in ip_mc_msfilter()
2576 err = -EINVAL; in ip_mc_msfilter()
2579 if (msf->imsf_numsrc) { in ip_mc_msfilter()
2581 msf->imsf_numsrc), in ip_mc_msfilter()
2584 err = -ENOBUFS; in ip_mc_msfilter()
2587 newpsl->sl_max = newpsl->sl_count = msf->imsf_numsrc; in ip_mc_msfilter()
2588 memcpy(newpsl->sl_addr, msf->imsf_slist_flex, in ip_mc_msfilter()
2589 flex_array_size(msf, imsf_slist_flex, msf->imsf_numsrc)); in ip_mc_msfilter()
2590 err = ip_mc_add_src(in_dev, &msf->imsf_multiaddr, in ip_mc_msfilter()
2591 msf->imsf_fmode, newpsl->sl_count, newpsl->sl_addr, 0); in ip_mc_msfilter()
2595 newpsl->sl_max)); in ip_mc_msfilter()
2600 (void) ip_mc_add_src(in_dev, &msf->imsf_multiaddr, in ip_mc_msfilter()
2601 msf->imsf_fmode, 0, NULL, 0); in ip_mc_msfilter()
2603 psl = rtnl_dereference(pmc->sflist); in ip_mc_msfilter()
2605 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, in ip_mc_msfilter()
2606 psl->sl_count, psl->sl_addr, 0); in ip_mc_msfilter()
2608 atomic_sub(struct_size(psl, sl_addr, psl->sl_max), in ip_mc_msfilter()
2609 &sk->sk_omem_alloc); in ip_mc_msfilter()
2611 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, in ip_mc_msfilter()
2614 rcu_assign_pointer(pmc->sflist, newpsl); in ip_mc_msfilter()
2617 pmc->sfmode = msf->imsf_fmode; in ip_mc_msfilter()
2629 __be32 addr = msf->imsf_multiaddr; in ip_mc_msfget()
2639 return -EINVAL; in ip_mc_msfget()
2641 imr.imr_multiaddr.s_addr = msf->imsf_multiaddr; in ip_mc_msfget()
2642 imr.imr_address.s_addr = msf->imsf_interface; in ip_mc_msfget()
2647 err = -ENODEV; in ip_mc_msfget()
2650 err = -EADDRNOTAVAIL; in ip_mc_msfget()
2653 if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && in ip_mc_msfget()
2654 pmc->multi.imr_ifindex == imr.imr_ifindex) in ip_mc_msfget()
2659 msf->imsf_fmode = pmc->sfmode; in ip_mc_msfget()
2660 psl = rtnl_dereference(pmc->sflist); in ip_mc_msfget()
2664 count = psl->sl_count; in ip_mc_msfget()
2666 copycount = count < msf->imsf_numsrc ? count : msf->imsf_numsrc; in ip_mc_msfget()
2668 msf->imsf_numsrc = count; in ip_mc_msfget()
2672 return -EFAULT; in ip_mc_msfget()
2677 psl->sl_addr, len)) in ip_mc_msfget()
2678 return -EFAULT; in ip_mc_msfget()
2696 psin = (struct sockaddr_in *)&gsf->gf_group; in ip_mc_gsfget()
2697 if (psin->sin_family != AF_INET) in ip_mc_gsfget()
2698 return -EINVAL; in ip_mc_gsfget()
2699 addr = psin->sin_addr.s_addr; in ip_mc_gsfget()
2701 return -EINVAL; in ip_mc_gsfget()
2704 if (pmc->multi.imr_multiaddr.s_addr == addr && in ip_mc_gsfget()
2705 pmc->multi.imr_ifindex == gsf->gf_interface) in ip_mc_gsfget()
2709 return -EADDRNOTAVAIL; in ip_mc_gsfget()
2710 gsf->gf_fmode = pmc->sfmode; in ip_mc_gsfget()
2711 psl = rtnl_dereference(pmc->sflist); in ip_mc_gsfget()
2712 count = psl ? psl->sl_count : 0; in ip_mc_gsfget()
2713 copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc; in ip_mc_gsfget()
2714 gsf->gf_numsrc = count; in ip_mc_gsfget()
2720 psin->sin_family = AF_INET; in ip_mc_gsfget()
2721 psin->sin_addr.s_addr = psl->sl_addr[i]; in ip_mc_gsfget()
2724 return -EFAULT; in ip_mc_gsfget()
2748 if (pmc->multi.imr_multiaddr.s_addr == loc_addr && in ip_mc_sf_allow()
2749 (pmc->multi.imr_ifindex == dif || in ip_mc_sf_allow()
2750 (sdif && pmc->multi.imr_ifindex == sdif))) in ip_mc_sf_allow()
2756 psl = rcu_dereference(pmc->sflist); in ip_mc_sf_allow()
2757 ret = (pmc->sfmode == MCAST_EXCLUDE); in ip_mc_sf_allow()
2761 for (i = 0; i < psl->sl_count; i++) { in ip_mc_sf_allow()
2762 if (psl->sl_addr[i] == rmt_addr) in ip_mc_sf_allow()
2766 if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) in ip_mc_sf_allow()
2768 if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) in ip_mc_sf_allow()
2787 if (!inet->mc_list) in ip_mc_drop_socket()
2791 while ((iml = rtnl_dereference(inet->mc_list)) != NULL) { in ip_mc_drop_socket()
2794 inet->mc_list = iml->next_rcu; in ip_mc_drop_socket()
2795 in_dev = inetdev_by_index(net, iml->multi.imr_ifindex); in ip_mc_drop_socket()
2798 ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); in ip_mc_drop_socket()
2800 atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); in ip_mc_drop_socket()
2809 struct ip_mc_list *im; in ip_check_mc_rcu() local
2814 mc_hash = rcu_dereference(in_dev->mc_hash); in ip_check_mc_rcu()
2818 for (im = rcu_dereference(mc_hash[hash]); in ip_check_mc_rcu()
2819 im != NULL; in ip_check_mc_rcu()
2820 im = rcu_dereference(im->next_hash)) { in ip_check_mc_rcu()
2821 if (im->multiaddr == mc_addr) in ip_check_mc_rcu()
2825 for_each_pmc_rcu(in_dev, im) { in ip_check_mc_rcu()
2826 if (im->multiaddr == mc_addr) in ip_check_mc_rcu()
2830 if (im && proto == IPPROTO_IGMP) { in ip_check_mc_rcu()
2832 } else if (im) { in ip_check_mc_rcu()
2834 spin_lock_bh(&im->lock); in ip_check_mc_rcu()
2835 for (psf = im->sources; psf; psf = psf->sf_next) { in ip_check_mc_rcu()
2836 if (psf->sf_inaddr == src_addr) in ip_check_mc_rcu()
2840 rv = psf->sf_count[MCAST_INCLUDE] || in ip_check_mc_rcu()
2841 psf->sf_count[MCAST_EXCLUDE] != in ip_check_mc_rcu()
2842 im->sfcount[MCAST_EXCLUDE]; in ip_check_mc_rcu()
2844 rv = im->sfcount[MCAST_EXCLUDE] != 0; in ip_check_mc_rcu()
2845 spin_unlock_bh(&im->lock); in ip_check_mc_rcu()
2859 #define igmp_mc_seq_private(seq) ((struct igmp_mc_iter_state *)(seq)->private)
2864 struct ip_mc_list *im = NULL; in igmp_mc_get_first() local
2867 state->in_dev = NULL; in igmp_mc_get_first()
2868 for_each_netdev_rcu(net, state->dev) { in igmp_mc_get_first()
2871 in_dev = __in_dev_get_rcu(state->dev); in igmp_mc_get_first()
2874 im = rcu_dereference(in_dev->mc_list); in igmp_mc_get_first()
2875 if (im) { in igmp_mc_get_first()
2876 state->in_dev = in_dev; in igmp_mc_get_first()
2880 return im; in igmp_mc_get_first()
2883 static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_list *im) in igmp_mc_get_next() argument
2887 im = rcu_dereference(im->next_rcu); in igmp_mc_get_next()
2888 while (!im) { in igmp_mc_get_next()
2889 state->dev = next_net_device_rcu(state->dev); in igmp_mc_get_next()
2890 if (!state->dev) { in igmp_mc_get_next()
2891 state->in_dev = NULL; in igmp_mc_get_next()
2894 state->in_dev = __in_dev_get_rcu(state->dev); in igmp_mc_get_next()
2895 if (!state->in_dev) in igmp_mc_get_next()
2897 im = rcu_dereference(state->in_dev->mc_list); in igmp_mc_get_next()
2899 return im; in igmp_mc_get_next()
2904 struct ip_mc_list *im = igmp_mc_get_first(seq); in igmp_mc_get_idx() local
2905 if (im) in igmp_mc_get_idx()
2906 while (pos && (im = igmp_mc_get_next(seq, im)) != NULL) in igmp_mc_get_idx()
2907 --pos; in igmp_mc_get_idx()
2908 return pos ? NULL : im; in igmp_mc_get_idx()
2915 return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in igmp_mc_seq_start()
2920 struct ip_mc_list *im; in igmp_mc_seq_next() local
2922 im = igmp_mc_get_first(seq); in igmp_mc_seq_next()
2924 im = igmp_mc_get_next(seq, v); in igmp_mc_seq_next()
2926 return im; in igmp_mc_seq_next()
2934 state->in_dev = NULL; in igmp_mc_seq_stop()
2935 state->dev = NULL; in igmp_mc_seq_stop()
2945 struct ip_mc_list *im = v; in igmp_mc_seq_show() local
2951 querier = IGMP_V1_SEEN(state->in_dev) ? "V1" : in igmp_mc_seq_show()
2952 IGMP_V2_SEEN(state->in_dev) ? "V2" : in igmp_mc_seq_show()
2958 if (rcu_access_pointer(state->in_dev->mc_list) == im) { in igmp_mc_seq_show()
2959 seq_printf(seq, "%d\t%-10s: %5d %7s\n", in igmp_mc_seq_show()
2960 state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier); in igmp_mc_seq_show()
2963 delta = im->timer.expires - jiffies; in igmp_mc_seq_show()
2966 im->multiaddr, im->users, in igmp_mc_seq_show()
2967 im->tm_running, in igmp_mc_seq_show()
2968 im->tm_running ? jiffies_delta_to_clock_t(delta) : 0, in igmp_mc_seq_show()
2969 im->reporter); in igmp_mc_seq_show()
2985 struct ip_mc_list *im; member
2988 #define igmp_mcf_seq_private(seq) ((struct igmp_mcf_iter_state *)(seq)->private)
2994 struct ip_mc_list *im = NULL; in igmp_mcf_get_first() local
2997 state->idev = NULL; in igmp_mcf_get_first()
2998 state->im = NULL; in igmp_mcf_get_first()
2999 for_each_netdev_rcu(net, state->dev) { in igmp_mcf_get_first()
3001 idev = __in_dev_get_rcu(state->dev); in igmp_mcf_get_first()
3004 im = rcu_dereference(idev->mc_list); in igmp_mcf_get_first()
3005 if (likely(im)) { in igmp_mcf_get_first()
3006 spin_lock_bh(&im->lock); in igmp_mcf_get_first()
3007 psf = im->sources; in igmp_mcf_get_first()
3009 state->im = im; in igmp_mcf_get_first()
3010 state->idev = idev; in igmp_mcf_get_first()
3013 spin_unlock_bh(&im->lock); in igmp_mcf_get_first()
3023 psf = psf->sf_next; in igmp_mcf_get_next()
3025 spin_unlock_bh(&state->im->lock); in igmp_mcf_get_next()
3026 state->im = state->im->next; in igmp_mcf_get_next()
3027 while (!state->im) { in igmp_mcf_get_next()
3028 state->dev = next_net_device_rcu(state->dev); in igmp_mcf_get_next()
3029 if (!state->dev) { in igmp_mcf_get_next()
3030 state->idev = NULL; in igmp_mcf_get_next()
3033 state->idev = __in_dev_get_rcu(state->dev); in igmp_mcf_get_next()
3034 if (!state->idev) in igmp_mcf_get_next()
3036 state->im = rcu_dereference(state->idev->mc_list); in igmp_mcf_get_next()
3038 spin_lock_bh(&state->im->lock); in igmp_mcf_get_next()
3039 psf = state->im->sources; in igmp_mcf_get_next()
3050 --pos; in igmp_mcf_get_idx()
3058 return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in igmp_mcf_seq_start()
3076 if (likely(state->im)) { in igmp_mcf_seq_stop()
3077 spin_unlock_bh(&state->im->lock); in igmp_mcf_seq_stop()
3078 state->im = NULL; in igmp_mcf_seq_stop()
3080 state->idev = NULL; in igmp_mcf_seq_stop()
3081 state->dev = NULL; in igmp_mcf_seq_stop()
3096 state->dev->ifindex, state->dev->name, in igmp_mcf_seq_show()
3097 ntohl(state->im->multiaddr), in igmp_mcf_seq_show()
3098 ntohl(psf->sf_inaddr), in igmp_mcf_seq_show()
3099 psf->sf_count[MCAST_INCLUDE], in igmp_mcf_seq_show()
3100 psf->sf_count[MCAST_EXCLUDE]); in igmp_mcf_seq_show()
3117 pde = proc_create_net("igmp", 0444, net->proc_net, &igmp_mc_seq_ops, in igmp_net_init()
3121 pde = proc_create_net("mcfilter", 0444, net->proc_net, in igmp_net_init()
3125 err = inet_ctl_sock_create(&net->ipv4.mc_autojoin_sk, AF_INET, in igmp_net_init()
3136 remove_proc_entry("mcfilter", net->proc_net); in igmp_net_init()
3138 remove_proc_entry("igmp", net->proc_net); in igmp_net_init()
3140 return -ENOMEM; in igmp_net_init()
3145 remove_proc_entry("mcfilter", net->proc_net); in igmp_net_exit()
3146 remove_proc_entry("igmp", net->proc_net); in igmp_net_exit()
3147 inet_ctl_sock_destroy(net->ipv4.mc_autojoin_sk); in igmp_net_exit()