1 /*
2 * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*-
29 * Copyright (c) 2009 Bruce Simpson.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
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
41 * permission.
42 *
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
53 * SUCH DAMAGE.
54 */
55
56 /*
57 * Copyright (c) 1988 Stephen Deering.
58 * Copyright (c) 1992, 1993
59 * The Regents of the University of California. All rights reserved.
60 *
61 * This code is derived from software contributed to Berkeley by
62 * Stephen Deering of Stanford University.
63 *
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions
66 * are met:
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.
79 *
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
90 * SUCH DAMAGE.
91 *
92 * @(#)igmp.c 8.1 (Berkeley) 7/19/93
93 */
94 /*
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,
98 * Version 2.0.
99 */
100
101 #include <sys/cdefs.h>
102
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>
112
113 #include <dev/random/randomdev.h>
114
115 #include <kern/zalloc.h>
116
117 #include <net/if.h>
118 #include <net/route.h>
119
120 #include <netinet/in.h>
121 #include <netinet/in_var.h>
122 #include <netinet6/in6_var.h>
123 #include <netinet/ip6.h>
124 #include <netinet6/ip6_var.h>
125 #include <netinet6/scope6_var.h>
126 #include <netinet/icmp6.h>
127 #include <netinet6/mld6.h>
128 #include <netinet6/mld6_var.h>
129
130 /* Lock group and attribute for mld_mtx */
131 static LCK_ATTR_DECLARE(mld_mtx_attr, 0, 0);
132 static LCK_GRP_DECLARE(mld_mtx_grp, "mld_mtx");
133
134 /*
135 * Locking and reference counting:
136 *
137 * mld_mtx mainly protects mli_head. In cases where both mld_mtx and
138 * in6_multihead_lock must be held, the former must be acquired first in order
139 * to maintain lock ordering. It is not a requirement that mld_mtx be
140 * acquired first before in6_multihead_lock, but in case both must be acquired
141 * in succession, the correct lock ordering must be followed.
142 *
143 * Instead of walking the if_multiaddrs list at the interface and returning
144 * the ifma_protospec value of a matching entry, we search the global list
145 * of in6_multi records and find it that way; this is done with in6_multihead
146 * lock held. Doing so avoids the race condition issues that many other BSDs
147 * suffer from (therefore in our implementation, ifma_protospec will never be
148 * NULL for as long as the in6_multi is valid.)
149 *
150 * The above creates a requirement for the in6_multi to stay in in6_multihead
151 * list even after the final MLD leave (in MLDv2 mode) until no longer needs
152 * be retransmitted (this is not required for MLDv1.) In order to handle
153 * this, the request and reference counts of the in6_multi are bumped up when
154 * the state changes to MLD_LEAVING_MEMBER, and later dropped in the timeout
155 * handler. Each in6_multi holds a reference to the underlying mld_ifinfo.
156 *
157 * Thus, the permitted lock order is:
158 *
159 * mld_mtx, in6_multihead_lock, inm6_lock, mli_lock
160 *
161 * Any may be taken independently, but if any are held at the same time,
162 * the above lock order must be followed.
163 */
164 static LCK_MTX_DECLARE_ATTR(mld_mtx, &mld_mtx_grp, &mld_mtx_attr);
165
166 SLIST_HEAD(mld_in6m_relhead, in6_multi);
167
168 static void mli_initvar(struct mld_ifinfo *, struct ifnet *, int);
169 static struct mld_ifinfo *mli_alloc(zalloc_flags_t);
170 static void mli_free(struct mld_ifinfo *);
171 static void mli_delete(const struct ifnet *, struct mld_in6m_relhead *);
172 static void mld_dispatch_packet(struct mbuf *);
173 static void mld_final_leave(struct in6_multi *, struct mld_ifinfo *,
174 struct mld_tparams *);
175 static int mld_handle_state_change(struct in6_multi *, struct mld_ifinfo *,
176 struct mld_tparams *);
177 static int mld_initial_join(struct in6_multi *, struct mld_ifinfo *,
178 struct mld_tparams *, const int);
179 #ifdef MLD_DEBUG
180 static const char * mld_rec_type_to_str(const int);
181 #endif
182 static uint32_t mld_set_version(struct mld_ifinfo *, const int);
183 static void mld_flush_relq(struct mld_ifinfo *, struct mld_in6m_relhead *);
184 static void mld_dispatch_queue_locked(struct mld_ifinfo *, struct ifqueue *, int);
185 static int mld_v1_input_query(struct ifnet *, const struct ip6_hdr *,
186 /*const*/ struct mld_hdr *);
187 static int mld_v1_input_report(struct ifnet *, struct mbuf *,
188 const struct ip6_hdr *, /*const*/ struct mld_hdr *);
189 static void mld_v1_process_group_timer(struct in6_multi *, const int);
190 static void mld_v1_process_querier_timers(struct mld_ifinfo *);
191 static int mld_v1_transmit_report(struct in6_multi *, const uint8_t);
192 static uint32_t mld_v1_update_group(struct in6_multi *, const int);
193 static void mld_v2_cancel_link_timers(struct mld_ifinfo *);
194 static uint32_t mld_v2_dispatch_general_query(struct mld_ifinfo *);
195 static struct mbuf *
196 mld_v2_encap_report(struct ifnet *, struct mbuf *);
197 static int mld_v2_enqueue_filter_change(struct ifqueue *,
198 struct in6_multi *);
199 static int mld_v2_enqueue_group_record(struct ifqueue *,
200 struct in6_multi *, const int, const int, const int,
201 const int);
202 static int mld_v2_input_query(struct ifnet *, const struct ip6_hdr *,
203 struct mbuf *, const int, const int);
204 static int mld_v2_merge_state_changes(struct in6_multi *,
205 struct ifqueue *);
206 static void mld_v2_process_group_timers(struct mld_ifinfo *,
207 struct ifqueue *, struct ifqueue *,
208 struct in6_multi *, const int);
209 static int mld_v2_process_group_query(struct in6_multi *,
210 int, struct mbuf *, const int);
211 static int sysctl_mld_gsr SYSCTL_HANDLER_ARGS;
212 static int sysctl_mld_ifinfo SYSCTL_HANDLER_ARGS;
213 static int sysctl_mld_v2enable SYSCTL_HANDLER_ARGS;
214
215 static int mld_timeout_run; /* MLD timer is scheduled to run */
216 static void mld_timeout(void *);
217 static void mld_sched_timeout(void);
218
219 /*
220 * Normative references: RFC 2710, RFC 3590, RFC 3810.
221 */
222 static struct timeval mld_gsrdelay = {.tv_sec = 10, .tv_usec = 0};
223 static LIST_HEAD(, mld_ifinfo) mli_head;
224
225 static int querier_present_timers_running6;
226 static int interface_timers_running6;
227 static int state_change_timers_running6;
228 static int current_state_timers_running6;
229
230 static unsigned int mld_mli_list_genid;
231 /*
232 * Subsystem lock macros.
233 */
234 #define MLD_LOCK() \
235 lck_mtx_lock(&mld_mtx)
236 #define MLD_LOCK_ASSERT_HELD() \
237 LCK_MTX_ASSERT(&mld_mtx, LCK_MTX_ASSERT_OWNED)
238 #define MLD_LOCK_ASSERT_NOTHELD() \
239 LCK_MTX_ASSERT(&mld_mtx, LCK_MTX_ASSERT_NOTOWNED)
240 #define MLD_UNLOCK() \
241 lck_mtx_unlock(&mld_mtx)
242
243 #define MLD_ADD_DETACHED_IN6M(_head, _in6m) { \
244 SLIST_INSERT_HEAD(_head, _in6m, in6m_dtle); \
245 }
246
247 #define MLD_REMOVE_DETACHED_IN6M(_head) { \
248 struct in6_multi *_in6m, *_inm_tmp; \
249 SLIST_FOREACH_SAFE(_in6m, _head, in6m_dtle, _inm_tmp) { \
250 SLIST_REMOVE(_head, _in6m, in6_multi, in6m_dtle); \
251 IN6M_REMREF(_in6m); \
252 } \
253 VERIFY(SLIST_EMPTY(_head)); \
254 }
255
256 static ZONE_DEFINE(mli_zone, "mld_ifinfo",
257 sizeof(struct mld_ifinfo), ZC_ZFREE_CLEARMEM);
258
259 SYSCTL_DECL(_net_inet6); /* Note: Not in any common header. */
260
261 SYSCTL_NODE(_net_inet6, OID_AUTO, mld, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
262 "IPv6 Multicast Listener Discovery");
263 SYSCTL_PROC(_net_inet6_mld, OID_AUTO, gsrdelay,
264 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
265 &mld_gsrdelay.tv_sec, 0, sysctl_mld_gsr, "I",
266 "Rate limit for MLDv2 Group-and-Source queries in seconds");
267
268 SYSCTL_NODE(_net_inet6_mld, OID_AUTO, ifinfo, CTLFLAG_RD | CTLFLAG_LOCKED,
269 sysctl_mld_ifinfo, "Per-interface MLDv2 state");
270
271 static int mld_v1enable = 1;
272 SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RW | CTLFLAG_LOCKED,
273 &mld_v1enable, 0, "Enable fallback to MLDv1");
274
275 static int mld_v2enable = 1;
276 SYSCTL_PROC(_net_inet6_mld, OID_AUTO, v2enable,
277 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
278 &mld_v2enable, 0, sysctl_mld_v2enable, "I",
279 "Enable MLDv2 (debug purposes only)");
280
281 static int mld_use_allow = 1;
282 SYSCTL_INT(_net_inet6_mld, OID_AUTO, use_allow, CTLFLAG_RW | CTLFLAG_LOCKED,
283 &mld_use_allow, 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves");
284
285 #ifdef MLD_DEBUG
286 int mld_debug = 0;
287 SYSCTL_INT(_net_inet6_mld, OID_AUTO,
288 debug, CTLFLAG_RW | CTLFLAG_LOCKED, &mld_debug, 0, "");
289 #endif
290 /*
291 * Packed Router Alert option structure declaration.
292 */
293 struct mld_raopt {
294 struct ip6_hbh hbh;
295 struct ip6_opt pad;
296 struct ip6_opt_router ra;
297 } __packed;
298
299 /*
300 * Router Alert hop-by-hop option header.
301 */
302 static struct mld_raopt mld_ra = {
303 .hbh = { .ip6h_nxt = 0, .ip6h_len = 0 },
304 .pad = { .ip6o_type = IP6OPT_PADN, .ip6o_len = 0 },
305 .ra = {
306 .ip6or_type = (u_int8_t)IP6OPT_ROUTER_ALERT,
307 .ip6or_len = (u_int8_t)(IP6OPT_RTALERT_LEN - 2),
308 .ip6or_value = {((IP6OPT_RTALERT_MLD >> 8) & 0xFF),
309 (IP6OPT_RTALERT_MLD & 0xFF) }
310 }
311 };
312 static struct ip6_pktopts mld_po;
313
314 /* Store MLDv2 record count in the module private scratch space */
315 #define vt_nrecs pkt_mpriv.__mpriv_u.__mpriv32[0].__mpriv32_u.__val16[0]
316
317 static __inline void
mld_save_context(struct mbuf * m,struct ifnet * ifp)318 mld_save_context(struct mbuf *m, struct ifnet *ifp)
319 {
320 m->m_pkthdr.rcvif = ifp;
321 }
322
323 static __inline void
mld_scrub_context(struct mbuf * m)324 mld_scrub_context(struct mbuf *m)
325 {
326 m->m_pkthdr.rcvif = NULL;
327 }
328
329 /*
330 * Restore context from a queued output chain.
331 * Return saved ifp.
332 */
333 static __inline struct ifnet *
mld_restore_context(struct mbuf * m)334 mld_restore_context(struct mbuf *m)
335 {
336 return m->m_pkthdr.rcvif;
337 }
338
339 /*
340 * Retrieve or set threshold between group-source queries in seconds.
341 */
342 static int
343 sysctl_mld_gsr SYSCTL_HANDLER_ARGS
344 {
345 #pragma unused(arg1, arg2)
346 int error;
347 int i;
348
349 MLD_LOCK();
350
351 i = (int)mld_gsrdelay.tv_sec;
352
353 error = sysctl_handle_int(oidp, &i, 0, req);
354 if (error || !req->newptr) {
355 goto out_locked;
356 }
357
358 if (i < -1 || i >= 60) {
359 error = EINVAL;
360 goto out_locked;
361 }
362
363 mld_gsrdelay.tv_sec = i;
364
365 out_locked:
366 MLD_UNLOCK();
367 return error;
368 }
369 /*
370 * Expose struct mld_ifinfo to userland, keyed by ifindex.
371 * For use by ifmcstat(8).
372 *
373 */
374 static int
375 sysctl_mld_ifinfo SYSCTL_HANDLER_ARGS
376 {
377 #pragma unused(oidp)
378 int *name;
379 int error;
380 u_int namelen;
381 struct ifnet *ifp;
382 struct mld_ifinfo *mli;
383 struct mld_ifinfo_u mli_u;
384
385 name = (int *)arg1;
386 namelen = arg2;
387
388 if (req->newptr != USER_ADDR_NULL) {
389 return EPERM;
390 }
391
392 if (namelen != 1) {
393 return EINVAL;
394 }
395
396 MLD_LOCK();
397
398 if (name[0] <= 0 || name[0] > (u_int)if_index) {
399 error = ENOENT;
400 goto out_locked;
401 }
402
403 error = ENOENT;
404
405 ifnet_head_lock_shared();
406 ifp = ifindex2ifnet[name[0]];
407 ifnet_head_done();
408 if (ifp == NULL) {
409 goto out_locked;
410 }
411
412 bzero(&mli_u, sizeof(mli_u));
413
414 LIST_FOREACH(mli, &mli_head, mli_link) {
415 MLI_LOCK(mli);
416 if (ifp != mli->mli_ifp) {
417 MLI_UNLOCK(mli);
418 continue;
419 }
420
421 mli_u.mli_ifindex = mli->mli_ifp->if_index;
422 mli_u.mli_version = mli->mli_version;
423 mli_u.mli_v1_timer = mli->mli_v1_timer;
424 mli_u.mli_v2_timer = mli->mli_v2_timer;
425 mli_u.mli_flags = mli->mli_flags;
426 mli_u.mli_rv = mli->mli_rv;
427 mli_u.mli_qi = mli->mli_qi;
428 mli_u.mli_qri = mli->mli_qri;
429 mli_u.mli_uri = mli->mli_uri;
430 MLI_UNLOCK(mli);
431
432 error = SYSCTL_OUT(req, &mli_u, sizeof(mli_u));
433 break;
434 }
435
436 out_locked:
437 MLD_UNLOCK();
438 return error;
439 }
440
441 static int
442 sysctl_mld_v2enable SYSCTL_HANDLER_ARGS
443 {
444 #pragma unused(arg1, arg2)
445 int error;
446 int i;
447 struct mld_ifinfo *mli;
448 struct mld_tparams mtp = { .qpt = 0, .it = 0, .cst = 0, .sct = 0 };
449
450 MLD_LOCK();
451
452 i = mld_v2enable;
453
454 error = sysctl_handle_int(oidp, &i, 0, req);
455 if (error || !req->newptr) {
456 goto out_locked;
457 }
458
459 if (i < 0 || i > 1) {
460 error = EINVAL;
461 goto out_locked;
462 }
463
464 mld_v2enable = i;
465 /*
466 * If we enabled v2, the state transition will take care of upgrading
467 * the MLD version back to v2. Otherwise, we have to explicitly
468 * downgrade. Note that this functionality is to be used for debugging.
469 */
470 if (mld_v2enable == 1) {
471 goto out_locked;
472 }
473
474 LIST_FOREACH(mli, &mli_head, mli_link) {
475 MLI_LOCK(mli);
476 if (mld_set_version(mli, MLD_VERSION_1) > 0) {
477 mtp.qpt = 1;
478 }
479 MLI_UNLOCK(mli);
480 }
481
482 out_locked:
483 MLD_UNLOCK();
484
485 mld_set_timeout(&mtp);
486
487 return error;
488 }
489
490 /*
491 * Dispatch an entire queue of pending packet chains.
492 *
493 * Must not be called with in6m_lock held.
494 * XXX This routine unlocks MLD global lock and also mli locks.
495 * Make sure that the calling routine takes reference on the mli
496 * before calling this routine.
497 * Also if we are traversing mli_head, remember to check for
498 * mli list generation count and restart the loop if generation count
499 * has changed.
500 */
501 static void
mld_dispatch_queue_locked(struct mld_ifinfo * mli,struct ifqueue * ifq,int limit)502 mld_dispatch_queue_locked(struct mld_ifinfo *mli, struct ifqueue *ifq, int limit)
503 {
504 struct mbuf *m;
505
506 MLD_LOCK_ASSERT_HELD();
507
508 if (mli != NULL) {
509 MLI_LOCK_ASSERT_HELD(mli);
510 }
511
512 for (;;) {
513 IF_DEQUEUE(ifq, m);
514 if (m == NULL) {
515 break;
516 }
517 MLD_PRINTF(("%s: dispatch 0x%llx from 0x%llx\n", __func__,
518 (uint64_t)VM_KERNEL_ADDRPERM(ifq),
519 (uint64_t)VM_KERNEL_ADDRPERM(m)));
520
521 if (mli != NULL) {
522 MLI_UNLOCK(mli);
523 }
524 MLD_UNLOCK();
525
526 mld_dispatch_packet(m);
527
528 MLD_LOCK();
529 if (mli != NULL) {
530 MLI_LOCK(mli);
531 }
532
533 if (--limit == 0) {
534 break;
535 }
536 }
537
538 if (mli != NULL) {
539 MLI_LOCK_ASSERT_HELD(mli);
540 }
541 }
542
543 /*
544 * Filter outgoing MLD report state by group.
545 *
546 * Reports are ALWAYS suppressed for ALL-HOSTS (ff02::1)
547 * and node-local addresses. However, kernel and socket consumers
548 * always embed the KAME scope ID in the address provided, so strip it
549 * when performing comparison.
550 * Note: This is not the same as the *multicast* scope.
551 *
552 * Return zero if the given group is one for which MLD reports
553 * should be suppressed, or non-zero if reports should be issued.
554 */
555 static __inline__ int
mld_is_addr_reported(const struct in6_addr * addr)556 mld_is_addr_reported(const struct in6_addr *addr)
557 {
558 VERIFY(IN6_IS_ADDR_MULTICAST(addr));
559
560 if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_NODELOCAL) {
561 return 0;
562 }
563
564 if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_LINKLOCAL && !IN6_IS_ADDR_UNICAST_BASED_MULTICAST(addr)) {
565 struct in6_addr tmp = *addr;
566 in6_clearscope(&tmp);
567 if (IN6_ARE_ADDR_EQUAL(&tmp, &in6addr_linklocal_allnodes)) {
568 return 0;
569 }
570 }
571
572 return 1;
573 }
574
575 /*
576 * Attach MLD when PF_INET6 is attached to an interface.
577 */
578 struct mld_ifinfo *
mld_domifattach(struct ifnet * ifp,zalloc_flags_t how)579 mld_domifattach(struct ifnet *ifp, zalloc_flags_t how)
580 {
581 struct mld_ifinfo *mli;
582
583 MLD_PRINTF(("%s: called for ifp 0x%llx(%s)\n", __func__,
584 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
585
586 mli = mli_alloc(how);
587 if (mli == NULL) {
588 return NULL;
589 }
590
591 MLD_LOCK();
592
593 MLI_LOCK(mli);
594 mli_initvar(mli, ifp, 0);
595 mli->mli_debug |= IFD_ATTACHED;
596 MLI_ADDREF_LOCKED(mli); /* hold a reference for mli_head */
597 MLI_ADDREF_LOCKED(mli); /* hold a reference for caller */
598 MLI_UNLOCK(mli);
599 ifnet_lock_shared(ifp);
600 mld6_initsilent(ifp, mli);
601 ifnet_lock_done(ifp);
602
603 LIST_INSERT_HEAD(&mli_head, mli, mli_link);
604 mld_mli_list_genid++;
605
606 MLD_UNLOCK();
607
608 MLD_PRINTF(("%s: allocate mld_ifinfo for ifp 0x%llx(%s)\n",
609 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
610
611 return mli;
612 }
613
614 /*
615 * Attach MLD when PF_INET6 is reattached to an interface. Caller is
616 * expected to have an outstanding reference to the mli.
617 */
618 void
mld_domifreattach(struct mld_ifinfo * mli)619 mld_domifreattach(struct mld_ifinfo *mli)
620 {
621 struct ifnet *ifp;
622
623 MLD_LOCK();
624
625 MLI_LOCK(mli);
626 VERIFY(!(mli->mli_debug & IFD_ATTACHED));
627 ifp = mli->mli_ifp;
628 VERIFY(ifp != NULL);
629 mli_initvar(mli, ifp, 1);
630 mli->mli_debug |= IFD_ATTACHED;
631 MLI_ADDREF_LOCKED(mli); /* hold a reference for mli_head */
632 MLI_UNLOCK(mli);
633 ifnet_lock_shared(ifp);
634 mld6_initsilent(ifp, mli);
635 ifnet_lock_done(ifp);
636
637 LIST_INSERT_HEAD(&mli_head, mli, mli_link);
638 mld_mli_list_genid++;
639
640 MLD_UNLOCK();
641
642 MLD_PRINTF(("%s: reattached mld_ifinfo for ifp 0x%llx(%s)\n",
643 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
644 }
645
646 /*
647 * Hook for domifdetach.
648 */
649 void
mld_domifdetach(struct ifnet * ifp)650 mld_domifdetach(struct ifnet *ifp)
651 {
652 SLIST_HEAD(, in6_multi) in6m_dthead;
653
654 SLIST_INIT(&in6m_dthead);
655
656 MLD_PRINTF(("%s: called for ifp 0x%llx(%s)\n", __func__,
657 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
658
659 MLD_LOCK();
660 mli_delete(ifp, (struct mld_in6m_relhead *)&in6m_dthead);
661 MLD_UNLOCK();
662
663 /* Now that we're dropped all locks, release detached records */
664 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead);
665 }
666
667 /*
668 * Called at interface detach time. Note that we only flush all deferred
669 * responses and record releases; all remaining inm records and their source
670 * entries related to this interface are left intact, in order to handle
671 * the reattach case.
672 */
673 static void
mli_delete(const struct ifnet * ifp,struct mld_in6m_relhead * in6m_dthead)674 mli_delete(const struct ifnet *ifp, struct mld_in6m_relhead *in6m_dthead)
675 {
676 struct mld_ifinfo *mli, *tmli;
677
678 MLD_LOCK_ASSERT_HELD();
679
680 LIST_FOREACH_SAFE(mli, &mli_head, mli_link, tmli) {
681 MLI_LOCK(mli);
682 if (mli->mli_ifp == ifp) {
683 /*
684 * Free deferred General Query responses.
685 */
686 IF_DRAIN(&mli->mli_gq);
687 IF_DRAIN(&mli->mli_v1q);
688 mld_flush_relq(mli, in6m_dthead);
689 VERIFY(SLIST_EMPTY(&mli->mli_relinmhead));
690 mli->mli_debug &= ~IFD_ATTACHED;
691 MLI_UNLOCK(mli);
692
693 LIST_REMOVE(mli, mli_link);
694 MLI_REMREF(mli); /* release mli_head reference */
695 mld_mli_list_genid++;
696 return;
697 }
698 MLI_UNLOCK(mli);
699 }
700 panic("%s: mld_ifinfo not found for ifp %p(%s)", __func__,
701 ifp, ifp->if_xname);
702 }
703
704 __private_extern__ void
mld6_initsilent(struct ifnet * ifp,struct mld_ifinfo * mli)705 mld6_initsilent(struct ifnet *ifp, struct mld_ifinfo *mli)
706 {
707 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_OWNED);
708
709 MLI_LOCK_ASSERT_NOTHELD(mli);
710 MLI_LOCK(mli);
711 if (!(ifp->if_flags & IFF_MULTICAST) &&
712 (ifp->if_eflags & (IFEF_IPV6_ND6ALT | IFEF_LOCALNET_PRIVATE))) {
713 mli->mli_flags |= MLIF_SILENT;
714 } else {
715 mli->mli_flags &= ~MLIF_SILENT;
716 }
717 MLI_UNLOCK(mli);
718 }
719
720 static void
mli_initvar(struct mld_ifinfo * mli,struct ifnet * ifp,int reattach)721 mli_initvar(struct mld_ifinfo *mli, struct ifnet *ifp, int reattach)
722 {
723 MLI_LOCK_ASSERT_HELD(mli);
724
725 mli->mli_ifp = ifp;
726 if (mld_v2enable) {
727 mli->mli_version = MLD_VERSION_2;
728 } else {
729 mli->mli_version = MLD_VERSION_1;
730 }
731 mli->mli_flags = 0;
732 mli->mli_rv = MLD_RV_INIT;
733 mli->mli_qi = MLD_QI_INIT;
734 mli->mli_qri = MLD_QRI_INIT;
735 mli->mli_uri = MLD_URI_INIT;
736
737 if (mld_use_allow) {
738 mli->mli_flags |= MLIF_USEALLOW;
739 }
740 if (!reattach) {
741 SLIST_INIT(&mli->mli_relinmhead);
742 }
743
744 /*
745 * Responses to general queries are subject to bounds.
746 */
747 mli->mli_gq.ifq_maxlen = MLD_MAX_RESPONSE_PACKETS;
748 mli->mli_v1q.ifq_maxlen = MLD_MAX_RESPONSE_PACKETS;
749 }
750
751 static struct mld_ifinfo *
mli_alloc(zalloc_flags_t how)752 mli_alloc(zalloc_flags_t how)
753 {
754 struct mld_ifinfo *mli = zalloc_flags(mli_zone, how | Z_ZERO);
755 if (mli != NULL) {
756 lck_mtx_init(&mli->mli_lock, &mld_mtx_grp, &mld_mtx_attr);
757 mli->mli_debug |= IFD_ALLOC;
758 }
759 return mli;
760 }
761
762 static void
mli_free(struct mld_ifinfo * mli)763 mli_free(struct mld_ifinfo *mli)
764 {
765 MLI_LOCK(mli);
766 if (mli->mli_debug & IFD_ATTACHED) {
767 panic("%s: attached mli=%p is being freed", __func__, mli);
768 /* NOTREACHED */
769 } else if (mli->mli_ifp != NULL) {
770 panic("%s: ifp not NULL for mli=%p", __func__, mli);
771 /* NOTREACHED */
772 } else if (!(mli->mli_debug & IFD_ALLOC)) {
773 panic("%s: mli %p cannot be freed", __func__, mli);
774 /* NOTREACHED */
775 } else if (mli->mli_refcnt != 0) {
776 panic("%s: non-zero refcnt mli=%p", __func__, mli);
777 /* NOTREACHED */
778 }
779 mli->mli_debug &= ~IFD_ALLOC;
780 MLI_UNLOCK(mli);
781
782 lck_mtx_destroy(&mli->mli_lock, &mld_mtx_grp);
783 zfree(mli_zone, mli);
784 }
785
786 void
mli_addref(struct mld_ifinfo * mli,int locked)787 mli_addref(struct mld_ifinfo *mli, int locked)
788 {
789 if (!locked) {
790 MLI_LOCK_SPIN(mli);
791 } else {
792 MLI_LOCK_ASSERT_HELD(mli);
793 }
794
795 if (++mli->mli_refcnt == 0) {
796 panic("%s: mli=%p wraparound refcnt", __func__, mli);
797 /* NOTREACHED */
798 }
799 if (!locked) {
800 MLI_UNLOCK(mli);
801 }
802 }
803
804 void
mli_remref(struct mld_ifinfo * mli)805 mli_remref(struct mld_ifinfo *mli)
806 {
807 SLIST_HEAD(, in6_multi) in6m_dthead;
808 struct ifnet *ifp;
809
810 MLI_LOCK_SPIN(mli);
811
812 if (mli->mli_refcnt == 0) {
813 panic("%s: mli=%p negative refcnt", __func__, mli);
814 /* NOTREACHED */
815 }
816
817 --mli->mli_refcnt;
818 if (mli->mli_refcnt > 0) {
819 MLI_UNLOCK(mli);
820 return;
821 }
822
823 ifp = mli->mli_ifp;
824 mli->mli_ifp = NULL;
825 IF_DRAIN(&mli->mli_gq);
826 IF_DRAIN(&mli->mli_v1q);
827 SLIST_INIT(&in6m_dthead);
828 mld_flush_relq(mli, (struct mld_in6m_relhead *)&in6m_dthead);
829 VERIFY(SLIST_EMPTY(&mli->mli_relinmhead));
830 MLI_UNLOCK(mli);
831
832 /* Now that we're dropped all locks, release detached records */
833 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead);
834
835 MLD_PRINTF(("%s: freeing mld_ifinfo for ifp 0x%llx(%s)\n",
836 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
837
838 mli_free(mli);
839 }
840
841 /*
842 * Process a received MLDv1 general or address-specific query.
843 * Assumes that the query header has been pulled up to sizeof(mld_hdr).
844 *
845 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
846 * mld_addr. This is OK as we own the mbuf chain.
847 */
848 static int
mld_v1_input_query(struct ifnet * ifp,const struct ip6_hdr * ip6,struct mld_hdr * mld)849 mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
850 /*const*/ struct mld_hdr *mld)
851 {
852 struct mld_ifinfo *mli;
853 struct in6_multi *inm;
854 int err = 0, is_general_query;
855 uint16_t timer;
856 struct mld_tparams mtp = { .qpt = 0, .it = 0, .cst = 0, .sct = 0 };
857
858 MLD_LOCK_ASSERT_NOTHELD();
859
860 is_general_query = 0;
861
862 if (!mld_v1enable) {
863 MLD_PRINTF(("%s: ignore v1 query %s on ifp 0x%llx(%s)\n",
864 __func__, ip6_sprintf(&mld->mld_addr),
865 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
866 goto done;
867 }
868
869 /*
870 * RFC3810 Section 6.2: MLD queries must originate from
871 * a router's link-local address.
872 */
873 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
874 MLD_PRINTF(("%s: ignore v1 query src %s on ifp 0x%llx(%s)\n",
875 __func__, ip6_sprintf(&ip6->ip6_src),
876 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
877 goto done;
878 }
879
880 /*
881 * Do address field validation upfront before we accept
882 * the query.
883 */
884 if (IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
885 /*
886 * MLDv1 General Query.
887 * If this was not sent to the all-nodes group, ignore it.
888 */
889 struct in6_addr dst;
890
891 dst = ip6->ip6_dst;
892 in6_clearscope(&dst);
893 if (!IN6_ARE_ADDR_EQUAL(&dst, &in6addr_linklocal_allnodes)) {
894 err = EINVAL;
895 goto done;
896 }
897 is_general_query = 1;
898 } else {
899 /*
900 * Embed scope ID of receiving interface in MLD query for
901 * lookup whilst we don't hold other locks.
902 */
903 (void)in6_setscope(&mld->mld_addr, ifp, NULL);
904 }
905
906 /*
907 * Switch to MLDv1 host compatibility mode.
908 */
909 mli = MLD_IFINFO(ifp);
910 VERIFY(mli != NULL);
911
912 MLI_LOCK(mli);
913 mtp.qpt = mld_set_version(mli, MLD_VERSION_1);
914 MLI_UNLOCK(mli);
915
916 timer = ntohs(mld->mld_maxdelay) / MLD_TIMER_SCALE;
917 if (timer == 0) {
918 timer = 1;
919 }
920
921 if (is_general_query) {
922 struct in6_multistep step;
923
924 MLD_PRINTF(("%s: process v1 general query on ifp 0x%llx(%s)\n",
925 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
926 /*
927 * For each reporting group joined on this
928 * interface, kick the report timer.
929 */
930 in6_multihead_lock_shared();
931 IN6_FIRST_MULTI(step, inm);
932 while (inm != NULL) {
933 IN6M_LOCK(inm);
934 if (inm->in6m_ifp == ifp) {
935 mtp.cst += mld_v1_update_group(inm, timer);
936 }
937 IN6M_UNLOCK(inm);
938 IN6_NEXT_MULTI(step, inm);
939 }
940 in6_multihead_lock_done();
941 } else {
942 /*
943 * MLDv1 Group-Specific Query.
944 * If this is a group-specific MLDv1 query, we need only
945 * look up the single group to process it.
946 */
947 in6_multihead_lock_shared();
948 IN6_LOOKUP_MULTI(&mld->mld_addr, ifp, inm);
949 in6_multihead_lock_done();
950
951 if (inm != NULL) {
952 IN6M_LOCK(inm);
953 MLD_PRINTF(("%s: process v1 query %s on "
954 "ifp 0x%llx(%s)\n", __func__,
955 ip6_sprintf(&mld->mld_addr),
956 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
957 mtp.cst = mld_v1_update_group(inm, timer);
958 IN6M_UNLOCK(inm);
959 IN6M_REMREF(inm); /* from IN6_LOOKUP_MULTI */
960 }
961 /* XXX Clear embedded scope ID as userland won't expect it. */
962 in6_clearscope(&mld->mld_addr);
963 }
964 done:
965 mld_set_timeout(&mtp);
966
967 return err;
968 }
969
970 /*
971 * Update the report timer on a group in response to an MLDv1 query.
972 *
973 * If we are becoming the reporting member for this group, start the timer.
974 * If we already are the reporting member for this group, and timer is
975 * below the threshold, reset it.
976 *
977 * We may be updating the group for the first time since we switched
978 * to MLDv2. If we are, then we must clear any recorded source lists,
979 * and transition to REPORTING state; the group timer is overloaded
980 * for group and group-source query responses.
981 *
982 * Unlike MLDv2, the delay per group should be jittered
983 * to avoid bursts of MLDv1 reports.
984 */
985 static uint32_t
mld_v1_update_group(struct in6_multi * inm,const int timer)986 mld_v1_update_group(struct in6_multi *inm, const int timer)
987 {
988 IN6M_LOCK_ASSERT_HELD(inm);
989
990 MLD_PRINTF(("%s: %s/%s timer=%d\n", __func__,
991 ip6_sprintf(&inm->in6m_addr),
992 if_name(inm->in6m_ifp), timer));
993
994 switch (inm->in6m_state) {
995 case MLD_NOT_MEMBER:
996 case MLD_SILENT_MEMBER:
997 break;
998 case MLD_REPORTING_MEMBER:
999 if (inm->in6m_timer != 0 &&
1000 inm->in6m_timer <= timer) {
1001 MLD_PRINTF(("%s: REPORTING and timer running, "
1002 "skipping.\n", __func__));
1003 break;
1004 }
1005 OS_FALLTHROUGH;
1006 case MLD_SG_QUERY_PENDING_MEMBER:
1007 case MLD_G_QUERY_PENDING_MEMBER:
1008 case MLD_IDLE_MEMBER:
1009 case MLD_LAZY_MEMBER:
1010 case MLD_AWAKENING_MEMBER:
1011 MLD_PRINTF(("%s: ->REPORTING\n", __func__));
1012 inm->in6m_state = MLD_REPORTING_MEMBER;
1013 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1014 break;
1015 case MLD_SLEEPING_MEMBER:
1016 MLD_PRINTF(("%s: ->AWAKENING\n", __func__));
1017 inm->in6m_state = MLD_AWAKENING_MEMBER;
1018 break;
1019 case MLD_LEAVING_MEMBER:
1020 break;
1021 }
1022
1023 return inm->in6m_timer;
1024 }
1025
1026 /*
1027 * Process a received MLDv2 general, group-specific or
1028 * group-and-source-specific query.
1029 *
1030 * Assumes that the query header has been pulled up to sizeof(mldv2_query).
1031 *
1032 * Return 0 if successful, otherwise an appropriate error code is returned.
1033 */
1034 static int
mld_v2_input_query(struct ifnet * ifp,const struct ip6_hdr * ip6,struct mbuf * m,const int off,const int icmp6len)1035 mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
1036 struct mbuf *m, const int off, const int icmp6len)
1037 {
1038 struct mld_ifinfo *mli;
1039 struct mldv2_query *mld;
1040 struct in6_multi *inm;
1041 uint32_t maxdelay, nsrc, qqi, timer;
1042 int err = 0, is_general_query;
1043 uint8_t qrv;
1044 struct mld_tparams mtp = { .qpt = 0, .it = 0, .cst = 0, .sct = 0 };
1045
1046 MLD_LOCK_ASSERT_NOTHELD();
1047
1048 is_general_query = 0;
1049
1050 if (!mld_v2enable) {
1051 MLD_PRINTF(("%s: ignore v2 query %s on ifp 0x%llx(%s)\n",
1052 __func__, ip6_sprintf(&ip6->ip6_src),
1053 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1054 goto done;
1055 }
1056
1057 /*
1058 * RFC3810 Section 6.2: MLD queries must originate from
1059 * a router's link-local address.
1060 */
1061 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
1062 MLD_PRINTF(("%s: ignore v1 query src %s on ifp 0x%llx(%s)\n",
1063 __func__, ip6_sprintf(&ip6->ip6_src),
1064 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1065 goto done;
1066 }
1067
1068 MLD_PRINTF(("%s: input v2 query on ifp 0x%llx(%s)\n", __func__,
1069 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1070
1071 mld = (struct mldv2_query *)(mtod(m, uint8_t *) + off);
1072
1073 maxdelay = ntohs(mld->mld_maxdelay); /* in 1/10ths of a second */
1074 if (maxdelay > SHRT_MAX) {
1075 maxdelay = (MLD_MRC_MANT((uint16_t)maxdelay) | 0x1000) <<
1076 (MLD_MRC_EXP((uint16_t)maxdelay) + 3);
1077 }
1078 timer = maxdelay / MLD_TIMER_SCALE;
1079 if (timer == 0) {
1080 timer = 1;
1081 }
1082
1083 qrv = MLD_QRV(mld->mld_misc);
1084 if (qrv < 2) {
1085 MLD_PRINTF(("%s: clamping qrv %d to %d\n", __func__,
1086 qrv, MLD_RV_INIT));
1087 qrv = MLD_RV_INIT;
1088 }
1089
1090 qqi = mld->mld_qqi;
1091 if (qqi >= 128) {
1092 qqi = MLD_QQIC_MANT(mld->mld_qqi) <<
1093 (MLD_QQIC_EXP(mld->mld_qqi) + 3);
1094 }
1095
1096 nsrc = ntohs(mld->mld_numsrc);
1097 if (nsrc > MLD_MAX_GS_SOURCES) {
1098 err = EMSGSIZE;
1099 goto done;
1100 }
1101 if (icmp6len < sizeof(struct mldv2_query) +
1102 (nsrc * sizeof(struct in6_addr))) {
1103 err = EMSGSIZE;
1104 goto done;
1105 }
1106
1107 /*
1108 * Do further input validation upfront to avoid resetting timers
1109 * should we need to discard this query.
1110 */
1111 if (IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
1112 /*
1113 * A general query with a source list has undefined
1114 * behaviour; discard it.
1115 */
1116 if (nsrc > 0) {
1117 err = EINVAL;
1118 goto done;
1119 }
1120 is_general_query = 1;
1121 } else {
1122 /*
1123 * Embed scope ID of receiving interface in MLD query for
1124 * lookup whilst we don't hold other locks (due to KAME
1125 * locking lameness). We own this mbuf chain just now.
1126 */
1127 (void)in6_setscope(&mld->mld_addr, ifp, NULL);
1128 }
1129
1130 mli = MLD_IFINFO(ifp);
1131 VERIFY(mli != NULL);
1132
1133 MLI_LOCK(mli);
1134 /*
1135 * Discard the v2 query if we're in Compatibility Mode.
1136 * The RFC is pretty clear that hosts need to stay in MLDv1 mode
1137 * until the Old Version Querier Present timer expires.
1138 */
1139 if (mli->mli_version != MLD_VERSION_2) {
1140 MLI_UNLOCK(mli);
1141 goto done;
1142 }
1143
1144 mtp.qpt = mld_set_version(mli, MLD_VERSION_2);
1145 mli->mli_rv = qrv;
1146 mli->mli_qi = qqi;
1147 mli->mli_qri = MAX(timer, MLD_QRI_MIN);
1148
1149 MLD_PRINTF(("%s: qrv %d qi %d qri %d\n", __func__, mli->mli_rv,
1150 mli->mli_qi, mli->mli_qri));
1151
1152 if (is_general_query) {
1153 /*
1154 * MLDv2 General Query.
1155 *
1156 * Schedule a current-state report on this ifp for
1157 * all groups, possibly containing source lists.
1158 *
1159 * If there is a pending General Query response
1160 * scheduled earlier than the selected delay, do
1161 * not schedule any other reports.
1162 * Otherwise, reset the interface timer.
1163 */
1164 MLD_PRINTF(("%s: process v2 general query on ifp 0x%llx(%s)\n",
1165 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1166 if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer) {
1167 mtp.it = mli->mli_v2_timer = MLD_RANDOM_DELAY(timer);
1168 }
1169 MLI_UNLOCK(mli);
1170 } else {
1171 MLI_UNLOCK(mli);
1172 /*
1173 * MLDv2 Group-specific or Group-and-source-specific Query.
1174 *
1175 * Group-source-specific queries are throttled on
1176 * a per-group basis to defeat denial-of-service attempts.
1177 * Queries for groups we are not a member of on this
1178 * link are simply ignored.
1179 */
1180 in6_multihead_lock_shared();
1181 IN6_LOOKUP_MULTI(&mld->mld_addr, ifp, inm);
1182 in6_multihead_lock_done();
1183 if (inm == NULL) {
1184 goto done;
1185 }
1186
1187 IN6M_LOCK(inm);
1188 if (nsrc > 0) {
1189 if (!ratecheck(&inm->in6m_lastgsrtv,
1190 &mld_gsrdelay)) {
1191 MLD_PRINTF(("%s: GS query throttled.\n",
1192 __func__));
1193 IN6M_UNLOCK(inm);
1194 IN6M_REMREF(inm); /* from IN6_LOOKUP_MULTI */
1195 goto done;
1196 }
1197 }
1198 MLD_PRINTF(("%s: process v2 group query on ifp 0x%llx(%s)\n",
1199 __func__, (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1200 /*
1201 * If there is a pending General Query response
1202 * scheduled sooner than the selected delay, no
1203 * further report need be scheduled.
1204 * Otherwise, prepare to respond to the
1205 * group-specific or group-and-source query.
1206 */
1207 MLI_LOCK(mli);
1208 mtp.it = mli->mli_v2_timer;
1209 MLI_UNLOCK(mli);
1210 if (mtp.it == 0 || mtp.it >= timer) {
1211 (void) mld_v2_process_group_query(inm, timer, m, off);
1212 mtp.cst = inm->in6m_timer;
1213 }
1214 IN6M_UNLOCK(inm);
1215 IN6M_REMREF(inm); /* from IN6_LOOKUP_MULTI */
1216 /* XXX Clear embedded scope ID as userland won't expect it. */
1217 in6_clearscope(&mld->mld_addr);
1218 }
1219 done:
1220 if (mtp.it > 0) {
1221 MLD_PRINTF(("%s: v2 general query response scheduled in "
1222 "T+%d seconds on ifp 0x%llx(%s)\n", __func__, mtp.it,
1223 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1224 }
1225 mld_set_timeout(&mtp);
1226
1227 return err;
1228 }
1229
1230 /*
1231 * Process a recieved MLDv2 group-specific or group-and-source-specific
1232 * query.
1233 * Return <0 if any error occured. Currently this is ignored.
1234 */
1235 static int
mld_v2_process_group_query(struct in6_multi * inm,int timer,struct mbuf * m0,const int off)1236 mld_v2_process_group_query(struct in6_multi *inm, int timer, struct mbuf *m0,
1237 const int off)
1238 {
1239 struct mldv2_query *mld;
1240 int retval;
1241 uint16_t nsrc;
1242
1243 IN6M_LOCK_ASSERT_HELD(inm);
1244
1245 retval = 0;
1246 mld = (struct mldv2_query *)(mtod(m0, uint8_t *) + off);
1247
1248 switch (inm->in6m_state) {
1249 case MLD_NOT_MEMBER:
1250 case MLD_SILENT_MEMBER:
1251 case MLD_SLEEPING_MEMBER:
1252 case MLD_LAZY_MEMBER:
1253 case MLD_AWAKENING_MEMBER:
1254 case MLD_IDLE_MEMBER:
1255 case MLD_LEAVING_MEMBER:
1256 return retval;
1257 case MLD_REPORTING_MEMBER:
1258 case MLD_G_QUERY_PENDING_MEMBER:
1259 case MLD_SG_QUERY_PENDING_MEMBER:
1260 break;
1261 }
1262
1263 nsrc = ntohs(mld->mld_numsrc);
1264
1265 /*
1266 * Deal with group-specific queries upfront.
1267 * If any group query is already pending, purge any recorded
1268 * source-list state if it exists, and schedule a query response
1269 * for this group-specific query.
1270 */
1271 if (nsrc == 0) {
1272 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER ||
1273 inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER) {
1274 in6m_clear_recorded(inm);
1275 timer = min(inm->in6m_timer, timer);
1276 }
1277 inm->in6m_state = MLD_G_QUERY_PENDING_MEMBER;
1278 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1279 return retval;
1280 }
1281
1282 /*
1283 * Deal with the case where a group-and-source-specific query has
1284 * been received but a group-specific query is already pending.
1285 */
1286 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER) {
1287 timer = min(inm->in6m_timer, timer);
1288 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1289 return retval;
1290 }
1291
1292 /*
1293 * Finally, deal with the case where a group-and-source-specific
1294 * query has been received, where a response to a previous g-s-r
1295 * query exists, or none exists.
1296 * In this case, we need to parse the source-list which the Querier
1297 * has provided us with and check if we have any source list filter
1298 * entries at T1 for these sources. If we do not, there is no need
1299 * schedule a report and the query may be dropped.
1300 * If we do, we must record them and schedule a current-state
1301 * report for those sources.
1302 */
1303 if (inm->in6m_nsrc > 0) {
1304 struct mbuf *m;
1305 struct in6_addr addr;
1306 int i, nrecorded;
1307 int soff;
1308
1309 m = m0;
1310 soff = off + sizeof(struct mldv2_query);
1311 nrecorded = 0;
1312 for (i = 0; i < nsrc; i++) {
1313 m_copydata(m, soff, sizeof(addr), &addr);
1314 retval = in6m_record_source(inm, &addr);
1315 if (retval < 0) {
1316 break;
1317 }
1318 nrecorded += retval;
1319 soff += sizeof(struct in6_addr);
1320
1321 while (m && (soff >= m->m_len)) {
1322 soff -= m->m_len;
1323 m = m->m_next;
1324 }
1325
1326 /* should not be possible: */
1327 if (m == NULL) {
1328 break;
1329 }
1330 }
1331 if (nrecorded > 0) {
1332 MLD_PRINTF(("%s: schedule response to SG query\n",
1333 __func__));
1334 inm->in6m_state = MLD_SG_QUERY_PENDING_MEMBER;
1335 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1336 }
1337 }
1338
1339 return retval;
1340 }
1341
1342 /*
1343 * Process a received MLDv1 host membership report.
1344 * Assumes mld points to mld_hdr in pulled up mbuf chain.
1345 *
1346 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
1347 * mld_addr. This is OK as we own the mbuf chain.
1348 */
1349 static int
mld_v1_input_report(struct ifnet * ifp,struct mbuf * m,const struct ip6_hdr * ip6,struct mld_hdr * mld)1350 mld_v1_input_report(struct ifnet *ifp, struct mbuf *m,
1351 const struct ip6_hdr *ip6, /*const*/ struct mld_hdr *mld)
1352 {
1353 struct in6_addr src, dst;
1354 struct in6_ifaddr *ia;
1355 struct in6_multi *inm;
1356
1357 if (!mld_v1enable) {
1358 MLD_PRINTF(("%s: ignore v1 report %s on ifp 0x%llx(%s)\n",
1359 __func__, ip6_sprintf(&mld->mld_addr),
1360 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1361 return 0;
1362 }
1363
1364 if ((ifp->if_flags & IFF_LOOPBACK) ||
1365 (m->m_pkthdr.pkt_flags & PKTF_LOOP)) {
1366 return 0;
1367 }
1368
1369 /*
1370 * MLDv1 reports must originate from a host's link-local address,
1371 * or the unspecified address (when booting).
1372 */
1373 src = ip6->ip6_src;
1374 in6_clearscope(&src);
1375 if (!IN6_IS_SCOPE_LINKLOCAL(&src) && !IN6_IS_ADDR_UNSPECIFIED(&src)) {
1376 MLD_PRINTF(("%s: ignore v1 query src %s on ifp 0x%llx(%s)\n",
1377 __func__, ip6_sprintf(&ip6->ip6_src),
1378 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1379 return EINVAL;
1380 }
1381
1382 /*
1383 * RFC2710 Section 4: MLDv1 reports must pertain to a multicast
1384 * group, and must be directed to the group itself.
1385 */
1386 dst = ip6->ip6_dst;
1387 in6_clearscope(&dst);
1388 if (!IN6_IS_ADDR_MULTICAST(&mld->mld_addr) ||
1389 !IN6_ARE_ADDR_EQUAL(&mld->mld_addr, &dst)) {
1390 MLD_PRINTF(("%s: ignore v1 query dst %s on ifp 0x%llx(%s)\n",
1391 __func__, ip6_sprintf(&ip6->ip6_dst),
1392 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1393 return EINVAL;
1394 }
1395
1396 /*
1397 * Make sure we don't hear our own membership report, as fast
1398 * leave requires knowing that we are the only member of a
1399 * group. Assume we used the link-local address if available,
1400 * otherwise look for ::.
1401 *
1402 * XXX Note that scope ID comparison is needed for the address
1403 * returned by in6ifa_ifpforlinklocal(), but SHOULD NOT be
1404 * performed for the on-wire address.
1405 */
1406 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
1407 if (ia != NULL) {
1408 IFA_LOCK(&ia->ia_ifa);
1409 if ((IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, IA6_IN6(ia)))) {
1410 IFA_UNLOCK(&ia->ia_ifa);
1411 IFA_REMREF(&ia->ia_ifa);
1412 return 0;
1413 }
1414 IFA_UNLOCK(&ia->ia_ifa);
1415 IFA_REMREF(&ia->ia_ifa);
1416 } else if (IN6_IS_ADDR_UNSPECIFIED(&src)) {
1417 return 0;
1418 }
1419
1420 MLD_PRINTF(("%s: process v1 report %s on ifp 0x%llx(%s)\n",
1421 __func__, ip6_sprintf(&mld->mld_addr),
1422 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1423
1424 /*
1425 * Embed scope ID of receiving interface in MLD query for lookup
1426 * whilst we don't hold other locks (due to KAME locking lameness).
1427 */
1428 if (!IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
1429 (void)in6_setscope(&mld->mld_addr, ifp, NULL);
1430 }
1431
1432 /*
1433 * MLDv1 report suppression.
1434 * If we are a member of this group, and our membership should be
1435 * reported, and our group timer is pending or about to be reset,
1436 * stop our group timer by transitioning to the 'lazy' state.
1437 */
1438 in6_multihead_lock_shared();
1439 IN6_LOOKUP_MULTI(&mld->mld_addr, ifp, inm);
1440 in6_multihead_lock_done();
1441
1442 if (inm != NULL) {
1443 struct mld_ifinfo *mli;
1444
1445 IN6M_LOCK(inm);
1446 mli = inm->in6m_mli;
1447 VERIFY(mli != NULL);
1448
1449 MLI_LOCK(mli);
1450 /*
1451 * If we are in MLDv2 host mode, do not allow the
1452 * other host's MLDv1 report to suppress our reports.
1453 */
1454 if (mli->mli_version == MLD_VERSION_2) {
1455 MLI_UNLOCK(mli);
1456 IN6M_UNLOCK(inm);
1457 IN6M_REMREF(inm); /* from IN6_LOOKUP_MULTI */
1458 goto out;
1459 }
1460 MLI_UNLOCK(mli);
1461
1462 inm->in6m_timer = 0;
1463
1464 switch (inm->in6m_state) {
1465 case MLD_NOT_MEMBER:
1466 case MLD_SILENT_MEMBER:
1467 case MLD_SLEEPING_MEMBER:
1468 break;
1469 case MLD_REPORTING_MEMBER:
1470 case MLD_IDLE_MEMBER:
1471 case MLD_AWAKENING_MEMBER:
1472 MLD_PRINTF(("%s: report suppressed for %s on "
1473 "ifp 0x%llx(%s)\n", __func__,
1474 ip6_sprintf(&mld->mld_addr),
1475 (uint64_t)VM_KERNEL_ADDRPERM(ifp), if_name(ifp)));
1476 OS_FALLTHROUGH;
1477 case MLD_LAZY_MEMBER:
1478 inm->in6m_state = MLD_LAZY_MEMBER;
1479 break;
1480 case MLD_G_QUERY_PENDING_MEMBER:
1481 case MLD_SG_QUERY_PENDING_MEMBER:
1482 case MLD_LEAVING_MEMBER:
1483 break;
1484 }
1485 IN6M_UNLOCK(inm);
1486 IN6M_REMREF(inm); /* from IN6_LOOKUP_MULTI */
1487 }
1488
1489 out:
1490 /* XXX Clear embedded scope ID as userland won't expect it. */
1491 in6_clearscope(&mld->mld_addr);
1492
1493 return 0;
1494 }
1495
1496 /*
1497 * MLD input path.
1498 *
1499 * Assume query messages which fit in a single ICMPv6 message header
1500 * have been pulled up.
1501 * Assume that userland will want to see the message, even if it
1502 * otherwise fails kernel input validation; do not free it.
1503 * Pullup may however free the mbuf chain m if it fails.
1504 *
1505 * Return IPPROTO_DONE if we freed m. Otherwise, return 0.
1506 */
1507 int
mld_input(struct mbuf * m,int off,int icmp6len)1508 mld_input(struct mbuf *m, int off, int icmp6len)
1509 {
1510 struct ifnet *ifp = NULL;
1511 struct ip6_hdr *ip6 = NULL;
1512 struct mld_hdr *mld = NULL;
1513 int mldlen = 0;
1514
1515 MLD_PRINTF(("%s: called w/mbuf (0x%llx,%d)\n", __func__,
1516 (uint64_t)VM_KERNEL_ADDRPERM(m), off));
1517
1518 ifp = m->m_pkthdr.rcvif;
1519
1520 /* Pullup to appropriate size. */
1521 mld = (struct mld_hdr *)(mtod(m, uint8_t *) + off);
1522 if (mld->mld_type == MLD_LISTENER_QUERY &&
1523 icmp6len >= sizeof(struct mldv2_query)) {
1524 mldlen = sizeof(struct mldv2_query);
1525 } else {
1526 mldlen = sizeof(struct mld_hdr);
1527 }
1528 // check if mldv2_query/mld_hdr fits in the first mbuf
1529 IP6_EXTHDR_CHECK(m, off, mldlen, return IPPROTO_DONE);
1530 IP6_EXTHDR_GET(mld, struct mld_hdr *, m, off, mldlen);
1531 if (mld == NULL) {
1532 icmp6stat.icp6s_badlen++;
1533 return IPPROTO_DONE;
1534 }
1535 ip6 = mtod(m, struct ip6_hdr *);
1536
1537 /*
1538 * Userland needs to see all of this traffic for implementing
1539 * the endpoint discovery portion of multicast routing.
1540 */
1541 switch (mld->mld_type) {
1542 case MLD_LISTENER_QUERY:
1543 icmp6_ifstat_inc(ifp, ifs6_in_mldquery);
1544 if (icmp6len == sizeof(struct mld_hdr)) {
1545 if (mld_v1_input_query(ifp, ip6, mld) != 0) {
1546 return 0;
1547 }
1548 } else if (icmp6len >= sizeof(struct mldv2_query)) {
1549 if (mld_v2_input_query(ifp, ip6, m, off,
1550 icmp6len) != 0) {
1551 return 0;
1552 }
1553 }
1554 break;
1555 case MLD_LISTENER_REPORT:
1556 icmp6_ifstat_inc(ifp, ifs6_in_mldreport);
1557 if (mld_v1_input_report(ifp, m, ip6, mld) != 0) {
1558 return 0;
1559 }
1560 break;
1561 case MLDV2_LISTENER_REPORT:
1562 icmp6_ifstat_inc(ifp, ifs6_in_mldreport);
1563 break;
1564 case MLD_LISTENER_DONE:
1565 icmp6_ifstat_inc(ifp, ifs6_in_mlddone);
1566 break;
1567 default:
1568 break;
1569 }
1570
1571 return 0;
1572 }
1573
1574 /*
1575 * Schedule MLD timer based on various parameters; caller must ensure that
1576 * lock ordering is maintained as this routine acquires MLD global lock.
1577 */
1578 void
mld_set_timeout(struct mld_tparams * mtp)1579 mld_set_timeout(struct mld_tparams *mtp)
1580 {
1581 MLD_LOCK_ASSERT_NOTHELD();
1582 VERIFY(mtp != NULL);
1583
1584 if (mtp->qpt != 0 || mtp->it != 0 || mtp->cst != 0 || mtp->sct != 0) {
1585 MLD_LOCK();
1586 if (mtp->qpt != 0) {
1587 querier_present_timers_running6 = 1;
1588 }
1589 if (mtp->it != 0) {
1590 interface_timers_running6 = 1;
1591 }
1592 if (mtp->cst != 0) {
1593 current_state_timers_running6 = 1;
1594 }
1595 if (mtp->sct != 0) {
1596 state_change_timers_running6 = 1;
1597 }
1598 mld_sched_timeout();
1599 MLD_UNLOCK();
1600 }
1601 }
1602
1603 /*
1604 * MLD6 timer handler (per 1 second).
1605 */
1606 static void
mld_timeout(void * arg)1607 mld_timeout(void *arg)
1608 {
1609 #pragma unused(arg)
1610 struct ifqueue scq; /* State-change packets */
1611 struct ifqueue qrq; /* Query response packets */
1612 struct ifnet *ifp;
1613 struct mld_ifinfo *mli;
1614 struct in6_multi *inm;
1615 int uri_sec = 0;
1616 unsigned int genid = mld_mli_list_genid;
1617
1618 SLIST_HEAD(, in6_multi) in6m_dthead;
1619
1620 SLIST_INIT(&in6m_dthead);
1621
1622 /*
1623 * Update coarse-grained networking timestamp (in sec.); the idea
1624 * is to piggy-back on the timeout callout to update the counter
1625 * returnable via net_uptime().
1626 */
1627 net_update_uptime();
1628
1629 MLD_LOCK();
1630
1631 MLD_PRINTF(("%s: qpt %d, it %d, cst %d, sct %d\n", __func__,
1632 querier_present_timers_running6, interface_timers_running6,
1633 current_state_timers_running6, state_change_timers_running6));
1634
1635 /*
1636 * MLDv1 querier present timer processing.
1637 */
1638 if (querier_present_timers_running6) {
1639 querier_present_timers_running6 = 0;
1640 LIST_FOREACH(mli, &mli_head, mli_link) {
1641 MLI_LOCK(mli);
1642 mld_v1_process_querier_timers(mli);
1643 if (mli->mli_v1_timer > 0) {
1644 querier_present_timers_running6 = 1;
1645 }
1646 MLI_UNLOCK(mli);
1647 }
1648 }
1649
1650 /*
1651 * MLDv2 General Query response timer processing.
1652 */
1653 if (interface_timers_running6) {
1654 MLD_PRINTF(("%s: interface timers running\n", __func__));
1655 interface_timers_running6 = 0;
1656 mli = LIST_FIRST(&mli_head);
1657
1658 while (mli != NULL) {
1659 if (mli->mli_flags & MLIF_PROCESSED) {
1660 mli = LIST_NEXT(mli, mli_link);
1661 continue;
1662 }
1663
1664 MLI_LOCK(mli);
1665 if (mli->mli_version != MLD_VERSION_2) {
1666 MLI_UNLOCK(mli);
1667 mli = LIST_NEXT(mli, mli_link);
1668 continue;
1669 }
1670 /*
1671 * XXX The logic below ends up calling
1672 * mld_dispatch_packet which can unlock mli
1673 * and the global MLD lock.
1674 * Therefore grab a reference on MLI and also
1675 * check for generation count to see if we should
1676 * iterate the list again.
1677 */
1678 MLI_ADDREF_LOCKED(mli);
1679
1680 if (mli->mli_v2_timer == 0) {
1681 /* Do nothing. */
1682 } else if (--mli->mli_v2_timer == 0) {
1683 if (mld_v2_dispatch_general_query(mli) > 0) {
1684 interface_timers_running6 = 1;
1685 }
1686 } else {
1687 interface_timers_running6 = 1;
1688 }
1689 mli->mli_flags |= MLIF_PROCESSED;
1690 MLI_UNLOCK(mli);
1691 MLI_REMREF(mli);
1692
1693 if (genid != mld_mli_list_genid) {
1694 MLD_PRINTF(("%s: MLD information list changed "
1695 "in the middle of iteration! Restart iteration.\n",
1696 __func__));
1697 mli = LIST_FIRST(&mli_head);
1698 genid = mld_mli_list_genid;
1699 } else {
1700 mli = LIST_NEXT(mli, mli_link);
1701 }
1702 }
1703
1704 LIST_FOREACH(mli, &mli_head, mli_link)
1705 mli->mli_flags &= ~MLIF_PROCESSED;
1706 }
1707
1708
1709
1710 if (!current_state_timers_running6 &&
1711 !state_change_timers_running6) {
1712 goto out_locked;
1713 }
1714
1715 current_state_timers_running6 = 0;
1716 state_change_timers_running6 = 0;
1717
1718 MLD_PRINTF(("%s: state change timers running\n", __func__));
1719
1720 memset(&qrq, 0, sizeof(struct ifqueue));
1721 qrq.ifq_maxlen = MLD_MAX_G_GS_PACKETS;
1722
1723 memset(&scq, 0, sizeof(struct ifqueue));
1724 scq.ifq_maxlen = MLD_MAX_STATE_CHANGE_PACKETS;
1725
1726 /*
1727 * MLD host report and state-change timer processing.
1728 * Note: Processing a v2 group timer may remove a node.
1729 */
1730 mli = LIST_FIRST(&mli_head);
1731
1732 while (mli != NULL) {
1733 struct in6_multistep step;
1734
1735 if (mli->mli_flags & MLIF_PROCESSED) {
1736 mli = LIST_NEXT(mli, mli_link);
1737 continue;
1738 }
1739
1740 MLI_LOCK(mli);
1741 ifp = mli->mli_ifp;
1742 uri_sec = MLD_RANDOM_DELAY(mli->mli_uri);
1743 MLI_UNLOCK(mli);
1744
1745 in6_multihead_lock_shared();
1746 IN6_FIRST_MULTI(step, inm);
1747 while (inm != NULL) {
1748 IN6M_LOCK(inm);
1749 if (inm->in6m_ifp != ifp) {
1750 goto next;
1751 }
1752
1753 MLI_LOCK(mli);
1754 switch (mli->mli_version) {
1755 case MLD_VERSION_1:
1756 mld_v1_process_group_timer(inm,
1757 mli->mli_version);
1758 break;
1759 case MLD_VERSION_2:
1760 mld_v2_process_group_timers(mli, &qrq,
1761 &scq, inm, uri_sec);
1762 break;
1763 }
1764 MLI_UNLOCK(mli);
1765 next:
1766 IN6M_UNLOCK(inm);
1767 IN6_NEXT_MULTI(step, inm);
1768 }
1769 in6_multihead_lock_done();
1770
1771 /*
1772 * XXX The logic below ends up calling
1773 * mld_dispatch_packet which can unlock mli
1774 * and the global MLD lock.
1775 * Therefore grab a reference on MLI and also
1776 * check for generation count to see if we should
1777 * iterate the list again.
1778 */
1779 MLI_LOCK(mli);
1780 MLI_ADDREF_LOCKED(mli);
1781 if (mli->mli_version == MLD_VERSION_1) {
1782 mld_dispatch_queue_locked(mli, &mli->mli_v1q, 0);
1783 } else if (mli->mli_version == MLD_VERSION_2) {
1784 MLI_UNLOCK(mli);
1785 mld_dispatch_queue_locked(NULL, &qrq, 0);
1786 mld_dispatch_queue_locked(NULL, &scq, 0);
1787 VERIFY(qrq.ifq_len == 0);
1788 VERIFY(scq.ifq_len == 0);
1789 MLI_LOCK(mli);
1790 }
1791 /*
1792 * In case there are still any pending membership reports
1793 * which didn't get drained at version change time.
1794 */
1795 IF_DRAIN(&mli->mli_v1q);
1796 /*
1797 * Release all deferred inm records, and drain any locally
1798 * enqueued packets; do it even if the current MLD version
1799 * for the link is no longer MLDv2, in order to handle the
1800 * version change case.
1801 */
1802 mld_flush_relq(mli, (struct mld_in6m_relhead *)&in6m_dthead);
1803 VERIFY(SLIST_EMPTY(&mli->mli_relinmhead));
1804 mli->mli_flags |= MLIF_PROCESSED;
1805 MLI_UNLOCK(mli);
1806 MLI_REMREF(mli);
1807
1808 IF_DRAIN(&qrq);
1809 IF_DRAIN(&scq);
1810
1811 if (genid != mld_mli_list_genid) {
1812 MLD_PRINTF(("%s: MLD information list changed "
1813 "in the middle of iteration! Restart iteration.\n",
1814 __func__));
1815 mli = LIST_FIRST(&mli_head);
1816 genid = mld_mli_list_genid;
1817 } else {
1818 mli = LIST_NEXT(mli, mli_link);
1819 }
1820 }
1821
1822 LIST_FOREACH(mli, &mli_head, mli_link)
1823 mli->mli_flags &= ~MLIF_PROCESSED;
1824
1825 out_locked:
1826 /* re-arm the timer if there's work to do */
1827 mld_timeout_run = 0;
1828 mld_sched_timeout();
1829 MLD_UNLOCK();
1830
1831 /* Now that we're dropped all locks, release detached records */
1832 MLD_REMOVE_DETACHED_IN6M(&in6m_dthead);
1833 }
1834
1835 static void
mld_sched_timeout(void)1836 mld_sched_timeout(void)
1837 {
1838 MLD_LOCK_ASSERT_HELD();
1839
1840 if (!mld_timeout_run &&
1841 (querier_present_timers_running6 || current_state_timers_running6 ||
1842 interface_timers_running6 || state_change_timers_running6)) {
1843 mld_timeout_run = 1;
1844 timeout(mld_timeout, NULL, hz);
1845 }
1846 }
1847
1848 /*
1849 * Free the in6_multi reference(s) for this MLD lifecycle.
1850 *
1851 * Caller must be holding mli_lock.
1852 */
1853 static void
mld_flush_relq(struct mld_ifinfo * mli,struct mld_in6m_relhead * in6m_dthead)1854 mld_flush_relq(struct mld_ifinfo *mli, struct mld_in6m_relhead *in6m_dthead)
1855 {
1856 struct in6_multi *inm;
1857
1858 again:
1859 MLI_LOCK_ASSERT_HELD(mli);
1860 inm = SLIST_FIRST(&mli->mli_relinmhead);
1861 if (inm != NULL) {
1862 int lastref;
1863
1864 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
1865 MLI_UNLOCK(mli);
1866
1867 in6_multihead_lock_exclusive();
1868 IN6M_LOCK(inm);
1869 VERIFY(inm->in6m_nrelecnt != 0);
1870 inm->in6m_nrelecnt--;
1871 lastref = in6_multi_detach(inm);
1872 VERIFY(!lastref || (!(inm->in6m_debug & IFD_ATTACHED) &&
1873 inm->in6m_reqcnt == 0));
1874 IN6M_UNLOCK(inm);
1875 in6_multihead_lock_done();
1876 /* from mli_relinmhead */
1877 IN6M_REMREF(inm);
1878 /* from in6_multihead_list */
1879 if (lastref) {
1880 /*
1881 * Defer releasing our final reference, as we
1882 * are holding the MLD lock at this point, and
1883 * we could end up with locking issues later on
1884 * (while issuing SIOCDELMULTI) when this is the
1885 * final reference count. Let the caller do it
1886 * when it is safe.
1887 */
1888 MLD_ADD_DETACHED_IN6M(in6m_dthead, inm);
1889 }
1890 MLI_LOCK(mli);
1891 goto again;
1892 }
1893 }
1894
1895 /*
1896 * Update host report group timer.
1897 * Will update the global pending timer flags.
1898 */
1899 static void
mld_v1_process_group_timer(struct in6_multi * inm,const int mld_version)1900 mld_v1_process_group_timer(struct in6_multi *inm, const int mld_version)
1901 {
1902 #pragma unused(mld_version)
1903 int report_timer_expired;
1904
1905 MLD_LOCK_ASSERT_HELD();
1906 IN6M_LOCK_ASSERT_HELD(inm);
1907 MLI_LOCK_ASSERT_HELD(inm->in6m_mli);
1908
1909 if (inm->in6m_timer == 0) {
1910 report_timer_expired = 0;
1911 } else if (--inm->in6m_timer == 0) {
1912 report_timer_expired = 1;
1913 } else {
1914 current_state_timers_running6 = 1;
1915 /* caller will schedule timer */
1916 return;
1917 }
1918
1919 switch (inm->in6m_state) {
1920 case MLD_NOT_MEMBER:
1921 case MLD_SILENT_MEMBER:
1922 case MLD_IDLE_MEMBER:
1923 case MLD_LAZY_MEMBER:
1924 case MLD_SLEEPING_MEMBER:
1925 case MLD_AWAKENING_MEMBER:
1926 break;
1927 case MLD_REPORTING_MEMBER:
1928 if (report_timer_expired) {
1929 inm->in6m_state = MLD_IDLE_MEMBER;
1930 (void) mld_v1_transmit_report(inm,
1931 MLD_LISTENER_REPORT);
1932 IN6M_LOCK_ASSERT_HELD(inm);
1933 MLI_LOCK_ASSERT_HELD(inm->in6m_mli);
1934 }
1935 break;
1936 case MLD_G_QUERY_PENDING_MEMBER:
1937 case MLD_SG_QUERY_PENDING_MEMBER:
1938 case MLD_LEAVING_MEMBER:
1939 break;
1940 }
1941 }
1942
1943 /*
1944 * Update a group's timers for MLDv2.
1945 * Will update the global pending timer flags.
1946 * Note: Unlocked read from mli.
1947 */
1948 static void
mld_v2_process_group_timers(struct mld_ifinfo * mli,struct ifqueue * qrq,struct ifqueue * scq,struct in6_multi * inm,const int uri_sec)1949 mld_v2_process_group_timers(struct mld_ifinfo *mli,
1950 struct ifqueue *qrq, struct ifqueue *scq,
1951 struct in6_multi *inm, const int uri_sec)
1952 {
1953 int query_response_timer_expired;
1954 int state_change_retransmit_timer_expired;
1955
1956 MLD_LOCK_ASSERT_HELD();
1957 IN6M_LOCK_ASSERT_HELD(inm);
1958 MLI_LOCK_ASSERT_HELD(mli);
1959 VERIFY(mli == inm->in6m_mli);
1960
1961 query_response_timer_expired = 0;
1962 state_change_retransmit_timer_expired = 0;
1963
1964 /*
1965 * During a transition from compatibility mode back to MLDv2,
1966 * a group record in REPORTING state may still have its group
1967 * timer active. This is a no-op in this function; it is easier
1968 * to deal with it here than to complicate the timeout path.
1969 */
1970 if (inm->in6m_timer == 0) {
1971 query_response_timer_expired = 0;
1972 } else if (--inm->in6m_timer == 0) {
1973 query_response_timer_expired = 1;
1974 } else {
1975 current_state_timers_running6 = 1;
1976 /* caller will schedule timer */
1977 }
1978
1979 if (inm->in6m_sctimer == 0) {
1980 state_change_retransmit_timer_expired = 0;
1981 } else if (--inm->in6m_sctimer == 0) {
1982 state_change_retransmit_timer_expired = 1;
1983 } else {
1984 state_change_timers_running6 = 1;
1985 /* caller will schedule timer */
1986 }
1987
1988 /* We are in timer callback, so be quick about it. */
1989 if (!state_change_retransmit_timer_expired &&
1990 !query_response_timer_expired) {
1991 return;
1992 }
1993
1994 switch (inm->in6m_state) {
1995 case MLD_NOT_MEMBER:
1996 case MLD_SILENT_MEMBER:
1997 case MLD_SLEEPING_MEMBER:
1998 case MLD_LAZY_MEMBER:
1999 case MLD_AWAKENING_MEMBER:
2000 case MLD_IDLE_MEMBER:
2001 break;
2002 case MLD_G_QUERY_PENDING_MEMBER:
2003 case MLD_SG_QUERY_PENDING_MEMBER:
2004 /*
2005 * Respond to a previously pending Group-Specific
2006 * or Group-and-Source-Specific query by enqueueing
2007 * the appropriate Current-State report for
2008 * immediate transmission.
2009 */
2010 if (query_response_timer_expired) {
2011 int retval;
2012
2013 retval = mld_v2_enqueue_group_record(qrq, inm, 0, 1,
2014 (inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER),
2015 0);
2016 MLD_PRINTF(("%s: enqueue record = %d\n",
2017 __func__, retval));
2018 inm->in6m_state = MLD_REPORTING_MEMBER;
2019 in6m_clear_recorded(inm);
2020 }
2021 OS_FALLTHROUGH;
2022 case MLD_REPORTING_MEMBER:
2023 case MLD_LEAVING_MEMBER:
2024 if (state_change_retransmit_timer_expired) {
2025 /*
2026 * State-change retransmission timer fired.
2027 * If there are any further pending retransmissions,
2028 * set the global pending state-change flag, and
2029 * reset the timer.
2030 */
2031 if (--inm->in6m_scrv > 0) {
2032 inm->in6m_sctimer = (uint16_t)uri_sec;
2033 state_change_timers_running6 = 1;
2034 /* caller will schedule timer */
2035 }
2036 /*
2037 * Retransmit the previously computed state-change
2038 * report. If there are no further pending
2039 * retransmissions, the mbuf queue will be consumed.
2040 * Update T0 state to T1 as we have now sent
2041 * a state-change.
2042 */
2043 (void) mld_v2_merge_state_changes(inm, scq);
2044
2045 in6m_commit(inm);
2046 MLD_PRINTF(("%s: T1 -> T0 for %s/%s\n", __func__,
2047 ip6_sprintf(&inm->in6m_addr),
2048 if_name(inm->in6m_ifp)));
2049
2050 /*
2051 * If we are leaving the group for good, make sure
2052 * we release MLD's reference to it.
2053 * This release must be deferred using a SLIST,
2054 * as we are called from a loop which traverses
2055 * the in_ifmultiaddr TAILQ.
2056 */
2057 if (inm->in6m_state == MLD_LEAVING_MEMBER &&
2058 inm->in6m_scrv == 0) {
2059 inm->in6m_state = MLD_NOT_MEMBER;
2060 /*
2061 * A reference has already been held in
2062 * mld_final_leave() for this inm, so
2063 * no need to hold another one. We also
2064 * bumped up its request count then, so
2065 * that it stays in in6_multihead. Both
2066 * of them will be released when it is
2067 * dequeued later on.
2068 */
2069 VERIFY(inm->in6m_nrelecnt != 0);
2070 SLIST_INSERT_HEAD(&mli->mli_relinmhead,
2071 inm, in6m_nrele);
2072 }
2073 }
2074 break;
2075 }
2076 }
2077
2078 /*
2079 * Switch to a different version on the given interface,
2080 * as per Section 9.12.
2081 */
2082 static uint32_t
mld_set_version(struct mld_ifinfo * mli,const int mld_version)2083 mld_set_version(struct mld_ifinfo *mli, const int mld_version)
2084 {
2085 int old_version_timer;
2086
2087 MLI_LOCK_ASSERT_HELD(mli);
2088
2089 MLD_PRINTF(("%s: switching to v%d on ifp 0x%llx(%s)\n", __func__,
2090 mld_version, (uint64_t)VM_KERNEL_ADDRPERM(mli->mli_ifp),
2091 if_name(mli->mli_ifp)));
2092
2093 if (mld_version == MLD_VERSION_1) {
2094 /*
2095 * Compute the "Older Version Querier Present" timer as per
2096 * Section 9.12, in seconds.
2097 */
2098 old_version_timer = (mli->mli_rv * mli->mli_qi) + mli->mli_qri;
2099 mli->mli_v1_timer = old_version_timer;
2100 }
2101
2102 if (mli->mli_v1_timer > 0 && mli->mli_version != MLD_VERSION_1) {
2103 mli->mli_version = MLD_VERSION_1;
2104 mld_v2_cancel_link_timers(mli);
2105 }
2106
2107 MLI_LOCK_ASSERT_HELD(mli);
2108
2109 return mli->mli_v1_timer;
2110 }
2111
2112 /*
2113 * Cancel pending MLDv2 timers for the given link and all groups
2114 * joined on it; state-change, general-query, and group-query timers.
2115 *
2116 * Only ever called on a transition from v2 to Compatibility mode. Kill
2117 * the timers stone dead (this may be expensive for large N groups), they
2118 * will be restarted if Compatibility Mode deems that they must be due to
2119 * query processing.
2120 */
2121 static void
mld_v2_cancel_link_timers(struct mld_ifinfo * mli)2122 mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
2123 {
2124 struct ifnet *ifp;
2125 struct in6_multi *inm;
2126 struct in6_multistep step;
2127
2128 MLI_LOCK_ASSERT_HELD(mli);
2129
2130 MLD_PRINTF(("%s: cancel v2 timers on ifp 0x%llx(%s)\n", __func__,
2131 (uint64_t)VM_KERNEL_ADDRPERM(mli->mli_ifp), if_name(mli->mli_ifp)));
2132
2133 /*
2134 * Stop the v2 General Query Response on this link stone dead.
2135 * If timer is woken up due to interface_timers_running6,
2136 * the flag will be cleared if there are no pending link timers.
2137 */
2138 mli->mli_v2_timer = 0;
2139
2140 /*
2141 * Now clear the current-state and state-change report timers
2142 * for all memberships scoped to this link.
2143 */
2144 ifp = mli->mli_ifp;
2145 MLI_UNLOCK(mli);
2146
2147 in6_multihead_lock_shared();
2148 IN6_FIRST_MULTI(step, inm);
2149 while (inm != NULL) {
2150 IN6M_LOCK(inm);
2151 if (inm->in6m_ifp != ifp) {
2152 goto next;
2153 }
2154
2155 switch (inm->in6m_state) {
2156 case MLD_NOT_MEMBER:
2157 case MLD_SILENT_MEMBER:
2158 case MLD_IDLE_MEMBER:
2159 case MLD_LAZY_MEMBER:
2160 case MLD_SLEEPING_MEMBER:
2161 case MLD_AWAKENING_MEMBER:
2162 /*
2163 * These states are either not relevant in v2 mode,
2164 * or are unreported. Do nothing.
2165 */
2166 break;
2167 case MLD_LEAVING_MEMBER:
2168 /*
2169 * If we are leaving the group and switching
2170 * version, we need to release the final
2171 * reference held for issuing the INCLUDE {}.
2172 * During mld_final_leave(), we bumped up both the
2173 * request and reference counts. Since we cannot
2174 * call in6_multi_detach() here, defer this task to
2175 * the timer routine.
2176 */
2177 VERIFY(inm->in6m_nrelecnt != 0);
2178 MLI_LOCK(mli);
2179 SLIST_INSERT_HEAD(&mli->mli_relinmhead, inm,
2180 in6m_nrele);
2181 MLI_UNLOCK(mli);
2182 OS_FALLTHROUGH;
2183 case MLD_G_QUERY_PENDING_MEMBER:
2184 case MLD_SG_QUERY_PENDING_MEMBER:
2185 in6m_clear_recorded(inm);
2186 OS_FALLTHROUGH;
2187 case MLD_REPORTING_MEMBER:
2188 inm->in6m_state = MLD_REPORTING_MEMBER;
2189 break;
2190 }
2191 /*
2192 * Always clear state-change and group report timers.
2193 * Free any pending MLDv2 state-change records.
2194 */
2195 inm->in6m_sctimer = 0;
2196 inm->in6m_timer = 0;
2197 IF_DRAIN(&inm->in6m_scq);
2198 next:
2199 IN6M_UNLOCK(inm);
2200 IN6_NEXT_MULTI(step, inm);
2201 }
2202 in6_multihead_lock_done();
2203
2204 MLI_LOCK(mli);
2205 }
2206
2207 /*
2208 * Update the Older Version Querier Present timers for a link.
2209 * See Section 9.12 of RFC 3810.
2210 */
2211 static void
mld_v1_process_querier_timers(struct mld_ifinfo * mli)2212 mld_v1_process_querier_timers(struct mld_ifinfo *mli)
2213 {
2214 MLI_LOCK_ASSERT_HELD(mli);
2215
2216 if (mld_v2enable && mli->mli_version != MLD_VERSION_2 &&
2217 --mli->mli_v1_timer == 0) {
2218 /*
2219 * MLDv1 Querier Present timer expired; revert to MLDv2.
2220 */
2221 MLD_PRINTF(("%s: transition from v%d -> v%d on 0x%llx(%s)\n",
2222 __func__, mli->mli_version, MLD_VERSION_2,
2223 (uint64_t)VM_KERNEL_ADDRPERM(mli->mli_ifp),
2224 if_name(mli->mli_ifp)));
2225 mli->mli_version = MLD_VERSION_2;
2226 }
2227 }
2228
2229 /*
2230 * Transmit an MLDv1 report immediately.
2231 */
2232 static int
mld_v1_transmit_report(struct in6_multi * in6m,const uint8_t type)2233 mld_v1_transmit_report(struct in6_multi *in6m, const uint8_t type)
2234 {
2235 struct ifnet *ifp;
2236 struct in6_ifaddr *ia;
2237 struct ip6_hdr *ip6;
2238 struct mbuf *mh, *md;
2239 struct mld_hdr *mld;
2240 int error = 0;
2241
2242 IN6M_LOCK_ASSERT_HELD(in6m);
2243 MLI_LOCK_ASSERT_HELD(in6m->in6m_mli);
2244
2245 ifp = in6m->in6m_ifp;
2246 /* ia may be NULL if link-local address is tentative. */
2247 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
2248
2249 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
2250 if (mh == NULL) {
2251 if (ia != NULL) {
2252 IFA_REMREF(&ia->ia_ifa);
2253 }
2254 return ENOMEM;
2255 }
2256 MGET(md, M_DONTWAIT, MT_DATA);
2257 if (md == NULL) {
2258 m_free(mh);
2259 if (ia != NULL) {
2260 IFA_REMREF(&ia->ia_ifa);
2261 }
2262 return ENOMEM;
2263 }
2264 mh->m_next = md;
2265
2266 /*
2267 * FUTURE: Consider increasing alignment by ETHER_HDR_LEN, so
2268 * that ether_output() does not need to allocate another mbuf
2269 * for the header in the most common case.
2270 */
2271 MH_ALIGN(mh, sizeof(struct ip6_hdr));
2272 mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld_hdr);
2273 mh->m_len = sizeof(struct ip6_hdr);
2274
2275 ip6 = mtod(mh, struct ip6_hdr *);
2276 ip6->ip6_flow = 0;
2277 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
2278 ip6->ip6_vfc |= IPV6_VERSION;
2279 ip6->ip6_nxt = IPPROTO_ICMPV6;
2280 if (ia != NULL) {
2281 IFA_LOCK(&ia->ia_ifa);
2282 }
2283 ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
2284 ip6_output_setsrcifscope(mh, IFSCOPE_NONE, ia);
2285 if (ia != NULL) {
2286 IFA_UNLOCK(&ia->ia_ifa);
2287 IFA_REMREF(&ia->ia_ifa);
2288 ia = NULL;
2289 }
2290 ip6->ip6_dst = in6m->in6m_addr;
2291 ip6_output_setdstifscope(mh, in6m->ifscope, NULL);
2292
2293 md->m_len = sizeof(struct mld_hdr);
2294 mld = mtod(md, struct mld_hdr *);
2295 mld->mld_type = type;
2296 mld->mld_code = 0;
2297 mld->mld_cksum = 0;
2298 mld->mld_maxdelay = 0;
2299 mld->mld_reserved = 0;
2300 mld->mld_addr = in6m->in6m_addr;
2301 in6_clearscope(&mld->mld_addr);
2302 mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6,
2303 sizeof(struct ip6_hdr), sizeof(struct mld_hdr));
2304
2305 mld_save_context(mh, ifp);
2306 mh->m_flags |= M_MLDV1;
2307
2308 /*
2309 * Due to the fact that at this point we are possibly holding
2310 * in6_multihead_lock in shared or exclusive mode, we can't call
2311 * mld_dispatch_packet() here since that will eventually call
2312 * ip6_output(), which will try to lock in6_multihead_lock and cause
2313 * a deadlock.
2314 * Instead we defer the work to the mld_timeout() thread, thus
2315 * avoiding unlocking in_multihead_lock here.
2316 */
2317 if (IF_QFULL(&in6m->in6m_mli->mli_v1q)) {
2318 MLD_PRINTF(("%s: v1 outbound queue full\n", __func__));
2319 error = ENOMEM;
2320 m_freem(mh);
2321 } else {
2322 IF_ENQUEUE(&in6m->in6m_mli->mli_v1q, mh);
2323 VERIFY(error == 0);
2324 }
2325
2326 return error;
2327 }
2328
2329 /*
2330 * Process a state change from the upper layer for the given IPv6 group.
2331 *
2332 * Each socket holds a reference on the in6_multi in its own ip_moptions.
2333 * The socket layer will have made the necessary updates to.the group
2334 * state, it is now up to MLD to issue a state change report if there
2335 * has been any change between T0 (when the last state-change was issued)
2336 * and T1 (now).
2337 *
2338 * We use the MLDv2 state machine at group level. The MLd module
2339 * however makes the decision as to which MLD protocol version to speak.
2340 * A state change *from* INCLUDE {} always means an initial join.
2341 * A state change *to* INCLUDE {} always means a final leave.
2342 *
2343 * If delay is non-zero, and the state change is an initial multicast
2344 * join, the state change report will be delayed by 'delay' ticks
2345 * in units of seconds if MLDv1 is active on the link; otherwise
2346 * the initial MLDv2 state change report will be delayed by whichever
2347 * is sooner, a pending state-change timer or delay itself.
2348 */
2349 int
mld_change_state(struct in6_multi * inm,struct mld_tparams * mtp,const int delay)2350 mld_change_state(struct in6_multi *inm, struct mld_tparams *mtp,
2351 const int delay)
2352 {
2353 struct mld_ifinfo *mli;
2354 struct ifnet *ifp;
2355 int error = 0;
2356
2357 VERIFY(mtp != NULL);
2358 bzero(mtp, sizeof(*mtp));
2359
2360 IN6M_LOCK_ASSERT_HELD(inm);
2361 VERIFY(inm->in6m_mli != NULL);
2362 MLI_LOCK_ASSERT_NOTHELD(inm->in6m_mli);
2363
2364 /*
2365 * Try to detect if the upper layer just asked us to change state
2366 * for an interface which has now gone away.
2367 */
2368 VERIFY(inm->in6m_ifma != NULL);
2369 ifp = inm->in6m_ifma->ifma_ifp;
2370 /*
2371 * Sanity check that netinet6's notion of ifp is the same as net's.
2372 */
2373 VERIFY(inm->in6m_ifp == ifp);
2374
2375 mli = MLD_IFINFO(ifp);
2376 VERIFY(mli != NULL);
2377
2378 /*
2379 * If we detect a state transition to or from MCAST_UNDEFINED
2380 * for this group, then we are starting or finishing an MLD
2381 * life cycle for this group.
2382 */
2383 if (inm->in6m_st[1].iss_fmode != inm->in6m_st[0].iss_fmode) {
2384 MLD_PRINTF(("%s: inm transition %d -> %d\n", __func__,
2385 inm->in6m_st[0].iss_fmode, inm->in6m_st[1].iss_fmode));
2386 if (inm->in6m_st[0].iss_fmode == MCAST_UNDEFINED) {
2387 MLD_PRINTF(("%s: initial join\n", __func__));
2388 error = mld_initial_join(inm, mli, mtp, delay);
2389 goto out;
2390 } else if (inm->in6m_st[1].iss_fmode == MCAST_UNDEFINED) {
2391 MLD_PRINTF(("%s: final leave\n", __func__));
2392 mld_final_leave(inm, mli, mtp);
2393 goto out;
2394 }
2395 } else {
2396 MLD_PRINTF(("%s: filter set change\n", __func__));
2397 }
2398
2399 error = mld_handle_state_change(inm, mli, mtp);
2400 out:
2401 return error;
2402 }
2403
2404 /*
2405 * Perform the initial join for an MLD group.
2406 *
2407 * When joining a group:
2408 * If the group should have its MLD traffic suppressed, do nothing.
2409 * MLDv1 starts sending MLDv1 host membership reports.
2410 * MLDv2 will schedule an MLDv2 state-change report containing the
2411 * initial state of the membership.
2412 *
2413 * If the delay argument is non-zero, then we must delay sending the
2414 * initial state change for delay ticks (in units of seconds).
2415 */
2416 static int
mld_initial_join(struct in6_multi * inm,struct mld_ifinfo * mli,struct mld_tparams * mtp,const int delay)2417 mld_initial_join(struct in6_multi *inm, struct mld_ifinfo *mli,
2418 struct mld_tparams *mtp, const int delay)
2419 {
2420 struct ifnet *ifp;
2421 struct ifqueue *ifq;
2422 int error, retval, syncstates;
2423 int odelay;
2424
2425 IN6M_LOCK_ASSERT_HELD(inm);
2426 MLI_LOCK_ASSERT_NOTHELD(mli);
2427 VERIFY(mtp != NULL);
2428
2429 MLD_PRINTF(("%s: initial join %s on ifp 0x%llx(%s)\n",
2430 __func__, ip6_sprintf(&inm->in6m_addr),
2431 (uint64_t)VM_KERNEL_ADDRPERM(inm->in6m_ifp),
2432 if_name(inm->in6m_ifp)));
2433
2434 error = 0;
2435 syncstates = 1;
2436
2437 ifp = inm->in6m_ifp;
2438
2439 MLI_LOCK(mli);
2440 VERIFY(mli->mli_ifp == ifp);
2441
2442 /*
2443 * Avoid MLD if group is :
2444 * 1. Joined on loopback, OR
2445 * 2. On a link that is marked MLIF_SILENT
2446 * 3. rdar://problem/19227650 Is link local scoped and
2447 * on cellular interface
2448 * 4. Is a type that should not be reported (node local
2449 * or all node link local multicast.
2450 * All other groups enter the appropriate state machine
2451 * for the version in use on this link.
2452 */
2453 if ((ifp->if_flags & IFF_LOOPBACK) ||
2454 (mli->mli_flags & MLIF_SILENT) ||
2455 (IFNET_IS_CELLULAR(ifp) &&
2456 (IN6_IS_ADDR_MC_LINKLOCAL(&inm->in6m_addr) || IN6_IS_ADDR_MC_UNICAST_BASED_LINKLOCAL(&inm->in6m_addr))) ||
2457 !mld_is_addr_reported(&inm->in6m_addr)) {
2458 MLD_PRINTF(("%s: not kicking state machine for silent group\n",
2459 __func__));
2460 inm->in6m_state = MLD_SILENT_MEMBER;
2461 inm->in6m_timer = 0;
2462 } else {
2463 /*
2464 * Deal with overlapping in6_multi lifecycle.
2465 * If this group was LEAVING, then make sure
2466 * we drop the reference we picked up to keep the
2467 * group around for the final INCLUDE {} enqueue.
2468 * Since we cannot call in6_multi_detach() here,
2469 * defer this task to the timer routine.
2470 */
2471 if (mli->mli_version == MLD_VERSION_2 &&
2472 inm->in6m_state == MLD_LEAVING_MEMBER) {
2473 VERIFY(inm->in6m_nrelecnt != 0);
2474 SLIST_INSERT_HEAD(&mli->mli_relinmhead, inm,
2475 in6m_nrele);
2476 }
2477
2478 inm->in6m_state = MLD_REPORTING_MEMBER;
2479
2480 switch (mli->mli_version) {
2481 case MLD_VERSION_1:
2482 /*
2483 * If a delay was provided, only use it if
2484 * it is greater than the delay normally
2485 * used for an MLDv1 state change report,
2486 * and delay sending the initial MLDv1 report
2487 * by not transitioning to the IDLE state.
2488 */
2489 odelay = MLD_RANDOM_DELAY(MLD_V1_MAX_RI);
2490 if (delay) {
2491 inm->in6m_timer = max(delay, odelay);
2492 mtp->cst = 1;
2493 } else {
2494 inm->in6m_state = MLD_IDLE_MEMBER;
2495 error = mld_v1_transmit_report(inm,
2496 MLD_LISTENER_REPORT);
2497
2498 IN6M_LOCK_ASSERT_HELD(inm);
2499 MLI_LOCK_ASSERT_HELD(mli);
2500
2501 if (error == 0) {
2502 inm->in6m_timer = odelay;
2503 mtp->cst = 1;
2504 }
2505 }
2506 break;
2507
2508 case MLD_VERSION_2:
2509 /*
2510 * Defer update of T0 to T1, until the first copy
2511 * of the state change has been transmitted.
2512 */
2513 syncstates = 0;
2514
2515 /*
2516 * Immediately enqueue a State-Change Report for
2517 * this interface, freeing any previous reports.
2518 * Don't kick the timers if there is nothing to do,
2519 * or if an error occurred.
2520 */
2521 ifq = &inm->in6m_scq;
2522 IF_DRAIN(ifq);
2523 retval = mld_v2_enqueue_group_record(ifq, inm, 1,
2524 0, 0, (mli->mli_flags & MLIF_USEALLOW));
2525 mtp->cst = (ifq->ifq_len > 0);
2526 MLD_PRINTF(("%s: enqueue record = %d\n",
2527 __func__, retval));
2528 if (retval <= 0) {
2529 error = retval * -1;
2530 break;
2531 }
2532
2533 /*
2534 * Schedule transmission of pending state-change
2535 * report up to RV times for this link. The timer
2536 * will fire at the next mld_timeout (1 second)),
2537 * giving us an opportunity to merge the reports.
2538 *
2539 * If a delay was provided to this function, only
2540 * use this delay if sooner than the existing one.
2541 */
2542 VERIFY(mli->mli_rv > 1);
2543 inm->in6m_scrv = (uint16_t)mli->mli_rv;
2544 if (delay) {
2545 if (inm->in6m_sctimer > 1) {
2546 inm->in6m_sctimer =
2547 MIN(inm->in6m_sctimer, (uint16_t)delay);
2548 } else {
2549 inm->in6m_sctimer = (uint16_t)delay;
2550 }
2551 } else {
2552 inm->in6m_sctimer = 1;
2553 }
2554 mtp->sct = 1;
2555 error = 0;
2556 break;
2557 }
2558 }
2559 MLI_UNLOCK(mli);
2560
2561 /*
2562 * Only update the T0 state if state change is atomic,
2563 * i.e. we don't need to wait for a timer to fire before we
2564 * can consider the state change to have been communicated.
2565 */
2566 if (syncstates) {
2567 in6m_commit(inm);
2568 MLD_PRINTF(("%s: T1 -> T0 for %s/%s\n", __func__,
2569 ip6_sprintf(&inm->in6m_addr),
2570 if_name(inm->in6m_ifp)));
2571 }
2572
2573 return error;
2574 }
2575
2576 /*
2577 * Issue an intermediate state change during the life-cycle.
2578 */
2579 static int
mld_handle_state_change(struct in6_multi * inm,struct mld_ifinfo * mli,struct mld_tparams * mtp)2580 mld_handle_state_change(struct in6_multi *inm, struct mld_ifinfo *mli,
2581 struct mld_tparams *mtp)
2582 {
2583 struct ifnet *ifp;
2584 int retval = 0;
2585
2586 IN6M_LOCK_ASSERT_HELD(inm);
2587 MLI_LOCK_ASSERT_NOTHELD(mli);
2588 VERIFY(mtp != NULL);
2589
2590 MLD_PRINTF(("%s: state change for %s on ifp 0x%llx(%s)\n",
2591 __func__, ip6_sprintf(&inm->in6m_addr),
2592 (uint64_t)VM_KERNEL_ADDRPERM(inm->in6m_ifp),
2593 if_name(inm->in6m_ifp)));
2594
2595 ifp = inm->in6m_ifp;
2596
2597 MLI_LOCK(mli);
2598 VERIFY(mli->mli_ifp == ifp);
2599
2600 if ((ifp->if_flags & IFF_LOOPBACK) ||
2601 (mli->mli_flags & MLIF_SILENT) ||
2602 !mld_is_addr_reported(&inm->in6m_addr) ||
2603 (mli->mli_version != MLD_VERSION_2)) {
2604 MLI_UNLOCK(mli);
2605 if (!mld_is_addr_reported(&inm->in6m_addr)) {
2606 MLD_PRINTF(("%s: not kicking state machine for silent "
2607 "group\n", __func__));
2608 }
2609 MLD_PRINTF(("%s: nothing to do\n", __func__));
2610 in6m_commit(inm);
2611 MLD_PRINTF(("%s: T1 -> T0 for %s/%s\n", __func__,
2612 ip6_sprintf(&inm->in6m_addr),
2613 if_name(inm->in6m_ifp)));
2614 goto done;
2615 }
2616
2617 IF_DRAIN(&inm->in6m_scq);
2618
2619 retval = mld_v2_enqueue_group_record(&inm->in6m_scq, inm, 1, 0, 0,
2620 (mli->mli_flags & MLIF_USEALLOW));
2621 mtp->cst = (inm->in6m_scq.ifq_len > 0);
2622 MLD_PRINTF(("%s: enqueue record = %d\n", __func__, retval));
2623 if (retval <= 0) {
2624 MLI_UNLOCK(mli);
2625 retval *= -1;
2626 goto done;
2627 } else {
2628 retval = 0;
2629 }
2630
2631 /*
2632 * If record(s) were enqueued, start the state-change
2633 * report timer for this group.
2634 */
2635 inm->in6m_scrv = (uint16_t)mli->mli_rv;
2636 inm->in6m_sctimer = 1;
2637 mtp->sct = 1;
2638 MLI_UNLOCK(mli);
2639
2640 done:
2641 return retval;
2642 }
2643
2644 /*
2645 * Perform the final leave for a multicast address.
2646 *
2647 * When leaving a group:
2648 * MLDv1 sends a DONE message, if and only if we are the reporter.
2649 * MLDv2 enqueues a state-change report containing a transition
2650 * to INCLUDE {} for immediate transmission.
2651 */
2652 static void
mld_final_leave(struct in6_multi * inm,struct mld_ifinfo * mli,struct mld_tparams * mtp)2653 mld_final_leave(struct in6_multi *inm, struct mld_ifinfo *mli,
2654 struct mld_tparams *mtp)
2655 {
2656 int syncstates = 1;
2657
2658 IN6M_LOCK_ASSERT_HELD(inm);
2659 MLI_LOCK_ASSERT_NOTHELD(mli);
2660 VERIFY(mtp != NULL);
2661
2662 MLD_PRINTF(("%s: final leave %s on ifp 0x%llx(%s)\n",
2663 __func__, ip6_sprintf(&inm->in6m_addr),
2664 (uint64_t)VM_KERNEL_ADDRPERM(inm->in6m_ifp),
2665 if_name(inm->in6m_ifp)));
2666
2667 switch (inm->in6m_state) {
2668 case MLD_NOT_MEMBER:
2669 case MLD_SILENT_MEMBER:
2670 case MLD_LEAVING_MEMBER:
2671 /* Already leaving or left; do nothing. */
2672 MLD_PRINTF(("%s: not kicking state machine for silent group\n",
2673 __func__));
2674 break;
2675 case MLD_REPORTING_MEMBER:
2676 case MLD_IDLE_MEMBER:
2677 case MLD_G_QUERY_PENDING_MEMBER:
2678 case MLD_SG_QUERY_PENDING_MEMBER:
2679 MLI_LOCK(mli);
2680 if (mli->mli_version == MLD_VERSION_1) {
2681 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER ||
2682 inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER) {
2683 panic("%s: MLDv2 state reached, not MLDv2 "
2684 "mode\n", __func__);
2685 /* NOTREACHED */
2686 }
2687 /* scheduler timer if enqueue is successful */
2688 mtp->cst = (mld_v1_transmit_report(inm,
2689 MLD_LISTENER_DONE) == 0);
2690
2691 IN6M_LOCK_ASSERT_HELD(inm);
2692 MLI_LOCK_ASSERT_HELD(mli);
2693
2694 inm->in6m_state = MLD_NOT_MEMBER;
2695 } else if (mli->mli_version == MLD_VERSION_2) {
2696 /*
2697 * Stop group timer and all pending reports.
2698 * Immediately enqueue a state-change report
2699 * TO_IN {} to be sent on the next timeout,
2700 * giving us an opportunity to merge reports.
2701 */
2702 IF_DRAIN(&inm->in6m_scq);
2703 inm->in6m_timer = 0;
2704 inm->in6m_scrv = (uint16_t)mli->mli_rv;
2705 MLD_PRINTF(("%s: Leaving %s/%s with %d "
2706 "pending retransmissions.\n", __func__,
2707 ip6_sprintf(&inm->in6m_addr),
2708 if_name(inm->in6m_ifp),
2709 inm->in6m_scrv));
2710 if (inm->in6m_scrv == 0) {
2711 inm->in6m_state = MLD_NOT_MEMBER;
2712 inm->in6m_sctimer = 0;
2713 } else {
2714 int retval;
2715 /*
2716 * Stick around in the in6_multihead list;
2717 * the final detach will be issued by
2718 * mld_v2_process_group_timers() when
2719 * the retransmit timer expires.
2720 */
2721 IN6M_ADDREF_LOCKED(inm);
2722 VERIFY(inm->in6m_debug & IFD_ATTACHED);
2723 inm->in6m_reqcnt++;
2724 VERIFY(inm->in6m_reqcnt >= 1);
2725 inm->in6m_nrelecnt++;
2726 VERIFY(inm->in6m_nrelecnt != 0);
2727
2728 retval = mld_v2_enqueue_group_record(
2729 &inm->in6m_scq, inm, 1, 0, 0,
2730 (mli->mli_flags & MLIF_USEALLOW));
2731 mtp->cst = (inm->in6m_scq.ifq_len > 0);
2732 KASSERT(retval != 0,
2733 ("%s: enqueue record = %d\n", __func__,
2734 retval));
2735
2736 inm->in6m_state = MLD_LEAVING_MEMBER;
2737 inm->in6m_sctimer = 1;
2738 mtp->sct = 1;
2739 syncstates = 0;
2740 }
2741 }
2742 MLI_UNLOCK(mli);
2743 break;
2744 case MLD_LAZY_MEMBER:
2745 case MLD_SLEEPING_MEMBER:
2746 case MLD_AWAKENING_MEMBER:
2747 /* Our reports are suppressed; do nothing. */
2748 break;
2749 }
2750
2751 if (syncstates) {
2752 in6m_commit(inm);
2753 MLD_PRINTF(("%s: T1 -> T0 for %s/%s\n", __func__,
2754 ip6_sprintf(&inm->in6m_addr),
2755 if_name(inm->in6m_ifp)));
2756 inm->in6m_st[1].iss_fmode = MCAST_UNDEFINED;
2757 MLD_PRINTF(("%s: T1 now MCAST_UNDEFINED for 0x%llx/%s\n",
2758 __func__, (uint64_t)VM_KERNEL_ADDRPERM(&inm->in6m_addr),
2759 if_name(inm->in6m_ifp)));
2760 }
2761 }
2762
2763 /*
2764 * Enqueue an MLDv2 group record to the given output queue.
2765 *
2766 * If is_state_change is zero, a current-state record is appended.
2767 * If is_state_change is non-zero, a state-change report is appended.
2768 *
2769 * If is_group_query is non-zero, an mbuf packet chain is allocated.
2770 * If is_group_query is zero, and if there is a packet with free space
2771 * at the tail of the queue, it will be appended to providing there
2772 * is enough free space.
2773 * Otherwise a new mbuf packet chain is allocated.
2774 *
2775 * If is_source_query is non-zero, each source is checked to see if
2776 * it was recorded for a Group-Source query, and will be omitted if
2777 * it is not both in-mode and recorded.
2778 *
2779 * If use_block_allow is non-zero, state change reports for initial join
2780 * and final leave, on an inclusive mode group with a source list, will be
2781 * rewritten to use the ALLOW_NEW and BLOCK_OLD record types, respectively.
2782 *
2783 * The function will attempt to allocate leading space in the packet
2784 * for the IPv6+ICMP headers to be prepended without fragmenting the chain.
2785 *
2786 * If successful the size of all data appended to the queue is returned,
2787 * otherwise an error code less than zero is returned, or zero if
2788 * no record(s) were appended.
2789 */
2790 static int
mld_v2_enqueue_group_record(struct ifqueue * ifq,struct in6_multi * inm,const int is_state_change,const int is_group_query,const int is_source_query,const int use_block_allow)2791 mld_v2_enqueue_group_record(struct ifqueue *ifq, struct in6_multi *inm,
2792 const int is_state_change, const int is_group_query,
2793 const int is_source_query, const int use_block_allow)
2794 {
2795 struct mldv2_record mr;
2796 struct mldv2_record *pmr;
2797 struct ifnet *ifp;
2798 struct ip6_msource *ims, *nims;
2799 struct mbuf *m0, *m, *md;
2800 int error, is_filter_list_change;
2801 int minrec0len, m0srcs, msrcs, nbytes, off;
2802 int record_has_sources;
2803 int now;
2804 uint8_t type;
2805 uint8_t mode;
2806
2807 IN6M_LOCK_ASSERT_HELD(inm);
2808 MLI_LOCK_ASSERT_HELD(inm->in6m_mli);
2809
2810 error = 0;
2811 ifp = inm->in6m_ifp;
2812 is_filter_list_change = 0;
2813 m = NULL;
2814 m0 = NULL;
2815 m0srcs = 0;
2816 msrcs = 0;
2817 nbytes = 0;
2818 nims = NULL;
2819 record_has_sources = 1;
2820 pmr = NULL;
2821 type = MLD_DO_NOTHING;
2822 mode = (uint8_t)inm->in6m_st[1].iss_fmode;
2823
2824 /*
2825 * If we did not transition out of ASM mode during t0->t1,
2826 * and there are no source nodes to process, we can skip
2827 * the generation of source records.
2828 */
2829 if (inm->in6m_st[0].iss_asm > 0 && inm->in6m_st[1].iss_asm > 0 &&
2830 inm->in6m_nsrc == 0) {
2831 record_has_sources = 0;
2832 }
2833
2834 if (is_state_change) {
2835 /*
2836 * Queue a state change record.
2837 * If the mode did not change, and there are non-ASM
2838 * listeners or source filters present,
2839 * we potentially need to issue two records for the group.
2840 * If there are ASM listeners, and there was no filter
2841 * mode transition of any kind, do nothing.
2842 *
2843 * If we are transitioning to MCAST_UNDEFINED, we need
2844 * not send any sources. A transition to/from this state is
2845 * considered inclusive with some special treatment.
2846 *
2847 * If we are rewriting initial joins/leaves to use
2848 * ALLOW/BLOCK, and the group's membership is inclusive,
2849 * we need to send sources in all cases.
2850 */
2851 if (mode != inm->in6m_st[0].iss_fmode) {
2852 if (mode == MCAST_EXCLUDE) {
2853 MLD_PRINTF(("%s: change to EXCLUDE\n",
2854 __func__));
2855 type = MLD_CHANGE_TO_EXCLUDE_MODE;
2856 } else {
2857 MLD_PRINTF(("%s: change to INCLUDE\n",
2858 __func__));
2859 if (use_block_allow) {
2860 /*
2861 * XXX
2862 * Here we're interested in state
2863 * edges either direction between
2864 * MCAST_UNDEFINED and MCAST_INCLUDE.
2865 * Perhaps we should just check
2866 * the group state, rather than
2867 * the filter mode.
2868 */
2869 if (mode == MCAST_UNDEFINED) {
2870 type = MLD_BLOCK_OLD_SOURCES;
2871 } else {
2872 type = MLD_ALLOW_NEW_SOURCES;
2873 }
2874 } else {
2875 type = MLD_CHANGE_TO_INCLUDE_MODE;
2876 if (mode == MCAST_UNDEFINED) {
2877 record_has_sources = 0;
2878 }
2879 }
2880 }
2881 } else {
2882 if (record_has_sources) {
2883 is_filter_list_change = 1;
2884 } else {
2885 type = MLD_DO_NOTHING;
2886 }
2887 }
2888 } else {
2889 /*
2890 * Queue a current state record.
2891 */
2892 if (mode == MCAST_EXCLUDE) {
2893 type = MLD_MODE_IS_EXCLUDE;
2894 } else if (mode == MCAST_INCLUDE) {
2895 type = MLD_MODE_IS_INCLUDE;
2896 VERIFY(inm->in6m_st[1].iss_asm == 0);
2897 }
2898 }
2899
2900 /*
2901 * Generate the filter list changes using a separate function.
2902 */
2903 if (is_filter_list_change) {
2904 return mld_v2_enqueue_filter_change(ifq, inm);
2905 }
2906
2907 if (type == MLD_DO_NOTHING) {
2908 MLD_PRINTF(("%s: nothing to do for %s/%s\n",
2909 __func__, ip6_sprintf(&inm->in6m_addr),
2910 if_name(inm->in6m_ifp)));
2911 return 0;
2912 }
2913
2914 /*
2915 * If any sources are present, we must be able to fit at least
2916 * one in the trailing space of the tail packet's mbuf,
2917 * ideally more.
2918 */
2919 minrec0len = sizeof(struct mldv2_record);
2920 if (record_has_sources) {
2921 minrec0len += sizeof(struct in6_addr);
2922 }
2923 MLD_PRINTF(("%s: queueing %s for %s/%s\n", __func__,
2924 mld_rec_type_to_str(type),
2925 ip6_sprintf(&inm->in6m_addr),
2926 if_name(inm->in6m_ifp)));
2927
2928 /*
2929 * Check if we have a packet in the tail of the queue for this
2930 * group into which the first group record for this group will fit.
2931 * Otherwise allocate a new packet.
2932 * Always allocate leading space for IP6+RA+ICMPV6+REPORT.
2933 * Note: Group records for G/GSR query responses MUST be sent
2934 * in their own packet.
2935 */
2936 m0 = ifq->ifq_tail;
2937 if (!is_group_query &&
2938 m0 != NULL &&
2939 (m0->m_pkthdr.vt_nrecs + 1 <= MLD_V2_REPORT_MAXRECS) &&
2940 (m0->m_pkthdr.len + minrec0len) <
2941 (ifp->if_mtu - MLD_MTUSPACE)) {
2942 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len -
2943 sizeof(struct mldv2_record)) /
2944 sizeof(struct in6_addr);
2945 m = m0;
2946 MLD_PRINTF(("%s: use existing packet\n", __func__));
2947 } else {
2948 if (IF_QFULL(ifq)) {
2949 MLD_PRINTF(("%s: outbound queue full\n", __func__));
2950 return -ENOMEM;
2951 }
2952 m = NULL;
2953 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
2954 sizeof(struct mldv2_record)) / sizeof(struct in6_addr);
2955 if (!is_state_change && !is_group_query) {
2956 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2957 }
2958 if (m == NULL) {
2959 m = m_gethdr(M_DONTWAIT, MT_DATA);
2960 }
2961 if (m == NULL) {
2962 return -ENOMEM;
2963 }
2964
2965 mld_save_context(m, ifp);
2966
2967 MLD_PRINTF(("%s: allocated first packet\n", __func__));
2968 }
2969
2970 /*
2971 * Append group record.
2972 * If we have sources, we don't know how many yet.
2973 */
2974 mr.mr_type = type;
2975 mr.mr_datalen = 0;
2976 mr.mr_numsrc = 0;
2977 mr.mr_addr = inm->in6m_addr;
2978 in6_clearscope(&mr.mr_addr);
2979 if (!m_append(m, sizeof(struct mldv2_record), (void *)&mr)) {
2980 if (m != m0) {
2981 m_freem(m);
2982 }
2983 MLD_PRINTF(("%s: m_append() failed.\n", __func__));
2984 return -ENOMEM;
2985 }
2986 nbytes += sizeof(struct mldv2_record);
2987
2988 /*
2989 * Append as many sources as will fit in the first packet.
2990 * If we are appending to a new packet, the chain allocation
2991 * may potentially use clusters; use m_getptr() in this case.
2992 * If we are appending to an existing packet, we need to obtain
2993 * a pointer to the group record after m_append(), in case a new
2994 * mbuf was allocated.
2995 *
2996 * Only append sources which are in-mode at t1. If we are
2997 * transitioning to MCAST_UNDEFINED state on the group, and
2998 * use_block_allow is zero, do not include source entries.
2999 * Otherwise, we need to include this source in the report.
3000 *
3001 * Only report recorded sources in our filter set when responding
3002 * to a group-source query.
3003 */
3004 if (record_has_sources) {
3005 if (m == m0) {
3006 md = m_last(m);
3007 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) +
3008 md->m_len - nbytes);
3009 } else {
3010 md = m_getptr(m, 0, &off);
3011 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) +
3012 off);
3013 }
3014 msrcs = 0;
3015 RB_FOREACH_SAFE(ims, ip6_msource_tree, &inm->in6m_srcs,
3016 nims) {
3017 MLD_PRINTF(("%s: visit node %s\n", __func__,
3018 ip6_sprintf(&ims->im6s_addr)));
3019 now = im6s_get_mode(inm, ims, 1);
3020 MLD_PRINTF(("%s: node is %d\n", __func__, now));
3021 if ((now != mode) ||
3022 (now == mode &&
3023 (!use_block_allow && mode == MCAST_UNDEFINED))) {
3024 MLD_PRINTF(("%s: skip node\n", __func__));
3025 continue;
3026 }
3027 if (is_source_query && ims->im6s_stp == 0) {
3028 MLD_PRINTF(("%s: skip unrecorded node\n",
3029 __func__));
3030 continue;
3031 }
3032 MLD_PRINTF(("%s: append node\n", __func__));
3033 if (!m_append(m, sizeof(struct in6_addr),
3034 (void *)&ims->im6s_addr)) {
3035 if (m != m0) {
3036 m_freem(m);
3037 }
3038 MLD_PRINTF(("%s: m_append() failed.\n",
3039 __func__));
3040 return -ENOMEM;
3041 }
3042 nbytes += sizeof(struct in6_addr);
3043 ++msrcs;
3044 if (msrcs == m0srcs) {
3045 break;
3046 }
3047 }
3048 MLD_PRINTF(("%s: msrcs is %d this packet\n", __func__,
3049 msrcs));
3050 pmr->mr_numsrc = htons((uint16_t)msrcs);
3051 nbytes += (msrcs * sizeof(struct in6_addr));
3052 }
3053
3054 if (is_source_query && msrcs == 0) {
3055 MLD_PRINTF(("%s: no recorded sources to report\n", __func__));
3056 if (m != m0) {
3057 m_freem(m);
3058 }
3059 return 0;
3060 }
3061
3062 /*
3063 * We are good to go with first packet.
3064 */
3065 if (m != m0) {
3066 MLD_PRINTF(("%s: enqueueing first packet\n", __func__));
3067 m->m_pkthdr.vt_nrecs = 1;
3068 IF_ENQUEUE(ifq, m);
3069 } else {
3070 m->m_pkthdr.vt_nrecs++;
3071 }
3072 /*
3073 * No further work needed if no source list in packet(s).
3074 */
3075 if (!record_has_sources) {
3076 return nbytes;
3077 }
3078
3079 /*
3080 * Whilst sources remain to be announced, we need to allocate
3081 * a new packet and fill out as many sources as will fit.
3082 * Always try for a cluster first.
3083 */
3084 while (nims != NULL) {
3085 if (IF_QFULL(ifq)) {
3086 MLD_PRINTF(("%s: outbound queue full\n", __func__));
3087 return -ENOMEM;
3088 }
3089 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
3090 if (m == NULL) {
3091 m = m_gethdr(M_DONTWAIT, MT_DATA);
3092 }
3093 if (m == NULL) {
3094 return -ENOMEM;
3095 }
3096 mld_save_context(m, ifp);
3097 md = m_getptr(m, 0, &off);
3098 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) + off);
3099 MLD_PRINTF(("%s: allocated next packet\n", __func__));
3100
3101 if (!m_append(m, sizeof(struct mldv2_record), (void *)&mr)) {
3102 if (m != m0) {
3103 m_freem(m);
3104 }
3105 MLD_PRINTF(("%s: m_append() failed.\n", __func__));
3106 return -ENOMEM;
3107 }
3108 m->m_pkthdr.vt_nrecs = 1;
3109 nbytes += sizeof(struct mldv2_record);
3110
3111 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
3112 sizeof(struct mldv2_record)) / sizeof(struct in6_addr);
3113
3114 msrcs = 0;
3115 RB_FOREACH_FROM(ims, ip6_msource_tree, nims) {
3116 MLD_PRINTF(("%s: visit node %s\n",
3117 __func__, ip6_sprintf(&ims->im6s_addr)));
3118 now = im6s_get_mode(inm, ims, 1);
3119 if ((now != mode) ||
3120 (now == mode &&
3121 (!use_block_allow && mode == MCAST_UNDEFINED))) {
3122 MLD_PRINTF(("%s: skip node\n", __func__));
3123 continue;
3124 }
3125 if (is_source_query && ims->im6s_stp == 0) {
3126 MLD_PRINTF(("%s: skip unrecorded node\n",
3127 __func__));
3128 continue;
3129 }
3130 MLD_PRINTF(("%s: append node\n", __func__));
3131 if (!m_append(m, sizeof(struct in6_addr),
3132 (void *)&ims->im6s_addr)) {
3133 if (m != m0) {
3134 m_freem(m);
3135 }
3136 MLD_PRINTF(("%s: m_append() failed.\n",
3137 __func__));
3138 return -ENOMEM;
3139 }
3140 ++msrcs;
3141 if (msrcs == m0srcs) {
3142 break;
3143 }
3144 }
3145 pmr->mr_numsrc = htons((uint16_t)msrcs);
3146 nbytes += (msrcs * sizeof(struct in6_addr));
3147
3148 MLD_PRINTF(("%s: enqueueing next packet\n", __func__));
3149 IF_ENQUEUE(ifq, m);
3150 }
3151
3152 return nbytes;
3153 }
3154
3155 /*
3156 * Type used to mark record pass completion.
3157 * We exploit the fact we can cast to this easily from the
3158 * current filter modes on each ip_msource node.
3159 */
3160 typedef enum {
3161 REC_NONE = 0x00, /* MCAST_UNDEFINED */
3162 REC_ALLOW = 0x01, /* MCAST_INCLUDE */
3163 REC_BLOCK = 0x02, /* MCAST_EXCLUDE */
3164 REC_FULL = REC_ALLOW | REC_BLOCK
3165 } rectype_t;
3166
3167 /*
3168 * Enqueue an MLDv2 filter list change to the given output queue.
3169 *
3170 * Source list filter state is held in an RB-tree. When the filter list
3171 * for a group is changed without changing its mode, we need to compute
3172 * the deltas between T0 and T1 for each source in the filter set,
3173 * and enqueue the appropriate ALLOW_NEW/BLOCK_OLD records.
3174 *
3175 * As we may potentially queue two record types, and the entire R-B tree
3176 * needs to be walked at once, we break this out into its own function
3177 * so we can generate a tightly packed queue of packets.
3178 *
3179 * XXX This could be written to only use one tree walk, although that makes
3180 * serializing into the mbuf chains a bit harder. For now we do two walks
3181 * which makes things easier on us, and it may or may not be harder on
3182 * the L2 cache.
3183 *
3184 * If successful the size of all data appended to the queue is returned,
3185 * otherwise an error code less than zero is returned, or zero if
3186 * no record(s) were appended.
3187 */
3188 static int
mld_v2_enqueue_filter_change(struct ifqueue * ifq,struct in6_multi * inm)3189 mld_v2_enqueue_filter_change(struct ifqueue *ifq, struct in6_multi *inm)
3190 {
3191 static const int MINRECLEN =
3192 sizeof(struct mldv2_record) + sizeof(struct in6_addr);
3193 struct ifnet *ifp;
3194 struct mldv2_record mr;
3195 struct mldv2_record *pmr;
3196 struct ip6_msource *ims, *nims;
3197 struct mbuf *m, *m0, *md;
3198 int m0srcs, nbytes, npbytes, off, rsrcs, schanged;
3199 int nallow, nblock;
3200 uint8_t mode, now, then;
3201 rectype_t crt, drt, nrt;
3202
3203 IN6M_LOCK_ASSERT_HELD(inm);
3204
3205 if (inm->in6m_nsrc == 0 ||
3206 (inm->in6m_st[0].iss_asm > 0 && inm->in6m_st[1].iss_asm > 0)) {
3207 return 0;
3208 }
3209
3210 ifp = inm->in6m_ifp; /* interface */
3211 mode = (uint8_t)inm->in6m_st[1].iss_fmode; /* filter mode at t1 */
3212 crt = REC_NONE; /* current group record type */
3213 drt = REC_NONE; /* mask of completed group record types */
3214 nrt = REC_NONE; /* record type for current node */
3215 m0srcs = 0; /* # source which will fit in current mbuf chain */
3216 npbytes = 0; /* # of bytes appended this packet */
3217 nbytes = 0; /* # of bytes appended to group's state-change queue */
3218 rsrcs = 0; /* # sources encoded in current record */
3219 schanged = 0; /* # nodes encoded in overall filter change */
3220 nallow = 0; /* # of source entries in ALLOW_NEW */
3221 nblock = 0; /* # of source entries in BLOCK_OLD */
3222 nims = NULL; /* next tree node pointer */
3223
3224 /*
3225 * For each possible filter record mode.
3226 * The first kind of source we encounter tells us which
3227 * is the first kind of record we start appending.
3228 * If a node transitioned to UNDEFINED at t1, its mode is treated
3229 * as the inverse of the group's filter mode.
3230 */
3231 while (drt != REC_FULL) {
3232 do {
3233 m0 = ifq->ifq_tail;
3234 if (m0 != NULL &&
3235 (m0->m_pkthdr.vt_nrecs + 1 <=
3236 MLD_V2_REPORT_MAXRECS) &&
3237 (m0->m_pkthdr.len + MINRECLEN) <
3238 (ifp->if_mtu - MLD_MTUSPACE)) {
3239 m = m0;
3240 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len -
3241 sizeof(struct mldv2_record)) /
3242 sizeof(struct in6_addr);
3243 MLD_PRINTF(("%s: use previous packet\n",
3244 __func__));
3245 } else {
3246 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
3247 if (m == NULL) {
3248 m = m_gethdr(M_DONTWAIT, MT_DATA);
3249 }
3250 if (m == NULL) {
3251 MLD_PRINTF(("%s: m_get*() failed\n",
3252 __func__));
3253 return -ENOMEM;
3254 }
3255 m->m_pkthdr.vt_nrecs = 0;
3256 mld_save_context(m, ifp);
3257 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
3258 sizeof(struct mldv2_record)) /
3259 sizeof(struct in6_addr);
3260 npbytes = 0;
3261 MLD_PRINTF(("%s: allocated new packet\n",
3262 __func__));
3263 }
3264 /*
3265 * Append the MLD group record header to the
3266 * current packet's data area.
3267 * Recalculate pointer to free space for next
3268 * group record, in case m_append() allocated
3269 * a new mbuf or cluster.
3270 */
3271 memset(&mr, 0, sizeof(mr));
3272 mr.mr_addr = inm->in6m_addr;
3273 in6_clearscope(&mr.mr_addr);
3274 if (!m_append(m, sizeof(mr), (void *)&mr)) {
3275 if (m != m0) {
3276 m_freem(m);
3277 }
3278 MLD_PRINTF(("%s: m_append() failed\n",
3279 __func__));
3280 return -ENOMEM;
3281 }
3282 npbytes += sizeof(struct mldv2_record);
3283 if (m != m0) {
3284 /* new packet; offset in chain */
3285 md = m_getptr(m, npbytes -
3286 sizeof(struct mldv2_record), &off);
3287 pmr = (struct mldv2_record *)(mtod(md,
3288 uint8_t *) + off);
3289 } else {
3290 /* current packet; offset from last append */
3291 md = m_last(m);
3292 pmr = (struct mldv2_record *)(mtod(md,
3293 uint8_t *) + md->m_len -
3294 sizeof(struct mldv2_record));
3295 }
3296 /*
3297 * Begin walking the tree for this record type
3298 * pass, or continue from where we left off
3299 * previously if we had to allocate a new packet.
3300 * Only report deltas in-mode at t1.
3301 * We need not report included sources as allowed
3302 * if we are in inclusive mode on the group,
3303 * however the converse is not true.
3304 */
3305 rsrcs = 0;
3306 if (nims == NULL) {
3307 nims = RB_MIN(ip6_msource_tree,
3308 &inm->in6m_srcs);
3309 }
3310 RB_FOREACH_FROM(ims, ip6_msource_tree, nims) {
3311 MLD_PRINTF(("%s: visit node %s\n", __func__,
3312 ip6_sprintf(&ims->im6s_addr)));
3313 now = im6s_get_mode(inm, ims, 1);
3314 then = im6s_get_mode(inm, ims, 0);
3315 MLD_PRINTF(("%s: mode: t0 %d, t1 %d\n",
3316 __func__, then, now));
3317 if (now == then) {
3318 MLD_PRINTF(("%s: skip unchanged\n",
3319 __func__));
3320 continue;
3321 }
3322 if (mode == MCAST_EXCLUDE &&
3323 now == MCAST_INCLUDE) {
3324 MLD_PRINTF(("%s: skip IN src on EX "
3325 "group\n", __func__));
3326 continue;
3327 }
3328 nrt = (rectype_t)now;
3329 if (nrt == REC_NONE) {
3330 nrt = (rectype_t)(~mode & REC_FULL);
3331 }
3332 if (schanged++ == 0) {
3333 crt = nrt;
3334 } else if (crt != nrt) {
3335 continue;
3336 }
3337 if (!m_append(m, sizeof(struct in6_addr),
3338 (void *)&ims->im6s_addr)) {
3339 if (m != m0) {
3340 m_freem(m);
3341 }
3342 MLD_PRINTF(("%s: m_append() failed\n",
3343 __func__));
3344 return -ENOMEM;
3345 }
3346 nallow += !!(crt == REC_ALLOW);
3347 nblock += !!(crt == REC_BLOCK);
3348 if (++rsrcs == m0srcs) {
3349 break;
3350 }
3351 }
3352 /*
3353 * If we did not append any tree nodes on this
3354 * pass, back out of allocations.
3355 */
3356 if (rsrcs == 0) {
3357 npbytes -= sizeof(struct mldv2_record);
3358 if (m != m0) {
3359 MLD_PRINTF(("%s: m_free(m)\n",
3360 __func__));
3361 m_freem(m);
3362 } else {
3363 MLD_PRINTF(("%s: m_adj(m, -mr)\n",
3364 __func__));
3365 m_adj(m, -((int)sizeof(
3366 struct mldv2_record)));
3367 }
3368 continue;
3369 }
3370 npbytes += (rsrcs * sizeof(struct in6_addr));
3371 if (crt == REC_ALLOW) {
3372 pmr->mr_type = MLD_ALLOW_NEW_SOURCES;
3373 } else if (crt == REC_BLOCK) {
3374 pmr->mr_type = MLD_BLOCK_OLD_SOURCES;
3375 }
3376 pmr->mr_numsrc = htons((uint16_t)rsrcs);
3377 /*
3378 * Count the new group record, and enqueue this
3379 * packet if it wasn't already queued.
3380 */
3381 m->m_pkthdr.vt_nrecs++;
3382 if (m != m0) {
3383 IF_ENQUEUE(ifq, m);
3384 }
3385 nbytes += npbytes;
3386 } while (nims != NULL);
3387 drt |= crt;
3388 crt = (~crt & REC_FULL);
3389 }
3390
3391 MLD_PRINTF(("%s: queued %d ALLOW_NEW, %d BLOCK_OLD\n", __func__,
3392 nallow, nblock));
3393
3394 return nbytes;
3395 }
3396
3397 static int
mld_v2_merge_state_changes(struct in6_multi * inm,struct ifqueue * ifscq)3398 mld_v2_merge_state_changes(struct in6_multi *inm, struct ifqueue *ifscq)
3399 {
3400 struct ifqueue *gq;
3401 struct mbuf *m; /* pending state-change */
3402 struct mbuf *m0; /* copy of pending state-change */
3403 struct mbuf *mt; /* last state-change in packet */
3404 struct mbuf *n;
3405 int docopy, domerge;
3406 u_int recslen;
3407
3408 IN6M_LOCK_ASSERT_HELD(inm);
3409
3410 docopy = 0;
3411 domerge = 0;
3412 recslen = 0;
3413
3414 /*
3415 * If there are further pending retransmissions, make a writable
3416 * copy of each queued state-change message before merging.
3417 */
3418 if (inm->in6m_scrv > 0) {
3419 docopy = 1;
3420 }
3421
3422 gq = &inm->in6m_scq;
3423 #ifdef MLD_DEBUG
3424 if (gq->ifq_head == NULL) {
3425 MLD_PRINTF(("%s: WARNING: queue for inm 0x%llx is empty\n",
3426 __func__, (uint64_t)VM_KERNEL_ADDRPERM(inm)));
3427 }
3428 #endif
3429
3430 /*
3431 * Use IF_REMQUEUE() instead of IF_DEQUEUE() below, since the
3432 * packet might not always be at the head of the ifqueue.
3433 */
3434 m = gq->ifq_head;
3435 while (m != NULL) {
3436 /*
3437 * Only merge the report into the current packet if
3438 * there is sufficient space to do so; an MLDv2 report
3439 * packet may only contain 65,535 group records.
3440 * Always use a simple mbuf chain concatentation to do this,
3441 * as large state changes for single groups may have
3442 * allocated clusters.
3443 */
3444 domerge = 0;
3445 mt = ifscq->ifq_tail;
3446 if (mt != NULL) {
3447 recslen = m_length(m);
3448
3449 if ((mt->m_pkthdr.vt_nrecs +
3450 m->m_pkthdr.vt_nrecs <=
3451 MLD_V2_REPORT_MAXRECS) &&
3452 (mt->m_pkthdr.len + recslen <=
3453 (inm->in6m_ifp->if_mtu - MLD_MTUSPACE))) {
3454 domerge = 1;
3455 }
3456 }
3457
3458 if (!domerge && IF_QFULL(gq)) {
3459 MLD_PRINTF(("%s: outbound queue full, skipping whole "
3460 "packet 0x%llx\n", __func__,
3461 (uint64_t)VM_KERNEL_ADDRPERM(m)));
3462 n = m->m_nextpkt;
3463 if (!docopy) {
3464 IF_REMQUEUE(gq, m);
3465 m_freem(m);
3466 }
3467 m = n;
3468 continue;
3469 }
3470
3471 if (!docopy) {
3472 MLD_PRINTF(("%s: dequeueing 0x%llx\n", __func__,
3473 (uint64_t)VM_KERNEL_ADDRPERM(m)));
3474 n = m->m_nextpkt;
3475 IF_REMQUEUE(gq, m);
3476 m0 = m;
3477 m = n;
3478 } else {
3479 MLD_PRINTF(("%s: copying 0x%llx\n", __func__,
3480 (uint64_t)VM_KERNEL_ADDRPERM(m)));
3481 m0 = m_dup(m, M_NOWAIT);
3482 if (m0 == NULL) {
3483 return ENOMEM;
3484 }
3485 m0->m_nextpkt = NULL;
3486 m = m->m_nextpkt;
3487 }
3488
3489 if (!domerge) {
3490 MLD_PRINTF(("%s: queueing 0x%llx to ifscq 0x%llx)\n",
3491 __func__, (uint64_t)VM_KERNEL_ADDRPERM(m0),
3492 (uint64_t)VM_KERNEL_ADDRPERM(ifscq)));
3493 IF_ENQUEUE(ifscq, m0);
3494 } else {
3495 struct mbuf *mtl; /* last mbuf of packet mt */
3496
3497 MLD_PRINTF(("%s: merging 0x%llx with ifscq tail "
3498 "0x%llx)\n", __func__,
3499 (uint64_t)VM_KERNEL_ADDRPERM(m0),
3500 (uint64_t)VM_KERNEL_ADDRPERM(mt)));
3501
3502 mtl = m_last(mt);
3503 m0->m_flags &= ~M_PKTHDR;
3504 mt->m_pkthdr.len += recslen;
3505 mt->m_pkthdr.vt_nrecs +=
3506 m0->m_pkthdr.vt_nrecs;
3507
3508 mtl->m_next = m0;
3509 }
3510 }
3511
3512 return 0;
3513 }
3514
3515 /*
3516 * Respond to a pending MLDv2 General Query.
3517 */
3518 static uint32_t
mld_v2_dispatch_general_query(struct mld_ifinfo * mli)3519 mld_v2_dispatch_general_query(struct mld_ifinfo *mli)
3520 {
3521 struct ifnet *ifp;
3522 struct in6_multi *inm;
3523 struct in6_multistep step;
3524 int retval;
3525
3526 MLI_LOCK_ASSERT_HELD(mli);
3527
3528 VERIFY(mli->mli_version == MLD_VERSION_2);
3529
3530 ifp = mli->mli_ifp;
3531 MLI_UNLOCK(mli);
3532
3533 in6_multihead_lock_shared();
3534 IN6_FIRST_MULTI(step, inm);
3535 while (inm != NULL) {
3536 IN6M_LOCK(inm);
3537 if (inm->in6m_ifp != ifp) {
3538 goto next;
3539 }
3540
3541 switch (inm->in6m_state) {
3542 case MLD_NOT_MEMBER:
3543 case MLD_SILENT_MEMBER:
3544 break;
3545 case MLD_REPORTING_MEMBER:
3546 case MLD_IDLE_MEMBER:
3547 case MLD_LAZY_MEMBER:
3548 case MLD_SLEEPING_MEMBER:
3549 case MLD_AWAKENING_MEMBER:
3550 inm->in6m_state = MLD_REPORTING_MEMBER;
3551 MLI_LOCK(mli);
3552 retval = mld_v2_enqueue_group_record(&mli->mli_gq,
3553 inm, 0, 0, 0, 0);
3554 MLI_UNLOCK(mli);
3555 MLD_PRINTF(("%s: enqueue record = %d\n",
3556 __func__, retval));
3557 break;
3558 case MLD_G_QUERY_PENDING_MEMBER:
3559 case MLD_SG_QUERY_PENDING_MEMBER:
3560 case MLD_LEAVING_MEMBER:
3561 break;
3562 }
3563 next:
3564 IN6M_UNLOCK(inm);
3565 IN6_NEXT_MULTI(step, inm);
3566 }
3567 in6_multihead_lock_done();
3568
3569 MLI_LOCK(mli);
3570 mld_dispatch_queue_locked(mli, &mli->mli_gq, MLD_MAX_RESPONSE_BURST);
3571 MLI_LOCK_ASSERT_HELD(mli);
3572
3573 /*
3574 * Slew transmission of bursts over 1 second intervals.
3575 */
3576 if (mli->mli_gq.ifq_head != NULL) {
3577 mli->mli_v2_timer = 1 + MLD_RANDOM_DELAY(
3578 MLD_RESPONSE_BURST_INTERVAL);
3579 }
3580
3581 return mli->mli_v2_timer;
3582 }
3583
3584 /*
3585 * Transmit the next pending message in the output queue.
3586 *
3587 * Must not be called with in6m_lockm or mli_lock held.
3588 */
3589 static void
mld_dispatch_packet(struct mbuf * m)3590 mld_dispatch_packet(struct mbuf *m)
3591 {
3592 struct ip6_moptions *im6o;
3593 struct ifnet *ifp;
3594 struct ifnet *oifp = NULL;
3595 struct mbuf *m0;
3596 struct mbuf *md;
3597 struct ip6_hdr *ip6;
3598 struct mld_hdr *mld;
3599 int error;
3600 int off;
3601 int type;
3602
3603 MLD_PRINTF(("%s: transmit 0x%llx\n", __func__,
3604 (uint64_t)VM_KERNEL_ADDRPERM(m)));
3605
3606 /*
3607 * Check if the ifnet is still attached.
3608 */
3609 ifp = mld_restore_context(m);
3610 if (ifp == NULL || !ifnet_is_attached(ifp, 0)) {
3611 MLD_PRINTF(("%s: dropped 0x%llx as ifindex %u went away.\n",
3612 __func__, (uint64_t)VM_KERNEL_ADDRPERM(m),
3613 (u_int)if_index));
3614 m_freem(m);
3615 ip6stat.ip6s_noroute++;
3616 return;
3617 }
3618
3619 im6o = ip6_allocmoptions(Z_WAITOK);
3620 if (im6o == NULL) {
3621 m_freem(m);
3622 return;
3623 }
3624
3625 im6o->im6o_multicast_hlim = 1;
3626 im6o->im6o_multicast_loop = 0;
3627 im6o->im6o_multicast_ifp = ifp;
3628
3629 if (m->m_flags & M_MLDV1) {
3630 m0 = m;
3631 } else {
3632 m0 = mld_v2_encap_report(ifp, m);
3633 if (m0 == NULL) {
3634 MLD_PRINTF(("%s: dropped 0x%llx\n", __func__,
3635 (uint64_t)VM_KERNEL_ADDRPERM(m)));
3636 /*
3637 * mld_v2_encap_report() has already freed our mbuf.
3638 */
3639 IM6O_REMREF(im6o);
3640 ip6stat.ip6s_odropped++;
3641 return;
3642 }
3643 }
3644
3645 mld_scrub_context(m0);
3646 m->m_flags &= ~(M_PROTOFLAGS);
3647 m0->m_pkthdr.rcvif = lo_ifp;
3648
3649 ip6 = mtod(m0, struct ip6_hdr *);
3650 (void)in6_setscope(&ip6->ip6_dst, ifp, NULL);
3651 ip6_output_setdstifscope(m0, ifp->if_index, NULL);
3652 /*
3653 * Retrieve the ICMPv6 type before handoff to ip6_output(),
3654 * so we can bump the stats.
3655 */
3656 md = m_getptr(m0, sizeof(struct ip6_hdr), &off);
3657 mld = (struct mld_hdr *)(mtod(md, uint8_t *) + off);
3658 type = mld->mld_type;
3659
3660 if (ifp->if_eflags & IFEF_TXSTART) {
3661 /*
3662 * Use control service class if the outgoing
3663 * interface supports transmit-start model.
3664 */
3665 (void) m_set_service_class(m0, MBUF_SC_CTL);
3666 }
3667
3668 error = ip6_output(m0, &mld_po, NULL, IPV6_UNSPECSRC, im6o,
3669 &oifp, NULL);
3670
3671 IM6O_REMREF(im6o);
3672
3673 if (error) {
3674 MLD_PRINTF(("%s: ip6_output(0x%llx) = %d\n", __func__,
3675 (uint64_t)VM_KERNEL_ADDRPERM(m0), error));
3676 if (oifp != NULL) {
3677 ifnet_release(oifp);
3678 }
3679 return;
3680 }
3681
3682 icmp6stat.icp6s_outhist[type]++;
3683 if (oifp != NULL) {
3684 icmp6_ifstat_inc(oifp, ifs6_out_msg);
3685 switch (type) {
3686 case MLD_LISTENER_REPORT:
3687 case MLDV2_LISTENER_REPORT:
3688 icmp6_ifstat_inc(oifp, ifs6_out_mldreport);
3689 break;
3690 case MLD_LISTENER_DONE:
3691 icmp6_ifstat_inc(oifp, ifs6_out_mlddone);
3692 break;
3693 }
3694 ifnet_release(oifp);
3695 }
3696 }
3697
3698 /*
3699 * Encapsulate an MLDv2 report.
3700 *
3701 * KAME IPv6 requires that hop-by-hop options be passed separately,
3702 * and that the IPv6 header be prepended in a separate mbuf.
3703 *
3704 * Returns a pointer to the new mbuf chain head, or NULL if the
3705 * allocation failed.
3706 */
3707 static struct mbuf *
mld_v2_encap_report(struct ifnet * ifp,struct mbuf * m)3708 mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m)
3709 {
3710 struct mbuf *mh;
3711 struct mldv2_report *mld;
3712 struct ip6_hdr *ip6;
3713 struct in6_ifaddr *ia;
3714 int mldreclen;
3715
3716 VERIFY(m->m_flags & M_PKTHDR);
3717
3718 /*
3719 * RFC3590: OK to send as :: or tentative during DAD.
3720 */
3721 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
3722 if (ia == NULL) {
3723 MLD_PRINTF(("%s: warning: ia is NULL\n", __func__));
3724 }
3725
3726 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
3727 if (mh == NULL) {
3728 if (ia != NULL) {
3729 IFA_REMREF(&ia->ia_ifa);
3730 }
3731 m_freem(m);
3732 return NULL;
3733 }
3734 MH_ALIGN(mh, sizeof(struct ip6_hdr) + sizeof(struct mldv2_report));
3735
3736 mldreclen = m_length(m);
3737 MLD_PRINTF(("%s: mldreclen is %d\n", __func__, mldreclen));
3738
3739 mh->m_len = sizeof(struct ip6_hdr) + sizeof(struct mldv2_report);
3740 mh->m_pkthdr.len = sizeof(struct ip6_hdr) +
3741 sizeof(struct mldv2_report) + mldreclen;
3742
3743 ip6 = mtod(mh, struct ip6_hdr *);
3744 ip6->ip6_flow = 0;
3745 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
3746 ip6->ip6_vfc |= IPV6_VERSION;
3747 ip6->ip6_nxt = IPPROTO_ICMPV6;
3748 if (ia != NULL) {
3749 IFA_LOCK(&ia->ia_ifa);
3750 }
3751 ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
3752 ip6_output_setsrcifscope(mh, IFSCOPE_NONE, ia);
3753
3754 if (ia != NULL) {
3755 IFA_UNLOCK(&ia->ia_ifa);
3756 IFA_REMREF(&ia->ia_ifa);
3757 ia = NULL;
3758 }
3759 ip6->ip6_dst = in6addr_linklocal_allv2routers;
3760 ip6_output_setdstifscope(mh, ifp->if_index, NULL);
3761 /* scope ID will be set in netisr */
3762
3763 mld = (struct mldv2_report *)(ip6 + 1);
3764 mld->mld_type = MLDV2_LISTENER_REPORT;
3765 mld->mld_code = 0;
3766 mld->mld_cksum = 0;
3767 mld->mld_v2_reserved = 0;
3768 mld->mld_v2_numrecs = htons(m->m_pkthdr.vt_nrecs);
3769 m->m_pkthdr.vt_nrecs = 0;
3770 m->m_flags &= ~M_PKTHDR;
3771
3772 mh->m_next = m;
3773 mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6,
3774 sizeof(struct ip6_hdr), sizeof(struct mldv2_report) + mldreclen);
3775 return mh;
3776 }
3777
3778 #ifdef MLD_DEBUG
3779 static const char *
mld_rec_type_to_str(const int type)3780 mld_rec_type_to_str(const int type)
3781 {
3782 switch (type) {
3783 case MLD_CHANGE_TO_EXCLUDE_MODE:
3784 return "TO_EX";
3785 case MLD_CHANGE_TO_INCLUDE_MODE:
3786 return "TO_IN";
3787 case MLD_MODE_IS_EXCLUDE:
3788 return "MODE_EX";
3789 case MLD_MODE_IS_INCLUDE:
3790 return "MODE_IN";
3791 case MLD_ALLOW_NEW_SOURCES:
3792 return "ALLOW_NEW";
3793 case MLD_BLOCK_OLD_SOURCES:
3794 return "BLOCK_OLD";
3795 default:
3796 break;
3797 }
3798 return "unknown";
3799 }
3800 #endif
3801
3802 void
mld_init(void)3803 mld_init(void)
3804 {
3805 MLD_PRINTF(("%s: initializing\n", __func__));
3806
3807 ip6_initpktopts(&mld_po);
3808 mld_po.ip6po_hlim = 1;
3809 mld_po.ip6po_hbh = &mld_ra.hbh;
3810 mld_po.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER;
3811 mld_po.ip6po_flags = IP6PO_DONTFRAG;
3812 LIST_INIT(&mli_head);
3813 }
3814