FreeBSD/Linux Kernel Cross Reference
sys/netinet6/mld6.c
1 /*-
2 * Copyright (c) 2009 Bruce Simpson.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $KAME: mld6.c,v 1.27 2001/04/04 05:17:30 itojun Exp $
29 */
30
31 /*-
32 * Copyright (c) 1988 Stephen Deering.
33 * Copyright (c) 1992, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * This code is derived from software contributed to Berkeley by
37 * Stephen Deering of Stanford University.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)igmp.c 8.1 (Berkeley) 7/19/93
64 */
65
66 #include <sys/cdefs.h>
67 __FBSDID("$FreeBSD: releng/8.0/sys/netinet6/mld6.c 196019 2009-08-01 19:26:27Z rwatson $");
68
69 #include "opt_inet.h"
70 #include "opt_inet6.h"
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/mbuf.h>
75 #include <sys/socket.h>
76 #include <sys/protosw.h>
77 #include <sys/sysctl.h>
78 #include <sys/kernel.h>
79 #include <sys/callout.h>
80 #include <sys/malloc.h>
81 #include <sys/module.h>
82
83 #include <net/if.h>
84 #include <net/route.h>
85 #include <net/vnet.h>
86
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89 #include <netinet6/in6_var.h>
90 #include <netinet/ip6.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/scope6_var.h>
93 #include <netinet/icmp6.h>
94 #include <netinet6/mld6.h>
95 #include <netinet6/mld6_var.h>
96
97 #include <security/mac/mac_framework.h>
98
99 #ifndef KTR_MLD
100 #define KTR_MLD KTR_INET6
101 #endif
102
103 static struct mld_ifinfo *
104 mli_alloc_locked(struct ifnet *);
105 static void mli_delete_locked(const struct ifnet *);
106 static void mld_dispatch_packet(struct mbuf *);
107 static void mld_dispatch_queue(struct ifqueue *, int);
108 static void mld_final_leave(struct in6_multi *, struct mld_ifinfo *);
109 static void mld_fasttimo_vnet(void);
110 static int mld_handle_state_change(struct in6_multi *,
111 struct mld_ifinfo *);
112 static int mld_initial_join(struct in6_multi *, struct mld_ifinfo *,
113 const int);
114 #ifdef KTR
115 static char * mld_rec_type_to_str(const int);
116 #endif
117 static void mld_set_version(struct mld_ifinfo *, const int);
118 static void mld_slowtimo_vnet(void);
119 static int mld_v1_input_query(struct ifnet *, const struct ip6_hdr *,
120 /*const*/ struct mld_hdr *);
121 static int mld_v1_input_report(struct ifnet *, const struct ip6_hdr *,
122 /*const*/ struct mld_hdr *);
123 static void mld_v1_process_group_timer(struct in6_multi *, const int);
124 static void mld_v1_process_querier_timers(struct mld_ifinfo *);
125 static int mld_v1_transmit_report(struct in6_multi *, const int);
126 static void mld_v1_update_group(struct in6_multi *, const int);
127 static void mld_v2_cancel_link_timers(struct mld_ifinfo *);
128 static void mld_v2_dispatch_general_query(struct mld_ifinfo *);
129 static struct mbuf *
130 mld_v2_encap_report(struct ifnet *, struct mbuf *);
131 static int mld_v2_enqueue_filter_change(struct ifqueue *,
132 struct in6_multi *);
133 static int mld_v2_enqueue_group_record(struct ifqueue *,
134 struct in6_multi *, const int, const int, const int);
135 static int mld_v2_input_query(struct ifnet *, const struct ip6_hdr *,
136 struct mbuf *, const int, const int);
137 static int mld_v2_merge_state_changes(struct in6_multi *,
138 struct ifqueue *);
139 static void mld_v2_process_group_timers(struct mld_ifinfo *,
140 struct ifqueue *, struct ifqueue *,
141 struct in6_multi *, const int);
142 static int mld_v2_process_group_query(struct in6_multi *,
143 struct mld_ifinfo *mli, int, struct mbuf *, const int);
144 static int sysctl_mld_gsr(SYSCTL_HANDLER_ARGS);
145 static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS);
146
147 /*
148 * Normative references: RFC 2710, RFC 3590, RFC 3810.
149 *
150 * Locking:
151 * * The MLD subsystem lock ends up being system-wide for the moment,
152 * but could be per-VIMAGE later on.
153 * * The permitted lock order is: IN6_MULTI_LOCK, MLD_LOCK, IF_ADDR_LOCK.
154 * Any may be taken independently; if any are held at the same
155 * time, the above lock order must be followed.
156 * * IN6_MULTI_LOCK covers in_multi.
157 * * MLD_LOCK covers per-link state and any global variables in this file.
158 * * IF_ADDR_LOCK covers if_multiaddrs, which is used for a variety of
159 * per-link state iterators.
160 *
161 * XXX LOR PREVENTION
162 * A special case for IPv6 is the in6_setscope() routine. ip6_output()
163 * will not accept an ifp; it wants an embedded scope ID, unlike
164 * ip_output(), which happily takes the ifp given to it. The embedded
165 * scope ID is only used by MLD to select the outgoing interface.
166 *
167 * During interface attach and detach, MLD will take MLD_LOCK *after*
168 * the IF_AFDATA_LOCK.
169 * As in6_setscope() takes IF_AFDATA_LOCK then SCOPE_LOCK, we can't call
170 * it with MLD_LOCK held without triggering an LOR. A netisr with indirect
171 * dispatch could work around this, but we'd rather not do that, as it
172 * can introduce other races.
173 *
174 * As such, we exploit the fact that the scope ID is just the interface
175 * index, and embed it in the IPv6 destination address accordingly.
176 * This is potentially NOT VALID for MLDv1 reports, as they
177 * are always sent to the multicast group itself; as MLDv2
178 * reports are always sent to ff02::16, this is not an issue
179 * when MLDv2 is in use.
180 *
181 * This does not however eliminate the LOR when ip6_output() itself
182 * calls in6_setscope() internally whilst MLD_LOCK is held. This will
183 * trigger a LOR warning in WITNESS when the ifnet is detached.
184 *
185 * The right answer is probably to make IF_AFDATA_LOCK an rwlock, given
186 * how it's used across the network stack. Here we're simply exploiting
187 * the fact that MLD runs at a similar layer in the stack to scope6.c.
188 *
189 * VIMAGE:
190 * * Each in6_multi corresponds to an ifp, and each ifp corresponds
191 * to a vnet in ifp->if_vnet.
192 */
193 static struct mtx mld_mtx;
194 MALLOC_DEFINE(M_MLD, "mld", "mld state");
195
196 #define MLD_EMBEDSCOPE(pin6, zoneid) \
197 (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)
198
199 /*
200 * VIMAGE-wide globals.
201 */
202 static VNET_DEFINE(struct timeval, mld_gsrdelay) = {10, 0};
203 static VNET_DEFINE(LIST_HEAD(, mld_ifinfo), mli_head);
204 static VNET_DEFINE(int, interface_timers_running6);
205 static VNET_DEFINE(int, state_change_timers_running6);
206 static VNET_DEFINE(int, current_state_timers_running6);
207
208 #define V_mld_gsrdelay VNET(mld_gsrdelay)
209 #define V_mli_head VNET(mli_head)
210 #define V_interface_timers_running6 VNET(interface_timers_running6)
211 #define V_state_change_timers_running6 VNET(state_change_timers_running6)
212 #define V_current_state_timers_running6 VNET(current_state_timers_running6)
213
214 SYSCTL_DECL(_net_inet6); /* Note: Not in any common header. */
215
216 SYSCTL_NODE(_net_inet6, OID_AUTO, mld, CTLFLAG_RW, 0,
217 "IPv6 Multicast Listener Discovery");
218
219 /*
220 * Virtualized sysctls.
221 */
222 SYSCTL_VNET_PROC(_net_inet6_mld, OID_AUTO, gsrdelay,
223 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
224 &VNET_NAME(mld_gsrdelay.tv_sec), 0, sysctl_mld_gsr, "I",
225 "Rate limit for MLDv2 Group-and-Source queries in seconds");
226
227 /*
228 * Non-virtualized sysctls.
229 */
230 SYSCTL_NODE(_net_inet6_mld, OID_AUTO, ifinfo, CTLFLAG_RD | CTLFLAG_MPSAFE,
231 sysctl_mld_ifinfo, "Per-interface MLDv2 state");
232
233 static int mld_v1enable = 1;
234 SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RW,
235 &mld_v1enable, 0, "Enable fallback to MLDv1");
236 TUNABLE_INT("net.inet6.mld.v1enable", &mld_v1enable);
237
238 /*
239 * Packed Router Alert option structure declaration.
240 */
241 struct mld_raopt {
242 struct ip6_hbh hbh;
243 struct ip6_opt pad;
244 struct ip6_opt_router ra;
245 } __packed;
246
247 /*
248 * Router Alert hop-by-hop option header.
249 */
250 static struct mld_raopt mld_ra = {
251 .hbh = { 0, 0 },
252 .pad = { .ip6o_type = IP6OPT_PADN, 0 },
253 .ra = {
254 .ip6or_type = IP6OPT_ROUTER_ALERT,
255 .ip6or_len = IP6OPT_RTALERT_LEN - 2,
256 .ip6or_value[0] = ((IP6OPT_RTALERT_MLD >> 8) & 0xFF),
257 .ip6or_value[1] = (IP6OPT_RTALERT_MLD & 0xFF)
258 }
259 };
260 static struct ip6_pktopts mld_po;
261
262 static __inline void
263 mld_save_context(struct mbuf *m, struct ifnet *ifp)
264 {
265
266 #ifdef VIMAGE
267 m->m_pkthdr.header = ifp->if_vnet;
268 #endif /* VIMAGE */
269 m->m_pkthdr.flowid = ifp->if_index;
270 }
271
272 static __inline void
273 mld_scrub_context(struct mbuf *m)
274 {
275
276 m->m_pkthdr.header = NULL;
277 m->m_pkthdr.flowid = 0;
278 }
279
280 /*
281 * Restore context from a queued output chain.
282 * Return saved ifindex.
283 *
284 * VIMAGE: The assertion is there to make sure that we
285 * actually called CURVNET_SET() with what's in the mbuf chain.
286 */
287 static __inline uint32_t
288 mld_restore_context(struct mbuf *m)
289 {
290
291 #if defined(VIMAGE) && defined(INVARIANTS)
292 KASSERT(curvnet == m->m_pkthdr.header,
293 ("%s: called when curvnet was not restored", __func__));
294 #endif
295 return (m->m_pkthdr.flowid);
296 }
297
298 /*
299 * Retrieve or set threshold between group-source queries in seconds.
300 *
301 * VIMAGE: Assume curvnet set by caller.
302 * SMPng: NOTE: Serialized by MLD lock.
303 */
304 static int
305 sysctl_mld_gsr(SYSCTL_HANDLER_ARGS)
306 {
307 int error;
308 int i;
309
310 error = sysctl_wire_old_buffer(req, sizeof(int));
311 if (error)
312 return (error);
313
314 MLD_LOCK();
315
316 i = V_mld_gsrdelay.tv_sec;
317
318 error = sysctl_handle_int(oidp, &i, 0, req);
319 if (error || !req->newptr)
320 goto out_locked;
321
322 if (i < -1 || i >= 60) {
323 error = EINVAL;
324 goto out_locked;
325 }
326
327 CTR2(KTR_MLD, "change mld_gsrdelay from %d to %d",
328 V_mld_gsrdelay.tv_sec, i);
329 V_mld_gsrdelay.tv_sec = i;
330
331 out_locked:
332 MLD_UNLOCK();
333 return (error);
334 }
335
336 /*
337 * Expose struct mld_ifinfo to userland, keyed by ifindex.
338 * For use by ifmcstat(8).
339 *
340 * SMPng: NOTE: Does an unlocked ifindex space read.
341 * VIMAGE: Assume curvnet set by caller. The node handler itself
342 * is not directly virtualized.
343 */
344 static int
345 sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS)
346 {
347 int *name;
348 int error;
349 u_int namelen;
350 struct ifnet *ifp;
351 struct mld_ifinfo *mli;
352
353 name = (int *)arg1;
354 namelen = arg2;
355
356 if (req->newptr != NULL)
357 return (EPERM);
358
359 if (namelen != 1)
360 return (EINVAL);
361
362 error = sysctl_wire_old_buffer(req, sizeof(struct mld_ifinfo));
363 if (error)
364 return (error);
365
366 IN6_MULTI_LOCK();
367 MLD_LOCK();
368
369 if (name[0] <= 0 || name[0] > V_if_index) {
370 error = ENOENT;
371 goto out_locked;
372 }
373
374 error = ENOENT;
375
376 ifp = ifnet_byindex(name[0]);
377 if (ifp == NULL)
378 goto out_locked;
379
380 LIST_FOREACH(mli, &V_mli_head, mli_link) {
381 if (ifp == mli->mli_ifp) {
382 error = SYSCTL_OUT(req, mli,
383 sizeof(struct mld_ifinfo));
384 break;
385 }
386 }
387
388 out_locked:
389 MLD_UNLOCK();
390 IN6_MULTI_UNLOCK();
391 return (error);
392 }
393
394 /*
395 * Dispatch an entire queue of pending packet chains.
396 * VIMAGE: Assumes the vnet pointer has been set.
397 */
398 static void
399 mld_dispatch_queue(struct ifqueue *ifq, int limit)
400 {
401 struct mbuf *m;
402
403 for (;;) {
404 _IF_DEQUEUE(ifq, m);
405 if (m == NULL)
406 break;
407 CTR3(KTR_MLD, "%s: dispatch %p from %p", __func__, ifq, m);
408 mld_dispatch_packet(m);
409 if (--limit == 0)
410 break;
411 }
412 }
413
414 /*
415 * Filter outgoing MLD report state by group.
416 *
417 * Reports are ALWAYS suppressed for ALL-HOSTS (ff02::1)
418 * and node-local addresses. However, kernel and socket consumers
419 * always embed the KAME scope ID in the address provided, so strip it
420 * when performing comparison.
421 * Note: This is not the same as the *multicast* scope.
422 *
423 * Return zero if the given group is one for which MLD reports
424 * should be suppressed, or non-zero if reports should be issued.
425 */
426 static __inline int
427 mld_is_addr_reported(const struct in6_addr *addr)
428 {
429
430 KASSERT(IN6_IS_ADDR_MULTICAST(addr), ("%s: not multicast", __func__));
431
432 if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_NODELOCAL)
433 return (0);
434
435 if (IPV6_ADDR_MC_SCOPE(addr) == IPV6_ADDR_SCOPE_LINKLOCAL) {
436 struct in6_addr tmp = *addr;
437 in6_clearscope(&tmp);
438 if (IN6_ARE_ADDR_EQUAL(&tmp, &in6addr_linklocal_allnodes))
439 return (0);
440 }
441
442 return (1);
443 }
444
445 /*
446 * Attach MLD when PF_INET6 is attached to an interface.
447 *
448 * SMPng: Normally called with IF_AFDATA_LOCK held.
449 */
450 struct mld_ifinfo *
451 mld_domifattach(struct ifnet *ifp)
452 {
453 struct mld_ifinfo *mli;
454
455 CTR3(KTR_MLD, "%s: called for ifp %p(%s)",
456 __func__, ifp, ifp->if_xname);
457
458 MLD_LOCK();
459
460 mli = mli_alloc_locked(ifp);
461 if (!(ifp->if_flags & IFF_MULTICAST))
462 mli->mli_flags |= MLIF_SILENT;
463
464 MLD_UNLOCK();
465
466 return (mli);
467 }
468
469 /*
470 * VIMAGE: assume curvnet set by caller.
471 */
472 static struct mld_ifinfo *
473 mli_alloc_locked(/*const*/ struct ifnet *ifp)
474 {
475 struct mld_ifinfo *mli;
476
477 MLD_LOCK_ASSERT();
478
479 mli = malloc(sizeof(struct mld_ifinfo), M_MLD, M_NOWAIT|M_ZERO);
480 if (mli == NULL)
481 goto out;
482
483 mli->mli_ifp = ifp;
484 mli->mli_version = MLD_VERSION_2;
485 mli->mli_flags = 0;
486 mli->mli_rv = MLD_RV_INIT;
487 mli->mli_qi = MLD_QI_INIT;
488 mli->mli_qri = MLD_QRI_INIT;
489 mli->mli_uri = MLD_URI_INIT;
490
491 SLIST_INIT(&mli->mli_relinmhead);
492
493 /*
494 * Responses to general queries are subject to bounds.
495 */
496 IFQ_SET_MAXLEN(&mli->mli_gq, MLD_MAX_RESPONSE_PACKETS);
497
498 LIST_INSERT_HEAD(&V_mli_head, mli, mli_link);
499
500 CTR2(KTR_MLD, "allocate mld_ifinfo for ifp %p(%s)",
501 ifp, ifp->if_xname);
502
503 out:
504 return (mli);
505 }
506
507 /*
508 * Hook for ifdetach.
509 *
510 * NOTE: Some finalization tasks need to run before the protocol domain
511 * is detached, but also before the link layer does its cleanup.
512 * Run before link-layer cleanup; cleanup groups, but do not free MLD state.
513 *
514 * SMPng: Caller must hold IN6_MULTI_LOCK().
515 * Must take IF_ADDR_LOCK() to cover if_multiaddrs iterator.
516 * XXX This routine is also bitten by unlocked ifma_protospec access.
517 */
518 void
519 mld_ifdetach(struct ifnet *ifp)
520 {
521 struct mld_ifinfo *mli;
522 struct ifmultiaddr *ifma;
523 struct in6_multi *inm, *tinm;
524
525 CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp,
526 ifp->if_xname);
527
528 IN6_MULTI_LOCK_ASSERT();
529 MLD_LOCK();
530
531 mli = MLD_IFINFO(ifp);
532 if (mli->mli_version == MLD_VERSION_2) {
533 IF_ADDR_LOCK(ifp);
534 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
535 if (ifma->ifma_addr->sa_family != AF_INET6 ||
536 ifma->ifma_protospec == NULL)
537 continue;
538 inm = (struct in6_multi *)ifma->ifma_protospec;
539 if (inm->in6m_state == MLD_LEAVING_MEMBER) {
540 SLIST_INSERT_HEAD(&mli->mli_relinmhead,
541 inm, in6m_nrele);
542 }
543 in6m_clear_recorded(inm);
544 }
545 IF_ADDR_UNLOCK(ifp);
546 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele,
547 tinm) {
548 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
549 in6m_release_locked(inm);
550 }
551 }
552
553 MLD_UNLOCK();
554 }
555
556 /*
557 * Hook for domifdetach.
558 * Runs after link-layer cleanup; free MLD state.
559 *
560 * SMPng: Normally called with IF_AFDATA_LOCK held.
561 */
562 void
563 mld_domifdetach(struct ifnet *ifp)
564 {
565
566 CTR3(KTR_MLD, "%s: called for ifp %p(%s)",
567 __func__, ifp, ifp->if_xname);
568
569 MLD_LOCK();
570 mli_delete_locked(ifp);
571 MLD_UNLOCK();
572 }
573
574 static void
575 mli_delete_locked(const struct ifnet *ifp)
576 {
577 struct mld_ifinfo *mli, *tmli;
578
579 CTR3(KTR_MLD, "%s: freeing mld_ifinfo for ifp %p(%s)",
580 __func__, ifp, ifp->if_xname);
581
582 MLD_LOCK_ASSERT();
583
584 LIST_FOREACH_SAFE(mli, &V_mli_head, mli_link, tmli) {
585 if (mli->mli_ifp == ifp) {
586 /*
587 * Free deferred General Query responses.
588 */
589 _IF_DRAIN(&mli->mli_gq);
590
591 LIST_REMOVE(mli, mli_link);
592
593 KASSERT(SLIST_EMPTY(&mli->mli_relinmhead),
594 ("%s: there are dangling in_multi references",
595 __func__));
596
597 free(mli, M_MLD);
598 return;
599 }
600 }
601 #ifdef INVARIANTS
602 panic("%s: mld_ifinfo not found for ifp %p\n", __func__, ifp);
603 #endif
604 }
605
606 /*
607 * Process a received MLDv1 general or address-specific query.
608 * Assumes that the query header has been pulled up to sizeof(mld_hdr).
609 *
610 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
611 * mld_addr. This is OK as we own the mbuf chain.
612 */
613 static int
614 mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
615 /*const*/ struct mld_hdr *mld)
616 {
617 struct ifmultiaddr *ifma;
618 struct mld_ifinfo *mli;
619 struct in6_multi *inm;
620 int is_general_query;
621 uint16_t timer;
622 #ifdef KTR
623 char ip6tbuf[INET6_ADDRSTRLEN];
624 #endif
625
626 is_general_query = 0;
627
628 if (!mld_v1enable) {
629 CTR3(KTR_MLD, "ignore v1 query %s on ifp %p(%s)",
630 ip6_sprintf(ip6tbuf, &mld->mld_addr),
631 ifp, ifp->if_xname);
632 return (0);
633 }
634
635 /*
636 * RFC3810 Section 6.2: MLD queries must originate from
637 * a router's link-local address.
638 */
639 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
640 CTR3(KTR_MLD, "ignore v1 query src %s on ifp %p(%s)",
641 ip6_sprintf(ip6tbuf, &ip6->ip6_src),
642 ifp, ifp->if_xname);
643 return (0);
644 }
645
646 /*
647 * Do address field validation upfront before we accept
648 * the query.
649 */
650 if (IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
651 /*
652 * MLDv1 General Query.
653 * If this was not sent to the all-nodes group, ignore it.
654 */
655 struct in6_addr dst;
656
657 dst = ip6->ip6_dst;
658 in6_clearscope(&dst);
659 if (!IN6_ARE_ADDR_EQUAL(&dst, &in6addr_linklocal_allnodes))
660 return (EINVAL);
661 is_general_query = 1;
662 } else {
663 /*
664 * Embed scope ID of receiving interface in MLD query for
665 * lookup whilst we don't hold other locks.
666 */
667 in6_setscope(&mld->mld_addr, ifp, NULL);
668 }
669
670 IN6_MULTI_LOCK();
671 MLD_LOCK();
672 IF_ADDR_LOCK(ifp);
673
674 /*
675 * Switch to MLDv1 host compatibility mode.
676 */
677 mli = MLD_IFINFO(ifp);
678 KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
679 mld_set_version(mli, MLD_VERSION_1);
680
681 timer = (ntohs(mld->mld_maxdelay) * PR_FASTHZ) / MLD_TIMER_SCALE;
682 if (timer == 0)
683 timer = 1;
684
685 if (is_general_query) {
686 /*
687 * For each reporting group joined on this
688 * interface, kick the report timer.
689 */
690 CTR2(KTR_MLD, "process v1 general query on ifp %p(%s)",
691 ifp, ifp->if_xname);
692 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
693 if (ifma->ifma_addr->sa_family != AF_INET6 ||
694 ifma->ifma_protospec == NULL)
695 continue;
696 inm = (struct in6_multi *)ifma->ifma_protospec;
697 mld_v1_update_group(inm, timer);
698 }
699 } else {
700 /*
701 * MLDv1 Group-Specific Query.
702 * If this is a group-specific MLDv1 query, we need only
703 * look up the single group to process it.
704 */
705 inm = in6m_lookup_locked(ifp, &mld->mld_addr);
706 if (inm != NULL) {
707 CTR3(KTR_MLD, "process v1 query %s on ifp %p(%s)",
708 ip6_sprintf(ip6tbuf, &mld->mld_addr),
709 ifp, ifp->if_xname);
710 mld_v1_update_group(inm, timer);
711 }
712 /* XXX Clear embedded scope ID as userland won't expect it. */
713 in6_clearscope(&mld->mld_addr);
714 }
715
716 IF_ADDR_UNLOCK(ifp);
717 MLD_UNLOCK();
718 IN6_MULTI_UNLOCK();
719
720 return (0);
721 }
722
723 /*
724 * Update the report timer on a group in response to an MLDv1 query.
725 *
726 * If we are becoming the reporting member for this group, start the timer.
727 * If we already are the reporting member for this group, and timer is
728 * below the threshold, reset it.
729 *
730 * We may be updating the group for the first time since we switched
731 * to MLDv2. If we are, then we must clear any recorded source lists,
732 * and transition to REPORTING state; the group timer is overloaded
733 * for group and group-source query responses.
734 *
735 * Unlike MLDv2, the delay per group should be jittered
736 * to avoid bursts of MLDv1 reports.
737 */
738 static void
739 mld_v1_update_group(struct in6_multi *inm, const int timer)
740 {
741 #ifdef KTR
742 char ip6tbuf[INET6_ADDRSTRLEN];
743 #endif
744
745 CTR4(KTR_MLD, "%s: %s/%s timer=%d", __func__,
746 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
747 inm->in6m_ifp->if_xname, timer);
748
749 IN6_MULTI_LOCK_ASSERT();
750
751 switch (inm->in6m_state) {
752 case MLD_NOT_MEMBER:
753 case MLD_SILENT_MEMBER:
754 break;
755 case MLD_REPORTING_MEMBER:
756 if (inm->in6m_timer != 0 &&
757 inm->in6m_timer <= timer) {
758 CTR1(KTR_MLD, "%s: REPORTING and timer running, "
759 "skipping.", __func__);
760 break;
761 }
762 /* FALLTHROUGH */
763 case MLD_SG_QUERY_PENDING_MEMBER:
764 case MLD_G_QUERY_PENDING_MEMBER:
765 case MLD_IDLE_MEMBER:
766 case MLD_LAZY_MEMBER:
767 case MLD_AWAKENING_MEMBER:
768 CTR1(KTR_MLD, "%s: ->REPORTING", __func__);
769 inm->in6m_state = MLD_REPORTING_MEMBER;
770 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
771 V_current_state_timers_running6 = 1;
772 break;
773 case MLD_SLEEPING_MEMBER:
774 CTR1(KTR_MLD, "%s: ->AWAKENING", __func__);
775 inm->in6m_state = MLD_AWAKENING_MEMBER;
776 break;
777 case MLD_LEAVING_MEMBER:
778 break;
779 }
780 }
781
782 /*
783 * Process a received MLDv2 general, group-specific or
784 * group-and-source-specific query.
785 *
786 * Assumes that the query header has been pulled up to sizeof(mldv2_query).
787 *
788 * Return 0 if successful, otherwise an appropriate error code is returned.
789 */
790 static int
791 mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
792 struct mbuf *m, const int off, const int icmp6len)
793 {
794 struct mld_ifinfo *mli;
795 struct mldv2_query *mld;
796 struct in6_multi *inm;
797 uint32_t maxdelay, nsrc, qqi;
798 int is_general_query;
799 uint16_t timer;
800 uint8_t qrv;
801 #ifdef KTR
802 char ip6tbuf[INET6_ADDRSTRLEN];
803 #endif
804
805 is_general_query = 0;
806
807 /*
808 * RFC3810 Section 6.2: MLD queries must originate from
809 * a router's link-local address.
810 */
811 if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
812 CTR3(KTR_MLD, "ignore v1 query src %s on ifp %p(%s)",
813 ip6_sprintf(ip6tbuf, &ip6->ip6_src),
814 ifp, ifp->if_xname);
815 return (0);
816 }
817
818 CTR2(KTR_MLD, "input v2 query on ifp %p(%s)", ifp, ifp->if_xname);
819
820 mld = (struct mldv2_query *)(mtod(m, uint8_t *) + off);
821
822 maxdelay = ntohs(mld->mld_maxdelay); /* in 1/10ths of a second */
823 if (maxdelay >= 32678) {
824 maxdelay = (MLD_MRC_MANT(maxdelay) | 0x1000) <<
825 (MLD_MRC_EXP(maxdelay) + 3);
826 }
827 timer = (maxdelay * PR_FASTHZ) / MLD_TIMER_SCALE;
828 if (timer == 0)
829 timer = 1;
830
831 qrv = MLD_QRV(mld->mld_misc);
832 if (qrv < 2) {
833 CTR3(KTR_MLD, "%s: clamping qrv %d to %d", __func__,
834 qrv, MLD_RV_INIT);
835 qrv = MLD_RV_INIT;
836 }
837
838 qqi = mld->mld_qqi;
839 if (qqi >= 128) {
840 qqi = MLD_QQIC_MANT(mld->mld_qqi) <<
841 (MLD_QQIC_EXP(mld->mld_qqi) + 3);
842 }
843
844 nsrc = ntohs(mld->mld_numsrc);
845 if (nsrc > MLD_MAX_GS_SOURCES)
846 return (EMSGSIZE);
847 if (icmp6len < sizeof(struct mldv2_query) +
848 (nsrc * sizeof(struct in6_addr)))
849 return (EMSGSIZE);
850
851 /*
852 * Do further input validation upfront to avoid resetting timers
853 * should we need to discard this query.
854 */
855 if (IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr)) {
856 /*
857 * General Queries SHOULD be directed to ff02::1.
858 * A general query with a source list has undefined
859 * behaviour; discard it.
860 */
861 struct in6_addr dst;
862
863 dst = ip6->ip6_dst;
864 in6_clearscope(&dst);
865 if (!IN6_ARE_ADDR_EQUAL(&dst, &in6addr_linklocal_allnodes) ||
866 nsrc > 0)
867 return (EINVAL);
868 is_general_query = 1;
869 } else {
870 /*
871 * Embed scope ID of receiving interface in MLD query for
872 * lookup whilst we don't hold other locks (due to KAME
873 * locking lameness). We own this mbuf chain just now.
874 */
875 in6_setscope(&mld->mld_addr, ifp, NULL);
876 }
877
878 IN6_MULTI_LOCK();
879 MLD_LOCK();
880 IF_ADDR_LOCK(ifp);
881
882 mli = MLD_IFINFO(ifp);
883 KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
884
885 /*
886 * Discard the v2 query if we're in Compatibility Mode.
887 * The RFC is pretty clear that hosts need to stay in MLDv1 mode
888 * until the Old Version Querier Present timer expires.
889 */
890 if (mli->mli_version != MLD_VERSION_2)
891 goto out_locked;
892
893 mld_set_version(mli, MLD_VERSION_2);
894 mli->mli_rv = qrv;
895 mli->mli_qi = qqi;
896 mli->mli_qri = maxdelay;
897
898 CTR4(KTR_MLD, "%s: qrv %d qi %d maxdelay %d", __func__, qrv, qqi,
899 maxdelay);
900
901 if (is_general_query) {
902 /*
903 * MLDv2 General Query.
904 *
905 * Schedule a current-state report on this ifp for
906 * all groups, possibly containing source lists.
907 *
908 * If there is a pending General Query response
909 * scheduled earlier than the selected delay, do
910 * not schedule any other reports.
911 * Otherwise, reset the interface timer.
912 */
913 CTR2(KTR_MLD, "process v2 general query on ifp %p(%s)",
914 ifp, ifp->if_xname);
915 if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer) {
916 mli->mli_v2_timer = MLD_RANDOM_DELAY(timer);
917 V_interface_timers_running6 = 1;
918 }
919 } else {
920 /*
921 * MLDv2 Group-specific or Group-and-source-specific Query.
922 *
923 * Group-source-specific queries are throttled on
924 * a per-group basis to defeat denial-of-service attempts.
925 * Queries for groups we are not a member of on this
926 * link are simply ignored.
927 */
928 inm = in6m_lookup_locked(ifp, &mld->mld_addr);
929 if (inm == NULL)
930 goto out_locked;
931 if (nsrc > 0) {
932 if (!ratecheck(&inm->in6m_lastgsrtv,
933 &V_mld_gsrdelay)) {
934 CTR1(KTR_MLD, "%s: GS query throttled.",
935 __func__);
936 goto out_locked;
937 }
938 }
939 CTR2(KTR_MLD, "process v2 group query on ifp %p(%s)",
940 ifp, ifp->if_xname);
941 /*
942 * If there is a pending General Query response
943 * scheduled sooner than the selected delay, no
944 * further report need be scheduled.
945 * Otherwise, prepare to respond to the
946 * group-specific or group-and-source query.
947 */
948 if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer)
949 mld_v2_process_group_query(inm, mli, timer, m, off);
950
951 /* XXX Clear embedded scope ID as userland won't expect it. */
952 in6_clearscope(&mld->mld_addr);
953 }
954
955 out_locked:
956 IF_ADDR_UNLOCK(ifp);
957 MLD_UNLOCK();
958 IN6_MULTI_UNLOCK();
959
960 return (0);
961 }
962
963 /*
964 * Process a recieved MLDv2 group-specific or group-and-source-specific
965 * query.
966 * Return <0 if any error occured. Currently this is ignored.
967 */
968 static int
969 mld_v2_process_group_query(struct in6_multi *inm, struct mld_ifinfo *mli,
970 int timer, struct mbuf *m0, const int off)
971 {
972 struct mldv2_query *mld;
973 int retval;
974 uint16_t nsrc;
975
976 IN6_MULTI_LOCK_ASSERT();
977 MLD_LOCK_ASSERT();
978
979 retval = 0;
980 mld = (struct mldv2_query *)(mtod(m0, uint8_t *) + off);
981
982 switch (inm->in6m_state) {
983 case MLD_NOT_MEMBER:
984 case MLD_SILENT_MEMBER:
985 case MLD_SLEEPING_MEMBER:
986 case MLD_LAZY_MEMBER:
987 case MLD_AWAKENING_MEMBER:
988 case MLD_IDLE_MEMBER:
989 case MLD_LEAVING_MEMBER:
990 return (retval);
991 break;
992 case MLD_REPORTING_MEMBER:
993 case MLD_G_QUERY_PENDING_MEMBER:
994 case MLD_SG_QUERY_PENDING_MEMBER:
995 break;
996 }
997
998 nsrc = ntohs(mld->mld_numsrc);
999
1000 /*
1001 * Deal with group-specific queries upfront.
1002 * If any group query is already pending, purge any recorded
1003 * source-list state if it exists, and schedule a query response
1004 * for this group-specific query.
1005 */
1006 if (nsrc == 0) {
1007 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER ||
1008 inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER) {
1009 in6m_clear_recorded(inm);
1010 timer = min(inm->in6m_timer, timer);
1011 }
1012 inm->in6m_state = MLD_G_QUERY_PENDING_MEMBER;
1013 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1014 V_current_state_timers_running6 = 1;
1015 return (retval);
1016 }
1017
1018 /*
1019 * Deal with the case where a group-and-source-specific query has
1020 * been received but a group-specific query is already pending.
1021 */
1022 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER) {
1023 timer = min(inm->in6m_timer, timer);
1024 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1025 V_current_state_timers_running6 = 1;
1026 return (retval);
1027 }
1028
1029 /*
1030 * Finally, deal with the case where a group-and-source-specific
1031 * query has been received, where a response to a previous g-s-r
1032 * query exists, or none exists.
1033 * In this case, we need to parse the source-list which the Querier
1034 * has provided us with and check if we have any source list filter
1035 * entries at T1 for these sources. If we do not, there is no need
1036 * schedule a report and the query may be dropped.
1037 * If we do, we must record them and schedule a current-state
1038 * report for those sources.
1039 */
1040 if (inm->in6m_nsrc > 0) {
1041 struct mbuf *m;
1042 uint8_t *sp;
1043 int i, nrecorded;
1044 int soff;
1045
1046 m = m0;
1047 soff = off + sizeof(struct mldv2_query);
1048 nrecorded = 0;
1049 for (i = 0; i < nsrc; i++) {
1050 sp = mtod(m, uint8_t *) + soff;
1051 retval = in6m_record_source(inm,
1052 (const struct in6_addr *)sp);
1053 if (retval < 0)
1054 break;
1055 nrecorded += retval;
1056 soff += sizeof(struct in6_addr);
1057 if (soff >= m->m_len) {
1058 soff = soff - m->m_len;
1059 m = m->m_next;
1060 if (m == NULL)
1061 break;
1062 }
1063 }
1064 if (nrecorded > 0) {
1065 CTR1(KTR_MLD,
1066 "%s: schedule response to SG query", __func__);
1067 inm->in6m_state = MLD_SG_QUERY_PENDING_MEMBER;
1068 inm->in6m_timer = MLD_RANDOM_DELAY(timer);
1069 V_current_state_timers_running6 = 1;
1070 }
1071 }
1072
1073 return (retval);
1074 }
1075
1076 /*
1077 * Process a received MLDv1 host membership report.
1078 * Assumes mld points to mld_hdr in pulled up mbuf chain.
1079 *
1080 * NOTE: Can't be fully const correct as we temporarily embed scope ID in
1081 * mld_addr. This is OK as we own the mbuf chain.
1082 */
1083 static int
1084 mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6,
1085 /*const*/ struct mld_hdr *mld)
1086 {
1087 struct in6_addr src, dst;
1088 struct in6_ifaddr *ia;
1089 struct in6_multi *inm;
1090 #ifdef KTR
1091 char ip6tbuf[INET6_ADDRSTRLEN];
1092 #endif
1093
1094 if (!mld_v1enable) {
1095 CTR3(KTR_MLD, "ignore v1 report %s on ifp %p(%s)",
1096 ip6_sprintf(ip6tbuf, &mld->mld_addr),
1097 ifp, ifp->if_xname);
1098 return (0);
1099 }
1100
1101 if (ifp->if_flags & IFF_LOOPBACK)
1102 return (0);
1103
1104 /*
1105 * MLDv1 reports must originate from a host's link-local address,
1106 * or the unspecified address (when booting).
1107 */
1108 src = ip6->ip6_src;
1109 in6_clearscope(&src);
1110 if (!IN6_IS_SCOPE_LINKLOCAL(&src) && !IN6_IS_ADDR_UNSPECIFIED(&src)) {
1111 CTR3(KTR_MLD, "ignore v1 query src %s on ifp %p(%s)",
1112 ip6_sprintf(ip6tbuf, &ip6->ip6_src),
1113 ifp, ifp->if_xname);
1114 return (EINVAL);
1115 }
1116
1117 /*
1118 * RFC2710 Section 4: MLDv1 reports must pertain to a multicast
1119 * group, and must be directed to the group itself.
1120 */
1121 dst = ip6->ip6_dst;
1122 in6_clearscope(&dst);
1123 if (!IN6_IS_ADDR_MULTICAST(&mld->mld_addr) ||
1124 !IN6_ARE_ADDR_EQUAL(&mld->mld_addr, &dst)) {
1125 CTR3(KTR_MLD, "ignore v1 query dst %s on ifp %p(%s)",
1126 ip6_sprintf(ip6tbuf, &ip6->ip6_dst),
1127 ifp, ifp->if_xname);
1128 return (EINVAL);
1129 }
1130
1131 /*
1132 * Make sure we don't hear our own membership report, as fast
1133 * leave requires knowing that we are the only member of a
1134 * group. Assume we used the link-local address if available,
1135 * otherwise look for ::.
1136 *
1137 * XXX Note that scope ID comparison is needed for the address
1138 * returned by in6ifa_ifpforlinklocal(), but SHOULD NOT be
1139 * performed for the on-wire address.
1140 */
1141 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
1142 if ((ia && IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, IA6_IN6(ia))) ||
1143 (ia == NULL && IN6_IS_ADDR_UNSPECIFIED(&src))) {
1144 if (ia != NULL)
1145 ifa_free(&ia->ia_ifa);
1146 return (0);
1147 }
1148 if (ia != NULL)
1149 ifa_free(&ia->ia_ifa);
1150
1151 CTR3(KTR_MLD, "process v1 report %s on ifp %p(%s)",
1152 ip6_sprintf(ip6tbuf, &mld->mld_addr), ifp, ifp->if_xname);
1153
1154 /*
1155 * Embed scope ID of receiving interface in MLD query for lookup
1156 * whilst we don't hold other locks (due to KAME locking lameness).
1157 */
1158 if (!IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr))
1159 in6_setscope(&mld->mld_addr, ifp, NULL);
1160
1161 IN6_MULTI_LOCK();
1162 MLD_LOCK();
1163 IF_ADDR_LOCK(ifp);
1164
1165 /*
1166 * MLDv1 report suppression.
1167 * If we are a member of this group, and our membership should be
1168 * reported, and our group timer is pending or about to be reset,
1169 * stop our group timer by transitioning to the 'lazy' state.
1170 */
1171 inm = in6m_lookup_locked(ifp, &mld->mld_addr);
1172 if (inm != NULL) {
1173 struct mld_ifinfo *mli;
1174
1175 mli = inm->in6m_mli;
1176 KASSERT(mli != NULL,
1177 ("%s: no mli for ifp %p", __func__, ifp));
1178
1179 /*
1180 * If we are in MLDv2 host mode, do not allow the
1181 * other host's MLDv1 report to suppress our reports.
1182 */
1183 if (mli->mli_version == MLD_VERSION_2)
1184 goto out_locked;
1185
1186 inm->in6m_timer = 0;
1187
1188 switch (inm->in6m_state) {
1189 case MLD_NOT_MEMBER:
1190 case MLD_SILENT_MEMBER:
1191 case MLD_SLEEPING_MEMBER:
1192 break;
1193 case MLD_REPORTING_MEMBER:
1194 case MLD_IDLE_MEMBER:
1195 case MLD_AWAKENING_MEMBER:
1196 CTR3(KTR_MLD,
1197 "report suppressed for %s on ifp %p(%s)",
1198 ip6_sprintf(ip6tbuf, &mld->mld_addr),
1199 ifp, ifp->if_xname);
1200 case MLD_LAZY_MEMBER:
1201 inm->in6m_state = MLD_LAZY_MEMBER;
1202 break;
1203 case MLD_G_QUERY_PENDING_MEMBER:
1204 case MLD_SG_QUERY_PENDING_MEMBER:
1205 case MLD_LEAVING_MEMBER:
1206 break;
1207 }
1208 }
1209
1210 out_locked:
1211 MLD_UNLOCK();
1212 IF_ADDR_UNLOCK(ifp);
1213 IN6_MULTI_UNLOCK();
1214
1215 /* XXX Clear embedded scope ID as userland won't expect it. */
1216 in6_clearscope(&mld->mld_addr);
1217
1218 return (0);
1219 }
1220
1221 /*
1222 * MLD input path.
1223 *
1224 * Assume query messages which fit in a single ICMPv6 message header
1225 * have been pulled up.
1226 * Assume that userland will want to see the message, even if it
1227 * otherwise fails kernel input validation; do not free it.
1228 * Pullup may however free the mbuf chain m if it fails.
1229 *
1230 * Return IPPROTO_DONE if we freed m. Otherwise, return 0.
1231 */
1232 int
1233 mld_input(struct mbuf *m, int off, int icmp6len)
1234 {
1235 struct ifnet *ifp;
1236 struct ip6_hdr *ip6;
1237 struct mld_hdr *mld;
1238 int mldlen;
1239
1240 CTR3(KTR_MLD, "%s: called w/mbuf (%p,%d)", __func__, m, off);
1241
1242 ifp = m->m_pkthdr.rcvif;
1243
1244 ip6 = mtod(m, struct ip6_hdr *);
1245
1246 /* Pullup to appropriate size. */
1247 mld = (struct mld_hdr *)(mtod(m, uint8_t *) + off);
1248 if (mld->mld_type == MLD_LISTENER_QUERY &&
1249 icmp6len >= sizeof(struct mldv2_query)) {
1250 mldlen = sizeof(struct mldv2_query);
1251 } else {
1252 mldlen = sizeof(struct mld_hdr);
1253 }
1254 IP6_EXTHDR_GET(mld, struct mld_hdr *, m, off, mldlen);
1255 if (mld == NULL) {
1256 ICMP6STAT_INC(icp6s_badlen);
1257 return (IPPROTO_DONE);
1258 }
1259
1260 /*
1261 * Userland needs to see all of this traffic for implementing
1262 * the endpoint discovery portion of multicast routing.
1263 */
1264 switch (mld->mld_type) {
1265 case MLD_LISTENER_QUERY:
1266 icmp6_ifstat_inc(ifp, ifs6_in_mldquery);
1267 if (icmp6len == sizeof(struct mld_hdr)) {
1268 if (mld_v1_input_query(ifp, ip6, mld) != 0)
1269 return (0);
1270 } else if (icmp6len >= sizeof(struct mldv2_query)) {
1271 if (mld_v2_input_query(ifp, ip6, m, off,
1272 icmp6len) != 0)
1273 return (0);
1274 }
1275 break;
1276 case MLD_LISTENER_REPORT:
1277 icmp6_ifstat_inc(ifp, ifs6_in_mldreport);
1278 if (mld_v1_input_report(ifp, ip6, mld) != 0)
1279 return (0);
1280 break;
1281 case MLDV2_LISTENER_REPORT:
1282 icmp6_ifstat_inc(ifp, ifs6_in_mldreport);
1283 break;
1284 case MLD_LISTENER_DONE:
1285 icmp6_ifstat_inc(ifp, ifs6_in_mlddone);
1286 break;
1287 default:
1288 break;
1289 }
1290
1291 return (0);
1292 }
1293
1294 /*
1295 * Fast timeout handler (global).
1296 * VIMAGE: Timeout handlers are expected to service all vimages.
1297 */
1298 void
1299 mld_fasttimo(void)
1300 {
1301 VNET_ITERATOR_DECL(vnet_iter);
1302
1303 VNET_LIST_RLOCK_NOSLEEP();
1304 VNET_FOREACH(vnet_iter) {
1305 CURVNET_SET(vnet_iter);
1306 mld_fasttimo_vnet();
1307 CURVNET_RESTORE();
1308 }
1309 VNET_LIST_RUNLOCK_NOSLEEP();
1310 }
1311
1312 /*
1313 * Fast timeout handler (per-vnet).
1314 *
1315 * VIMAGE: Assume caller has set up our curvnet.
1316 */
1317 static void
1318 mld_fasttimo_vnet(void)
1319 {
1320 struct ifqueue scq; /* State-change packets */
1321 struct ifqueue qrq; /* Query response packets */
1322 struct ifnet *ifp;
1323 struct mld_ifinfo *mli;
1324 struct ifmultiaddr *ifma, *tifma;
1325 struct in6_multi *inm;
1326 int uri_fasthz;
1327
1328 uri_fasthz = 0;
1329
1330 /*
1331 * Quick check to see if any work needs to be done, in order to
1332 * minimize the overhead of fasttimo processing.
1333 * SMPng: XXX Unlocked reads.
1334 */
1335 if (!V_current_state_timers_running6 &&
1336 !V_interface_timers_running6 &&
1337 !V_state_change_timers_running6)
1338 return;
1339
1340 IN6_MULTI_LOCK();
1341 MLD_LOCK();
1342
1343 /*
1344 * MLDv2 General Query response timer processing.
1345 */
1346 if (V_interface_timers_running6) {
1347 CTR1(KTR_MLD, "%s: interface timers running", __func__);
1348
1349 V_interface_timers_running6 = 0;
1350 LIST_FOREACH(mli, &V_mli_head, mli_link) {
1351 if (mli->mli_v2_timer == 0) {
1352 /* Do nothing. */
1353 } else if (--mli->mli_v2_timer == 0) {
1354 mld_v2_dispatch_general_query(mli);
1355 } else {
1356 V_interface_timers_running6 = 1;
1357 }
1358 }
1359 }
1360
1361 if (!V_current_state_timers_running6 &&
1362 !V_state_change_timers_running6)
1363 goto out_locked;
1364
1365 V_current_state_timers_running6 = 0;
1366 V_state_change_timers_running6 = 0;
1367
1368 CTR1(KTR_MLD, "%s: state change timers running", __func__);
1369
1370 /*
1371 * MLD host report and state-change timer processing.
1372 * Note: Processing a v2 group timer may remove a node.
1373 */
1374 LIST_FOREACH(mli, &V_mli_head, mli_link) {
1375 ifp = mli->mli_ifp;
1376
1377 if (mli->mli_version == MLD_VERSION_2) {
1378 uri_fasthz = MLD_RANDOM_DELAY(mli->mli_uri *
1379 PR_FASTHZ);
1380
1381 memset(&qrq, 0, sizeof(struct ifqueue));
1382 IFQ_SET_MAXLEN(&qrq, MLD_MAX_G_GS_PACKETS);
1383
1384 memset(&scq, 0, sizeof(struct ifqueue));
1385 IFQ_SET_MAXLEN(&scq, MLD_MAX_STATE_CHANGE_PACKETS);
1386 }
1387
1388 IF_ADDR_LOCK(ifp);
1389 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link,
1390 tifma) {
1391 if (ifma->ifma_addr->sa_family != AF_INET6 ||
1392 ifma->ifma_protospec == NULL)
1393 continue;
1394 inm = (struct in6_multi *)ifma->ifma_protospec;
1395 switch (mli->mli_version) {
1396 case MLD_VERSION_1:
1397 /*
1398 * XXX Drop IF_ADDR lock temporarily to
1399 * avoid recursion caused by a potential
1400 * call by in6ifa_ifpforlinklocal().
1401 * rwlock candidate?
1402 */
1403 IF_ADDR_UNLOCK(ifp);
1404 mld_v1_process_group_timer(inm,
1405 mli->mli_version);
1406 IF_ADDR_LOCK(ifp);
1407 break;
1408 case MLD_VERSION_2:
1409 mld_v2_process_group_timers(mli, &qrq,
1410 &scq, inm, uri_fasthz);
1411 break;
1412 }
1413 }
1414 IF_ADDR_UNLOCK(ifp);
1415
1416 if (mli->mli_version == MLD_VERSION_2) {
1417 struct in6_multi *tinm;
1418
1419 mld_dispatch_queue(&qrq, 0);
1420 mld_dispatch_queue(&scq, 0);
1421
1422 /*
1423 * Free the in_multi reference(s) for
1424 * this lifecycle.
1425 */
1426 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead,
1427 in6m_nrele, tinm) {
1428 SLIST_REMOVE_HEAD(&mli->mli_relinmhead,
1429 in6m_nrele);
1430 in6m_release_locked(inm);
1431 }
1432 }
1433 }
1434
1435 out_locked:
1436 MLD_UNLOCK();
1437 IN6_MULTI_UNLOCK();
1438 }
1439
1440 /*
1441 * Update host report group timer.
1442 * Will update the global pending timer flags.
1443 */
1444 static void
1445 mld_v1_process_group_timer(struct in6_multi *inm, const int version)
1446 {
1447 int report_timer_expired;
1448
1449 IN6_MULTI_LOCK_ASSERT();
1450 MLD_LOCK_ASSERT();
1451
1452 if (inm->in6m_timer == 0) {
1453 report_timer_expired = 0;
1454 } else if (--inm->in6m_timer == 0) {
1455 report_timer_expired = 1;
1456 } else {
1457 V_current_state_timers_running6 = 1;
1458 return;
1459 }
1460
1461 switch (inm->in6m_state) {
1462 case MLD_NOT_MEMBER:
1463 case MLD_SILENT_MEMBER:
1464 case MLD_IDLE_MEMBER:
1465 case MLD_LAZY_MEMBER:
1466 case MLD_SLEEPING_MEMBER:
1467 case MLD_AWAKENING_MEMBER:
1468 break;
1469 case MLD_REPORTING_MEMBER:
1470 if (report_timer_expired) {
1471 inm->in6m_state = MLD_IDLE_MEMBER;
1472 (void)mld_v1_transmit_report(inm,
1473 MLD_LISTENER_REPORT);
1474 }
1475 break;
1476 case MLD_G_QUERY_PENDING_MEMBER:
1477 case MLD_SG_QUERY_PENDING_MEMBER:
1478 case MLD_LEAVING_MEMBER:
1479 break;
1480 }
1481 }
1482
1483 /*
1484 * Update a group's timers for MLDv2.
1485 * Will update the global pending timer flags.
1486 * Note: Unlocked read from mli.
1487 */
1488 static void
1489 mld_v2_process_group_timers(struct mld_ifinfo *mli,
1490 struct ifqueue *qrq, struct ifqueue *scq,
1491 struct in6_multi *inm, const int uri_fasthz)
1492 {
1493 int query_response_timer_expired;
1494 int state_change_retransmit_timer_expired;
1495 #ifdef KTR
1496 char ip6tbuf[INET6_ADDRSTRLEN];
1497 #endif
1498
1499 IN6_MULTI_LOCK_ASSERT();
1500 MLD_LOCK_ASSERT();
1501
1502 query_response_timer_expired = 0;
1503 state_change_retransmit_timer_expired = 0;
1504
1505 /*
1506 * During a transition from compatibility mode back to MLDv2,
1507 * a group record in REPORTING state may still have its group
1508 * timer active. This is a no-op in this function; it is easier
1509 * to deal with it here than to complicate the slow-timeout path.
1510 */
1511 if (inm->in6m_timer == 0) {
1512 query_response_timer_expired = 0;
1513 } else if (--inm->in6m_timer == 0) {
1514 query_response_timer_expired = 1;
1515 } else {
1516 V_current_state_timers_running6 = 1;
1517 }
1518
1519 if (inm->in6m_sctimer == 0) {
1520 state_change_retransmit_timer_expired = 0;
1521 } else if (--inm->in6m_sctimer == 0) {
1522 state_change_retransmit_timer_expired = 1;
1523 } else {
1524 V_state_change_timers_running6 = 1;
1525 }
1526
1527 /* We are in fasttimo, so be quick about it. */
1528 if (!state_change_retransmit_timer_expired &&
1529 !query_response_timer_expired)
1530 return;
1531
1532 switch (inm->in6m_state) {
1533 case MLD_NOT_MEMBER:
1534 case MLD_SILENT_MEMBER:
1535 case MLD_SLEEPING_MEMBER:
1536 case MLD_LAZY_MEMBER:
1537 case MLD_AWAKENING_MEMBER:
1538 case MLD_IDLE_MEMBER:
1539 break;
1540 case MLD_G_QUERY_PENDING_MEMBER:
1541 case MLD_SG_QUERY_PENDING_MEMBER:
1542 /*
1543 * Respond to a previously pending Group-Specific
1544 * or Group-and-Source-Specific query by enqueueing
1545 * the appropriate Current-State report for
1546 * immediate transmission.
1547 */
1548 if (query_response_timer_expired) {
1549 int retval;
1550
1551 retval = mld_v2_enqueue_group_record(qrq, inm, 0, 1,
1552 (inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER));
1553 CTR2(KTR_MLD, "%s: enqueue record = %d",
1554 __func__, retval);
1555 inm->in6m_state = MLD_REPORTING_MEMBER;
1556 in6m_clear_recorded(inm);
1557 }
1558 /* FALLTHROUGH */
1559 case MLD_REPORTING_MEMBER:
1560 case MLD_LEAVING_MEMBER:
1561 if (state_change_retransmit_timer_expired) {
1562 /*
1563 * State-change retransmission timer fired.
1564 * If there are any further pending retransmissions,
1565 * set the global pending state-change flag, and
1566 * reset the timer.
1567 */
1568 if (--inm->in6m_scrv > 0) {
1569 inm->in6m_sctimer = uri_fasthz;
1570 V_state_change_timers_running6 = 1;
1571 }
1572 /*
1573 * Retransmit the previously computed state-change
1574 * report. If there are no further pending
1575 * retransmissions, the mbuf queue will be consumed.
1576 * Update T0 state to T1 as we have now sent
1577 * a state-change.
1578 */
1579 (void)mld_v2_merge_state_changes(inm, scq);
1580
1581 in6m_commit(inm);
1582 CTR3(KTR_MLD, "%s: T1 -> T0 for %s/%s", __func__,
1583 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
1584 inm->in6m_ifp->if_xname);
1585
1586 /*
1587 * If we are leaving the group for good, make sure
1588 * we release MLD's reference to it.
1589 * This release must be deferred using a SLIST,
1590 * as we are called from a loop which traverses
1591 * the in_ifmultiaddr TAILQ.
1592 */
1593 if (inm->in6m_state == MLD_LEAVING_MEMBER &&
1594 inm->in6m_scrv == 0) {
1595 inm->in6m_state = MLD_NOT_MEMBER;
1596 SLIST_INSERT_HEAD(&mli->mli_relinmhead,
1597 inm, in6m_nrele);
1598 }
1599 }
1600 break;
1601 }
1602 }
1603
1604 /*
1605 * Switch to a different version on the given interface,
1606 * as per Section 9.12.
1607 */
1608 static void
1609 mld_set_version(struct mld_ifinfo *mli, const int version)
1610 {
1611 int old_version_timer;
1612
1613 MLD_LOCK_ASSERT();
1614
1615 CTR4(KTR_MLD, "%s: switching to v%d on ifp %p(%s)", __func__,
1616 version, mli->mli_ifp, mli->mli_ifp->if_xname);
1617
1618 if (version == MLD_VERSION_1) {
1619 /*
1620 * Compute the "Older Version Querier Present" timer as per
1621 * Section 9.12.
1622 */
1623 old_version_timer = (mli->mli_rv * mli->mli_qi) + mli->mli_qri;
1624 old_version_timer *= PR_SLOWHZ;
1625 mli->mli_v1_timer = old_version_timer;
1626 }
1627
1628 if (mli->mli_v1_timer > 0 && mli->mli_version != MLD_VERSION_1) {
1629 mli->mli_version = MLD_VERSION_1;
1630 mld_v2_cancel_link_timers(mli);
1631 }
1632 }
1633
1634 /*
1635 * Cancel pending MLDv2 timers for the given link and all groups
1636 * joined on it; state-change, general-query, and group-query timers.
1637 */
1638 static void
1639 mld_v2_cancel_link_timers(struct mld_ifinfo *mli)
1640 {
1641 struct ifmultiaddr *ifma;
1642 struct ifnet *ifp;
1643 struct in6_multi *inm;
1644
1645 CTR3(KTR_MLD, "%s: cancel v2 timers on ifp %p(%s)", __func__,
1646 mli->mli_ifp, mli->mli_ifp->if_xname);
1647
1648 IN6_MULTI_LOCK_ASSERT();
1649 MLD_LOCK_ASSERT();
1650
1651 /*
1652 * Fast-track this potentially expensive operation
1653 * by checking all the global 'timer pending' flags.
1654 */
1655 if (!V_interface_timers_running6 &&
1656 !V_state_change_timers_running6 &&
1657 !V_current_state_timers_running6)
1658 return;
1659
1660 mli->mli_v2_timer = 0;
1661
1662 ifp = mli->mli_ifp;
1663
1664 IF_ADDR_LOCK(ifp);
1665 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1666 if (ifma->ifma_addr->sa_family != AF_INET6)
1667 continue;
1668 inm = (struct in6_multi *)ifma->ifma_protospec;
1669 switch (inm->in6m_state) {
1670 case MLD_NOT_MEMBER:
1671 case MLD_SILENT_MEMBER:
1672 case MLD_IDLE_MEMBER:
1673 case MLD_LAZY_MEMBER:
1674 case MLD_SLEEPING_MEMBER:
1675 case MLD_AWAKENING_MEMBER:
1676 break;
1677 case MLD_LEAVING_MEMBER:
1678 /*
1679 * If we are leaving the group and switching
1680 * version, we need to release the final
1681 * reference held for issuing the INCLUDE {}.
1682 *
1683 * SMPNG: Must drop and re-acquire IF_ADDR_LOCK
1684 * around in6m_release_locked(), as it is not
1685 * a recursive mutex.
1686 */
1687 IF_ADDR_UNLOCK(ifp);
1688 in6m_release_locked(inm);
1689 IF_ADDR_LOCK(ifp);
1690 /* FALLTHROUGH */
1691 case MLD_G_QUERY_PENDING_MEMBER:
1692 case MLD_SG_QUERY_PENDING_MEMBER:
1693 in6m_clear_recorded(inm);
1694 /* FALLTHROUGH */
1695 case MLD_REPORTING_MEMBER:
1696 inm->in6m_sctimer = 0;
1697 inm->in6m_timer = 0;
1698 inm->in6m_state = MLD_REPORTING_MEMBER;
1699 /*
1700 * Free any pending MLDv2 state-change records.
1701 */
1702 _IF_DRAIN(&inm->in6m_scq);
1703 break;
1704 }
1705 }
1706 IF_ADDR_UNLOCK(ifp);
1707 }
1708
1709 /*
1710 * Global slowtimo handler.
1711 * VIMAGE: Timeout handlers are expected to service all vimages.
1712 */
1713 void
1714 mld_slowtimo(void)
1715 {
1716 VNET_ITERATOR_DECL(vnet_iter);
1717
1718 VNET_LIST_RLOCK_NOSLEEP();
1719 VNET_FOREACH(vnet_iter) {
1720 CURVNET_SET(vnet_iter);
1721 mld_slowtimo_vnet();
1722 CURVNET_RESTORE();
1723 }
1724 VNET_LIST_RUNLOCK_NOSLEEP();
1725 }
1726
1727 /*
1728 * Per-vnet slowtimo handler.
1729 */
1730 static void
1731 mld_slowtimo_vnet(void)
1732 {
1733 struct mld_ifinfo *mli;
1734
1735 MLD_LOCK();
1736
1737 LIST_FOREACH(mli, &V_mli_head, mli_link) {
1738 mld_v1_process_querier_timers(mli);
1739 }
1740
1741 MLD_UNLOCK();
1742 }
1743
1744 /*
1745 * Update the Older Version Querier Present timers for a link.
1746 * See Section 9.12 of RFC 3810.
1747 */
1748 static void
1749 mld_v1_process_querier_timers(struct mld_ifinfo *mli)
1750 {
1751
1752 MLD_LOCK_ASSERT();
1753
1754 if (mli->mli_version != MLD_VERSION_2 && --mli->mli_v1_timer == 0) {
1755 /*
1756 * MLDv1 Querier Present timer expired; revert to MLDv2.
1757 */
1758 CTR5(KTR_MLD,
1759 "%s: transition from v%d -> v%d on %p(%s)",
1760 __func__, mli->mli_version, MLD_VERSION_2,
1761 mli->mli_ifp, mli->mli_ifp->if_xname);
1762 mli->mli_version = MLD_VERSION_2;
1763 }
1764 }
1765
1766 /*
1767 * Transmit an MLDv1 report immediately.
1768 */
1769 static int
1770 mld_v1_transmit_report(struct in6_multi *in6m, const int type)
1771 {
1772 struct ifnet *ifp;
1773 struct in6_ifaddr *ia;
1774 struct ip6_hdr *ip6;
1775 struct mbuf *mh, *md;
1776 struct mld_hdr *mld;
1777
1778 IN6_MULTI_LOCK_ASSERT();
1779 MLD_LOCK_ASSERT();
1780
1781 ifp = in6m->in6m_ifp;
1782 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
1783 /* ia may be NULL if link-local address is tentative. */
1784
1785 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
1786 if (mh == NULL) {
1787 if (ia != NULL)
1788 ifa_free(&ia->ia_ifa);
1789 return (ENOMEM);
1790 }
1791 MGET(md, M_DONTWAIT, MT_DATA);
1792 if (md == NULL) {
1793 m_free(mh);
1794 if (ia != NULL)
1795 ifa_free(&ia->ia_ifa);
1796 return (ENOMEM);
1797 }
1798 mh->m_next = md;
1799
1800 /*
1801 * FUTURE: Consider increasing alignment by ETHER_HDR_LEN, so
1802 * that ether_output() does not need to allocate another mbuf
1803 * for the header in the most common case.
1804 */
1805 MH_ALIGN(mh, sizeof(struct ip6_hdr));
1806 mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld_hdr);
1807 mh->m_len = sizeof(struct ip6_hdr);
1808
1809 ip6 = mtod(mh, struct ip6_hdr *);
1810 ip6->ip6_flow = 0;
1811 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1812 ip6->ip6_vfc |= IPV6_VERSION;
1813 ip6->ip6_nxt = IPPROTO_ICMPV6;
1814 ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
1815 ip6->ip6_dst = in6m->in6m_addr;
1816
1817 md->m_len = sizeof(struct mld_hdr);
1818 mld = mtod(md, struct mld_hdr *);
1819 mld->mld_type = type;
1820 mld->mld_code = 0;
1821 mld->mld_cksum = 0;
1822 mld->mld_maxdelay = 0;
1823 mld->mld_reserved = 0;
1824 mld->mld_addr = in6m->in6m_addr;
1825 in6_clearscope(&mld->mld_addr);
1826 mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6,
1827 sizeof(struct ip6_hdr), sizeof(struct mld_hdr));
1828
1829 mld_save_context(mh, ifp);
1830 mh->m_flags |= M_MLDV1;
1831
1832 mld_dispatch_packet(mh);
1833
1834 if (ia != NULL)
1835 ifa_free(&ia->ia_ifa);
1836 return (0);
1837 }
1838
1839 /*
1840 * Process a state change from the upper layer for the given IPv6 group.
1841 *
1842 * Each socket holds a reference on the in_multi in its own ip_moptions.
1843 * The socket layer will have made the necessary updates to.the group
1844 * state, it is now up to MLD to issue a state change report if there
1845 * has been any change between T0 (when the last state-change was issued)
1846 * and T1 (now).
1847 *
1848 * We use the MLDv2 state machine at group level. The MLd module
1849 * however makes the decision as to which MLD protocol version to speak.
1850 * A state change *from* INCLUDE {} always means an initial join.
1851 * A state change *to* INCLUDE {} always means a final leave.
1852 *
1853 * If delay is non-zero, and the state change is an initial multicast
1854 * join, the state change report will be delayed by 'delay' ticks
1855 * in units of PR_FASTHZ if MLDv1 is active on the link; otherwise
1856 * the initial MLDv2 state change report will be delayed by whichever
1857 * is sooner, a pending state-change timer or delay itself.
1858 *
1859 * VIMAGE: curvnet should have been set by caller, as this routine
1860 * is called from the socket option handlers.
1861 */
1862 int
1863 mld_change_state(struct in6_multi *inm, const int delay)
1864 {
1865 struct mld_ifinfo *mli;
1866 struct ifnet *ifp;
1867 int error;
1868
1869 IN6_MULTI_LOCK_ASSERT();
1870
1871 error = 0;
1872
1873 /*
1874 * Try to detect if the upper layer just asked us to change state
1875 * for an interface which has now gone away.
1876 */
1877 KASSERT(inm->in6m_ifma != NULL, ("%s: no ifma", __func__));
1878 ifp = inm->in6m_ifma->ifma_ifp;
1879 if (ifp != NULL) {
1880 /*
1881 * Sanity check that netinet6's notion of ifp is the
1882 * same as net's.
1883 */
1884 KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__));
1885 }
1886
1887 MLD_LOCK();
1888
1889 mli = MLD_IFINFO(ifp);
1890 KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
1891
1892 /*
1893 * If we detect a state transition to or from MCAST_UNDEFINED
1894 * for this group, then we are starting or finishing an MLD
1895 * life cycle for this group.
1896 */
1897 if (inm->in6m_st[1].iss_fmode != inm->in6m_st[0].iss_fmode) {
1898 CTR3(KTR_MLD, "%s: inm transition %d -> %d", __func__,
1899 inm->in6m_st[0].iss_fmode, inm->in6m_st[1].iss_fmode);
1900 if (inm->in6m_st[0].iss_fmode == MCAST_UNDEFINED) {
1901 CTR1(KTR_MLD, "%s: initial join", __func__);
1902 error = mld_initial_join(inm, mli, delay);
1903 goto out_locked;
1904 } else if (inm->in6m_st[1].iss_fmode == MCAST_UNDEFINED) {
1905 CTR1(KTR_MLD, "%s: final leave", __func__);
1906 mld_final_leave(inm, mli);
1907 goto out_locked;
1908 }
1909 } else {
1910 CTR1(KTR_MLD, "%s: filter set change", __func__);
1911 }
1912
1913 error = mld_handle_state_change(inm, mli);
1914
1915 out_locked:
1916 MLD_UNLOCK();
1917 return (error);
1918 }
1919
1920 /*
1921 * Perform the initial join for an MLD group.
1922 *
1923 * When joining a group:
1924 * If the group should have its MLD traffic suppressed, do nothing.
1925 * MLDv1 starts sending MLDv1 host membership reports.
1926 * MLDv2 will schedule an MLDv2 state-change report containing the
1927 * initial state of the membership.
1928 *
1929 * If the delay argument is non-zero, then we must delay sending the
1930 * initial state change for delay ticks (in units of PR_FASTHZ).
1931 */
1932 static int
1933 mld_initial_join(struct in6_multi *inm, struct mld_ifinfo *mli,
1934 const int delay)
1935 {
1936 struct ifnet *ifp;
1937 struct ifqueue *ifq;
1938 int error, retval, syncstates;
1939 int odelay;
1940 #ifdef KTR
1941 char ip6tbuf[INET6_ADDRSTRLEN];
1942 #endif
1943
1944 CTR4(KTR_MLD, "%s: initial join %s on ifp %p(%s)",
1945 __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr),
1946 inm->in6m_ifp, inm->in6m_ifp->if_xname);
1947
1948 error = 0;
1949 syncstates = 1;
1950
1951 ifp = inm->in6m_ifp;
1952
1953 IN6_MULTI_LOCK_ASSERT();
1954 MLD_LOCK_ASSERT();
1955
1956 KASSERT(mli && mli->mli_ifp == ifp, ("%s: inconsistent ifp", __func__));
1957
1958 /*
1959 * Groups joined on loopback or marked as 'not reported',
1960 * enter the MLD_SILENT_MEMBER state and
1961 * are never reported in any protocol exchanges.
1962 * All other groups enter the appropriate state machine
1963 * for the version in use on this link.
1964 * A link marked as MLIF_SILENT causes MLD to be completely
1965 * disabled for the link.
1966 */
1967 if ((ifp->if_flags & IFF_LOOPBACK) ||
1968 (mli->mli_flags & MLIF_SILENT) ||
1969 !mld_is_addr_reported(&inm->in6m_addr)) {
1970 CTR1(KTR_MLD,
1971 "%s: not kicking state machine for silent group", __func__);
1972 inm->in6m_state = MLD_SILENT_MEMBER;
1973 inm->in6m_timer = 0;
1974 } else {
1975 /*
1976 * Deal with overlapping in_multi lifecycle.
1977 * If this group was LEAVING, then make sure
1978 * we drop the reference we picked up to keep the
1979 * group around for the final INCLUDE {} enqueue.
1980 */
1981 if (mli->mli_version == MLD_VERSION_2 &&
1982 inm->in6m_state == MLD_LEAVING_MEMBER)
1983 in6m_release_locked(inm);
1984
1985 inm->in6m_state = MLD_REPORTING_MEMBER;
1986
1987 switch (mli->mli_version) {
1988 case MLD_VERSION_1:
1989 /*
1990 * If a delay was provided, only use it if
1991 * it is greater than the delay normally
1992 * used for an MLDv1 state change report,
1993 * and delay sending the initial MLDv1 report
1994 * by not transitioning to the IDLE state.
1995 */
1996 odelay = MLD_RANDOM_DELAY(MLD_V1_MAX_RI * PR_FASTHZ);
1997 if (delay) {
1998 inm->in6m_timer = max(delay, odelay);
1999 V_current_state_timers_running6 = 1;
2000 } else {
2001 inm->in6m_state = MLD_IDLE_MEMBER;
2002 error = mld_v1_transmit_report(inm,
2003 MLD_LISTENER_REPORT);
2004 if (error == 0) {
2005 inm->in6m_timer = odelay;
2006 V_current_state_timers_running6 = 1;
2007 }
2008 }
2009 break;
2010
2011 case MLD_VERSION_2:
2012 /*
2013 * Defer update of T0 to T1, until the first copy
2014 * of the state change has been transmitted.
2015 */
2016 syncstates = 0;
2017
2018 /*
2019 * Immediately enqueue a State-Change Report for
2020 * this interface, freeing any previous reports.
2021 * Don't kick the timers if there is nothing to do,
2022 * or if an error occurred.
2023 */
2024 ifq = &inm->in6m_scq;
2025 _IF_DRAIN(ifq);
2026 retval = mld_v2_enqueue_group_record(ifq, inm, 1,
2027 0, 0);
2028 CTR2(KTR_MLD, "%s: enqueue record = %d",
2029 __func__, retval);
2030 if (retval <= 0) {
2031 error = retval * -1;
2032 break;
2033 }
2034
2035 /*
2036 * Schedule transmission of pending state-change
2037 * report up to RV times for this link. The timer
2038 * will fire at the next mld_fasttimo (~200ms),
2039 * giving us an opportunity to merge the reports.
2040 *
2041 * If a delay was provided to this function, only
2042 * use this delay if sooner than the existing one.
2043 */
2044 KASSERT(mli->mli_rv > 1,
2045 ("%s: invalid robustness %d", __func__,
2046 mli->mli_rv));
2047 inm->in6m_scrv = mli->mli_rv;
2048 if (delay) {
2049 if (inm->in6m_sctimer > 1) {
2050 inm->in6m_sctimer =
2051 min(inm->in6m_sctimer, delay);
2052 } else
2053 inm->in6m_sctimer = delay;
2054 } else
2055 inm->in6m_sctimer = 1;
2056 V_state_change_timers_running6 = 1;
2057
2058 error = 0;
2059 break;
2060 }
2061 }
2062
2063 /*
2064 * Only update the T0 state if state change is atomic,
2065 * i.e. we don't need to wait for a timer to fire before we
2066 * can consider the state change to have been communicated.
2067 */
2068 if (syncstates) {
2069 in6m_commit(inm);
2070 CTR3(KTR_MLD, "%s: T1 -> T0 for %s/%s", __func__,
2071 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2072 inm->in6m_ifp->if_xname);
2073 }
2074
2075 return (error);
2076 }
2077
2078 /*
2079 * Issue an intermediate state change during the life-cycle.
2080 */
2081 static int
2082 mld_handle_state_change(struct in6_multi *inm, struct mld_ifinfo *mli)
2083 {
2084 struct ifnet *ifp;
2085 int retval;
2086 #ifdef KTR
2087 char ip6tbuf[INET6_ADDRSTRLEN];
2088 #endif
2089
2090 CTR4(KTR_MLD, "%s: state change for %s on ifp %p(%s)",
2091 __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2092 inm->in6m_ifp, inm->in6m_ifp->if_xname);
2093
2094 ifp = inm->in6m_ifp;
2095
2096 IN6_MULTI_LOCK_ASSERT();
2097 MLD_LOCK_ASSERT();
2098
2099 KASSERT(mli && mli->mli_ifp == ifp,
2100 ("%s: inconsistent ifp", __func__));
2101
2102 if ((ifp->if_flags & IFF_LOOPBACK) ||
2103 (mli->mli_flags & MLIF_SILENT) ||
2104 !mld_is_addr_reported(&inm->in6m_addr) ||
2105 (mli->mli_version != MLD_VERSION_2)) {
2106 if (!mld_is_addr_reported(&inm->in6m_addr)) {
2107 CTR1(KTR_MLD,
2108 "%s: not kicking state machine for silent group", __func__);
2109 }
2110 CTR1(KTR_MLD, "%s: nothing to do", __func__);
2111 in6m_commit(inm);
2112 CTR3(KTR_MLD, "%s: T1 -> T0 for %s/%s", __func__,
2113 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2114 inm->in6m_ifp->if_xname);
2115 return (0);
2116 }
2117
2118 _IF_DRAIN(&inm->in6m_scq);
2119
2120 retval = mld_v2_enqueue_group_record(&inm->in6m_scq, inm, 1, 0, 0);
2121 CTR2(KTR_MLD, "%s: enqueue record = %d", __func__, retval);
2122 if (retval <= 0)
2123 return (-retval);
2124
2125 /*
2126 * If record(s) were enqueued, start the state-change
2127 * report timer for this group.
2128 */
2129 inm->in6m_scrv = mli->mli_rv;
2130 inm->in6m_sctimer = 1;
2131 V_state_change_timers_running6 = 1;
2132
2133 return (0);
2134 }
2135
2136 /*
2137 * Perform the final leave for a multicast address.
2138 *
2139 * When leaving a group:
2140 * MLDv1 sends a DONE message, if and only if we are the reporter.
2141 * MLDv2 enqueues a state-change report containing a transition
2142 * to INCLUDE {} for immediate transmission.
2143 */
2144 static void
2145 mld_final_leave(struct in6_multi *inm, struct mld_ifinfo *mli)
2146 {
2147 int syncstates;
2148 #ifdef KTR
2149 char ip6tbuf[INET6_ADDRSTRLEN];
2150 #endif
2151
2152 syncstates = 1;
2153
2154 CTR4(KTR_MLD, "%s: final leave %s on ifp %p(%s)",
2155 __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2156 inm->in6m_ifp, inm->in6m_ifp->if_xname);
2157
2158 IN6_MULTI_LOCK_ASSERT();
2159 MLD_LOCK_ASSERT();
2160
2161 switch (inm->in6m_state) {
2162 case MLD_NOT_MEMBER:
2163 case MLD_SILENT_MEMBER:
2164 case MLD_LEAVING_MEMBER:
2165 /* Already leaving or left; do nothing. */
2166 CTR1(KTR_MLD,
2167 "%s: not kicking state machine for silent group", __func__);
2168 break;
2169 case MLD_REPORTING_MEMBER:
2170 case MLD_IDLE_MEMBER:
2171 case MLD_G_QUERY_PENDING_MEMBER:
2172 case MLD_SG_QUERY_PENDING_MEMBER:
2173 if (mli->mli_version == MLD_VERSION_1) {
2174 #ifdef INVARIANTS
2175 if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER ||
2176 inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER)
2177 panic("%s: MLDv2 state reached, not MLDv2 mode",
2178 __func__);
2179 #endif
2180 mld_v1_transmit_report(inm, MLD_LISTENER_DONE);
2181 inm->in6m_state = MLD_NOT_MEMBER;
2182 } else if (mli->mli_version == MLD_VERSION_2) {
2183 /*
2184 * Stop group timer and all pending reports.
2185 * Immediately enqueue a state-change report
2186 * TO_IN {} to be sent on the next fast timeout,
2187 * giving us an opportunity to merge reports.
2188 */
2189 _IF_DRAIN(&inm->in6m_scq);
2190 inm->in6m_timer = 0;
2191 inm->in6m_scrv = mli->mli_rv;
2192 CTR4(KTR_MLD, "%s: Leaving %s/%s with %d "
2193 "pending retransmissions.", __func__,
2194 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2195 inm->in6m_ifp->if_xname, inm->in6m_scrv);
2196 if (inm->in6m_scrv == 0) {
2197 inm->in6m_state = MLD_NOT_MEMBER;
2198 inm->in6m_sctimer = 0;
2199 } else {
2200 int retval;
2201
2202 in6m_acquire_locked(inm);
2203
2204 retval = mld_v2_enqueue_group_record(
2205 &inm->in6m_scq, inm, 1, 0, 0);
2206 KASSERT(retval != 0,
2207 ("%s: enqueue record = %d", __func__,
2208 retval));
2209
2210 inm->in6m_state = MLD_LEAVING_MEMBER;
2211 inm->in6m_sctimer = 1;
2212 V_state_change_timers_running6 = 1;
2213 syncstates = 0;
2214 }
2215 break;
2216 }
2217 break;
2218 case MLD_LAZY_MEMBER:
2219 case MLD_SLEEPING_MEMBER:
2220 case MLD_AWAKENING_MEMBER:
2221 /* Our reports are suppressed; do nothing. */
2222 break;
2223 }
2224
2225 if (syncstates) {
2226 in6m_commit(inm);
2227 CTR3(KTR_MLD, "%s: T1 -> T0 for %s/%s", __func__,
2228 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2229 inm->in6m_ifp->if_xname);
2230 inm->in6m_st[1].iss_fmode = MCAST_UNDEFINED;
2231 CTR3(KTR_MLD, "%s: T1 now MCAST_UNDEFINED for %p/%s",
2232 __func__, &inm->in6m_addr, inm->in6m_ifp->if_xname);
2233 }
2234 }
2235
2236 /*
2237 * Enqueue an MLDv2 group record to the given output queue.
2238 *
2239 * If is_state_change is zero, a current-state record is appended.
2240 * If is_state_change is non-zero, a state-change report is appended.
2241 *
2242 * If is_group_query is non-zero, an mbuf packet chain is allocated.
2243 * If is_group_query is zero, and if there is a packet with free space
2244 * at the tail of the queue, it will be appended to providing there
2245 * is enough free space.
2246 * Otherwise a new mbuf packet chain is allocated.
2247 *
2248 * If is_source_query is non-zero, each source is checked to see if
2249 * it was recorded for a Group-Source query, and will be omitted if
2250 * it is not both in-mode and recorded.
2251 *
2252 * The function will attempt to allocate leading space in the packet
2253 * for the IPv6+ICMP headers to be prepended without fragmenting the chain.
2254 *
2255 * If successful the size of all data appended to the queue is returned,
2256 * otherwise an error code less than zero is returned, or zero if
2257 * no record(s) were appended.
2258 */
2259 static int
2260 mld_v2_enqueue_group_record(struct ifqueue *ifq, struct in6_multi *inm,
2261 const int is_state_change, const int is_group_query,
2262 const int is_source_query)
2263 {
2264 struct mldv2_record mr;
2265 struct mldv2_record *pmr;
2266 struct ifnet *ifp;
2267 struct ip6_msource *ims, *nims;
2268 struct mbuf *m0, *m, *md;
2269 int error, is_filter_list_change;
2270 int minrec0len, m0srcs, msrcs, nbytes, off;
2271 int record_has_sources;
2272 int now;
2273 int type;
2274 uint8_t mode;
2275 #ifdef KTR
2276 char ip6tbuf[INET6_ADDRSTRLEN];
2277 #endif
2278
2279 IN6_MULTI_LOCK_ASSERT();
2280
2281 error = 0;
2282 ifp = inm->in6m_ifp;
2283 is_filter_list_change = 0;
2284 m = NULL;
2285 m0 = NULL;
2286 m0srcs = 0;
2287 msrcs = 0;
2288 nbytes = 0;
2289 nims = NULL;
2290 record_has_sources = 1;
2291 pmr = NULL;
2292 type = MLD_DO_NOTHING;
2293 mode = inm->in6m_st[1].iss_fmode;
2294
2295 /*
2296 * If we did not transition out of ASM mode during t0->t1,
2297 * and there are no source nodes to process, we can skip
2298 * the generation of source records.
2299 */
2300 if (inm->in6m_st[0].iss_asm > 0 && inm->in6m_st[1].iss_asm > 0 &&
2301 inm->in6m_nsrc == 0)
2302 record_has_sources = 0;
2303
2304 if (is_state_change) {
2305 /*
2306 * Queue a state change record.
2307 * If the mode did not change, and there are non-ASM
2308 * listeners or source filters present,
2309 * we potentially need to issue two records for the group.
2310 * If we are transitioning to MCAST_UNDEFINED, we need
2311 * not send any sources.
2312 * If there are ASM listeners, and there was no filter
2313 * mode transition of any kind, do nothing.
2314 */
2315 if (mode != inm->in6m_st[0].iss_fmode) {
2316 if (mode == MCAST_EXCLUDE) {
2317 CTR1(KTR_MLD, "%s: change to EXCLUDE",
2318 __func__);
2319 type = MLD_CHANGE_TO_EXCLUDE_MODE;
2320 } else {
2321 CTR1(KTR_MLD, "%s: change to INCLUDE",
2322 __func__);
2323 type = MLD_CHANGE_TO_INCLUDE_MODE;
2324 if (mode == MCAST_UNDEFINED)
2325 record_has_sources = 0;
2326 }
2327 } else {
2328 if (record_has_sources) {
2329 is_filter_list_change = 1;
2330 } else {
2331 type = MLD_DO_NOTHING;
2332 }
2333 }
2334 } else {
2335 /*
2336 * Queue a current state record.
2337 */
2338 if (mode == MCAST_EXCLUDE) {
2339 type = MLD_MODE_IS_EXCLUDE;
2340 } else if (mode == MCAST_INCLUDE) {
2341 type = MLD_MODE_IS_INCLUDE;
2342 KASSERT(inm->in6m_st[1].iss_asm == 0,
2343 ("%s: inm %p is INCLUDE but ASM count is %d",
2344 __func__, inm, inm->in6m_st[1].iss_asm));
2345 }
2346 }
2347
2348 /*
2349 * Generate the filter list changes using a separate function.
2350 */
2351 if (is_filter_list_change)
2352 return (mld_v2_enqueue_filter_change(ifq, inm));
2353
2354 if (type == MLD_DO_NOTHING) {
2355 CTR3(KTR_MLD, "%s: nothing to do for %s/%s",
2356 __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2357 inm->in6m_ifp->if_xname);
2358 return (0);
2359 }
2360
2361 /*
2362 * If any sources are present, we must be able to fit at least
2363 * one in the trailing space of the tail packet's mbuf,
2364 * ideally more.
2365 */
2366 minrec0len = sizeof(struct mldv2_record);
2367 if (record_has_sources)
2368 minrec0len += sizeof(struct in6_addr);
2369
2370 CTR4(KTR_MLD, "%s: queueing %s for %s/%s", __func__,
2371 mld_rec_type_to_str(type),
2372 ip6_sprintf(ip6tbuf, &inm->in6m_addr),
2373 inm->in6m_ifp->if_xname);
2374
2375 /*
2376 * Check if we have a packet in the tail of the queue for this
2377 * group into which the first group record for this group will fit.
2378 * Otherwise allocate a new packet.
2379 * Always allocate leading space for IP6+RA+ICMPV6+REPORT.
2380 * Note: Group records for G/GSR query responses MUST be sent
2381 * in their own packet.
2382 */
2383 m0 = ifq->ifq_tail;
2384 if (!is_group_query &&
2385 m0 != NULL &&
2386 (m0->m_pkthdr.PH_vt.vt_nrecs + 1 <= MLD_V2_REPORT_MAXRECS) &&
2387 (m0->m_pkthdr.len + minrec0len) <
2388 (ifp->if_mtu - MLD_MTUSPACE)) {
2389 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len -
2390 sizeof(struct mldv2_record)) /
2391 sizeof(struct in6_addr);
2392 m = m0;
2393 CTR1(KTR_MLD, "%s: use existing packet", __func__);
2394 } else {
2395 if (_IF_QFULL(ifq)) {
2396 CTR1(KTR_MLD, "%s: outbound queue full", __func__);
2397 return (-ENOMEM);
2398 }
2399 m = NULL;
2400 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
2401 sizeof(struct mldv2_record)) / sizeof(struct in6_addr);
2402 if (!is_state_change && !is_group_query)
2403 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2404 if (m == NULL)
2405 m = m_gethdr(M_DONTWAIT, MT_DATA);
2406 if (m == NULL)
2407 return (-ENOMEM);
2408
2409 mld_save_context(m, ifp);
2410
2411 CTR1(KTR_MLD, "%s: allocated first packet", __func__);
2412 }
2413
2414 /*
2415 * Append group record.
2416 * If we have sources, we don't know how many yet.
2417 */
2418 mr.mr_type = type;
2419 mr.mr_datalen = 0;
2420 mr.mr_numsrc = 0;
2421 mr.mr_addr = inm->in6m_addr;
2422 in6_clearscope(&mr.mr_addr);
2423 if (!m_append(m, sizeof(struct mldv2_record), (void *)&mr)) {
2424 if (m != m0)
2425 m_freem(m);
2426 CTR1(KTR_MLD, "%s: m_append() failed.", __func__);
2427 return (-ENOMEM);
2428 }
2429 nbytes += sizeof(struct mldv2_record);
2430
2431 /*
2432 * Append as many sources as will fit in the first packet.
2433 * If we are appending to a new packet, the chain allocation
2434 * may potentially use clusters; use m_getptr() in this case.
2435 * If we are appending to an existing packet, we need to obtain
2436 * a pointer to the group record after m_append(), in case a new
2437 * mbuf was allocated.
2438 * Only append sources which are in-mode at t1. If we are
2439 * transitioning to MCAST_UNDEFINED state on the group, do not
2440 * include source entries.
2441 * Only report recorded sources in our filter set when responding
2442 * to a group-source query.
2443 */
2444 if (record_has_sources) {
2445 if (m == m0) {
2446 md = m_last(m);
2447 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) +
2448 md->m_len - nbytes);
2449 } else {
2450 md = m_getptr(m, 0, &off);
2451 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) +
2452 off);
2453 }
2454 msrcs = 0;
2455 RB_FOREACH_SAFE(ims, ip6_msource_tree, &inm->in6m_srcs,
2456 nims) {
2457 CTR2(KTR_MLD, "%s: visit node %s", __func__,
2458 ip6_sprintf(ip6tbuf, &ims->im6s_addr));
2459 now = im6s_get_mode(inm, ims, 1);
2460 CTR2(KTR_MLD, "%s: node is %d", __func__, now);
2461 if ((now != mode) ||
2462 (now == mode && mode == MCAST_UNDEFINED)) {
2463 CTR1(KTR_MLD, "%s: skip node", __func__);
2464 continue;
2465 }
2466 if (is_source_query && ims->im6s_stp == 0) {
2467 CTR1(KTR_MLD, "%s: skip unrecorded node",
2468 __func__);
2469 continue;
2470 }
2471 CTR1(KTR_MLD, "%s: append node", __func__);
2472 if (!m_append(m, sizeof(struct in6_addr),
2473 (void *)&ims->im6s_addr)) {
2474 if (m != m0)
2475 m_freem(m);
2476 CTR1(KTR_MLD, "%s: m_append() failed.",
2477 __func__);
2478 return (-ENOMEM);
2479 }
2480 nbytes += sizeof(struct in6_addr);
2481 ++msrcs;
2482 if (msrcs == m0srcs)
2483 break;
2484 }
2485 CTR2(KTR_MLD, "%s: msrcs is %d this packet", __func__,
2486 msrcs);
2487 pmr->mr_numsrc = htons(msrcs);
2488 nbytes += (msrcs * sizeof(struct in6_addr));
2489 }
2490
2491 if (is_source_query && msrcs == 0) {
2492 CTR1(KTR_MLD, "%s: no recorded sources to report", __func__);
2493 if (m != m0)
2494 m_freem(m);
2495 return (0);
2496 }
2497
2498 /*
2499 * We are good to go with first packet.
2500 */
2501 if (m != m0) {
2502 CTR1(KTR_MLD, "%s: enqueueing first packet", __func__);
2503 m->m_pkthdr.PH_vt.vt_nrecs = 1;
2504 _IF_ENQUEUE(ifq, m);
2505 } else
2506 m->m_pkthdr.PH_vt.vt_nrecs++;
2507
2508 /*
2509 * No further work needed if no source list in packet(s).
2510 */
2511 if (!record_has_sources)
2512 return (nbytes);
2513
2514 /*
2515 * Whilst sources remain to be announced, we need to allocate
2516 * a new packet and fill out as many sources as will fit.
2517 * Always try for a cluster first.
2518 */
2519 while (nims != NULL) {
2520 if (_IF_QFULL(ifq)) {
2521 CTR1(KTR_MLD, "%s: outbound queue full", __func__);
2522 return (-ENOMEM);
2523 }
2524 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2525 if (m == NULL)
2526 m = m_gethdr(M_DONTWAIT, MT_DATA);
2527 if (m == NULL)
2528 return (-ENOMEM);
2529 mld_save_context(m, ifp);
2530 md = m_getptr(m, 0, &off);
2531 pmr = (struct mldv2_record *)(mtod(md, uint8_t *) + off);
2532 CTR1(KTR_MLD, "%s: allocated next packet", __func__);
2533
2534 if (!m_append(m, sizeof(struct mldv2_record), (void *)&mr)) {
2535 if (m != m0)
2536 m_freem(m);
2537 CTR1(KTR_MLD, "%s: m_append() failed.", __func__);
2538 return (-ENOMEM);
2539 }
2540 m->m_pkthdr.PH_vt.vt_nrecs = 1;
2541 nbytes += sizeof(struct mldv2_record);
2542
2543 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
2544 sizeof(struct mldv2_record)) / sizeof(struct in6_addr);
2545
2546 msrcs = 0;
2547 RB_FOREACH_FROM(ims, ip6_msource_tree, nims) {
2548 CTR2(KTR_MLD, "%s: visit node %s",
2549 __func__, ip6_sprintf(ip6tbuf, &ims->im6s_addr));
2550 now = im6s_get_mode(inm, ims, 1);
2551 if ((now != mode) ||
2552 (now == mode && mode == MCAST_UNDEFINED)) {
2553 CTR1(KTR_MLD, "%s: skip node", __func__);
2554 continue;
2555 }
2556 if (is_source_query && ims->im6s_stp == 0) {
2557 CTR1(KTR_MLD, "%s: skip unrecorded node",
2558 __func__);
2559 continue;
2560 }
2561 CTR1(KTR_MLD, "%s: append node", __func__);
2562 if (!m_append(m, sizeof(struct in6_addr),
2563 (void *)&ims->im6s_addr)) {
2564 if (m != m0)
2565 m_freem(m);
2566 CTR1(KTR_MLD, "%s: m_append() failed.",
2567 __func__);
2568 return (-ENOMEM);
2569 }
2570 ++msrcs;
2571 if (msrcs == m0srcs)
2572 break;
2573 }
2574 pmr->mr_numsrc = htons(msrcs);
2575 nbytes += (msrcs * sizeof(struct in6_addr));
2576
2577 CTR1(KTR_MLD, "%s: enqueueing next packet", __func__);
2578 _IF_ENQUEUE(ifq, m);
2579 }
2580
2581 return (nbytes);
2582 }
2583
2584 /*
2585 * Type used to mark record pass completion.
2586 * We exploit the fact we can cast to this easily from the
2587 * current filter modes on each ip_msource node.
2588 */
2589 typedef enum {
2590 REC_NONE = 0x00, /* MCAST_UNDEFINED */
2591 REC_ALLOW = 0x01, /* MCAST_INCLUDE */
2592 REC_BLOCK = 0x02, /* MCAST_EXCLUDE */
2593 REC_FULL = REC_ALLOW | REC_BLOCK
2594 } rectype_t;
2595
2596 /*
2597 * Enqueue an MLDv2 filter list change to the given output queue.
2598 *
2599 * Source list filter state is held in an RB-tree. When the filter list
2600 * for a group is changed without changing its mode, we need to compute
2601 * the deltas between T0 and T1 for each source in the filter set,
2602 * and enqueue the appropriate ALLOW_NEW/BLOCK_OLD records.
2603 *
2604 * As we may potentially queue two record types, and the entire R-B tree
2605 * needs to be walked at once, we break this out into its own function
2606 * so we can generate a tightly packed queue of packets.
2607 *
2608 * XXX This could be written to only use one tree walk, although that makes
2609 * serializing into the mbuf chains a bit harder. For now we do two walks
2610 * which makes things easier on us, and it may or may not be harder on
2611 * the L2 cache.
2612 *
2613 * If successful the size of all data appended to the queue is returned,
2614 * otherwise an error code less than zero is returned, or zero if
2615 * no record(s) were appended.
2616 */
2617 static int
2618 mld_v2_enqueue_filter_change(struct ifqueue *ifq, struct in6_multi *inm)
2619 {
2620 static const int MINRECLEN =
2621 sizeof(struct mldv2_record) + sizeof(struct in6_addr);
2622 struct ifnet *ifp;
2623 struct mldv2_record mr;
2624 struct mldv2_record *pmr;
2625 struct ip6_msource *ims, *nims;
2626 struct mbuf *m, *m0, *md;
2627 int m0srcs, nbytes, npbytes, off, rsrcs, schanged;
2628 int nallow, nblock;
2629 uint8_t mode, now, then;
2630 rectype_t crt, drt, nrt;
2631 #ifdef KTR
2632 char ip6tbuf[INET6_ADDRSTRLEN];
2633 #endif
2634
2635 IN6_MULTI_LOCK_ASSERT();
2636
2637 if (inm->in6m_nsrc == 0 ||
2638 (inm->in6m_st[0].iss_asm > 0 && inm->in6m_st[1].iss_asm > 0))
2639 return (0);
2640
2641 ifp = inm->in6m_ifp; /* interface */
2642 mode = inm->in6m_st[1].iss_fmode; /* filter mode at t1 */
2643 crt = REC_NONE; /* current group record type */
2644 drt = REC_NONE; /* mask of completed group record types */
2645 nrt = REC_NONE; /* record type for current node */
2646 m0srcs = 0; /* # source which will fit in current mbuf chain */
2647 npbytes = 0; /* # of bytes appended this packet */
2648 nbytes = 0; /* # of bytes appended to group's state-change queue */
2649 rsrcs = 0; /* # sources encoded in current record */
2650 schanged = 0; /* # nodes encoded in overall filter change */
2651 nallow = 0; /* # of source entries in ALLOW_NEW */
2652 nblock = 0; /* # of source entries in BLOCK_OLD */
2653 nims = NULL; /* next tree node pointer */
2654
2655 /*
2656 * For each possible filter record mode.
2657 * The first kind of source we encounter tells us which
2658 * is the first kind of record we start appending.
2659 * If a node transitioned to UNDEFINED at t1, its mode is treated
2660 * as the inverse of the group's filter mode.
2661 */
2662 while (drt != REC_FULL) {
2663 do {
2664 m0 = ifq->ifq_tail;
2665 if (m0 != NULL &&
2666 (m0->m_pkthdr.PH_vt.vt_nrecs + 1 <=
2667 MLD_V2_REPORT_MAXRECS) &&
2668 (m0->m_pkthdr.len + MINRECLEN) <
2669 (ifp->if_mtu - MLD_MTUSPACE)) {
2670 m = m0;
2671 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len -
2672 sizeof(struct mldv2_record)) /
2673 sizeof(struct in6_addr);
2674 CTR1(KTR_MLD,
2675 "%s: use previous packet", __func__);
2676 } else {
2677 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2678 if (m == NULL)
2679 m = m_gethdr(M_DONTWAIT, MT_DATA);
2680 if (m == NULL) {
2681 CTR1(KTR_MLD,
2682 "%s: m_get*() failed", __func__);
2683 return (-ENOMEM);
2684 }
2685 m->m_pkthdr.PH_vt.vt_nrecs = 0;
2686 mld_save_context(m, ifp);
2687 m0srcs = (ifp->if_mtu - MLD_MTUSPACE -
2688 sizeof(struct mldv2_record)) /
2689 sizeof(struct in6_addr);
2690 npbytes = 0;
2691 CTR1(KTR_MLD,
2692 "%s: allocated new packet", __func__);
2693 }
2694 /*
2695 * Append the MLD group record header to the
2696 * current packet's data area.
2697 * Recalculate pointer to free space for next
2698 * group record, in case m_append() allocated
2699 * a new mbuf or cluster.
2700 */
2701 memset(&mr, 0, sizeof(mr));
2702 mr.mr_addr = inm->in6m_addr;
2703 in6_clearscope(&mr.mr_addr);
2704 if (!m_append(m, sizeof(mr), (void *)&mr)) {
2705 if (m != m0)
2706 m_freem(m);
2707 CTR1(KTR_MLD,
2708 "%s: m_append() failed", __func__);
2709 return (-ENOMEM);
2710 }
2711 npbytes += sizeof(struct mldv2_record);
2712 if (m != m0) {
2713 /* new packet; offset in chain */
2714 md = m_getptr(m, npbytes -
2715 sizeof(struct mldv2_record), &off);
2716 pmr = (struct mldv2_record *)(mtod(md,
2717 uint8_t *) + off);
2718 } else {
2719 /* current packet; offset from last append */
2720 md = m_last(m);
2721 pmr = (struct mldv2_record *)(mtod(md,
2722 uint8_t *) + md->m_len -
2723 sizeof(struct mldv2_record));
2724 }
2725 /*
2726 * Begin walking the tree for this record type
2727 * pass, or continue from where we left off
2728 * previously if we had to allocate a new packet.
2729 * Only report deltas in-mode at t1.
2730 * We need not report included sources as allowed
2731 * if we are in inclusive mode on the group,
2732 * however the converse is not true.
2733 */
2734 rsrcs = 0;
2735 if (nims == NULL) {
2736 nims = RB_MIN(ip6_msource_tree,
2737 &inm->in6m_srcs);
2738 }
2739 RB_FOREACH_FROM(ims, ip6_msource_tree, nims) {
2740 CTR2(KTR_MLD, "%s: visit node %s", __func__,
2741 ip6_sprintf(ip6tbuf, &ims->im6s_addr));
2742 now = im6s_get_mode(inm, ims, 1);
2743 then = im6s_get_mode(inm, ims, 0);
2744 CTR3(KTR_MLD, "%s: mode: t0 %d, t1 %d",
2745 __func__, then, now);
2746 if (now == then) {
2747 CTR1(KTR_MLD,
2748 "%s: skip unchanged", __func__);
2749 continue;
2750 }
2751 if (mode == MCAST_EXCLUDE &&
2752 now == MCAST_INCLUDE) {
2753 CTR1(KTR_MLD,
2754 "%s: skip IN src on EX group",
2755 __func__);
2756 continue;
2757 }
2758 nrt = (rectype_t)now;
2759 if (nrt == REC_NONE)
2760 nrt = (rectype_t)(~mode & REC_FULL);
2761 if (schanged++ == 0) {
2762 crt = nrt;
2763 } else if (crt != nrt)
2764 continue;
2765 if (!m_append(m, sizeof(struct in6_addr),
2766 (void *)&ims->im6s_addr)) {
2767 if (m != m0)
2768 m_freem(m);
2769 CTR1(KTR_MLD,
2770 "%s: m_append() failed", __func__);
2771 return (-ENOMEM);
2772 }
2773 nallow += !!(crt == REC_ALLOW);
2774 nblock += !!(crt == REC_BLOCK);
2775 if (++rsrcs == m0srcs)
2776 break;
2777 }
2778 /*
2779 * If we did not append any tree nodes on this
2780 * pass, back out of allocations.
2781 */
2782 if (rsrcs == 0) {
2783 npbytes -= sizeof(struct mldv2_record);
2784 if (m != m0) {
2785 CTR1(KTR_MLD,
2786 "%s: m_free(m)", __func__);
2787 m_freem(m);
2788 } else {
2789 CTR1(KTR_MLD,
2790 "%s: m_adj(m, -mr)", __func__);
2791 m_adj(m, -((int)sizeof(
2792 struct mldv2_record)));
2793 }
2794 continue;
2795 }
2796 npbytes += (rsrcs * sizeof(struct in6_addr));
2797 if (crt == REC_ALLOW)
2798 pmr->mr_type = MLD_ALLOW_NEW_SOURCES;
2799 else if (crt == REC_BLOCK)
2800 pmr->mr_type = MLD_BLOCK_OLD_SOURCES;
2801 pmr->mr_numsrc = htons(rsrcs);
2802 /*
2803 * Count the new group record, and enqueue this
2804 * packet if it wasn't already queued.
2805 */
2806 m->m_pkthdr.PH_vt.vt_nrecs++;
2807 if (m != m0)
2808 _IF_ENQUEUE(ifq, m);
2809 nbytes += npbytes;
2810 } while (nims != NULL);
2811 drt |= crt;
2812 crt = (~crt & REC_FULL);
2813 }
2814
2815 CTR3(KTR_MLD, "%s: queued %d ALLOW_NEW, %d BLOCK_OLD", __func__,
2816 nallow, nblock);
2817
2818 return (nbytes);
2819 }
2820
2821 static int
2822 mld_v2_merge_state_changes(struct in6_multi *inm, struct ifqueue *ifscq)
2823 {
2824 struct ifqueue *gq;
2825 struct mbuf *m; /* pending state-change */
2826 struct mbuf *m0; /* copy of pending state-change */
2827 struct mbuf *mt; /* last state-change in packet */
2828 int docopy, domerge;
2829 u_int recslen;
2830
2831 docopy = 0;
2832 domerge = 0;
2833 recslen = 0;
2834
2835 IN6_MULTI_LOCK_ASSERT();
2836 MLD_LOCK_ASSERT();
2837
2838 /*
2839 * If there are further pending retransmissions, make a writable
2840 * copy of each queued state-change message before merging.
2841 */
2842 if (inm->in6m_scrv > 0)
2843 docopy = 1;
2844
2845 gq = &inm->in6m_scq;
2846 #ifdef KTR
2847 if (gq->ifq_head == NULL) {
2848 CTR2(KTR_MLD, "%s: WARNING: queue for inm %p is empty",
2849 __func__, inm);
2850 }
2851 #endif
2852
2853 m = gq->ifq_head;
2854 while (m != NULL) {
2855 /*
2856 * Only merge the report into the current packet if
2857 * there is sufficient space to do so; an MLDv2 report
2858 * packet may only contain 65,535 group records.
2859 * Always use a simple mbuf chain concatentation to do this,
2860 * as large state changes for single groups may have
2861 * allocated clusters.
2862 */
2863 domerge = 0;
2864 mt = ifscq->ifq_tail;
2865 if (mt != NULL) {
2866 recslen = m_length(m, NULL);
2867
2868 if ((mt->m_pkthdr.PH_vt.vt_nrecs +
2869 m->m_pkthdr.PH_vt.vt_nrecs <=
2870 MLD_V2_REPORT_MAXRECS) &&
2871 (mt->m_pkthdr.len + recslen <=
2872 (inm->in6m_ifp->if_mtu - MLD_MTUSPACE)))
2873 domerge = 1;
2874 }
2875
2876 if (!domerge && _IF_QFULL(gq)) {
2877 CTR2(KTR_MLD,
2878 "%s: outbound queue full, skipping whole packet %p",
2879 __func__, m);
2880 mt = m->m_nextpkt;
2881 if (!docopy)
2882 m_freem(m);
2883 m = mt;
2884 continue;
2885 }
2886
2887 if (!docopy) {
2888 CTR2(KTR_MLD, "%s: dequeueing %p", __func__, m);
2889 _IF_DEQUEUE(gq, m0);
2890 m = m0->m_nextpkt;
2891 } else {
2892 CTR2(KTR_MLD, "%s: copying %p", __func__, m);
2893 m0 = m_dup(m, M_NOWAIT);
2894 if (m0 == NULL)
2895 return (ENOMEM);
2896 m0->m_nextpkt = NULL;
2897 m = m->m_nextpkt;
2898 }
2899
2900 if (!domerge) {
2901 CTR3(KTR_MLD, "%s: queueing %p to ifscq %p)",
2902 __func__, m0, ifscq);
2903 _IF_ENQUEUE(ifscq, m0);
2904 } else {
2905 struct mbuf *mtl; /* last mbuf of packet mt */
2906
2907 CTR3(KTR_MLD, "%s: merging %p with ifscq tail %p)",
2908 __func__, m0, mt);
2909
2910 mtl = m_last(mt);
2911 m0->m_flags &= ~M_PKTHDR;
2912 mt->m_pkthdr.len += recslen;
2913 mt->m_pkthdr.PH_vt.vt_nrecs +=
2914 m0->m_pkthdr.PH_vt.vt_nrecs;
2915
2916 mtl->m_next = m0;
2917 }
2918 }
2919
2920 return (0);
2921 }
2922
2923 /*
2924 * Respond to a pending MLDv2 General Query.
2925 */
2926 static void
2927 mld_v2_dispatch_general_query(struct mld_ifinfo *mli)
2928 {
2929 struct ifmultiaddr *ifma, *tifma;
2930 struct ifnet *ifp;
2931 struct in6_multi *inm;
2932 int retval;
2933
2934 IN6_MULTI_LOCK_ASSERT();
2935 MLD_LOCK_ASSERT();
2936
2937 KASSERT(mli->mli_version == MLD_VERSION_2,
2938 ("%s: called when version %d", __func__, mli->mli_version));
2939
2940 ifp = mli->mli_ifp;
2941
2942 IF_ADDR_LOCK(ifp);
2943 TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, tifma) {
2944 if (ifma->ifma_addr->sa_family != AF_INET6 ||
2945 ifma->ifma_protospec == NULL)
2946 continue;
2947
2948 inm = (struct in6_multi *)ifma->ifma_protospec;
2949 KASSERT(ifp == inm->in6m_ifp,
2950 ("%s: inconsistent ifp", __func__));
2951
2952 switch (inm->in6m_state) {
2953 case MLD_NOT_MEMBER:
2954 case MLD_SILENT_MEMBER:
2955 break;
2956 case MLD_REPORTING_MEMBER:
2957 case MLD_IDLE_MEMBER:
2958 case MLD_LAZY_MEMBER:
2959 case MLD_SLEEPING_MEMBER:
2960 case MLD_AWAKENING_MEMBER:
2961 inm->in6m_state = MLD_REPORTING_MEMBER;
2962 retval = mld_v2_enqueue_group_record(&mli->mli_gq,
2963 inm, 0, 0, 0);
2964 CTR2(KTR_MLD, "%s: enqueue record = %d",
2965 __func__, retval);
2966 break;
2967 case MLD_G_QUERY_PENDING_MEMBER:
2968 case MLD_SG_QUERY_PENDING_MEMBER:
2969 case MLD_LEAVING_MEMBER:
2970 break;
2971 }
2972 }
2973 IF_ADDR_UNLOCK(ifp);
2974
2975 mld_dispatch_queue(&mli->mli_gq, MLD_MAX_RESPONSE_BURST);
2976
2977 /*
2978 * Slew transmission of bursts over 500ms intervals.
2979 */
2980 if (mli->mli_gq.ifq_head != NULL) {
2981 mli->mli_v2_timer = 1 + MLD_RANDOM_DELAY(
2982 MLD_RESPONSE_BURST_INTERVAL);
2983 V_interface_timers_running6 = 1;
2984 }
2985 }
2986
2987 /*
2988 * Transmit the next pending message in the output queue.
2989 *
2990 * VIMAGE: Needs to store/restore vnet pointer on a per-mbuf-chain basis.
2991 * MRT: Nothing needs to be done, as MLD traffic is always local to
2992 * a link and uses a link-scope multicast address.
2993 */
2994 static void
2995 mld_dispatch_packet(struct mbuf *m)
2996 {
2997 struct ip6_moptions im6o;
2998 struct ifnet *ifp;
2999 struct ifnet *oifp;
3000 struct mbuf *m0;
3001 struct mbuf *md;
3002 struct ip6_hdr *ip6;
3003 struct mld_hdr *mld;
3004 int error;
3005 int off;
3006 int type;
3007 uint32_t ifindex;
3008
3009 CTR2(KTR_MLD, "%s: transmit %p", __func__, m);
3010
3011 /*
3012 * Set VNET image pointer from enqueued mbuf chain
3013 * before doing anything else. Whilst we use interface
3014 * indexes to guard against interface detach, they are
3015 * unique to each VIMAGE and must be retrieved.
3016 */
3017 ifindex = mld_restore_context(m);
3018
3019 /*
3020 * Check if the ifnet still exists. This limits the scope of
3021 * any race in the absence of a global ifp lock for low cost
3022 * (an array lookup).
3023 */
3024 ifp = ifnet_byindex(ifindex);
3025 if (ifp == NULL) {
3026 CTR3(KTR_MLD, "%s: dropped %p as ifindex %u went away.",
3027 __func__, m, ifindex);
3028 m_freem(m);
3029 IP6STAT_INC(ip6s_noroute);
3030 goto out;
3031 }
3032
3033 im6o.im6o_multicast_hlim = 1;
3034 im6o.im6o_multicast_loop = (V_ip6_mrouter != NULL);
3035 im6o.im6o_multicast_ifp = ifp;
3036
3037 if (m->m_flags & M_MLDV1) {
3038 m0 = m;
3039 } else {
3040 m0 = mld_v2_encap_report(ifp, m);
3041 if (m0 == NULL) {
3042 CTR2(KTR_MLD, "%s: dropped %p", __func__, m);
3043 m_freem(m);
3044 IP6STAT_INC(ip6s_odropped);
3045 goto out;
3046 }
3047 }
3048
3049 mld_scrub_context(m0);
3050 m->m_flags &= ~(M_PROTOFLAGS);
3051 m0->m_pkthdr.rcvif = V_loif;
3052
3053 ip6 = mtod(m0, struct ip6_hdr *);
3054 #if 0
3055 (void)in6_setscope(&ip6->ip6_dst, ifp, NULL); /* XXX LOR */
3056 #else
3057 /*
3058 * XXX XXX Break some KPI rules to prevent an LOR which would
3059 * occur if we called in6_setscope() at transmission.
3060 * See comments at top of file.
3061 */
3062 MLD_EMBEDSCOPE(&ip6->ip6_dst, ifp->if_index);
3063 #endif
3064
3065 /*
3066 * Retrieve the ICMPv6 type before handoff to ip6_output(),
3067 * so we can bump the stats.
3068 */
3069 md = m_getptr(m0, sizeof(struct ip6_hdr), &off);
3070 mld = (struct mld_hdr *)(mtod(md, uint8_t *) + off);
3071 type = mld->mld_type;
3072
3073 error = ip6_output(m0, &mld_po, NULL, IPV6_UNSPECSRC, &im6o,
3074 &oifp, NULL);
3075 if (error) {
3076 CTR3(KTR_MLD, "%s: ip6_output(%p) = %d", __func__, m0, error);
3077 goto out;
3078 }
3079 ICMP6STAT_INC(icp6s_outhist[type]);
3080 if (oifp != NULL) {
3081 icmp6_ifstat_inc(oifp, ifs6_out_msg);
3082 switch (type) {
3083 case MLD_LISTENER_REPORT:
3084 case MLDV2_LISTENER_REPORT:
3085 icmp6_ifstat_inc(oifp, ifs6_out_mldreport);
3086 break;
3087 case MLD_LISTENER_DONE:
3088 icmp6_ifstat_inc(oifp, ifs6_out_mlddone);
3089 break;
3090 }
3091 }
3092 out:
3093 return;
3094 }
3095
3096 /*
3097 * Encapsulate an MLDv2 report.
3098 *
3099 * KAME IPv6 requires that hop-by-hop options be passed separately,
3100 * and that the IPv6 header be prepended in a separate mbuf.
3101 *
3102 * Returns a pointer to the new mbuf chain head, or NULL if the
3103 * allocation failed.
3104 */
3105 static struct mbuf *
3106 mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m)
3107 {
3108 struct mbuf *mh;
3109 struct mldv2_report *mld;
3110 struct ip6_hdr *ip6;
3111 struct in6_ifaddr *ia;
3112 int mldreclen;
3113
3114 KASSERT(ifp != NULL, ("%s: null ifp", __func__));
3115 KASSERT((m->m_flags & M_PKTHDR),
3116 ("%s: mbuf chain %p is !M_PKTHDR", __func__, m));
3117
3118 /*
3119 * RFC3590: OK to send as :: or tentative during DAD.
3120 */
3121 ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
3122 if (ia == NULL)
3123 CTR1(KTR_MLD, "%s: warning: ia is NULL", __func__);
3124
3125 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
3126 if (mh == NULL) {
3127 if (ia != NULL)
3128 ifa_free(&ia->ia_ifa);
3129 m_freem(m);
3130 return (NULL);
3131 }
3132 MH_ALIGN(mh, sizeof(struct ip6_hdr) + sizeof(struct mldv2_report));
3133
3134 mldreclen = m_length(m, NULL);
3135 CTR2(KTR_MLD, "%s: mldreclen is %d", __func__, mldreclen);
3136
3137 mh->m_len = sizeof(struct ip6_hdr) + sizeof(struct mldv2_report);
3138 mh->m_pkthdr.len = sizeof(struct ip6_hdr) +
3139 sizeof(struct mldv2_report) + mldreclen;
3140
3141 ip6 = mtod(mh, struct ip6_hdr *);
3142 ip6->ip6_flow = 0;
3143 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
3144 ip6->ip6_vfc |= IPV6_VERSION;
3145 ip6->ip6_nxt = IPPROTO_ICMPV6;
3146 ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
3147 if (ia != NULL)
3148 ifa_free(&ia->ia_ifa);
3149 ip6->ip6_dst = in6addr_linklocal_allv2routers;
3150 /* scope ID will be set in netisr */
3151
3152 mld = (struct mldv2_report *)(ip6 + 1);
3153 mld->mld_type = MLDV2_LISTENER_REPORT;
3154 mld->mld_code = 0;
3155 mld->mld_cksum = 0;
3156 mld->mld_v2_reserved = 0;
3157 mld->mld_v2_numrecs = htons(m->m_pkthdr.PH_vt.vt_nrecs);
3158 m->m_pkthdr.PH_vt.vt_nrecs = 0;
3159
3160 mh->m_next = m;
3161 mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6,
3162 sizeof(struct ip6_hdr), sizeof(struct mldv2_report) + mldreclen);
3163 return (mh);
3164 }
3165
3166 #ifdef KTR
3167 static char *
3168 mld_rec_type_to_str(const int type)
3169 {
3170
3171 switch (type) {
3172 case MLD_CHANGE_TO_EXCLUDE_MODE:
3173 return "TO_EX";
3174 break;
3175 case MLD_CHANGE_TO_INCLUDE_MODE:
3176 return "TO_IN";
3177 break;
3178 case MLD_MODE_IS_EXCLUDE:
3179 return "MODE_EX";
3180 break;
3181 case MLD_MODE_IS_INCLUDE:
3182 return "MODE_IN";
3183 break;
3184 case MLD_ALLOW_NEW_SOURCES:
3185 return "ALLOW_NEW";
3186 break;
3187 case MLD_BLOCK_OLD_SOURCES:
3188 return "BLOCK_OLD";
3189 break;
3190 default:
3191 break;
3192 }
3193 return "unknown";
3194 }
3195 #endif
3196
3197 static void
3198 mld_init(void *unused __unused)
3199 {
3200
3201 CTR1(KTR_MLD, "%s: initializing", __func__);
3202 MLD_LOCK_INIT();
3203
3204 ip6_initpktopts(&mld_po);
3205 mld_po.ip6po_hlim = 1;
3206 mld_po.ip6po_hbh = &mld_ra.hbh;
3207 mld_po.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER;
3208 mld_po.ip6po_flags = IP6PO_DONTFRAG;
3209 }
3210 SYSINIT(mld_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_init, NULL);
3211
3212 static void
3213 mld_uninit(void *unused __unused)
3214 {
3215
3216 CTR1(KTR_MLD, "%s: tearing down", __func__);
3217 MLD_LOCK_DESTROY();
3218 }
3219 SYSUNINIT(mld_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, mld_uninit, NULL);
3220
3221 static void
3222 vnet_mld_init(const void *unused __unused)
3223 {
3224
3225 CTR1(KTR_MLD, "%s: initializing", __func__);
3226
3227 LIST_INIT(&V_mli_head);
3228 }
3229 VNET_SYSINIT(vnet_mld_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_init,
3230 NULL);
3231
3232 static void
3233 vnet_mld_uninit(const void *unused __unused)
3234 {
3235
3236 CTR1(KTR_MLD, "%s: tearing down", __func__);
3237
3238 KASSERT(LIST_EMPTY(&V_mli_head),
3239 ("%s: mli list not empty; ifnets not detached?", __func__));
3240 }
3241 VNET_SYSUNINIT(vnet_mld_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_mld_uninit,
3242 NULL);
3243
3244 static int
3245 mld_modevent(module_t mod, int type, void *unused __unused)
3246 {
3247
3248 switch (type) {
3249 case MOD_LOAD:
3250 case MOD_UNLOAD:
3251 break;
3252 default:
3253 return (EOPNOTSUPP);
3254 }
3255 return (0);
3256 }
3257
3258 static moduledata_t mld_mod = {
3259 "mld",
3260 mld_modevent,
3261 0
3262 };
3263 DECLARE_MODULE(mld, mld_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
Cache object: 7130196b4a903c944046ae318fa5b93f
|