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