2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 2007-2009 Bruce Simpson.
30 * Copyright (c) 1988 Stephen Deering.
31 * Copyright (c) 1992, 1993
32 * The Regents of the University of California. All rights reserved.
34 * This code is derived from software contributed to Berkeley by
35 * Stephen Deering of Stanford University.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * @(#)igmp.c 8.1 (Berkeley) 7/19/93
68 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
69 * support for mandatory and extensible security protections. This notice
70 * is included in support of clause 2.2 (b) of the Apple Public License,
75 * Internet Group Management Protocol (IGMP) routines.
76 * [RFC1112, RFC2236, RFC3376]
78 * Written by Steve Deering, Stanford, May 1988.
79 * Modified by Rosen Sharma, Stanford, Aug 1994.
80 * Modified by Bill Fenner, Xerox PARC, Feb 1995.
81 * Modified to fully comply to IGMPv2 by Bill Fenner, Oct 1995.
82 * Significantly rewritten for IGMPv3, VIMAGE, and SMP by Bruce Simpson.
84 * MULTICAST Revision: 3.5.1.4
87 #include <sys/cdefs.h>
89 #include <sys/param.h>
90 #include <sys/systm.h>
91 #include <sys/malloc.h>
93 #include <sys/socket.h>
94 #include <sys/protosw.h>
95 #include <sys/kernel.h>
96 #include <sys/sysctl.h>
97 #include <sys/mcache.h>
99 #include <libkern/libkern.h>
100 #include <kern/zalloc.h>
103 #include <net/route.h>
105 #include <netinet/in.h>
106 #include <netinet/in_var.h>
107 #include <netinet/in_systm.h>
108 #include <netinet/ip.h>
109 #include <netinet/ip_var.h>
110 #include <netinet/igmp.h>
111 #include <netinet/igmp_var.h>
112 #include <netinet/kpi_ipfilter_var.h>
114 SLIST_HEAD(igmp_inm_relhead
, in_multi
);
116 static void igi_initvar(struct igmp_ifinfo
*, struct ifnet
*, int);
117 static struct igmp_ifinfo
*igi_alloc(int);
118 static void igi_free(struct igmp_ifinfo
*);
119 static void igi_delete(const struct ifnet
*, struct igmp_inm_relhead
*);
120 static void igmp_dispatch_queue(struct igmp_ifinfo
*, struct ifqueue
*,
122 static void igmp_final_leave(struct in_multi
*, struct igmp_ifinfo
*,
123 struct igmp_tparams
*);
124 static int igmp_handle_state_change(struct in_multi
*,
125 struct igmp_ifinfo
*, struct igmp_tparams
*);
126 static int igmp_initial_join(struct in_multi
*, struct igmp_ifinfo
*,
127 struct igmp_tparams
*);
128 static int igmp_input_v1_query(struct ifnet
*, const struct ip
*,
129 const struct igmp
*);
130 static int igmp_input_v2_query(struct ifnet
*, const struct ip
*,
131 const struct igmp
*);
132 static int igmp_input_v3_query(struct ifnet
*, const struct ip
*,
133 /*const*/ struct igmpv3
*);
134 static int igmp_input_v3_group_query(struct in_multi
*,
135 int, /*const*/ struct igmpv3
*);
136 static int igmp_input_v1_report(struct ifnet
*, struct mbuf
*,
137 /*const*/ struct ip
*, /*const*/ struct igmp
*);
138 static int igmp_input_v2_report(struct ifnet
*, struct mbuf
*,
139 /*const*/ struct ip
*, /*const*/ struct igmp
*);
140 static void igmp_sendpkt(struct mbuf
*);
141 static __inline__
int igmp_isgroupreported(const struct in_addr
);
142 static struct mbuf
*igmp_ra_alloc(void);
144 static const char *igmp_rec_type_to_str(const int);
146 static uint32_t igmp_set_version(struct igmp_ifinfo
*, const int);
147 static void igmp_flush_relq(struct igmp_ifinfo
*,
148 struct igmp_inm_relhead
*);
149 static int igmp_v1v2_queue_report(struct in_multi
*, const int);
150 static void igmp_v1v2_process_group_timer(struct in_multi
*, const int);
151 static void igmp_v1v2_process_querier_timers(struct igmp_ifinfo
*);
152 static uint32_t igmp_v2_update_group(struct in_multi
*, const int);
153 static void igmp_v3_cancel_link_timers(struct igmp_ifinfo
*);
154 static uint32_t igmp_v3_dispatch_general_query(struct igmp_ifinfo
*);
156 igmp_v3_encap_report(struct ifnet
*, struct mbuf
*);
157 static int igmp_v3_enqueue_group_record(struct ifqueue
*,
158 struct in_multi
*, const int, const int, const int);
159 static int igmp_v3_enqueue_filter_change(struct ifqueue
*,
161 static void igmp_v3_process_group_timers(struct igmp_ifinfo
*,
162 struct ifqueue
*, struct ifqueue
*, struct in_multi
*,
164 static int igmp_v3_merge_state_changes(struct in_multi
*,
166 static void igmp_v3_suppress_group_record(struct in_multi
*);
167 static int sysctl_igmp_ifinfo SYSCTL_HANDLER_ARGS
;
168 static int sysctl_igmp_gsr SYSCTL_HANDLER_ARGS
;
169 static int sysctl_igmp_default_version SYSCTL_HANDLER_ARGS
;
171 static int igmp_timeout_run
; /* IGMP timer is scheduled to run */
172 static void igmp_timeout(void *);
173 static void igmp_sched_timeout(void);
175 static struct mbuf
*m_raopt
; /* Router Alert option */
177 static int querier_present_timers_running
; /* IGMPv1/v2 older version
179 static int interface_timers_running
; /* IGMPv3 general
181 static int state_change_timers_running
; /* IGMPv3 state-change
183 static int current_state_timers_running
; /* IGMPv1/v2 host
184 * report; IGMPv3 g/sg
188 * Subsystem lock macros.
190 #define IGMP_LOCK() \
191 lck_mtx_lock(&igmp_mtx)
192 #define IGMP_LOCK_ASSERT_HELD() \
193 LCK_MTX_ASSERT(&igmp_mtx, LCK_MTX_ASSERT_OWNED)
194 #define IGMP_LOCK_ASSERT_NOTHELD() \
195 LCK_MTX_ASSERT(&igmp_mtx, LCK_MTX_ASSERT_NOTOWNED)
196 #define IGMP_UNLOCK() \
197 lck_mtx_unlock(&igmp_mtx)
199 static LIST_HEAD(, igmp_ifinfo
) igi_head
;
200 static struct igmpstat_v3 igmpstat_v3
= {
201 .igps_version
= IGPS_VERSION_3
,
202 .igps_len
= sizeof(struct igmpstat_v3
),
204 static struct igmpstat igmpstat
; /* old IGMPv2 stats structure */
205 static struct timeval igmp_gsrdelay
= {10, 0};
207 static int igmp_recvifkludge
= 1;
208 static int igmp_sendra
= 1;
209 static int igmp_sendlocal
= 1;
210 static int igmp_v1enable
= 1;
211 static int igmp_v2enable
= 1;
212 static int igmp_legacysupp
= 0;
213 static int igmp_default_version
= IGMP_VERSION_3
;
215 SYSCTL_STRUCT(_net_inet_igmp
, IGMPCTL_STATS
, stats
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
216 &igmpstat
, igmpstat
, "");
217 SYSCTL_STRUCT(_net_inet_igmp
, OID_AUTO
, v3stats
,
218 CTLFLAG_RD
| CTLFLAG_LOCKED
, &igmpstat_v3
, igmpstat_v3
, "");
219 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, recvifkludge
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
220 &igmp_recvifkludge
, 0,
221 "Rewrite IGMPv1/v2 reports from 0.0.0.0 to contain subnet address");
222 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, sendra
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
224 "Send IP Router Alert option in IGMPv2/v3 messages");
225 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, sendlocal
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
227 "Send IGMP membership reports for 224.0.0.0/24 groups");
228 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, v1enable
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
230 "Enable backwards compatibility with IGMPv1");
231 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, v2enable
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
233 "Enable backwards compatibility with IGMPv2");
234 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
, legacysupp
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
236 "Allow v1/v2 reports to suppress v3 group responses");
237 SYSCTL_PROC(_net_inet_igmp
, OID_AUTO
, default_version
,
238 CTLTYPE_INT
| CTLFLAG_RW
,
239 &igmp_default_version
, 0, sysctl_igmp_default_version
, "I",
240 "Default version of IGMP to run on each interface");
241 SYSCTL_PROC(_net_inet_igmp
, OID_AUTO
, gsrdelay
,
242 CTLTYPE_INT
| CTLFLAG_RW
,
243 &igmp_gsrdelay
.tv_sec
, 0, sysctl_igmp_gsr
, "I",
244 "Rate limit for IGMPv3 Group-and-Source queries in seconds");
247 SYSCTL_INT(_net_inet_igmp
, OID_AUTO
,
248 debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &igmp_debug
, 0, "");
251 SYSCTL_NODE(_net_inet_igmp
, OID_AUTO
, ifinfo
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
252 sysctl_igmp_ifinfo
, "Per-interface IGMPv3 state");
254 /* Lock group and attribute for igmp_mtx */
255 static lck_attr_t
*igmp_mtx_attr
;
256 static lck_grp_t
*igmp_mtx_grp
;
257 static lck_grp_attr_t
*igmp_mtx_grp_attr
;
260 * Locking and reference counting:
262 * igmp_mtx mainly protects igi_head. In cases where both igmp_mtx and
263 * in_multihead_lock must be held, the former must be acquired first in order
264 * to maintain lock ordering. It is not a requirement that igmp_mtx be
265 * acquired first before in_multihead_lock, but in case both must be acquired
266 * in succession, the correct lock ordering must be followed.
268 * Instead of walking the if_multiaddrs list at the interface and returning
269 * the ifma_protospec value of a matching entry, we search the global list
270 * of in_multi records and find it that way; this is done with in_multihead
271 * lock held. Doing so avoids the race condition issues that many other BSDs
272 * suffer from (therefore in our implementation, ifma_protospec will never be
273 * NULL for as long as the in_multi is valid.)
275 * The above creates a requirement for the in_multi to stay in in_multihead
276 * list even after the final IGMP leave (in IGMPv3 mode) until no longer needs
277 * be retransmitted (this is not required for IGMPv1/v2.) In order to handle
278 * this, the request and reference counts of the in_multi are bumped up when
279 * the state changes to IGMP_LEAVING_MEMBER, and later dropped in the timeout
280 * handler. Each in_multi holds a reference to the underlying igmp_ifinfo.
282 * Thus, the permitted lock oder is:
284 * igmp_mtx, in_multihead_lock, inm_lock, igi_lock
286 * Any may be taken independently, but if any are held at the same time,
287 * the above lock order must be followed.
289 static decl_lck_mtx_data(, igmp_mtx
);
290 static int igmp_timers_are_running
;
292 #define IGMP_ADD_DETACHED_INM(_head, _inm) { \
293 SLIST_INSERT_HEAD(_head, _inm, inm_dtle); \
296 #define IGMP_REMOVE_DETACHED_INM(_head) { \
297 struct in_multi *_inm, *_inm_tmp; \
298 SLIST_FOREACH_SAFE(_inm, _head, inm_dtle, _inm_tmp) { \
299 SLIST_REMOVE(_head, _inm, in_multi, inm_dtle); \
302 VERIFY(SLIST_EMPTY(_head)); \
305 #define IGI_ZONE_MAX 64 /* maximum elements in zone */
306 #define IGI_ZONE_NAME "igmp_ifinfo" /* zone name */
308 static unsigned int igi_size
; /* size of zone element */
309 static struct zone
*igi_zone
; /* zone for igmp_ifinfo */
311 /* Store IGMPv3 record count in the module private scratch space */
312 #define vt_nrecs pkt_mpriv.__mpriv_u.__mpriv32[0].__mpriv32_u.__val16[0]
315 igmp_save_context(struct mbuf
*m
, struct ifnet
*ifp
)
317 m
->m_pkthdr
.rcvif
= ifp
;
321 igmp_scrub_context(struct mbuf
*m
)
323 m
->m_pkthdr
.rcvif
= NULL
;
327 static __inline
const char *
328 inet_ntop_haddr(in_addr_t haddr
, char *buf
, socklen_t size
)
332 ia
.s_addr
= htonl(haddr
);
333 return (inet_ntop(AF_INET
, &ia
, buf
, size
));
338 * Restore context from a queued IGMP output chain.
341 static __inline
struct ifnet
*
342 igmp_restore_context(struct mbuf
*m
)
344 return (m
->m_pkthdr
.rcvif
);
348 * Retrieve or set default IGMP version.
351 sysctl_igmp_default_version SYSCTL_HANDLER_ARGS
353 #pragma unused(oidp, arg2)
359 error
= SYSCTL_OUT(req
, arg1
, sizeof(int));
360 if (error
|| !req
->newptr
)
363 new = igmp_default_version
;
365 error
= SYSCTL_IN(req
, &new, sizeof(int));
369 if (new < IGMP_VERSION_1
|| new > IGMP_VERSION_3
) {
374 IGMP_PRINTF(("%s: change igmp_default_version from %d to %d\n",
375 __func__
, igmp_default_version
, new));
377 igmp_default_version
= new;
385 * Retrieve or set threshold between group-source queries in seconds.
389 sysctl_igmp_gsr SYSCTL_HANDLER_ARGS
391 #pragma unused(arg1, arg2)
397 i
= igmp_gsrdelay
.tv_sec
;
399 error
= sysctl_handle_int(oidp
, &i
, 0, req
);
400 if (error
|| !req
->newptr
)
403 if (i
< -1 || i
>= 60) {
408 igmp_gsrdelay
.tv_sec
= i
;
416 * Expose struct igmp_ifinfo to userland, keyed by ifindex.
417 * For use by ifmcstat(8).
421 sysctl_igmp_ifinfo SYSCTL_HANDLER_ARGS
428 struct igmp_ifinfo
*igi
;
429 struct igmp_ifinfo_u igi_u
;
434 if (req
->newptr
!= USER_ADDR_NULL
)
442 if (name
[0] <= 0 || name
[0] > (u_int
)if_index
) {
449 ifnet_head_lock_shared();
450 ifp
= ifindex2ifnet
[name
[0]];
455 bzero(&igi_u
, sizeof (igi_u
));
457 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
459 if (ifp
!= igi
->igi_ifp
) {
463 igi_u
.igi_ifindex
= igi
->igi_ifp
->if_index
;
464 igi_u
.igi_version
= igi
->igi_version
;
465 igi_u
.igi_v1_timer
= igi
->igi_v1_timer
;
466 igi_u
.igi_v2_timer
= igi
->igi_v2_timer
;
467 igi_u
.igi_v3_timer
= igi
->igi_v3_timer
;
468 igi_u
.igi_flags
= igi
->igi_flags
;
469 igi_u
.igi_rv
= igi
->igi_rv
;
470 igi_u
.igi_qi
= igi
->igi_qi
;
471 igi_u
.igi_qri
= igi
->igi_qri
;
472 igi_u
.igi_uri
= igi
->igi_uri
;
475 error
= SYSCTL_OUT(req
, &igi_u
, sizeof (igi_u
));
485 * Dispatch an entire queue of pending packet chains
487 * Must not be called with inm_lock held.
490 igmp_dispatch_queue(struct igmp_ifinfo
*igi
, struct ifqueue
*ifq
, int limit
,
497 IGI_LOCK_ASSERT_HELD(igi
);
503 IGMP_PRINTF(("%s: dispatch 0x%llx from 0x%llx\n", __func__
,
504 (uint64_t)VM_KERNEL_ADDRPERM(ifq
),
505 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
506 ip
= mtod(m
, struct ip
*);
508 m
->m_flags
|= M_IGMP_LOOP
;
519 IGI_LOCK_ASSERT_HELD(igi
);
523 * Filter outgoing IGMP report state by group.
525 * Reports are ALWAYS suppressed for ALL-HOSTS (224.0.0.1).
526 * If the net.inet.igmp.sendlocal sysctl is 0, then IGMP reports are
527 * disabled for all groups in the 224.0.0.0/24 link-local scope. However,
528 * this may break certain IGMP snooping switches which rely on the old
531 * Return zero if the given group is one for which IGMP reports
532 * should be suppressed, or non-zero if reports should be issued.
536 int igmp_isgroupreported(const struct in_addr addr
)
539 if (in_allhosts(addr
) ||
540 ((!igmp_sendlocal
&& IN_LOCAL_GROUP(ntohl(addr
.s_addr
)))))
547 * Construct a Router Alert option to use in outgoing packets.
555 MGET(m
, M_WAITOK
, MT_DATA
);
556 p
= mtod(m
, struct ipoption
*);
557 p
->ipopt_dst
.s_addr
= INADDR_ANY
;
558 p
->ipopt_list
[0] = (char)IPOPT_RA
; /* Router Alert Option */
559 p
->ipopt_list
[1] = 0x04; /* 4 bytes long */
560 p
->ipopt_list
[2] = IPOPT_EOL
; /* End of IP option list */
561 p
->ipopt_list
[3] = 0x00; /* pad byte */
562 m
->m_len
= sizeof(p
->ipopt_dst
) + p
->ipopt_list
[1];
568 * Attach IGMP when PF_INET is attached to an interface.
571 igmp_domifattach(struct ifnet
*ifp
, int how
)
573 struct igmp_ifinfo
*igi
;
575 IGMP_PRINTF(("%s: called for ifp 0x%llx(%s)\n",
576 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
), ifp
->if_name
));
578 igi
= igi_alloc(how
);
585 igi_initvar(igi
, ifp
, 0);
586 igi
->igi_debug
|= IFD_ATTACHED
;
587 IGI_ADDREF_LOCKED(igi
); /* hold a reference for igi_head */
588 IGI_ADDREF_LOCKED(igi
); /* hold a reference for caller */
590 ifnet_lock_shared(ifp
);
591 igmp_initsilent(ifp
, igi
);
592 ifnet_lock_done(ifp
);
594 LIST_INSERT_HEAD(&igi_head
, igi
, igi_link
);
598 IGMP_PRINTF(("%s: allocate igmp_ifinfo for ifp 0x%llx(%s)\n", __func__
,
599 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), ifp
->if_name
));
605 * Attach IGMP when PF_INET is reattached to an interface. Caller is
606 * expected to have an outstanding reference to the igi.
609 igmp_domifreattach(struct igmp_ifinfo
*igi
)
616 VERIFY(!(igi
->igi_debug
& IFD_ATTACHED
));
619 igi_initvar(igi
, ifp
, 1);
620 igi
->igi_debug
|= IFD_ATTACHED
;
621 IGI_ADDREF_LOCKED(igi
); /* hold a reference for igi_head */
623 ifnet_lock_shared(ifp
);
624 igmp_initsilent(ifp
, igi
);
625 ifnet_lock_done(ifp
);
627 LIST_INSERT_HEAD(&igi_head
, igi
, igi_link
);
631 IGMP_PRINTF(("%s: reattached igmp_ifinfo for ifp 0x%llx(%s)\n",
632 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
), ifp
->if_name
));
636 * Hook for domifdetach.
639 igmp_domifdetach(struct ifnet
*ifp
)
641 SLIST_HEAD(, in_multi
) inm_dthead
;
643 SLIST_INIT(&inm_dthead
);
645 IGMP_PRINTF(("%s: called for ifp 0x%llx(%s%d)\n", __func__
,
646 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), ifp
->if_name
, ifp
->if_unit
));
649 igi_delete(ifp
, (struct igmp_inm_relhead
*)&inm_dthead
);
652 /* Now that we're dropped all locks, release detached records */
653 IGMP_REMOVE_DETACHED_INM(&inm_dthead
);
657 * Called at interface detach time. Note that we only flush all deferred
658 * responses and record releases; all remaining inm records and their source
659 * entries related to this interface are left intact, in order to handle
663 igi_delete(const struct ifnet
*ifp
, struct igmp_inm_relhead
*inm_dthead
)
665 struct igmp_ifinfo
*igi
, *tigi
;
667 IGMP_LOCK_ASSERT_HELD();
669 LIST_FOREACH_SAFE(igi
, &igi_head
, igi_link
, tigi
) {
671 if (igi
->igi_ifp
== ifp
) {
673 * Free deferred General Query responses.
675 IF_DRAIN(&igi
->igi_gq
);
676 IF_DRAIN(&igi
->igi_v2q
);
677 igmp_flush_relq(igi
, inm_dthead
);
678 VERIFY(SLIST_EMPTY(&igi
->igi_relinmhead
));
679 igi
->igi_debug
&= ~IFD_ATTACHED
;
682 LIST_REMOVE(igi
, igi_link
);
683 IGI_REMREF(igi
); /* release igi_head reference */
688 panic("%s: igmp_ifinfo not found for ifp %p(%s)\n", __func__
,
692 __private_extern__
void
693 igmp_initsilent(struct ifnet
*ifp
, struct igmp_ifinfo
*igi
)
695 ifnet_lock_assert(ifp
, IFNET_LCK_ASSERT_OWNED
);
697 IGI_LOCK_ASSERT_NOTHELD(igi
);
699 if (!(ifp
->if_flags
& IFF_MULTICAST
))
700 igi
->igi_flags
|= IGIF_SILENT
;
702 igi
->igi_flags
&= ~IGIF_SILENT
;
707 igi_initvar(struct igmp_ifinfo
*igi
, struct ifnet
*ifp
, int reattach
)
709 IGI_LOCK_ASSERT_HELD(igi
);
712 igi
->igi_version
= igmp_default_version
;
714 igi
->igi_rv
= IGMP_RV_INIT
;
715 igi
->igi_qi
= IGMP_QI_INIT
;
716 igi
->igi_qri
= IGMP_QRI_INIT
;
717 igi
->igi_uri
= IGMP_URI_INIT
;
720 SLIST_INIT(&igi
->igi_relinmhead
);
723 * Responses to general queries are subject to bounds.
725 igi
->igi_gq
.ifq_maxlen
= IGMP_MAX_RESPONSE_PACKETS
;
726 igi
->igi_v2q
.ifq_maxlen
= IGMP_MAX_RESPONSE_PACKETS
;
729 static struct igmp_ifinfo
*
732 struct igmp_ifinfo
*igi
;
734 igi
= (how
== M_WAITOK
) ? zalloc(igi_zone
) : zalloc_noblock(igi_zone
);
736 bzero(igi
, igi_size
);
737 lck_mtx_init(&igi
->igi_lock
, igmp_mtx_grp
, igmp_mtx_attr
);
738 igi
->igi_debug
|= IFD_ALLOC
;
744 igi_free(struct igmp_ifinfo
*igi
)
747 if (igi
->igi_debug
& IFD_ATTACHED
) {
748 panic("%s: attached igi=%p is being freed", __func__
, igi
);
750 } else if (igi
->igi_ifp
!= NULL
) {
751 panic("%s: ifp not NULL for igi=%p", __func__
, igi
);
753 } else if (!(igi
->igi_debug
& IFD_ALLOC
)) {
754 panic("%s: igi %p cannot be freed", __func__
, igi
);
756 } else if (igi
->igi_refcnt
!= 0) {
757 panic("%s: non-zero refcnt igi=%p", __func__
, igi
);
760 igi
->igi_debug
&= ~IFD_ALLOC
;
763 lck_mtx_destroy(&igi
->igi_lock
, igmp_mtx_grp
);
764 zfree(igi_zone
, igi
);
768 igi_addref(struct igmp_ifinfo
*igi
, int locked
)
773 IGI_LOCK_ASSERT_HELD(igi
);
775 if (++igi
->igi_refcnt
== 0) {
776 panic("%s: igi=%p wraparound refcnt", __func__
, igi
);
784 igi_remref(struct igmp_ifinfo
*igi
)
786 SLIST_HEAD(, in_multi
) inm_dthead
;
791 if (igi
->igi_refcnt
== 0) {
792 panic("%s: igi=%p negative refcnt", __func__
, igi
);
797 if (igi
->igi_refcnt
> 0) {
804 IF_DRAIN(&igi
->igi_gq
);
805 IF_DRAIN(&igi
->igi_v2q
);
806 SLIST_INIT(&inm_dthead
);
807 igmp_flush_relq(igi
, (struct igmp_inm_relhead
*)&inm_dthead
);
808 VERIFY(SLIST_EMPTY(&igi
->igi_relinmhead
));
811 /* Now that we're dropped all locks, release detached records */
812 IGMP_REMOVE_DETACHED_INM(&inm_dthead
);
814 IGMP_PRINTF(("%s: freeing igmp_ifinfo for ifp 0x%llx(%s)\n",
815 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
821 * Process a received IGMPv1 query.
822 * Return non-zero if the message should be dropped.
825 igmp_input_v1_query(struct ifnet
*ifp
, const struct ip
*ip
,
826 const struct igmp
*igmp
)
828 struct igmp_ifinfo
*igi
;
829 struct in_multi
*inm
;
830 struct in_multistep step
;
831 struct igmp_tparams itp
= { 0, 0, 0, 0 };
833 IGMP_LOCK_ASSERT_NOTHELD();
836 * IGMPv1 Host Membership Queries SHOULD always be addressed to
837 * 224.0.0.1. They are always treated as General Queries.
838 * igmp_group is always ignored. Do not drop it as a userland
839 * daemon may wish to see it.
841 if (!in_allhosts(ip
->ip_dst
) || !in_nullhost(igmp
->igmp_group
)) {
842 IGMPSTAT_INC(igps_rcv_badqueries
);
843 OIGMPSTAT_INC(igps_rcv_badqueries
);
846 IGMPSTAT_INC(igps_rcv_gen_queries
);
848 igi
= IGMP_IFINFO(ifp
);
852 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
853 IGMP_PRINTF(("%s: ignore v1 query on IGIF_LOOPBACK "
854 "ifp 0x%llx(%s)\n", __func__
,
855 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
860 * Switch to IGMPv1 host compatibility mode.
862 itp
.qpt
= igmp_set_version(igi
, IGMP_VERSION_1
);
865 IGMP_PRINTF(("%s: process v1 query on ifp 0x%llx(%s)\n", __func__
,
866 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
869 * Start the timers in all of our group records
870 * for the interface on which the query arrived,
871 * except those which are already running.
873 in_multihead_lock_shared();
874 IN_FIRST_MULTI(step
, inm
);
875 while (inm
!= NULL
) {
877 if (inm
->inm_ifp
!= ifp
|| inm
->inm_timer
!= 0)
880 switch (inm
->inm_state
) {
881 case IGMP_NOT_MEMBER
:
882 case IGMP_SILENT_MEMBER
:
884 case IGMP_G_QUERY_PENDING_MEMBER
:
885 case IGMP_SG_QUERY_PENDING_MEMBER
:
886 case IGMP_REPORTING_MEMBER
:
887 case IGMP_IDLE_MEMBER
:
888 case IGMP_LAZY_MEMBER
:
889 case IGMP_SLEEPING_MEMBER
:
890 case IGMP_AWAKENING_MEMBER
:
891 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
892 inm
->inm_timer
= IGMP_RANDOM_DELAY(IGMP_V1V2_MAX_RI
);
895 case IGMP_LEAVING_MEMBER
:
900 IN_NEXT_MULTI(step
, inm
);
902 in_multihead_lock_done();
904 igmp_set_timeout(&itp
);
910 * Process a received IGMPv2 general or group-specific query.
913 igmp_input_v2_query(struct ifnet
*ifp
, const struct ip
*ip
,
914 const struct igmp
*igmp
)
916 struct igmp_ifinfo
*igi
;
917 struct in_multi
*inm
;
918 int is_general_query
;
920 struct igmp_tparams itp
= { 0, 0, 0, 0 };
922 IGMP_LOCK_ASSERT_NOTHELD();
924 is_general_query
= 0;
927 * Validate address fields upfront.
929 if (in_nullhost(igmp
->igmp_group
)) {
931 * IGMPv2 General Query.
932 * If this was not sent to the all-hosts group, ignore it.
934 if (!in_allhosts(ip
->ip_dst
))
936 IGMPSTAT_INC(igps_rcv_gen_queries
);
937 is_general_query
= 1;
939 /* IGMPv2 Group-Specific Query. */
940 IGMPSTAT_INC(igps_rcv_group_queries
);
943 igi
= IGMP_IFINFO(ifp
);
947 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
948 IGMP_PRINTF(("%s: ignore v2 query on IGIF_LOOPBACK "
949 "ifp 0x%llx(%s)\n", __func__
,
950 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
955 * Ignore v2 query if in v1 Compatibility Mode.
957 if (igi
->igi_version
== IGMP_VERSION_1
) {
961 itp
.qpt
= igmp_set_version(igi
, IGMP_VERSION_2
);
964 timer
= igmp
->igmp_code
/ IGMP_TIMER_SCALE
;
968 if (is_general_query
) {
969 struct in_multistep step
;
971 IGMP_PRINTF(("%s: process v2 general query on ifp 0x%llx(%s)\n",
972 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
974 * For each reporting group joined on this
975 * interface, kick the report timer.
977 in_multihead_lock_shared();
978 IN_FIRST_MULTI(step
, inm
);
979 while (inm
!= NULL
) {
981 if (inm
->inm_ifp
== ifp
)
982 itp
.cst
+= igmp_v2_update_group(inm
, timer
);
984 IN_NEXT_MULTI(step
, inm
);
986 in_multihead_lock_done();
989 * Group-specific IGMPv2 query, we need only
990 * look up the single group to process it.
992 in_multihead_lock_shared();
993 IN_LOOKUP_MULTI(&igmp
->igmp_group
, ifp
, inm
);
994 in_multihead_lock_done();
997 IGMP_INET_PRINTF(igmp
->igmp_group
,
998 ("process v2 query %s on ifp 0x%llx(%s)\n",
1000 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1001 itp
.cst
= igmp_v2_update_group(inm
, timer
);
1003 INM_REMREF(inm
); /* from IN_LOOKUP_MULTI */
1007 igmp_set_timeout(&itp
);
1013 * Update the report timer on a group in response to an IGMPv2 query.
1015 * If we are becoming the reporting member for this group, start the timer.
1016 * If we already are the reporting member for this group, and timer is
1017 * below the threshold, reset it.
1019 * We may be updating the group for the first time since we switched
1020 * to IGMPv3. If we are, then we must clear any recorded source lists,
1021 * and transition to REPORTING state; the group timer is overloaded
1022 * for group and group-source query responses.
1024 * Unlike IGMPv3, the delay per group should be jittered
1025 * to avoid bursts of IGMPv2 reports.
1028 igmp_v2_update_group(struct in_multi
*inm
, const int timer
)
1031 IGMP_INET_PRINTF(inm
->inm_addr
, ("%s: %s/%s timer=%d\n",
1032 __func__
, _igmp_inet_buf
, if_name(inm
->inm_ifp
),
1035 INM_LOCK_ASSERT_HELD(inm
);
1037 switch (inm
->inm_state
) {
1038 case IGMP_NOT_MEMBER
:
1039 case IGMP_SILENT_MEMBER
:
1041 case IGMP_REPORTING_MEMBER
:
1042 if (inm
->inm_timer
!= 0 &&
1043 inm
->inm_timer
<= timer
) {
1044 IGMP_PRINTF(("%s: REPORTING and timer running, "
1045 "skipping.\n", __func__
));
1049 case IGMP_SG_QUERY_PENDING_MEMBER
:
1050 case IGMP_G_QUERY_PENDING_MEMBER
:
1051 case IGMP_IDLE_MEMBER
:
1052 case IGMP_LAZY_MEMBER
:
1053 case IGMP_AWAKENING_MEMBER
:
1054 IGMP_PRINTF(("%s: ->REPORTING\n", __func__
));
1055 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
1056 inm
->inm_timer
= IGMP_RANDOM_DELAY(timer
);
1058 case IGMP_SLEEPING_MEMBER
:
1059 IGMP_PRINTF(("%s: ->AWAKENING\n", __func__
));
1060 inm
->inm_state
= IGMP_AWAKENING_MEMBER
;
1062 case IGMP_LEAVING_MEMBER
:
1066 return (inm
->inm_timer
);
1070 * Process a received IGMPv3 general, group-specific or
1071 * group-and-source-specific query.
1072 * Assumes m has already been pulled up to the full IGMP message length.
1073 * Return 0 if successful, otherwise an appropriate error code is returned.
1076 igmp_input_v3_query(struct ifnet
*ifp
, const struct ip
*ip
,
1077 /*const*/ struct igmpv3
*igmpv3
)
1079 struct igmp_ifinfo
*igi
;
1080 struct in_multi
*inm
;
1081 int is_general_query
;
1082 uint32_t maxresp
, nsrc
, qqi
;
1085 struct igmp_tparams itp
= { 0, 0, 0, 0 };
1087 IGMP_LOCK_ASSERT_NOTHELD();
1089 is_general_query
= 0;
1091 IGMP_PRINTF(("%s: process v3 query on ifp 0x%llx(%s)\n", __func__
,
1092 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1094 maxresp
= igmpv3
->igmp_code
; /* in 1/10ths of a second */
1095 if (maxresp
>= 128) {
1096 maxresp
= IGMP_MANT(igmpv3
->igmp_code
) <<
1097 (IGMP_EXP(igmpv3
->igmp_code
) + 3);
1101 * Robustness must never be less than 2 for on-wire IGMPv3.
1102 * FUTURE: Check if ifp has IGIF_LOOPBACK set, as we will make
1103 * an exception for interfaces whose IGMPv3 state changes
1104 * are redirected to loopback (e.g. MANET).
1106 qrv
= IGMP_QRV(igmpv3
->igmp_misc
);
1108 IGMP_PRINTF(("%s: clamping qrv %d to %d\n", __func__
,
1109 qrv
, IGMP_RV_INIT
));
1113 qqi
= igmpv3
->igmp_qqi
;
1115 qqi
= IGMP_MANT(igmpv3
->igmp_qqi
) <<
1116 (IGMP_EXP(igmpv3
->igmp_qqi
) + 3);
1119 timer
= maxresp
/ IGMP_TIMER_SCALE
;
1123 nsrc
= ntohs(igmpv3
->igmp_numsrc
);
1126 * Validate address fields and versions upfront before
1127 * accepting v3 query.
1129 if (in_nullhost(igmpv3
->igmp_group
)) {
1131 * IGMPv3 General Query.
1133 * General Queries SHOULD be directed to 224.0.0.1.
1134 * A general query with a source list has undefined
1135 * behaviour; discard it.
1137 IGMPSTAT_INC(igps_rcv_gen_queries
);
1138 if (!in_allhosts(ip
->ip_dst
) || nsrc
> 0) {
1139 IGMPSTAT_INC(igps_rcv_badqueries
);
1140 OIGMPSTAT_INC(igps_rcv_badqueries
);
1143 is_general_query
= 1;
1145 /* Group or group-source specific query. */
1147 IGMPSTAT_INC(igps_rcv_group_queries
);
1149 IGMPSTAT_INC(igps_rcv_gsr_queries
);
1152 igi
= IGMP_IFINFO(ifp
);
1153 VERIFY(igi
!= NULL
);
1156 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
1157 IGMP_PRINTF(("%s: ignore v3 query on IGIF_LOOPBACK "
1158 "ifp 0x%llx(%s)\n", __func__
,
1159 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1165 * Discard the v3 query if we're in Compatibility Mode.
1166 * The RFC is not obviously worded that hosts need to stay in
1167 * compatibility mode until the Old Version Querier Present
1170 if (igi
->igi_version
!= IGMP_VERSION_3
) {
1171 IGMP_PRINTF(("%s: ignore v3 query in v%d mode on "
1172 "ifp 0x%llx(%s)\n", __func__
, igi
->igi_version
,
1173 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1178 itp
.qpt
= igmp_set_version(igi
, IGMP_VERSION_3
);
1181 igi
->igi_qri
= MAX(timer
, IGMP_QRI_MIN
);
1183 IGMP_PRINTF(("%s: qrv %d qi %d qri %d\n", __func__
, igi
->igi_rv
,
1184 igi
->igi_qi
, igi
->igi_qri
));
1186 if (is_general_query
) {
1188 * Schedule a current-state report on this ifp for
1189 * all groups, possibly containing source lists.
1190 * If there is a pending General Query response
1191 * scheduled earlier than the selected delay, do
1192 * not schedule any other reports.
1193 * Otherwise, reset the interface timer.
1195 IGMP_PRINTF(("%s: process v3 general query on ifp 0x%llx(%s)\n",
1196 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1197 if (igi
->igi_v3_timer
== 0 || igi
->igi_v3_timer
>= timer
) {
1198 itp
.it
= igi
->igi_v3_timer
= IGMP_RANDOM_DELAY(timer
);
1204 * Group-source-specific queries are throttled on
1205 * a per-group basis to defeat denial-of-service attempts.
1206 * Queries for groups we are not a member of on this
1207 * link are simply ignored.
1209 in_multihead_lock_shared();
1210 IN_LOOKUP_MULTI(&igmpv3
->igmp_group
, ifp
, inm
);
1211 in_multihead_lock_done();
1217 if (!ratecheck(&inm
->inm_lastgsrtv
,
1219 IGMP_PRINTF(("%s: GS query throttled.\n",
1221 IGMPSTAT_INC(igps_drop_gsr_queries
);
1223 INM_REMREF(inm
); /* from IN_LOOKUP_MULTI */
1227 IGMP_INET_PRINTF(igmpv3
->igmp_group
,
1228 ("process v3 %s query on ifp 0x%llx(%s)\n", _igmp_inet_buf
,
1229 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1231 * If there is a pending General Query response
1232 * scheduled sooner than the selected delay, no
1233 * further report need be scheduled.
1234 * Otherwise, prepare to respond to the
1235 * group-specific or group-and-source query.
1238 itp
.it
= igi
->igi_v3_timer
;
1240 if (itp
.it
== 0 || itp
.it
>= timer
) {
1241 (void) igmp_input_v3_group_query(inm
, timer
, igmpv3
);
1242 itp
.cst
= inm
->inm_timer
;
1245 INM_REMREF(inm
); /* from IN_LOOKUP_MULTI */
1249 IGMP_PRINTF(("%s: v3 general query response scheduled in "
1250 "T+%d seconds on ifp 0x%llx(%s)\n", __func__
, itp
.it
,
1251 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1253 igmp_set_timeout(&itp
);
1259 * Process a recieved IGMPv3 group-specific or group-and-source-specific
1261 * Return <0 if any error occured. Currently this is ignored.
1264 igmp_input_v3_group_query(struct in_multi
*inm
,
1265 int timer
, /*const*/ struct igmpv3
*igmpv3
)
1270 INM_LOCK_ASSERT_HELD(inm
);
1274 switch (inm
->inm_state
) {
1275 case IGMP_NOT_MEMBER
:
1276 case IGMP_SILENT_MEMBER
:
1277 case IGMP_SLEEPING_MEMBER
:
1278 case IGMP_LAZY_MEMBER
:
1279 case IGMP_AWAKENING_MEMBER
:
1280 case IGMP_IDLE_MEMBER
:
1281 case IGMP_LEAVING_MEMBER
:
1283 case IGMP_REPORTING_MEMBER
:
1284 case IGMP_G_QUERY_PENDING_MEMBER
:
1285 case IGMP_SG_QUERY_PENDING_MEMBER
:
1289 nsrc
= ntohs(igmpv3
->igmp_numsrc
);
1292 * Deal with group-specific queries upfront.
1293 * If any group query is already pending, purge any recorded
1294 * source-list state if it exists, and schedule a query response
1295 * for this group-specific query.
1298 if (inm
->inm_state
== IGMP_G_QUERY_PENDING_MEMBER
||
1299 inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
) {
1300 inm_clear_recorded(inm
);
1301 timer
= min(inm
->inm_timer
, timer
);
1303 inm
->inm_state
= IGMP_G_QUERY_PENDING_MEMBER
;
1304 inm
->inm_timer
= IGMP_RANDOM_DELAY(timer
);
1309 * Deal with the case where a group-and-source-specific query has
1310 * been received but a group-specific query is already pending.
1312 if (inm
->inm_state
== IGMP_G_QUERY_PENDING_MEMBER
) {
1313 timer
= min(inm
->inm_timer
, timer
);
1314 inm
->inm_timer
= IGMP_RANDOM_DELAY(timer
);
1319 * Finally, deal with the case where a group-and-source-specific
1320 * query has been received, where a response to a previous g-s-r
1321 * query exists, or none exists.
1322 * In this case, we need to parse the source-list which the Querier
1323 * has provided us with and check if we have any source list filter
1324 * entries at T1 for these sources. If we do not, there is no need
1325 * schedule a report and the query may be dropped.
1326 * If we do, we must record them and schedule a current-state
1327 * report for those sources.
1328 * FIXME: Handling source lists larger than 1 mbuf requires that
1329 * we pass the mbuf chain pointer down to this function, and use
1330 * m_getptr() to walk the chain.
1332 if (inm
->inm_nsrc
> 0) {
1333 const struct in_addr
*ap
;
1336 ap
= (const struct in_addr
*)(igmpv3
+ 1);
1338 for (i
= 0; i
< nsrc
; i
++, ap
++) {
1339 retval
= inm_record_source(inm
, ap
->s_addr
);
1342 nrecorded
+= retval
;
1344 if (nrecorded
> 0) {
1345 IGMP_PRINTF(("%s: schedule response to SG query\n",
1347 inm
->inm_state
= IGMP_SG_QUERY_PENDING_MEMBER
;
1348 inm
->inm_timer
= IGMP_RANDOM_DELAY(timer
);
1356 * Process a received IGMPv1 host membership report.
1358 * NOTE: 0.0.0.0 workaround breaks const correctness.
1361 igmp_input_v1_report(struct ifnet
*ifp
, struct mbuf
*m
, /*const*/ struct ip
*ip
,
1362 /*const*/ struct igmp
*igmp
)
1364 struct in_ifaddr
*ia
;
1365 struct in_multi
*inm
;
1367 IGMPSTAT_INC(igps_rcv_reports
);
1368 OIGMPSTAT_INC(igps_rcv_reports
);
1370 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
1371 (m
->m_pkthdr
.pkt_flags
& PKTF_LOOP
))
1374 if (!IN_MULTICAST(ntohl(igmp
->igmp_group
.s_addr
) ||
1375 !in_hosteq(igmp
->igmp_group
, ip
->ip_dst
))) {
1376 IGMPSTAT_INC(igps_rcv_badreports
);
1377 OIGMPSTAT_INC(igps_rcv_badreports
);
1382 * RFC 3376, Section 4.2.13, 9.2, 9.3:
1383 * Booting clients may use the source address 0.0.0.0. Some
1384 * IGMP daemons may not know how to use IP_RECVIF to determine
1385 * the interface upon which this message was received.
1386 * Replace 0.0.0.0 with the subnet address if told to do so.
1388 if (igmp_recvifkludge
&& in_nullhost(ip
->ip_src
)) {
1391 IFA_LOCK(&ia
->ia_ifa
);
1392 ip
->ip_src
.s_addr
= htonl(ia
->ia_subnet
);
1393 IFA_UNLOCK(&ia
->ia_ifa
);
1394 IFA_REMREF(&ia
->ia_ifa
);
1398 IGMP_INET_PRINTF(igmp
->igmp_group
,
1399 ("process v1 report %s on ifp 0x%llx(%s)\n", _igmp_inet_buf
,
1400 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1403 * IGMPv1 report suppression.
1404 * If we are a member of this group, and our membership should be
1405 * reported, stop our group timer and transition to the 'lazy' state.
1407 in_multihead_lock_shared();
1408 IN_LOOKUP_MULTI(&igmp
->igmp_group
, ifp
, inm
);
1409 in_multihead_lock_done();
1411 struct igmp_ifinfo
*igi
;
1416 VERIFY(igi
!= NULL
);
1418 IGMPSTAT_INC(igps_rcv_ourreports
);
1419 OIGMPSTAT_INC(igps_rcv_ourreports
);
1422 * If we are in IGMPv3 host mode, do not allow the
1423 * other host's IGMPv1 report to suppress our reports
1424 * unless explicitly configured to do so.
1427 if (igi
->igi_version
== IGMP_VERSION_3
) {
1428 if (igmp_legacysupp
)
1429 igmp_v3_suppress_group_record(inm
);
1432 INM_REMREF(inm
); /* from IN_LOOKUP_MULTI */
1436 INM_LOCK_ASSERT_HELD(inm
);
1439 switch (inm
->inm_state
) {
1440 case IGMP_NOT_MEMBER
:
1441 case IGMP_SILENT_MEMBER
:
1443 case IGMP_IDLE_MEMBER
:
1444 case IGMP_LAZY_MEMBER
:
1445 case IGMP_AWAKENING_MEMBER
:
1446 IGMP_INET_PRINTF(igmp
->igmp_group
,
1447 ("report suppressed for %s on ifp 0x%llx(%s)\n",
1449 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1450 case IGMP_SLEEPING_MEMBER
:
1451 inm
->inm_state
= IGMP_SLEEPING_MEMBER
;
1453 case IGMP_REPORTING_MEMBER
:
1454 IGMP_INET_PRINTF(igmp
->igmp_group
,
1455 ("report suppressed for %s on ifp 0x%llx(%s)\n",
1457 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1458 if (igi
->igi_version
== IGMP_VERSION_1
)
1459 inm
->inm_state
= IGMP_LAZY_MEMBER
;
1460 else if (igi
->igi_version
== IGMP_VERSION_2
)
1461 inm
->inm_state
= IGMP_SLEEPING_MEMBER
;
1463 case IGMP_G_QUERY_PENDING_MEMBER
:
1464 case IGMP_SG_QUERY_PENDING_MEMBER
:
1465 case IGMP_LEAVING_MEMBER
:
1470 INM_REMREF(inm
); /* from IN_LOOKUP_MULTI */
1477 * Process a received IGMPv2 host membership report.
1479 * NOTE: 0.0.0.0 workaround breaks const correctness.
1482 igmp_input_v2_report(struct ifnet
*ifp
, struct mbuf
*m
, /*const*/ struct ip
*ip
,
1483 /*const*/ struct igmp
*igmp
)
1485 struct in_ifaddr
*ia
;
1486 struct in_multi
*inm
;
1489 * Make sure we don't hear our own membership report. Fast
1490 * leave requires knowing that we are the only member of a
1495 IFA_LOCK(&ia
->ia_ifa
);
1496 if (in_hosteq(ip
->ip_src
, IA_SIN(ia
)->sin_addr
)) {
1497 IFA_UNLOCK(&ia
->ia_ifa
);
1498 IFA_REMREF(&ia
->ia_ifa
);
1501 IFA_UNLOCK(&ia
->ia_ifa
);
1504 IGMPSTAT_INC(igps_rcv_reports
);
1505 OIGMPSTAT_INC(igps_rcv_reports
);
1507 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
1508 (m
->m_pkthdr
.pkt_flags
& PKTF_LOOP
)) {
1510 IFA_REMREF(&ia
->ia_ifa
);
1514 if (!IN_MULTICAST(ntohl(igmp
->igmp_group
.s_addr
)) ||
1515 !in_hosteq(igmp
->igmp_group
, ip
->ip_dst
)) {
1517 IFA_REMREF(&ia
->ia_ifa
);
1518 IGMPSTAT_INC(igps_rcv_badreports
);
1519 OIGMPSTAT_INC(igps_rcv_badreports
);
1524 * RFC 3376, Section 4.2.13, 9.2, 9.3:
1525 * Booting clients may use the source address 0.0.0.0. Some
1526 * IGMP daemons may not know how to use IP_RECVIF to determine
1527 * the interface upon which this message was received.
1528 * Replace 0.0.0.0 with the subnet address if told to do so.
1530 if (igmp_recvifkludge
&& in_nullhost(ip
->ip_src
)) {
1532 IFA_LOCK(&ia
->ia_ifa
);
1533 ip
->ip_src
.s_addr
= htonl(ia
->ia_subnet
);
1534 IFA_UNLOCK(&ia
->ia_ifa
);
1538 IFA_REMREF(&ia
->ia_ifa
);
1540 IGMP_INET_PRINTF(igmp
->igmp_group
,
1541 ("process v2 report %s on ifp 0x%llx(%s)\n", _igmp_inet_buf
,
1542 (uint64_t)VM_KERNEL_ADDRPERM(ifp
), if_name(ifp
)));
1545 * IGMPv2 report suppression.
1546 * If we are a member of this group, and our membership should be
1547 * reported, and our group timer is pending or about to be reset,
1548 * stop our group timer by transitioning to the 'lazy' state.
1550 in_multihead_lock_shared();
1551 IN_LOOKUP_MULTI(&igmp
->igmp_group
, ifp
, inm
);
1552 in_multihead_lock_done();
1554 struct igmp_ifinfo
*igi
;
1558 VERIFY(igi
!= NULL
);
1560 IGMPSTAT_INC(igps_rcv_ourreports
);
1561 OIGMPSTAT_INC(igps_rcv_ourreports
);
1564 * If we are in IGMPv3 host mode, do not allow the
1565 * other host's IGMPv1 report to suppress our reports
1566 * unless explicitly configured to do so.
1569 if (igi
->igi_version
== IGMP_VERSION_3
) {
1570 if (igmp_legacysupp
)
1571 igmp_v3_suppress_group_record(inm
);
1580 switch (inm
->inm_state
) {
1581 case IGMP_NOT_MEMBER
:
1582 case IGMP_SILENT_MEMBER
:
1583 case IGMP_SLEEPING_MEMBER
:
1585 case IGMP_REPORTING_MEMBER
:
1586 case IGMP_IDLE_MEMBER
:
1587 case IGMP_AWAKENING_MEMBER
:
1588 IGMP_INET_PRINTF(igmp
->igmp_group
,
1589 ("report suppressed for %s on ifp 0x%llx(%s)\n",
1590 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(ifp
),
1592 case IGMP_LAZY_MEMBER
:
1593 inm
->inm_state
= IGMP_LAZY_MEMBER
;
1595 case IGMP_G_QUERY_PENDING_MEMBER
:
1596 case IGMP_SG_QUERY_PENDING_MEMBER
:
1597 case IGMP_LEAVING_MEMBER
:
1609 igmp_input(struct mbuf
*m
, int off
)
1619 IGMP_PRINTF(("%s: called w/mbuf (0x%llx,%d)\n", __func__
,
1620 (uint64_t)VM_KERNEL_ADDRPERM(m
), off
));
1622 ifp
= m
->m_pkthdr
.rcvif
;
1624 IGMPSTAT_INC(igps_rcv_total
);
1625 OIGMPSTAT_INC(igps_rcv_total
);
1627 /* Expect 32-bit aligned data pointer on strict-align platforms */
1628 MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
);
1630 ip
= mtod(m
, struct ip
*);
1633 /* By now, ip_len no longer contains the length of IP header */
1634 igmplen
= ip
->ip_len
;
1639 if (igmplen
< IGMP_MINLEN
) {
1640 IGMPSTAT_INC(igps_rcv_tooshort
);
1641 OIGMPSTAT_INC(igps_rcv_tooshort
);
1647 * Always pullup to the minimum size for v1/v2 or v3
1648 * to amortize calls to m_pulldown().
1650 if (igmplen
>= IGMP_V3_QUERY_MINLEN
)
1651 minlen
= IGMP_V3_QUERY_MINLEN
;
1653 minlen
= IGMP_MINLEN
;
1655 /* A bit more expensive than M_STRUCT_GET, but ensures alignment */
1656 M_STRUCT_GET0(igmp
, struct igmp
*, m
, off
, minlen
);
1658 IGMPSTAT_INC(igps_rcv_tooshort
);
1659 OIGMPSTAT_INC(igps_rcv_tooshort
);
1662 /* N.B.: we assume the packet was correctly aligned in ip_input. */
1665 * Validate checksum.
1667 m
->m_data
+= iphlen
;
1669 if (in_cksum(m
, igmplen
)) {
1670 IGMPSTAT_INC(igps_rcv_badsum
);
1671 OIGMPSTAT_INC(igps_rcv_badsum
);
1675 m
->m_data
-= iphlen
;
1679 * IGMP control traffic is link-scope, and must have a TTL of 1.
1680 * DVMRP traffic (e.g. mrinfo, mtrace) is an exception;
1681 * probe packets may come from beyond the LAN.
1683 if (igmp
->igmp_type
!= IGMP_DVMRP
&& ip
->ip_ttl
!= 1) {
1684 IGMPSTAT_INC(igps_rcv_badttl
);
1689 switch (igmp
->igmp_type
) {
1690 case IGMP_HOST_MEMBERSHIP_QUERY
:
1691 if (igmplen
== IGMP_MINLEN
) {
1692 if (igmp
->igmp_code
== 0)
1693 queryver
= IGMP_VERSION_1
;
1695 queryver
= IGMP_VERSION_2
;
1696 } else if (igmplen
>= IGMP_V3_QUERY_MINLEN
) {
1697 queryver
= IGMP_VERSION_3
;
1699 IGMPSTAT_INC(igps_rcv_tooshort
);
1700 OIGMPSTAT_INC(igps_rcv_tooshort
);
1705 OIGMPSTAT_INC(igps_rcv_queries
);
1708 case IGMP_VERSION_1
:
1709 IGMPSTAT_INC(igps_rcv_v1v2_queries
);
1712 if (igmp_input_v1_query(ifp
, ip
, igmp
) != 0) {
1718 case IGMP_VERSION_2
:
1719 IGMPSTAT_INC(igps_rcv_v1v2_queries
);
1722 if (igmp_input_v2_query(ifp
, ip
, igmp
) != 0) {
1728 case IGMP_VERSION_3
: {
1729 struct igmpv3
*igmpv3
;
1734 IGMPSTAT_INC(igps_rcv_v3_queries
);
1735 igmpv3
= (struct igmpv3
*)igmp
;
1737 * Validate length based on source count.
1739 nsrc
= ntohs(igmpv3
->igmp_numsrc
);
1741 * The max vaue of nsrc is limited by the
1742 * MTU of the network on which the datagram
1745 if (nsrc
< 0 || nsrc
> IGMP_V3_QUERY_MAX_SRCS
) {
1746 IGMPSTAT_INC(igps_rcv_tooshort
);
1747 OIGMPSTAT_INC(igps_rcv_tooshort
);
1751 srclen
= sizeof(struct in_addr
) * nsrc
;
1752 if (igmplen
< (IGMP_V3_QUERY_MINLEN
+ srclen
)) {
1753 IGMPSTAT_INC(igps_rcv_tooshort
);
1754 OIGMPSTAT_INC(igps_rcv_tooshort
);
1758 igmpv3len
= IGMP_V3_QUERY_MINLEN
+ srclen
;
1760 * A bit more expensive than M_STRUCT_GET,
1761 * but ensures alignment.
1763 M_STRUCT_GET0(igmpv3
, struct igmpv3
*, m
,
1765 if (igmpv3
== NULL
) {
1766 IGMPSTAT_INC(igps_rcv_tooshort
);
1767 OIGMPSTAT_INC(igps_rcv_tooshort
);
1771 * N.B.: we assume the packet was correctly
1772 * aligned in ip_input.
1774 if (igmp_input_v3_query(ifp
, ip
, igmpv3
) != 0) {
1783 case IGMP_v1_HOST_MEMBERSHIP_REPORT
:
1786 if (igmp_input_v1_report(ifp
, m
, ip
, igmp
) != 0) {
1792 case IGMP_v2_HOST_MEMBERSHIP_REPORT
:
1795 if (!ip_checkrouteralert(m
))
1796 IGMPSTAT_INC(igps_rcv_nora
);
1797 if (igmp_input_v2_report(ifp
, m
, ip
, igmp
) != 0) {
1803 case IGMP_v3_HOST_MEMBERSHIP_REPORT
:
1805 * Hosts do not need to process IGMPv3 membership reports,
1806 * as report suppression is no longer required.
1808 if (!ip_checkrouteralert(m
))
1809 IGMPSTAT_INC(igps_rcv_nora
);
1816 IGMP_LOCK_ASSERT_NOTHELD();
1818 * Pass all valid IGMP packets up to any process(es) listening on a
1825 * Schedule IGMP timer based on various parameters; caller must ensure that
1826 * lock ordering is maintained as this routine acquires IGMP global lock.
1829 igmp_set_timeout(struct igmp_tparams
*itp
)
1831 IGMP_LOCK_ASSERT_NOTHELD();
1832 VERIFY(itp
!= NULL
);
1834 if (itp
->qpt
!= 0 || itp
->it
!= 0 || itp
->cst
!= 0 || itp
->sct
!= 0) {
1837 querier_present_timers_running
= 1;
1839 interface_timers_running
= 1;
1841 current_state_timers_running
= 1;
1843 state_change_timers_running
= 1;
1844 igmp_sched_timeout();
1850 * IGMP timer handler (per 1 second).
1853 igmp_timeout(void *arg
)
1856 struct ifqueue scq
; /* State-change packets */
1857 struct ifqueue qrq
; /* Query response packets */
1859 struct igmp_ifinfo
*igi
;
1860 struct in_multi
*inm
;
1861 int loop
= 0, uri_sec
= 0;
1862 SLIST_HEAD(, in_multi
) inm_dthead
;
1864 SLIST_INIT(&inm_dthead
);
1867 * Update coarse-grained networking timestamp (in sec.); the idea
1868 * is to piggy-back on the timeout callout to update the counter
1869 * returnable via net_uptime().
1871 net_update_uptime();
1875 IGMP_PRINTF(("%s: qpt %d, it %d, cst %d, sct %d\n", __func__
,
1876 querier_present_timers_running
, interface_timers_running
,
1877 current_state_timers_running
, state_change_timers_running
));
1880 * IGMPv1/v2 querier present timer processing.
1882 if (querier_present_timers_running
) {
1883 querier_present_timers_running
= 0;
1884 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1886 igmp_v1v2_process_querier_timers(igi
);
1887 if (igi
->igi_v1_timer
> 0 || igi
->igi_v2_timer
> 0)
1888 querier_present_timers_running
= 1;
1894 * IGMPv3 General Query response timer processing.
1896 if (interface_timers_running
) {
1897 IGMP_PRINTF(("%s: interface timers running\n", __func__
));
1898 interface_timers_running
= 0;
1899 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1901 if (igi
->igi_version
!= IGMP_VERSION_3
) {
1905 if (igi
->igi_v3_timer
== 0) {
1907 } else if (--igi
->igi_v3_timer
== 0) {
1908 if (igmp_v3_dispatch_general_query(igi
) > 0)
1909 interface_timers_running
= 1;
1911 interface_timers_running
= 1;
1917 if (!current_state_timers_running
&&
1918 !state_change_timers_running
)
1921 current_state_timers_running
= 0;
1922 state_change_timers_running
= 0;
1924 memset(&qrq
, 0, sizeof(struct ifqueue
));
1925 qrq
.ifq_maxlen
= IGMP_MAX_G_GS_PACKETS
;
1927 memset(&scq
, 0, sizeof(struct ifqueue
));
1928 scq
.ifq_maxlen
= IGMP_MAX_STATE_CHANGE_PACKETS
;
1930 IGMP_PRINTF(("%s: state change timers running\n", __func__
));
1933 * IGMPv1/v2/v3 host report and state-change timer processing.
1934 * Note: Processing a v3 group timer may remove a node.
1936 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1937 struct in_multistep step
;
1941 loop
= (igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : 0;
1942 uri_sec
= IGMP_RANDOM_DELAY(igi
->igi_uri
);
1945 in_multihead_lock_shared();
1946 IN_FIRST_MULTI(step
, inm
);
1947 while (inm
!= NULL
) {
1949 if (inm
->inm_ifp
!= ifp
)
1953 switch (igi
->igi_version
) {
1954 case IGMP_VERSION_1
:
1955 case IGMP_VERSION_2
:
1956 igmp_v1v2_process_group_timer(inm
,
1959 case IGMP_VERSION_3
:
1960 igmp_v3_process_group_timers(igi
, &qrq
,
1961 &scq
, inm
, uri_sec
);
1967 IN_NEXT_MULTI(step
, inm
);
1969 in_multihead_lock_done();
1972 if (igi
->igi_version
== IGMP_VERSION_1
||
1973 igi
->igi_version
== IGMP_VERSION_2
) {
1974 igmp_dispatch_queue(igi
, &igi
->igi_v2q
, 0, loop
);
1975 } else if (igi
->igi_version
== IGMP_VERSION_3
) {
1977 igmp_dispatch_queue(NULL
, &qrq
, 0, loop
);
1978 igmp_dispatch_queue(NULL
, &scq
, 0, loop
);
1979 VERIFY(qrq
.ifq_len
== 0);
1980 VERIFY(scq
.ifq_len
== 0);
1984 * In case there are still any pending membership reports
1985 * which didn't get drained at version change time.
1987 IF_DRAIN(&igi
->igi_v2q
);
1989 * Release all deferred inm records, and drain any locally
1990 * enqueued packets; do it even if the current IGMP version
1991 * for the link is no longer IGMPv3, in order to handle the
1992 * version change case.
1994 igmp_flush_relq(igi
, (struct igmp_inm_relhead
*)&inm_dthead
);
1995 VERIFY(SLIST_EMPTY(&igi
->igi_relinmhead
));
2003 /* re-arm the timer if there's work to do */
2004 igmp_timeout_run
= 0;
2005 igmp_sched_timeout();
2008 /* Now that we're dropped all locks, release detached records */
2009 IGMP_REMOVE_DETACHED_INM(&inm_dthead
);
2013 igmp_sched_timeout(void)
2015 IGMP_LOCK_ASSERT_HELD();
2017 if (!igmp_timeout_run
&&
2018 (querier_present_timers_running
|| current_state_timers_running
||
2019 interface_timers_running
|| state_change_timers_running
)) {
2020 igmp_timeout_run
= 1;
2021 timeout(igmp_timeout
, NULL
, hz
);
2026 * Free the in_multi reference(s) for this IGMP lifecycle.
2028 * Caller must be holding igi_lock.
2031 igmp_flush_relq(struct igmp_ifinfo
*igi
, struct igmp_inm_relhead
*inm_dthead
)
2033 struct in_multi
*inm
;
2036 IGI_LOCK_ASSERT_HELD(igi
);
2037 inm
= SLIST_FIRST(&igi
->igi_relinmhead
);
2041 SLIST_REMOVE_HEAD(&igi
->igi_relinmhead
, inm_nrele
);
2044 in_multihead_lock_exclusive();
2046 VERIFY(inm
->inm_nrelecnt
!= 0);
2047 inm
->inm_nrelecnt
--;
2048 lastref
= in_multi_detach(inm
);
2049 VERIFY(!lastref
|| (!(inm
->inm_debug
& IFD_ATTACHED
) &&
2050 inm
->inm_reqcnt
== 0));
2052 in_multihead_lock_done();
2053 /* from igi_relinmhead */
2055 /* from in_multihead list */
2058 * Defer releasing our final reference, as we
2059 * are holding the IGMP lock at this point, and
2060 * we could end up with locking issues later on
2061 * (while issuing SIOCDELMULTI) when this is the
2062 * final reference count. Let the caller do it
2065 IGMP_ADD_DETACHED_INM(inm_dthead
, inm
);
2073 * Update host report group timer for IGMPv1/v2.
2074 * Will update the global pending timer flags.
2077 igmp_v1v2_process_group_timer(struct in_multi
*inm
, const int igmp_version
)
2079 int report_timer_expired
;
2081 IGMP_LOCK_ASSERT_HELD();
2082 INM_LOCK_ASSERT_HELD(inm
);
2083 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2085 if (inm
->inm_timer
== 0) {
2086 report_timer_expired
= 0;
2087 } else if (--inm
->inm_timer
== 0) {
2088 report_timer_expired
= 1;
2090 current_state_timers_running
= 1;
2091 /* caller will schedule timer */
2095 switch (inm
->inm_state
) {
2096 case IGMP_NOT_MEMBER
:
2097 case IGMP_SILENT_MEMBER
:
2098 case IGMP_IDLE_MEMBER
:
2099 case IGMP_LAZY_MEMBER
:
2100 case IGMP_SLEEPING_MEMBER
:
2101 case IGMP_AWAKENING_MEMBER
:
2103 case IGMP_REPORTING_MEMBER
:
2104 if (report_timer_expired
) {
2105 inm
->inm_state
= IGMP_IDLE_MEMBER
;
2106 (void) igmp_v1v2_queue_report(inm
,
2107 (igmp_version
== IGMP_VERSION_2
) ?
2108 IGMP_v2_HOST_MEMBERSHIP_REPORT
:
2109 IGMP_v1_HOST_MEMBERSHIP_REPORT
);
2110 INM_LOCK_ASSERT_HELD(inm
);
2111 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2114 case IGMP_G_QUERY_PENDING_MEMBER
:
2115 case IGMP_SG_QUERY_PENDING_MEMBER
:
2116 case IGMP_LEAVING_MEMBER
:
2122 * Update a group's timers for IGMPv3.
2123 * Will update the global pending timer flags.
2124 * Note: Unlocked read from igi.
2127 igmp_v3_process_group_timers(struct igmp_ifinfo
*igi
,
2128 struct ifqueue
*qrq
, struct ifqueue
*scq
,
2129 struct in_multi
*inm
, const int uri_sec
)
2131 int query_response_timer_expired
;
2132 int state_change_retransmit_timer_expired
;
2134 IGMP_LOCK_ASSERT_HELD();
2135 INM_LOCK_ASSERT_HELD(inm
);
2136 IGI_LOCK_ASSERT_HELD(igi
);
2137 VERIFY(igi
== inm
->inm_igi
);
2139 query_response_timer_expired
= 0;
2140 state_change_retransmit_timer_expired
= 0;
2143 * During a transition from v1/v2 compatibility mode back to v3,
2144 * a group record in REPORTING state may still have its group
2145 * timer active. This is a no-op in this function; it is easier
2146 * to deal with it here than to complicate the timeout path.
2148 if (inm
->inm_timer
== 0) {
2149 query_response_timer_expired
= 0;
2150 } else if (--inm
->inm_timer
== 0) {
2151 query_response_timer_expired
= 1;
2153 current_state_timers_running
= 1;
2154 /* caller will schedule timer */
2157 if (inm
->inm_sctimer
== 0) {
2158 state_change_retransmit_timer_expired
= 0;
2159 } else if (--inm
->inm_sctimer
== 0) {
2160 state_change_retransmit_timer_expired
= 1;
2162 state_change_timers_running
= 1;
2163 /* caller will schedule timer */
2166 /* We are in timer callback, so be quick about it. */
2167 if (!state_change_retransmit_timer_expired
&&
2168 !query_response_timer_expired
)
2171 switch (inm
->inm_state
) {
2172 case IGMP_NOT_MEMBER
:
2173 case IGMP_SILENT_MEMBER
:
2174 case IGMP_SLEEPING_MEMBER
:
2175 case IGMP_LAZY_MEMBER
:
2176 case IGMP_AWAKENING_MEMBER
:
2177 case IGMP_IDLE_MEMBER
:
2179 case IGMP_G_QUERY_PENDING_MEMBER
:
2180 case IGMP_SG_QUERY_PENDING_MEMBER
:
2182 * Respond to a previously pending Group-Specific
2183 * or Group-and-Source-Specific query by enqueueing
2184 * the appropriate Current-State report for
2185 * immediate transmission.
2187 if (query_response_timer_expired
) {
2190 retval
= igmp_v3_enqueue_group_record(qrq
, inm
, 0, 1,
2191 (inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
));
2192 IGMP_PRINTF(("%s: enqueue record = %d\n",
2194 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2195 /* XXX Clear recorded sources for next time. */
2196 inm_clear_recorded(inm
);
2199 case IGMP_REPORTING_MEMBER
:
2200 case IGMP_LEAVING_MEMBER
:
2201 if (state_change_retransmit_timer_expired
) {
2203 * State-change retransmission timer fired.
2204 * If there are any further pending retransmissions,
2205 * set the global pending state-change flag, and
2208 if (--inm
->inm_scrv
> 0) {
2209 inm
->inm_sctimer
= uri_sec
;
2210 state_change_timers_running
= 1;
2211 /* caller will schedule timer */
2214 * Retransmit the previously computed state-change
2215 * report. If there are no further pending
2216 * retransmissions, the mbuf queue will be consumed.
2217 * Update T0 state to T1 as we have now sent
2220 (void) igmp_v3_merge_state_changes(inm
, scq
);
2223 IGMP_INET_PRINTF(inm
->inm_addr
,
2224 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2225 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2228 * If we are leaving the group for good, make sure
2229 * we release IGMP's reference to it.
2230 * This release must be deferred using a SLIST,
2231 * as we are called from a loop which traverses
2232 * the in_multihead list.
2234 if (inm
->inm_state
== IGMP_LEAVING_MEMBER
&&
2235 inm
->inm_scrv
== 0) {
2236 inm
->inm_state
= IGMP_NOT_MEMBER
;
2238 * A reference has already been held in
2239 * igmp_final_leave() for this inm, so
2240 * no need to hold another one. We also
2241 * bumped up its request count then, so
2242 * that it stays in in_multihead. Both
2243 * of them will be released when it is
2244 * dequeued later on.
2246 VERIFY(inm
->inm_nrelecnt
!= 0);
2247 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
,
2256 * Suppress a group's pending response to a group or source/group query.
2258 * Do NOT suppress state changes. This leads to IGMPv3 inconsistency.
2259 * Do NOT update ST1/ST0 as this operation merely suppresses
2260 * the currently pending group record.
2261 * Do NOT suppress the response to a general query. It is possible but
2262 * it would require adding another state or flag.
2265 igmp_v3_suppress_group_record(struct in_multi
*inm
)
2268 INM_LOCK_ASSERT_HELD(inm
);
2269 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2271 VERIFY(inm
->inm_igi
->igi_version
== IGMP_VERSION_3
);
2273 if (inm
->inm_state
!= IGMP_G_QUERY_PENDING_MEMBER
||
2274 inm
->inm_state
!= IGMP_SG_QUERY_PENDING_MEMBER
)
2277 if (inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
)
2278 inm_clear_recorded(inm
);
2281 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2285 * Switch to a different IGMP version on the given interface,
2286 * as per Section 7.2.1.
2289 igmp_set_version(struct igmp_ifinfo
*igi
, const int igmp_version
)
2291 int old_version_timer
;
2293 IGI_LOCK_ASSERT_HELD(igi
);
2295 IGMP_PRINTF(("%s: switching to v%d on ifp 0x%llx(%s)\n", __func__
,
2296 igmp_version
, (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2297 if_name(igi
->igi_ifp
)));
2299 if (igmp_version
== IGMP_VERSION_1
|| igmp_version
== IGMP_VERSION_2
) {
2301 * Compute the "Older Version Querier Present" timer as per
2302 * Section 8.12, in seconds.
2304 old_version_timer
= igi
->igi_rv
* igi
->igi_qi
+ igi
->igi_qri
;
2306 if (igmp_version
== IGMP_VERSION_1
) {
2307 igi
->igi_v1_timer
= old_version_timer
;
2308 igi
->igi_v2_timer
= 0;
2309 } else if (igmp_version
== IGMP_VERSION_2
) {
2310 igi
->igi_v1_timer
= 0;
2311 igi
->igi_v2_timer
= old_version_timer
;
2315 if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
> 0) {
2316 if (igi
->igi_version
!= IGMP_VERSION_2
) {
2317 igi
->igi_version
= IGMP_VERSION_2
;
2318 igmp_v3_cancel_link_timers(igi
);
2320 } else if (igi
->igi_v1_timer
> 0) {
2321 if (igi
->igi_version
!= IGMP_VERSION_1
) {
2322 igi
->igi_version
= IGMP_VERSION_1
;
2323 igmp_v3_cancel_link_timers(igi
);
2327 IGI_LOCK_ASSERT_HELD(igi
);
2329 return (MAX(igi
->igi_v1_timer
, igi
->igi_v2_timer
));
2333 * Cancel pending IGMPv3 timers for the given link and all groups
2334 * joined on it; state-change, general-query, and group-query timers.
2336 * Only ever called on a transition from v3 to Compatibility mode. Kill
2337 * the timers stone dead (this may be expensive for large N groups), they
2338 * will be restarted if Compatibility Mode deems that they must be due to
2342 igmp_v3_cancel_link_timers(struct igmp_ifinfo
*igi
)
2345 struct in_multi
*inm
;
2346 struct in_multistep step
;
2348 IGI_LOCK_ASSERT_HELD(igi
);
2350 IGMP_PRINTF(("%s: cancel v3 timers on ifp 0x%llx(%s)\n", __func__
,
2351 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
), if_name(igi
->igi_ifp
)));
2354 * Stop the v3 General Query Response on this link stone dead.
2355 * If timer is woken up due to interface_timers_running,
2356 * the flag will be cleared if there are no pending link timers.
2358 igi
->igi_v3_timer
= 0;
2361 * Now clear the current-state and state-change report timers
2362 * for all memberships scoped to this link.
2367 in_multihead_lock_shared();
2368 IN_FIRST_MULTI(step
, inm
);
2369 while (inm
!= NULL
) {
2371 if (inm
->inm_ifp
!= ifp
)
2374 switch (inm
->inm_state
) {
2375 case IGMP_NOT_MEMBER
:
2376 case IGMP_SILENT_MEMBER
:
2377 case IGMP_IDLE_MEMBER
:
2378 case IGMP_LAZY_MEMBER
:
2379 case IGMP_SLEEPING_MEMBER
:
2380 case IGMP_AWAKENING_MEMBER
:
2382 * These states are either not relevant in v3 mode,
2383 * or are unreported. Do nothing.
2386 case IGMP_LEAVING_MEMBER
:
2388 * If we are leaving the group and switching to
2389 * compatibility mode, we need to release the final
2390 * reference held for issuing the INCLUDE {}, and
2391 * transition to REPORTING to ensure the host leave
2392 * message is sent upstream to the old querier --
2393 * transition to NOT would lose the leave and race.
2394 * During igmp_final_leave(), we bumped up both the
2395 * request and reference counts. Since we cannot
2396 * call in_multi_detach() here, defer this task to
2397 * the timer routine.
2399 VERIFY(inm
->inm_nrelecnt
!= 0);
2401 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
, inm
, inm_nrele
);
2404 case IGMP_G_QUERY_PENDING_MEMBER
:
2405 case IGMP_SG_QUERY_PENDING_MEMBER
:
2406 inm_clear_recorded(inm
);
2408 case IGMP_REPORTING_MEMBER
:
2409 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2413 * Always clear state-change and group report timers.
2414 * Free any pending IGMPv3 state-change records.
2416 inm
->inm_sctimer
= 0;
2418 IF_DRAIN(&inm
->inm_scq
);
2421 IN_NEXT_MULTI(step
, inm
);
2423 in_multihead_lock_done();
2429 * Update the Older Version Querier Present timers for a link.
2430 * See Section 7.2.1 of RFC 3376.
2433 igmp_v1v2_process_querier_timers(struct igmp_ifinfo
*igi
)
2435 IGI_LOCK_ASSERT_HELD(igi
);
2437 if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
== 0) {
2439 * IGMPv1 and IGMPv2 Querier Present timers expired.
2443 if (igi
->igi_version
!= IGMP_VERSION_3
) {
2444 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2445 "on 0x%llx(%s)\n", __func__
,
2446 igi
->igi_version
, IGMP_VERSION_3
,
2447 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2448 if_name(igi
->igi_ifp
)));
2449 igi
->igi_version
= IGMP_VERSION_3
;
2450 IF_DRAIN(&igi
->igi_v2q
);
2452 } else if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
> 0) {
2454 * IGMPv1 Querier Present timer expired,
2455 * IGMPv2 Querier Present timer running.
2456 * If IGMPv2 was disabled since last timeout,
2458 * If IGMPv2 is enabled, revert to IGMPv2.
2460 if (!igmp_v2enable
) {
2461 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2462 "on 0x%llx(%s%d)\n", __func__
,
2463 igi
->igi_version
, IGMP_VERSION_3
,
2464 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2465 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2466 igi
->igi_v2_timer
= 0;
2467 igi
->igi_version
= IGMP_VERSION_3
;
2468 IF_DRAIN(&igi
->igi_v2q
);
2470 --igi
->igi_v2_timer
;
2471 if (igi
->igi_version
!= IGMP_VERSION_2
) {
2472 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2473 "on 0x%llx(%s)\n", __func__
,
2474 igi
->igi_version
, IGMP_VERSION_2
,
2475 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2476 if_name(igi
->igi_ifp
)));
2477 igi
->igi_version
= IGMP_VERSION_2
;
2478 IF_DRAIN(&igi
->igi_gq
);
2479 igmp_v3_cancel_link_timers(igi
);
2482 } else if (igi
->igi_v1_timer
> 0) {
2484 * IGMPv1 Querier Present timer running.
2485 * Stop IGMPv2 timer if running.
2487 * If IGMPv1 was disabled since last timeout,
2489 * If IGMPv1 is enabled, reset IGMPv2 timer if running.
2491 if (!igmp_v1enable
) {
2492 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2493 "on 0x%llx(%s%d)\n", __func__
,
2494 igi
->igi_version
, IGMP_VERSION_3
,
2495 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2496 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2497 igi
->igi_v1_timer
= 0;
2498 igi
->igi_version
= IGMP_VERSION_3
;
2499 IF_DRAIN(&igi
->igi_v2q
);
2501 --igi
->igi_v1_timer
;
2503 if (igi
->igi_v2_timer
> 0) {
2504 IGMP_PRINTF(("%s: cancel v2 timer on 0x%llx(%s%d)\n",
2506 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2507 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2508 igi
->igi_v2_timer
= 0;
2514 * Dispatch an IGMPv1/v2 host report or leave message.
2515 * These are always small enough to fit inside a single mbuf.
2518 igmp_v1v2_queue_report(struct in_multi
*inm
, const int type
)
2526 INM_LOCK_ASSERT_HELD(inm
);
2527 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2531 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
2534 MH_ALIGN(m
, sizeof(struct ip
) + sizeof(struct igmp
));
2536 m
->m_pkthdr
.len
= sizeof(struct ip
) + sizeof(struct igmp
);
2538 m
->m_data
+= sizeof(struct ip
);
2539 m
->m_len
= sizeof(struct igmp
);
2541 igmp
= mtod(m
, struct igmp
*);
2542 igmp
->igmp_type
= type
;
2543 igmp
->igmp_code
= 0;
2544 igmp
->igmp_group
= inm
->inm_addr
;
2545 igmp
->igmp_cksum
= 0;
2546 igmp
->igmp_cksum
= in_cksum(m
, sizeof(struct igmp
));
2548 m
->m_data
-= sizeof(struct ip
);
2549 m
->m_len
+= sizeof(struct ip
);
2551 ip
= mtod(m
, struct ip
*);
2553 ip
->ip_len
= sizeof(struct ip
) + sizeof(struct igmp
);
2555 ip
->ip_p
= IPPROTO_IGMP
;
2556 ip
->ip_src
.s_addr
= INADDR_ANY
;
2558 if (type
== IGMP_HOST_LEAVE_MESSAGE
)
2559 ip
->ip_dst
.s_addr
= htonl(INADDR_ALLRTRS_GROUP
);
2561 ip
->ip_dst
= inm
->inm_addr
;
2563 igmp_save_context(m
, ifp
);
2565 m
->m_flags
|= M_IGMPV2
;
2566 if (inm
->inm_igi
->igi_flags
& IGIF_LOOPBACK
)
2567 m
->m_flags
|= M_IGMP_LOOP
;
2570 * Due to the fact that at this point we are possibly holding
2571 * in_multihead_lock in shared or exclusive mode, we can't call
2572 * igmp_sendpkt() here since that will eventually call ip_output(),
2573 * which will try to lock in_multihead_lock and cause a deadlock.
2574 * Instead we defer the work to the igmp_timeout() thread, thus
2575 * avoiding unlocking in_multihead_lock here.
2577 if (IF_QFULL(&inm
->inm_igi
->igi_v2q
)) {
2578 IGMP_PRINTF(("%s: v1/v2 outbound queue full\n", __func__
));
2582 IF_ENQUEUE(&inm
->inm_igi
->igi_v2q
, m
);
2589 * Process a state change from the upper layer for the given IPv4 group.
2591 * Each socket holds a reference on the in_multi in its own ip_moptions.
2592 * The socket layer will have made the necessary updates to the group
2593 * state, it is now up to IGMP to issue a state change report if there
2594 * has been any change between T0 (when the last state-change was issued)
2597 * We use the IGMPv3 state machine at group level. The IGMP module
2598 * however makes the decision as to which IGMP protocol version to speak.
2599 * A state change *from* INCLUDE {} always means an initial join.
2600 * A state change *to* INCLUDE {} always means a final leave.
2602 * FUTURE: If IGIF_V3LITE is enabled for this interface, then we can
2603 * save ourselves a bunch of work; any exclusive mode groups need not
2604 * compute source filter lists.
2607 igmp_change_state(struct in_multi
*inm
, struct igmp_tparams
*itp
)
2609 struct igmp_ifinfo
*igi
;
2613 VERIFY(itp
!= NULL
);
2614 bzero(itp
, sizeof (*itp
));
2616 INM_LOCK_ASSERT_HELD(inm
);
2617 VERIFY(inm
->inm_igi
!= NULL
);
2618 IGI_LOCK_ASSERT_NOTHELD(inm
->inm_igi
);
2621 * Try to detect if the upper layer just asked us to change state
2622 * for an interface which has now gone away.
2624 VERIFY(inm
->inm_ifma
!= NULL
);
2625 ifp
= inm
->inm_ifma
->ifma_ifp
;
2627 * Sanity check that netinet's notion of ifp is the same as net's.
2629 VERIFY(inm
->inm_ifp
== ifp
);
2631 igi
= IGMP_IFINFO(ifp
);
2632 VERIFY(igi
!= NULL
);
2635 * If we detect a state transition to or from MCAST_UNDEFINED
2636 * for this group, then we are starting or finishing an IGMP
2637 * life cycle for this group.
2639 if (inm
->inm_st
[1].iss_fmode
!= inm
->inm_st
[0].iss_fmode
) {
2640 IGMP_PRINTF(("%s: inm transition %d -> %d\n", __func__
,
2641 inm
->inm_st
[0].iss_fmode
, inm
->inm_st
[1].iss_fmode
));
2642 if (inm
->inm_st
[0].iss_fmode
== MCAST_UNDEFINED
) {
2643 IGMP_PRINTF(("%s: initial join\n", __func__
));
2644 error
= igmp_initial_join(inm
, igi
, itp
);
2646 } else if (inm
->inm_st
[1].iss_fmode
== MCAST_UNDEFINED
) {
2647 IGMP_PRINTF(("%s: final leave\n", __func__
));
2648 igmp_final_leave(inm
, igi
, itp
);
2652 IGMP_PRINTF(("%s: filter set change\n", __func__
));
2655 error
= igmp_handle_state_change(inm
, igi
, itp
);
2661 * Perform the initial join for an IGMP group.
2663 * When joining a group:
2664 * If the group should have its IGMP traffic suppressed, do nothing.
2665 * IGMPv1 starts sending IGMPv1 host membership reports.
2666 * IGMPv2 starts sending IGMPv2 host membership reports.
2667 * IGMPv3 will schedule an IGMPv3 state-change report containing the
2668 * initial state of the membership.
2671 igmp_initial_join(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2672 struct igmp_tparams
*itp
)
2675 struct ifqueue
*ifq
;
2676 int error
, retval
, syncstates
;
2678 INM_LOCK_ASSERT_HELD(inm
);
2679 IGI_LOCK_ASSERT_NOTHELD(igi
);
2680 VERIFY(itp
!= NULL
);
2682 IGMP_INET_PRINTF(inm
->inm_addr
,
2683 ("%s: initial join %s on ifp 0x%llx(%s)\n", __func__
,
2684 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2685 if_name(inm
->inm_ifp
)));
2693 VERIFY(igi
->igi_ifp
== ifp
);
2696 * Groups joined on loopback or marked as 'not reported',
2697 * e.g. 224.0.0.1, enter the IGMP_SILENT_MEMBER state and
2698 * are never reported in any IGMP protocol exchanges.
2699 * All other groups enter the appropriate IGMP state machine
2700 * for the version in use on this link.
2701 * A link marked as IGIF_SILENT causes IGMP to be completely
2702 * disabled for the link.
2704 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2705 (igi
->igi_flags
& IGIF_SILENT
) ||
2706 !igmp_isgroupreported(inm
->inm_addr
)) {
2707 IGMP_PRINTF(("%s: not kicking state machine for silent group\n",
2709 inm
->inm_state
= IGMP_SILENT_MEMBER
;
2713 * Deal with overlapping in_multi lifecycle.
2714 * If this group was LEAVING, then make sure
2715 * we drop the reference we picked up to keep the
2716 * group around for the final INCLUDE {} enqueue.
2717 * Since we cannot call in_multi_detach() here,
2718 * defer this task to the timer routine.
2720 if (igi
->igi_version
== IGMP_VERSION_3
&&
2721 inm
->inm_state
== IGMP_LEAVING_MEMBER
) {
2722 VERIFY(inm
->inm_nrelecnt
!= 0);
2723 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
, inm
, inm_nrele
);
2726 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2728 switch (igi
->igi_version
) {
2729 case IGMP_VERSION_1
:
2730 case IGMP_VERSION_2
:
2731 inm
->inm_state
= IGMP_IDLE_MEMBER
;
2732 error
= igmp_v1v2_queue_report(inm
,
2733 (igi
->igi_version
== IGMP_VERSION_2
) ?
2734 IGMP_v2_HOST_MEMBERSHIP_REPORT
:
2735 IGMP_v1_HOST_MEMBERSHIP_REPORT
);
2737 INM_LOCK_ASSERT_HELD(inm
);
2738 IGI_LOCK_ASSERT_HELD(igi
);
2742 IGMP_RANDOM_DELAY(IGMP_V1V2_MAX_RI
);
2747 case IGMP_VERSION_3
:
2749 * Defer update of T0 to T1, until the first copy
2750 * of the state change has been transmitted.
2755 * Immediately enqueue a State-Change Report for
2756 * this interface, freeing any previous reports.
2757 * Don't kick the timers if there is nothing to do,
2758 * or if an error occurred.
2760 ifq
= &inm
->inm_scq
;
2762 retval
= igmp_v3_enqueue_group_record(ifq
, inm
, 1,
2764 itp
->cst
= (ifq
->ifq_len
> 0);
2765 IGMP_PRINTF(("%s: enqueue record = %d\n",
2768 error
= retval
* -1;
2773 * Schedule transmission of pending state-change
2774 * report up to RV times for this link. The timer
2775 * will fire at the next igmp_timeout (1 second),
2776 * giving us an opportunity to merge the reports.
2778 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
2781 VERIFY(igi
->igi_rv
> 1);
2782 inm
->inm_scrv
= igi
->igi_rv
;
2784 inm
->inm_sctimer
= 1;
2794 * Only update the T0 state if state change is atomic,
2795 * i.e. we don't need to wait for a timer to fire before we
2796 * can consider the state change to have been communicated.
2800 IGMP_INET_PRINTF(inm
->inm_addr
,
2801 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2802 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2809 * Issue an intermediate state change during the IGMP life-cycle.
2812 igmp_handle_state_change(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2813 struct igmp_tparams
*itp
)
2818 INM_LOCK_ASSERT_HELD(inm
);
2819 IGI_LOCK_ASSERT_NOTHELD(igi
);
2820 VERIFY(itp
!= NULL
);
2822 IGMP_INET_PRINTF(inm
->inm_addr
,
2823 ("%s: state change for %s on ifp 0x%llx(%s)\n", __func__
,
2824 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2825 if_name(inm
->inm_ifp
)));
2830 VERIFY(igi
->igi_ifp
== ifp
);
2832 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2833 (igi
->igi_flags
& IGIF_SILENT
) ||
2834 !igmp_isgroupreported(inm
->inm_addr
) ||
2835 (igi
->igi_version
!= IGMP_VERSION_3
)) {
2837 if (!igmp_isgroupreported(inm
->inm_addr
)) {
2838 IGMP_PRINTF(("%s: not kicking state "
2839 "machine for silent group\n", __func__
));
2841 IGMP_PRINTF(("%s: nothing to do\n", __func__
));
2843 IGMP_INET_PRINTF(inm
->inm_addr
,
2844 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2845 _igmp_inet_buf
, inm
->inm_ifp
->if_name
));
2849 IF_DRAIN(&inm
->inm_scq
);
2851 retval
= igmp_v3_enqueue_group_record(&inm
->inm_scq
, inm
, 1, 0, 0);
2852 itp
->cst
= (inm
->inm_scq
.ifq_len
> 0);
2853 IGMP_PRINTF(("%s: enqueue record = %d\n", __func__
, retval
));
2860 * If record(s) were enqueued, start the state-change
2861 * report timer for this group.
2863 inm
->inm_scrv
= ((igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : igi
->igi_rv
);
2864 inm
->inm_sctimer
= 1;
2872 * Perform the final leave for an IGMP group.
2874 * When leaving a group:
2875 * IGMPv1 does nothing.
2876 * IGMPv2 sends a host leave message, if and only if we are the reporter.
2877 * IGMPv3 enqueues a state-change report containing a transition
2878 * to INCLUDE {} for immediate transmission.
2881 igmp_final_leave(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2882 struct igmp_tparams
*itp
)
2886 INM_LOCK_ASSERT_HELD(inm
);
2887 IGI_LOCK_ASSERT_NOTHELD(igi
);
2888 VERIFY(itp
!= NULL
);
2890 IGMP_INET_PRINTF(inm
->inm_addr
,
2891 ("%s: final leave %s on ifp 0x%llx(%s)\n", __func__
,
2892 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2893 if_name(inm
->inm_ifp
)));
2895 switch (inm
->inm_state
) {
2896 case IGMP_NOT_MEMBER
:
2897 case IGMP_SILENT_MEMBER
:
2898 case IGMP_LEAVING_MEMBER
:
2899 /* Already leaving or left; do nothing. */
2900 IGMP_PRINTF(("%s: not kicking state machine for silent group\n",
2903 case IGMP_REPORTING_MEMBER
:
2904 case IGMP_IDLE_MEMBER
:
2905 case IGMP_G_QUERY_PENDING_MEMBER
:
2906 case IGMP_SG_QUERY_PENDING_MEMBER
:
2908 if (igi
->igi_version
== IGMP_VERSION_2
) {
2909 if (inm
->inm_state
== IGMP_G_QUERY_PENDING_MEMBER
||
2910 inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
) {
2911 panic("%s: IGMPv3 state reached, not IGMPv3 "
2912 "mode\n", __func__
);
2915 /* scheduler timer if enqueue is successful */
2916 itp
->cst
= (igmp_v1v2_queue_report(inm
,
2917 IGMP_HOST_LEAVE_MESSAGE
) == 0);
2919 INM_LOCK_ASSERT_HELD(inm
);
2920 IGI_LOCK_ASSERT_HELD(igi
);
2922 inm
->inm_state
= IGMP_NOT_MEMBER
;
2923 } else if (igi
->igi_version
== IGMP_VERSION_3
) {
2925 * Stop group timer and all pending reports.
2926 * Immediately enqueue a state-change report
2927 * TO_IN {} to be sent on the next timeout,
2928 * giving us an opportunity to merge reports.
2930 IF_DRAIN(&inm
->inm_scq
);
2932 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
2935 inm
->inm_scrv
= igi
->igi_rv
;
2937 IGMP_INET_PRINTF(inm
->inm_addr
,
2938 ("%s: Leaving %s/%s with %d "
2939 "pending retransmissions.\n", __func__
,
2940 _igmp_inet_buf
, if_name(inm
->inm_ifp
),
2942 if (inm
->inm_scrv
== 0) {
2943 inm
->inm_state
= IGMP_NOT_MEMBER
;
2944 inm
->inm_sctimer
= 0;
2948 * Stick around in the in_multihead list;
2949 * the final detach will be issued by
2950 * igmp_v3_process_group_timers() when
2951 * the retransmit timer expires.
2953 INM_ADDREF_LOCKED(inm
);
2954 VERIFY(inm
->inm_debug
& IFD_ATTACHED
);
2956 VERIFY(inm
->inm_reqcnt
>= 1);
2957 inm
->inm_nrelecnt
++;
2958 VERIFY(inm
->inm_nrelecnt
!= 0);
2960 retval
= igmp_v3_enqueue_group_record(
2961 &inm
->inm_scq
, inm
, 1, 0, 0);
2962 itp
->cst
= (inm
->inm_scq
.ifq_len
> 0);
2963 KASSERT(retval
!= 0,
2964 ("%s: enqueue record = %d\n", __func__
,
2967 inm
->inm_state
= IGMP_LEAVING_MEMBER
;
2968 inm
->inm_sctimer
= 1;
2975 case IGMP_LAZY_MEMBER
:
2976 case IGMP_SLEEPING_MEMBER
:
2977 case IGMP_AWAKENING_MEMBER
:
2978 /* Our reports are suppressed; do nothing. */
2984 IGMP_INET_PRINTF(inm
->inm_addr
,
2985 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2986 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2987 inm
->inm_st
[1].iss_fmode
= MCAST_UNDEFINED
;
2988 IGMP_INET_PRINTF(inm
->inm_addr
,
2989 ("%s: T1 now MCAST_UNDEFINED for %s/%s\n",
2990 __func__
, _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2995 * Enqueue an IGMPv3 group record to the given output queue.
2997 * XXX This function could do with having the allocation code
2998 * split out, and the multiple-tree-walks coalesced into a single
2999 * routine as has been done in igmp_v3_enqueue_filter_change().
3001 * If is_state_change is zero, a current-state record is appended.
3002 * If is_state_change is non-zero, a state-change report is appended.
3004 * If is_group_query is non-zero, an mbuf packet chain is allocated.
3005 * If is_group_query is zero, and if there is a packet with free space
3006 * at the tail of the queue, it will be appended to providing there
3007 * is enough free space.
3008 * Otherwise a new mbuf packet chain is allocated.
3010 * If is_source_query is non-zero, each source is checked to see if
3011 * it was recorded for a Group-Source query, and will be omitted if
3012 * it is not both in-mode and recorded.
3014 * The function will attempt to allocate leading space in the packet
3015 * for the IP/IGMP header to be prepended without fragmenting the chain.
3017 * If successful the size of all data appended to the queue is returned,
3018 * otherwise an error code less than zero is returned, or zero if
3019 * no record(s) were appended.
3022 igmp_v3_enqueue_group_record(struct ifqueue
*ifq
, struct in_multi
*inm
,
3023 const int is_state_change
, const int is_group_query
,
3024 const int is_source_query
)
3026 struct igmp_grouprec ig
;
3027 struct igmp_grouprec
*pig
;
3029 struct ip_msource
*ims
, *nims
;
3030 struct mbuf
*m0
, *m
, *md
;
3031 int error
, is_filter_list_change
;
3032 int minrec0len
, m0srcs
, msrcs
, nbytes
, off
;
3033 int record_has_sources
;
3038 u_int16_t ig_numsrc
;
3040 INM_LOCK_ASSERT_HELD(inm
);
3041 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
3045 is_filter_list_change
= 0;
3052 record_has_sources
= 1;
3054 type
= IGMP_DO_NOTHING
;
3055 mode
= inm
->inm_st
[1].iss_fmode
;
3058 * If we did not transition out of ASM mode during t0->t1,
3059 * and there are no source nodes to process, we can skip
3060 * the generation of source records.
3062 if (inm
->inm_st
[0].iss_asm
> 0 && inm
->inm_st
[1].iss_asm
> 0 &&
3064 record_has_sources
= 0;
3066 if (is_state_change
) {
3068 * Queue a state change record.
3069 * If the mode did not change, and there are non-ASM
3070 * listeners or source filters present,
3071 * we potentially need to issue two records for the group.
3072 * If we are transitioning to MCAST_UNDEFINED, we need
3073 * not send any sources.
3074 * If there are ASM listeners, and there was no filter
3075 * mode transition of any kind, do nothing.
3077 if (mode
!= inm
->inm_st
[0].iss_fmode
) {
3078 if (mode
== MCAST_EXCLUDE
) {
3079 IGMP_PRINTF(("%s: change to EXCLUDE\n",
3081 type
= IGMP_CHANGE_TO_EXCLUDE_MODE
;
3083 IGMP_PRINTF(("%s: change to INCLUDE\n",
3085 type
= IGMP_CHANGE_TO_INCLUDE_MODE
;
3086 if (mode
== MCAST_UNDEFINED
)
3087 record_has_sources
= 0;
3090 if (record_has_sources
) {
3091 is_filter_list_change
= 1;
3093 type
= IGMP_DO_NOTHING
;
3098 * Queue a current state record.
3100 if (mode
== MCAST_EXCLUDE
) {
3101 type
= IGMP_MODE_IS_EXCLUDE
;
3102 } else if (mode
== MCAST_INCLUDE
) {
3103 type
= IGMP_MODE_IS_INCLUDE
;
3104 VERIFY(inm
->inm_st
[1].iss_asm
== 0);
3109 * Generate the filter list changes using a separate function.
3111 if (is_filter_list_change
)
3112 return (igmp_v3_enqueue_filter_change(ifq
, inm
));
3114 if (type
== IGMP_DO_NOTHING
) {
3115 IGMP_INET_PRINTF(inm
->inm_addr
,
3116 ("%s: nothing to do for %s/%s\n",
3117 __func__
, _igmp_inet_buf
,
3118 if_name(inm
->inm_ifp
)));
3123 * If any sources are present, we must be able to fit at least
3124 * one in the trailing space of the tail packet's mbuf,
3127 minrec0len
= sizeof(struct igmp_grouprec
);
3128 if (record_has_sources
)
3129 minrec0len
+= sizeof(in_addr_t
);
3131 IGMP_INET_PRINTF(inm
->inm_addr
,
3132 ("%s: queueing %s for %s/%s\n", __func__
,
3133 igmp_rec_type_to_str(type
), _igmp_inet_buf
,
3134 if_name(inm
->inm_ifp
)));
3137 * Check if we have a packet in the tail of the queue for this
3138 * group into which the first group record for this group will fit.
3139 * Otherwise allocate a new packet.
3140 * Always allocate leading space for IP+RA_OPT+IGMP+REPORT.
3141 * Note: Group records for G/GSR query responses MUST be sent
3142 * in their own packet.
3145 if (!is_group_query
&&
3147 (m0
->m_pkthdr
.vt_nrecs
+ 1 <= IGMP_V3_REPORT_MAXRECS
) &&
3148 (m0
->m_pkthdr
.len
+ minrec0len
) <
3149 (ifp
->if_mtu
- IGMP_LEADINGSPACE
)) {
3150 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
3151 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3153 IGMP_PRINTF(("%s: use existing packet\n", __func__
));
3155 if (IF_QFULL(ifq
)) {
3156 IGMP_PRINTF(("%s: outbound queue full\n", __func__
));
3160 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3161 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3162 if (!is_state_change
&& !is_group_query
) {
3163 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3165 m
->m_data
+= IGMP_LEADINGSPACE
;
3168 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3170 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3175 igmp_save_context(m
, ifp
);
3177 IGMP_PRINTF(("%s: allocated first packet\n", __func__
));
3181 * Append group record.
3182 * If we have sources, we don't know how many yet.
3187 ig
.ig_group
= inm
->inm_addr
;
3188 if (!m_append(m
, sizeof(struct igmp_grouprec
), (void *)&ig
)) {
3191 IGMP_PRINTF(("%s: m_append() failed.\n", __func__
));
3194 nbytes
+= sizeof(struct igmp_grouprec
);
3197 * Append as many sources as will fit in the first packet.
3198 * If we are appending to a new packet, the chain allocation
3199 * may potentially use clusters; use m_getptr() in this case.
3200 * If we are appending to an existing packet, we need to obtain
3201 * a pointer to the group record after m_append(), in case a new
3202 * mbuf was allocated.
3203 * Only append sources which are in-mode at t1. If we are
3204 * transitioning to MCAST_UNDEFINED state on the group, do not
3205 * include source entries.
3206 * Only report recorded sources in our filter set when responding
3207 * to a group-source query.
3209 if (record_has_sources
) {
3212 pig
= (struct igmp_grouprec
*)(void *)
3213 (mtod(md
, uint8_t *) + md
->m_len
- nbytes
);
3215 md
= m_getptr(m
, 0, &off
);
3216 pig
= (struct igmp_grouprec
*)(void *)
3217 (mtod(md
, uint8_t *) + off
);
3220 RB_FOREACH_SAFE(ims
, ip_msource_tree
, &inm
->inm_srcs
, nims
) {
3222 char buf
[MAX_IPv4_STR_LEN
];
3224 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3225 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3227 now
= ims_get_mode(inm
, ims
, 1);
3228 IGMP_PRINTF(("%s: node is %d\n", __func__
, now
));
3229 if ((now
!= mode
) ||
3230 (now
== mode
&& mode
== MCAST_UNDEFINED
)) {
3231 IGMP_PRINTF(("%s: skip node\n", __func__
));
3234 if (is_source_query
&& ims
->ims_stp
== 0) {
3235 IGMP_PRINTF(("%s: skip unrecorded node\n",
3239 IGMP_PRINTF(("%s: append node\n", __func__
));
3240 naddr
= htonl(ims
->ims_haddr
);
3241 if (!m_append(m
, sizeof(in_addr_t
), (void *)&naddr
)) {
3244 IGMP_PRINTF(("%s: m_append() failed.\n",
3248 nbytes
+= sizeof(in_addr_t
);
3250 if (msrcs
== m0srcs
)
3253 IGMP_PRINTF(("%s: msrcs is %d this packet\n", __func__
,
3255 ig_numsrc
= htons(msrcs
);
3256 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3257 nbytes
+= (msrcs
* sizeof(in_addr_t
));
3260 if (is_source_query
&& msrcs
== 0) {
3261 IGMP_PRINTF(("%s: no recorded sources to report\n", __func__
));
3268 * We are good to go with first packet.
3271 IGMP_PRINTF(("%s: enqueueing first packet\n", __func__
));
3272 m
->m_pkthdr
.vt_nrecs
= 1;
3275 m
->m_pkthdr
.vt_nrecs
++;
3278 * No further work needed if no source list in packet(s).
3280 if (!record_has_sources
)
3284 * Whilst sources remain to be announced, we need to allocate
3285 * a new packet and fill out as many sources as will fit.
3286 * Always try for a cluster first.
3288 while (nims
!= NULL
) {
3289 if (IF_QFULL(ifq
)) {
3290 IGMP_PRINTF(("%s: outbound queue full\n", __func__
));
3293 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3295 m
->m_data
+= IGMP_LEADINGSPACE
;
3297 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3299 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3303 igmp_save_context(m
, ifp
);
3304 md
= m_getptr(m
, 0, &off
);
3305 pig
= (struct igmp_grouprec
*)(void *)
3306 (mtod(md
, uint8_t *) + off
);
3307 IGMP_PRINTF(("%s: allocated next packet\n", __func__
));
3309 if (!m_append(m
, sizeof(struct igmp_grouprec
), (void *)&ig
)) {
3312 IGMP_PRINTF(("%s: m_append() failed.\n", __func__
));
3315 m
->m_pkthdr
.vt_nrecs
= 1;
3316 nbytes
+= sizeof(struct igmp_grouprec
);
3318 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3319 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3322 RB_FOREACH_FROM(ims
, ip_msource_tree
, nims
) {
3324 char buf
[MAX_IPv4_STR_LEN
];
3326 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3327 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3329 now
= ims_get_mode(inm
, ims
, 1);
3330 if ((now
!= mode
) ||
3331 (now
== mode
&& mode
== MCAST_UNDEFINED
)) {
3332 IGMP_PRINTF(("%s: skip node\n", __func__
));
3335 if (is_source_query
&& ims
->ims_stp
== 0) {
3336 IGMP_PRINTF(("%s: skip unrecorded node\n",
3340 IGMP_PRINTF(("%s: append node\n", __func__
));
3341 naddr
= htonl(ims
->ims_haddr
);
3342 if (!m_append(m
, sizeof(in_addr_t
), (void *)&naddr
)) {
3345 IGMP_PRINTF(("%s: m_append() failed.\n",
3350 if (msrcs
== m0srcs
)
3353 ig_numsrc
= htons(msrcs
);
3354 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3355 nbytes
+= (msrcs
* sizeof(in_addr_t
));
3357 IGMP_PRINTF(("%s: enqueueing next packet\n", __func__
));
3365 * Type used to mark record pass completion.
3366 * We exploit the fact we can cast to this easily from the
3367 * current filter modes on each ip_msource node.
3370 REC_NONE
= 0x00, /* MCAST_UNDEFINED */
3371 REC_ALLOW
= 0x01, /* MCAST_INCLUDE */
3372 REC_BLOCK
= 0x02, /* MCAST_EXCLUDE */
3373 REC_FULL
= REC_ALLOW
| REC_BLOCK
3377 * Enqueue an IGMPv3 filter list change to the given output queue.
3379 * Source list filter state is held in an RB-tree. When the filter list
3380 * for a group is changed without changing its mode, we need to compute
3381 * the deltas between T0 and T1 for each source in the filter set,
3382 * and enqueue the appropriate ALLOW_NEW/BLOCK_OLD records.
3384 * As we may potentially queue two record types, and the entire R-B tree
3385 * needs to be walked at once, we break this out into its own function
3386 * so we can generate a tightly packed queue of packets.
3388 * XXX This could be written to only use one tree walk, although that makes
3389 * serializing into the mbuf chains a bit harder. For now we do two walks
3390 * which makes things easier on us, and it may or may not be harder on
3393 * If successful the size of all data appended to the queue is returned,
3394 * otherwise an error code less than zero is returned, or zero if
3395 * no record(s) were appended.
3398 igmp_v3_enqueue_filter_change(struct ifqueue
*ifq
, struct in_multi
*inm
)
3400 static const int MINRECLEN
=
3401 sizeof(struct igmp_grouprec
) + sizeof(in_addr_t
);
3403 struct igmp_grouprec ig
;
3404 struct igmp_grouprec
*pig
;
3405 struct ip_msource
*ims
, *nims
;
3406 struct mbuf
*m
, *m0
, *md
;
3408 int m0srcs
, nbytes
, npbytes
, off
, rsrcs
, schanged
;
3410 uint8_t mode
, now
, then
;
3411 rectype_t crt
, drt
, nrt
;
3412 u_int16_t ig_numsrc
;
3414 INM_LOCK_ASSERT_HELD(inm
);
3416 if (inm
->inm_nsrc
== 0 ||
3417 (inm
->inm_st
[0].iss_asm
> 0 && inm
->inm_st
[1].iss_asm
> 0))
3420 ifp
= inm
->inm_ifp
; /* interface */
3421 mode
= inm
->inm_st
[1].iss_fmode
; /* filter mode at t1 */
3422 crt
= REC_NONE
; /* current group record type */
3423 drt
= REC_NONE
; /* mask of completed group record types */
3424 nrt
= REC_NONE
; /* record type for current node */
3425 m0srcs
= 0; /* # source which will fit in current mbuf chain */
3426 nbytes
= 0; /* # of bytes appended to group's state-change queue */
3427 npbytes
= 0; /* # of bytes appended this packet */
3428 rsrcs
= 0; /* # sources encoded in current record */
3429 schanged
= 0; /* # nodes encoded in overall filter change */
3430 nallow
= 0; /* # of source entries in ALLOW_NEW */
3431 nblock
= 0; /* # of source entries in BLOCK_OLD */
3432 nims
= NULL
; /* next tree node pointer */
3435 * For each possible filter record mode.
3436 * The first kind of source we encounter tells us which
3437 * is the first kind of record we start appending.
3438 * If a node transitioned to UNDEFINED at t1, its mode is treated
3439 * as the inverse of the group's filter mode.
3441 while (drt
!= REC_FULL
) {
3445 (m0
->m_pkthdr
.vt_nrecs
+ 1 <=
3446 IGMP_V3_REPORT_MAXRECS
) &&
3447 (m0
->m_pkthdr
.len
+ MINRECLEN
) <
3448 (ifp
->if_mtu
- IGMP_LEADINGSPACE
)) {
3450 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
3451 sizeof(struct igmp_grouprec
)) /
3453 IGMP_PRINTF(("%s: use previous packet\n",
3456 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3458 m
->m_data
+= IGMP_LEADINGSPACE
;
3460 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3462 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3465 IGMP_PRINTF(("%s: m_get*() failed\n",
3469 m
->m_pkthdr
.vt_nrecs
= 0;
3470 igmp_save_context(m
, ifp
);
3471 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3472 sizeof(struct igmp_grouprec
)) /
3475 IGMP_PRINTF(("%s: allocated new packet\n",
3479 * Append the IGMP group record header to the
3480 * current packet's data area.
3481 * Recalculate pointer to free space for next
3482 * group record, in case m_append() allocated
3483 * a new mbuf or cluster.
3485 memset(&ig
, 0, sizeof(ig
));
3486 ig
.ig_group
= inm
->inm_addr
;
3487 if (!m_append(m
, sizeof(ig
), (void *)&ig
)) {
3490 IGMP_PRINTF(("%s: m_append() failed\n",
3494 npbytes
+= sizeof(struct igmp_grouprec
);
3496 /* new packet; offset in c hain */
3497 md
= m_getptr(m
, npbytes
-
3498 sizeof(struct igmp_grouprec
), &off
);
3499 pig
= (struct igmp_grouprec
*)(void *)(mtod(md
,
3502 /* current packet; offset from last append */
3504 pig
= (struct igmp_grouprec
*)(void *)(mtod(md
,
3505 uint8_t *) + md
->m_len
-
3506 sizeof(struct igmp_grouprec
));
3509 * Begin walking the tree for this record type
3510 * pass, or continue from where we left off
3511 * previously if we had to allocate a new packet.
3512 * Only report deltas in-mode at t1.
3513 * We need not report included sources as allowed
3514 * if we are in inclusive mode on the group,
3515 * however the converse is not true.
3519 nims
= RB_MIN(ip_msource_tree
, &inm
->inm_srcs
);
3520 RB_FOREACH_FROM(ims
, ip_msource_tree
, nims
) {
3522 char buf
[MAX_IPv4_STR_LEN
];
3524 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3525 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3527 now
= ims_get_mode(inm
, ims
, 1);
3528 then
= ims_get_mode(inm
, ims
, 0);
3529 IGMP_PRINTF(("%s: mode: t0 %d, t1 %d\n",
3530 __func__
, then
, now
));
3532 IGMP_PRINTF(("%s: skip unchanged\n",
3536 if (mode
== MCAST_EXCLUDE
&&
3537 now
== MCAST_INCLUDE
) {
3538 IGMP_PRINTF(("%s: skip IN src on EX "
3539 "group\n", __func__
));
3542 nrt
= (rectype_t
)now
;
3543 if (nrt
== REC_NONE
)
3544 nrt
= (rectype_t
)(~mode
& REC_FULL
);
3545 if (schanged
++ == 0) {
3547 } else if (crt
!= nrt
)
3549 naddr
= htonl(ims
->ims_haddr
);
3550 if (!m_append(m
, sizeof(in_addr_t
),
3554 IGMP_PRINTF(("%s: m_append() failed\n",
3558 nallow
+= !!(crt
== REC_ALLOW
);
3559 nblock
+= !!(crt
== REC_BLOCK
);
3560 if (++rsrcs
== m0srcs
)
3564 * If we did not append any tree nodes on this
3565 * pass, back out of allocations.
3568 npbytes
-= sizeof(struct igmp_grouprec
);
3570 IGMP_PRINTF(("%s: m_free(m)\n",
3574 IGMP_PRINTF(("%s: m_adj(m, -ig)\n",
3576 m_adj(m
, -((int)sizeof(
3577 struct igmp_grouprec
)));
3581 npbytes
+= (rsrcs
* sizeof(in_addr_t
));
3582 if (crt
== REC_ALLOW
)
3583 pig
->ig_type
= IGMP_ALLOW_NEW_SOURCES
;
3584 else if (crt
== REC_BLOCK
)
3585 pig
->ig_type
= IGMP_BLOCK_OLD_SOURCES
;
3586 ig_numsrc
= htons(rsrcs
);
3587 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3589 * Count the new group record, and enqueue this
3590 * packet if it wasn't already queued.
3592 m
->m_pkthdr
.vt_nrecs
++;
3596 } while (nims
!= NULL
);
3598 crt
= (~crt
& REC_FULL
);
3601 IGMP_PRINTF(("%s: queued %d ALLOW_NEW, %d BLOCK_OLD\n", __func__
,
3608 igmp_v3_merge_state_changes(struct in_multi
*inm
, struct ifqueue
*ifscq
)
3611 struct mbuf
*m
; /* pending state-change */
3612 struct mbuf
*m0
; /* copy of pending state-change */
3613 struct mbuf
*mt
; /* last state-change in packet */
3615 int docopy
, domerge
;
3618 INM_LOCK_ASSERT_HELD(inm
);
3625 * If there are further pending retransmissions, make a writable
3626 * copy of each queued state-change message before merging.
3628 if (inm
->inm_scrv
> 0)
3633 if (gq
->ifq_head
== NULL
) {
3634 IGMP_PRINTF(("%s: WARNING: queue for inm 0x%llx is empty\n",
3635 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(inm
)));
3640 * Use IF_REMQUEUE() instead of IF_DEQUEUE() below, since the
3641 * packet might not always be at the head of the ifqueue.
3646 * Only merge the report into the current packet if
3647 * there is sufficient space to do so; an IGMPv3 report
3648 * packet may only contain 65,535 group records.
3649 * Always use a simple mbuf chain concatentation to do this,
3650 * as large state changes for single groups may have
3651 * allocated clusters.
3654 mt
= ifscq
->ifq_tail
;
3656 recslen
= m_length(m
);
3658 if ((mt
->m_pkthdr
.vt_nrecs
+
3659 m
->m_pkthdr
.vt_nrecs
<=
3660 IGMP_V3_REPORT_MAXRECS
) &&
3661 (mt
->m_pkthdr
.len
+ recslen
<=
3662 (inm
->inm_ifp
->if_mtu
- IGMP_LEADINGSPACE
)))
3666 if (!domerge
&& IF_QFULL(gq
)) {
3667 IGMP_PRINTF(("%s: outbound queue full, skipping whole "
3668 "packet 0x%llx\n", __func__
,
3669 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3680 IGMP_PRINTF(("%s: dequeueing 0x%llx\n", __func__
,
3681 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3687 IGMP_PRINTF(("%s: copying 0x%llx\n", __func__
,
3688 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3689 m0
= m_dup(m
, M_NOWAIT
);
3692 m0
->m_nextpkt
= NULL
;
3697 IGMP_PRINTF(("%s: queueing 0x%llx to ifscq 0x%llx)\n",
3698 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(m0
),
3699 (uint64_t)VM_KERNEL_ADDRPERM(ifscq
)));
3700 IF_ENQUEUE(ifscq
, m0
);
3702 struct mbuf
*mtl
; /* last mbuf of packet mt */
3704 IGMP_PRINTF(("%s: merging 0x%llx with ifscq tail "
3705 "0x%llx)\n", __func__
,
3706 (uint64_t)VM_KERNEL_ADDRPERM(m0
),
3707 (uint64_t)VM_KERNEL_ADDRPERM(mt
)));
3710 m0
->m_flags
&= ~M_PKTHDR
;
3711 mt
->m_pkthdr
.len
+= recslen
;
3712 mt
->m_pkthdr
.vt_nrecs
+=
3713 m0
->m_pkthdr
.vt_nrecs
;
3723 * Respond to a pending IGMPv3 General Query.
3726 igmp_v3_dispatch_general_query(struct igmp_ifinfo
*igi
)
3729 struct in_multi
*inm
;
3730 struct in_multistep step
;
3733 IGI_LOCK_ASSERT_HELD(igi
);
3735 VERIFY(igi
->igi_version
== IGMP_VERSION_3
);
3740 in_multihead_lock_shared();
3741 IN_FIRST_MULTI(step
, inm
);
3742 while (inm
!= NULL
) {
3744 if (inm
->inm_ifp
!= ifp
)
3747 switch (inm
->inm_state
) {
3748 case IGMP_NOT_MEMBER
:
3749 case IGMP_SILENT_MEMBER
:
3751 case IGMP_REPORTING_MEMBER
:
3752 case IGMP_IDLE_MEMBER
:
3753 case IGMP_LAZY_MEMBER
:
3754 case IGMP_SLEEPING_MEMBER
:
3755 case IGMP_AWAKENING_MEMBER
:
3756 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
3758 retval
= igmp_v3_enqueue_group_record(&igi
->igi_gq
,
3761 IGMP_PRINTF(("%s: enqueue record = %d\n",
3764 case IGMP_G_QUERY_PENDING_MEMBER
:
3765 case IGMP_SG_QUERY_PENDING_MEMBER
:
3766 case IGMP_LEAVING_MEMBER
:
3771 IN_NEXT_MULTI(step
, inm
);
3773 in_multihead_lock_done();
3776 loop
= (igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : 0;
3777 igmp_dispatch_queue(igi
, &igi
->igi_gq
, IGMP_MAX_RESPONSE_BURST
,
3779 IGI_LOCK_ASSERT_HELD(igi
);
3781 * Slew transmission of bursts over 1 second intervals.
3783 if (igi
->igi_gq
.ifq_head
!= NULL
) {
3784 igi
->igi_v3_timer
= 1 + IGMP_RANDOM_DELAY(
3785 IGMP_RESPONSE_BURST_INTERVAL
);
3788 return (igi
->igi_v3_timer
);
3792 * Transmit the next pending IGMP message in the output queue.
3794 * Must not be called with inm_lock or igi_lock held.
3797 igmp_sendpkt(struct mbuf
*m
)
3799 struct ip_moptions
*imo
;
3800 struct mbuf
*ipopts
, *m0
;
3805 IGMP_PRINTF(("%s: transmit 0x%llx\n", __func__
,
3806 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3808 ifp
= igmp_restore_context(m
);
3810 * Check if the ifnet is still attached.
3812 if (ifp
== NULL
|| !ifnet_is_attached(ifp
, 0)) {
3813 IGMP_PRINTF(("%s: dropped 0x%llx as ifp went away.\n",
3814 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3816 OSAddAtomic(1, &ipstat
.ips_noroute
);
3820 ipopts
= igmp_sendra
? m_raopt
: NULL
;
3822 imo
= ip_allocmoptions(M_WAITOK
);
3828 imo
->imo_multicast_ttl
= 1;
3829 imo
->imo_multicast_vif
= -1;
3830 imo
->imo_multicast_loop
= 0;
3833 * If the user requested that IGMP traffic be explicitly
3834 * redirected to the loopback interface (e.g. they are running a
3835 * MANET interface and the routing protocol needs to see the
3836 * updates), handle this now.
3838 if (m
->m_flags
& M_IGMP_LOOP
)
3839 imo
->imo_multicast_ifp
= lo_ifp
;
3841 imo
->imo_multicast_ifp
= ifp
;
3843 if (m
->m_flags
& M_IGMPV2
) {
3846 m0
= igmp_v3_encap_report(ifp
, m
);
3849 * If igmp_v3_encap_report() failed, then M_PREPEND()
3850 * already freed the original mbuf chain.
3851 * This means that we don't have to m_freem(m) here.
3853 IGMP_PRINTF(("%s: dropped 0x%llx\n", __func__
,
3854 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3856 atomic_add_32(&ipstat
.ips_odropped
, 1);
3861 igmp_scrub_context(m0
);
3862 m
->m_flags
&= ~(M_PROTOFLAGS
| M_IGMP_LOOP
);
3863 m0
->m_pkthdr
.rcvif
= lo_ifp
;
3865 mac_netinet_igmp_send(ifp
, m0
);
3868 if (ifp
->if_eflags
& IFEF_TXSTART
) {
3870 * Use control service class if the interface supports
3871 * transmit-start model.
3873 (void) m_set_service_class(m0
, MBUF_SC_CTL
);
3875 bzero(&ro
, sizeof (ro
));
3876 error
= ip_output(m0
, ipopts
, &ro
, 0, imo
, NULL
);
3882 IGMP_PRINTF(("%s: ip_output(0x%llx) = %d\n", __func__
,
3883 (uint64_t)VM_KERNEL_ADDRPERM(m0
), error
));
3887 IGMPSTAT_INC(igps_snd_reports
);
3888 OIGMPSTAT_INC(igps_snd_reports
);
3891 * Encapsulate an IGMPv3 report.
3893 * The internal mbuf flag M_IGMPV3_HDR is used to indicate that the mbuf
3894 * chain has already had its IP/IGMPv3 header prepended. In this case
3895 * the function will not attempt to prepend; the lengths and checksums
3896 * will however be re-computed.
3898 * Returns a pointer to the new mbuf chain head, or NULL if the
3899 * allocation failed.
3901 static struct mbuf
*
3902 igmp_v3_encap_report(struct ifnet
*ifp
, struct mbuf
*m
)
3904 struct igmp_report
*igmp
;
3906 int hdrlen
, igmpreclen
;
3908 VERIFY((m
->m_flags
& M_PKTHDR
));
3910 igmpreclen
= m_length(m
);
3911 hdrlen
= sizeof(struct ip
) + sizeof(struct igmp_report
);
3913 if (m
->m_flags
& M_IGMPV3_HDR
) {
3914 igmpreclen
-= hdrlen
;
3916 M_PREPEND(m
, hdrlen
, M_DONTWAIT
, 1);
3919 m
->m_flags
|= M_IGMPV3_HDR
;
3922 IGMP_PRINTF(("%s: igmpreclen is %d\n", __func__
, igmpreclen
));
3924 m
->m_data
+= sizeof(struct ip
);
3925 m
->m_len
-= sizeof(struct ip
);
3927 igmp
= mtod(m
, struct igmp_report
*);
3928 igmp
->ir_type
= IGMP_v3_HOST_MEMBERSHIP_REPORT
;
3931 igmp
->ir_numgrps
= htons(m
->m_pkthdr
.vt_nrecs
);
3933 igmp
->ir_cksum
= in_cksum(m
, sizeof(struct igmp_report
) + igmpreclen
);
3934 m
->m_pkthdr
.vt_nrecs
= 0;
3936 m
->m_data
-= sizeof(struct ip
);
3937 m
->m_len
+= sizeof(struct ip
);
3939 ip
= mtod(m
, struct ip
*);
3940 ip
->ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
3941 ip
->ip_len
= hdrlen
+ igmpreclen
;
3943 ip
->ip_p
= IPPROTO_IGMP
;
3946 ip
->ip_src
.s_addr
= INADDR_ANY
;
3948 if (m
->m_flags
& M_IGMP_LOOP
) {
3949 struct in_ifaddr
*ia
;
3953 IFA_LOCK(&ia
->ia_ifa
);
3954 ip
->ip_src
= ia
->ia_addr
.sin_addr
;
3955 IFA_UNLOCK(&ia
->ia_ifa
);
3956 IFA_REMREF(&ia
->ia_ifa
);
3960 ip
->ip_dst
.s_addr
= htonl(INADDR_ALLRPTS_GROUP
);
3967 igmp_rec_type_to_str(const int type
)
3970 case IGMP_CHANGE_TO_EXCLUDE_MODE
:
3972 case IGMP_CHANGE_TO_INCLUDE_MODE
:
3974 case IGMP_MODE_IS_EXCLUDE
:
3976 case IGMP_MODE_IS_INCLUDE
:
3978 case IGMP_ALLOW_NEW_SOURCES
:
3980 case IGMP_BLOCK_OLD_SOURCES
:
3990 igmp_init(struct protosw
*pp
, struct domain
*dp
)
3993 static int igmp_initialized
= 0;
3995 VERIFY((pp
->pr_flags
& (PR_INITIALIZED
|PR_ATTACHED
)) == PR_ATTACHED
);
3997 if (igmp_initialized
)
3999 igmp_initialized
= 1;
4001 IGMP_PRINTF(("%s: initializing\n", __func__
));
4003 igmp_timers_are_running
= 0;
4005 /* Setup lock group and attribute for igmp_mtx */
4006 igmp_mtx_grp_attr
= lck_grp_attr_alloc_init();
4007 igmp_mtx_grp
= lck_grp_alloc_init("igmp_mtx", igmp_mtx_grp_attr
);
4008 igmp_mtx_attr
= lck_attr_alloc_init();
4009 lck_mtx_init(&igmp_mtx
, igmp_mtx_grp
, igmp_mtx_attr
);
4011 LIST_INIT(&igi_head
);
4012 m_raopt
= igmp_ra_alloc();
4014 igi_size
= sizeof (struct igmp_ifinfo
);
4015 igi_zone
= zinit(igi_size
, IGI_ZONE_MAX
* igi_size
,
4017 if (igi_zone
== NULL
) {
4018 panic("%s: failed allocating %s", __func__
, IGI_ZONE_NAME
);
4021 zone_change(igi_zone
, Z_EXPAND
, TRUE
);
4022 zone_change(igi_zone
, Z_CALLERACCT
, FALSE
);