1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2009 Bruce Simpson. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote 16 * products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * IPv6 multicast socket, group, and socket option processing module. 34 * Normative references: RFC 2292, RFC 3492, RFC 3542, RFC 3678, RFC 3810. 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_inet6.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/gtaskqueue.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.h> 48 #include <sys/protosw.h> 49 #include <sys/socket.h> 50 #include <sys/socketvar.h> 51 #include <sys/sysctl.h> 52 #include <sys/priv.h> 53 #include <sys/ktr.h> 54 #include <sys/tree.h> 55 56 #include <net/if.h> 57 #include <net/if_var.h> 58 #include <net/if_dl.h> 59 #include <net/route.h> 60 #include <net/vnet.h> 61 62 63 #include <netinet/in.h> 64 #include <netinet/udp.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip_var.h> 67 #include <netinet/udp_var.h> 68 #include <netinet6/in6_fib.h> 69 #include <netinet6/in6_var.h> 70 #include <netinet/ip6.h> 71 #include <netinet/icmp6.h> 72 #include <netinet6/ip6_var.h> 73 #include <netinet/in_pcb.h> 74 #include <netinet/tcp_var.h> 75 #include <netinet6/nd6.h> 76 #include <netinet6/mld6_var.h> 77 #include <netinet6/scope6_var.h> 78 79 #ifndef KTR_MLD 80 #define KTR_MLD KTR_INET6 81 #endif 82 83 #ifndef __SOCKUNION_DECLARED 84 union sockunion { 85 struct sockaddr_storage ss; 86 struct sockaddr sa; 87 struct sockaddr_dl sdl; 88 struct sockaddr_in6 sin6; 89 }; 90 typedef union sockunion sockunion_t; 91 #define __SOCKUNION_DECLARED 92 #endif /* __SOCKUNION_DECLARED */ 93 94 static MALLOC_DEFINE(M_IN6MFILTER, "in6_mfilter", 95 "IPv6 multicast PCB-layer source filter"); 96 MALLOC_DEFINE(M_IP6MADDR, "in6_multi", "IPv6 multicast group"); 97 static MALLOC_DEFINE(M_IP6MOPTS, "ip6_moptions", "IPv6 multicast options"); 98 static MALLOC_DEFINE(M_IP6MSOURCE, "ip6_msource", 99 "IPv6 multicast MLD-layer source filter"); 100 101 RB_GENERATE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp); 102 103 /* 104 * Locking: 105 * - Lock order is: Giant, INP_WLOCK, IN6_MULTI_LOCK, MLD_LOCK, IF_ADDR_LOCK. 106 * - The IF_ADDR_LOCK is implicitly taken by in6m_lookup() earlier, however 107 * it can be taken by code in net/if.c also. 108 * - ip6_moptions and in6_mfilter are covered by the INP_WLOCK. 109 * 110 * struct in6_multi is covered by IN6_MULTI_LOCK. There isn't strictly 111 * any need for in6_multi itself to be virtualized -- it is bound to an ifp 112 * anyway no matter what happens. 113 */ 114 struct mtx in6_multi_list_mtx; 115 MTX_SYSINIT(in6_multi_mtx, &in6_multi_list_mtx, "in6_multi_list_mtx", MTX_DEF); 116 117 struct mtx in6_multi_free_mtx; 118 MTX_SYSINIT(in6_multi_free_mtx, &in6_multi_free_mtx, "in6_multi_free_mtx", MTX_DEF); 119 120 struct sx in6_multi_sx; 121 SX_SYSINIT(in6_multi_sx, &in6_multi_sx, "in6_multi_sx"); 122 123 124 125 static void im6f_commit(struct in6_mfilter *); 126 static int im6f_get_source(struct in6_mfilter *imf, 127 const struct sockaddr_in6 *psin, 128 struct in6_msource **); 129 static struct in6_msource * 130 im6f_graft(struct in6_mfilter *, const uint8_t, 131 const struct sockaddr_in6 *); 132 static void im6f_leave(struct in6_mfilter *); 133 static int im6f_prune(struct in6_mfilter *, const struct sockaddr_in6 *); 134 static void im6f_purge(struct in6_mfilter *); 135 static void im6f_rollback(struct in6_mfilter *); 136 static void im6f_reap(struct in6_mfilter *); 137 static int im6o_grow(struct ip6_moptions *); 138 static size_t im6o_match_group(const struct ip6_moptions *, 139 const struct ifnet *, const struct sockaddr *); 140 static struct in6_msource * 141 im6o_match_source(const struct ip6_moptions *, const size_t, 142 const struct sockaddr *); 143 static void im6s_merge(struct ip6_msource *ims, 144 const struct in6_msource *lims, const int rollback); 145 static int in6_getmulti(struct ifnet *, const struct in6_addr *, 146 struct in6_multi **); 147 static int in6m_get_source(struct in6_multi *inm, 148 const struct in6_addr *addr, const int noalloc, 149 struct ip6_msource **pims); 150 #ifdef KTR 151 static int in6m_is_ifp_detached(const struct in6_multi *); 152 #endif 153 static int in6m_merge(struct in6_multi *, /*const*/ struct in6_mfilter *); 154 static void in6m_purge(struct in6_multi *); 155 static void in6m_reap(struct in6_multi *); 156 static struct ip6_moptions * 157 in6p_findmoptions(struct inpcb *); 158 static int in6p_get_source_filters(struct inpcb *, struct sockopt *); 159 static int in6p_join_group(struct inpcb *, struct sockopt *); 160 static int in6p_leave_group(struct inpcb *, struct sockopt *); 161 static struct ifnet * 162 in6p_lookup_mcast_ifp(const struct inpcb *, 163 const struct sockaddr_in6 *); 164 static int in6p_block_unblock_source(struct inpcb *, struct sockopt *); 165 static int in6p_set_multicast_if(struct inpcb *, struct sockopt *); 166 static int in6p_set_source_filters(struct inpcb *, struct sockopt *); 167 static int sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS); 168 169 SYSCTL_DECL(_net_inet6_ip6); /* XXX Not in any common header. */ 170 171 static SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, mcast, CTLFLAG_RW, 0, 172 "IPv6 multicast"); 173 174 static u_long in6_mcast_maxgrpsrc = IPV6_MAX_GROUP_SRC_FILTER; 175 SYSCTL_ULONG(_net_inet6_ip6_mcast, OID_AUTO, maxgrpsrc, 176 CTLFLAG_RWTUN, &in6_mcast_maxgrpsrc, 0, 177 "Max source filters per group"); 178 179 static u_long in6_mcast_maxsocksrc = IPV6_MAX_SOCK_SRC_FILTER; 180 SYSCTL_ULONG(_net_inet6_ip6_mcast, OID_AUTO, maxsocksrc, 181 CTLFLAG_RWTUN, &in6_mcast_maxsocksrc, 0, 182 "Max source filters per socket"); 183 184 /* TODO Virtualize this switch. */ 185 int in6_mcast_loop = IPV6_DEFAULT_MULTICAST_LOOP; 186 SYSCTL_INT(_net_inet6_ip6_mcast, OID_AUTO, loop, CTLFLAG_RWTUN, 187 &in6_mcast_loop, 0, "Loopback multicast datagrams by default"); 188 189 static SYSCTL_NODE(_net_inet6_ip6_mcast, OID_AUTO, filters, 190 CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_ip6_mcast_filters, 191 "Per-interface stack-wide source filters"); 192 193 #ifdef KTR 194 /* 195 * Inline function which wraps assertions for a valid ifp. 196 * The ifnet layer will set the ifma's ifp pointer to NULL if the ifp 197 * is detached. 198 */ 199 static int __inline 200 in6m_is_ifp_detached(const struct in6_multi *inm) 201 { 202 struct ifnet *ifp; 203 204 KASSERT(inm->in6m_ifma != NULL, ("%s: no ifma", __func__)); 205 ifp = inm->in6m_ifma->ifma_ifp; 206 if (ifp != NULL) { 207 /* 208 * Sanity check that network-layer notion of ifp is the 209 * same as that of link-layer. 210 */ 211 KASSERT(inm->in6m_ifp == ifp, ("%s: bad ifp", __func__)); 212 } 213 214 return (ifp == NULL); 215 } 216 #endif 217 218 /* 219 * Initialize an in6_mfilter structure to a known state at t0, t1 220 * with an empty source filter list. 221 */ 222 static __inline void 223 im6f_init(struct in6_mfilter *imf, const int st0, const int st1) 224 { 225 memset(imf, 0, sizeof(struct in6_mfilter)); 226 RB_INIT(&imf->im6f_sources); 227 imf->im6f_st[0] = st0; 228 imf->im6f_st[1] = st1; 229 } 230 231 /* 232 * Resize the ip6_moptions vector to the next power-of-two minus 1. 233 * May be called with locks held; do not sleep. 234 */ 235 static int 236 im6o_grow(struct ip6_moptions *imo) 237 { 238 struct in6_multi **nmships; 239 struct in6_multi **omships; 240 struct in6_mfilter *nmfilters; 241 struct in6_mfilter *omfilters; 242 size_t idx; 243 size_t newmax; 244 size_t oldmax; 245 246 nmships = NULL; 247 nmfilters = NULL; 248 omships = imo->im6o_membership; 249 omfilters = imo->im6o_mfilters; 250 oldmax = imo->im6o_max_memberships; 251 newmax = ((oldmax + 1) * 2) - 1; 252 253 if (newmax <= IPV6_MAX_MEMBERSHIPS) { 254 nmships = (struct in6_multi **)realloc(omships, 255 sizeof(struct in6_multi *) * newmax, M_IP6MOPTS, M_NOWAIT); 256 nmfilters = (struct in6_mfilter *)realloc(omfilters, 257 sizeof(struct in6_mfilter) * newmax, M_IN6MFILTER, 258 M_NOWAIT); 259 if (nmships != NULL && nmfilters != NULL) { 260 /* Initialize newly allocated source filter heads. */ 261 for (idx = oldmax; idx < newmax; idx++) { 262 im6f_init(&nmfilters[idx], MCAST_UNDEFINED, 263 MCAST_EXCLUDE); 264 } 265 imo->im6o_max_memberships = newmax; 266 imo->im6o_membership = nmships; 267 imo->im6o_mfilters = nmfilters; 268 } 269 } 270 271 if (nmships == NULL || nmfilters == NULL) { 272 if (nmships != NULL) 273 free(nmships, M_IP6MOPTS); 274 if (nmfilters != NULL) 275 free(nmfilters, M_IN6MFILTER); 276 return (ETOOMANYREFS); 277 } 278 279 return (0); 280 } 281 282 /* 283 * Find an IPv6 multicast group entry for this ip6_moptions instance 284 * which matches the specified group, and optionally an interface. 285 * Return its index into the array, or -1 if not found. 286 */ 287 static size_t 288 im6o_match_group(const struct ip6_moptions *imo, const struct ifnet *ifp, 289 const struct sockaddr *group) 290 { 291 const struct sockaddr_in6 *gsin6; 292 struct in6_multi **pinm; 293 int idx; 294 int nmships; 295 296 gsin6 = (const struct sockaddr_in6 *)group; 297 298 /* The im6o_membership array may be lazy allocated. */ 299 if (imo->im6o_membership == NULL || imo->im6o_num_memberships == 0) 300 return (-1); 301 302 nmships = imo->im6o_num_memberships; 303 pinm = &imo->im6o_membership[0]; 304 for (idx = 0; idx < nmships; idx++, pinm++) { 305 if (*pinm == NULL) 306 continue; 307 if ((ifp == NULL || ((*pinm)->in6m_ifp == ifp)) && 308 IN6_ARE_ADDR_EQUAL(&(*pinm)->in6m_addr, 309 &gsin6->sin6_addr)) { 310 break; 311 } 312 } 313 if (idx >= nmships) 314 idx = -1; 315 316 return (idx); 317 } 318 319 /* 320 * Find an IPv6 multicast source entry for this imo which matches 321 * the given group index for this socket, and source address. 322 * 323 * XXX TODO: The scope ID, if present in src, is stripped before 324 * any comparison. We SHOULD enforce scope/zone checks where the source 325 * filter entry has a link scope. 326 * 327 * NOTE: This does not check if the entry is in-mode, merely if 328 * it exists, which may not be the desired behaviour. 329 */ 330 static struct in6_msource * 331 im6o_match_source(const struct ip6_moptions *imo, const size_t gidx, 332 const struct sockaddr *src) 333 { 334 struct ip6_msource find; 335 struct in6_mfilter *imf; 336 struct ip6_msource *ims; 337 const sockunion_t *psa; 338 339 KASSERT(src->sa_family == AF_INET6, ("%s: !AF_INET6", __func__)); 340 KASSERT(gidx != -1 && gidx < imo->im6o_num_memberships, 341 ("%s: invalid index %d\n", __func__, (int)gidx)); 342 343 /* The im6o_mfilters array may be lazy allocated. */ 344 if (imo->im6o_mfilters == NULL) 345 return (NULL); 346 imf = &imo->im6o_mfilters[gidx]; 347 348 psa = (const sockunion_t *)src; 349 find.im6s_addr = psa->sin6.sin6_addr; 350 in6_clearscope(&find.im6s_addr); /* XXX */ 351 ims = RB_FIND(ip6_msource_tree, &imf->im6f_sources, &find); 352 353 return ((struct in6_msource *)ims); 354 } 355 356 /* 357 * Perform filtering for multicast datagrams on a socket by group and source. 358 * 359 * Returns 0 if a datagram should be allowed through, or various error codes 360 * if the socket was not a member of the group, or the source was muted, etc. 361 */ 362 int 363 im6o_mc_filter(const struct ip6_moptions *imo, const struct ifnet *ifp, 364 const struct sockaddr *group, const struct sockaddr *src) 365 { 366 size_t gidx; 367 struct in6_msource *ims; 368 int mode; 369 370 KASSERT(ifp != NULL, ("%s: null ifp", __func__)); 371 372 gidx = im6o_match_group(imo, ifp, group); 373 if (gidx == -1) 374 return (MCAST_NOTGMEMBER); 375 376 /* 377 * Check if the source was included in an (S,G) join. 378 * Allow reception on exclusive memberships by default, 379 * reject reception on inclusive memberships by default. 380 * Exclude source only if an in-mode exclude filter exists. 381 * Include source only if an in-mode include filter exists. 382 * NOTE: We are comparing group state here at MLD t1 (now) 383 * with socket-layer t0 (since last downcall). 384 */ 385 mode = imo->im6o_mfilters[gidx].im6f_st[1]; 386 ims = im6o_match_source(imo, gidx, src); 387 388 if ((ims == NULL && mode == MCAST_INCLUDE) || 389 (ims != NULL && ims->im6sl_st[0] != mode)) 390 return (MCAST_NOTSMEMBER); 391 392 return (MCAST_PASS); 393 } 394 395 /* 396 * Find and return a reference to an in6_multi record for (ifp, group), 397 * and bump its reference count. 398 * If one does not exist, try to allocate it, and update link-layer multicast 399 * filters on ifp to listen for group. 400 * Assumes the IN6_MULTI lock is held across the call. 401 * Return 0 if successful, otherwise return an appropriate error code. 402 */ 403 static int 404 in6_getmulti(struct ifnet *ifp, const struct in6_addr *group, 405 struct in6_multi **pinm) 406 { 407 struct epoch_tracker et; 408 struct sockaddr_in6 gsin6; 409 struct ifmultiaddr *ifma; 410 struct in6_multi *inm; 411 int error; 412 413 error = 0; 414 415 /* 416 * XXX: Accesses to ifma_protospec must be covered by IF_ADDR_LOCK; 417 * if_addmulti() takes this mutex itself, so we must drop and 418 * re-acquire around the call. 419 */ 420 IN6_MULTI_LOCK_ASSERT(); 421 IN6_MULTI_LIST_LOCK(); 422 IF_ADDR_WLOCK(ifp); 423 NET_EPOCH_ENTER(et); 424 inm = in6m_lookup_locked(ifp, group); 425 NET_EPOCH_EXIT(et); 426 427 if (inm != NULL) { 428 /* 429 * If we already joined this group, just bump the 430 * refcount and return it. 431 */ 432 KASSERT(inm->in6m_refcount >= 1, 433 ("%s: bad refcount %d", __func__, inm->in6m_refcount)); 434 in6m_acquire_locked(inm); 435 *pinm = inm; 436 goto out_locked; 437 } 438 439 memset(&gsin6, 0, sizeof(gsin6)); 440 gsin6.sin6_family = AF_INET6; 441 gsin6.sin6_len = sizeof(struct sockaddr_in6); 442 gsin6.sin6_addr = *group; 443 444 /* 445 * Check if a link-layer group is already associated 446 * with this network-layer group on the given ifnet. 447 */ 448 IN6_MULTI_LIST_UNLOCK(); 449 IF_ADDR_WUNLOCK(ifp); 450 error = if_addmulti(ifp, (struct sockaddr *)&gsin6, &ifma); 451 if (error != 0) 452 return (error); 453 IN6_MULTI_LIST_LOCK(); 454 IF_ADDR_WLOCK(ifp); 455 456 /* 457 * If something other than netinet6 is occupying the link-layer 458 * group, print a meaningful error message and back out of 459 * the allocation. 460 * Otherwise, bump the refcount on the existing network-layer 461 * group association and return it. 462 */ 463 if (ifma->ifma_protospec != NULL) { 464 inm = (struct in6_multi *)ifma->ifma_protospec; 465 #ifdef INVARIANTS 466 KASSERT(ifma->ifma_addr != NULL, ("%s: no ifma_addr", 467 __func__)); 468 KASSERT(ifma->ifma_addr->sa_family == AF_INET6, 469 ("%s: ifma not AF_INET6", __func__)); 470 KASSERT(inm != NULL, ("%s: no ifma_protospec", __func__)); 471 if (inm->in6m_ifma != ifma || inm->in6m_ifp != ifp || 472 !IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, group)) 473 panic("%s: ifma %p is inconsistent with %p (%p)", 474 __func__, ifma, inm, group); 475 #endif 476 in6m_acquire_locked(inm); 477 *pinm = inm; 478 goto out_locked; 479 } 480 481 IF_ADDR_WLOCK_ASSERT(ifp); 482 483 /* 484 * A new in6_multi record is needed; allocate and initialize it. 485 * We DO NOT perform an MLD join as the in6_ layer may need to 486 * push an initial source list down to MLD to support SSM. 487 * 488 * The initial source filter state is INCLUDE, {} as per the RFC. 489 * Pending state-changes per group are subject to a bounds check. 490 */ 491 inm = malloc(sizeof(*inm), M_IP6MADDR, M_NOWAIT | M_ZERO); 492 if (inm == NULL) { 493 IN6_MULTI_LIST_UNLOCK(); 494 IF_ADDR_WUNLOCK(ifp); 495 if_delmulti_ifma(ifma); 496 return (ENOMEM); 497 } 498 inm->in6m_addr = *group; 499 inm->in6m_ifp = ifp; 500 inm->in6m_mli = MLD_IFINFO(ifp); 501 inm->in6m_ifma = ifma; 502 inm->in6m_refcount = 1; 503 inm->in6m_state = MLD_NOT_MEMBER; 504 mbufq_init(&inm->in6m_scq, MLD_MAX_STATE_CHANGES); 505 506 inm->in6m_st[0].iss_fmode = MCAST_UNDEFINED; 507 inm->in6m_st[1].iss_fmode = MCAST_UNDEFINED; 508 RB_INIT(&inm->in6m_srcs); 509 510 ifma->ifma_protospec = inm; 511 *pinm = inm; 512 513 out_locked: 514 IN6_MULTI_LIST_UNLOCK(); 515 IF_ADDR_WUNLOCK(ifp); 516 return (error); 517 } 518 519 /* 520 * Drop a reference to an in6_multi record. 521 * 522 * If the refcount drops to 0, free the in6_multi record and 523 * delete the underlying link-layer membership. 524 */ 525 static void 526 in6m_release(struct in6_multi *inm) 527 { 528 struct ifmultiaddr *ifma; 529 struct ifnet *ifp; 530 531 CTR2(KTR_MLD, "%s: refcount is %d", __func__, inm->in6m_refcount); 532 533 MPASS(inm->in6m_refcount == 0); 534 CTR2(KTR_MLD, "%s: freeing inm %p", __func__, inm); 535 536 ifma = inm->in6m_ifma; 537 ifp = inm->in6m_ifp; 538 MPASS(ifma->ifma_llifma == NULL); 539 540 /* XXX this access is not covered by IF_ADDR_LOCK */ 541 CTR2(KTR_MLD, "%s: purging ifma %p", __func__, ifma); 542 KASSERT(ifma->ifma_protospec == NULL, 543 ("%s: ifma_protospec != NULL", __func__)); 544 if (ifp == NULL) 545 ifp = ifma->ifma_ifp; 546 547 if (ifp != NULL) { 548 CURVNET_SET(ifp->if_vnet); 549 in6m_purge(inm); 550 free(inm, M_IP6MADDR); 551 if_delmulti_ifma_flags(ifma, 1); 552 CURVNET_RESTORE(); 553 if_rele(ifp); 554 } else { 555 in6m_purge(inm); 556 free(inm, M_IP6MADDR); 557 if_delmulti_ifma_flags(ifma, 1); 558 } 559 } 560 561 static struct grouptask free_gtask; 562 static struct in6_multi_head in6m_free_list; 563 static void in6m_release_task(void *arg __unused); 564 static void in6m_init(void) 565 { 566 SLIST_INIT(&in6m_free_list); 567 taskqgroup_config_gtask_init(NULL, &free_gtask, in6m_release_task, "in6m release task"); 568 } 569 570 #ifdef EARLY_AP_STARTUP 571 SYSINIT(in6m_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, 572 in6m_init, NULL); 573 #else 574 SYSINIT(in6m_init, SI_SUB_ROOT_CONF - 1, SI_ORDER_SECOND, 575 in6m_init, NULL); 576 #endif 577 578 579 void 580 in6m_release_list_deferred(struct in6_multi_head *inmh) 581 { 582 if (SLIST_EMPTY(inmh)) 583 return; 584 mtx_lock(&in6_multi_free_mtx); 585 SLIST_CONCAT(&in6m_free_list, inmh, in6_multi, in6m_nrele); 586 mtx_unlock(&in6_multi_free_mtx); 587 GROUPTASK_ENQUEUE(&free_gtask); 588 } 589 590 void 591 in6m_release_wait(void) 592 { 593 594 /* Wait for all jobs to complete. */ 595 gtaskqueue_drain_all(free_gtask.gt_taskqueue); 596 } 597 598 void 599 in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm) 600 { 601 struct ifnet *ifp; 602 struct ifaddr *ifa; 603 struct in6_ifaddr *ifa6; 604 struct in6_multi_mship *imm, *imm_tmp; 605 struct ifmultiaddr *ifma, *ll_ifma; 606 607 IN6_MULTI_LIST_LOCK_ASSERT(); 608 609 ifp = inm->in6m_ifp; 610 if (ifp == NULL) 611 return; /* already called */ 612 613 inm->in6m_ifp = NULL; 614 IF_ADDR_WLOCK_ASSERT(ifp); 615 ifma = inm->in6m_ifma; 616 if (ifma == NULL) 617 return; 618 619 if_ref(ifp); 620 if (ifma->ifma_flags & IFMA_F_ENQUEUED) { 621 CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifmultiaddr, ifma_link); 622 ifma->ifma_flags &= ~IFMA_F_ENQUEUED; 623 } 624 MCDPRINTF("removed ifma: %p from %s\n", ifma, ifp->if_xname); 625 if ((ll_ifma = ifma->ifma_llifma) != NULL) { 626 MPASS(ifma != ll_ifma); 627 ifma->ifma_llifma = NULL; 628 MPASS(ll_ifma->ifma_llifma == NULL); 629 MPASS(ll_ifma->ifma_ifp == ifp); 630 if (--ll_ifma->ifma_refcount == 0) { 631 if (ll_ifma->ifma_flags & IFMA_F_ENQUEUED) { 632 CK_STAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifmultiaddr, ifma_link); 633 ll_ifma->ifma_flags &= ~IFMA_F_ENQUEUED; 634 } 635 MCDPRINTF("removed ll_ifma: %p from %s\n", ll_ifma, ifp->if_xname); 636 if_freemulti(ll_ifma); 637 } 638 } 639 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 640 if (ifa->ifa_addr->sa_family != AF_INET6) 641 continue; 642 ifa6 = (void *)ifa; 643 LIST_FOREACH_SAFE(imm, &ifa6->ia6_memberships, 644 i6mm_chain, imm_tmp) { 645 if (inm == imm->i6mm_maddr) { 646 LIST_REMOVE(imm, i6mm_chain); 647 free(imm, M_IP6MADDR); 648 in6m_rele_locked(inmh, inm); 649 } 650 } 651 } 652 } 653 654 static void 655 in6m_release_task(void *arg __unused) 656 { 657 struct in6_multi_head in6m_free_tmp; 658 struct in6_multi *inm, *tinm; 659 660 SLIST_INIT(&in6m_free_tmp); 661 mtx_lock(&in6_multi_free_mtx); 662 SLIST_CONCAT(&in6m_free_tmp, &in6m_free_list, in6_multi, in6m_nrele); 663 mtx_unlock(&in6_multi_free_mtx); 664 IN6_MULTI_LOCK(); 665 SLIST_FOREACH_SAFE(inm, &in6m_free_tmp, in6m_nrele, tinm) { 666 SLIST_REMOVE_HEAD(&in6m_free_tmp, in6m_nrele); 667 in6m_release(inm); 668 } 669 IN6_MULTI_UNLOCK(); 670 } 671 672 /* 673 * Clear recorded source entries for a group. 674 * Used by the MLD code. Caller must hold the IN6_MULTI lock. 675 * FIXME: Should reap. 676 */ 677 void 678 in6m_clear_recorded(struct in6_multi *inm) 679 { 680 struct ip6_msource *ims; 681 682 IN6_MULTI_LIST_LOCK_ASSERT(); 683 684 RB_FOREACH(ims, ip6_msource_tree, &inm->in6m_srcs) { 685 if (ims->im6s_stp) { 686 ims->im6s_stp = 0; 687 --inm->in6m_st[1].iss_rec; 688 } 689 } 690 KASSERT(inm->in6m_st[1].iss_rec == 0, 691 ("%s: iss_rec %d not 0", __func__, inm->in6m_st[1].iss_rec)); 692 } 693 694 /* 695 * Record a source as pending for a Source-Group MLDv2 query. 696 * This lives here as it modifies the shared tree. 697 * 698 * inm is the group descriptor. 699 * naddr is the address of the source to record in network-byte order. 700 * 701 * If the net.inet6.mld.sgalloc sysctl is non-zero, we will 702 * lazy-allocate a source node in response to an SG query. 703 * Otherwise, no allocation is performed. This saves some memory 704 * with the trade-off that the source will not be reported to the 705 * router if joined in the window between the query response and 706 * the group actually being joined on the local host. 707 * 708 * VIMAGE: XXX: Currently the mld_sgalloc feature has been removed. 709 * This turns off the allocation of a recorded source entry if 710 * the group has not been joined. 711 * 712 * Return 0 if the source didn't exist or was already marked as recorded. 713 * Return 1 if the source was marked as recorded by this function. 714 * Return <0 if any error occurred (negated errno code). 715 */ 716 int 717 in6m_record_source(struct in6_multi *inm, const struct in6_addr *addr) 718 { 719 struct ip6_msource find; 720 struct ip6_msource *ims, *nims; 721 722 IN6_MULTI_LIST_LOCK_ASSERT(); 723 724 find.im6s_addr = *addr; 725 ims = RB_FIND(ip6_msource_tree, &inm->in6m_srcs, &find); 726 if (ims && ims->im6s_stp) 727 return (0); 728 if (ims == NULL) { 729 if (inm->in6m_nsrc == in6_mcast_maxgrpsrc) 730 return (-ENOSPC); 731 nims = malloc(sizeof(struct ip6_msource), M_IP6MSOURCE, 732 M_NOWAIT | M_ZERO); 733 if (nims == NULL) 734 return (-ENOMEM); 735 nims->im6s_addr = find.im6s_addr; 736 RB_INSERT(ip6_msource_tree, &inm->in6m_srcs, nims); 737 ++inm->in6m_nsrc; 738 ims = nims; 739 } 740 741 /* 742 * Mark the source as recorded and update the recorded 743 * source count. 744 */ 745 ++ims->im6s_stp; 746 ++inm->in6m_st[1].iss_rec; 747 748 return (1); 749 } 750 751 /* 752 * Return a pointer to an in6_msource owned by an in6_mfilter, 753 * given its source address. 754 * Lazy-allocate if needed. If this is a new entry its filter state is 755 * undefined at t0. 756 * 757 * imf is the filter set being modified. 758 * addr is the source address. 759 * 760 * SMPng: May be called with locks held; malloc must not block. 761 */ 762 static int 763 im6f_get_source(struct in6_mfilter *imf, const struct sockaddr_in6 *psin, 764 struct in6_msource **plims) 765 { 766 struct ip6_msource find; 767 struct ip6_msource *ims, *nims; 768 struct in6_msource *lims; 769 int error; 770 771 error = 0; 772 ims = NULL; 773 lims = NULL; 774 775 find.im6s_addr = psin->sin6_addr; 776 ims = RB_FIND(ip6_msource_tree, &imf->im6f_sources, &find); 777 lims = (struct in6_msource *)ims; 778 if (lims == NULL) { 779 if (imf->im6f_nsrc == in6_mcast_maxsocksrc) 780 return (ENOSPC); 781 nims = malloc(sizeof(struct in6_msource), M_IN6MFILTER, 782 M_NOWAIT | M_ZERO); 783 if (nims == NULL) 784 return (ENOMEM); 785 lims = (struct in6_msource *)nims; 786 lims->im6s_addr = find.im6s_addr; 787 lims->im6sl_st[0] = MCAST_UNDEFINED; 788 RB_INSERT(ip6_msource_tree, &imf->im6f_sources, nims); 789 ++imf->im6f_nsrc; 790 } 791 792 *plims = lims; 793 794 return (error); 795 } 796 797 /* 798 * Graft a source entry into an existing socket-layer filter set, 799 * maintaining any required invariants and checking allocations. 800 * 801 * The source is marked as being in the new filter mode at t1. 802 * 803 * Return the pointer to the new node, otherwise return NULL. 804 */ 805 static struct in6_msource * 806 im6f_graft(struct in6_mfilter *imf, const uint8_t st1, 807 const struct sockaddr_in6 *psin) 808 { 809 struct ip6_msource *nims; 810 struct in6_msource *lims; 811 812 nims = malloc(sizeof(struct in6_msource), M_IN6MFILTER, 813 M_NOWAIT | M_ZERO); 814 if (nims == NULL) 815 return (NULL); 816 lims = (struct in6_msource *)nims; 817 lims->im6s_addr = psin->sin6_addr; 818 lims->im6sl_st[0] = MCAST_UNDEFINED; 819 lims->im6sl_st[1] = st1; 820 RB_INSERT(ip6_msource_tree, &imf->im6f_sources, nims); 821 ++imf->im6f_nsrc; 822 823 return (lims); 824 } 825 826 /* 827 * Prune a source entry from an existing socket-layer filter set, 828 * maintaining any required invariants and checking allocations. 829 * 830 * The source is marked as being left at t1, it is not freed. 831 * 832 * Return 0 if no error occurred, otherwise return an errno value. 833 */ 834 static int 835 im6f_prune(struct in6_mfilter *imf, const struct sockaddr_in6 *psin) 836 { 837 struct ip6_msource find; 838 struct ip6_msource *ims; 839 struct in6_msource *lims; 840 841 find.im6s_addr = psin->sin6_addr; 842 ims = RB_FIND(ip6_msource_tree, &imf->im6f_sources, &find); 843 if (ims == NULL) 844 return (ENOENT); 845 lims = (struct in6_msource *)ims; 846 lims->im6sl_st[1] = MCAST_UNDEFINED; 847 return (0); 848 } 849 850 /* 851 * Revert socket-layer filter set deltas at t1 to t0 state. 852 */ 853 static void 854 im6f_rollback(struct in6_mfilter *imf) 855 { 856 struct ip6_msource *ims, *tims; 857 struct in6_msource *lims; 858 859 RB_FOREACH_SAFE(ims, ip6_msource_tree, &imf->im6f_sources, tims) { 860 lims = (struct in6_msource *)ims; 861 if (lims->im6sl_st[0] == lims->im6sl_st[1]) { 862 /* no change at t1 */ 863 continue; 864 } else if (lims->im6sl_st[0] != MCAST_UNDEFINED) { 865 /* revert change to existing source at t1 */ 866 lims->im6sl_st[1] = lims->im6sl_st[0]; 867 } else { 868 /* revert source added t1 */ 869 CTR2(KTR_MLD, "%s: free ims %p", __func__, ims); 870 RB_REMOVE(ip6_msource_tree, &imf->im6f_sources, ims); 871 free(ims, M_IN6MFILTER); 872 imf->im6f_nsrc--; 873 } 874 } 875 imf->im6f_st[1] = imf->im6f_st[0]; 876 } 877 878 /* 879 * Mark socket-layer filter set as INCLUDE {} at t1. 880 */ 881 static void 882 im6f_leave(struct in6_mfilter *imf) 883 { 884 struct ip6_msource *ims; 885 struct in6_msource *lims; 886 887 RB_FOREACH(ims, ip6_msource_tree, &imf->im6f_sources) { 888 lims = (struct in6_msource *)ims; 889 lims->im6sl_st[1] = MCAST_UNDEFINED; 890 } 891 imf->im6f_st[1] = MCAST_INCLUDE; 892 } 893 894 /* 895 * Mark socket-layer filter set deltas as committed. 896 */ 897 static void 898 im6f_commit(struct in6_mfilter *imf) 899 { 900 struct ip6_msource *ims; 901 struct in6_msource *lims; 902 903 RB_FOREACH(ims, ip6_msource_tree, &imf->im6f_sources) { 904 lims = (struct in6_msource *)ims; 905 lims->im6sl_st[0] = lims->im6sl_st[1]; 906 } 907 imf->im6f_st[0] = imf->im6f_st[1]; 908 } 909 910 /* 911 * Reap unreferenced sources from socket-layer filter set. 912 */ 913 static void 914 im6f_reap(struct in6_mfilter *imf) 915 { 916 struct ip6_msource *ims, *tims; 917 struct in6_msource *lims; 918 919 RB_FOREACH_SAFE(ims, ip6_msource_tree, &imf->im6f_sources, tims) { 920 lims = (struct in6_msource *)ims; 921 if ((lims->im6sl_st[0] == MCAST_UNDEFINED) && 922 (lims->im6sl_st[1] == MCAST_UNDEFINED)) { 923 CTR2(KTR_MLD, "%s: free lims %p", __func__, ims); 924 RB_REMOVE(ip6_msource_tree, &imf->im6f_sources, ims); 925 free(ims, M_IN6MFILTER); 926 imf->im6f_nsrc--; 927 } 928 } 929 } 930 931 /* 932 * Purge socket-layer filter set. 933 */ 934 static void 935 im6f_purge(struct in6_mfilter *imf) 936 { 937 struct ip6_msource *ims, *tims; 938 939 RB_FOREACH_SAFE(ims, ip6_msource_tree, &imf->im6f_sources, tims) { 940 CTR2(KTR_MLD, "%s: free ims %p", __func__, ims); 941 RB_REMOVE(ip6_msource_tree, &imf->im6f_sources, ims); 942 free(ims, M_IN6MFILTER); 943 imf->im6f_nsrc--; 944 } 945 imf->im6f_st[0] = imf->im6f_st[1] = MCAST_UNDEFINED; 946 KASSERT(RB_EMPTY(&imf->im6f_sources), 947 ("%s: im6f_sources not empty", __func__)); 948 } 949 950 /* 951 * Look up a source filter entry for a multicast group. 952 * 953 * inm is the group descriptor to work with. 954 * addr is the IPv6 address to look up. 955 * noalloc may be non-zero to suppress allocation of sources. 956 * *pims will be set to the address of the retrieved or allocated source. 957 * 958 * SMPng: NOTE: may be called with locks held. 959 * Return 0 if successful, otherwise return a non-zero error code. 960 */ 961 static int 962 in6m_get_source(struct in6_multi *inm, const struct in6_addr *addr, 963 const int noalloc, struct ip6_msource **pims) 964 { 965 struct ip6_msource find; 966 struct ip6_msource *ims, *nims; 967 #ifdef KTR 968 char ip6tbuf[INET6_ADDRSTRLEN]; 969 #endif 970 971 find.im6s_addr = *addr; 972 ims = RB_FIND(ip6_msource_tree, &inm->in6m_srcs, &find); 973 if (ims == NULL && !noalloc) { 974 if (inm->in6m_nsrc == in6_mcast_maxgrpsrc) 975 return (ENOSPC); 976 nims = malloc(sizeof(struct ip6_msource), M_IP6MSOURCE, 977 M_NOWAIT | M_ZERO); 978 if (nims == NULL) 979 return (ENOMEM); 980 nims->im6s_addr = *addr; 981 RB_INSERT(ip6_msource_tree, &inm->in6m_srcs, nims); 982 ++inm->in6m_nsrc; 983 ims = nims; 984 CTR3(KTR_MLD, "%s: allocated %s as %p", __func__, 985 ip6_sprintf(ip6tbuf, addr), ims); 986 } 987 988 *pims = ims; 989 return (0); 990 } 991 992 /* 993 * Merge socket-layer source into MLD-layer source. 994 * If rollback is non-zero, perform the inverse of the merge. 995 */ 996 static void 997 im6s_merge(struct ip6_msource *ims, const struct in6_msource *lims, 998 const int rollback) 999 { 1000 int n = rollback ? -1 : 1; 1001 #ifdef KTR 1002 char ip6tbuf[INET6_ADDRSTRLEN]; 1003 1004 ip6_sprintf(ip6tbuf, &lims->im6s_addr); 1005 #endif 1006 1007 if (lims->im6sl_st[0] == MCAST_EXCLUDE) { 1008 CTR3(KTR_MLD, "%s: t1 ex -= %d on %s", __func__, n, ip6tbuf); 1009 ims->im6s_st[1].ex -= n; 1010 } else if (lims->im6sl_st[0] == MCAST_INCLUDE) { 1011 CTR3(KTR_MLD, "%s: t1 in -= %d on %s", __func__, n, ip6tbuf); 1012 ims->im6s_st[1].in -= n; 1013 } 1014 1015 if (lims->im6sl_st[1] == MCAST_EXCLUDE) { 1016 CTR3(KTR_MLD, "%s: t1 ex += %d on %s", __func__, n, ip6tbuf); 1017 ims->im6s_st[1].ex += n; 1018 } else if (lims->im6sl_st[1] == MCAST_INCLUDE) { 1019 CTR3(KTR_MLD, "%s: t1 in += %d on %s", __func__, n, ip6tbuf); 1020 ims->im6s_st[1].in += n; 1021 } 1022 } 1023 1024 /* 1025 * Atomically update the global in6_multi state, when a membership's 1026 * filter list is being updated in any way. 1027 * 1028 * imf is the per-inpcb-membership group filter pointer. 1029 * A fake imf may be passed for in-kernel consumers. 1030 * 1031 * XXX This is a candidate for a set-symmetric-difference style loop 1032 * which would eliminate the repeated lookup from root of ims nodes, 1033 * as they share the same key space. 1034 * 1035 * If any error occurred this function will back out of refcounts 1036 * and return a non-zero value. 1037 */ 1038 static int 1039 in6m_merge(struct in6_multi *inm, /*const*/ struct in6_mfilter *imf) 1040 { 1041 struct ip6_msource *ims, *nims; 1042 struct in6_msource *lims; 1043 int schanged, error; 1044 int nsrc0, nsrc1; 1045 1046 schanged = 0; 1047 error = 0; 1048 nsrc1 = nsrc0 = 0; 1049 IN6_MULTI_LIST_LOCK_ASSERT(); 1050 1051 /* 1052 * Update the source filters first, as this may fail. 1053 * Maintain count of in-mode filters at t0, t1. These are 1054 * used to work out if we transition into ASM mode or not. 1055 * Maintain a count of source filters whose state was 1056 * actually modified by this operation. 1057 */ 1058 RB_FOREACH(ims, ip6_msource_tree, &imf->im6f_sources) { 1059 lims = (struct in6_msource *)ims; 1060 if (lims->im6sl_st[0] == imf->im6f_st[0]) nsrc0++; 1061 if (lims->im6sl_st[1] == imf->im6f_st[1]) nsrc1++; 1062 if (lims->im6sl_st[0] == lims->im6sl_st[1]) continue; 1063 error = in6m_get_source(inm, &lims->im6s_addr, 0, &nims); 1064 ++schanged; 1065 if (error) 1066 break; 1067 im6s_merge(nims, lims, 0); 1068 } 1069 if (error) { 1070 struct ip6_msource *bims; 1071 1072 RB_FOREACH_REVERSE_FROM(ims, ip6_msource_tree, nims) { 1073 lims = (struct in6_msource *)ims; 1074 if (lims->im6sl_st[0] == lims->im6sl_st[1]) 1075 continue; 1076 (void)in6m_get_source(inm, &lims->im6s_addr, 1, &bims); 1077 if (bims == NULL) 1078 continue; 1079 im6s_merge(bims, lims, 1); 1080 } 1081 goto out_reap; 1082 } 1083 1084 CTR3(KTR_MLD, "%s: imf filters in-mode: %d at t0, %d at t1", 1085 __func__, nsrc0, nsrc1); 1086 1087 /* Handle transition between INCLUDE {n} and INCLUDE {} on socket. */ 1088 if (imf->im6f_st[0] == imf->im6f_st[1] && 1089 imf->im6f_st[1] == MCAST_INCLUDE) { 1090 if (nsrc1 == 0) { 1091 CTR1(KTR_MLD, "%s: --in on inm at t1", __func__); 1092 --inm->in6m_st[1].iss_in; 1093 } 1094 } 1095 1096 /* Handle filter mode transition on socket. */ 1097 if (imf->im6f_st[0] != imf->im6f_st[1]) { 1098 CTR3(KTR_MLD, "%s: imf transition %d to %d", 1099 __func__, imf->im6f_st[0], imf->im6f_st[1]); 1100 1101 if (imf->im6f_st[0] == MCAST_EXCLUDE) { 1102 CTR1(KTR_MLD, "%s: --ex on inm at t1", __func__); 1103 --inm->in6m_st[1].iss_ex; 1104 } else if (imf->im6f_st[0] == MCAST_INCLUDE) { 1105 CTR1(KTR_MLD, "%s: --in on inm at t1", __func__); 1106 --inm->in6m_st[1].iss_in; 1107 } 1108 1109 if (imf->im6f_st[1] == MCAST_EXCLUDE) { 1110 CTR1(KTR_MLD, "%s: ex++ on inm at t1", __func__); 1111 inm->in6m_st[1].iss_ex++; 1112 } else if (imf->im6f_st[1] == MCAST_INCLUDE && nsrc1 > 0) { 1113 CTR1(KTR_MLD, "%s: in++ on inm at t1", __func__); 1114 inm->in6m_st[1].iss_in++; 1115 } 1116 } 1117 1118 /* 1119 * Track inm filter state in terms of listener counts. 1120 * If there are any exclusive listeners, stack-wide 1121 * membership is exclusive. 1122 * Otherwise, if only inclusive listeners, stack-wide is inclusive. 1123 * If no listeners remain, state is undefined at t1, 1124 * and the MLD lifecycle for this group should finish. 1125 */ 1126 if (inm->in6m_st[1].iss_ex > 0) { 1127 CTR1(KTR_MLD, "%s: transition to EX", __func__); 1128 inm->in6m_st[1].iss_fmode = MCAST_EXCLUDE; 1129 } else if (inm->in6m_st[1].iss_in > 0) { 1130 CTR1(KTR_MLD, "%s: transition to IN", __func__); 1131 inm->in6m_st[1].iss_fmode = MCAST_INCLUDE; 1132 } else { 1133 CTR1(KTR_MLD, "%s: transition to UNDEF", __func__); 1134 inm->in6m_st[1].iss_fmode = MCAST_UNDEFINED; 1135 } 1136 1137 /* Decrement ASM listener count on transition out of ASM mode. */ 1138 if (imf->im6f_st[0] == MCAST_EXCLUDE && nsrc0 == 0) { 1139 if ((imf->im6f_st[1] != MCAST_EXCLUDE) || 1140 (imf->im6f_st[1] == MCAST_EXCLUDE && nsrc1 > 0)) { 1141 CTR1(KTR_MLD, "%s: --asm on inm at t1", __func__); 1142 --inm->in6m_st[1].iss_asm; 1143 } 1144 } 1145 1146 /* Increment ASM listener count on transition to ASM mode. */ 1147 if (imf->im6f_st[1] == MCAST_EXCLUDE && nsrc1 == 0) { 1148 CTR1(KTR_MLD, "%s: asm++ on inm at t1", __func__); 1149 inm->in6m_st[1].iss_asm++; 1150 } 1151 1152 CTR3(KTR_MLD, "%s: merged imf %p to inm %p", __func__, imf, inm); 1153 in6m_print(inm); 1154 1155 out_reap: 1156 if (schanged > 0) { 1157 CTR1(KTR_MLD, "%s: sources changed; reaping", __func__); 1158 in6m_reap(inm); 1159 } 1160 return (error); 1161 } 1162 1163 /* 1164 * Mark an in6_multi's filter set deltas as committed. 1165 * Called by MLD after a state change has been enqueued. 1166 */ 1167 void 1168 in6m_commit(struct in6_multi *inm) 1169 { 1170 struct ip6_msource *ims; 1171 1172 CTR2(KTR_MLD, "%s: commit inm %p", __func__, inm); 1173 CTR1(KTR_MLD, "%s: pre commit:", __func__); 1174 in6m_print(inm); 1175 1176 RB_FOREACH(ims, ip6_msource_tree, &inm->in6m_srcs) { 1177 ims->im6s_st[0] = ims->im6s_st[1]; 1178 } 1179 inm->in6m_st[0] = inm->in6m_st[1]; 1180 } 1181 1182 /* 1183 * Reap unreferenced nodes from an in6_multi's filter set. 1184 */ 1185 static void 1186 in6m_reap(struct in6_multi *inm) 1187 { 1188 struct ip6_msource *ims, *tims; 1189 1190 RB_FOREACH_SAFE(ims, ip6_msource_tree, &inm->in6m_srcs, tims) { 1191 if (ims->im6s_st[0].ex > 0 || ims->im6s_st[0].in > 0 || 1192 ims->im6s_st[1].ex > 0 || ims->im6s_st[1].in > 0 || 1193 ims->im6s_stp != 0) 1194 continue; 1195 CTR2(KTR_MLD, "%s: free ims %p", __func__, ims); 1196 RB_REMOVE(ip6_msource_tree, &inm->in6m_srcs, ims); 1197 free(ims, M_IP6MSOURCE); 1198 inm->in6m_nsrc--; 1199 } 1200 } 1201 1202 /* 1203 * Purge all source nodes from an in6_multi's filter set. 1204 */ 1205 static void 1206 in6m_purge(struct in6_multi *inm) 1207 { 1208 struct ip6_msource *ims, *tims; 1209 1210 RB_FOREACH_SAFE(ims, ip6_msource_tree, &inm->in6m_srcs, tims) { 1211 CTR2(KTR_MLD, "%s: free ims %p", __func__, ims); 1212 RB_REMOVE(ip6_msource_tree, &inm->in6m_srcs, ims); 1213 free(ims, M_IP6MSOURCE); 1214 inm->in6m_nsrc--; 1215 } 1216 /* Free state-change requests that might be queued. */ 1217 mbufq_drain(&inm->in6m_scq); 1218 } 1219 1220 /* 1221 * Join a multicast address w/o sources. 1222 * KAME compatibility entry point. 1223 * 1224 * SMPng: Assume no mc locks held by caller. 1225 */ 1226 int 1227 in6_joingroup(struct ifnet *ifp, const struct in6_addr *mcaddr, 1228 /*const*/ struct in6_mfilter *imf, struct in6_multi **pinm, 1229 const int delay) 1230 { 1231 int error; 1232 1233 IN6_MULTI_LOCK(); 1234 error = in6_joingroup_locked(ifp, mcaddr, NULL, pinm, delay); 1235 IN6_MULTI_UNLOCK(); 1236 return (error); 1237 } 1238 1239 /* 1240 * Join a multicast group; real entry point. 1241 * 1242 * Only preserves atomicity at inm level. 1243 * NOTE: imf argument cannot be const due to sys/tree.h limitations. 1244 * 1245 * If the MLD downcall fails, the group is not joined, and an error 1246 * code is returned. 1247 */ 1248 int 1249 in6_joingroup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr, 1250 /*const*/ struct in6_mfilter *imf, struct in6_multi **pinm, 1251 const int delay) 1252 { 1253 struct in6_multi_head inmh; 1254 struct in6_mfilter timf; 1255 struct in6_multi *inm; 1256 struct ifmultiaddr *ifma; 1257 int error; 1258 #ifdef KTR 1259 char ip6tbuf[INET6_ADDRSTRLEN]; 1260 #endif 1261 1262 /* 1263 * Sanity: Check scope zone ID was set for ifp, if and 1264 * only if group is scoped to an interface. 1265 */ 1266 KASSERT(IN6_IS_ADDR_MULTICAST(mcaddr), 1267 ("%s: not a multicast address", __func__)); 1268 if (IN6_IS_ADDR_MC_LINKLOCAL(mcaddr) || 1269 IN6_IS_ADDR_MC_INTFACELOCAL(mcaddr)) { 1270 KASSERT(mcaddr->s6_addr16[1] != 0, 1271 ("%s: scope zone ID not set", __func__)); 1272 } 1273 1274 IN6_MULTI_LOCK_ASSERT(); 1275 IN6_MULTI_LIST_UNLOCK_ASSERT(); 1276 1277 CTR4(KTR_MLD, "%s: join %s on %p(%s))", __func__, 1278 ip6_sprintf(ip6tbuf, mcaddr), ifp, if_name(ifp)); 1279 1280 error = 0; 1281 inm = NULL; 1282 1283 /* 1284 * If no imf was specified (i.e. kernel consumer), 1285 * fake one up and assume it is an ASM join. 1286 */ 1287 if (imf == NULL) { 1288 im6f_init(&timf, MCAST_UNDEFINED, MCAST_EXCLUDE); 1289 imf = &timf; 1290 } 1291 error = in6_getmulti(ifp, mcaddr, &inm); 1292 if (error) { 1293 CTR1(KTR_MLD, "%s: in6_getmulti() failure", __func__); 1294 return (error); 1295 } 1296 1297 IN6_MULTI_LIST_LOCK(); 1298 CTR1(KTR_MLD, "%s: merge inm state", __func__); 1299 error = in6m_merge(inm, imf); 1300 if (error) { 1301 CTR1(KTR_MLD, "%s: failed to merge inm state", __func__); 1302 goto out_in6m_release; 1303 } 1304 1305 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 1306 error = mld_change_state(inm, delay); 1307 if (error) { 1308 CTR1(KTR_MLD, "%s: failed to update source", __func__); 1309 goto out_in6m_release; 1310 } 1311 1312 out_in6m_release: 1313 SLIST_INIT(&inmh); 1314 if (error) { 1315 struct epoch_tracker et; 1316 1317 CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm); 1318 NET_EPOCH_ENTER(et); 1319 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1320 if (ifma->ifma_protospec == inm) { 1321 ifma->ifma_protospec = NULL; 1322 break; 1323 } 1324 } 1325 in6m_disconnect_locked(&inmh, inm); 1326 in6m_rele_locked(&inmh, inm); 1327 NET_EPOCH_EXIT(et); 1328 } else { 1329 *pinm = inm; 1330 } 1331 IN6_MULTI_LIST_UNLOCK(); 1332 in6m_release_list_deferred(&inmh); 1333 return (error); 1334 } 1335 1336 /* 1337 * Leave a multicast group; unlocked entry point. 1338 */ 1339 int 1340 in6_leavegroup(struct in6_multi *inm, /*const*/ struct in6_mfilter *imf) 1341 { 1342 int error; 1343 1344 IN6_MULTI_LOCK(); 1345 error = in6_leavegroup_locked(inm, imf); 1346 IN6_MULTI_UNLOCK(); 1347 return (error); 1348 } 1349 1350 /* 1351 * Leave a multicast group; real entry point. 1352 * All source filters will be expunged. 1353 * 1354 * Only preserves atomicity at inm level. 1355 * 1356 * Holding the write lock for the INP which contains imf 1357 * is highly advisable. We can't assert for it as imf does not 1358 * contain a back-pointer to the owning inp. 1359 * 1360 * Note: This is not the same as in6m_release(*) as this function also 1361 * makes a state change downcall into MLD. 1362 */ 1363 int 1364 in6_leavegroup_locked(struct in6_multi *inm, /*const*/ struct in6_mfilter *imf) 1365 { 1366 struct in6_multi_head inmh; 1367 struct in6_mfilter timf; 1368 struct ifnet *ifp; 1369 int error; 1370 #ifdef KTR 1371 char ip6tbuf[INET6_ADDRSTRLEN]; 1372 #endif 1373 1374 error = 0; 1375 1376 IN6_MULTI_LOCK_ASSERT(); 1377 1378 CTR5(KTR_MLD, "%s: leave inm %p, %s/%s, imf %p", __func__, 1379 inm, ip6_sprintf(ip6tbuf, &inm->in6m_addr), 1380 (in6m_is_ifp_detached(inm) ? "null" : if_name(inm->in6m_ifp)), 1381 imf); 1382 1383 /* 1384 * If no imf was specified (i.e. kernel consumer), 1385 * fake one up and assume it is an ASM join. 1386 */ 1387 if (imf == NULL) { 1388 im6f_init(&timf, MCAST_EXCLUDE, MCAST_UNDEFINED); 1389 imf = &timf; 1390 } 1391 1392 /* 1393 * Begin state merge transaction at MLD layer. 1394 * 1395 * As this particular invocation should not cause any memory 1396 * to be allocated, and there is no opportunity to roll back 1397 * the transaction, it MUST NOT fail. 1398 */ 1399 1400 ifp = inm->in6m_ifp; 1401 IN6_MULTI_LIST_LOCK(); 1402 CTR1(KTR_MLD, "%s: merge inm state", __func__); 1403 error = in6m_merge(inm, imf); 1404 KASSERT(error == 0, ("%s: failed to merge inm state", __func__)); 1405 1406 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 1407 error = 0; 1408 if (ifp) 1409 error = mld_change_state(inm, 0); 1410 if (error) 1411 CTR1(KTR_MLD, "%s: failed mld downcall", __func__); 1412 1413 CTR2(KTR_MLD, "%s: dropping ref on %p", __func__, inm); 1414 if (ifp) 1415 IF_ADDR_WLOCK(ifp); 1416 1417 SLIST_INIT(&inmh); 1418 if (inm->in6m_refcount == 1) 1419 in6m_disconnect_locked(&inmh, inm); 1420 in6m_rele_locked(&inmh, inm); 1421 if (ifp) 1422 IF_ADDR_WUNLOCK(ifp); 1423 IN6_MULTI_LIST_UNLOCK(); 1424 in6m_release_list_deferred(&inmh); 1425 return (error); 1426 } 1427 1428 1429 /* 1430 * Block or unblock an ASM multicast source on an inpcb. 1431 * This implements the delta-based API described in RFC 3678. 1432 * 1433 * The delta-based API applies only to exclusive-mode memberships. 1434 * An MLD downcall will be performed. 1435 * 1436 * SMPng: NOTE: Must take Giant as a join may create a new ifma. 1437 * 1438 * Return 0 if successful, otherwise return an appropriate error code. 1439 */ 1440 static int 1441 in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) 1442 { 1443 struct group_source_req gsr; 1444 sockunion_t *gsa, *ssa; 1445 struct ifnet *ifp; 1446 struct in6_mfilter *imf; 1447 struct ip6_moptions *imo; 1448 struct in6_msource *ims; 1449 struct in6_multi *inm; 1450 size_t idx; 1451 uint16_t fmode; 1452 int error, doblock; 1453 #ifdef KTR 1454 char ip6tbuf[INET6_ADDRSTRLEN]; 1455 #endif 1456 1457 ifp = NULL; 1458 error = 0; 1459 doblock = 0; 1460 1461 memset(&gsr, 0, sizeof(struct group_source_req)); 1462 gsa = (sockunion_t *)&gsr.gsr_group; 1463 ssa = (sockunion_t *)&gsr.gsr_source; 1464 1465 switch (sopt->sopt_name) { 1466 case MCAST_BLOCK_SOURCE: 1467 case MCAST_UNBLOCK_SOURCE: 1468 error = sooptcopyin(sopt, &gsr, 1469 sizeof(struct group_source_req), 1470 sizeof(struct group_source_req)); 1471 if (error) 1472 return (error); 1473 1474 if (gsa->sin6.sin6_family != AF_INET6 || 1475 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 1476 return (EINVAL); 1477 1478 if (ssa->sin6.sin6_family != AF_INET6 || 1479 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 1480 return (EINVAL); 1481 1482 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 1483 return (EADDRNOTAVAIL); 1484 1485 ifp = ifnet_byindex(gsr.gsr_interface); 1486 1487 if (sopt->sopt_name == MCAST_BLOCK_SOURCE) 1488 doblock = 1; 1489 break; 1490 1491 default: 1492 CTR2(KTR_MLD, "%s: unknown sopt_name %d", 1493 __func__, sopt->sopt_name); 1494 return (EOPNOTSUPP); 1495 break; 1496 } 1497 1498 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) 1499 return (EINVAL); 1500 1501 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL); 1502 1503 /* 1504 * Check if we are actually a member of this group. 1505 */ 1506 imo = in6p_findmoptions(inp); 1507 idx = im6o_match_group(imo, ifp, &gsa->sa); 1508 if (idx == -1 || imo->im6o_mfilters == NULL) { 1509 error = EADDRNOTAVAIL; 1510 goto out_in6p_locked; 1511 } 1512 1513 KASSERT(imo->im6o_mfilters != NULL, 1514 ("%s: im6o_mfilters not allocated", __func__)); 1515 imf = &imo->im6o_mfilters[idx]; 1516 inm = imo->im6o_membership[idx]; 1517 1518 /* 1519 * Attempting to use the delta-based API on an 1520 * non exclusive-mode membership is an error. 1521 */ 1522 fmode = imf->im6f_st[0]; 1523 if (fmode != MCAST_EXCLUDE) { 1524 error = EINVAL; 1525 goto out_in6p_locked; 1526 } 1527 1528 /* 1529 * Deal with error cases up-front: 1530 * Asked to block, but already blocked; or 1531 * Asked to unblock, but nothing to unblock. 1532 * If adding a new block entry, allocate it. 1533 */ 1534 ims = im6o_match_source(imo, idx, &ssa->sa); 1535 if ((ims != NULL && doblock) || (ims == NULL && !doblock)) { 1536 CTR3(KTR_MLD, "%s: source %s %spresent", __func__, 1537 ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr), 1538 doblock ? "" : "not "); 1539 error = EADDRNOTAVAIL; 1540 goto out_in6p_locked; 1541 } 1542 1543 INP_WLOCK_ASSERT(inp); 1544 1545 /* 1546 * Begin state merge transaction at socket layer. 1547 */ 1548 if (doblock) { 1549 CTR2(KTR_MLD, "%s: %s source", __func__, "block"); 1550 ims = im6f_graft(imf, fmode, &ssa->sin6); 1551 if (ims == NULL) 1552 error = ENOMEM; 1553 } else { 1554 CTR2(KTR_MLD, "%s: %s source", __func__, "allow"); 1555 error = im6f_prune(imf, &ssa->sin6); 1556 } 1557 1558 if (error) { 1559 CTR1(KTR_MLD, "%s: merge imf state failed", __func__); 1560 goto out_im6f_rollback; 1561 } 1562 1563 /* 1564 * Begin state merge transaction at MLD layer. 1565 */ 1566 IN6_MULTI_LIST_LOCK(); 1567 CTR1(KTR_MLD, "%s: merge inm state", __func__); 1568 error = in6m_merge(inm, imf); 1569 if (error) 1570 CTR1(KTR_MLD, "%s: failed to merge inm state", __func__); 1571 else { 1572 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 1573 error = mld_change_state(inm, 0); 1574 if (error) 1575 CTR1(KTR_MLD, "%s: failed mld downcall", __func__); 1576 } 1577 1578 IN6_MULTI_LIST_UNLOCK(); 1579 1580 out_im6f_rollback: 1581 if (error) 1582 im6f_rollback(imf); 1583 else 1584 im6f_commit(imf); 1585 1586 im6f_reap(imf); 1587 1588 out_in6p_locked: 1589 INP_WUNLOCK(inp); 1590 return (error); 1591 } 1592 1593 /* 1594 * Given an inpcb, return its multicast options structure pointer. Accepts 1595 * an unlocked inpcb pointer, but will return it locked. May sleep. 1596 * 1597 * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held. 1598 * SMPng: NOTE: Returns with the INP write lock held. 1599 */ 1600 static struct ip6_moptions * 1601 in6p_findmoptions(struct inpcb *inp) 1602 { 1603 struct ip6_moptions *imo; 1604 struct in6_multi **immp; 1605 struct in6_mfilter *imfp; 1606 size_t idx; 1607 1608 INP_WLOCK(inp); 1609 if (inp->in6p_moptions != NULL) 1610 return (inp->in6p_moptions); 1611 1612 INP_WUNLOCK(inp); 1613 1614 imo = malloc(sizeof(*imo), M_IP6MOPTS, M_WAITOK); 1615 immp = malloc(sizeof(*immp) * IPV6_MIN_MEMBERSHIPS, M_IP6MOPTS, 1616 M_WAITOK | M_ZERO); 1617 imfp = malloc(sizeof(struct in6_mfilter) * IPV6_MIN_MEMBERSHIPS, 1618 M_IN6MFILTER, M_WAITOK); 1619 1620 imo->im6o_multicast_ifp = NULL; 1621 imo->im6o_multicast_hlim = V_ip6_defmcasthlim; 1622 imo->im6o_multicast_loop = in6_mcast_loop; 1623 imo->im6o_num_memberships = 0; 1624 imo->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS; 1625 imo->im6o_membership = immp; 1626 1627 /* Initialize per-group source filters. */ 1628 for (idx = 0; idx < IPV6_MIN_MEMBERSHIPS; idx++) 1629 im6f_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE); 1630 imo->im6o_mfilters = imfp; 1631 1632 INP_WLOCK(inp); 1633 if (inp->in6p_moptions != NULL) { 1634 free(imfp, M_IN6MFILTER); 1635 free(immp, M_IP6MOPTS); 1636 free(imo, M_IP6MOPTS); 1637 return (inp->in6p_moptions); 1638 } 1639 inp->in6p_moptions = imo; 1640 return (imo); 1641 } 1642 1643 /* 1644 * Discard the IPv6 multicast options (and source filters). 1645 * 1646 * SMPng: NOTE: assumes INP write lock is held. 1647 * 1648 * XXX can all be safely deferred to epoch_call 1649 * 1650 */ 1651 1652 static void 1653 inp_gcmoptions(struct ip6_moptions *imo) 1654 { 1655 struct in6_mfilter *imf; 1656 struct in6_multi *inm; 1657 struct ifnet *ifp; 1658 size_t idx, nmships; 1659 1660 nmships = imo->im6o_num_memberships; 1661 for (idx = 0; idx < nmships; ++idx) { 1662 imf = imo->im6o_mfilters ? &imo->im6o_mfilters[idx] : NULL; 1663 if (imf) 1664 im6f_leave(imf); 1665 inm = imo->im6o_membership[idx]; 1666 ifp = inm->in6m_ifp; 1667 if (ifp != NULL) { 1668 CURVNET_SET(ifp->if_vnet); 1669 (void)in6_leavegroup(inm, imf); 1670 CURVNET_RESTORE(); 1671 } else { 1672 (void)in6_leavegroup(inm, imf); 1673 } 1674 if (imf) 1675 im6f_purge(imf); 1676 } 1677 1678 if (imo->im6o_mfilters) 1679 free(imo->im6o_mfilters, M_IN6MFILTER); 1680 free(imo->im6o_membership, M_IP6MOPTS); 1681 free(imo, M_IP6MOPTS); 1682 } 1683 1684 void 1685 ip6_freemoptions(struct ip6_moptions *imo) 1686 { 1687 if (imo == NULL) 1688 return; 1689 inp_gcmoptions(imo); 1690 } 1691 1692 /* 1693 * Atomically get source filters on a socket for an IPv6 multicast group. 1694 * Called with INP lock held; returns with lock released. 1695 */ 1696 static int 1697 in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt) 1698 { 1699 struct __msfilterreq msfr; 1700 sockunion_t *gsa; 1701 struct ifnet *ifp; 1702 struct ip6_moptions *imo; 1703 struct in6_mfilter *imf; 1704 struct ip6_msource *ims; 1705 struct in6_msource *lims; 1706 struct sockaddr_in6 *psin; 1707 struct sockaddr_storage *ptss; 1708 struct sockaddr_storage *tss; 1709 int error; 1710 size_t idx, nsrcs, ncsrcs; 1711 1712 INP_WLOCK_ASSERT(inp); 1713 1714 imo = inp->in6p_moptions; 1715 KASSERT(imo != NULL, ("%s: null ip6_moptions", __func__)); 1716 1717 INP_WUNLOCK(inp); 1718 1719 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 1720 sizeof(struct __msfilterreq)); 1721 if (error) 1722 return (error); 1723 1724 if (msfr.msfr_group.ss_family != AF_INET6 || 1725 msfr.msfr_group.ss_len != sizeof(struct sockaddr_in6)) 1726 return (EINVAL); 1727 1728 gsa = (sockunion_t *)&msfr.msfr_group; 1729 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) 1730 return (EINVAL); 1731 1732 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 1733 return (EADDRNOTAVAIL); 1734 ifp = ifnet_byindex(msfr.msfr_ifindex); 1735 if (ifp == NULL) 1736 return (EADDRNOTAVAIL); 1737 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL); 1738 1739 INP_WLOCK(inp); 1740 1741 /* 1742 * Lookup group on the socket. 1743 */ 1744 idx = im6o_match_group(imo, ifp, &gsa->sa); 1745 if (idx == -1 || imo->im6o_mfilters == NULL) { 1746 INP_WUNLOCK(inp); 1747 return (EADDRNOTAVAIL); 1748 } 1749 imf = &imo->im6o_mfilters[idx]; 1750 1751 /* 1752 * Ignore memberships which are in limbo. 1753 */ 1754 if (imf->im6f_st[1] == MCAST_UNDEFINED) { 1755 INP_WUNLOCK(inp); 1756 return (EAGAIN); 1757 } 1758 msfr.msfr_fmode = imf->im6f_st[1]; 1759 1760 /* 1761 * If the user specified a buffer, copy out the source filter 1762 * entries to userland gracefully. 1763 * We only copy out the number of entries which userland 1764 * has asked for, but we always tell userland how big the 1765 * buffer really needs to be. 1766 */ 1767 if (msfr.msfr_nsrcs > in6_mcast_maxsocksrc) 1768 msfr.msfr_nsrcs = in6_mcast_maxsocksrc; 1769 tss = NULL; 1770 if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) { 1771 tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 1772 M_TEMP, M_NOWAIT | M_ZERO); 1773 if (tss == NULL) { 1774 INP_WUNLOCK(inp); 1775 return (ENOBUFS); 1776 } 1777 } 1778 1779 /* 1780 * Count number of sources in-mode at t0. 1781 * If buffer space exists and remains, copy out source entries. 1782 */ 1783 nsrcs = msfr.msfr_nsrcs; 1784 ncsrcs = 0; 1785 ptss = tss; 1786 RB_FOREACH(ims, ip6_msource_tree, &imf->im6f_sources) { 1787 lims = (struct in6_msource *)ims; 1788 if (lims->im6sl_st[0] == MCAST_UNDEFINED || 1789 lims->im6sl_st[0] != imf->im6f_st[0]) 1790 continue; 1791 ++ncsrcs; 1792 if (tss != NULL && nsrcs > 0) { 1793 psin = (struct sockaddr_in6 *)ptss; 1794 psin->sin6_family = AF_INET6; 1795 psin->sin6_len = sizeof(struct sockaddr_in6); 1796 psin->sin6_addr = lims->im6s_addr; 1797 psin->sin6_port = 0; 1798 --nsrcs; 1799 ++ptss; 1800 } 1801 } 1802 1803 INP_WUNLOCK(inp); 1804 1805 if (tss != NULL) { 1806 error = copyout(tss, msfr.msfr_srcs, 1807 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 1808 free(tss, M_TEMP); 1809 if (error) 1810 return (error); 1811 } 1812 1813 msfr.msfr_nsrcs = ncsrcs; 1814 error = sooptcopyout(sopt, &msfr, sizeof(struct __msfilterreq)); 1815 1816 return (error); 1817 } 1818 1819 /* 1820 * Return the IP multicast options in response to user getsockopt(). 1821 */ 1822 int 1823 ip6_getmoptions(struct inpcb *inp, struct sockopt *sopt) 1824 { 1825 struct ip6_moptions *im6o; 1826 int error; 1827 u_int optval; 1828 1829 INP_WLOCK(inp); 1830 im6o = inp->in6p_moptions; 1831 /* 1832 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 1833 * or is a divert socket, reject it. 1834 */ 1835 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 1836 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 1837 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) { 1838 INP_WUNLOCK(inp); 1839 return (EOPNOTSUPP); 1840 } 1841 1842 error = 0; 1843 switch (sopt->sopt_name) { 1844 case IPV6_MULTICAST_IF: 1845 if (im6o == NULL || im6o->im6o_multicast_ifp == NULL) { 1846 optval = 0; 1847 } else { 1848 optval = im6o->im6o_multicast_ifp->if_index; 1849 } 1850 INP_WUNLOCK(inp); 1851 error = sooptcopyout(sopt, &optval, sizeof(u_int)); 1852 break; 1853 1854 case IPV6_MULTICAST_HOPS: 1855 if (im6o == NULL) 1856 optval = V_ip6_defmcasthlim; 1857 else 1858 optval = im6o->im6o_multicast_hlim; 1859 INP_WUNLOCK(inp); 1860 error = sooptcopyout(sopt, &optval, sizeof(u_int)); 1861 break; 1862 1863 case IPV6_MULTICAST_LOOP: 1864 if (im6o == NULL) 1865 optval = in6_mcast_loop; /* XXX VIMAGE */ 1866 else 1867 optval = im6o->im6o_multicast_loop; 1868 INP_WUNLOCK(inp); 1869 error = sooptcopyout(sopt, &optval, sizeof(u_int)); 1870 break; 1871 1872 case IPV6_MSFILTER: 1873 if (im6o == NULL) { 1874 error = EADDRNOTAVAIL; 1875 INP_WUNLOCK(inp); 1876 } else { 1877 error = in6p_get_source_filters(inp, sopt); 1878 } 1879 break; 1880 1881 default: 1882 INP_WUNLOCK(inp); 1883 error = ENOPROTOOPT; 1884 break; 1885 } 1886 1887 INP_UNLOCK_ASSERT(inp); 1888 1889 return (error); 1890 } 1891 1892 /* 1893 * Look up the ifnet to use for a multicast group membership, 1894 * given the address of an IPv6 group. 1895 * 1896 * This routine exists to support legacy IPv6 multicast applications. 1897 * 1898 * If inp is non-NULL, use this socket's current FIB number for any 1899 * required FIB lookup. Look up the group address in the unicast FIB, 1900 * and use its ifp; usually, this points to the default next-hop. 1901 * If the FIB lookup fails, return NULL. 1902 * 1903 * FUTURE: Support multiple forwarding tables for IPv6. 1904 * 1905 * Returns NULL if no ifp could be found. 1906 */ 1907 static struct ifnet * 1908 in6p_lookup_mcast_ifp(const struct inpcb *in6p, 1909 const struct sockaddr_in6 *gsin6) 1910 { 1911 struct nhop6_basic nh6; 1912 struct in6_addr dst; 1913 uint32_t scopeid; 1914 uint32_t fibnum; 1915 1916 KASSERT(in6p->inp_vflag & INP_IPV6, 1917 ("%s: not INP_IPV6 inpcb", __func__)); 1918 KASSERT(gsin6->sin6_family == AF_INET6, 1919 ("%s: not AF_INET6 group", __func__)); 1920 1921 in6_splitscope(&gsin6->sin6_addr, &dst, &scopeid); 1922 fibnum = in6p ? in6p->inp_inc.inc_fibnum : RT_DEFAULT_FIB; 1923 if (fib6_lookup_nh_basic(fibnum, &dst, scopeid, 0, 0, &nh6) != 0) 1924 return (NULL); 1925 1926 return (nh6.nh_ifp); 1927 } 1928 1929 /* 1930 * Join an IPv6 multicast group, possibly with a source. 1931 * 1932 * FIXME: The KAME use of the unspecified address (::) 1933 * to join *all* multicast groups is currently unsupported. 1934 */ 1935 static int 1936 in6p_join_group(struct inpcb *inp, struct sockopt *sopt) 1937 { 1938 struct in6_multi_head inmh; 1939 struct group_source_req gsr; 1940 sockunion_t *gsa, *ssa; 1941 struct ifnet *ifp; 1942 struct in6_mfilter *imf; 1943 struct ip6_moptions *imo; 1944 struct in6_multi *inm; 1945 struct in6_msource *lims; 1946 size_t idx; 1947 int error, is_new; 1948 1949 SLIST_INIT(&inmh); 1950 ifp = NULL; 1951 imf = NULL; 1952 lims = NULL; 1953 error = 0; 1954 is_new = 0; 1955 1956 memset(&gsr, 0, sizeof(struct group_source_req)); 1957 gsa = (sockunion_t *)&gsr.gsr_group; 1958 gsa->ss.ss_family = AF_UNSPEC; 1959 ssa = (sockunion_t *)&gsr.gsr_source; 1960 ssa->ss.ss_family = AF_UNSPEC; 1961 1962 /* 1963 * Chew everything into struct group_source_req. 1964 * Overwrite the port field if present, as the sockaddr 1965 * being copied in may be matched with a binary comparison. 1966 * Ignore passed-in scope ID. 1967 */ 1968 switch (sopt->sopt_name) { 1969 case IPV6_JOIN_GROUP: { 1970 struct ipv6_mreq mreq; 1971 1972 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq), 1973 sizeof(struct ipv6_mreq)); 1974 if (error) 1975 return (error); 1976 1977 gsa->sin6.sin6_family = AF_INET6; 1978 gsa->sin6.sin6_len = sizeof(struct sockaddr_in6); 1979 gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr; 1980 1981 if (mreq.ipv6mr_interface == 0) { 1982 ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6); 1983 } else { 1984 if (V_if_index < mreq.ipv6mr_interface) 1985 return (EADDRNOTAVAIL); 1986 ifp = ifnet_byindex(mreq.ipv6mr_interface); 1987 } 1988 CTR3(KTR_MLD, "%s: ipv6mr_interface = %d, ifp = %p", 1989 __func__, mreq.ipv6mr_interface, ifp); 1990 } break; 1991 1992 case MCAST_JOIN_GROUP: 1993 case MCAST_JOIN_SOURCE_GROUP: 1994 if (sopt->sopt_name == MCAST_JOIN_GROUP) { 1995 error = sooptcopyin(sopt, &gsr, 1996 sizeof(struct group_req), 1997 sizeof(struct group_req)); 1998 } else if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 1999 error = sooptcopyin(sopt, &gsr, 2000 sizeof(struct group_source_req), 2001 sizeof(struct group_source_req)); 2002 } 2003 if (error) 2004 return (error); 2005 2006 if (gsa->sin6.sin6_family != AF_INET6 || 2007 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 2008 return (EINVAL); 2009 2010 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 2011 if (ssa->sin6.sin6_family != AF_INET6 || 2012 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 2013 return (EINVAL); 2014 if (IN6_IS_ADDR_MULTICAST(&ssa->sin6.sin6_addr)) 2015 return (EINVAL); 2016 /* 2017 * TODO: Validate embedded scope ID in source 2018 * list entry against passed-in ifp, if and only 2019 * if source list filter entry is iface or node local. 2020 */ 2021 in6_clearscope(&ssa->sin6.sin6_addr); 2022 ssa->sin6.sin6_port = 0; 2023 ssa->sin6.sin6_scope_id = 0; 2024 } 2025 2026 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 2027 return (EADDRNOTAVAIL); 2028 ifp = ifnet_byindex(gsr.gsr_interface); 2029 break; 2030 2031 default: 2032 CTR2(KTR_MLD, "%s: unknown sopt_name %d", 2033 __func__, sopt->sopt_name); 2034 return (EOPNOTSUPP); 2035 break; 2036 } 2037 2038 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) 2039 return (EINVAL); 2040 2041 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) 2042 return (EADDRNOTAVAIL); 2043 2044 gsa->sin6.sin6_port = 0; 2045 gsa->sin6.sin6_scope_id = 0; 2046 2047 /* 2048 * Always set the scope zone ID on memberships created from userland. 2049 * Use the passed-in ifp to do this. 2050 * XXX The in6_setscope() return value is meaningless. 2051 * XXX SCOPE6_LOCK() is taken by in6_setscope(). 2052 */ 2053 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL); 2054 2055 imo = in6p_findmoptions(inp); 2056 idx = im6o_match_group(imo, ifp, &gsa->sa); 2057 if (idx == -1) { 2058 is_new = 1; 2059 } else { 2060 inm = imo->im6o_membership[idx]; 2061 imf = &imo->im6o_mfilters[idx]; 2062 if (ssa->ss.ss_family != AF_UNSPEC) { 2063 /* 2064 * MCAST_JOIN_SOURCE_GROUP on an exclusive membership 2065 * is an error. On an existing inclusive membership, 2066 * it just adds the source to the filter list. 2067 */ 2068 if (imf->im6f_st[1] != MCAST_INCLUDE) { 2069 error = EINVAL; 2070 goto out_in6p_locked; 2071 } 2072 /* 2073 * Throw out duplicates. 2074 * 2075 * XXX FIXME: This makes a naive assumption that 2076 * even if entries exist for *ssa in this imf, 2077 * they will be rejected as dupes, even if they 2078 * are not valid in the current mode (in-mode). 2079 * 2080 * in6_msource is transactioned just as for anything 2081 * else in SSM -- but note naive use of in6m_graft() 2082 * below for allocating new filter entries. 2083 * 2084 * This is only an issue if someone mixes the 2085 * full-state SSM API with the delta-based API, 2086 * which is discouraged in the relevant RFCs. 2087 */ 2088 lims = im6o_match_source(imo, idx, &ssa->sa); 2089 if (lims != NULL /*&& 2090 lims->im6sl_st[1] == MCAST_INCLUDE*/) { 2091 error = EADDRNOTAVAIL; 2092 goto out_in6p_locked; 2093 } 2094 } else { 2095 /* 2096 * MCAST_JOIN_GROUP alone, on any existing membership, 2097 * is rejected, to stop the same inpcb tying up 2098 * multiple refs to the in_multi. 2099 * On an existing inclusive membership, this is also 2100 * an error; if you want to change filter mode, 2101 * you must use the userland API setsourcefilter(). 2102 * XXX We don't reject this for imf in UNDEFINED 2103 * state at t1, because allocation of a filter 2104 * is atomic with allocation of a membership. 2105 */ 2106 error = EINVAL; 2107 goto out_in6p_locked; 2108 } 2109 } 2110 2111 /* 2112 * Begin state merge transaction at socket layer. 2113 */ 2114 INP_WLOCK_ASSERT(inp); 2115 2116 if (is_new) { 2117 if (imo->im6o_num_memberships == imo->im6o_max_memberships) { 2118 error = im6o_grow(imo); 2119 if (error) 2120 goto out_in6p_locked; 2121 } 2122 /* 2123 * Allocate the new slot upfront so we can deal with 2124 * grafting the new source filter in same code path 2125 * as for join-source on existing membership. 2126 */ 2127 idx = imo->im6o_num_memberships; 2128 imo->im6o_membership[idx] = NULL; 2129 imo->im6o_num_memberships++; 2130 KASSERT(imo->im6o_mfilters != NULL, 2131 ("%s: im6f_mfilters vector was not allocated", __func__)); 2132 imf = &imo->im6o_mfilters[idx]; 2133 KASSERT(RB_EMPTY(&imf->im6f_sources), 2134 ("%s: im6f_sources not empty", __func__)); 2135 } 2136 2137 /* 2138 * Graft new source into filter list for this inpcb's 2139 * membership of the group. The in6_multi may not have 2140 * been allocated yet if this is a new membership, however, 2141 * the in_mfilter slot will be allocated and must be initialized. 2142 * 2143 * Note: Grafting of exclusive mode filters doesn't happen 2144 * in this path. 2145 * XXX: Should check for non-NULL lims (node exists but may 2146 * not be in-mode) for interop with full-state API. 2147 */ 2148 if (ssa->ss.ss_family != AF_UNSPEC) { 2149 /* Membership starts in IN mode */ 2150 if (is_new) { 2151 CTR1(KTR_MLD, "%s: new join w/source", __func__); 2152 im6f_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE); 2153 } else { 2154 CTR2(KTR_MLD, "%s: %s source", __func__, "allow"); 2155 } 2156 lims = im6f_graft(imf, MCAST_INCLUDE, &ssa->sin6); 2157 if (lims == NULL) { 2158 CTR1(KTR_MLD, "%s: merge imf state failed", 2159 __func__); 2160 error = ENOMEM; 2161 goto out_im6o_free; 2162 } 2163 } else { 2164 /* No address specified; Membership starts in EX mode */ 2165 if (is_new) { 2166 CTR1(KTR_MLD, "%s: new join w/o source", __func__); 2167 im6f_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE); 2168 } 2169 } 2170 2171 /* 2172 * Begin state merge transaction at MLD layer. 2173 */ 2174 in_pcbref(inp); 2175 INP_WUNLOCK(inp); 2176 IN6_MULTI_LOCK(); 2177 2178 if (is_new) { 2179 error = in6_joingroup_locked(ifp, &gsa->sin6.sin6_addr, imf, 2180 &inm, 0); 2181 if (error) { 2182 IN6_MULTI_UNLOCK(); 2183 goto out_im6o_free; 2184 } 2185 /* 2186 * NOTE: Refcount from in6_joingroup_locked() 2187 * is protecting membership. 2188 */ 2189 imo->im6o_membership[idx] = inm; 2190 } else { 2191 CTR1(KTR_MLD, "%s: merge inm state", __func__); 2192 IN6_MULTI_LIST_LOCK(); 2193 error = in6m_merge(inm, imf); 2194 if (error) 2195 CTR1(KTR_MLD, "%s: failed to merge inm state", 2196 __func__); 2197 else { 2198 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 2199 error = mld_change_state(inm, 0); 2200 if (error) 2201 CTR1(KTR_MLD, "%s: failed mld downcall", 2202 __func__); 2203 } 2204 IN6_MULTI_LIST_UNLOCK(); 2205 } 2206 2207 IN6_MULTI_UNLOCK(); 2208 INP_WLOCK(inp); 2209 if (in_pcbrele_wlocked(inp)) 2210 return (ENXIO); 2211 if (error) { 2212 im6f_rollback(imf); 2213 if (is_new) 2214 im6f_purge(imf); 2215 else 2216 im6f_reap(imf); 2217 } else { 2218 im6f_commit(imf); 2219 } 2220 2221 out_im6o_free: 2222 if (error && is_new) { 2223 inm = imo->im6o_membership[idx]; 2224 if (inm != NULL) { 2225 IN6_MULTI_LIST_LOCK(); 2226 in6m_rele_locked(&inmh, inm); 2227 IN6_MULTI_LIST_UNLOCK(); 2228 } 2229 imo->im6o_membership[idx] = NULL; 2230 --imo->im6o_num_memberships; 2231 } 2232 2233 out_in6p_locked: 2234 INP_WUNLOCK(inp); 2235 in6m_release_list_deferred(&inmh); 2236 return (error); 2237 } 2238 2239 /* 2240 * Leave an IPv6 multicast group on an inpcb, possibly with a source. 2241 */ 2242 static int 2243 in6p_leave_group(struct inpcb *inp, struct sockopt *sopt) 2244 { 2245 struct ipv6_mreq mreq; 2246 struct group_source_req gsr; 2247 sockunion_t *gsa, *ssa; 2248 struct ifnet *ifp; 2249 struct in6_mfilter *imf; 2250 struct ip6_moptions *imo; 2251 struct in6_msource *ims; 2252 struct in6_multi *inm; 2253 uint32_t ifindex; 2254 size_t idx; 2255 int error, is_final; 2256 #ifdef KTR 2257 char ip6tbuf[INET6_ADDRSTRLEN]; 2258 #endif 2259 2260 ifp = NULL; 2261 ifindex = 0; 2262 error = 0; 2263 is_final = 1; 2264 2265 memset(&gsr, 0, sizeof(struct group_source_req)); 2266 gsa = (sockunion_t *)&gsr.gsr_group; 2267 gsa->ss.ss_family = AF_UNSPEC; 2268 ssa = (sockunion_t *)&gsr.gsr_source; 2269 ssa->ss.ss_family = AF_UNSPEC; 2270 2271 /* 2272 * Chew everything passed in up into a struct group_source_req 2273 * as that is easier to process. 2274 * Note: Any embedded scope ID in the multicast group passed 2275 * in by userland is ignored, the interface index is the recommended 2276 * mechanism to specify an interface; see below. 2277 */ 2278 switch (sopt->sopt_name) { 2279 case IPV6_LEAVE_GROUP: 2280 error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq), 2281 sizeof(struct ipv6_mreq)); 2282 if (error) 2283 return (error); 2284 gsa->sin6.sin6_family = AF_INET6; 2285 gsa->sin6.sin6_len = sizeof(struct sockaddr_in6); 2286 gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr; 2287 gsa->sin6.sin6_port = 0; 2288 gsa->sin6.sin6_scope_id = 0; 2289 ifindex = mreq.ipv6mr_interface; 2290 break; 2291 2292 case MCAST_LEAVE_GROUP: 2293 case MCAST_LEAVE_SOURCE_GROUP: 2294 if (sopt->sopt_name == MCAST_LEAVE_GROUP) { 2295 error = sooptcopyin(sopt, &gsr, 2296 sizeof(struct group_req), 2297 sizeof(struct group_req)); 2298 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 2299 error = sooptcopyin(sopt, &gsr, 2300 sizeof(struct group_source_req), 2301 sizeof(struct group_source_req)); 2302 } 2303 if (error) 2304 return (error); 2305 2306 if (gsa->sin6.sin6_family != AF_INET6 || 2307 gsa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 2308 return (EINVAL); 2309 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 2310 if (ssa->sin6.sin6_family != AF_INET6 || 2311 ssa->sin6.sin6_len != sizeof(struct sockaddr_in6)) 2312 return (EINVAL); 2313 if (IN6_IS_ADDR_MULTICAST(&ssa->sin6.sin6_addr)) 2314 return (EINVAL); 2315 /* 2316 * TODO: Validate embedded scope ID in source 2317 * list entry against passed-in ifp, if and only 2318 * if source list filter entry is iface or node local. 2319 */ 2320 in6_clearscope(&ssa->sin6.sin6_addr); 2321 } 2322 gsa->sin6.sin6_port = 0; 2323 gsa->sin6.sin6_scope_id = 0; 2324 ifindex = gsr.gsr_interface; 2325 break; 2326 2327 default: 2328 CTR2(KTR_MLD, "%s: unknown sopt_name %d", 2329 __func__, sopt->sopt_name); 2330 return (EOPNOTSUPP); 2331 break; 2332 } 2333 2334 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) 2335 return (EINVAL); 2336 2337 /* 2338 * Validate interface index if provided. If no interface index 2339 * was provided separately, attempt to look the membership up 2340 * from the default scope as a last resort to disambiguate 2341 * the membership we are being asked to leave. 2342 * XXX SCOPE6 lock potentially taken here. 2343 */ 2344 if (ifindex != 0) { 2345 if (V_if_index < ifindex) 2346 return (EADDRNOTAVAIL); 2347 ifp = ifnet_byindex(ifindex); 2348 if (ifp == NULL) 2349 return (EADDRNOTAVAIL); 2350 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL); 2351 } else { 2352 error = sa6_embedscope(&gsa->sin6, V_ip6_use_defzone); 2353 if (error) 2354 return (EADDRNOTAVAIL); 2355 /* 2356 * Some badly behaved applications don't pass an ifindex 2357 * or a scope ID, which is an API violation. In this case, 2358 * perform a lookup as per a v6 join. 2359 * 2360 * XXX For now, stomp on zone ID for the corner case. 2361 * This is not the 'KAME way', but we need to see the ifp 2362 * directly until such time as this implementation is 2363 * refactored, assuming the scope IDs are the way to go. 2364 */ 2365 ifindex = ntohs(gsa->sin6.sin6_addr.s6_addr16[1]); 2366 if (ifindex == 0) { 2367 CTR2(KTR_MLD, "%s: warning: no ifindex, looking up " 2368 "ifp for group %s.", __func__, 2369 ip6_sprintf(ip6tbuf, &gsa->sin6.sin6_addr)); 2370 ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6); 2371 } else { 2372 ifp = ifnet_byindex(ifindex); 2373 } 2374 if (ifp == NULL) 2375 return (EADDRNOTAVAIL); 2376 } 2377 2378 CTR2(KTR_MLD, "%s: ifp = %p", __func__, ifp); 2379 KASSERT(ifp != NULL, ("%s: ifp did not resolve", __func__)); 2380 2381 /* 2382 * Find the membership in the membership array. 2383 */ 2384 imo = in6p_findmoptions(inp); 2385 idx = im6o_match_group(imo, ifp, &gsa->sa); 2386 if (idx == -1) { 2387 error = EADDRNOTAVAIL; 2388 goto out_in6p_locked; 2389 } 2390 inm = imo->im6o_membership[idx]; 2391 imf = &imo->im6o_mfilters[idx]; 2392 2393 if (ssa->ss.ss_family != AF_UNSPEC) 2394 is_final = 0; 2395 2396 /* 2397 * Begin state merge transaction at socket layer. 2398 */ 2399 INP_WLOCK_ASSERT(inp); 2400 2401 /* 2402 * If we were instructed only to leave a given source, do so. 2403 * MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships. 2404 */ 2405 if (is_final) { 2406 im6f_leave(imf); 2407 } else { 2408 if (imf->im6f_st[0] == MCAST_EXCLUDE) { 2409 error = EADDRNOTAVAIL; 2410 goto out_in6p_locked; 2411 } 2412 ims = im6o_match_source(imo, idx, &ssa->sa); 2413 if (ims == NULL) { 2414 CTR3(KTR_MLD, "%s: source %p %spresent", __func__, 2415 ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr), 2416 "not "); 2417 error = EADDRNOTAVAIL; 2418 goto out_in6p_locked; 2419 } 2420 CTR2(KTR_MLD, "%s: %s source", __func__, "block"); 2421 error = im6f_prune(imf, &ssa->sin6); 2422 if (error) { 2423 CTR1(KTR_MLD, "%s: merge imf state failed", 2424 __func__); 2425 goto out_in6p_locked; 2426 } 2427 } 2428 2429 /* 2430 * Begin state merge transaction at MLD layer. 2431 */ 2432 in_pcbref(inp); 2433 INP_WUNLOCK(inp); 2434 IN6_MULTI_LOCK(); 2435 2436 if (is_final) { 2437 /* 2438 * Give up the multicast address record to which 2439 * the membership points. 2440 */ 2441 (void)in6_leavegroup_locked(inm, imf); 2442 } else { 2443 CTR1(KTR_MLD, "%s: merge inm state", __func__); 2444 IN6_MULTI_LIST_LOCK(); 2445 error = in6m_merge(inm, imf); 2446 if (error) 2447 CTR1(KTR_MLD, "%s: failed to merge inm state", 2448 __func__); 2449 else { 2450 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 2451 error = mld_change_state(inm, 0); 2452 if (error) 2453 CTR1(KTR_MLD, "%s: failed mld downcall", 2454 __func__); 2455 } 2456 IN6_MULTI_LIST_UNLOCK(); 2457 } 2458 2459 IN6_MULTI_UNLOCK(); 2460 INP_WLOCK(inp); 2461 if (in_pcbrele_wlocked(inp)) 2462 return (ENXIO); 2463 2464 if (error) 2465 im6f_rollback(imf); 2466 else 2467 im6f_commit(imf); 2468 2469 im6f_reap(imf); 2470 2471 if (is_final) { 2472 /* Remove the gap in the membership array. */ 2473 KASSERT(RB_EMPTY(&imf->im6f_sources), 2474 ("%s: im6f_sources not empty", __func__)); 2475 for (++idx; idx < imo->im6o_num_memberships; ++idx) { 2476 imo->im6o_membership[idx - 1] = imo->im6o_membership[idx]; 2477 imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx]; 2478 } 2479 im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED, 2480 MCAST_EXCLUDE); 2481 imo->im6o_num_memberships--; 2482 } 2483 2484 out_in6p_locked: 2485 INP_WUNLOCK(inp); 2486 return (error); 2487 } 2488 2489 /* 2490 * Select the interface for transmitting IPv6 multicast datagrams. 2491 * 2492 * Either an instance of struct in6_addr or an instance of struct ipv6_mreqn 2493 * may be passed to this socket option. An address of in6addr_any or an 2494 * interface index of 0 is used to remove a previous selection. 2495 * When no interface is selected, one is chosen for every send. 2496 */ 2497 static int 2498 in6p_set_multicast_if(struct inpcb *inp, struct sockopt *sopt) 2499 { 2500 struct ifnet *ifp; 2501 struct ip6_moptions *imo; 2502 u_int ifindex; 2503 int error; 2504 2505 if (sopt->sopt_valsize != sizeof(u_int)) 2506 return (EINVAL); 2507 2508 error = sooptcopyin(sopt, &ifindex, sizeof(u_int), sizeof(u_int)); 2509 if (error) 2510 return (error); 2511 if (V_if_index < ifindex) 2512 return (EINVAL); 2513 if (ifindex == 0) 2514 ifp = NULL; 2515 else { 2516 ifp = ifnet_byindex(ifindex); 2517 if (ifp == NULL) 2518 return (EINVAL); 2519 if ((ifp->if_flags & IFF_MULTICAST) == 0) 2520 return (EADDRNOTAVAIL); 2521 } 2522 imo = in6p_findmoptions(inp); 2523 imo->im6o_multicast_ifp = ifp; 2524 INP_WUNLOCK(inp); 2525 2526 return (0); 2527 } 2528 2529 /* 2530 * Atomically set source filters on a socket for an IPv6 multicast group. 2531 * 2532 * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held. 2533 */ 2534 static int 2535 in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt) 2536 { 2537 struct __msfilterreq msfr; 2538 sockunion_t *gsa; 2539 struct ifnet *ifp; 2540 struct in6_mfilter *imf; 2541 struct ip6_moptions *imo; 2542 struct in6_multi *inm; 2543 size_t idx; 2544 int error; 2545 2546 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 2547 sizeof(struct __msfilterreq)); 2548 if (error) 2549 return (error); 2550 2551 if (msfr.msfr_nsrcs > in6_mcast_maxsocksrc) 2552 return (ENOBUFS); 2553 2554 if (msfr.msfr_fmode != MCAST_EXCLUDE && 2555 msfr.msfr_fmode != MCAST_INCLUDE) 2556 return (EINVAL); 2557 2558 if (msfr.msfr_group.ss_family != AF_INET6 || 2559 msfr.msfr_group.ss_len != sizeof(struct sockaddr_in6)) 2560 return (EINVAL); 2561 2562 gsa = (sockunion_t *)&msfr.msfr_group; 2563 if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) 2564 return (EINVAL); 2565 2566 gsa->sin6.sin6_port = 0; /* ignore port */ 2567 2568 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 2569 return (EADDRNOTAVAIL); 2570 ifp = ifnet_byindex(msfr.msfr_ifindex); 2571 if (ifp == NULL) 2572 return (EADDRNOTAVAIL); 2573 (void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL); 2574 2575 /* 2576 * Take the INP write lock. 2577 * Check if this socket is a member of this group. 2578 */ 2579 imo = in6p_findmoptions(inp); 2580 idx = im6o_match_group(imo, ifp, &gsa->sa); 2581 if (idx == -1 || imo->im6o_mfilters == NULL) { 2582 error = EADDRNOTAVAIL; 2583 goto out_in6p_locked; 2584 } 2585 inm = imo->im6o_membership[idx]; 2586 imf = &imo->im6o_mfilters[idx]; 2587 2588 /* 2589 * Begin state merge transaction at socket layer. 2590 */ 2591 INP_WLOCK_ASSERT(inp); 2592 2593 imf->im6f_st[1] = msfr.msfr_fmode; 2594 2595 /* 2596 * Apply any new source filters, if present. 2597 * Make a copy of the user-space source vector so 2598 * that we may copy them with a single copyin. This 2599 * allows us to deal with page faults up-front. 2600 */ 2601 if (msfr.msfr_nsrcs > 0) { 2602 struct in6_msource *lims; 2603 struct sockaddr_in6 *psin; 2604 struct sockaddr_storage *kss, *pkss; 2605 int i; 2606 2607 INP_WUNLOCK(inp); 2608 2609 CTR2(KTR_MLD, "%s: loading %lu source list entries", 2610 __func__, (unsigned long)msfr.msfr_nsrcs); 2611 kss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 2612 M_TEMP, M_WAITOK); 2613 error = copyin(msfr.msfr_srcs, kss, 2614 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 2615 if (error) { 2616 free(kss, M_TEMP); 2617 return (error); 2618 } 2619 2620 INP_WLOCK(inp); 2621 2622 /* 2623 * Mark all source filters as UNDEFINED at t1. 2624 * Restore new group filter mode, as im6f_leave() 2625 * will set it to INCLUDE. 2626 */ 2627 im6f_leave(imf); 2628 imf->im6f_st[1] = msfr.msfr_fmode; 2629 2630 /* 2631 * Update socket layer filters at t1, lazy-allocating 2632 * new entries. This saves a bunch of memory at the 2633 * cost of one RB_FIND() per source entry; duplicate 2634 * entries in the msfr_nsrcs vector are ignored. 2635 * If we encounter an error, rollback transaction. 2636 * 2637 * XXX This too could be replaced with a set-symmetric 2638 * difference like loop to avoid walking from root 2639 * every time, as the key space is common. 2640 */ 2641 for (i = 0, pkss = kss; i < msfr.msfr_nsrcs; i++, pkss++) { 2642 psin = (struct sockaddr_in6 *)pkss; 2643 if (psin->sin6_family != AF_INET6) { 2644 error = EAFNOSUPPORT; 2645 break; 2646 } 2647 if (psin->sin6_len != sizeof(struct sockaddr_in6)) { 2648 error = EINVAL; 2649 break; 2650 } 2651 if (IN6_IS_ADDR_MULTICAST(&psin->sin6_addr)) { 2652 error = EINVAL; 2653 break; 2654 } 2655 /* 2656 * TODO: Validate embedded scope ID in source 2657 * list entry against passed-in ifp, if and only 2658 * if source list filter entry is iface or node local. 2659 */ 2660 in6_clearscope(&psin->sin6_addr); 2661 error = im6f_get_source(imf, psin, &lims); 2662 if (error) 2663 break; 2664 lims->im6sl_st[1] = imf->im6f_st[1]; 2665 } 2666 free(kss, M_TEMP); 2667 } 2668 2669 if (error) 2670 goto out_im6f_rollback; 2671 2672 INP_WLOCK_ASSERT(inp); 2673 IN6_MULTI_LIST_LOCK(); 2674 2675 /* 2676 * Begin state merge transaction at MLD layer. 2677 */ 2678 CTR1(KTR_MLD, "%s: merge inm state", __func__); 2679 error = in6m_merge(inm, imf); 2680 if (error) 2681 CTR1(KTR_MLD, "%s: failed to merge inm state", __func__); 2682 else { 2683 CTR1(KTR_MLD, "%s: doing mld downcall", __func__); 2684 error = mld_change_state(inm, 0); 2685 if (error) 2686 CTR1(KTR_MLD, "%s: failed mld downcall", __func__); 2687 } 2688 2689 IN6_MULTI_LIST_UNLOCK(); 2690 2691 out_im6f_rollback: 2692 if (error) 2693 im6f_rollback(imf); 2694 else 2695 im6f_commit(imf); 2696 2697 im6f_reap(imf); 2698 2699 out_in6p_locked: 2700 INP_WUNLOCK(inp); 2701 return (error); 2702 } 2703 2704 /* 2705 * Set the IP multicast options in response to user setsockopt(). 2706 * 2707 * Many of the socket options handled in this function duplicate the 2708 * functionality of socket options in the regular unicast API. However, 2709 * it is not possible to merge the duplicate code, because the idempotence 2710 * of the IPv6 multicast part of the BSD Sockets API must be preserved; 2711 * the effects of these options must be treated as separate and distinct. 2712 * 2713 * SMPng: XXX: Unlocked read of inp_socket believed OK. 2714 */ 2715 int 2716 ip6_setmoptions(struct inpcb *inp, struct sockopt *sopt) 2717 { 2718 struct ip6_moptions *im6o; 2719 int error; 2720 2721 error = 0; 2722 2723 /* 2724 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 2725 * or is a divert socket, reject it. 2726 */ 2727 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 2728 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 2729 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) 2730 return (EOPNOTSUPP); 2731 2732 switch (sopt->sopt_name) { 2733 case IPV6_MULTICAST_IF: 2734 error = in6p_set_multicast_if(inp, sopt); 2735 break; 2736 2737 case IPV6_MULTICAST_HOPS: { 2738 int hlim; 2739 2740 if (sopt->sopt_valsize != sizeof(int)) { 2741 error = EINVAL; 2742 break; 2743 } 2744 error = sooptcopyin(sopt, &hlim, sizeof(hlim), sizeof(int)); 2745 if (error) 2746 break; 2747 if (hlim < -1 || hlim > 255) { 2748 error = EINVAL; 2749 break; 2750 } else if (hlim == -1) { 2751 hlim = V_ip6_defmcasthlim; 2752 } 2753 im6o = in6p_findmoptions(inp); 2754 im6o->im6o_multicast_hlim = hlim; 2755 INP_WUNLOCK(inp); 2756 break; 2757 } 2758 2759 case IPV6_MULTICAST_LOOP: { 2760 u_int loop; 2761 2762 /* 2763 * Set the loopback flag for outgoing multicast packets. 2764 * Must be zero or one. 2765 */ 2766 if (sopt->sopt_valsize != sizeof(u_int)) { 2767 error = EINVAL; 2768 break; 2769 } 2770 error = sooptcopyin(sopt, &loop, sizeof(u_int), sizeof(u_int)); 2771 if (error) 2772 break; 2773 if (loop > 1) { 2774 error = EINVAL; 2775 break; 2776 } 2777 im6o = in6p_findmoptions(inp); 2778 im6o->im6o_multicast_loop = loop; 2779 INP_WUNLOCK(inp); 2780 break; 2781 } 2782 2783 case IPV6_JOIN_GROUP: 2784 case MCAST_JOIN_GROUP: 2785 case MCAST_JOIN_SOURCE_GROUP: 2786 error = in6p_join_group(inp, sopt); 2787 break; 2788 2789 case IPV6_LEAVE_GROUP: 2790 case MCAST_LEAVE_GROUP: 2791 case MCAST_LEAVE_SOURCE_GROUP: 2792 error = in6p_leave_group(inp, sopt); 2793 break; 2794 2795 case MCAST_BLOCK_SOURCE: 2796 case MCAST_UNBLOCK_SOURCE: 2797 error = in6p_block_unblock_source(inp, sopt); 2798 break; 2799 2800 case IPV6_MSFILTER: 2801 error = in6p_set_source_filters(inp, sopt); 2802 break; 2803 2804 default: 2805 error = EOPNOTSUPP; 2806 break; 2807 } 2808 2809 INP_UNLOCK_ASSERT(inp); 2810 2811 return (error); 2812 } 2813 2814 /* 2815 * Expose MLD's multicast filter mode and source list(s) to userland, 2816 * keyed by (ifindex, group). 2817 * The filter mode is written out as a uint32_t, followed by 2818 * 0..n of struct in6_addr. 2819 * For use by ifmcstat(8). 2820 * SMPng: NOTE: unlocked read of ifindex space. 2821 */ 2822 static int 2823 sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS) 2824 { 2825 struct in6_addr mcaddr; 2826 struct in6_addr src; 2827 struct epoch_tracker et; 2828 struct ifnet *ifp; 2829 struct ifmultiaddr *ifma; 2830 struct in6_multi *inm; 2831 struct ip6_msource *ims; 2832 int *name; 2833 int retval; 2834 u_int namelen; 2835 uint32_t fmode, ifindex; 2836 #ifdef KTR 2837 char ip6tbuf[INET6_ADDRSTRLEN]; 2838 #endif 2839 2840 name = (int *)arg1; 2841 namelen = arg2; 2842 2843 if (req->newptr != NULL) 2844 return (EPERM); 2845 2846 /* int: ifindex + 4 * 32 bits of IPv6 address */ 2847 if (namelen != 5) 2848 return (EINVAL); 2849 2850 ifindex = name[0]; 2851 if (ifindex <= 0 || ifindex > V_if_index) { 2852 CTR2(KTR_MLD, "%s: ifindex %u out of range", 2853 __func__, ifindex); 2854 return (ENOENT); 2855 } 2856 2857 memcpy(&mcaddr, &name[1], sizeof(struct in6_addr)); 2858 if (!IN6_IS_ADDR_MULTICAST(&mcaddr)) { 2859 CTR2(KTR_MLD, "%s: group %s is not multicast", 2860 __func__, ip6_sprintf(ip6tbuf, &mcaddr)); 2861 return (EINVAL); 2862 } 2863 2864 ifp = ifnet_byindex(ifindex); 2865 if (ifp == NULL) { 2866 CTR2(KTR_MLD, "%s: no ifp for ifindex %u", 2867 __func__, ifindex); 2868 return (ENOENT); 2869 } 2870 /* 2871 * Internal MLD lookups require that scope/zone ID is set. 2872 */ 2873 (void)in6_setscope(&mcaddr, ifp, NULL); 2874 2875 retval = sysctl_wire_old_buffer(req, 2876 sizeof(uint32_t) + (in6_mcast_maxgrpsrc * sizeof(struct in6_addr))); 2877 if (retval) 2878 return (retval); 2879 2880 IN6_MULTI_LOCK(); 2881 IN6_MULTI_LIST_LOCK(); 2882 NET_EPOCH_ENTER(et); 2883 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2884 inm = in6m_ifmultiaddr_get_inm(ifma); 2885 if (inm == NULL) 2886 continue; 2887 if (!IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, &mcaddr)) 2888 continue; 2889 fmode = inm->in6m_st[1].iss_fmode; 2890 retval = SYSCTL_OUT(req, &fmode, sizeof(uint32_t)); 2891 if (retval != 0) 2892 break; 2893 RB_FOREACH(ims, ip6_msource_tree, &inm->in6m_srcs) { 2894 CTR2(KTR_MLD, "%s: visit node %p", __func__, ims); 2895 /* 2896 * Only copy-out sources which are in-mode. 2897 */ 2898 if (fmode != im6s_get_mode(inm, ims, 1)) { 2899 CTR1(KTR_MLD, "%s: skip non-in-mode", 2900 __func__); 2901 continue; 2902 } 2903 src = ims->im6s_addr; 2904 retval = SYSCTL_OUT(req, &src, 2905 sizeof(struct in6_addr)); 2906 if (retval != 0) 2907 break; 2908 } 2909 } 2910 NET_EPOCH_EXIT(et); 2911 2912 IN6_MULTI_LIST_UNLOCK(); 2913 IN6_MULTI_UNLOCK(); 2914 2915 return (retval); 2916 } 2917 2918 #ifdef KTR 2919 2920 static const char *in6m_modestrs[] = { "un", "in", "ex" }; 2921 2922 static const char * 2923 in6m_mode_str(const int mode) 2924 { 2925 2926 if (mode >= MCAST_UNDEFINED && mode <= MCAST_EXCLUDE) 2927 return (in6m_modestrs[mode]); 2928 return ("??"); 2929 } 2930 2931 static const char *in6m_statestrs[] = { 2932 "not-member", 2933 "silent", 2934 "idle", 2935 "lazy", 2936 "sleeping", 2937 "awakening", 2938 "query-pending", 2939 "sg-query-pending", 2940 "leaving" 2941 }; 2942 2943 static const char * 2944 in6m_state_str(const int state) 2945 { 2946 2947 if (state >= MLD_NOT_MEMBER && state <= MLD_LEAVING_MEMBER) 2948 return (in6m_statestrs[state]); 2949 return ("??"); 2950 } 2951 2952 /* 2953 * Dump an in6_multi structure to the console. 2954 */ 2955 void 2956 in6m_print(const struct in6_multi *inm) 2957 { 2958 int t; 2959 char ip6tbuf[INET6_ADDRSTRLEN]; 2960 2961 if ((ktr_mask & KTR_MLD) == 0) 2962 return; 2963 2964 printf("%s: --- begin in6m %p ---\n", __func__, inm); 2965 printf("addr %s ifp %p(%s) ifma %p\n", 2966 ip6_sprintf(ip6tbuf, &inm->in6m_addr), 2967 inm->in6m_ifp, 2968 if_name(inm->in6m_ifp), 2969 inm->in6m_ifma); 2970 printf("timer %u state %s refcount %u scq.len %u\n", 2971 inm->in6m_timer, 2972 in6m_state_str(inm->in6m_state), 2973 inm->in6m_refcount, 2974 mbufq_len(&inm->in6m_scq)); 2975 printf("mli %p nsrc %lu sctimer %u scrv %u\n", 2976 inm->in6m_mli, 2977 inm->in6m_nsrc, 2978 inm->in6m_sctimer, 2979 inm->in6m_scrv); 2980 for (t = 0; t < 2; t++) { 2981 printf("t%d: fmode %s asm %u ex %u in %u rec %u\n", t, 2982 in6m_mode_str(inm->in6m_st[t].iss_fmode), 2983 inm->in6m_st[t].iss_asm, 2984 inm->in6m_st[t].iss_ex, 2985 inm->in6m_st[t].iss_in, 2986 inm->in6m_st[t].iss_rec); 2987 } 2988 printf("%s: --- end in6m %p ---\n", __func__, inm); 2989 } 2990 2991 #else /* !KTR */ 2992 2993 void 2994 in6m_print(const struct in6_multi *inm) 2995 { 2996 2997 } 2998 2999 #endif /* KTR */ 3000