2 * Copyright (c) 2000-2013 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] = 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
);
1740 srclen
= sizeof(struct in_addr
) * nsrc
;
1741 if (igmplen
< (IGMP_V3_QUERY_MINLEN
+ srclen
)) {
1742 IGMPSTAT_INC(igps_rcv_tooshort
);
1743 OIGMPSTAT_INC(igps_rcv_tooshort
);
1747 igmpv3len
= IGMP_V3_QUERY_MINLEN
+ srclen
;
1749 * A bit more expensive than M_STRUCT_GET,
1750 * but ensures alignment.
1752 M_STRUCT_GET0(igmpv3
, struct igmpv3
*, m
,
1754 if (igmpv3
== NULL
) {
1755 IGMPSTAT_INC(igps_rcv_tooshort
);
1756 OIGMPSTAT_INC(igps_rcv_tooshort
);
1760 * N.B.: we assume the packet was correctly
1761 * aligned in ip_input.
1763 if (igmp_input_v3_query(ifp
, ip
, igmpv3
) != 0) {
1772 case IGMP_v1_HOST_MEMBERSHIP_REPORT
:
1775 if (igmp_input_v1_report(ifp
, m
, ip
, igmp
) != 0) {
1781 case IGMP_v2_HOST_MEMBERSHIP_REPORT
:
1784 if (!ip_checkrouteralert(m
))
1785 IGMPSTAT_INC(igps_rcv_nora
);
1786 if (igmp_input_v2_report(ifp
, m
, ip
, igmp
) != 0) {
1792 case IGMP_v3_HOST_MEMBERSHIP_REPORT
:
1794 * Hosts do not need to process IGMPv3 membership reports,
1795 * as report suppression is no longer required.
1797 if (!ip_checkrouteralert(m
))
1798 IGMPSTAT_INC(igps_rcv_nora
);
1805 IGMP_LOCK_ASSERT_NOTHELD();
1807 * Pass all valid IGMP packets up to any process(es) listening on a
1814 * Schedule IGMP timer based on various parameters; caller must ensure that
1815 * lock ordering is maintained as this routine acquires IGMP global lock.
1818 igmp_set_timeout(struct igmp_tparams
*itp
)
1820 IGMP_LOCK_ASSERT_NOTHELD();
1821 VERIFY(itp
!= NULL
);
1823 if (itp
->qpt
!= 0 || itp
->it
!= 0 || itp
->cst
!= 0 || itp
->sct
!= 0) {
1826 querier_present_timers_running
= 1;
1828 interface_timers_running
= 1;
1830 current_state_timers_running
= 1;
1832 state_change_timers_running
= 1;
1833 igmp_sched_timeout();
1839 * IGMP timer handler (per 1 second).
1842 igmp_timeout(void *arg
)
1845 struct ifqueue scq
; /* State-change packets */
1846 struct ifqueue qrq
; /* Query response packets */
1848 struct igmp_ifinfo
*igi
;
1849 struct in_multi
*inm
;
1850 int loop
= 0, uri_sec
= 0;
1851 SLIST_HEAD(, in_multi
) inm_dthead
;
1853 SLIST_INIT(&inm_dthead
);
1856 * Update coarse-grained networking timestamp (in sec.); the idea
1857 * is to piggy-back on the timeout callout to update the counter
1858 * returnable via net_uptime().
1860 net_update_uptime();
1864 IGMP_PRINTF(("%s: qpt %d, it %d, cst %d, sct %d\n", __func__
,
1865 querier_present_timers_running
, interface_timers_running
,
1866 current_state_timers_running
, state_change_timers_running
));
1869 * IGMPv1/v2 querier present timer processing.
1871 if (querier_present_timers_running
) {
1872 querier_present_timers_running
= 0;
1873 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1875 igmp_v1v2_process_querier_timers(igi
);
1876 if (igi
->igi_v1_timer
> 0 || igi
->igi_v2_timer
> 0)
1877 querier_present_timers_running
= 1;
1883 * IGMPv3 General Query response timer processing.
1885 if (interface_timers_running
) {
1886 IGMP_PRINTF(("%s: interface timers running\n", __func__
));
1887 interface_timers_running
= 0;
1888 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1890 if (igi
->igi_v3_timer
== 0) {
1892 } else if (--igi
->igi_v3_timer
== 0) {
1893 if (igmp_v3_dispatch_general_query(igi
) > 0)
1894 interface_timers_running
= 1;
1896 interface_timers_running
= 1;
1902 if (!current_state_timers_running
&&
1903 !state_change_timers_running
)
1906 current_state_timers_running
= 0;
1907 state_change_timers_running
= 0;
1909 memset(&qrq
, 0, sizeof(struct ifqueue
));
1910 qrq
.ifq_maxlen
= IGMP_MAX_G_GS_PACKETS
;
1912 memset(&scq
, 0, sizeof(struct ifqueue
));
1913 scq
.ifq_maxlen
= IGMP_MAX_STATE_CHANGE_PACKETS
;
1915 IGMP_PRINTF(("%s: state change timers running\n", __func__
));
1918 * IGMPv1/v2/v3 host report and state-change timer processing.
1919 * Note: Processing a v3 group timer may remove a node.
1921 LIST_FOREACH(igi
, &igi_head
, igi_link
) {
1922 struct in_multistep step
;
1926 loop
= (igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : 0;
1927 uri_sec
= IGMP_RANDOM_DELAY(igi
->igi_uri
);
1930 in_multihead_lock_shared();
1931 IN_FIRST_MULTI(step
, inm
);
1932 while (inm
!= NULL
) {
1934 if (inm
->inm_ifp
!= ifp
)
1938 switch (igi
->igi_version
) {
1939 case IGMP_VERSION_1
:
1940 case IGMP_VERSION_2
:
1941 igmp_v1v2_process_group_timer(inm
,
1944 case IGMP_VERSION_3
:
1945 igmp_v3_process_group_timers(igi
, &qrq
,
1946 &scq
, inm
, uri_sec
);
1952 IN_NEXT_MULTI(step
, inm
);
1954 in_multihead_lock_done();
1957 if (igi
->igi_version
== IGMP_VERSION_1
||
1958 igi
->igi_version
== IGMP_VERSION_2
) {
1959 igmp_dispatch_queue(igi
, &igi
->igi_v2q
, 0, loop
);
1960 } else if (igi
->igi_version
== IGMP_VERSION_3
) {
1962 igmp_dispatch_queue(NULL
, &qrq
, 0, loop
);
1963 igmp_dispatch_queue(NULL
, &scq
, 0, loop
);
1964 VERIFY(qrq
.ifq_len
== 0);
1965 VERIFY(scq
.ifq_len
== 0);
1969 * In case there are still any pending membership reports
1970 * which didn't get drained at version change time.
1972 IF_DRAIN(&igi
->igi_v2q
);
1974 * Release all deferred inm records, and drain any locally
1975 * enqueued packets; do it even if the current IGMP version
1976 * for the link is no longer IGMPv3, in order to handle the
1977 * version change case.
1979 igmp_flush_relq(igi
, (struct igmp_inm_relhead
*)&inm_dthead
);
1980 VERIFY(SLIST_EMPTY(&igi
->igi_relinmhead
));
1988 /* re-arm the timer if there's work to do */
1989 igmp_timeout_run
= 0;
1990 igmp_sched_timeout();
1993 /* Now that we're dropped all locks, release detached records */
1994 IGMP_REMOVE_DETACHED_INM(&inm_dthead
);
1998 igmp_sched_timeout(void)
2000 IGMP_LOCK_ASSERT_HELD();
2002 if (!igmp_timeout_run
&&
2003 (querier_present_timers_running
|| current_state_timers_running
||
2004 interface_timers_running
|| state_change_timers_running
)) {
2005 igmp_timeout_run
= 1;
2006 timeout(igmp_timeout
, NULL
, hz
);
2011 * Free the in_multi reference(s) for this IGMP lifecycle.
2013 * Caller must be holding igi_lock.
2016 igmp_flush_relq(struct igmp_ifinfo
*igi
, struct igmp_inm_relhead
*inm_dthead
)
2018 struct in_multi
*inm
;
2021 IGI_LOCK_ASSERT_HELD(igi
);
2022 inm
= SLIST_FIRST(&igi
->igi_relinmhead
);
2026 SLIST_REMOVE_HEAD(&igi
->igi_relinmhead
, inm_nrele
);
2029 in_multihead_lock_exclusive();
2031 VERIFY(inm
->inm_nrelecnt
!= 0);
2032 inm
->inm_nrelecnt
--;
2033 lastref
= in_multi_detach(inm
);
2034 VERIFY(!lastref
|| (!(inm
->inm_debug
& IFD_ATTACHED
) &&
2035 inm
->inm_reqcnt
== 0));
2037 in_multihead_lock_done();
2038 /* from igi_relinmhead */
2040 /* from in_multihead list */
2043 * Defer releasing our final reference, as we
2044 * are holding the IGMP lock at this point, and
2045 * we could end up with locking issues later on
2046 * (while issuing SIOCDELMULTI) when this is the
2047 * final reference count. Let the caller do it
2050 IGMP_ADD_DETACHED_INM(inm_dthead
, inm
);
2058 * Update host report group timer for IGMPv1/v2.
2059 * Will update the global pending timer flags.
2062 igmp_v1v2_process_group_timer(struct in_multi
*inm
, const int igmp_version
)
2064 int report_timer_expired
;
2066 IGMP_LOCK_ASSERT_HELD();
2067 INM_LOCK_ASSERT_HELD(inm
);
2068 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2070 if (inm
->inm_timer
== 0) {
2071 report_timer_expired
= 0;
2072 } else if (--inm
->inm_timer
== 0) {
2073 report_timer_expired
= 1;
2075 current_state_timers_running
= 1;
2076 /* caller will schedule timer */
2080 switch (inm
->inm_state
) {
2081 case IGMP_NOT_MEMBER
:
2082 case IGMP_SILENT_MEMBER
:
2083 case IGMP_IDLE_MEMBER
:
2084 case IGMP_LAZY_MEMBER
:
2085 case IGMP_SLEEPING_MEMBER
:
2086 case IGMP_AWAKENING_MEMBER
:
2088 case IGMP_REPORTING_MEMBER
:
2089 if (report_timer_expired
) {
2090 inm
->inm_state
= IGMP_IDLE_MEMBER
;
2091 (void) igmp_v1v2_queue_report(inm
,
2092 (igmp_version
== IGMP_VERSION_2
) ?
2093 IGMP_v2_HOST_MEMBERSHIP_REPORT
:
2094 IGMP_v1_HOST_MEMBERSHIP_REPORT
);
2095 INM_LOCK_ASSERT_HELD(inm
);
2096 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2099 case IGMP_G_QUERY_PENDING_MEMBER
:
2100 case IGMP_SG_QUERY_PENDING_MEMBER
:
2101 case IGMP_LEAVING_MEMBER
:
2107 * Update a group's timers for IGMPv3.
2108 * Will update the global pending timer flags.
2109 * Note: Unlocked read from igi.
2112 igmp_v3_process_group_timers(struct igmp_ifinfo
*igi
,
2113 struct ifqueue
*qrq
, struct ifqueue
*scq
,
2114 struct in_multi
*inm
, const int uri_sec
)
2116 int query_response_timer_expired
;
2117 int state_change_retransmit_timer_expired
;
2119 IGMP_LOCK_ASSERT_HELD();
2120 INM_LOCK_ASSERT_HELD(inm
);
2121 IGI_LOCK_ASSERT_HELD(igi
);
2122 VERIFY(igi
== inm
->inm_igi
);
2124 query_response_timer_expired
= 0;
2125 state_change_retransmit_timer_expired
= 0;
2128 * During a transition from v1/v2 compatibility mode back to v3,
2129 * a group record in REPORTING state may still have its group
2130 * timer active. This is a no-op in this function; it is easier
2131 * to deal with it here than to complicate the timeout path.
2133 if (inm
->inm_timer
== 0) {
2134 query_response_timer_expired
= 0;
2135 } else if (--inm
->inm_timer
== 0) {
2136 query_response_timer_expired
= 1;
2138 current_state_timers_running
= 1;
2139 /* caller will schedule timer */
2142 if (inm
->inm_sctimer
== 0) {
2143 state_change_retransmit_timer_expired
= 0;
2144 } else if (--inm
->inm_sctimer
== 0) {
2145 state_change_retransmit_timer_expired
= 1;
2147 state_change_timers_running
= 1;
2148 /* caller will schedule timer */
2151 /* We are in timer callback, so be quick about it. */
2152 if (!state_change_retransmit_timer_expired
&&
2153 !query_response_timer_expired
)
2156 switch (inm
->inm_state
) {
2157 case IGMP_NOT_MEMBER
:
2158 case IGMP_SILENT_MEMBER
:
2159 case IGMP_SLEEPING_MEMBER
:
2160 case IGMP_LAZY_MEMBER
:
2161 case IGMP_AWAKENING_MEMBER
:
2162 case IGMP_IDLE_MEMBER
:
2164 case IGMP_G_QUERY_PENDING_MEMBER
:
2165 case IGMP_SG_QUERY_PENDING_MEMBER
:
2167 * Respond to a previously pending Group-Specific
2168 * or Group-and-Source-Specific query by enqueueing
2169 * the appropriate Current-State report for
2170 * immediate transmission.
2172 if (query_response_timer_expired
) {
2175 retval
= igmp_v3_enqueue_group_record(qrq
, inm
, 0, 1,
2176 (inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
));
2177 IGMP_PRINTF(("%s: enqueue record = %d\n",
2179 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2180 /* XXX Clear recorded sources for next time. */
2181 inm_clear_recorded(inm
);
2184 case IGMP_REPORTING_MEMBER
:
2185 case IGMP_LEAVING_MEMBER
:
2186 if (state_change_retransmit_timer_expired
) {
2188 * State-change retransmission timer fired.
2189 * If there are any further pending retransmissions,
2190 * set the global pending state-change flag, and
2193 if (--inm
->inm_scrv
> 0) {
2194 inm
->inm_sctimer
= uri_sec
;
2195 state_change_timers_running
= 1;
2196 /* caller will schedule timer */
2199 * Retransmit the previously computed state-change
2200 * report. If there are no further pending
2201 * retransmissions, the mbuf queue will be consumed.
2202 * Update T0 state to T1 as we have now sent
2205 (void) igmp_v3_merge_state_changes(inm
, scq
);
2208 IGMP_INET_PRINTF(inm
->inm_addr
,
2209 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2210 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2213 * If we are leaving the group for good, make sure
2214 * we release IGMP's reference to it.
2215 * This release must be deferred using a SLIST,
2216 * as we are called from a loop which traverses
2217 * the in_multihead list.
2219 if (inm
->inm_state
== IGMP_LEAVING_MEMBER
&&
2220 inm
->inm_scrv
== 0) {
2221 inm
->inm_state
= IGMP_NOT_MEMBER
;
2223 * A reference has already been held in
2224 * igmp_final_leave() for this inm, so
2225 * no need to hold another one. We also
2226 * bumped up its request count then, so
2227 * that it stays in in_multihead. Both
2228 * of them will be released when it is
2229 * dequeued later on.
2231 VERIFY(inm
->inm_nrelecnt
!= 0);
2232 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
,
2241 * Suppress a group's pending response to a group or source/group query.
2243 * Do NOT suppress state changes. This leads to IGMPv3 inconsistency.
2244 * Do NOT update ST1/ST0 as this operation merely suppresses
2245 * the currently pending group record.
2246 * Do NOT suppress the response to a general query. It is possible but
2247 * it would require adding another state or flag.
2250 igmp_v3_suppress_group_record(struct in_multi
*inm
)
2253 INM_LOCK_ASSERT_HELD(inm
);
2254 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2256 VERIFY(inm
->inm_igi
->igi_version
== IGMP_VERSION_3
);
2258 if (inm
->inm_state
!= IGMP_G_QUERY_PENDING_MEMBER
||
2259 inm
->inm_state
!= IGMP_SG_QUERY_PENDING_MEMBER
)
2262 if (inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
)
2263 inm_clear_recorded(inm
);
2266 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2270 * Switch to a different IGMP version on the given interface,
2271 * as per Section 7.2.1.
2274 igmp_set_version(struct igmp_ifinfo
*igi
, const int igmp_version
)
2276 int old_version_timer
;
2278 IGI_LOCK_ASSERT_HELD(igi
);
2280 IGMP_PRINTF(("%s: switching to v%d on ifp 0x%llx(%s)\n", __func__
,
2281 igmp_version
, (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2282 if_name(igi
->igi_ifp
)));
2284 if (igmp_version
== IGMP_VERSION_1
|| igmp_version
== IGMP_VERSION_2
) {
2286 * Compute the "Older Version Querier Present" timer as per
2287 * Section 8.12, in seconds.
2289 old_version_timer
= igi
->igi_rv
* igi
->igi_qi
+ igi
->igi_qri
;
2291 if (igmp_version
== IGMP_VERSION_1
) {
2292 igi
->igi_v1_timer
= old_version_timer
;
2293 igi
->igi_v2_timer
= 0;
2294 } else if (igmp_version
== IGMP_VERSION_2
) {
2295 igi
->igi_v1_timer
= 0;
2296 igi
->igi_v2_timer
= old_version_timer
;
2300 if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
> 0) {
2301 if (igi
->igi_version
!= IGMP_VERSION_2
) {
2302 igi
->igi_version
= IGMP_VERSION_2
;
2303 igmp_v3_cancel_link_timers(igi
);
2305 } else if (igi
->igi_v1_timer
> 0) {
2306 if (igi
->igi_version
!= IGMP_VERSION_1
) {
2307 igi
->igi_version
= IGMP_VERSION_1
;
2308 igmp_v3_cancel_link_timers(igi
);
2312 IGI_LOCK_ASSERT_HELD(igi
);
2314 return (MAX(igi
->igi_v1_timer
, igi
->igi_v2_timer
));
2318 * Cancel pending IGMPv3 timers for the given link and all groups
2319 * joined on it; state-change, general-query, and group-query timers.
2321 * Only ever called on a transition from v3 to Compatibility mode. Kill
2322 * the timers stone dead (this may be expensive for large N groups), they
2323 * will be restarted if Compatibility Mode deems that they must be due to
2327 igmp_v3_cancel_link_timers(struct igmp_ifinfo
*igi
)
2330 struct in_multi
*inm
;
2331 struct in_multistep step
;
2333 IGI_LOCK_ASSERT_HELD(igi
);
2335 IGMP_PRINTF(("%s: cancel v3 timers on ifp 0x%llx(%s)\n", __func__
,
2336 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
), if_name(igi
->igi_ifp
)));
2339 * Stop the v3 General Query Response on this link stone dead.
2340 * If timer is woken up due to interface_timers_running,
2341 * the flag will be cleared if there are no pending link timers.
2343 igi
->igi_v3_timer
= 0;
2346 * Now clear the current-state and state-change report timers
2347 * for all memberships scoped to this link.
2352 in_multihead_lock_shared();
2353 IN_FIRST_MULTI(step
, inm
);
2354 while (inm
!= NULL
) {
2356 if (inm
->inm_ifp
!= ifp
)
2359 switch (inm
->inm_state
) {
2360 case IGMP_NOT_MEMBER
:
2361 case IGMP_SILENT_MEMBER
:
2362 case IGMP_IDLE_MEMBER
:
2363 case IGMP_LAZY_MEMBER
:
2364 case IGMP_SLEEPING_MEMBER
:
2365 case IGMP_AWAKENING_MEMBER
:
2367 * These states are either not relevant in v3 mode,
2368 * or are unreported. Do nothing.
2371 case IGMP_LEAVING_MEMBER
:
2373 * If we are leaving the group and switching to
2374 * compatibility mode, we need to release the final
2375 * reference held for issuing the INCLUDE {}, and
2376 * transition to REPORTING to ensure the host leave
2377 * message is sent upstream to the old querier --
2378 * transition to NOT would lose the leave and race.
2379 * During igmp_final_leave(), we bumped up both the
2380 * request and reference counts. Since we cannot
2381 * call in_multi_detach() here, defer this task to
2382 * the timer routine.
2384 VERIFY(inm
->inm_nrelecnt
!= 0);
2386 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
, inm
, inm_nrele
);
2389 case IGMP_G_QUERY_PENDING_MEMBER
:
2390 case IGMP_SG_QUERY_PENDING_MEMBER
:
2391 inm_clear_recorded(inm
);
2393 case IGMP_REPORTING_MEMBER
:
2394 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2398 * Always clear state-change and group report timers.
2399 * Free any pending IGMPv3 state-change records.
2401 inm
->inm_sctimer
= 0;
2403 IF_DRAIN(&inm
->inm_scq
);
2406 IN_NEXT_MULTI(step
, inm
);
2408 in_multihead_lock_done();
2414 * Update the Older Version Querier Present timers for a link.
2415 * See Section 7.2.1 of RFC 3376.
2418 igmp_v1v2_process_querier_timers(struct igmp_ifinfo
*igi
)
2420 IGI_LOCK_ASSERT_HELD(igi
);
2422 if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
== 0) {
2424 * IGMPv1 and IGMPv2 Querier Present timers expired.
2428 if (igi
->igi_version
!= IGMP_VERSION_3
) {
2429 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2430 "on 0x%llx(%s)\n", __func__
,
2431 igi
->igi_version
, IGMP_VERSION_3
,
2432 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2433 if_name(igi
->igi_ifp
)));
2434 igi
->igi_version
= IGMP_VERSION_3
;
2435 IF_DRAIN(&igi
->igi_v2q
);
2437 } else if (igi
->igi_v1_timer
== 0 && igi
->igi_v2_timer
> 0) {
2439 * IGMPv1 Querier Present timer expired,
2440 * IGMPv2 Querier Present timer running.
2441 * If IGMPv2 was disabled since last timeout,
2443 * If IGMPv2 is enabled, revert to IGMPv2.
2445 if (!igmp_v2enable
) {
2446 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2447 "on 0x%llx(%s%d)\n", __func__
,
2448 igi
->igi_version
, IGMP_VERSION_3
,
2449 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2450 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2451 igi
->igi_v2_timer
= 0;
2452 igi
->igi_version
= IGMP_VERSION_3
;
2453 IF_DRAIN(&igi
->igi_v2q
);
2455 --igi
->igi_v2_timer
;
2456 if (igi
->igi_version
!= IGMP_VERSION_2
) {
2457 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2458 "on 0x%llx(%s)\n", __func__
,
2459 igi
->igi_version
, IGMP_VERSION_2
,
2460 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2461 if_name(igi
->igi_ifp
)));
2462 igi
->igi_version
= IGMP_VERSION_2
;
2463 IF_DRAIN(&igi
->igi_gq
);
2464 igmp_v3_cancel_link_timers(igi
);
2467 } else if (igi
->igi_v1_timer
> 0) {
2469 * IGMPv1 Querier Present timer running.
2470 * Stop IGMPv2 timer if running.
2472 * If IGMPv1 was disabled since last timeout,
2474 * If IGMPv1 is enabled, reset IGMPv2 timer if running.
2476 if (!igmp_v1enable
) {
2477 IGMP_PRINTF(("%s: transition from v%d -> v%d "
2478 "on 0x%llx(%s%d)\n", __func__
,
2479 igi
->igi_version
, IGMP_VERSION_3
,
2480 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2481 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2482 igi
->igi_v1_timer
= 0;
2483 igi
->igi_version
= IGMP_VERSION_3
;
2484 IF_DRAIN(&igi
->igi_v2q
);
2486 --igi
->igi_v1_timer
;
2488 if (igi
->igi_v2_timer
> 0) {
2489 IGMP_PRINTF(("%s: cancel v2 timer on 0x%llx(%s%d)\n",
2491 (uint64_t)VM_KERNEL_ADDRPERM(igi
->igi_ifp
),
2492 igi
->igi_ifp
->if_name
, igi
->igi_ifp
->if_unit
));
2493 igi
->igi_v2_timer
= 0;
2499 * Dispatch an IGMPv1/v2 host report or leave message.
2500 * These are always small enough to fit inside a single mbuf.
2503 igmp_v1v2_queue_report(struct in_multi
*inm
, const int type
)
2511 INM_LOCK_ASSERT_HELD(inm
);
2512 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
2516 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
2519 MH_ALIGN(m
, sizeof(struct ip
) + sizeof(struct igmp
));
2521 m
->m_pkthdr
.len
= sizeof(struct ip
) + sizeof(struct igmp
);
2523 m
->m_data
+= sizeof(struct ip
);
2524 m
->m_len
= sizeof(struct igmp
);
2526 igmp
= mtod(m
, struct igmp
*);
2527 igmp
->igmp_type
= type
;
2528 igmp
->igmp_code
= 0;
2529 igmp
->igmp_group
= inm
->inm_addr
;
2530 igmp
->igmp_cksum
= 0;
2531 igmp
->igmp_cksum
= in_cksum(m
, sizeof(struct igmp
));
2533 m
->m_data
-= sizeof(struct ip
);
2534 m
->m_len
+= sizeof(struct ip
);
2536 ip
= mtod(m
, struct ip
*);
2538 ip
->ip_len
= sizeof(struct ip
) + sizeof(struct igmp
);
2540 ip
->ip_p
= IPPROTO_IGMP
;
2541 ip
->ip_src
.s_addr
= INADDR_ANY
;
2543 if (type
== IGMP_HOST_LEAVE_MESSAGE
)
2544 ip
->ip_dst
.s_addr
= htonl(INADDR_ALLRTRS_GROUP
);
2546 ip
->ip_dst
= inm
->inm_addr
;
2548 igmp_save_context(m
, ifp
);
2550 m
->m_flags
|= M_IGMPV2
;
2551 if (inm
->inm_igi
->igi_flags
& IGIF_LOOPBACK
)
2552 m
->m_flags
|= M_IGMP_LOOP
;
2555 * Due to the fact that at this point we are possibly holding
2556 * in_multihead_lock in shared or exclusive mode, we can't call
2557 * igmp_sendpkt() here since that will eventually call ip_output(),
2558 * which will try to lock in_multihead_lock and cause a deadlock.
2559 * Instead we defer the work to the igmp_timeout() thread, thus
2560 * avoiding unlocking in_multihead_lock here.
2562 if (IF_QFULL(&inm
->inm_igi
->igi_v2q
)) {
2563 IGMP_PRINTF(("%s: v1/v2 outbound queue full\n", __func__
));
2567 IF_ENQUEUE(&inm
->inm_igi
->igi_v2q
, m
);
2574 * Process a state change from the upper layer for the given IPv4 group.
2576 * Each socket holds a reference on the in_multi in its own ip_moptions.
2577 * The socket layer will have made the necessary updates to the group
2578 * state, it is now up to IGMP to issue a state change report if there
2579 * has been any change between T0 (when the last state-change was issued)
2582 * We use the IGMPv3 state machine at group level. The IGMP module
2583 * however makes the decision as to which IGMP protocol version to speak.
2584 * A state change *from* INCLUDE {} always means an initial join.
2585 * A state change *to* INCLUDE {} always means a final leave.
2587 * FUTURE: If IGIF_V3LITE is enabled for this interface, then we can
2588 * save ourselves a bunch of work; any exclusive mode groups need not
2589 * compute source filter lists.
2592 igmp_change_state(struct in_multi
*inm
, struct igmp_tparams
*itp
)
2594 struct igmp_ifinfo
*igi
;
2598 VERIFY(itp
!= NULL
);
2599 bzero(itp
, sizeof (*itp
));
2601 INM_LOCK_ASSERT_HELD(inm
);
2602 VERIFY(inm
->inm_igi
!= NULL
);
2603 IGI_LOCK_ASSERT_NOTHELD(inm
->inm_igi
);
2606 * Try to detect if the upper layer just asked us to change state
2607 * for an interface which has now gone away.
2609 VERIFY(inm
->inm_ifma
!= NULL
);
2610 ifp
= inm
->inm_ifma
->ifma_ifp
;
2612 * Sanity check that netinet's notion of ifp is the same as net's.
2614 VERIFY(inm
->inm_ifp
== ifp
);
2616 igi
= IGMP_IFINFO(ifp
);
2617 VERIFY(igi
!= NULL
);
2620 * If we detect a state transition to or from MCAST_UNDEFINED
2621 * for this group, then we are starting or finishing an IGMP
2622 * life cycle for this group.
2624 if (inm
->inm_st
[1].iss_fmode
!= inm
->inm_st
[0].iss_fmode
) {
2625 IGMP_PRINTF(("%s: inm transition %d -> %d\n", __func__
,
2626 inm
->inm_st
[0].iss_fmode
, inm
->inm_st
[1].iss_fmode
));
2627 if (inm
->inm_st
[0].iss_fmode
== MCAST_UNDEFINED
) {
2628 IGMP_PRINTF(("%s: initial join\n", __func__
));
2629 error
= igmp_initial_join(inm
, igi
, itp
);
2631 } else if (inm
->inm_st
[1].iss_fmode
== MCAST_UNDEFINED
) {
2632 IGMP_PRINTF(("%s: final leave\n", __func__
));
2633 igmp_final_leave(inm
, igi
, itp
);
2637 IGMP_PRINTF(("%s: filter set change\n", __func__
));
2640 error
= igmp_handle_state_change(inm
, igi
, itp
);
2646 * Perform the initial join for an IGMP group.
2648 * When joining a group:
2649 * If the group should have its IGMP traffic suppressed, do nothing.
2650 * IGMPv1 starts sending IGMPv1 host membership reports.
2651 * IGMPv2 starts sending IGMPv2 host membership reports.
2652 * IGMPv3 will schedule an IGMPv3 state-change report containing the
2653 * initial state of the membership.
2656 igmp_initial_join(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2657 struct igmp_tparams
*itp
)
2660 struct ifqueue
*ifq
;
2661 int error
, retval
, syncstates
;
2663 INM_LOCK_ASSERT_HELD(inm
);
2664 IGI_LOCK_ASSERT_NOTHELD(igi
);
2665 VERIFY(itp
!= NULL
);
2667 IGMP_INET_PRINTF(inm
->inm_addr
,
2668 ("%s: initial join %s on ifp 0x%llx(%s)\n", __func__
,
2669 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2670 if_name(inm
->inm_ifp
)));
2678 VERIFY(igi
->igi_ifp
== ifp
);
2681 * Groups joined on loopback or marked as 'not reported',
2682 * e.g. 224.0.0.1, enter the IGMP_SILENT_MEMBER state and
2683 * are never reported in any IGMP protocol exchanges.
2684 * All other groups enter the appropriate IGMP state machine
2685 * for the version in use on this link.
2686 * A link marked as IGIF_SILENT causes IGMP to be completely
2687 * disabled for the link.
2689 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2690 (igi
->igi_flags
& IGIF_SILENT
) ||
2691 !igmp_isgroupreported(inm
->inm_addr
)) {
2692 IGMP_PRINTF(("%s: not kicking state machine for silent group\n",
2694 inm
->inm_state
= IGMP_SILENT_MEMBER
;
2698 * Deal with overlapping in_multi lifecycle.
2699 * If this group was LEAVING, then make sure
2700 * we drop the reference we picked up to keep the
2701 * group around for the final INCLUDE {} enqueue.
2702 * Since we cannot call in_multi_detach() here,
2703 * defer this task to the timer routine.
2705 if (igi
->igi_version
== IGMP_VERSION_3
&&
2706 inm
->inm_state
== IGMP_LEAVING_MEMBER
) {
2707 VERIFY(inm
->inm_nrelecnt
!= 0);
2708 SLIST_INSERT_HEAD(&igi
->igi_relinmhead
, inm
, inm_nrele
);
2711 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
2713 switch (igi
->igi_version
) {
2714 case IGMP_VERSION_1
:
2715 case IGMP_VERSION_2
:
2716 inm
->inm_state
= IGMP_IDLE_MEMBER
;
2717 error
= igmp_v1v2_queue_report(inm
,
2718 (igi
->igi_version
== IGMP_VERSION_2
) ?
2719 IGMP_v2_HOST_MEMBERSHIP_REPORT
:
2720 IGMP_v1_HOST_MEMBERSHIP_REPORT
);
2722 INM_LOCK_ASSERT_HELD(inm
);
2723 IGI_LOCK_ASSERT_HELD(igi
);
2727 IGMP_RANDOM_DELAY(IGMP_V1V2_MAX_RI
);
2732 case IGMP_VERSION_3
:
2734 * Defer update of T0 to T1, until the first copy
2735 * of the state change has been transmitted.
2740 * Immediately enqueue a State-Change Report for
2741 * this interface, freeing any previous reports.
2742 * Don't kick the timers if there is nothing to do,
2743 * or if an error occurred.
2745 ifq
= &inm
->inm_scq
;
2747 retval
= igmp_v3_enqueue_group_record(ifq
, inm
, 1,
2749 itp
->cst
= (ifq
->ifq_len
> 0);
2750 IGMP_PRINTF(("%s: enqueue record = %d\n",
2753 error
= retval
* -1;
2758 * Schedule transmission of pending state-change
2759 * report up to RV times for this link. The timer
2760 * will fire at the next igmp_timeout (1 second),
2761 * giving us an opportunity to merge the reports.
2763 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
2766 VERIFY(igi
->igi_rv
> 1);
2767 inm
->inm_scrv
= igi
->igi_rv
;
2769 inm
->inm_sctimer
= 1;
2779 * Only update the T0 state if state change is atomic,
2780 * i.e. we don't need to wait for a timer to fire before we
2781 * can consider the state change to have been communicated.
2785 IGMP_INET_PRINTF(inm
->inm_addr
,
2786 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2787 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2794 * Issue an intermediate state change during the IGMP life-cycle.
2797 igmp_handle_state_change(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2798 struct igmp_tparams
*itp
)
2803 INM_LOCK_ASSERT_HELD(inm
);
2804 IGI_LOCK_ASSERT_NOTHELD(igi
);
2805 VERIFY(itp
!= NULL
);
2807 IGMP_INET_PRINTF(inm
->inm_addr
,
2808 ("%s: state change for %s on ifp 0x%llx(%s)\n", __func__
,
2809 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2810 if_name(inm
->inm_ifp
)));
2815 VERIFY(igi
->igi_ifp
== ifp
);
2817 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2818 (igi
->igi_flags
& IGIF_SILENT
) ||
2819 !igmp_isgroupreported(inm
->inm_addr
) ||
2820 (igi
->igi_version
!= IGMP_VERSION_3
)) {
2822 if (!igmp_isgroupreported(inm
->inm_addr
)) {
2823 IGMP_PRINTF(("%s: not kicking state "
2824 "machine for silent group\n", __func__
));
2826 IGMP_PRINTF(("%s: nothing to do\n", __func__
));
2828 IGMP_INET_PRINTF(inm
->inm_addr
,
2829 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2830 _igmp_inet_buf
, inm
->inm_ifp
->if_name
));
2834 IF_DRAIN(&inm
->inm_scq
);
2836 retval
= igmp_v3_enqueue_group_record(&inm
->inm_scq
, inm
, 1, 0, 0);
2837 itp
->cst
= (inm
->inm_scq
.ifq_len
> 0);
2838 IGMP_PRINTF(("%s: enqueue record = %d\n", __func__
, retval
));
2845 * If record(s) were enqueued, start the state-change
2846 * report timer for this group.
2848 inm
->inm_scrv
= ((igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : igi
->igi_rv
);
2849 inm
->inm_sctimer
= 1;
2857 * Perform the final leave for an IGMP group.
2859 * When leaving a group:
2860 * IGMPv1 does nothing.
2861 * IGMPv2 sends a host leave message, if and only if we are the reporter.
2862 * IGMPv3 enqueues a state-change report containing a transition
2863 * to INCLUDE {} for immediate transmission.
2866 igmp_final_leave(struct in_multi
*inm
, struct igmp_ifinfo
*igi
,
2867 struct igmp_tparams
*itp
)
2871 INM_LOCK_ASSERT_HELD(inm
);
2872 IGI_LOCK_ASSERT_NOTHELD(igi
);
2873 VERIFY(itp
!= NULL
);
2875 IGMP_INET_PRINTF(inm
->inm_addr
,
2876 ("%s: final leave %s on ifp 0x%llx(%s)\n", __func__
,
2877 _igmp_inet_buf
, (uint64_t)VM_KERNEL_ADDRPERM(inm
->inm_ifp
),
2878 if_name(inm
->inm_ifp
)));
2880 switch (inm
->inm_state
) {
2881 case IGMP_NOT_MEMBER
:
2882 case IGMP_SILENT_MEMBER
:
2883 case IGMP_LEAVING_MEMBER
:
2884 /* Already leaving or left; do nothing. */
2885 IGMP_PRINTF(("%s: not kicking state machine for silent group\n",
2888 case IGMP_REPORTING_MEMBER
:
2889 case IGMP_IDLE_MEMBER
:
2890 case IGMP_G_QUERY_PENDING_MEMBER
:
2891 case IGMP_SG_QUERY_PENDING_MEMBER
:
2893 if (igi
->igi_version
== IGMP_VERSION_2
) {
2894 if (inm
->inm_state
== IGMP_G_QUERY_PENDING_MEMBER
||
2895 inm
->inm_state
== IGMP_SG_QUERY_PENDING_MEMBER
) {
2896 panic("%s: IGMPv3 state reached, not IGMPv3 "
2897 "mode\n", __func__
);
2900 /* scheduler timer if enqueue is successful */
2901 itp
->cst
= (igmp_v1v2_queue_report(inm
,
2902 IGMP_HOST_LEAVE_MESSAGE
) == 0);
2904 INM_LOCK_ASSERT_HELD(inm
);
2905 IGI_LOCK_ASSERT_HELD(igi
);
2907 inm
->inm_state
= IGMP_NOT_MEMBER
;
2908 } else if (igi
->igi_version
== IGMP_VERSION_3
) {
2910 * Stop group timer and all pending reports.
2911 * Immediately enqueue a state-change report
2912 * TO_IN {} to be sent on the next timeout,
2913 * giving us an opportunity to merge reports.
2915 IF_DRAIN(&inm
->inm_scq
);
2917 if (igi
->igi_flags
& IGIF_LOOPBACK
) {
2920 inm
->inm_scrv
= igi
->igi_rv
;
2922 IGMP_INET_PRINTF(inm
->inm_addr
,
2923 ("%s: Leaving %s/%s with %d "
2924 "pending retransmissions.\n", __func__
,
2925 _igmp_inet_buf
, if_name(inm
->inm_ifp
),
2927 if (inm
->inm_scrv
== 0) {
2928 inm
->inm_state
= IGMP_NOT_MEMBER
;
2929 inm
->inm_sctimer
= 0;
2933 * Stick around in the in_multihead list;
2934 * the final detach will be issued by
2935 * igmp_v3_process_group_timers() when
2936 * the retransmit timer expires.
2938 INM_ADDREF_LOCKED(inm
);
2939 VERIFY(inm
->inm_debug
& IFD_ATTACHED
);
2941 VERIFY(inm
->inm_reqcnt
>= 1);
2942 inm
->inm_nrelecnt
++;
2943 VERIFY(inm
->inm_nrelecnt
!= 0);
2945 retval
= igmp_v3_enqueue_group_record(
2946 &inm
->inm_scq
, inm
, 1, 0, 0);
2947 itp
->cst
= (inm
->inm_scq
.ifq_len
> 0);
2948 KASSERT(retval
!= 0,
2949 ("%s: enqueue record = %d\n", __func__
,
2952 inm
->inm_state
= IGMP_LEAVING_MEMBER
;
2953 inm
->inm_sctimer
= 1;
2960 case IGMP_LAZY_MEMBER
:
2961 case IGMP_SLEEPING_MEMBER
:
2962 case IGMP_AWAKENING_MEMBER
:
2963 /* Our reports are suppressed; do nothing. */
2969 IGMP_INET_PRINTF(inm
->inm_addr
,
2970 ("%s: T1 -> T0 for %s/%s\n", __func__
,
2971 _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2972 inm
->inm_st
[1].iss_fmode
= MCAST_UNDEFINED
;
2973 IGMP_INET_PRINTF(inm
->inm_addr
,
2974 ("%s: T1 now MCAST_UNDEFINED for %s/%s\n",
2975 __func__
, _igmp_inet_buf
, if_name(inm
->inm_ifp
)));
2980 * Enqueue an IGMPv3 group record to the given output queue.
2982 * XXX This function could do with having the allocation code
2983 * split out, and the multiple-tree-walks coalesced into a single
2984 * routine as has been done in igmp_v3_enqueue_filter_change().
2986 * If is_state_change is zero, a current-state record is appended.
2987 * If is_state_change is non-zero, a state-change report is appended.
2989 * If is_group_query is non-zero, an mbuf packet chain is allocated.
2990 * If is_group_query is zero, and if there is a packet with free space
2991 * at the tail of the queue, it will be appended to providing there
2992 * is enough free space.
2993 * Otherwise a new mbuf packet chain is allocated.
2995 * If is_source_query is non-zero, each source is checked to see if
2996 * it was recorded for a Group-Source query, and will be omitted if
2997 * it is not both in-mode and recorded.
2999 * The function will attempt to allocate leading space in the packet
3000 * for the IP/IGMP header to be prepended without fragmenting the chain.
3002 * If successful the size of all data appended to the queue is returned,
3003 * otherwise an error code less than zero is returned, or zero if
3004 * no record(s) were appended.
3007 igmp_v3_enqueue_group_record(struct ifqueue
*ifq
, struct in_multi
*inm
,
3008 const int is_state_change
, const int is_group_query
,
3009 const int is_source_query
)
3011 struct igmp_grouprec ig
;
3012 struct igmp_grouprec
*pig
;
3014 struct ip_msource
*ims
, *nims
;
3015 struct mbuf
*m0
, *m
, *md
;
3016 int error
, is_filter_list_change
;
3017 int minrec0len
, m0srcs
, msrcs
, nbytes
, off
;
3018 int record_has_sources
;
3023 u_int16_t ig_numsrc
;
3025 INM_LOCK_ASSERT_HELD(inm
);
3026 IGI_LOCK_ASSERT_HELD(inm
->inm_igi
);
3030 is_filter_list_change
= 0;
3037 record_has_sources
= 1;
3039 type
= IGMP_DO_NOTHING
;
3040 mode
= inm
->inm_st
[1].iss_fmode
;
3043 * If we did not transition out of ASM mode during t0->t1,
3044 * and there are no source nodes to process, we can skip
3045 * the generation of source records.
3047 if (inm
->inm_st
[0].iss_asm
> 0 && inm
->inm_st
[1].iss_asm
> 0 &&
3049 record_has_sources
= 0;
3051 if (is_state_change
) {
3053 * Queue a state change record.
3054 * If the mode did not change, and there are non-ASM
3055 * listeners or source filters present,
3056 * we potentially need to issue two records for the group.
3057 * If we are transitioning to MCAST_UNDEFINED, we need
3058 * not send any sources.
3059 * If there are ASM listeners, and there was no filter
3060 * mode transition of any kind, do nothing.
3062 if (mode
!= inm
->inm_st
[0].iss_fmode
) {
3063 if (mode
== MCAST_EXCLUDE
) {
3064 IGMP_PRINTF(("%s: change to EXCLUDE\n",
3066 type
= IGMP_CHANGE_TO_EXCLUDE_MODE
;
3068 IGMP_PRINTF(("%s: change to INCLUDE\n",
3070 type
= IGMP_CHANGE_TO_INCLUDE_MODE
;
3071 if (mode
== MCAST_UNDEFINED
)
3072 record_has_sources
= 0;
3075 if (record_has_sources
) {
3076 is_filter_list_change
= 1;
3078 type
= IGMP_DO_NOTHING
;
3083 * Queue a current state record.
3085 if (mode
== MCAST_EXCLUDE
) {
3086 type
= IGMP_MODE_IS_EXCLUDE
;
3087 } else if (mode
== MCAST_INCLUDE
) {
3088 type
= IGMP_MODE_IS_INCLUDE
;
3089 VERIFY(inm
->inm_st
[1].iss_asm
== 0);
3094 * Generate the filter list changes using a separate function.
3096 if (is_filter_list_change
)
3097 return (igmp_v3_enqueue_filter_change(ifq
, inm
));
3099 if (type
== IGMP_DO_NOTHING
) {
3100 IGMP_INET_PRINTF(inm
->inm_addr
,
3101 ("%s: nothing to do for %s/%s\n",
3102 __func__
, _igmp_inet_buf
,
3103 if_name(inm
->inm_ifp
)));
3108 * If any sources are present, we must be able to fit at least
3109 * one in the trailing space of the tail packet's mbuf,
3112 minrec0len
= sizeof(struct igmp_grouprec
);
3113 if (record_has_sources
)
3114 minrec0len
+= sizeof(in_addr_t
);
3116 IGMP_INET_PRINTF(inm
->inm_addr
,
3117 ("%s: queueing %s for %s/%s\n", __func__
,
3118 igmp_rec_type_to_str(type
), _igmp_inet_buf
,
3119 if_name(inm
->inm_ifp
)));
3122 * Check if we have a packet in the tail of the queue for this
3123 * group into which the first group record for this group will fit.
3124 * Otherwise allocate a new packet.
3125 * Always allocate leading space for IP+RA_OPT+IGMP+REPORT.
3126 * Note: Group records for G/GSR query responses MUST be sent
3127 * in their own packet.
3130 if (!is_group_query
&&
3132 (m0
->m_pkthdr
.vt_nrecs
+ 1 <= IGMP_V3_REPORT_MAXRECS
) &&
3133 (m0
->m_pkthdr
.len
+ minrec0len
) <
3134 (ifp
->if_mtu
- IGMP_LEADINGSPACE
)) {
3135 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
3136 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3138 IGMP_PRINTF(("%s: use existing packet\n", __func__
));
3140 if (IF_QFULL(ifq
)) {
3141 IGMP_PRINTF(("%s: outbound queue full\n", __func__
));
3145 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3146 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3147 if (!is_state_change
&& !is_group_query
) {
3148 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3150 m
->m_data
+= IGMP_LEADINGSPACE
;
3153 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3155 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3160 igmp_save_context(m
, ifp
);
3162 IGMP_PRINTF(("%s: allocated first packet\n", __func__
));
3166 * Append group record.
3167 * If we have sources, we don't know how many yet.
3172 ig
.ig_group
= inm
->inm_addr
;
3173 if (!m_append(m
, sizeof(struct igmp_grouprec
), (void *)&ig
)) {
3176 IGMP_PRINTF(("%s: m_append() failed.\n", __func__
));
3179 nbytes
+= sizeof(struct igmp_grouprec
);
3182 * Append as many sources as will fit in the first packet.
3183 * If we are appending to a new packet, the chain allocation
3184 * may potentially use clusters; use m_getptr() in this case.
3185 * If we are appending to an existing packet, we need to obtain
3186 * a pointer to the group record after m_append(), in case a new
3187 * mbuf was allocated.
3188 * Only append sources which are in-mode at t1. If we are
3189 * transitioning to MCAST_UNDEFINED state on the group, do not
3190 * include source entries.
3191 * Only report recorded sources in our filter set when responding
3192 * to a group-source query.
3194 if (record_has_sources
) {
3197 pig
= (struct igmp_grouprec
*)(void *)
3198 (mtod(md
, uint8_t *) + md
->m_len
- nbytes
);
3200 md
= m_getptr(m
, 0, &off
);
3201 pig
= (struct igmp_grouprec
*)(void *)
3202 (mtod(md
, uint8_t *) + off
);
3205 RB_FOREACH_SAFE(ims
, ip_msource_tree
, &inm
->inm_srcs
, nims
) {
3207 char buf
[MAX_IPv4_STR_LEN
];
3209 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3210 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3212 now
= ims_get_mode(inm
, ims
, 1);
3213 IGMP_PRINTF(("%s: node is %d\n", __func__
, now
));
3214 if ((now
!= mode
) ||
3215 (now
== mode
&& mode
== MCAST_UNDEFINED
)) {
3216 IGMP_PRINTF(("%s: skip node\n", __func__
));
3219 if (is_source_query
&& ims
->ims_stp
== 0) {
3220 IGMP_PRINTF(("%s: skip unrecorded node\n",
3224 IGMP_PRINTF(("%s: append node\n", __func__
));
3225 naddr
= htonl(ims
->ims_haddr
);
3226 if (!m_append(m
, sizeof(in_addr_t
), (void *)&naddr
)) {
3229 IGMP_PRINTF(("%s: m_append() failed.\n",
3233 nbytes
+= sizeof(in_addr_t
);
3235 if (msrcs
== m0srcs
)
3238 IGMP_PRINTF(("%s: msrcs is %d this packet\n", __func__
,
3240 ig_numsrc
= htons(msrcs
);
3241 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3242 nbytes
+= (msrcs
* sizeof(in_addr_t
));
3245 if (is_source_query
&& msrcs
== 0) {
3246 IGMP_PRINTF(("%s: no recorded sources to report\n", __func__
));
3253 * We are good to go with first packet.
3256 IGMP_PRINTF(("%s: enqueueing first packet\n", __func__
));
3257 m
->m_pkthdr
.vt_nrecs
= 1;
3260 m
->m_pkthdr
.vt_nrecs
++;
3263 * No further work needed if no source list in packet(s).
3265 if (!record_has_sources
)
3269 * Whilst sources remain to be announced, we need to allocate
3270 * a new packet and fill out as many sources as will fit.
3271 * Always try for a cluster first.
3273 while (nims
!= NULL
) {
3274 if (IF_QFULL(ifq
)) {
3275 IGMP_PRINTF(("%s: outbound queue full\n", __func__
));
3278 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3280 m
->m_data
+= IGMP_LEADINGSPACE
;
3282 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3284 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3288 igmp_save_context(m
, ifp
);
3289 md
= m_getptr(m
, 0, &off
);
3290 pig
= (struct igmp_grouprec
*)(void *)
3291 (mtod(md
, uint8_t *) + off
);
3292 IGMP_PRINTF(("%s: allocated next packet\n", __func__
));
3294 if (!m_append(m
, sizeof(struct igmp_grouprec
), (void *)&ig
)) {
3297 IGMP_PRINTF(("%s: m_append() failed.\n", __func__
));
3300 m
->m_pkthdr
.vt_nrecs
= 1;
3301 nbytes
+= sizeof(struct igmp_grouprec
);
3303 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3304 sizeof(struct igmp_grouprec
)) / sizeof(in_addr_t
);
3307 RB_FOREACH_FROM(ims
, ip_msource_tree
, nims
) {
3309 char buf
[MAX_IPv4_STR_LEN
];
3311 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3312 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3314 now
= ims_get_mode(inm
, ims
, 1);
3315 if ((now
!= mode
) ||
3316 (now
== mode
&& mode
== MCAST_UNDEFINED
)) {
3317 IGMP_PRINTF(("%s: skip node\n", __func__
));
3320 if (is_source_query
&& ims
->ims_stp
== 0) {
3321 IGMP_PRINTF(("%s: skip unrecorded node\n",
3325 IGMP_PRINTF(("%s: append node\n", __func__
));
3326 naddr
= htonl(ims
->ims_haddr
);
3327 if (!m_append(m
, sizeof(in_addr_t
), (void *)&naddr
)) {
3330 IGMP_PRINTF(("%s: m_append() failed.\n",
3335 if (msrcs
== m0srcs
)
3338 ig_numsrc
= htons(msrcs
);
3339 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3340 nbytes
+= (msrcs
* sizeof(in_addr_t
));
3342 IGMP_PRINTF(("%s: enqueueing next packet\n", __func__
));
3350 * Type used to mark record pass completion.
3351 * We exploit the fact we can cast to this easily from the
3352 * current filter modes on each ip_msource node.
3355 REC_NONE
= 0x00, /* MCAST_UNDEFINED */
3356 REC_ALLOW
= 0x01, /* MCAST_INCLUDE */
3357 REC_BLOCK
= 0x02, /* MCAST_EXCLUDE */
3358 REC_FULL
= REC_ALLOW
| REC_BLOCK
3362 * Enqueue an IGMPv3 filter list change to the given output queue.
3364 * Source list filter state is held in an RB-tree. When the filter list
3365 * for a group is changed without changing its mode, we need to compute
3366 * the deltas between T0 and T1 for each source in the filter set,
3367 * and enqueue the appropriate ALLOW_NEW/BLOCK_OLD records.
3369 * As we may potentially queue two record types, and the entire R-B tree
3370 * needs to be walked at once, we break this out into its own function
3371 * so we can generate a tightly packed queue of packets.
3373 * XXX This could be written to only use one tree walk, although that makes
3374 * serializing into the mbuf chains a bit harder. For now we do two walks
3375 * which makes things easier on us, and it may or may not be harder on
3378 * If successful the size of all data appended to the queue is returned,
3379 * otherwise an error code less than zero is returned, or zero if
3380 * no record(s) were appended.
3383 igmp_v3_enqueue_filter_change(struct ifqueue
*ifq
, struct in_multi
*inm
)
3385 static const int MINRECLEN
=
3386 sizeof(struct igmp_grouprec
) + sizeof(in_addr_t
);
3388 struct igmp_grouprec ig
;
3389 struct igmp_grouprec
*pig
;
3390 struct ip_msource
*ims
, *nims
;
3391 struct mbuf
*m
, *m0
, *md
;
3393 int m0srcs
, nbytes
, npbytes
, off
, rsrcs
, schanged
;
3395 uint8_t mode
, now
, then
;
3396 rectype_t crt
, drt
, nrt
;
3397 u_int16_t ig_numsrc
;
3399 INM_LOCK_ASSERT_HELD(inm
);
3401 if (inm
->inm_nsrc
== 0 ||
3402 (inm
->inm_st
[0].iss_asm
> 0 && inm
->inm_st
[1].iss_asm
> 0))
3405 ifp
= inm
->inm_ifp
; /* interface */
3406 mode
= inm
->inm_st
[1].iss_fmode
; /* filter mode at t1 */
3407 crt
= REC_NONE
; /* current group record type */
3408 drt
= REC_NONE
; /* mask of completed group record types */
3409 nrt
= REC_NONE
; /* record type for current node */
3410 m0srcs
= 0; /* # source which will fit in current mbuf chain */
3411 nbytes
= 0; /* # of bytes appended to group's state-change queue */
3412 npbytes
= 0; /* # of bytes appended this packet */
3413 rsrcs
= 0; /* # sources encoded in current record */
3414 schanged
= 0; /* # nodes encoded in overall filter change */
3415 nallow
= 0; /* # of source entries in ALLOW_NEW */
3416 nblock
= 0; /* # of source entries in BLOCK_OLD */
3417 nims
= NULL
; /* next tree node pointer */
3420 * For each possible filter record mode.
3421 * The first kind of source we encounter tells us which
3422 * is the first kind of record we start appending.
3423 * If a node transitioned to UNDEFINED at t1, its mode is treated
3424 * as the inverse of the group's filter mode.
3426 while (drt
!= REC_FULL
) {
3430 (m0
->m_pkthdr
.vt_nrecs
+ 1 <=
3431 IGMP_V3_REPORT_MAXRECS
) &&
3432 (m0
->m_pkthdr
.len
+ MINRECLEN
) <
3433 (ifp
->if_mtu
- IGMP_LEADINGSPACE
)) {
3435 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
3436 sizeof(struct igmp_grouprec
)) /
3438 IGMP_PRINTF(("%s: use previous packet\n",
3441 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
3443 m
->m_data
+= IGMP_LEADINGSPACE
;
3445 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
3447 MH_ALIGN(m
, IGMP_LEADINGSPACE
);
3450 IGMP_PRINTF(("%s: m_get*() failed\n",
3454 m
->m_pkthdr
.vt_nrecs
= 0;
3455 igmp_save_context(m
, ifp
);
3456 m0srcs
= (ifp
->if_mtu
- IGMP_LEADINGSPACE
-
3457 sizeof(struct igmp_grouprec
)) /
3460 IGMP_PRINTF(("%s: allocated new packet\n",
3464 * Append the IGMP group record header to the
3465 * current packet's data area.
3466 * Recalculate pointer to free space for next
3467 * group record, in case m_append() allocated
3468 * a new mbuf or cluster.
3470 memset(&ig
, 0, sizeof(ig
));
3471 ig
.ig_group
= inm
->inm_addr
;
3472 if (!m_append(m
, sizeof(ig
), (void *)&ig
)) {
3475 IGMP_PRINTF(("%s: m_append() failed\n",
3479 npbytes
+= sizeof(struct igmp_grouprec
);
3481 /* new packet; offset in c hain */
3482 md
= m_getptr(m
, npbytes
-
3483 sizeof(struct igmp_grouprec
), &off
);
3484 pig
= (struct igmp_grouprec
*)(void *)(mtod(md
,
3487 /* current packet; offset from last append */
3489 pig
= (struct igmp_grouprec
*)(void *)(mtod(md
,
3490 uint8_t *) + md
->m_len
-
3491 sizeof(struct igmp_grouprec
));
3494 * Begin walking the tree for this record type
3495 * pass, or continue from where we left off
3496 * previously if we had to allocate a new packet.
3497 * Only report deltas in-mode at t1.
3498 * We need not report included sources as allowed
3499 * if we are in inclusive mode on the group,
3500 * however the converse is not true.
3504 nims
= RB_MIN(ip_msource_tree
, &inm
->inm_srcs
);
3505 RB_FOREACH_FROM(ims
, ip_msource_tree
, nims
) {
3507 char buf
[MAX_IPv4_STR_LEN
];
3509 inet_ntop_haddr(ims
->ims_haddr
, buf
, sizeof(buf
));
3510 IGMP_PRINTF(("%s: visit node %s\n", __func__
, buf
));
3512 now
= ims_get_mode(inm
, ims
, 1);
3513 then
= ims_get_mode(inm
, ims
, 0);
3514 IGMP_PRINTF(("%s: mode: t0 %d, t1 %d\n",
3515 __func__
, then
, now
));
3517 IGMP_PRINTF(("%s: skip unchanged\n",
3521 if (mode
== MCAST_EXCLUDE
&&
3522 now
== MCAST_INCLUDE
) {
3523 IGMP_PRINTF(("%s: skip IN src on EX "
3524 "group\n", __func__
));
3527 nrt
= (rectype_t
)now
;
3528 if (nrt
== REC_NONE
)
3529 nrt
= (rectype_t
)(~mode
& REC_FULL
);
3530 if (schanged
++ == 0) {
3532 } else if (crt
!= nrt
)
3534 naddr
= htonl(ims
->ims_haddr
);
3535 if (!m_append(m
, sizeof(in_addr_t
),
3539 IGMP_PRINTF(("%s: m_append() failed\n",
3543 nallow
+= !!(crt
== REC_ALLOW
);
3544 nblock
+= !!(crt
== REC_BLOCK
);
3545 if (++rsrcs
== m0srcs
)
3549 * If we did not append any tree nodes on this
3550 * pass, back out of allocations.
3553 npbytes
-= sizeof(struct igmp_grouprec
);
3555 IGMP_PRINTF(("%s: m_free(m)\n",
3559 IGMP_PRINTF(("%s: m_adj(m, -ig)\n",
3561 m_adj(m
, -((int)sizeof(
3562 struct igmp_grouprec
)));
3566 npbytes
+= (rsrcs
* sizeof(in_addr_t
));
3567 if (crt
== REC_ALLOW
)
3568 pig
->ig_type
= IGMP_ALLOW_NEW_SOURCES
;
3569 else if (crt
== REC_BLOCK
)
3570 pig
->ig_type
= IGMP_BLOCK_OLD_SOURCES
;
3571 ig_numsrc
= htons(rsrcs
);
3572 bcopy(&ig_numsrc
, &pig
->ig_numsrc
, sizeof (ig_numsrc
));
3574 * Count the new group record, and enqueue this
3575 * packet if it wasn't already queued.
3577 m
->m_pkthdr
.vt_nrecs
++;
3581 } while (nims
!= NULL
);
3583 crt
= (~crt
& REC_FULL
);
3586 IGMP_PRINTF(("%s: queued %d ALLOW_NEW, %d BLOCK_OLD\n", __func__
,
3593 igmp_v3_merge_state_changes(struct in_multi
*inm
, struct ifqueue
*ifscq
)
3596 struct mbuf
*m
; /* pending state-change */
3597 struct mbuf
*m0
; /* copy of pending state-change */
3598 struct mbuf
*mt
; /* last state-change in packet */
3600 int docopy
, domerge
;
3603 INM_LOCK_ASSERT_HELD(inm
);
3610 * If there are further pending retransmissions, make a writable
3611 * copy of each queued state-change message before merging.
3613 if (inm
->inm_scrv
> 0)
3618 if (gq
->ifq_head
== NULL
) {
3619 IGMP_PRINTF(("%s: WARNING: queue for inm 0x%llx is empty\n",
3620 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(inm
)));
3625 * Use IF_REMQUEUE() instead of IF_DEQUEUE() below, since the
3626 * packet might not always be at the head of the ifqueue.
3631 * Only merge the report into the current packet if
3632 * there is sufficient space to do so; an IGMPv3 report
3633 * packet may only contain 65,535 group records.
3634 * Always use a simple mbuf chain concatentation to do this,
3635 * as large state changes for single groups may have
3636 * allocated clusters.
3639 mt
= ifscq
->ifq_tail
;
3641 recslen
= m_length(m
);
3643 if ((mt
->m_pkthdr
.vt_nrecs
+
3644 m
->m_pkthdr
.vt_nrecs
<=
3645 IGMP_V3_REPORT_MAXRECS
) &&
3646 (mt
->m_pkthdr
.len
+ recslen
<=
3647 (inm
->inm_ifp
->if_mtu
- IGMP_LEADINGSPACE
)))
3651 if (!domerge
&& IF_QFULL(gq
)) {
3652 IGMP_PRINTF(("%s: outbound queue full, skipping whole "
3653 "packet 0x%llx\n", __func__
,
3654 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3665 IGMP_PRINTF(("%s: dequeueing 0x%llx\n", __func__
,
3666 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3672 IGMP_PRINTF(("%s: copying 0x%llx\n", __func__
,
3673 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3674 m0
= m_dup(m
, M_NOWAIT
);
3677 m0
->m_nextpkt
= NULL
;
3682 IGMP_PRINTF(("%s: queueing 0x%llx to ifscq 0x%llx)\n",
3683 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(m0
),
3684 (uint64_t)VM_KERNEL_ADDRPERM(ifscq
)));
3685 IF_ENQUEUE(ifscq
, m0
);
3687 struct mbuf
*mtl
; /* last mbuf of packet mt */
3689 IGMP_PRINTF(("%s: merging 0x%llx with ifscq tail "
3690 "0x%llx)\n", __func__
,
3691 (uint64_t)VM_KERNEL_ADDRPERM(m0
),
3692 (uint64_t)VM_KERNEL_ADDRPERM(mt
)));
3695 m0
->m_flags
&= ~M_PKTHDR
;
3696 mt
->m_pkthdr
.len
+= recslen
;
3697 mt
->m_pkthdr
.vt_nrecs
+=
3698 m0
->m_pkthdr
.vt_nrecs
;
3708 * Respond to a pending IGMPv3 General Query.
3711 igmp_v3_dispatch_general_query(struct igmp_ifinfo
*igi
)
3714 struct in_multi
*inm
;
3715 struct in_multistep step
;
3718 IGI_LOCK_ASSERT_HELD(igi
);
3720 VERIFY(igi
->igi_version
== IGMP_VERSION_3
);
3725 in_multihead_lock_shared();
3726 IN_FIRST_MULTI(step
, inm
);
3727 while (inm
!= NULL
) {
3729 if (inm
->inm_ifp
!= ifp
)
3732 switch (inm
->inm_state
) {
3733 case IGMP_NOT_MEMBER
:
3734 case IGMP_SILENT_MEMBER
:
3736 case IGMP_REPORTING_MEMBER
:
3737 case IGMP_IDLE_MEMBER
:
3738 case IGMP_LAZY_MEMBER
:
3739 case IGMP_SLEEPING_MEMBER
:
3740 case IGMP_AWAKENING_MEMBER
:
3741 inm
->inm_state
= IGMP_REPORTING_MEMBER
;
3743 retval
= igmp_v3_enqueue_group_record(&igi
->igi_gq
,
3746 IGMP_PRINTF(("%s: enqueue record = %d\n",
3749 case IGMP_G_QUERY_PENDING_MEMBER
:
3750 case IGMP_SG_QUERY_PENDING_MEMBER
:
3751 case IGMP_LEAVING_MEMBER
:
3756 IN_NEXT_MULTI(step
, inm
);
3758 in_multihead_lock_done();
3761 loop
= (igi
->igi_flags
& IGIF_LOOPBACK
) ? 1 : 0;
3762 igmp_dispatch_queue(igi
, &igi
->igi_gq
, IGMP_MAX_RESPONSE_BURST
,
3764 IGI_LOCK_ASSERT_HELD(igi
);
3766 * Slew transmission of bursts over 1 second intervals.
3768 if (igi
->igi_gq
.ifq_head
!= NULL
) {
3769 igi
->igi_v3_timer
= 1 + IGMP_RANDOM_DELAY(
3770 IGMP_RESPONSE_BURST_INTERVAL
);
3773 return (igi
->igi_v3_timer
);
3777 * Transmit the next pending IGMP message in the output queue.
3779 * Must not be called with inm_lock or igi_lock held.
3782 igmp_sendpkt(struct mbuf
*m
)
3784 struct ip_moptions
*imo
;
3785 struct mbuf
*ipopts
, *m0
;
3790 IGMP_PRINTF(("%s: transmit 0x%llx\n", __func__
,
3791 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3793 ifp
= igmp_restore_context(m
);
3795 * Check if the ifnet is still attached.
3797 if (ifp
== NULL
|| !ifnet_is_attached(ifp
, 0)) {
3798 IGMP_PRINTF(("%s: dropped 0x%llx as ifp went away.\n",
3799 __func__
, (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3801 OSAddAtomic(1, &ipstat
.ips_noroute
);
3805 ipopts
= igmp_sendra
? m_raopt
: NULL
;
3807 imo
= ip_allocmoptions(M_WAITOK
);
3813 imo
->imo_multicast_ttl
= 1;
3814 imo
->imo_multicast_vif
= -1;
3816 imo
->imo_multicast_loop
= (ip_mrouter
!= NULL
);
3818 imo
->imo_multicast_loop
= 0;
3822 * If the user requested that IGMP traffic be explicitly
3823 * redirected to the loopback interface (e.g. they are running a
3824 * MANET interface and the routing protocol needs to see the
3825 * updates), handle this now.
3827 if (m
->m_flags
& M_IGMP_LOOP
)
3828 imo
->imo_multicast_ifp
= lo_ifp
;
3830 imo
->imo_multicast_ifp
= ifp
;
3832 if (m
->m_flags
& M_IGMPV2
) {
3835 m0
= igmp_v3_encap_report(ifp
, m
);
3838 * If igmp_v3_encap_report() failed, then M_PREPEND()
3839 * already freed the original mbuf chain.
3840 * This means that we don't have to m_freem(m) here.
3842 IGMP_PRINTF(("%s: dropped 0x%llx\n", __func__
,
3843 (uint64_t)VM_KERNEL_ADDRPERM(m
)));
3845 atomic_add_32(&ipstat
.ips_odropped
, 1);
3850 igmp_scrub_context(m0
);
3851 m
->m_flags
&= ~(M_PROTOFLAGS
| M_IGMP_LOOP
);
3852 m0
->m_pkthdr
.rcvif
= lo_ifp
;
3854 mac_netinet_igmp_send(ifp
, m0
);
3857 if (ifp
->if_eflags
& IFEF_TXSTART
) {
3859 * Use control service class if the interface supports
3860 * transmit-start model.
3862 (void) m_set_service_class(m0
, MBUF_SC_CTL
);
3864 bzero(&ro
, sizeof (ro
));
3865 error
= ip_output(m0
, ipopts
, &ro
, 0, imo
, NULL
);
3871 IGMP_PRINTF(("%s: ip_output(0x%llx) = %d\n", __func__
,
3872 (uint64_t)VM_KERNEL_ADDRPERM(m0
), error
));
3876 IGMPSTAT_INC(igps_snd_reports
);
3877 OIGMPSTAT_INC(igps_snd_reports
);
3880 * Encapsulate an IGMPv3 report.
3882 * The internal mbuf flag M_IGMPV3_HDR is used to indicate that the mbuf
3883 * chain has already had its IP/IGMPv3 header prepended. In this case
3884 * the function will not attempt to prepend; the lengths and checksums
3885 * will however be re-computed.
3887 * Returns a pointer to the new mbuf chain head, or NULL if the
3888 * allocation failed.
3890 static struct mbuf
*
3891 igmp_v3_encap_report(struct ifnet
*ifp
, struct mbuf
*m
)
3893 struct igmp_report
*igmp
;
3895 int hdrlen
, igmpreclen
;
3897 VERIFY((m
->m_flags
& M_PKTHDR
));
3899 igmpreclen
= m_length(m
);
3900 hdrlen
= sizeof(struct ip
) + sizeof(struct igmp_report
);
3902 if (m
->m_flags
& M_IGMPV3_HDR
) {
3903 igmpreclen
-= hdrlen
;
3905 M_PREPEND(m
, hdrlen
, M_DONTWAIT
);
3908 m
->m_flags
|= M_IGMPV3_HDR
;
3911 IGMP_PRINTF(("%s: igmpreclen is %d\n", __func__
, igmpreclen
));
3913 m
->m_data
+= sizeof(struct ip
);
3914 m
->m_len
-= sizeof(struct ip
);
3916 igmp
= mtod(m
, struct igmp_report
*);
3917 igmp
->ir_type
= IGMP_v3_HOST_MEMBERSHIP_REPORT
;
3920 igmp
->ir_numgrps
= htons(m
->m_pkthdr
.vt_nrecs
);
3922 igmp
->ir_cksum
= in_cksum(m
, sizeof(struct igmp_report
) + igmpreclen
);
3923 m
->m_pkthdr
.vt_nrecs
= 0;
3925 m
->m_data
-= sizeof(struct ip
);
3926 m
->m_len
+= sizeof(struct ip
);
3928 ip
= mtod(m
, struct ip
*);
3929 ip
->ip_tos
= IPTOS_PREC_INTERNETCONTROL
;
3930 ip
->ip_len
= hdrlen
+ igmpreclen
;
3932 ip
->ip_p
= IPPROTO_IGMP
;
3935 ip
->ip_src
.s_addr
= INADDR_ANY
;
3937 if (m
->m_flags
& M_IGMP_LOOP
) {
3938 struct in_ifaddr
*ia
;
3942 IFA_LOCK(&ia
->ia_ifa
);
3943 ip
->ip_src
= ia
->ia_addr
.sin_addr
;
3944 IFA_UNLOCK(&ia
->ia_ifa
);
3945 IFA_REMREF(&ia
->ia_ifa
);
3949 ip
->ip_dst
.s_addr
= htonl(INADDR_ALLRPTS_GROUP
);
3956 igmp_rec_type_to_str(const int type
)
3959 case IGMP_CHANGE_TO_EXCLUDE_MODE
:
3962 case IGMP_CHANGE_TO_INCLUDE_MODE
:
3965 case IGMP_MODE_IS_EXCLUDE
:
3968 case IGMP_MODE_IS_INCLUDE
:
3971 case IGMP_ALLOW_NEW_SOURCES
:
3974 case IGMP_BLOCK_OLD_SOURCES
:
3985 igmp_init(struct protosw
*pp
, struct domain
*dp
)
3988 static int igmp_initialized
= 0;
3990 VERIFY((pp
->pr_flags
& (PR_INITIALIZED
|PR_ATTACHED
)) == PR_ATTACHED
);
3992 if (igmp_initialized
)
3994 igmp_initialized
= 1;
3996 IGMP_PRINTF(("%s: initializing\n", __func__
));
3998 igmp_timers_are_running
= 0;
4000 /* Setup lock group and attribute for igmp_mtx */
4001 igmp_mtx_grp_attr
= lck_grp_attr_alloc_init();
4002 igmp_mtx_grp
= lck_grp_alloc_init("igmp_mtx", igmp_mtx_grp_attr
);
4003 igmp_mtx_attr
= lck_attr_alloc_init();
4004 lck_mtx_init(&igmp_mtx
, igmp_mtx_grp
, igmp_mtx_attr
);
4006 LIST_INIT(&igi_head
);
4007 m_raopt
= igmp_ra_alloc();
4009 igi_size
= sizeof (struct igmp_ifinfo
);
4010 igi_zone
= zinit(igi_size
, IGI_ZONE_MAX
* igi_size
,
4012 if (igi_zone
== NULL
) {
4013 panic("%s: failed allocating %s", __func__
, IGI_ZONE_NAME
);
4016 zone_change(igi_zone
, Z_EXPAND
, TRUE
);
4017 zone_change(igi_zone
, Z_CALLERACCT
, FALSE
);