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