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