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