2 * Copyright (c) 2000-2011 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) 2009 Bruce Simpson.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. The name of the author may not be used to endorse or promote
40 * products derived from this software without specific prior written
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * Copyright (c) 1988 Stephen Deering.
58 * Copyright (c) 1992, 1993
59 * The Regents of the University of California. All rights reserved.
61 * This code is derived from software contributed to Berkeley by
62 * Stephen Deering of Stanford University.
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions
67 * 1. Redistributions of source code must retain the above copyright
68 * notice, this list of conditions and the following disclaimer.
69 * 2. Redistributions in binary form must reproduce the above copyright
70 * notice, this list of conditions and the following disclaimer in the
71 * documentation and/or other materials provided with the distribution.
72 * 3. All advertising materials mentioning features or use of this software
73 * must display the following acknowledgement:
74 * This product includes software developed by the University of
75 * California, Berkeley and its contributors.
76 * 4. Neither the name of the University nor the names of its contributors
77 * may be used to endorse or promote products derived from this software
78 * without specific prior written permission.
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92 * @(#)igmp.c 8.1 (Berkeley) 7/19/93
95 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
96 * support for mandatory and extensible security protections. This notice
97 * is included in support of clause 2.2 (b) of the Apple Public License,
101 #include <sys/cdefs.h>
103 #include <sys/param.h>
104 #include <sys/systm.h>
105 #include <sys/mbuf.h>
106 #include <sys/socket.h>
107 #include <sys/protosw.h>
108 #include <sys/sysctl.h>
109 #include <sys/kernel.h>
110 #include <sys/malloc.h>
111 #include <sys/mcache.h>
113 #include <kern/zalloc.h>
116 #include <net/route.h>
118 #include <netinet/in.h>
119 #include <netinet/in_var.h>
120 #include <netinet6/in6_var.h>
121 #include <netinet/ip6.h>
122 #include <netinet6/ip6_var.h>
123 #include <netinet6/scope6_var.h>
124 #include <netinet/icmp6.h>
125 #include <netinet6/mld6.h>
126 #include <netinet6/mld6_var.h>
128 /* Lock group and attribute for mld6_mtx */
129 static lck_attr_t
*mld_mtx_attr
;
130 static lck_grp_t
*mld_mtx_grp
;
131 static lck_grp_attr_t
*mld_mtx_grp_attr
;
134 * Locking and reference counting:
136 * mld_mtx mainly protects mli_head. In cases where both mld_mtx and
137 * in6_multihead_lock must be held, the former must be acquired first in order
138 * to maintain lock ordering. It is not a requirement that mld_mtx be
139 * acquired first before in6_multihead_lock, but in case both must be acquired
140 * in succession, the correct lock ordering must be followed.
142 * Instead of walking the if_multiaddrs list at the interface and returning
143 * the ifma_protospec value of a matching entry, we search the global list
144 * of in6_multi records and find it that way; this is done with in6_multihead
145 * lock held. Doing so avoids the race condition issues that many other BSDs
146 * suffer from (therefore in our implementation, ifma_protospec will never be
147 * NULL for as long as the in6_multi is valid.)
149 * The above creates a requirement for the in6_multi to stay in in6_multihead
150 * list even after the final MLD leave (in MLDv2 mode) until no longer needs
151 * be retransmitted (this is not required for MLDv1.) In order to handle
152 * this, the request and reference counts of the in6_multi are bumped up when
153 * the state changes to MLD_LEAVING_MEMBER, and later dropped in the timeout
154 * handler. Each in6_multi holds a reference to the underlying mld_ifinfo.
156 * Thus, the permitted lock oder is:
158 * mld_mtx, in6_multihead_lock, inm6_lock, mli_lock
160 * Any may be taken independently, but if any are held at the same time,
161 * the above lock order must be followed.
163 static decl_lck_mtx_data(, mld_mtx
);
165 SLIST_HEAD(mld_in6m_relhead
, in6_multi
);
167 static void mli_initvar(struct mld_ifinfo
*, struct ifnet
*, int);
168 static struct mld_ifinfo
*mli_alloc(int);
169 static void mli_free(struct mld_ifinfo
*);
170 static void mli_delete(const struct ifnet
*, struct mld_in6m_relhead
*);
171 static void mld_dispatch_packet(struct mbuf
*);
172 static void mld_final_leave(struct in6_multi
*, struct mld_ifinfo
*);
173 static int mld_handle_state_change(struct in6_multi
*,
174 struct mld_ifinfo
*);
175 static int mld_initial_join(struct in6_multi
*, struct mld_ifinfo
*,
178 static const char * mld_rec_type_to_str(const int);
180 static void mld_set_version(struct mld_ifinfo
*, const int);
181 static void mld_flush_relq(struct mld_ifinfo
*, struct mld_in6m_relhead
*);
182 static void mld_dispatch_queue(struct mld_ifinfo
*, struct ifqueue
*, int);
183 static int mld_v1_input_query(struct ifnet
*, const struct ip6_hdr
*,
184 /*const*/ struct mld_hdr
*);
185 static int mld_v1_input_report(struct ifnet
*, const struct ip6_hdr
*,
186 /*const*/ struct mld_hdr
*);
187 static void mld_v1_process_group_timer(struct in6_multi
*, const int);
188 static void mld_v1_process_querier_timers(struct mld_ifinfo
*);
189 static int mld_v1_transmit_report(struct in6_multi
*, const int);
190 static void mld_v1_update_group(struct in6_multi
*, const int);
191 static void mld_v2_cancel_link_timers(struct mld_ifinfo
*);
192 static void mld_v2_dispatch_general_query(struct mld_ifinfo
*);
194 mld_v2_encap_report(struct ifnet
*, struct mbuf
*);
195 static int mld_v2_enqueue_filter_change(struct ifqueue
*,
197 static int mld_v2_enqueue_group_record(struct ifqueue
*,
198 struct in6_multi
*, const int, const int, const int,
200 static int mld_v2_input_query(struct ifnet
*, const struct ip6_hdr
*,
201 struct mbuf
*, const int, const int);
202 static int mld_v2_merge_state_changes(struct in6_multi
*,
204 static void mld_v2_process_group_timers(struct mld_ifinfo
*,
205 struct ifqueue
*, struct ifqueue
*,
206 struct in6_multi
*, const int);
207 static int mld_v2_process_group_query(struct in6_multi
*,
208 int, struct mbuf
*, const int);
209 static int sysctl_mld_gsr SYSCTL_HANDLER_ARGS
;
210 static int sysctl_mld_ifinfo SYSCTL_HANDLER_ARGS
;
213 * Normative references: RFC 2710, RFC 3590, RFC 3810.
216 * A special case for IPv6 is the in6_setscope() routine. ip6_output()
217 * will not accept an ifp; it wants an embedded scope ID, unlike
218 * ip_output(), which happily takes the ifp given to it. The embedded
219 * scope ID is only used by MLD to select the outgoing interface.
221 * As such, we exploit the fact that the scope ID is just the interface
222 * index, and embed it in the IPv6 destination address accordingly.
223 * This is potentially NOT VALID for MLDv1 reports, as they
224 * are always sent to the multicast group itself; as MLDv2
225 * reports are always sent to ff02::16, this is not an issue
226 * when MLDv2 is in use.
229 #define MLD_EMBEDSCOPE(pin6, zoneid) \
230 (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)
232 static struct timeval mld_gsrdelay
= {10, 0};
233 static LIST_HEAD(, mld_ifinfo
) mli_head
;
235 static int interface_timers_running6
;
236 static int state_change_timers_running6
;
237 static int current_state_timers_running6
;
239 static decl_lck_mtx_data(, mld6_mtx
);
242 lck_mtx_lock(&mld6_mtx)
243 #define MLD_LOCK_ASSERT_HELD() \
244 lck_mtx_assert(&mld6_mtx, LCK_MTX_ASSERT_OWNED)
245 #define MLD_LOCK_ASSERT_NOTHELD() \
246 lck_mtx_assert(&mld6_mtx, LCK_MTX_ASSERT_NOTOWNED)
247 #define MLD_UNLOCK() \
248 lck_mtx_unlock(&mld6_mtx)
250 #define MLD_ADD_DETACHED_IN6M(_head, _in6m) { \
251 SLIST_INSERT_HEAD(_head, _in6m, in6m_dtle); \
254 #define MLD_REMOVE_DETACHED_IN6M(_head) { \
255 struct in6_multi *_in6m, *_inm_tmp; \
256 SLIST_FOREACH_SAFE(_in6m, _head, in6m_dtle, _inm_tmp) { \
257 SLIST_REMOVE(_head, _in6m, in6_multi, in6m_dtle); \
258 IN6M_REMREF(_in6m); \
260 VERIFY(SLIST_EMPTY(_head)); \
263 #define MLI_ZONE_MAX 64 /* maximum elements in zone */
264 #define MLI_ZONE_NAME "mld_ifinfo" /* zone name */
266 static unsigned int mli_size
; /* size of zone element */
267 static struct zone
*mli_zone
; /* zone for mld_ifinfo */
269 SYSCTL_DECL(_net_inet6
); /* Note: Not in any common header. */
271 SYSCTL_NODE(_net_inet6
, OID_AUTO
, mld
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
272 "IPv6 Multicast Listener Discovery");
273 SYSCTL_PROC(_net_inet6_mld
, OID_AUTO
, gsrdelay
,
274 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
,
275 &mld_gsrdelay
.tv_sec
, 0, sysctl_mld_gsr
, "I",
276 "Rate limit for MLDv2 Group-and-Source queries in seconds");
278 SYSCTL_NODE(_net_inet6_mld
, OID_AUTO
, ifinfo
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
279 sysctl_mld_ifinfo
, "Per-interface MLDv2 state");
281 static int mld_v1enable
= 1;
282 SYSCTL_INT(_net_inet6_mld
, OID_AUTO
, v1enable
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
283 &mld_v1enable
, 0, "Enable fallback to MLDv1");
285 static int mld_use_allow
= 1;
286 SYSCTL_INT(_net_inet6_mld
, OID_AUTO
, use_allow
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
287 &mld_use_allow
, 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves");
291 SYSCTL_INT(_net_inet6_mld
, OID_AUTO
,
292 debug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &mld_debug
, 0, "");
295 * Packed Router Alert option structure declaration.
300 struct ip6_opt_router ra
;
304 * Router Alert hop-by-hop option header.
306 static struct mld_raopt mld_ra
= {
308 .pad
= { .ip6o_type
= IP6OPT_PADN
, 0 },
310 .ip6or_type
= (u_int8_t
)IP6OPT_ROUTER_ALERT
,
311 .ip6or_len
= (u_int8_t
)(IP6OPT_RTALERT_LEN
- 2),
312 .ip6or_value
= {((IP6OPT_RTALERT_MLD
>> 8) & 0xFF),
313 (IP6OPT_RTALERT_MLD
& 0xFF) }
316 static struct ip6_pktopts mld_po
;
319 * Retrieve or set threshold between group-source queries in seconds.
322 sysctl_mld_gsr SYSCTL_HANDLER_ARGS
324 #pragma unused(arg1, arg2)
330 i
= mld_gsrdelay
.tv_sec
;
332 error
= sysctl_handle_int(oidp
, &i
, 0, req
);
333 if (error
|| !req
->newptr
)
336 if (i
< -1 || i
>= 60) {
341 mld_gsrdelay
.tv_sec
= i
;
348 * Expose struct mld_ifinfo to userland, keyed by ifindex.
349 * For use by ifmcstat(8).
353 sysctl_mld_ifinfo SYSCTL_HANDLER_ARGS
360 struct mld_ifinfo
*mli
;
361 struct mld_ifinfo_u mli_u
;
366 if (req
->newptr
!= USER_ADDR_NULL
)
374 if (name
[0] <= 0 || name
[0] > (u_int
)if_index
) {
381 ifnet_head_lock_shared();
382 ifp
= ifindex2ifnet
[name
[0]];
387 bzero(&mli_u
, sizeof (mli_u
));
389 LIST_FOREACH(mli
, &mli_head
, mli_link
) {
391 if (ifp
!= mli
->mli_ifp
) {
396 mli_u
.mli_ifindex
= mli
->mli_ifp
->if_index
;
397 mli_u
.mli_version
= mli
->mli_version
;
398 mli_u
.mli_v1_timer
= mli
->mli_v1_timer
;
399 mli_u
.mli_v2_timer
= mli
->mli_v2_timer
;
400 mli_u
.mli_flags
= mli
->mli_flags
;
401 mli_u
.mli_rv
= mli
->mli_rv
;
402 mli_u
.mli_qi
= mli
->mli_qi
;
403 mli_u
.mli_qri
= mli
->mli_qri
;
404 mli_u
.mli_uri
= mli
->mli_uri
;
407 error
= SYSCTL_OUT(req
, &mli_u
, sizeof (mli_u
));
417 * Dispatch an entire queue of pending packet chains.
419 * Must not be called with in6m_lock held.
422 mld_dispatch_queue(struct mld_ifinfo
*mli
, struct ifqueue
*ifq
, int limit
)
427 MLI_LOCK_ASSERT_HELD(mli
);
433 MLD_PRINTF(("%s: dispatch %p from %p\n", __func__
, ifq
, m
));
436 mld_dispatch_packet(m
);
444 MLI_LOCK_ASSERT_HELD(mli
);
448 * Filter outgoing MLD report state by group.
450 * Reports are ALWAYS suppressed for ALL-HOSTS (ff02::1)
451 * and node-local addresses. However, kernel and socket consumers
452 * always embed the KAME scope ID in the address provided, so strip it
453 * when performing comparison.
454 * Note: This is not the same as the *multicast* scope.
456 * Return zero if the given group is one for which MLD reports
457 * should be suppressed, or non-zero if reports should be issued.
459 static __inline__
int
460 mld_is_addr_reported(const struct in6_addr
*addr
)
463 VERIFY(IN6_IS_ADDR_MULTICAST(addr
));
465 if (IPV6_ADDR_MC_SCOPE(addr
) == IPV6_ADDR_SCOPE_NODELOCAL
)
468 if (IPV6_ADDR_MC_SCOPE(addr
) == IPV6_ADDR_SCOPE_LINKLOCAL
) {
469 struct in6_addr tmp
= *addr
;
470 in6_clearscope(&tmp
);
471 if (IN6_ARE_ADDR_EQUAL(&tmp
, &in6addr_linklocal_allnodes
))
479 * Attach MLD when PF_INET6 is attached to an interface.
482 mld_domifattach(struct ifnet
*ifp
, int how
)
484 struct mld_ifinfo
*mli
;
486 MLD_PRINTF(("%s: called for ifp %p(%s%d)\n",
487 __func__
, ifp
, ifp
->if_name
, ifp
->if_unit
));
489 mli
= mli_alloc(how
);
496 mli_initvar(mli
, ifp
, 0);
497 mli
->mli_debug
|= IFD_ATTACHED
;
498 MLI_ADDREF_LOCKED(mli
); /* hold a reference for mli_head */
499 MLI_ADDREF_LOCKED(mli
); /* hold a reference for caller */
502 LIST_INSERT_HEAD(&mli_head
, mli
, mli_link
);
506 MLD_PRINTF(("allocate mld_ifinfo for ifp %p(%s%d)\n",
507 ifp
, ifp
->if_name
, ifp
->if_unit
));
513 * Attach MLD when PF_INET6 is reattached to an interface. Caller is
514 * expected to have an outstanding reference to the mli.
517 mld_domifreattach(struct mld_ifinfo
*mli
)
524 VERIFY(!(mli
->mli_debug
& IFD_ATTACHED
));
527 mli_initvar(mli
, ifp
, 1);
528 mli
->mli_debug
|= IFD_ATTACHED
;
529 MLI_ADDREF_LOCKED(mli
); /* hold a reference for mli_head */
532 LIST_INSERT_HEAD(&mli_head
, mli
, mli_link
);
536 MLD_PRINTF(("reattached mld_ifinfo for ifp %p(%s%d)\n",
537 ifp
, ifp
->if_name
, ifp
->if_unit
));
541 * Hook for domifdetach.
544 mld_domifdetach(struct ifnet
*ifp
)
546 SLIST_HEAD(, in6_multi
) in6m_dthead
;
548 SLIST_INIT(&in6m_dthead
);
550 MLD_PRINTF(("%s: called for ifp %p(%s%d)\n",
551 __func__
, ifp
, ifp
->if_name
, ifp
->if_unit
));
554 mli_delete(ifp
, (struct mld_in6m_relhead
*)&in6m_dthead
);
557 /* Now that we're dropped all locks, release detached records */
558 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead
);
562 * Called at interface detach time. Note that we only flush all deferred
563 * responses and record releases; all remaining inm records and their source
564 * entries related to this interface are left intact, in order to handle
568 mli_delete(const struct ifnet
*ifp
, struct mld_in6m_relhead
*in6m_dthead
)
570 struct mld_ifinfo
*mli
, *tmli
;
572 MLD_LOCK_ASSERT_HELD();
574 LIST_FOREACH_SAFE(mli
, &mli_head
, mli_link
, tmli
) {
576 if (mli
->mli_ifp
== ifp
) {
578 * Free deferred General Query responses.
580 IF_DRAIN(&mli
->mli_gq
);
581 IF_DRAIN(&mli
->mli_v1q
);
582 mld_flush_relq(mli
, in6m_dthead
);
583 VERIFY(SLIST_EMPTY(&mli
->mli_relinmhead
));
584 mli
->mli_debug
&= ~IFD_ATTACHED
;
587 LIST_REMOVE(mli
, mli_link
);
588 MLI_REMREF(mli
); /* release mli_head reference */
593 panic("%s: mld_ifinfo not found for ifp %p\n", __func__
, ifp
);
597 mli_initvar(struct mld_ifinfo
*mli
, struct ifnet
*ifp
, int reattach
)
599 MLI_LOCK_ASSERT_HELD(mli
);
602 mli
->mli_version
= MLD_VERSION_2
;
604 mli
->mli_rv
= MLD_RV_INIT
;
605 mli
->mli_qi
= MLD_QI_INIT
;
606 mli
->mli_qri
= MLD_QRI_INIT
;
607 mli
->mli_uri
= MLD_URI_INIT
;
609 /* ifnet is not yet attached; no need to hold ifnet lock */
610 if (!(ifp
->if_flags
& IFF_MULTICAST
))
611 mli
->mli_flags
|= MLIF_SILENT
;
613 mli
->mli_flags
|= MLIF_USEALLOW
;
615 SLIST_INIT(&mli
->mli_relinmhead
);
618 * Responses to general queries are subject to bounds.
620 mli
->mli_gq
.ifq_maxlen
= MLD_MAX_RESPONSE_PACKETS
;
621 mli
->mli_v1q
.ifq_maxlen
= MLD_MAX_RESPONSE_PACKETS
;
624 static struct mld_ifinfo
*
627 struct mld_ifinfo
*mli
;
629 mli
= (how
== M_WAITOK
) ? zalloc(mli_zone
) : zalloc_noblock(mli_zone
);
631 bzero(mli
, mli_size
);
632 lck_mtx_init(&mli
->mli_lock
, mld_mtx_grp
, mld_mtx_attr
);
633 mli
->mli_debug
|= IFD_ALLOC
;
639 mli_free(struct mld_ifinfo
*mli
)
642 if (mli
->mli_debug
& IFD_ATTACHED
) {
643 panic("%s: attached mli=%p is being freed", __func__
, mli
);
645 } else if (mli
->mli_ifp
!= NULL
) {
646 panic("%s: ifp not NULL for mli=%p", __func__
, mli
);
648 } else if (!(mli
->mli_debug
& IFD_ALLOC
)) {
649 panic("%s: mli %p cannot be freed", __func__
, mli
);
651 } else if (mli
->mli_refcnt
!= 0) {
652 panic("%s: non-zero refcnt mli=%p", __func__
, mli
);
655 mli
->mli_debug
&= ~IFD_ALLOC
;
658 lck_mtx_destroy(&mli
->mli_lock
, mld_mtx_grp
);
659 zfree(mli_zone
, mli
);
663 mli_addref(struct mld_ifinfo
*mli
, int locked
)
668 MLI_LOCK_ASSERT_HELD(mli
);
670 if (++mli
->mli_refcnt
== 0) {
671 panic("%s: mli=%p wraparound refcnt", __func__
, mli
);
679 mli_remref(struct mld_ifinfo
*mli
)
681 SLIST_HEAD(, in6_multi
) in6m_dthead
;
686 if (mli
->mli_refcnt
== 0) {
687 panic("%s: mli=%p negative refcnt", __func__
, mli
);
692 if (mli
->mli_refcnt
> 0) {
699 IF_DRAIN(&mli
->mli_gq
);
700 IF_DRAIN(&mli
->mli_v1q
);
701 SLIST_INIT(&in6m_dthead
);
702 mld_flush_relq(mli
, (struct mld_in6m_relhead
*)&in6m_dthead
);
703 VERIFY(SLIST_EMPTY(&mli
->mli_relinmhead
));
706 /* Now that we're dropped all locks, release detached records */
707 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead
);
709 MLD_PRINTF(("%s: freeing mld_ifinfo for ifp %p(%s%d)\n",
710 __func__
, ifp
, ifp
->if_name
, ifp
->if_unit
));
716 * Process a received MLDv1 general or address-specific query.
717 * Assumes that the query header has been pulled up to sizeof(mld_hdr).
719 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
720 * mld_addr. This is OK as we own the mbuf chain.
723 mld_v1_input_query(struct ifnet
*ifp
, const struct ip6_hdr
*ip6
,
724 /*const*/ struct mld_hdr
*mld
)
726 struct mld_ifinfo
*mli
;
727 struct in6_multi
*inm
;
728 int is_general_query
;
731 is_general_query
= 0;
734 MLD_PRINTF(("ignore v1 query %s on ifp %p(%s%d)\n",
735 ip6_sprintf(&mld
->mld_addr
),
736 ifp
, ifp
->if_name
, ifp
->if_unit
));
741 * RFC3810 Section 6.2: MLD queries must originate from
742 * a router's link-local address.
744 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_src
)) {
745 MLD_PRINTF(("ignore v1 query src %s on ifp %p(%s%d)\n",
746 ip6_sprintf(&ip6
->ip6_src
),
747 ifp
, ifp
->if_name
, ifp
->if_unit
));
752 * Do address field validation upfront before we accept
755 if (IN6_IS_ADDR_UNSPECIFIED(&mld
->mld_addr
)) {
757 * MLDv1 General Query.
758 * If this was not sent to the all-nodes group, ignore it.
763 in6_clearscope(&dst
);
764 if (!IN6_ARE_ADDR_EQUAL(&dst
, &in6addr_linklocal_allnodes
))
766 is_general_query
= 1;
769 * Embed scope ID of receiving interface in MLD query for
770 * lookup whilst we don't hold other locks.
772 in6_setscope(&mld
->mld_addr
, ifp
, NULL
);
776 * Switch to MLDv1 host compatibility mode.
778 mli
= MLD_IFINFO(ifp
);
782 mld_set_version(mli
, MLD_VERSION_1
);
785 timer
= (ntohs(mld
->mld_maxdelay
) * PR_SLOWHZ
) / MLD_TIMER_SCALE
;
789 if (is_general_query
) {
790 struct in6_multistep step
;
792 MLD_PRINTF(("process v1 general query on ifp %p(%s%d)\n",
793 ifp
, ifp
->if_name
, ifp
->if_unit
));
795 * For each reporting group joined on this
796 * interface, kick the report timer.
798 in6_multihead_lock_shared();
799 IN6_FIRST_MULTI(step
, inm
);
800 while (inm
!= NULL
) {
802 if (inm
->in6m_ifp
== ifp
)
803 mld_v1_update_group(inm
, timer
);
805 IN6_NEXT_MULTI(step
, inm
);
807 in6_multihead_lock_done();
810 * MLDv1 Group-Specific Query.
811 * If this is a group-specific MLDv1 query, we need only
812 * look up the single group to process it.
814 in6_multihead_lock_shared();
815 IN6_LOOKUP_MULTI(&mld
->mld_addr
, ifp
, inm
);
816 in6_multihead_lock_done();
820 MLD_PRINTF(("process v1 query %s on ifp %p(%s%d)\n",
821 ip6_sprintf(&mld
->mld_addr
),
822 ifp
, ifp
->if_name
, ifp
->if_unit
));
823 mld_v1_update_group(inm
, timer
);
825 IN6M_REMREF(inm
); /* from IN6_LOOKUP_MULTI */
827 /* XXX Clear embedded scope ID as userland won't expect it. */
828 in6_clearscope(&mld
->mld_addr
);
835 * Update the report timer on a group in response to an MLDv1 query.
837 * If we are becoming the reporting member for this group, start the timer.
838 * If we already are the reporting member for this group, and timer is
839 * below the threshold, reset it.
841 * We may be updating the group for the first time since we switched
842 * to MLDv2. If we are, then we must clear any recorded source lists,
843 * and transition to REPORTING state; the group timer is overloaded
844 * for group and group-source query responses.
846 * Unlike MLDv2, the delay per group should be jittered
847 * to avoid bursts of MLDv1 reports.
850 mld_v1_update_group(struct in6_multi
*inm
, const int timer
)
852 IN6M_LOCK_ASSERT_HELD(inm
);
854 MLD_PRINTF(("%s: %s/%s%d timer=%d\n", __func__
,
855 ip6_sprintf(&inm
->in6m_addr
),
856 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
, timer
));
858 switch (inm
->in6m_state
) {
860 case MLD_SILENT_MEMBER
:
862 case MLD_REPORTING_MEMBER
:
863 if (inm
->in6m_timer
!= 0 &&
864 inm
->in6m_timer
<= timer
) {
865 MLD_PRINTF(("%s: REPORTING and timer running, "
866 "skipping.\n", __func__
));
870 case MLD_SG_QUERY_PENDING_MEMBER
:
871 case MLD_G_QUERY_PENDING_MEMBER
:
872 case MLD_IDLE_MEMBER
:
873 case MLD_LAZY_MEMBER
:
874 case MLD_AWAKENING_MEMBER
:
875 MLD_PRINTF(("%s: ->REPORTING\n", __func__
));
876 inm
->in6m_state
= MLD_REPORTING_MEMBER
;
877 inm
->in6m_timer
= MLD_RANDOM_DELAY(timer
);
878 current_state_timers_running6
= 1;
880 case MLD_SLEEPING_MEMBER
:
881 MLD_PRINTF(("%s: ->AWAKENING\n", __func__
));
882 inm
->in6m_state
= MLD_AWAKENING_MEMBER
;
884 case MLD_LEAVING_MEMBER
:
890 * Process a received MLDv2 general, group-specific or
891 * group-and-source-specific query.
893 * Assumes that the query header has been pulled up to sizeof(mldv2_query).
895 * Return 0 if successful, otherwise an appropriate error code is returned.
898 mld_v2_input_query(struct ifnet
*ifp
, const struct ip6_hdr
*ip6
,
899 struct mbuf
*m
, const int off
, const int icmp6len
)
901 struct mld_ifinfo
*mli
;
902 struct mldv2_query
*mld
;
903 struct in6_multi
*inm
;
904 uint32_t maxdelay
, nsrc
, qqi
;
905 int is_general_query
;
909 is_general_query
= 0;
912 * RFC3810 Section 6.2: MLD queries must originate from
913 * a router's link-local address.
915 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_src
)) {
916 MLD_PRINTF(("ignore v1 query src %s on ifp %p(%s%d)\n",
917 ip6_sprintf(&ip6
->ip6_src
),
918 ifp
, ifp
->if_name
, ifp
->if_unit
));
922 MLD_PRINTF(("input v2 query on ifp %p(%s%d)\n", ifp
, ifp
->if_name
,
925 mld
= (struct mldv2_query
*)(mtod(m
, uint8_t *) + off
);
927 maxdelay
= ntohs(mld
->mld_maxdelay
); /* in 1/10ths of a second */
928 if (maxdelay
>= 32678) {
929 maxdelay
= (MLD_MRC_MANT(maxdelay
) | 0x1000) <<
930 (MLD_MRC_EXP(maxdelay
) + 3);
932 timer
= (maxdelay
* PR_SLOWHZ
) / MLD_TIMER_SCALE
;
936 qrv
= MLD_QRV(mld
->mld_misc
);
938 MLD_PRINTF(("%s: clamping qrv %d to %d\n", __func__
,
945 qqi
= MLD_QQIC_MANT(mld
->mld_qqi
) <<
946 (MLD_QQIC_EXP(mld
->mld_qqi
) + 3);
949 nsrc
= ntohs(mld
->mld_numsrc
);
950 if (nsrc
> MLD_MAX_GS_SOURCES
)
952 if (icmp6len
< sizeof(struct mldv2_query
) +
953 (nsrc
* sizeof(struct in6_addr
)))
957 * Do further input validation upfront to avoid resetting timers
958 * should we need to discard this query.
960 if (IN6_IS_ADDR_UNSPECIFIED(&mld
->mld_addr
)) {
962 * General Queries SHOULD be directed to ff02::1.
963 * A general query with a source list has undefined
964 * behaviour; discard it.
969 in6_clearscope(&dst
);
970 if (!IN6_ARE_ADDR_EQUAL(&dst
, &in6addr_linklocal_allnodes
) ||
973 is_general_query
= 1;
976 * Embed scope ID of receiving interface in MLD query for
977 * lookup whilst we don't hold other locks (due to KAME
978 * locking lameness). We own this mbuf chain just now.
980 in6_setscope(&mld
->mld_addr
, ifp
, NULL
);
983 mli
= MLD_IFINFO(ifp
);
988 * Discard the v2 query if we're in Compatibility Mode.
989 * The RFC is pretty clear that hosts need to stay in MLDv1 mode
990 * until the Old Version Querier Present timer expires.
992 if (mli
->mli_version
!= MLD_VERSION_2
) {
997 mld_set_version(mli
, MLD_VERSION_2
);
1000 mli
->mli_qri
= maxdelay
;
1002 MLD_PRINTF(("%s: qrv %d qi %d maxdelay %d\n", __func__
, qrv
, qqi
,
1005 if (is_general_query
) {
1007 * MLDv2 General Query.
1009 * Schedule a current-state report on this ifp for
1010 * all groups, possibly containing source lists.
1012 * If there is a pending General Query response
1013 * scheduled earlier than the selected delay, do
1014 * not schedule any other reports.
1015 * Otherwise, reset the interface timer.
1017 MLD_PRINTF(("process v2 general query on ifp %p(%s%d)\n",
1018 ifp
, ifp
->if_name
, ifp
->if_unit
));
1019 if (mli
->mli_v2_timer
== 0 || mli
->mli_v2_timer
>= timer
) {
1020 mli
->mli_v2_timer
= MLD_RANDOM_DELAY(timer
);
1021 interface_timers_running6
= 1;
1027 * MLDv2 Group-specific or Group-and-source-specific Query.
1029 * Group-source-specific queries are throttled on
1030 * a per-group basis to defeat denial-of-service attempts.
1031 * Queries for groups we are not a member of on this
1032 * link are simply ignored.
1034 in6_multihead_lock_shared();
1035 IN6_LOOKUP_MULTI(&mld
->mld_addr
, ifp
, inm
);
1036 in6_multihead_lock_done();
1042 /* TODO: need ratecheck equivalent */
1044 if (!ratecheck(&inm
->in6m_lastgsrtv
,
1046 MLD_PRINTF(("%s: GS query throttled.\n",
1049 IN6M_REMREF(inm
); /* from IN6_LOOKUP_MULTI */
1054 MLD_PRINTF(("process v2 group query on ifp %p(%s%d)\n",
1055 ifp
, ifp
->if_name
, ifp
->if_unit
));
1057 * If there is a pending General Query response
1058 * scheduled sooner than the selected delay, no
1059 * further report need be scheduled.
1060 * Otherwise, prepare to respond to the
1061 * group-specific or group-and-source query.
1064 if (mli
->mli_v2_timer
== 0 || mli
->mli_v2_timer
>= timer
) {
1066 mld_v2_process_group_query(inm
, timer
, m
, off
);
1071 IN6M_REMREF(inm
); /* from IN6_LOOKUP_MULTI */
1072 /* XXX Clear embedded scope ID as userland won't expect it. */
1073 in6_clearscope(&mld
->mld_addr
);
1080 * Process a recieved MLDv2 group-specific or group-and-source-specific
1082 * Return <0 if any error occured. Currently this is ignored.
1085 mld_v2_process_group_query(struct in6_multi
*inm
, int timer
, struct mbuf
*m0
,
1088 struct mldv2_query
*mld
;
1092 IN6M_LOCK_ASSERT_HELD(inm
);
1095 mld
= (struct mldv2_query
*)(mtod(m0
, uint8_t *) + off
);
1097 switch (inm
->in6m_state
) {
1098 case MLD_NOT_MEMBER
:
1099 case MLD_SILENT_MEMBER
:
1100 case MLD_SLEEPING_MEMBER
:
1101 case MLD_LAZY_MEMBER
:
1102 case MLD_AWAKENING_MEMBER
:
1103 case MLD_IDLE_MEMBER
:
1104 case MLD_LEAVING_MEMBER
:
1107 case MLD_REPORTING_MEMBER
:
1108 case MLD_G_QUERY_PENDING_MEMBER
:
1109 case MLD_SG_QUERY_PENDING_MEMBER
:
1113 nsrc
= ntohs(mld
->mld_numsrc
);
1116 * Deal with group-specific queries upfront.
1117 * If any group query is already pending, purge any recorded
1118 * source-list state if it exists, and schedule a query response
1119 * for this group-specific query.
1122 if (inm
->in6m_state
== MLD_G_QUERY_PENDING_MEMBER
||
1123 inm
->in6m_state
== MLD_SG_QUERY_PENDING_MEMBER
) {
1124 in6m_clear_recorded(inm
);
1125 timer
= min(inm
->in6m_timer
, timer
);
1127 inm
->in6m_state
= MLD_G_QUERY_PENDING_MEMBER
;
1128 inm
->in6m_timer
= MLD_RANDOM_DELAY(timer
);
1129 current_state_timers_running6
= 1;
1134 * Deal with the case where a group-and-source-specific query has
1135 * been received but a group-specific query is already pending.
1137 if (inm
->in6m_state
== MLD_G_QUERY_PENDING_MEMBER
) {
1138 timer
= min(inm
->in6m_timer
, timer
);
1139 inm
->in6m_timer
= MLD_RANDOM_DELAY(timer
);
1140 current_state_timers_running6
= 1;
1145 * Finally, deal with the case where a group-and-source-specific
1146 * query has been received, where a response to a previous g-s-r
1147 * query exists, or none exists.
1148 * In this case, we need to parse the source-list which the Querier
1149 * has provided us with and check if we have any source list filter
1150 * entries at T1 for these sources. If we do not, there is no need
1151 * schedule a report and the query may be dropped.
1152 * If we do, we must record them and schedule a current-state
1153 * report for those sources.
1155 if (inm
->in6m_nsrc
> 0) {
1162 soff
= off
+ sizeof(struct mldv2_query
);
1164 for (i
= 0; i
< nsrc
; i
++) {
1165 sp
= mtod(m
, uint8_t *) + soff
;
1166 retval
= in6m_record_source(inm
,
1167 (const struct in6_addr
*)sp
);
1170 nrecorded
+= retval
;
1171 soff
+= sizeof(struct in6_addr
);
1172 if (soff
>= m
->m_len
) {
1173 soff
= soff
- m
->m_len
;
1179 if (nrecorded
> 0) {
1180 MLD_PRINTF(( "%s: schedule response to SG query\n",
1182 inm
->in6m_state
= MLD_SG_QUERY_PENDING_MEMBER
;
1183 inm
->in6m_timer
= MLD_RANDOM_DELAY(timer
);
1184 current_state_timers_running6
= 1;
1192 * Process a received MLDv1 host membership report.
1193 * Assumes mld points to mld_hdr in pulled up mbuf chain.
1195 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
1196 * mld_addr. This is OK as we own the mbuf chain.
1199 mld_v1_input_report(struct ifnet
*ifp
, const struct ip6_hdr
*ip6
,
1200 /*const*/ struct mld_hdr
*mld
)
1202 struct in6_addr src
, dst
;
1203 struct in6_ifaddr
*ia
;
1204 struct in6_multi
*inm
;
1206 if (!mld_v1enable
) {
1207 MLD_PRINTF(("ignore v1 report %s on ifp %p(%s%d)\n",
1208 ip6_sprintf(&mld
->mld_addr
),
1209 ifp
, ifp
->if_name
, ifp
->if_unit
));
1213 if (ifp
->if_flags
& IFF_LOOPBACK
)
1217 * MLDv1 reports must originate from a host's link-local address,
1218 * or the unspecified address (when booting).
1221 in6_clearscope(&src
);
1222 if (!IN6_IS_SCOPE_LINKLOCAL(&src
) && !IN6_IS_ADDR_UNSPECIFIED(&src
)) {
1223 MLD_PRINTF(("ignore v1 query src %s on ifp %p(%s%d)\n",
1224 ip6_sprintf(&ip6
->ip6_src
),
1225 ifp
, ifp
->if_name
, ifp
->if_unit
));
1230 * RFC2710 Section 4: MLDv1 reports must pertain to a multicast
1231 * group, and must be directed to the group itself.
1234 in6_clearscope(&dst
);
1235 if (!IN6_IS_ADDR_MULTICAST(&mld
->mld_addr
) ||
1236 !IN6_ARE_ADDR_EQUAL(&mld
->mld_addr
, &dst
)) {
1237 MLD_PRINTF(("ignore v1 query dst %s on ifp %p(%s%d)\n",
1238 ip6_sprintf(&ip6
->ip6_dst
),
1239 ifp
, ifp
->if_name
, ifp
->if_unit
));
1244 * Make sure we don't hear our own membership report, as fast
1245 * leave requires knowing that we are the only member of a
1246 * group. Assume we used the link-local address if available,
1247 * otherwise look for ::.
1249 * XXX Note that scope ID comparison is needed for the address
1250 * returned by in6ifa_ifpforlinklocal(), but SHOULD NOT be
1251 * performed for the on-wire address.
1253 ia
= in6ifa_ifpforlinklocal(ifp
, IN6_IFF_NOTREADY
|IN6_IFF_ANYCAST
);
1255 IFA_LOCK(&ia
->ia_ifa
);
1256 if ((IN6_ARE_ADDR_EQUAL(&ip6
->ip6_src
, IA6_IN6(ia
)))){
1257 IFA_UNLOCK(&ia
->ia_ifa
);
1258 IFA_REMREF(&ia
->ia_ifa
);
1261 IFA_UNLOCK(&ia
->ia_ifa
);
1262 IFA_REMREF(&ia
->ia_ifa
);
1263 } else if (IN6_IS_ADDR_UNSPECIFIED(&src
)) {
1267 MLD_PRINTF(("process v1 report %s on ifp %p(%s%d)\n",
1268 ip6_sprintf(&mld
->mld_addr
), ifp
, ifp
->if_name
, ifp
->if_unit
));
1271 * Embed scope ID of receiving interface in MLD query for lookup
1272 * whilst we don't hold other locks (due to KAME locking lameness).
1274 if (!IN6_IS_ADDR_UNSPECIFIED(&mld
->mld_addr
))
1275 in6_setscope(&mld
->mld_addr
, ifp
, NULL
);
1278 * MLDv1 report suppression.
1279 * If we are a member of this group, and our membership should be
1280 * reported, and our group timer is pending or about to be reset,
1281 * stop our group timer by transitioning to the 'lazy' state.
1283 in6_multihead_lock_shared();
1284 IN6_LOOKUP_MULTI(&mld
->mld_addr
, ifp
, inm
);
1285 in6_multihead_lock_done();
1288 struct mld_ifinfo
*mli
;
1291 mli
= inm
->in6m_mli
;
1292 VERIFY(mli
!= NULL
);
1296 * If we are in MLDv2 host mode, do not allow the
1297 * other host's MLDv1 report to suppress our reports.
1299 if (mli
->mli_version
== MLD_VERSION_2
) {
1302 IN6M_REMREF(inm
); /* from IN6_LOOKUP_MULTI */
1307 inm
->in6m_timer
= 0;
1309 switch (inm
->in6m_state
) {
1310 case MLD_NOT_MEMBER
:
1311 case MLD_SILENT_MEMBER
:
1312 case MLD_SLEEPING_MEMBER
:
1314 case MLD_REPORTING_MEMBER
:
1315 case MLD_IDLE_MEMBER
:
1316 case MLD_AWAKENING_MEMBER
:
1317 MLD_PRINTF(("report suppressed for %s on ifp %p(%s%d)\n",
1318 ip6_sprintf(&mld
->mld_addr
),
1319 ifp
, ifp
->if_name
, ifp
->if_unit
));
1320 case MLD_LAZY_MEMBER
:
1321 inm
->in6m_state
= MLD_LAZY_MEMBER
;
1323 case MLD_G_QUERY_PENDING_MEMBER
:
1324 case MLD_SG_QUERY_PENDING_MEMBER
:
1325 case MLD_LEAVING_MEMBER
:
1329 IN6M_REMREF(inm
); /* from IN6_LOOKUP_MULTI */
1333 /* XXX Clear embedded scope ID as userland won't expect it. */
1334 in6_clearscope(&mld
->mld_addr
);
1342 * Assume query messages which fit in a single ICMPv6 message header
1343 * have been pulled up.
1344 * Assume that userland will want to see the message, even if it
1345 * otherwise fails kernel input validation; do not free it.
1346 * Pullup may however free the mbuf chain m if it fails.
1348 * Return IPPROTO_DONE if we freed m. Otherwise, return 0.
1351 mld_input(struct mbuf
*m
, int off
, int icmp6len
)
1354 struct ip6_hdr
*ip6
;
1355 struct mld_hdr
*mld
;
1358 MLD_PRINTF(("%s: called w/mbuf (%p,%d)\n", __func__
, m
, off
));
1360 ifp
= m
->m_pkthdr
.rcvif
;
1362 ip6
= mtod(m
, struct ip6_hdr
*);
1364 /* Pullup to appropriate size. */
1365 mld
= (struct mld_hdr
*)(mtod(m
, uint8_t *) + off
);
1366 if (mld
->mld_type
== MLD_LISTENER_QUERY
&&
1367 icmp6len
>= sizeof(struct mldv2_query
)) {
1368 mldlen
= sizeof(struct mldv2_query
);
1370 mldlen
= sizeof(struct mld_hdr
);
1372 IP6_EXTHDR_GET(mld
, struct mld_hdr
*, m
, off
, mldlen
);
1374 icmp6stat
.icp6s_badlen
++;
1375 return (IPPROTO_DONE
);
1379 * Userland needs to see all of this traffic for implementing
1380 * the endpoint discovery portion of multicast routing.
1382 switch (mld
->mld_type
) {
1383 case MLD_LISTENER_QUERY
:
1384 icmp6_ifstat_inc(ifp
, ifs6_in_mldquery
);
1385 if (icmp6len
== sizeof(struct mld_hdr
)) {
1386 if (mld_v1_input_query(ifp
, ip6
, mld
) != 0)
1388 } else if (icmp6len
>= sizeof(struct mldv2_query
)) {
1389 if (mld_v2_input_query(ifp
, ip6
, m
, off
,
1394 case MLD_LISTENER_REPORT
:
1395 icmp6_ifstat_inc(ifp
, ifs6_in_mldreport
);
1396 if (mld_v1_input_report(ifp
, ip6
, mld
) != 0)
1399 case MLDV2_LISTENER_REPORT
:
1400 icmp6_ifstat_inc(ifp
, ifs6_in_mldreport
);
1402 case MLD_LISTENER_DONE
:
1403 icmp6_ifstat_inc(ifp
, ifs6_in_mlddone
);
1413 * MLD6 slowtimo handler.
1414 * Combiles both the slow and fast timer into one. We loose some responsivness but
1415 * allows the system to avoid having a pr_fasttimo, thus allowing for power savings.
1420 struct ifqueue scq
; /* State-change packets */
1421 struct ifqueue qrq
; /* Query response packets */
1423 struct mld_ifinfo
*mli
;
1424 struct in6_multi
*inm
;
1426 SLIST_HEAD(, in6_multi
) in6m_dthead
;
1428 SLIST_INIT(&in6m_dthead
);
1432 LIST_FOREACH(mli
, &mli_head
, mli_link
) {
1434 mld_v1_process_querier_timers(mli
);
1439 * Quick check to see if any work needs to be done, in order to
1440 * minimize the overhead of fasttimo processing.
1442 if (!current_state_timers_running6
&&
1443 !interface_timers_running6
&&
1444 !state_change_timers_running6
) {
1450 * MLDv2 General Query response timer processing.
1452 if (interface_timers_running6
) {
1454 MLD_PRINTF(("%s: interface timers running\n", __func__
));
1456 interface_timers_running6
= 0;
1457 LIST_FOREACH(mli
, &mli_head
, mli_link
) {
1459 if (mli
->mli_v2_timer
== 0) {
1461 } else if (--mli
->mli_v2_timer
== 0) {
1462 mld_v2_dispatch_general_query(mli
);
1464 interface_timers_running6
= 1;
1470 if (!current_state_timers_running6
&&
1471 !state_change_timers_running6
)
1474 current_state_timers_running6
= 0;
1475 state_change_timers_running6
= 0;
1477 MLD_PRINTF(("%s: state change timers running\n", __func__
));
1480 memset(&qrq
, 0, sizeof(struct ifqueue
));
1481 qrq
.ifq_maxlen
= MLD_MAX_G_GS_PACKETS
;
1483 memset(&scq
, 0, sizeof(struct ifqueue
));
1484 scq
.ifq_maxlen
= MLD_MAX_STATE_CHANGE_PACKETS
;
1487 * MLD host report and state-change timer processing.
1488 * Note: Processing a v2 group timer may remove a node.
1490 LIST_FOREACH(mli
, &mli_head
, mli_link
) {
1491 struct in6_multistep step
;
1495 uri_fasthz
= MLD_RANDOM_DELAY(mli
->mli_uri
* PR_SLOWHZ
);
1498 in6_multihead_lock_shared();
1499 IN6_FIRST_MULTI(step
, inm
);
1500 while (inm
!= NULL
) {
1502 if (inm
->in6m_ifp
!= ifp
)
1506 switch (mli
->mli_version
) {
1508 mld_v1_process_group_timer(inm
,
1512 mld_v2_process_group_timers(mli
, &qrq
,
1513 &scq
, inm
, uri_fasthz
);
1519 IN6_NEXT_MULTI(step
, inm
);
1521 in6_multihead_lock_done();
1524 if (mli
->mli_version
== MLD_VERSION_1
) {
1525 mld_dispatch_queue(mli
, &mli
->mli_v1q
, 0);
1526 } else if (mli
->mli_version
== MLD_VERSION_2
) {
1528 mld_dispatch_queue(NULL
, &qrq
, 0);
1529 mld_dispatch_queue(NULL
, &scq
, 0);
1530 VERIFY(qrq
.ifq_len
== 0);
1531 VERIFY(scq
.ifq_len
== 0);
1535 * In case there are still any pending membership reports
1536 * which didn't get drained at version change time.
1538 IF_DRAIN(&mli
->mli_v1q
);
1540 * Release all deferred inm records, and drain any locally
1541 * enqueued packets; do it even if the current MLD version
1542 * for the link is no longer MLDv2, in order to handle the
1543 * version change case.
1545 mld_flush_relq(mli
, (struct mld_in6m_relhead
*)&in6m_dthead
);
1546 VERIFY(SLIST_EMPTY(&mli
->mli_relinmhead
));
1556 /* Now that we're dropped all locks, release detached records */
1557 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead
);
1561 * Free the in6_multi reference(s) for this MLD lifecycle.
1563 * Caller must be holding mli_lock.
1566 mld_flush_relq(struct mld_ifinfo
*mli
, struct mld_in6m_relhead
*in6m_dthead
)
1568 struct in6_multi
*inm
;
1571 MLI_LOCK_ASSERT_HELD(mli
);
1572 inm
= SLIST_FIRST(&mli
->mli_relinmhead
);
1576 SLIST_REMOVE_HEAD(&mli
->mli_relinmhead
, in6m_nrele
);
1579 in6_multihead_lock_exclusive();
1581 VERIFY(inm
->in6m_nrelecnt
!= 0);
1582 inm
->in6m_nrelecnt
--;
1583 lastref
= in6_multi_detach(inm
);
1584 VERIFY(!lastref
|| (!(inm
->in6m_debug
& IFD_ATTACHED
) &&
1585 inm
->in6m_reqcnt
== 0));
1587 in6_multihead_lock_done();
1588 /* from mli_relinmhead */
1590 /* from in6_multihead_list */
1593 * Defer releasing our final reference, as we
1594 * are holding the MLD lock at this point, and
1595 * we could end up with locking issues later on
1596 * (while issuing SIOCDELMULTI) when this is the
1597 * final reference count. Let the caller do it
1600 MLD_ADD_DETACHED_IN6M(in6m_dthead
, inm
);
1608 * Update host report group timer.
1609 * Will update the global pending timer flags.
1612 mld_v1_process_group_timer(struct in6_multi
*inm
, const int mld_version
)
1614 #pragma unused(mld_version)
1615 int report_timer_expired
;
1617 IN6M_LOCK_ASSERT_HELD(inm
);
1618 MLI_LOCK_ASSERT_HELD(inm
->in6m_mli
);
1620 if (inm
->in6m_timer
== 0) {
1621 report_timer_expired
= 0;
1622 } else if (--inm
->in6m_timer
== 0) {
1623 report_timer_expired
= 1;
1625 current_state_timers_running6
= 1;
1629 switch (inm
->in6m_state
) {
1630 case MLD_NOT_MEMBER
:
1631 case MLD_SILENT_MEMBER
:
1632 case MLD_IDLE_MEMBER
:
1633 case MLD_LAZY_MEMBER
:
1634 case MLD_SLEEPING_MEMBER
:
1635 case MLD_AWAKENING_MEMBER
:
1637 case MLD_REPORTING_MEMBER
:
1638 if (report_timer_expired
) {
1639 inm
->in6m_state
= MLD_IDLE_MEMBER
;
1640 (void) mld_v1_transmit_report(inm
,
1641 MLD_LISTENER_REPORT
);
1642 IN6M_LOCK_ASSERT_HELD(inm
);
1643 MLI_LOCK_ASSERT_HELD(inm
->in6m_mli
);
1646 case MLD_G_QUERY_PENDING_MEMBER
:
1647 case MLD_SG_QUERY_PENDING_MEMBER
:
1648 case MLD_LEAVING_MEMBER
:
1654 * Update a group's timers for MLDv2.
1655 * Will update the global pending timer flags.
1656 * Note: Unlocked read from mli.
1659 mld_v2_process_group_timers(struct mld_ifinfo
*mli
,
1660 struct ifqueue
*qrq
, struct ifqueue
*scq
,
1661 struct in6_multi
*inm
, const int uri_fasthz
)
1663 int query_response_timer_expired
;
1664 int state_change_retransmit_timer_expired
;
1666 IN6M_LOCK_ASSERT_HELD(inm
);
1667 MLI_LOCK_ASSERT_HELD(mli
);
1668 VERIFY(mli
== inm
->in6m_mli
);
1670 query_response_timer_expired
= 0;
1671 state_change_retransmit_timer_expired
= 0;
1674 * During a transition from compatibility mode back to MLDv2,
1675 * a group record in REPORTING state may still have its group
1676 * timer active. This is a no-op in this function; it is easier
1677 * to deal with it here than to complicate the slow-timeout path.
1679 if (inm
->in6m_timer
== 0) {
1680 query_response_timer_expired
= 0;
1681 } else if (--inm
->in6m_timer
== 0) {
1682 query_response_timer_expired
= 1;
1684 current_state_timers_running6
= 1;
1687 if (inm
->in6m_sctimer
== 0) {
1688 state_change_retransmit_timer_expired
= 0;
1689 } else if (--inm
->in6m_sctimer
== 0) {
1690 state_change_retransmit_timer_expired
= 1;
1692 state_change_timers_running6
= 1;
1695 /* We are in fasttimo, so be quick about it. */
1696 if (!state_change_retransmit_timer_expired
&&
1697 !query_response_timer_expired
)
1700 switch (inm
->in6m_state
) {
1701 case MLD_NOT_MEMBER
:
1702 case MLD_SILENT_MEMBER
:
1703 case MLD_SLEEPING_MEMBER
:
1704 case MLD_LAZY_MEMBER
:
1705 case MLD_AWAKENING_MEMBER
:
1706 case MLD_IDLE_MEMBER
:
1708 case MLD_G_QUERY_PENDING_MEMBER
:
1709 case MLD_SG_QUERY_PENDING_MEMBER
:
1711 * Respond to a previously pending Group-Specific
1712 * or Group-and-Source-Specific query by enqueueing
1713 * the appropriate Current-State report for
1714 * immediate transmission.
1716 if (query_response_timer_expired
) {
1719 retval
= mld_v2_enqueue_group_record(qrq
, inm
, 0, 1,
1720 (inm
->in6m_state
== MLD_SG_QUERY_PENDING_MEMBER
),
1722 MLD_PRINTF(("%s: enqueue record = %d\n",
1724 inm
->in6m_state
= MLD_REPORTING_MEMBER
;
1725 in6m_clear_recorded(inm
);
1728 case MLD_REPORTING_MEMBER
:
1729 case MLD_LEAVING_MEMBER
:
1730 if (state_change_retransmit_timer_expired
) {
1732 * State-change retransmission timer fired.
1733 * If there are any further pending retransmissions,
1734 * set the global pending state-change flag, and
1737 if (--inm
->in6m_scrv
> 0) {
1738 inm
->in6m_sctimer
= uri_fasthz
;
1739 state_change_timers_running6
= 1;
1742 * Retransmit the previously computed state-change
1743 * report. If there are no further pending
1744 * retransmissions, the mbuf queue will be consumed.
1745 * Update T0 state to T1 as we have now sent
1748 (void) mld_v2_merge_state_changes(inm
, scq
);
1751 MLD_PRINTF(("%s: T1 -> T0 for %s/%s%d\n", __func__
,
1752 ip6_sprintf(&inm
->in6m_addr
),
1753 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
1756 * If we are leaving the group for good, make sure
1757 * we release MLD's reference to it.
1758 * This release must be deferred using a SLIST,
1759 * as we are called from a loop which traverses
1760 * the in_ifmultiaddr TAILQ.
1762 if (inm
->in6m_state
== MLD_LEAVING_MEMBER
&&
1763 inm
->in6m_scrv
== 0) {
1764 inm
->in6m_state
= MLD_NOT_MEMBER
;
1766 * A reference has already been held in
1767 * mld_final_leave() for this inm, so
1768 * no need to hold another one. We also
1769 * bumped up its request count then, so
1770 * that it stays in in6_multihead. Both
1771 * of them will be released when it is
1772 * dequeued later on.
1774 VERIFY(inm
->in6m_nrelecnt
!= 0);
1775 SLIST_INSERT_HEAD(&mli
->mli_relinmhead
,
1784 * Switch to a different version on the given interface,
1785 * as per Section 9.12.
1788 mld_set_version(struct mld_ifinfo
*mli
, const int mld_version
)
1790 int old_version_timer
;
1792 MLI_LOCK_ASSERT_HELD(mli
);
1794 MLD_PRINTF(("%s: switching to v%d on ifp %p(%s%d)\n", __func__
,
1795 mld_version
, mli
->mli_ifp
, mli
->mli_ifp
->if_name
,
1796 mli
->mli_ifp
->if_unit
));
1798 if (mld_version
== MLD_VERSION_1
) {
1800 * Compute the "Older Version Querier Present" timer as per
1803 old_version_timer
= (mli
->mli_rv
* mli
->mli_qi
) + mli
->mli_qri
;
1804 old_version_timer
*= PR_SLOWHZ
;
1805 mli
->mli_v1_timer
= old_version_timer
;
1808 if (mli
->mli_v1_timer
> 0 && mli
->mli_version
!= MLD_VERSION_1
) {
1809 mli
->mli_version
= MLD_VERSION_1
;
1810 mld_v2_cancel_link_timers(mli
);
1813 MLI_LOCK_ASSERT_HELD(mli
);
1817 * Cancel pending MLDv2 timers for the given link and all groups
1818 * joined on it; state-change, general-query, and group-query timers.
1821 mld_v2_cancel_link_timers(struct mld_ifinfo
*mli
)
1824 struct in6_multi
*inm
;
1825 struct in6_multistep step
;
1827 MLI_LOCK_ASSERT_HELD(mli
);
1829 MLD_PRINTF(("%s: cancel v2 timers on ifp %p(%s%d)\n", __func__
,
1830 mli
->mli_ifp
, mli
->mli_ifp
->if_name
, mli
->mli_ifp
->if_unit
));
1833 * Fast-track this potentially expensive operation
1834 * by checking all the global 'timer pending' flags.
1836 if (!interface_timers_running6
&&
1837 !state_change_timers_running6
&&
1838 !current_state_timers_running6
)
1841 mli
->mli_v2_timer
= 0;
1845 in6_multihead_lock_shared();
1846 IN6_FIRST_MULTI(step
, inm
);
1847 while (inm
!= NULL
) {
1849 if (inm
->in6m_ifp
!= ifp
)
1852 switch (inm
->in6m_state
) {
1853 case MLD_NOT_MEMBER
:
1854 case MLD_SILENT_MEMBER
:
1855 case MLD_IDLE_MEMBER
:
1856 case MLD_LAZY_MEMBER
:
1857 case MLD_SLEEPING_MEMBER
:
1858 case MLD_AWAKENING_MEMBER
:
1860 case MLD_LEAVING_MEMBER
:
1862 * If we are leaving the group and switching
1863 * version, we need to release the final
1864 * reference held for issuing the INCLUDE {}.
1865 * During mld_final_leave(), we bumped up both the
1866 * request and reference counts. Since we cannot
1867 * call in6_multi_detach() here, defer this task to
1868 * the timer routine.
1870 VERIFY(inm
->in6m_nrelecnt
!= 0);
1872 SLIST_INSERT_HEAD(&mli
->mli_relinmhead
, inm
,
1876 case MLD_G_QUERY_PENDING_MEMBER
:
1877 case MLD_SG_QUERY_PENDING_MEMBER
:
1878 in6m_clear_recorded(inm
);
1880 case MLD_REPORTING_MEMBER
:
1881 inm
->in6m_sctimer
= 0;
1882 inm
->in6m_timer
= 0;
1883 inm
->in6m_state
= MLD_REPORTING_MEMBER
;
1885 * Free any pending MLDv2 state-change records.
1887 IF_DRAIN(&inm
->in6m_scq
);
1892 IN6_NEXT_MULTI(step
, inm
);
1894 in6_multihead_lock_done();
1900 * Update the Older Version Querier Present timers for a link.
1901 * See Section 9.12 of RFC 3810.
1904 mld_v1_process_querier_timers(struct mld_ifinfo
*mli
)
1906 MLI_LOCK_ASSERT_HELD(mli
);
1908 if (mli
->mli_version
!= MLD_VERSION_2
&& --mli
->mli_v1_timer
== 0) {
1910 * MLDv1 Querier Present timer expired; revert to MLDv2.
1912 MLD_PRINTF(("%s: transition from v%d -> v%d on %p(%s%d)\n",
1913 __func__
, mli
->mli_version
, MLD_VERSION_2
,
1914 mli
->mli_ifp
, mli
->mli_ifp
->if_name
, mli
->mli_ifp
->if_unit
));
1915 mli
->mli_version
= MLD_VERSION_2
;
1920 * Transmit an MLDv1 report immediately.
1923 mld_v1_transmit_report(struct in6_multi
*in6m
, const int type
)
1926 struct in6_ifaddr
*ia
;
1927 struct ip6_hdr
*ip6
;
1928 struct mbuf
*mh
, *md
;
1929 struct mld_hdr
*mld
;
1932 IN6M_LOCK_ASSERT_HELD(in6m
);
1933 MLI_LOCK_ASSERT_HELD(in6m
->in6m_mli
);
1935 ifp
= in6m
->in6m_ifp
;
1936 /* ia may be NULL if link-local address is tentative. */
1937 ia
= in6ifa_ifpforlinklocal(ifp
, IN6_IFF_NOTREADY
|IN6_IFF_ANYCAST
);
1939 MGETHDR(mh
, M_DONTWAIT
, MT_HEADER
);
1942 IFA_REMREF(&ia
->ia_ifa
);
1945 MGET(md
, M_DONTWAIT
, MT_DATA
);
1949 IFA_REMREF(&ia
->ia_ifa
);
1955 * FUTURE: Consider increasing alignment by ETHER_HDR_LEN, so
1956 * that ether_output() does not need to allocate another mbuf
1957 * for the header in the most common case.
1959 MH_ALIGN(mh
, sizeof(struct ip6_hdr
));
1960 mh
->m_pkthdr
.len
= sizeof(struct ip6_hdr
) + sizeof(struct mld_hdr
);
1961 mh
->m_len
= sizeof(struct ip6_hdr
);
1963 ip6
= mtod(mh
, struct ip6_hdr
*);
1965 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
1966 ip6
->ip6_vfc
|= IPV6_VERSION
;
1967 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
1969 IFA_LOCK(&ia
->ia_ifa
);
1970 ip6
->ip6_src
= ia
? ia
->ia_addr
.sin6_addr
: in6addr_any
;
1972 IFA_UNLOCK(&ia
->ia_ifa
);
1973 IFA_REMREF(&ia
->ia_ifa
);
1976 ip6
->ip6_dst
= in6m
->in6m_addr
;
1978 md
->m_len
= sizeof(struct mld_hdr
);
1979 mld
= mtod(md
, struct mld_hdr
*);
1980 mld
->mld_type
= type
;
1983 mld
->mld_maxdelay
= 0;
1984 mld
->mld_reserved
= 0;
1985 mld
->mld_addr
= in6m
->in6m_addr
;
1986 in6_clearscope(&mld
->mld_addr
);
1987 mld
->mld_cksum
= in6_cksum(mh
, IPPROTO_ICMPV6
,
1988 sizeof(struct ip6_hdr
), sizeof(struct mld_hdr
));
1990 mh
->m_flags
|= M_MLDV1
;
1994 * Due to the fact that at this point we are possibly holding
1995 * in6_multihead_lock in shared or exclusive mode, we can't call
1996 * mld_dispatch_packet() here since that will eventually call
1997 * ip6_output(), which will try to lock in6_multihead_lock and cause
1999 * Instead we defer the work to the mld_slowtimo() thread, thus
2000 * avoiding unlocking in_multihead_lock here.
2002 if (IF_QFULL(&in6m
->in6m_mli
->mli_v1q
)) {
2003 MLD_PRINTF(("%s: v1 outbound queue full\n", __func__
));
2007 IF_ENQUEUE(&in6m
->in6m_mli
->mli_v1q
, mh
);
2013 * Process a state change from the upper layer for the given IPv6 group.
2015 * Each socket holds a reference on the in6_multi in its own ip_moptions.
2016 * The socket layer will have made the necessary updates to.the group
2017 * state, it is now up to MLD to issue a state change report if there
2018 * has been any change between T0 (when the last state-change was issued)
2021 * We use the MLDv2 state machine at group level. The MLd module
2022 * however makes the decision as to which MLD protocol version to speak.
2023 * A state change *from* INCLUDE {} always means an initial join.
2024 * A state change *to* INCLUDE {} always means a final leave.
2026 * If delay is non-zero, and the state change is an initial multicast
2027 * join, the state change report will be delayed by 'delay' ticks
2028 * in units of PR_FASTHZ if MLDv1 is active on the link; otherwise
2029 * the initial MLDv2 state change report will be delayed by whichever
2030 * is sooner, a pending state-change timer or delay itself.
2033 mld_change_state(struct in6_multi
*inm
, const int delay
)
2035 struct mld_ifinfo
*mli
;
2039 IN6M_LOCK_ASSERT_HELD(inm
);
2040 VERIFY(inm
->in6m_mli
!= NULL
);
2041 MLI_LOCK_ASSERT_NOTHELD(inm
->in6m_mli
);
2044 * Try to detect if the upper layer just asked us to change state
2045 * for an interface which has now gone away.
2047 VERIFY(inm
->in6m_ifma
!= NULL
);
2048 ifp
= inm
->in6m_ifma
->ifma_ifp
;
2050 * Sanity check that netinet6's notion of ifp is the same as net's.
2052 VERIFY(inm
->in6m_ifp
== ifp
);
2054 mli
= MLD_IFINFO(ifp
);
2055 VERIFY(mli
!= NULL
);
2058 * If we detect a state transition to or from MCAST_UNDEFINED
2059 * for this group, then we are starting or finishing an MLD
2060 * life cycle for this group.
2062 if (inm
->in6m_st
[1].iss_fmode
!= inm
->in6m_st
[0].iss_fmode
) {
2063 MLD_PRINTF(("%s: inm transition %d -> %d\n", __func__
,
2064 inm
->in6m_st
[0].iss_fmode
, inm
->in6m_st
[1].iss_fmode
));
2065 if (inm
->in6m_st
[0].iss_fmode
== MCAST_UNDEFINED
) {
2066 MLD_PRINTF(("%s: initial join\n", __func__
));
2067 error
= mld_initial_join(inm
, mli
, delay
);
2069 } else if (inm
->in6m_st
[1].iss_fmode
== MCAST_UNDEFINED
) {
2070 MLD_PRINTF(("%s: final leave\n", __func__
));
2071 mld_final_leave(inm
, mli
);
2075 MLD_PRINTF(("%s: filter set change\n", __func__
));
2078 error
= mld_handle_state_change(inm
, mli
);
2085 * Perform the initial join for an MLD group.
2087 * When joining a group:
2088 * If the group should have its MLD traffic suppressed, do nothing.
2089 * MLDv1 starts sending MLDv1 host membership reports.
2090 * MLDv2 will schedule an MLDv2 state-change report containing the
2091 * initial state of the membership.
2093 * If the delay argument is non-zero, then we must delay sending the
2094 * initial state change for delay ticks (in units of PR_FASTHZ).
2097 mld_initial_join(struct in6_multi
*inm
, struct mld_ifinfo
*mli
,
2101 struct ifqueue
*ifq
;
2102 int error
, retval
, syncstates
;
2105 IN6M_LOCK_ASSERT_HELD(inm
);
2106 MLI_LOCK_ASSERT_NOTHELD(mli
);
2108 MLD_PRINTF(("%s: initial join %s on ifp %p(%s%d)\n",
2109 __func__
, ip6_sprintf(&inm
->in6m_addr
),
2110 inm
->in6m_ifp
, inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2115 ifp
= inm
->in6m_ifp
;
2118 VERIFY(mli
->mli_ifp
== ifp
);
2121 * Groups joined on loopback or marked as 'not reported',
2122 * enter the MLD_SILENT_MEMBER state and
2123 * are never reported in any protocol exchanges.
2124 * All other groups enter the appropriate state machine
2125 * for the version in use on this link.
2126 * A link marked as MLIF_SILENT causes MLD to be completely
2127 * disabled for the link.
2129 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2130 (mli
->mli_flags
& MLIF_SILENT
) ||
2131 !mld_is_addr_reported(&inm
->in6m_addr
)) {
2132 MLD_PRINTF(("%s: not kicking state machine for silent group\n",
2134 inm
->in6m_state
= MLD_SILENT_MEMBER
;
2135 inm
->in6m_timer
= 0;
2138 * Deal with overlapping in6_multi lifecycle.
2139 * If this group was LEAVING, then make sure
2140 * we drop the reference we picked up to keep the
2141 * group around for the final INCLUDE {} enqueue.
2142 * Since we cannot call in6_multi_detach() here,
2143 * defer this task to the timer routine.
2145 if (mli
->mli_version
== MLD_VERSION_2
&&
2146 inm
->in6m_state
== MLD_LEAVING_MEMBER
) {
2147 VERIFY(inm
->in6m_nrelecnt
!= 0);
2148 SLIST_INSERT_HEAD(&mli
->mli_relinmhead
, inm
,
2152 inm
->in6m_state
= MLD_REPORTING_MEMBER
;
2154 switch (mli
->mli_version
) {
2157 * If a delay was provided, only use it if
2158 * it is greater than the delay normally
2159 * used for an MLDv1 state change report,
2160 * and delay sending the initial MLDv1 report
2161 * by not transitioning to the IDLE state.
2163 odelay
= MLD_RANDOM_DELAY(MLD_V1_MAX_RI
* PR_SLOWHZ
);
2165 inm
->in6m_timer
= max(delay
, odelay
);
2166 current_state_timers_running6
= 1;
2168 inm
->in6m_state
= MLD_IDLE_MEMBER
;
2169 error
= mld_v1_transmit_report(inm
,
2170 MLD_LISTENER_REPORT
);
2172 IN6M_LOCK_ASSERT_HELD(inm
);
2173 MLI_LOCK_ASSERT_HELD(mli
);
2176 inm
->in6m_timer
= odelay
;
2177 current_state_timers_running6
= 1;
2184 * Defer update of T0 to T1, until the first copy
2185 * of the state change has been transmitted.
2190 * Immediately enqueue a State-Change Report for
2191 * this interface, freeing any previous reports.
2192 * Don't kick the timers if there is nothing to do,
2193 * or if an error occurred.
2195 ifq
= &inm
->in6m_scq
;
2197 retval
= mld_v2_enqueue_group_record(ifq
, inm
, 1,
2198 0, 0, (mli
->mli_flags
& MLIF_USEALLOW
));
2199 MLD_PRINTF(("%s: enqueue record = %d\n",
2202 error
= retval
* -1;
2207 * Schedule transmission of pending state-change
2208 * report up to RV times for this link. The timer
2209 * will fire at the next mld_fasttimo (~200ms),
2210 * giving us an opportunity to merge the reports.
2212 * If a delay was provided to this function, only
2213 * use this delay if sooner than the existing one.
2215 VERIFY(mli
->mli_rv
> 1);
2216 inm
->in6m_scrv
= mli
->mli_rv
;
2218 if (inm
->in6m_sctimer
> 1) {
2220 min(inm
->in6m_sctimer
, delay
);
2222 inm
->in6m_sctimer
= delay
;
2224 inm
->in6m_sctimer
= 1;
2225 state_change_timers_running6
= 1;
2234 * Only update the T0 state if state change is atomic,
2235 * i.e. we don't need to wait for a timer to fire before we
2236 * can consider the state change to have been communicated.
2240 MLD_PRINTF(("%s: T1 -> T0 for %s/%s%d\n", __func__
,
2241 ip6_sprintf(&inm
->in6m_addr
),
2242 inm
->in6m_ifp
->if_name
, ifp
->if_unit
));
2249 * Issue an intermediate state change during the life-cycle.
2252 mld_handle_state_change(struct in6_multi
*inm
, struct mld_ifinfo
*mli
)
2257 IN6M_LOCK_ASSERT_HELD(inm
);
2258 MLI_LOCK_ASSERT_NOTHELD(mli
);
2260 MLD_PRINTF(("%s: state change for %s on ifp %p(%s%d)\n",
2261 __func__
, ip6_sprintf(&inm
->in6m_addr
),
2262 inm
->in6m_ifp
, inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2264 ifp
= inm
->in6m_ifp
;
2267 VERIFY(mli
->mli_ifp
== ifp
);
2269 if ((ifp
->if_flags
& IFF_LOOPBACK
) ||
2270 (mli
->mli_flags
& MLIF_SILENT
) ||
2271 !mld_is_addr_reported(&inm
->in6m_addr
) ||
2272 (mli
->mli_version
!= MLD_VERSION_2
)) {
2274 if (!mld_is_addr_reported(&inm
->in6m_addr
)) {
2275 MLD_PRINTF(("%s: not kicking state machine for silent "
2276 "group\n", __func__
));
2278 MLD_PRINTF(("%s: nothing to do\n", __func__
));
2280 MLD_PRINTF(("%s: T1 -> T0 for %s/%s%d\n", __func__
,
2281 ip6_sprintf(&inm
->in6m_addr
),
2282 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2286 IF_DRAIN(&inm
->in6m_scq
);
2288 retval
= mld_v2_enqueue_group_record(&inm
->in6m_scq
, inm
, 1, 0, 0,
2289 (mli
->mli_flags
& MLIF_USEALLOW
));
2290 MLD_PRINTF(("%s: enqueue record = %d\n", __func__
, retval
));
2296 * If record(s) were enqueued, start the state-change
2297 * report timer for this group.
2299 inm
->in6m_scrv
= mli
->mli_rv
;
2300 inm
->in6m_sctimer
= 1;
2301 state_change_timers_running6
= 1;
2308 * Perform the final leave for a multicast address.
2310 * When leaving a group:
2311 * MLDv1 sends a DONE message, if and only if we are the reporter.
2312 * MLDv2 enqueues a state-change report containing a transition
2313 * to INCLUDE {} for immediate transmission.
2316 mld_final_leave(struct in6_multi
*inm
, struct mld_ifinfo
*mli
)
2320 IN6M_LOCK_ASSERT_HELD(inm
);
2321 MLI_LOCK_ASSERT_NOTHELD(mli
);
2323 MLD_PRINTF(("%s: final leave %s on ifp %p(%s%d)\n",
2324 __func__
, ip6_sprintf(&inm
->in6m_addr
),
2325 inm
->in6m_ifp
, inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2327 switch (inm
->in6m_state
) {
2328 case MLD_NOT_MEMBER
:
2329 case MLD_SILENT_MEMBER
:
2330 case MLD_LEAVING_MEMBER
:
2331 /* Already leaving or left; do nothing. */
2332 MLD_PRINTF(("%s: not kicking state machine for silent group\n",
2335 case MLD_REPORTING_MEMBER
:
2336 case MLD_IDLE_MEMBER
:
2337 case MLD_G_QUERY_PENDING_MEMBER
:
2338 case MLD_SG_QUERY_PENDING_MEMBER
:
2340 if (mli
->mli_version
== MLD_VERSION_1
) {
2341 if (inm
->in6m_state
== MLD_G_QUERY_PENDING_MEMBER
||
2342 inm
->in6m_state
== MLD_SG_QUERY_PENDING_MEMBER
) {
2343 panic("%s: MLDv2 state reached, not MLDv2 "
2344 "mode\n", __func__
);
2347 mld_v1_transmit_report(inm
, MLD_LISTENER_DONE
);
2349 IN6M_LOCK_ASSERT_HELD(inm
);
2350 MLI_LOCK_ASSERT_HELD(mli
);
2352 inm
->in6m_state
= MLD_NOT_MEMBER
;
2353 } else if (mli
->mli_version
== MLD_VERSION_2
) {
2355 * Stop group timer and all pending reports.
2356 * Immediately enqueue a state-change report
2357 * TO_IN {} to be sent on the next fast timeout,
2358 * giving us an opportunity to merge reports.
2360 IF_DRAIN(&inm
->in6m_scq
);
2361 inm
->in6m_timer
= 0;
2362 inm
->in6m_scrv
= mli
->mli_rv
;
2363 MLD_PRINTF(("%s: Leaving %s/%s%d with %d "
2364 "pending retransmissions.\n", __func__
,
2365 ip6_sprintf(&inm
->in6m_addr
),
2366 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
,
2368 if (inm
->in6m_scrv
== 0) {
2369 inm
->in6m_state
= MLD_NOT_MEMBER
;
2370 inm
->in6m_sctimer
= 0;
2374 * Stick around in the in6_multihead list;
2375 * the final detach will be issued by
2376 * mld_v2_process_group_timers() when
2377 * the retransmit timer expires.
2379 IN6M_ADDREF_LOCKED(inm
);
2380 VERIFY(inm
->in6m_debug
& IFD_ATTACHED
);
2382 VERIFY(inm
->in6m_reqcnt
>= 1);
2383 inm
->in6m_nrelecnt
++;
2384 VERIFY(inm
->in6m_nrelecnt
!= 0);
2386 retval
= mld_v2_enqueue_group_record(
2387 &inm
->in6m_scq
, inm
, 1, 0, 0,
2388 (mli
->mli_flags
& MLIF_USEALLOW
));
2389 KASSERT(retval
!= 0,
2390 ("%s: enqueue record = %d\n", __func__
,
2393 inm
->in6m_state
= MLD_LEAVING_MEMBER
;
2394 inm
->in6m_sctimer
= 1;
2395 state_change_timers_running6
= 1;
2401 case MLD_LAZY_MEMBER
:
2402 case MLD_SLEEPING_MEMBER
:
2403 case MLD_AWAKENING_MEMBER
:
2404 /* Our reports are suppressed; do nothing. */
2410 MLD_PRINTF(("%s: T1 -> T0 for %s/%s%d\n", __func__
,
2411 ip6_sprintf(&inm
->in6m_addr
),
2412 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2413 inm
->in6m_st
[1].iss_fmode
= MCAST_UNDEFINED
;
2414 MLD_PRINTF(("%s: T1 now MCAST_UNDEFINED for %p/%s%d\n",
2415 __func__
, &inm
->in6m_addr
, inm
->in6m_ifp
->if_name
,
2416 inm
->in6m_ifp
->if_unit
));
2421 * Enqueue an MLDv2 group record to the given output queue.
2423 * If is_state_change is zero, a current-state record is appended.
2424 * If is_state_change is non-zero, a state-change report is appended.
2426 * If is_group_query is non-zero, an mbuf packet chain is allocated.
2427 * If is_group_query is zero, and if there is a packet with free space
2428 * at the tail of the queue, it will be appended to providing there
2429 * is enough free space.
2430 * Otherwise a new mbuf packet chain is allocated.
2432 * If is_source_query is non-zero, each source is checked to see if
2433 * it was recorded for a Group-Source query, and will be omitted if
2434 * it is not both in-mode and recorded.
2436 * If use_block_allow is non-zero, state change reports for initial join
2437 * and final leave, on an inclusive mode group with a source list, will be
2438 * rewritten to use the ALLOW_NEW and BLOCK_OLD record types, respectively.
2440 * The function will attempt to allocate leading space in the packet
2441 * for the IPv6+ICMP headers to be prepended without fragmenting the chain.
2443 * If successful the size of all data appended to the queue is returned,
2444 * otherwise an error code less than zero is returned, or zero if
2445 * no record(s) were appended.
2448 mld_v2_enqueue_group_record(struct ifqueue
*ifq
, struct in6_multi
*inm
,
2449 const int is_state_change
, const int is_group_query
,
2450 const int is_source_query
, const int use_block_allow
)
2452 struct mldv2_record mr
;
2453 struct mldv2_record
*pmr
;
2455 struct ip6_msource
*ims
, *nims
;
2456 struct mbuf
*m0
, *m
, *md
;
2457 int error
, is_filter_list_change
;
2458 int minrec0len
, m0srcs
, msrcs
, nbytes
, off
;
2459 int record_has_sources
;
2464 IN6M_LOCK_ASSERT_HELD(inm
);
2465 MLI_LOCK_ASSERT_HELD(inm
->in6m_mli
);
2468 ifp
= inm
->in6m_ifp
;
2469 is_filter_list_change
= 0;
2476 record_has_sources
= 1;
2478 type
= MLD_DO_NOTHING
;
2479 mode
= inm
->in6m_st
[1].iss_fmode
;
2482 * If we did not transition out of ASM mode during t0->t1,
2483 * and there are no source nodes to process, we can skip
2484 * the generation of source records.
2486 if (inm
->in6m_st
[0].iss_asm
> 0 && inm
->in6m_st
[1].iss_asm
> 0 &&
2487 inm
->in6m_nsrc
== 0)
2488 record_has_sources
= 0;
2490 if (is_state_change
) {
2492 * Queue a state change record.
2493 * If the mode did not change, and there are non-ASM
2494 * listeners or source filters present,
2495 * we potentially need to issue two records for the group.
2496 * If there are ASM listeners, and there was no filter
2497 * mode transition of any kind, do nothing.
2499 * If we are transitioning to MCAST_UNDEFINED, we need
2500 * not send any sources. A transition to/from this state is
2501 * considered inclusive with some special treatment.
2503 * If we are rewriting initial joins/leaves to use
2504 * ALLOW/BLOCK, and the group's membership is inclusive,
2505 * we need to send sources in all cases.
2507 if (mode
!= inm
->in6m_st
[0].iss_fmode
) {
2508 if (mode
== MCAST_EXCLUDE
) {
2509 MLD_PRINTF(("%s: change to EXCLUDE\n",
2511 type
= MLD_CHANGE_TO_EXCLUDE_MODE
;
2513 MLD_PRINTF(("%s: change to INCLUDE\n",
2515 if (use_block_allow
) {
2518 * Here we're interested in state
2519 * edges either direction between
2520 * MCAST_UNDEFINED and MCAST_INCLUDE.
2521 * Perhaps we should just check
2522 * the group state, rather than
2525 if (mode
== MCAST_UNDEFINED
) {
2526 type
= MLD_BLOCK_OLD_SOURCES
;
2528 type
= MLD_ALLOW_NEW_SOURCES
;
2531 type
= MLD_CHANGE_TO_INCLUDE_MODE
;
2532 if (mode
== MCAST_UNDEFINED
)
2533 record_has_sources
= 0;
2537 if (record_has_sources
) {
2538 is_filter_list_change
= 1;
2540 type
= MLD_DO_NOTHING
;
2545 * Queue a current state record.
2547 if (mode
== MCAST_EXCLUDE
) {
2548 type
= MLD_MODE_IS_EXCLUDE
;
2549 } else if (mode
== MCAST_INCLUDE
) {
2550 type
= MLD_MODE_IS_INCLUDE
;
2551 VERIFY(inm
->in6m_st
[1].iss_asm
== 0);
2556 * Generate the filter list changes using a separate function.
2558 if (is_filter_list_change
)
2559 return (mld_v2_enqueue_filter_change(ifq
, inm
));
2561 if (type
== MLD_DO_NOTHING
) {
2562 MLD_PRINTF(("%s: nothing to do for %s/%s%d\n",
2563 __func__
, ip6_sprintf(&inm
->in6m_addr
),
2564 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2569 * If any sources are present, we must be able to fit at least
2570 * one in the trailing space of the tail packet's mbuf,
2573 minrec0len
= sizeof(struct mldv2_record
);
2574 if (record_has_sources
)
2575 minrec0len
+= sizeof(struct in6_addr
);
2576 MLD_PRINTF(("%s: queueing %s for %s/%s%d\n", __func__
,
2577 mld_rec_type_to_str(type
),
2578 ip6_sprintf(&inm
->in6m_addr
),
2579 inm
->in6m_ifp
->if_name
, inm
->in6m_ifp
->if_unit
));
2582 * Check if we have a packet in the tail of the queue for this
2583 * group into which the first group record for this group will fit.
2584 * Otherwise allocate a new packet.
2585 * Always allocate leading space for IP6+RA+ICMPV6+REPORT.
2586 * Note: Group records for G/GSR query responses MUST be sent
2587 * in their own packet.
2590 if (!is_group_query
&&
2592 (m0
->m_pkthdr
.vt_nrecs
+ 1 <= MLD_V2_REPORT_MAXRECS
) &&
2593 (m0
->m_pkthdr
.len
+ minrec0len
) <
2594 (ifp
->if_mtu
- MLD_MTUSPACE
)) {
2595 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
2596 sizeof(struct mldv2_record
)) /
2597 sizeof(struct in6_addr
);
2599 MLD_PRINTF(("%s: use existing packet\n", __func__
));
2601 if (IF_QFULL(ifq
)) {
2602 MLD_PRINTF(("%s: outbound queue full\n", __func__
));
2606 m0srcs
= (ifp
->if_mtu
- MLD_MTUSPACE
-
2607 sizeof(struct mldv2_record
)) / sizeof(struct in6_addr
);
2608 if (!is_state_change
&& !is_group_query
)
2609 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
2611 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
2615 MLD_PRINTF(("%s: allocated first packet\n", __func__
));
2619 * Append group record.
2620 * If we have sources, we don't know how many yet.
2625 mr
.mr_addr
= inm
->in6m_addr
;
2626 in6_clearscope(&mr
.mr_addr
);
2627 if (!m_append(m
, sizeof(struct mldv2_record
), (void *)&mr
)) {
2630 MLD_PRINTF(("%s: m_append() failed.\n", __func__
));
2633 nbytes
+= sizeof(struct mldv2_record
);
2636 * Append as many sources as will fit in the first packet.
2637 * If we are appending to a new packet, the chain allocation
2638 * may potentially use clusters; use m_getptr() in this case.
2639 * If we are appending to an existing packet, we need to obtain
2640 * a pointer to the group record after m_append(), in case a new
2641 * mbuf was allocated.
2643 * Only append sources which are in-mode at t1. If we are
2644 * transitioning to MCAST_UNDEFINED state on the group, and
2645 * use_block_allow is zero, do not include source entries.
2646 * Otherwise, we need to include this source in the report.
2648 * Only report recorded sources in our filter set when responding
2649 * to a group-source query.
2651 if (record_has_sources
) {
2654 pmr
= (struct mldv2_record
*)(mtod(md
, uint8_t *) +
2655 md
->m_len
- nbytes
);
2657 md
= m_getptr(m
, 0, &off
);
2658 pmr
= (struct mldv2_record
*)(mtod(md
, uint8_t *) +
2662 RB_FOREACH_SAFE(ims
, ip6_msource_tree
, &inm
->in6m_srcs
,
2664 MLD_PRINTF(("%s: visit node %s\n", __func__
,
2665 ip6_sprintf(&ims
->im6s_addr
)));
2666 now
= im6s_get_mode(inm
, ims
, 1);
2667 MLD_PRINTF(("%s: node is %d\n", __func__
, now
));
2668 if ((now
!= mode
) ||
2670 (!use_block_allow
&& mode
== MCAST_UNDEFINED
))) {
2671 MLD_PRINTF(("%s: skip node\n", __func__
));
2674 if (is_source_query
&& ims
->im6s_stp
== 0) {
2675 MLD_PRINTF(("%s: skip unrecorded node\n",
2679 MLD_PRINTF(("%s: append node\n", __func__
));
2680 if (!m_append(m
, sizeof(struct in6_addr
),
2681 (void *)&ims
->im6s_addr
)) {
2684 MLD_PRINTF(("%s: m_append() failed.\n",
2688 nbytes
+= sizeof(struct in6_addr
);
2690 if (msrcs
== m0srcs
)
2693 MLD_PRINTF(("%s: msrcs is %d this packet\n", __func__
,
2695 pmr
->mr_numsrc
= htons(msrcs
);
2696 nbytes
+= (msrcs
* sizeof(struct in6_addr
));
2699 if (is_source_query
&& msrcs
== 0) {
2700 MLD_PRINTF(("%s: no recorded sources to report\n", __func__
));
2707 * We are good to go with first packet.
2710 MLD_PRINTF(("%s: enqueueing first packet\n", __func__
));
2711 m
->m_pkthdr
.vt_nrecs
= 1;
2712 m
->m_pkthdr
.rcvif
= ifp
;
2715 m
->m_pkthdr
.vt_nrecs
++;
2718 * No further work needed if no source list in packet(s).
2720 if (!record_has_sources
)
2724 * Whilst sources remain to be announced, we need to allocate
2725 * a new packet and fill out as many sources as will fit.
2726 * Always try for a cluster first.
2728 while (nims
!= NULL
) {
2729 if (IF_QFULL(ifq
)) {
2730 MLD_PRINTF(("%s: outbound queue full\n", __func__
));
2733 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
2735 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
2738 md
= m_getptr(m
, 0, &off
);
2739 pmr
= (struct mldv2_record
*)(mtod(md
, uint8_t *) + off
);
2740 MLD_PRINTF(("%s: allocated next packet\n", __func__
));
2742 if (!m_append(m
, sizeof(struct mldv2_record
), (void *)&mr
)) {
2745 MLD_PRINTF(("%s: m_append() failed.\n", __func__
));
2748 m
->m_pkthdr
.vt_nrecs
= 1;
2749 nbytes
+= sizeof(struct mldv2_record
);
2751 m0srcs
= (ifp
->if_mtu
- MLD_MTUSPACE
-
2752 sizeof(struct mldv2_record
)) / sizeof(struct in6_addr
);
2755 RB_FOREACH_FROM(ims
, ip6_msource_tree
, nims
) {
2756 MLD_PRINTF(("%s: visit node %s\n",
2757 __func__
, ip6_sprintf(&ims
->im6s_addr
)));
2758 now
= im6s_get_mode(inm
, ims
, 1);
2759 if ((now
!= mode
) ||
2761 (!use_block_allow
&& mode
== MCAST_UNDEFINED
))) {
2762 MLD_PRINTF(("%s: skip node\n", __func__
));
2765 if (is_source_query
&& ims
->im6s_stp
== 0) {
2766 MLD_PRINTF(("%s: skip unrecorded node\n",
2770 MLD_PRINTF(("%s: append node\n", __func__
));
2771 if (!m_append(m
, sizeof(struct in6_addr
),
2772 (void *)&ims
->im6s_addr
)) {
2775 MLD_PRINTF(("%s: m_append() failed.\n",
2780 if (msrcs
== m0srcs
)
2783 pmr
->mr_numsrc
= htons(msrcs
);
2784 nbytes
+= (msrcs
* sizeof(struct in6_addr
));
2786 MLD_PRINTF(("%s: enqueueing next packet\n", __func__
));
2787 m
->m_pkthdr
.rcvif
= ifp
;
2795 * Type used to mark record pass completion.
2796 * We exploit the fact we can cast to this easily from the
2797 * current filter modes on each ip_msource node.
2800 REC_NONE
= 0x00, /* MCAST_UNDEFINED */
2801 REC_ALLOW
= 0x01, /* MCAST_INCLUDE */
2802 REC_BLOCK
= 0x02, /* MCAST_EXCLUDE */
2803 REC_FULL
= REC_ALLOW
| REC_BLOCK
2807 * Enqueue an MLDv2 filter list change to the given output queue.
2809 * Source list filter state is held in an RB-tree. When the filter list
2810 * for a group is changed without changing its mode, we need to compute
2811 * the deltas between T0 and T1 for each source in the filter set,
2812 * and enqueue the appropriate ALLOW_NEW/BLOCK_OLD records.
2814 * As we may potentially queue two record types, and the entire R-B tree
2815 * needs to be walked at once, we break this out into its own function
2816 * so we can generate a tightly packed queue of packets.
2818 * XXX This could be written to only use one tree walk, although that makes
2819 * serializing into the mbuf chains a bit harder. For now we do two walks
2820 * which makes things easier on us, and it may or may not be harder on
2823 * If successful the size of all data appended to the queue is returned,
2824 * otherwise an error code less than zero is returned, or zero if
2825 * no record(s) were appended.
2828 mld_v2_enqueue_filter_change(struct ifqueue
*ifq
, struct in6_multi
*inm
)
2830 static const int MINRECLEN
=
2831 sizeof(struct mldv2_record
) + sizeof(struct in6_addr
);
2833 struct mldv2_record mr
;
2834 struct mldv2_record
*pmr
;
2835 struct ip6_msource
*ims
, *nims
;
2836 struct mbuf
*m
, *m0
, *md
;
2837 int m0srcs
, nbytes
, npbytes
, off
, rsrcs
, schanged
;
2839 uint8_t mode
, now
, then
;
2840 rectype_t crt
, drt
, nrt
;
2842 IN6M_LOCK_ASSERT_HELD(inm
);
2844 if (inm
->in6m_nsrc
== 0 ||
2845 (inm
->in6m_st
[0].iss_asm
> 0 && inm
->in6m_st
[1].iss_asm
> 0))
2848 ifp
= inm
->in6m_ifp
; /* interface */
2849 mode
= inm
->in6m_st
[1].iss_fmode
; /* filter mode at t1 */
2850 crt
= REC_NONE
; /* current group record type */
2851 drt
= REC_NONE
; /* mask of completed group record types */
2852 nrt
= REC_NONE
; /* record type for current node */
2853 m0srcs
= 0; /* # source which will fit in current mbuf chain */
2854 npbytes
= 0; /* # of bytes appended this packet */
2855 nbytes
= 0; /* # of bytes appended to group's state-change queue */
2856 rsrcs
= 0; /* # sources encoded in current record */
2857 schanged
= 0; /* # nodes encoded in overall filter change */
2858 nallow
= 0; /* # of source entries in ALLOW_NEW */
2859 nblock
= 0; /* # of source entries in BLOCK_OLD */
2860 nims
= NULL
; /* next tree node pointer */
2863 * For each possible filter record mode.
2864 * The first kind of source we encounter tells us which
2865 * is the first kind of record we start appending.
2866 * If a node transitioned to UNDEFINED at t1, its mode is treated
2867 * as the inverse of the group's filter mode.
2869 while (drt
!= REC_FULL
) {
2873 (m0
->m_pkthdr
.vt_nrecs
+ 1 <=
2874 MLD_V2_REPORT_MAXRECS
) &&
2875 (m0
->m_pkthdr
.len
+ MINRECLEN
) <
2876 (ifp
->if_mtu
- MLD_MTUSPACE
)) {
2878 m0srcs
= (ifp
->if_mtu
- m0
->m_pkthdr
.len
-
2879 sizeof(struct mldv2_record
)) /
2880 sizeof(struct in6_addr
);
2881 MLD_PRINTF(("%s: use previous packet\n",
2884 m
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
2886 m
= m_gethdr(M_DONTWAIT
, MT_DATA
);
2888 MLD_PRINTF(("%s: m_get*() failed\n",
2892 m
->m_pkthdr
.vt_nrecs
= 0;
2893 m0srcs
= (ifp
->if_mtu
- MLD_MTUSPACE
-
2894 sizeof(struct mldv2_record
)) /
2895 sizeof(struct in6_addr
);
2897 MLD_PRINTF(("%s: allocated new packet\n",
2901 * Append the MLD group record header to the
2902 * current packet's data area.
2903 * Recalculate pointer to free space for next
2904 * group record, in case m_append() allocated
2905 * a new mbuf or cluster.
2907 memset(&mr
, 0, sizeof(mr
));
2908 mr
.mr_addr
= inm
->in6m_addr
;
2909 in6_clearscope(&mr
.mr_addr
);
2910 if (!m_append(m
, sizeof(mr
), (void *)&mr
)) {
2913 MLD_PRINTF(("%s: m_append() failed\n",
2917 npbytes
+= sizeof(struct mldv2_record
);
2919 /* new packet; offset in chain */
2920 md
= m_getptr(m
, npbytes
-
2921 sizeof(struct mldv2_record
), &off
);
2922 pmr
= (struct mldv2_record
*)(mtod(md
,
2925 /* current packet; offset from last append */
2927 pmr
= (struct mldv2_record
*)(mtod(md
,
2928 uint8_t *) + md
->m_len
-
2929 sizeof(struct mldv2_record
));
2932 * Begin walking the tree for this record type
2933 * pass, or continue from where we left off
2934 * previously if we had to allocate a new packet.
2935 * Only report deltas in-mode at t1.
2936 * We need not report included sources as allowed
2937 * if we are in inclusive mode on the group,
2938 * however the converse is not true.
2942 nims
= RB_MIN(ip6_msource_tree
,
2945 RB_FOREACH_FROM(ims
, ip6_msource_tree
, nims
) {
2946 MLD_PRINTF(("%s: visit node %s\n", __func__
,
2947 ip6_sprintf(&ims
->im6s_addr
)));
2948 now
= im6s_get_mode(inm
, ims
, 1);
2949 then
= im6s_get_mode(inm
, ims
, 0);
2950 MLD_PRINTF(("%s: mode: t0 %d, t1 %d\n",
2951 __func__
, then
, now
));
2953 MLD_PRINTF(("%s: skip unchanged\n",
2957 if (mode
== MCAST_EXCLUDE
&&
2958 now
== MCAST_INCLUDE
) {
2959 MLD_PRINTF(("%s: skip IN src on EX "
2960 "group\n", __func__
));
2963 nrt
= (rectype_t
)now
;
2964 if (nrt
== REC_NONE
)
2965 nrt
= (rectype_t
)(~mode
& REC_FULL
);
2966 if (schanged
++ == 0) {
2968 } else if (crt
!= nrt
)
2970 if (!m_append(m
, sizeof(struct in6_addr
),
2971 (void *)&ims
->im6s_addr
)) {
2974 MLD_PRINTF(("%s: m_append() failed\n",
2978 nallow
+= !!(crt
== REC_ALLOW
);
2979 nblock
+= !!(crt
== REC_BLOCK
);
2980 if (++rsrcs
== m0srcs
)
2984 * If we did not append any tree nodes on this
2985 * pass, back out of allocations.
2988 npbytes
-= sizeof(struct mldv2_record
);
2990 MLD_PRINTF(("%s: m_free(m)\n",
2994 MLD_PRINTF(("%s: m_adj(m, -mr)\n",
2996 m_adj(m
, -((int)sizeof(
2997 struct mldv2_record
)));
3001 npbytes
+= (rsrcs
* sizeof(struct in6_addr
));
3002 if (crt
== REC_ALLOW
)
3003 pmr
->mr_type
= MLD_ALLOW_NEW_SOURCES
;
3004 else if (crt
== REC_BLOCK
)
3005 pmr
->mr_type
= MLD_BLOCK_OLD_SOURCES
;
3006 pmr
->mr_numsrc
= htons(rsrcs
);
3008 * Count the new group record, and enqueue this
3009 * packet if it wasn't already queued.
3011 m
->m_pkthdr
.vt_nrecs
++;
3012 m
->m_pkthdr
.rcvif
= ifp
;
3016 } while (nims
!= NULL
);
3018 crt
= (~crt
& REC_FULL
);
3021 MLD_PRINTF(("%s: queued %d ALLOW_NEW, %d BLOCK_OLD\n", __func__
,
3028 mld_v2_merge_state_changes(struct in6_multi
*inm
, struct ifqueue
*ifscq
)
3031 struct mbuf
*m
; /* pending state-change */
3032 struct mbuf
*m0
; /* copy of pending state-change */
3033 struct mbuf
*mt
; /* last state-change in packet */
3035 int docopy
, domerge
;
3038 IN6M_LOCK_ASSERT_HELD(inm
);
3045 * If there are further pending retransmissions, make a writable
3046 * copy of each queued state-change message before merging.
3048 if (inm
->in6m_scrv
> 0)
3051 gq
= &inm
->in6m_scq
;
3053 if (gq
->ifq_head
== NULL
) {
3054 MLD_PRINTF(("%s: WARNING: queue for inm %p is empty\n",
3060 * Use IF_REMQUEUE() instead of IF_DEQUEUE() below, since the
3061 * packet might not always be at the head of the ifqueue.
3066 * Only merge the report into the current packet if
3067 * there is sufficient space to do so; an MLDv2 report
3068 * packet may only contain 65,535 group records.
3069 * Always use a simple mbuf chain concatentation to do this,
3070 * as large state changes for single groups may have
3071 * allocated clusters.
3074 mt
= ifscq
->ifq_tail
;
3076 recslen
= m_length(m
);
3078 if ((mt
->m_pkthdr
.vt_nrecs
+
3079 m
->m_pkthdr
.vt_nrecs
<=
3080 MLD_V2_REPORT_MAXRECS
) &&
3081 (mt
->m_pkthdr
.len
+ recslen
<=
3082 (inm
->in6m_ifp
->if_mtu
- MLD_MTUSPACE
)))
3086 if (!domerge
&& IF_QFULL(gq
)) {
3087 MLD_PRINTF(("%s: outbound queue full, skipping whole "
3088 "packet %p\n", __func__
, m
));
3099 MLD_PRINTF(("%s: dequeueing %p\n", __func__
, m
));
3105 MLD_PRINTF(("%s: copying %p\n", __func__
, m
));
3106 m0
= m_dup(m
, M_NOWAIT
);
3109 m0
->m_nextpkt
= NULL
;
3114 MLD_PRINTF(("%s: queueing %p to ifscq %p)\n",
3115 __func__
, m0
, ifscq
));
3116 m0
->m_pkthdr
.rcvif
= inm
->in6m_ifp
;
3117 IF_ENQUEUE(ifscq
, m0
);
3119 struct mbuf
*mtl
; /* last mbuf of packet mt */
3121 MLD_PRINTF(("%s: merging %p with ifscq tail %p)\n",
3125 m0
->m_flags
&= ~M_PKTHDR
;
3126 mt
->m_pkthdr
.len
+= recslen
;
3127 mt
->m_pkthdr
.vt_nrecs
+=
3128 m0
->m_pkthdr
.vt_nrecs
;
3138 * Respond to a pending MLDv2 General Query.
3141 mld_v2_dispatch_general_query(struct mld_ifinfo
*mli
)
3144 struct in6_multi
*inm
;
3145 struct in6_multistep step
;
3148 MLI_LOCK_ASSERT_HELD(mli
);
3150 VERIFY(mli
->mli_version
== MLD_VERSION_2
);
3155 in6_multihead_lock_shared();
3156 IN6_FIRST_MULTI(step
, inm
);
3157 while (inm
!= NULL
) {
3159 if (inm
->in6m_ifp
!= ifp
)
3162 switch (inm
->in6m_state
) {
3163 case MLD_NOT_MEMBER
:
3164 case MLD_SILENT_MEMBER
:
3166 case MLD_REPORTING_MEMBER
:
3167 case MLD_IDLE_MEMBER
:
3168 case MLD_LAZY_MEMBER
:
3169 case MLD_SLEEPING_MEMBER
:
3170 case MLD_AWAKENING_MEMBER
:
3171 inm
->in6m_state
= MLD_REPORTING_MEMBER
;
3173 retval
= mld_v2_enqueue_group_record(&mli
->mli_gq
,
3176 MLD_PRINTF(("%s: enqueue record = %d\n",
3179 case MLD_G_QUERY_PENDING_MEMBER
:
3180 case MLD_SG_QUERY_PENDING_MEMBER
:
3181 case MLD_LEAVING_MEMBER
:
3186 IN6_NEXT_MULTI(step
, inm
);
3188 in6_multihead_lock_done();
3191 mld_dispatch_queue(mli
, &mli
->mli_gq
, MLD_MAX_RESPONSE_BURST
);
3192 MLI_LOCK_ASSERT_HELD(mli
);
3195 * Slew transmission of bursts over 500ms intervals.
3197 if (mli
->mli_gq
.ifq_head
!= NULL
) {
3198 mli
->mli_v2_timer
= 1 + MLD_RANDOM_DELAY(
3199 MLD_RESPONSE_BURST_INTERVAL
);
3200 interface_timers_running6
= 1;
3205 * Transmit the next pending message in the output queue.
3207 * Must not be called with in6m_lockm or mli_lock held.
3210 mld_dispatch_packet(struct mbuf
*m
)
3212 struct ip6_moptions
*im6o
;
3214 struct ifnet
*oifp
= NULL
;
3217 struct ip6_hdr
*ip6
;
3218 struct mld_hdr
*mld
;
3223 MLD_PRINTF(("%s: transmit %p\n", __func__
, m
));
3226 * Check if the ifnet is still attached.
3228 ifp
= m
->m_pkthdr
.rcvif
;
3229 if (ifp
== NULL
|| !ifnet_is_attached(ifp
, 0)) {
3230 MLD_PRINTF(("%s: dropped %p as ifindex %u went away.\n",
3231 __func__
, m
, (u_int
)if_index
));
3233 ip6stat
.ip6s_noroute
++;
3237 im6o
= ip6_allocmoptions(M_WAITOK
);
3243 im6o
->im6o_multicast_hlim
= 1;
3245 im6o
->im6o_multicast_loop
= (ip6_mrouter
!= NULL
);
3247 im6o
->im6o_multicast_loop
= 0;
3249 im6o
->im6o_multicast_ifp
= ifp
;
3251 if (m
->m_flags
& M_MLDV1
) {
3254 m0
= mld_v2_encap_report(ifp
, m
);
3256 MLD_PRINTF(("%s: dropped %p\n", __func__
, m
));
3258 * mld_v2_encap_report() has already freed our mbuf.
3261 ip6stat
.ip6s_odropped
++;
3266 m
->m_flags
&= ~(M_PROTOFLAGS
);
3267 m0
->m_pkthdr
.rcvif
= lo_ifp
;
3269 ip6
= mtod(m0
, struct ip6_hdr
*);
3271 (void) in6_setscope(&ip6
->ip6_dst
, ifp
, NULL
); /* XXX LOR */
3274 * XXX XXX Break some KPI rules to prevent an LOR which would
3275 * occur if we called in6_setscope() at transmission.
3276 * See comments at top of file.
3278 MLD_EMBEDSCOPE(&ip6
->ip6_dst
, ifp
->if_index
);
3282 * Retrieve the ICMPv6 type before handoff to ip6_output(),
3283 * so we can bump the stats.
3285 md
= m_getptr(m0
, sizeof(struct ip6_hdr
), &off
);
3286 mld
= (struct mld_hdr
*)(mtod(md
, uint8_t *) + off
);
3287 type
= mld
->mld_type
;
3289 error
= ip6_output(m0
, &mld_po
, NULL
, IPV6_UNSPECSRC
, im6o
,
3295 MLD_PRINTF(("%s: ip6_output(%p) = %d\n", __func__
, m0
, error
));
3297 ifnet_release(oifp
);
3301 icmp6stat
.icp6s_outhist
[type
]++;
3303 icmp6_ifstat_inc(oifp
, ifs6_out_msg
);
3305 case MLD_LISTENER_REPORT
:
3306 case MLDV2_LISTENER_REPORT
:
3307 icmp6_ifstat_inc(oifp
, ifs6_out_mldreport
);
3309 case MLD_LISTENER_DONE
:
3310 icmp6_ifstat_inc(oifp
, ifs6_out_mlddone
);
3313 ifnet_release(oifp
);
3318 * Encapsulate an MLDv2 report.
3320 * KAME IPv6 requires that hop-by-hop options be passed separately,
3321 * and that the IPv6 header be prepended in a separate mbuf.
3323 * Returns a pointer to the new mbuf chain head, or NULL if the
3324 * allocation failed.
3326 static struct mbuf
*
3327 mld_v2_encap_report(struct ifnet
*ifp
, struct mbuf
*m
)
3330 struct mldv2_report
*mld
;
3331 struct ip6_hdr
*ip6
;
3332 struct in6_ifaddr
*ia
;
3335 VERIFY(m
->m_flags
& M_PKTHDR
);
3338 * RFC3590: OK to send as :: or tentative during DAD.
3340 ia
= in6ifa_ifpforlinklocal(ifp
, IN6_IFF_NOTREADY
|IN6_IFF_ANYCAST
);
3342 MLD_PRINTF(("%s: warning: ia is NULL\n", __func__
));
3344 MGETHDR(mh
, M_DONTWAIT
, MT_HEADER
);
3347 IFA_REMREF(&ia
->ia_ifa
);
3351 MH_ALIGN(mh
, sizeof(struct ip6_hdr
) + sizeof(struct mldv2_report
));
3353 mldreclen
= m_length(m
);
3354 MLD_PRINTF(("%s: mldreclen is %d\n", __func__
, mldreclen
));
3356 mh
->m_len
= sizeof(struct ip6_hdr
) + sizeof(struct mldv2_report
);
3357 mh
->m_pkthdr
.len
= sizeof(struct ip6_hdr
) +
3358 sizeof(struct mldv2_report
) + mldreclen
;
3360 ip6
= mtod(mh
, struct ip6_hdr
*);
3362 ip6
->ip6_vfc
&= ~IPV6_VERSION_MASK
;
3363 ip6
->ip6_vfc
|= IPV6_VERSION
;
3364 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
3366 IFA_LOCK(&ia
->ia_ifa
);
3367 ip6
->ip6_src
= ia
? ia
->ia_addr
.sin6_addr
: in6addr_any
;
3369 IFA_UNLOCK(&ia
->ia_ifa
);
3370 IFA_REMREF(&ia
->ia_ifa
);
3373 ip6
->ip6_dst
= in6addr_linklocal_allv2routers
;
3374 /* scope ID will be set in netisr */
3376 mld
= (struct mldv2_report
*)(ip6
+ 1);
3377 mld
->mld_type
= MLDV2_LISTENER_REPORT
;
3380 mld
->mld_v2_reserved
= 0;
3381 mld
->mld_v2_numrecs
= htons(m
->m_pkthdr
.vt_nrecs
);
3382 m
->m_pkthdr
.vt_nrecs
= 0;
3383 m
->m_flags
&= ~M_PKTHDR
;
3386 mld
->mld_cksum
= in6_cksum(mh
, IPPROTO_ICMPV6
,
3387 sizeof(struct ip6_hdr
), sizeof(struct mldv2_report
) + mldreclen
);
3393 mld_rec_type_to_str(const int type
)
3396 case MLD_CHANGE_TO_EXCLUDE_MODE
:
3399 case MLD_CHANGE_TO_INCLUDE_MODE
:
3402 case MLD_MODE_IS_EXCLUDE
:
3405 case MLD_MODE_IS_INCLUDE
:
3408 case MLD_ALLOW_NEW_SOURCES
:
3411 case MLD_BLOCK_OLD_SOURCES
:
3425 MLD_PRINTF(("%s: initializing\n", __func__
));
3427 /* Setup lock group and attribute for mld6_mtx */
3428 mld_mtx_grp_attr
= lck_grp_attr_alloc_init();
3429 mld_mtx_grp
= lck_grp_alloc_init("mld_mtx\n", mld_mtx_grp_attr
);
3430 mld_mtx_attr
= lck_attr_alloc_init();
3431 lck_mtx_init(&mld_mtx
, mld_mtx_grp
, mld_mtx_attr
);
3433 ip6_initpktopts(&mld_po
);
3434 mld_po
.ip6po_hlim
= 1;
3435 mld_po
.ip6po_hbh
= &mld_ra
.hbh
;
3436 mld_po
.ip6po_prefer_tempaddr
= IP6PO_TEMPADDR_NOTPREFER
;
3437 mld_po
.ip6po_flags
= IP6PO_DONTFRAG
;
3438 LIST_INIT(&mli_head
);
3440 mli_size
= sizeof (struct mld_ifinfo
);
3441 mli_zone
= zinit(mli_size
, MLI_ZONE_MAX
* mli_size
,
3443 if (mli_zone
== NULL
) {
3444 panic("%s: failed allocating %s", __func__
, MLI_ZONE_NAME
);
3447 zone_change(mli_zone
, Z_EXPAND
, TRUE
);
3448 zone_change(mli_zone
, Z_CALLERACCT
, FALSE
);