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