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: releng/10.3/sys/netinet/in_mcast.c 261425 2014-02-03 03:31:35Z gnn $"); 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 /* Increment ASM listener count on transition to ASM mode. */ 1023 if (imf->imf_st[1] == MCAST_EXCLUDE && nsrc1 == 0) { 1024 CTR1(KTR_IGMPV3, "%s: asm++ on inm at t1", __func__); 1025 inm->inm_st[1].iss_asm++; 1026 } 1027 1028 CTR3(KTR_IGMPV3, "%s: merged imf %p to inm %p", __func__, imf, inm); 1029 inm_print(inm); 1030 1031out_reap: 1032 if (schanged > 0) { 1033 CTR1(KTR_IGMPV3, "%s: sources changed; reaping", __func__); 1034 inm_reap(inm); 1035 } 1036 return (error); 1037} 1038 1039/* 1040 * Mark an in_multi's filter set deltas as committed. 1041 * Called by IGMP after a state change has been enqueued. 1042 */ 1043void 1044inm_commit(struct in_multi *inm) 1045{ 1046 struct ip_msource *ims; 1047 1048 CTR2(KTR_IGMPV3, "%s: commit inm %p", __func__, inm); 1049 CTR1(KTR_IGMPV3, "%s: pre commit:", __func__); 1050 inm_print(inm); 1051 1052 RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) { 1053 ims->ims_st[0] = ims->ims_st[1]; 1054 } 1055 inm->inm_st[0] = inm->inm_st[1]; 1056} 1057 1058/* 1059 * Reap unreferenced nodes from an in_multi's filter set. 1060 */ 1061static void 1062inm_reap(struct in_multi *inm) 1063{ 1064 struct ip_msource *ims, *tims; 1065 1066 RB_FOREACH_SAFE(ims, ip_msource_tree, &inm->inm_srcs, tims) { 1067 if (ims->ims_st[0].ex > 0 || ims->ims_st[0].in > 0 || 1068 ims->ims_st[1].ex > 0 || ims->ims_st[1].in > 0 || 1069 ims->ims_stp != 0) 1070 continue; 1071 CTR2(KTR_IGMPV3, "%s: free ims %p", __func__, ims); 1072 RB_REMOVE(ip_msource_tree, &inm->inm_srcs, ims); 1073 free(ims, M_IPMSOURCE); 1074 inm->inm_nsrc--; 1075 } 1076} 1077 1078/* 1079 * Purge all source nodes from an in_multi's filter set. 1080 */ 1081static void 1082inm_purge(struct in_multi *inm) 1083{ 1084 struct ip_msource *ims, *tims; 1085 1086 RB_FOREACH_SAFE(ims, ip_msource_tree, &inm->inm_srcs, tims) { 1087 CTR2(KTR_IGMPV3, "%s: free ims %p", __func__, ims); 1088 RB_REMOVE(ip_msource_tree, &inm->inm_srcs, ims); 1089 free(ims, M_IPMSOURCE); 1090 inm->inm_nsrc--; 1091 } 1092} 1093 1094/* 1095 * Join a multicast group; unlocked entry point. 1096 * 1097 * SMPng: XXX: in_joingroup() is called from in_control() when Giant 1098 * is not held. Fortunately, ifp is unlikely to have been detached 1099 * at this point, so we assume it's OK to recurse. 1100 */ 1101int 1102in_joingroup(struct ifnet *ifp, const struct in_addr *gina, 1103 /*const*/ struct in_mfilter *imf, struct in_multi **pinm) 1104{ 1105 int error; 1106 1107 IN_MULTI_LOCK(); 1108 error = in_joingroup_locked(ifp, gina, imf, pinm); 1109 IN_MULTI_UNLOCK(); 1110 1111 return (error); 1112} 1113 1114/* 1115 * Join a multicast group; real entry point. 1116 * 1117 * Only preserves atomicity at inm level. 1118 * NOTE: imf argument cannot be const due to sys/tree.h limitations. 1119 * 1120 * If the IGMP downcall fails, the group is not joined, and an error 1121 * code is returned. 1122 */ 1123int 1124in_joingroup_locked(struct ifnet *ifp, const struct in_addr *gina, 1125 /*const*/ struct in_mfilter *imf, struct in_multi **pinm) 1126{ 1127 struct in_mfilter timf; 1128 struct in_multi *inm; 1129 int error; 1130 1131 IN_MULTI_LOCK_ASSERT(); 1132 1133 CTR4(KTR_IGMPV3, "%s: join %s on %p(%s))", __func__, 1134 inet_ntoa(*gina), ifp, ifp->if_xname); 1135 1136 error = 0; 1137 inm = NULL; 1138 1139 /* 1140 * If no imf was specified (i.e. kernel consumer), 1141 * fake one up and assume it is an ASM join. 1142 */ 1143 if (imf == NULL) { 1144 imf_init(&timf, MCAST_UNDEFINED, MCAST_EXCLUDE); 1145 imf = &timf; 1146 } 1147 1148 error = in_getmulti(ifp, gina, &inm); 1149 if (error) { 1150 CTR1(KTR_IGMPV3, "%s: in_getmulti() failure", __func__); 1151 return (error); 1152 } 1153 1154 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 1155 error = inm_merge(inm, imf); 1156 if (error) { 1157 CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); 1158 goto out_inm_release; 1159 } 1160 1161 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 1162 error = igmp_change_state(inm); 1163 if (error) { 1164 CTR1(KTR_IGMPV3, "%s: failed to update source", __func__); 1165 goto out_inm_release; 1166 } 1167 1168out_inm_release: 1169 if (error) { 1170 CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, inm); 1171 inm_release_locked(inm); 1172 } else { 1173 *pinm = inm; 1174 } 1175 1176 return (error); 1177} 1178 1179/* 1180 * Leave a multicast group; unlocked entry point. 1181 */ 1182int 1183in_leavegroup(struct in_multi *inm, /*const*/ struct in_mfilter *imf) 1184{ 1185 int error; 1186 1187 IN_MULTI_LOCK(); 1188 error = in_leavegroup_locked(inm, imf); 1189 IN_MULTI_UNLOCK(); 1190 1191 return (error); 1192} 1193 1194/* 1195 * Leave a multicast group; real entry point. 1196 * All source filters will be expunged. 1197 * 1198 * Only preserves atomicity at inm level. 1199 * 1200 * Holding the write lock for the INP which contains imf 1201 * is highly advisable. We can't assert for it as imf does not 1202 * contain a back-pointer to the owning inp. 1203 * 1204 * Note: This is not the same as inm_release(*) as this function also 1205 * makes a state change downcall into IGMP. 1206 */ 1207int 1208in_leavegroup_locked(struct in_multi *inm, /*const*/ struct in_mfilter *imf) 1209{ 1210 struct in_mfilter timf; 1211 int error; 1212 1213 error = 0; 1214 1215 IN_MULTI_LOCK_ASSERT(); 1216 1217 CTR5(KTR_IGMPV3, "%s: leave inm %p, %s/%s, imf %p", __func__, 1218 inm, inet_ntoa(inm->inm_addr), 1219 (inm_is_ifp_detached(inm) ? "null" : inm->inm_ifp->if_xname), 1220 imf); 1221 1222 /* 1223 * If no imf was specified (i.e. kernel consumer), 1224 * fake one up and assume it is an ASM join. 1225 */ 1226 if (imf == NULL) { 1227 imf_init(&timf, MCAST_EXCLUDE, MCAST_UNDEFINED); 1228 imf = &timf; 1229 } 1230 1231 /* 1232 * Begin state merge transaction at IGMP layer. 1233 * 1234 * As this particular invocation should not cause any memory 1235 * to be allocated, and there is no opportunity to roll back 1236 * the transaction, it MUST NOT fail. 1237 */ 1238 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 1239 error = inm_merge(inm, imf); 1240 KASSERT(error == 0, ("%s: failed to merge inm state", __func__)); 1241 1242 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 1243 CURVNET_SET(inm->inm_ifp->if_vnet); 1244 error = igmp_change_state(inm); 1245 CURVNET_RESTORE(); 1246 if (error) 1247 CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); 1248 1249 CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, inm); 1250 inm_release_locked(inm); 1251 1252 return (error); 1253} 1254 1255/*#ifndef BURN_BRIDGES*/ 1256/* 1257 * Join an IPv4 multicast group in (*,G) exclusive mode. 1258 * The group must be a 224.0.0.0/24 link-scope group. 1259 * This KPI is for legacy kernel consumers only. 1260 */ 1261struct in_multi * 1262in_addmulti(struct in_addr *ap, struct ifnet *ifp) 1263{ 1264 struct in_multi *pinm; 1265 int error; 1266 1267 KASSERT(IN_LOCAL_GROUP(ntohl(ap->s_addr)), 1268 ("%s: %s not in 224.0.0.0/24", __func__, inet_ntoa(*ap))); 1269 1270 error = in_joingroup(ifp, ap, NULL, &pinm); 1271 if (error != 0) 1272 pinm = NULL; 1273 1274 return (pinm); 1275} 1276 1277/* 1278 * Leave an IPv4 multicast group, assumed to be in exclusive (*,G) mode. 1279 * This KPI is for legacy kernel consumers only. 1280 */ 1281void 1282in_delmulti(struct in_multi *inm) 1283{ 1284 1285 (void)in_leavegroup(inm, NULL); 1286} 1287/*#endif*/ 1288 1289/* 1290 * Block or unblock an ASM multicast source on an inpcb. 1291 * This implements the delta-based API described in RFC 3678. 1292 * 1293 * The delta-based API applies only to exclusive-mode memberships. 1294 * An IGMP downcall will be performed. 1295 * 1296 * SMPng: NOTE: Must take Giant as a join may create a new ifma. 1297 * 1298 * Return 0 if successful, otherwise return an appropriate error code. 1299 */ 1300static int 1301inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) 1302{ 1303 struct group_source_req gsr; 1304 sockunion_t *gsa, *ssa; 1305 struct ifnet *ifp; 1306 struct in_mfilter *imf; 1307 struct ip_moptions *imo; 1308 struct in_msource *ims; 1309 struct in_multi *inm; 1310 size_t idx; 1311 uint16_t fmode; 1312 int error, doblock; 1313 1314 ifp = NULL; 1315 error = 0; 1316 doblock = 0; 1317 1318 memset(&gsr, 0, sizeof(struct group_source_req)); 1319 gsa = (sockunion_t *)&gsr.gsr_group; 1320 ssa = (sockunion_t *)&gsr.gsr_source; 1321 1322 switch (sopt->sopt_name) { 1323 case IP_BLOCK_SOURCE: 1324 case IP_UNBLOCK_SOURCE: { 1325 struct ip_mreq_source mreqs; 1326 1327 error = sooptcopyin(sopt, &mreqs, 1328 sizeof(struct ip_mreq_source), 1329 sizeof(struct ip_mreq_source)); 1330 if (error) 1331 return (error); 1332 1333 gsa->sin.sin_family = AF_INET; 1334 gsa->sin.sin_len = sizeof(struct sockaddr_in); 1335 gsa->sin.sin_addr = mreqs.imr_multiaddr; 1336 1337 ssa->sin.sin_family = AF_INET; 1338 ssa->sin.sin_len = sizeof(struct sockaddr_in); 1339 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 1340 1341 if (!in_nullhost(mreqs.imr_interface)) 1342 INADDR_TO_IFP(mreqs.imr_interface, ifp); 1343 1344 if (sopt->sopt_name == IP_BLOCK_SOURCE) 1345 doblock = 1; 1346 1347 CTR3(KTR_IGMPV3, "%s: imr_interface = %s, ifp = %p", 1348 __func__, inet_ntoa(mreqs.imr_interface), ifp); 1349 break; 1350 } 1351 1352 case MCAST_BLOCK_SOURCE: 1353 case MCAST_UNBLOCK_SOURCE: 1354 error = sooptcopyin(sopt, &gsr, 1355 sizeof(struct group_source_req), 1356 sizeof(struct group_source_req)); 1357 if (error) 1358 return (error); 1359 1360 if (gsa->sin.sin_family != AF_INET || 1361 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 1362 return (EINVAL); 1363 1364 if (ssa->sin.sin_family != AF_INET || 1365 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 1366 return (EINVAL); 1367 1368 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 1369 return (EADDRNOTAVAIL); 1370 1371 ifp = ifnet_byindex(gsr.gsr_interface); 1372 1373 if (sopt->sopt_name == MCAST_BLOCK_SOURCE) 1374 doblock = 1; 1375 break; 1376 1377 default: 1378 CTR2(KTR_IGMPV3, "%s: unknown sopt_name %d", 1379 __func__, sopt->sopt_name); 1380 return (EOPNOTSUPP); 1381 break; 1382 } 1383 1384 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1385 return (EINVAL); 1386 1387 /* 1388 * Check if we are actually a member of this group. 1389 */ 1390 imo = inp_findmoptions(inp); 1391 idx = imo_match_group(imo, ifp, &gsa->sa); 1392 if (idx == -1 || imo->imo_mfilters == NULL) { 1393 error = EADDRNOTAVAIL; 1394 goto out_inp_locked; 1395 } 1396 1397 KASSERT(imo->imo_mfilters != NULL, 1398 ("%s: imo_mfilters not allocated", __func__)); 1399 imf = &imo->imo_mfilters[idx]; 1400 inm = imo->imo_membership[idx]; 1401 1402 /* 1403 * Attempting to use the delta-based API on an 1404 * non exclusive-mode membership is an error. 1405 */ 1406 fmode = imf->imf_st[0]; 1407 if (fmode != MCAST_EXCLUDE) { 1408 error = EINVAL; 1409 goto out_inp_locked; 1410 } 1411 1412 /* 1413 * Deal with error cases up-front: 1414 * Asked to block, but already blocked; or 1415 * Asked to unblock, but nothing to unblock. 1416 * If adding a new block entry, allocate it. 1417 */ 1418 ims = imo_match_source(imo, idx, &ssa->sa); 1419 if ((ims != NULL && doblock) || (ims == NULL && !doblock)) { 1420 CTR3(KTR_IGMPV3, "%s: source %s %spresent", __func__, 1421 inet_ntoa(ssa->sin.sin_addr), doblock ? "" : "not "); 1422 error = EADDRNOTAVAIL; 1423 goto out_inp_locked; 1424 } 1425 1426 INP_WLOCK_ASSERT(inp); 1427 1428 /* 1429 * Begin state merge transaction at socket layer. 1430 */ 1431 if (doblock) { 1432 CTR2(KTR_IGMPV3, "%s: %s source", __func__, "block"); 1433 ims = imf_graft(imf, fmode, &ssa->sin); 1434 if (ims == NULL) 1435 error = ENOMEM; 1436 } else { 1437 CTR2(KTR_IGMPV3, "%s: %s source", __func__, "allow"); 1438 error = imf_prune(imf, &ssa->sin); 1439 } 1440 1441 if (error) { 1442 CTR1(KTR_IGMPV3, "%s: merge imf state failed", __func__); 1443 goto out_imf_rollback; 1444 } 1445 1446 /* 1447 * Begin state merge transaction at IGMP layer. 1448 */ 1449 IN_MULTI_LOCK(); 1450 1451 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 1452 error = inm_merge(inm, imf); 1453 if (error) { 1454 CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); 1455 goto out_in_multi_locked; 1456 } 1457 1458 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 1459 error = igmp_change_state(inm); 1460 if (error) 1461 CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); 1462 1463out_in_multi_locked: 1464 1465 IN_MULTI_UNLOCK(); 1466 1467out_imf_rollback: 1468 if (error) 1469 imf_rollback(imf); 1470 else 1471 imf_commit(imf); 1472 1473 imf_reap(imf); 1474 1475out_inp_locked: 1476 INP_WUNLOCK(inp); 1477 return (error); 1478} 1479 1480/* 1481 * Given an inpcb, return its multicast options structure pointer. Accepts 1482 * an unlocked inpcb pointer, but will return it locked. May sleep. 1483 * 1484 * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held. 1485 * SMPng: NOTE: Returns with the INP write lock held. 1486 */ 1487static struct ip_moptions * 1488inp_findmoptions(struct inpcb *inp) 1489{ 1490 struct ip_moptions *imo; 1491 struct in_multi **immp; 1492 struct in_mfilter *imfp; 1493 size_t idx; 1494 1495 INP_WLOCK(inp); 1496 if (inp->inp_moptions != NULL) 1497 return (inp->inp_moptions); 1498 1499 INP_WUNLOCK(inp); 1500 1501 imo = malloc(sizeof(*imo), M_IPMOPTS, M_WAITOK); 1502 immp = malloc(sizeof(*immp) * IP_MIN_MEMBERSHIPS, M_IPMOPTS, 1503 M_WAITOK | M_ZERO); 1504 imfp = malloc(sizeof(struct in_mfilter) * IP_MIN_MEMBERSHIPS, 1505 M_INMFILTER, M_WAITOK); 1506 1507 imo->imo_multicast_ifp = NULL; 1508 imo->imo_multicast_addr.s_addr = INADDR_ANY; 1509 imo->imo_multicast_vif = -1; 1510 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; 1511 imo->imo_multicast_loop = in_mcast_loop; 1512 imo->imo_num_memberships = 0; 1513 imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; 1514 imo->imo_membership = immp; 1515 1516 /* Initialize per-group source filters. */ 1517 for (idx = 0; idx < IP_MIN_MEMBERSHIPS; idx++) 1518 imf_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE); 1519 imo->imo_mfilters = imfp; 1520 1521 INP_WLOCK(inp); 1522 if (inp->inp_moptions != NULL) { 1523 free(imfp, M_INMFILTER); 1524 free(immp, M_IPMOPTS); 1525 free(imo, M_IPMOPTS); 1526 return (inp->inp_moptions); 1527 } 1528 inp->inp_moptions = imo; 1529 return (imo); 1530} 1531 1532/* 1533 * Discard the IP multicast options (and source filters). To minimize 1534 * the amount of work done while holding locks such as the INP's 1535 * pcbinfo lock (which is used in the receive path), the free 1536 * operation is performed asynchronously in a separate task. 1537 * 1538 * SMPng: NOTE: assumes INP write lock is held. 1539 */ 1540void 1541inp_freemoptions(struct ip_moptions *imo) 1542{ 1543 1544 KASSERT(imo != NULL, ("%s: ip_moptions is NULL", __func__)); 1545 IN_MULTI_LOCK(); 1546 STAILQ_INSERT_TAIL(&imo_gc_list, imo, imo_link); 1547 IN_MULTI_UNLOCK(); 1548 taskqueue_enqueue(taskqueue_thread, &imo_gc_task); 1549} 1550 1551static void 1552inp_freemoptions_internal(struct ip_moptions *imo) 1553{ 1554 struct in_mfilter *imf; 1555 size_t idx, nmships; 1556 1557 nmships = imo->imo_num_memberships; 1558 for (idx = 0; idx < nmships; ++idx) { 1559 imf = imo->imo_mfilters ? &imo->imo_mfilters[idx] : NULL; 1560 if (imf) 1561 imf_leave(imf); 1562 (void)in_leavegroup(imo->imo_membership[idx], imf); 1563 if (imf) 1564 imf_purge(imf); 1565 } 1566 1567 if (imo->imo_mfilters) 1568 free(imo->imo_mfilters, M_INMFILTER); 1569 free(imo->imo_membership, M_IPMOPTS); 1570 free(imo, M_IPMOPTS); 1571} 1572 1573static void 1574inp_gcmoptions(void *context, int pending) 1575{ 1576 struct ip_moptions *imo; 1577 1578 IN_MULTI_LOCK(); 1579 while (!STAILQ_EMPTY(&imo_gc_list)) { 1580 imo = STAILQ_FIRST(&imo_gc_list); 1581 STAILQ_REMOVE_HEAD(&imo_gc_list, imo_link); 1582 IN_MULTI_UNLOCK(); 1583 inp_freemoptions_internal(imo); 1584 IN_MULTI_LOCK(); 1585 } 1586 IN_MULTI_UNLOCK(); 1587} 1588 1589/* 1590 * Atomically get source filters on a socket for an IPv4 multicast group. 1591 * Called with INP lock held; returns with lock released. 1592 */ 1593static int 1594inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt) 1595{ 1596 struct __msfilterreq msfr; 1597 sockunion_t *gsa; 1598 struct ifnet *ifp; 1599 struct ip_moptions *imo; 1600 struct in_mfilter *imf; 1601 struct ip_msource *ims; 1602 struct in_msource *lims; 1603 struct sockaddr_in *psin; 1604 struct sockaddr_storage *ptss; 1605 struct sockaddr_storage *tss; 1606 int error; 1607 size_t idx, nsrcs, ncsrcs; 1608 1609 INP_WLOCK_ASSERT(inp); 1610 1611 imo = inp->inp_moptions; 1612 KASSERT(imo != NULL, ("%s: null ip_moptions", __func__)); 1613 1614 INP_WUNLOCK(inp); 1615 1616 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 1617 sizeof(struct __msfilterreq)); 1618 if (error) 1619 return (error); 1620 1621 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 1622 return (EINVAL); 1623 1624 ifp = ifnet_byindex(msfr.msfr_ifindex); 1625 if (ifp == NULL) 1626 return (EINVAL); 1627 1628 INP_WLOCK(inp); 1629 1630 /* 1631 * Lookup group on the socket. 1632 */ 1633 gsa = (sockunion_t *)&msfr.msfr_group; 1634 idx = imo_match_group(imo, ifp, &gsa->sa); 1635 if (idx == -1 || imo->imo_mfilters == NULL) { 1636 INP_WUNLOCK(inp); 1637 return (EADDRNOTAVAIL); 1638 } 1639 imf = &imo->imo_mfilters[idx]; 1640 1641 /* 1642 * Ignore memberships which are in limbo. 1643 */ 1644 if (imf->imf_st[1] == MCAST_UNDEFINED) { 1645 INP_WUNLOCK(inp); 1646 return (EAGAIN); 1647 } 1648 msfr.msfr_fmode = imf->imf_st[1]; 1649 1650 /* 1651 * If the user specified a buffer, copy out the source filter 1652 * entries to userland gracefully. 1653 * We only copy out the number of entries which userland 1654 * has asked for, but we always tell userland how big the 1655 * buffer really needs to be. 1656 */ 1657 if (msfr.msfr_nsrcs > in_mcast_maxsocksrc) 1658 msfr.msfr_nsrcs = in_mcast_maxsocksrc; 1659 tss = NULL; 1660 if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) { 1661 tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 1662 M_TEMP, M_NOWAIT | M_ZERO); 1663 if (tss == NULL) { 1664 INP_WUNLOCK(inp); 1665 return (ENOBUFS); 1666 } 1667 } 1668 1669 /* 1670 * Count number of sources in-mode at t0. 1671 * If buffer space exists and remains, copy out source entries. 1672 */ 1673 nsrcs = msfr.msfr_nsrcs; 1674 ncsrcs = 0; 1675 ptss = tss; 1676 RB_FOREACH(ims, ip_msource_tree, &imf->imf_sources) { 1677 lims = (struct in_msource *)ims; 1678 if (lims->imsl_st[0] == MCAST_UNDEFINED || 1679 lims->imsl_st[0] != imf->imf_st[0]) 1680 continue; 1681 ++ncsrcs; 1682 if (tss != NULL && nsrcs > 0) { 1683 psin = (struct sockaddr_in *)ptss; 1684 psin->sin_family = AF_INET; 1685 psin->sin_len = sizeof(struct sockaddr_in); 1686 psin->sin_addr.s_addr = htonl(lims->ims_haddr); 1687 psin->sin_port = 0; 1688 ++ptss; 1689 --nsrcs; 1690 } 1691 } 1692 1693 INP_WUNLOCK(inp); 1694 1695 if (tss != NULL) { 1696 error = copyout(tss, msfr.msfr_srcs, 1697 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 1698 free(tss, M_TEMP); 1699 if (error) 1700 return (error); 1701 } 1702 1703 msfr.msfr_nsrcs = ncsrcs; 1704 error = sooptcopyout(sopt, &msfr, sizeof(struct __msfilterreq)); 1705 1706 return (error); 1707} 1708 1709/* 1710 * Return the IP multicast options in response to user getsockopt(). 1711 */ 1712int 1713inp_getmoptions(struct inpcb *inp, struct sockopt *sopt) 1714{ 1715 struct ip_mreqn mreqn; 1716 struct ip_moptions *imo; 1717 struct ifnet *ifp; 1718 struct in_ifaddr *ia; 1719 int error, optval; 1720 u_char coptval; 1721 1722 INP_WLOCK(inp); 1723 imo = inp->inp_moptions; 1724 /* 1725 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 1726 * or is a divert socket, reject it. 1727 */ 1728 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 1729 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 1730 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) { 1731 INP_WUNLOCK(inp); 1732 return (EOPNOTSUPP); 1733 } 1734 1735 error = 0; 1736 switch (sopt->sopt_name) { 1737 case IP_MULTICAST_VIF: 1738 if (imo != NULL) 1739 optval = imo->imo_multicast_vif; 1740 else 1741 optval = -1; 1742 INP_WUNLOCK(inp); 1743 error = sooptcopyout(sopt, &optval, sizeof(int)); 1744 break; 1745 1746 case IP_MULTICAST_IF: 1747 memset(&mreqn, 0, sizeof(struct ip_mreqn)); 1748 if (imo != NULL) { 1749 ifp = imo->imo_multicast_ifp; 1750 if (!in_nullhost(imo->imo_multicast_addr)) { 1751 mreqn.imr_address = imo->imo_multicast_addr; 1752 } else if (ifp != NULL) { 1753 mreqn.imr_ifindex = ifp->if_index; 1754 IFP_TO_IA(ifp, ia); 1755 if (ia != NULL) { 1756 mreqn.imr_address = 1757 IA_SIN(ia)->sin_addr; 1758 ifa_free(&ia->ia_ifa); 1759 } 1760 } 1761 } 1762 INP_WUNLOCK(inp); 1763 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) { 1764 error = sooptcopyout(sopt, &mreqn, 1765 sizeof(struct ip_mreqn)); 1766 } else { 1767 error = sooptcopyout(sopt, &mreqn.imr_address, 1768 sizeof(struct in_addr)); 1769 } 1770 break; 1771 1772 case IP_MULTICAST_TTL: 1773 if (imo == 0) 1774 optval = coptval = IP_DEFAULT_MULTICAST_TTL; 1775 else 1776 optval = coptval = imo->imo_multicast_ttl; 1777 INP_WUNLOCK(inp); 1778 if (sopt->sopt_valsize == sizeof(u_char)) 1779 error = sooptcopyout(sopt, &coptval, sizeof(u_char)); 1780 else 1781 error = sooptcopyout(sopt, &optval, sizeof(int)); 1782 break; 1783 1784 case IP_MULTICAST_LOOP: 1785 if (imo == 0) 1786 optval = coptval = IP_DEFAULT_MULTICAST_LOOP; 1787 else 1788 optval = coptval = imo->imo_multicast_loop; 1789 INP_WUNLOCK(inp); 1790 if (sopt->sopt_valsize == sizeof(u_char)) 1791 error = sooptcopyout(sopt, &coptval, sizeof(u_char)); 1792 else 1793 error = sooptcopyout(sopt, &optval, sizeof(int)); 1794 break; 1795 1796 case IP_MSFILTER: 1797 if (imo == NULL) { 1798 error = EADDRNOTAVAIL; 1799 INP_WUNLOCK(inp); 1800 } else { 1801 error = inp_get_source_filters(inp, sopt); 1802 } 1803 break; 1804 1805 default: 1806 INP_WUNLOCK(inp); 1807 error = ENOPROTOOPT; 1808 break; 1809 } 1810 1811 INP_UNLOCK_ASSERT(inp); 1812 1813 return (error); 1814} 1815 1816/* 1817 * Look up the ifnet to use for a multicast group membership, 1818 * given the IPv4 address of an interface, and the IPv4 group address. 1819 * 1820 * This routine exists to support legacy multicast applications 1821 * which do not understand that multicast memberships are scoped to 1822 * specific physical links in the networking stack, or which need 1823 * to join link-scope groups before IPv4 addresses are configured. 1824 * 1825 * If inp is non-NULL, use this socket's current FIB number for any 1826 * required FIB lookup. 1827 * If ina is INADDR_ANY, look up the group address in the unicast FIB, 1828 * and use its ifp; usually, this points to the default next-hop. 1829 * 1830 * If the FIB lookup fails, attempt to use the first non-loopback 1831 * interface with multicast capability in the system as a 1832 * last resort. The legacy IPv4 ASM API requires that we do 1833 * this in order to allow groups to be joined when the routing 1834 * table has not yet been populated during boot. 1835 * 1836 * Returns NULL if no ifp could be found. 1837 * 1838 * SMPng: TODO: Acquire the appropriate locks for INADDR_TO_IFP. 1839 * FUTURE: Implement IPv4 source-address selection. 1840 */ 1841static struct ifnet * 1842inp_lookup_mcast_ifp(const struct inpcb *inp, 1843 const struct sockaddr_in *gsin, const struct in_addr ina) 1844{ 1845 struct ifnet *ifp; 1846 1847 KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__)); 1848 KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)), 1849 ("%s: not multicast", __func__)); 1850 1851 ifp = NULL; 1852 if (!in_nullhost(ina)) { 1853 INADDR_TO_IFP(ina, ifp); 1854 } else { 1855 struct route ro; 1856 1857 ro.ro_rt = NULL; 1858 memcpy(&ro.ro_dst, gsin, sizeof(struct sockaddr_in)); 1859 in_rtalloc_ign(&ro, 0, inp ? inp->inp_inc.inc_fibnum : 0); 1860 if (ro.ro_rt != NULL) { 1861 ifp = ro.ro_rt->rt_ifp; 1862 KASSERT(ifp != NULL, ("%s: null ifp", __func__)); 1863 RTFREE(ro.ro_rt); 1864 } else { 1865 struct in_ifaddr *ia; 1866 struct ifnet *mifp; 1867 1868 mifp = NULL; 1869 IN_IFADDR_RLOCK(); 1870 TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { 1871 mifp = ia->ia_ifp; 1872 if (!(mifp->if_flags & IFF_LOOPBACK) && 1873 (mifp->if_flags & IFF_MULTICAST)) { 1874 ifp = mifp; 1875 break; 1876 } 1877 } 1878 IN_IFADDR_RUNLOCK(); 1879 } 1880 } 1881 1882 return (ifp); 1883} 1884 1885/* 1886 * Join an IPv4 multicast group, possibly with a source. 1887 */ 1888static int 1889inp_join_group(struct inpcb *inp, struct sockopt *sopt) 1890{ 1891 struct group_source_req gsr; 1892 sockunion_t *gsa, *ssa; 1893 struct ifnet *ifp; 1894 struct in_mfilter *imf; 1895 struct ip_moptions *imo; 1896 struct in_multi *inm; 1897 struct in_msource *lims; 1898 size_t idx; 1899 int error, is_new; 1900 1901 ifp = NULL; 1902 imf = NULL; 1903 lims = NULL; 1904 error = 0; 1905 is_new = 0; 1906 1907 memset(&gsr, 0, sizeof(struct group_source_req)); 1908 gsa = (sockunion_t *)&gsr.gsr_group; 1909 gsa->ss.ss_family = AF_UNSPEC; 1910 ssa = (sockunion_t *)&gsr.gsr_source; 1911 ssa->ss.ss_family = AF_UNSPEC; 1912 1913 switch (sopt->sopt_name) { 1914 case IP_ADD_MEMBERSHIP: 1915 case IP_ADD_SOURCE_MEMBERSHIP: { 1916 struct ip_mreq_source mreqs; 1917 1918 if (sopt->sopt_name == IP_ADD_MEMBERSHIP) { 1919 error = sooptcopyin(sopt, &mreqs, 1920 sizeof(struct ip_mreq), 1921 sizeof(struct ip_mreq)); 1922 /* 1923 * Do argument switcharoo from ip_mreq into 1924 * ip_mreq_source to avoid using two instances. 1925 */ 1926 mreqs.imr_interface = mreqs.imr_sourceaddr; 1927 mreqs.imr_sourceaddr.s_addr = INADDR_ANY; 1928 } else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { 1929 error = sooptcopyin(sopt, &mreqs, 1930 sizeof(struct ip_mreq_source), 1931 sizeof(struct ip_mreq_source)); 1932 } 1933 if (error) 1934 return (error); 1935 1936 gsa->sin.sin_family = AF_INET; 1937 gsa->sin.sin_len = sizeof(struct sockaddr_in); 1938 gsa->sin.sin_addr = mreqs.imr_multiaddr; 1939 1940 if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { 1941 ssa->sin.sin_family = AF_INET; 1942 ssa->sin.sin_len = sizeof(struct sockaddr_in); 1943 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 1944 } 1945 1946 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1947 return (EINVAL); 1948 1949 ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, 1950 mreqs.imr_interface); 1951 CTR3(KTR_IGMPV3, "%s: imr_interface = %s, ifp = %p", 1952 __func__, inet_ntoa(mreqs.imr_interface), ifp); 1953 break; 1954 } 1955 1956 case MCAST_JOIN_GROUP: 1957 case MCAST_JOIN_SOURCE_GROUP: 1958 if (sopt->sopt_name == MCAST_JOIN_GROUP) { 1959 error = sooptcopyin(sopt, &gsr, 1960 sizeof(struct group_req), 1961 sizeof(struct group_req)); 1962 } else if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 1963 error = sooptcopyin(sopt, &gsr, 1964 sizeof(struct group_source_req), 1965 sizeof(struct group_source_req)); 1966 } 1967 if (error) 1968 return (error); 1969 1970 if (gsa->sin.sin_family != AF_INET || 1971 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 1972 return (EINVAL); 1973 1974 /* 1975 * Overwrite the port field if present, as the sockaddr 1976 * being copied in may be matched with a binary comparison. 1977 */ 1978 gsa->sin.sin_port = 0; 1979 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 1980 if (ssa->sin.sin_family != AF_INET || 1981 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 1982 return (EINVAL); 1983 ssa->sin.sin_port = 0; 1984 } 1985 1986 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1987 return (EINVAL); 1988 1989 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 1990 return (EADDRNOTAVAIL); 1991 ifp = ifnet_byindex(gsr.gsr_interface); 1992 break; 1993 1994 default: 1995 CTR2(KTR_IGMPV3, "%s: unknown sopt_name %d", 1996 __func__, sopt->sopt_name); 1997 return (EOPNOTSUPP); 1998 break; 1999 } 2000 2001 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) 2002 return (EADDRNOTAVAIL); 2003 2004 imo = inp_findmoptions(inp); 2005 idx = imo_match_group(imo, ifp, &gsa->sa); 2006 if (idx == -1) { 2007 is_new = 1; 2008 } else { 2009 inm = imo->imo_membership[idx]; 2010 imf = &imo->imo_mfilters[idx]; 2011 if (ssa->ss.ss_family != AF_UNSPEC) { 2012 /* 2013 * MCAST_JOIN_SOURCE_GROUP on an exclusive membership 2014 * is an error. On an existing inclusive membership, 2015 * it just adds the source to the filter list. 2016 */ 2017 if (imf->imf_st[1] != MCAST_INCLUDE) { 2018 error = EINVAL; 2019 goto out_inp_locked; 2020 } 2021 /* 2022 * Throw out duplicates. 2023 * 2024 * XXX FIXME: This makes a naive assumption that 2025 * even if entries exist for *ssa in this imf, 2026 * they will be rejected as dupes, even if they 2027 * are not valid in the current mode (in-mode). 2028 * 2029 * in_msource is transactioned just as for anything 2030 * else in SSM -- but note naive use of inm_graft() 2031 * below for allocating new filter entries. 2032 * 2033 * This is only an issue if someone mixes the 2034 * full-state SSM API with the delta-based API, 2035 * which is discouraged in the relevant RFCs. 2036 */ 2037 lims = imo_match_source(imo, idx, &ssa->sa); 2038 if (lims != NULL /*&& 2039 lims->imsl_st[1] == MCAST_INCLUDE*/) { 2040 error = EADDRNOTAVAIL; 2041 goto out_inp_locked; 2042 } 2043 } else { 2044 /* 2045 * MCAST_JOIN_GROUP on an existing exclusive 2046 * membership is an error; return EADDRINUSE 2047 * to preserve 4.4BSD API idempotence, and 2048 * avoid tedious detour to code below. 2049 * NOTE: This is bending RFC 3678 a bit. 2050 * 2051 * On an existing inclusive membership, this is also 2052 * an error; if you want to change filter mode, 2053 * you must use the userland API setsourcefilter(). 2054 * XXX We don't reject this for imf in UNDEFINED 2055 * state at t1, because allocation of a filter 2056 * is atomic with allocation of a membership. 2057 */ 2058 error = EINVAL; 2059 if (imf->imf_st[1] == MCAST_EXCLUDE) 2060 error = EADDRINUSE; 2061 goto out_inp_locked; 2062 } 2063 } 2064 2065 /* 2066 * Begin state merge transaction at socket layer. 2067 */ 2068 INP_WLOCK_ASSERT(inp); 2069 2070 if (is_new) { 2071 if (imo->imo_num_memberships == imo->imo_max_memberships) { 2072 error = imo_grow(imo); 2073 if (error) 2074 goto out_inp_locked; 2075 } 2076 /* 2077 * Allocate the new slot upfront so we can deal with 2078 * grafting the new source filter in same code path 2079 * as for join-source on existing membership. 2080 */ 2081 idx = imo->imo_num_memberships; 2082 imo->imo_membership[idx] = NULL; 2083 imo->imo_num_memberships++; 2084 KASSERT(imo->imo_mfilters != NULL, 2085 ("%s: imf_mfilters vector was not allocated", __func__)); 2086 imf = &imo->imo_mfilters[idx]; 2087 KASSERT(RB_EMPTY(&imf->imf_sources), 2088 ("%s: imf_sources not empty", __func__)); 2089 } 2090 2091 /* 2092 * Graft new source into filter list for this inpcb's 2093 * membership of the group. The in_multi may not have 2094 * been allocated yet if this is a new membership, however, 2095 * the in_mfilter slot will be allocated and must be initialized. 2096 * 2097 * Note: Grafting of exclusive mode filters doesn't happen 2098 * in this path. 2099 * XXX: Should check for non-NULL lims (node exists but may 2100 * not be in-mode) for interop with full-state API. 2101 */ 2102 if (ssa->ss.ss_family != AF_UNSPEC) { 2103 /* Membership starts in IN mode */ 2104 if (is_new) { 2105 CTR1(KTR_IGMPV3, "%s: new join w/source", __func__); 2106 imf_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE); 2107 } else { 2108 CTR2(KTR_IGMPV3, "%s: %s source", __func__, "allow"); 2109 } 2110 lims = imf_graft(imf, MCAST_INCLUDE, &ssa->sin); 2111 if (lims == NULL) { 2112 CTR1(KTR_IGMPV3, "%s: merge imf state failed", 2113 __func__); 2114 error = ENOMEM; 2115 goto out_imo_free; 2116 } 2117 } else { 2118 /* No address specified; Membership starts in EX mode */ 2119 if (is_new) { 2120 CTR1(KTR_IGMPV3, "%s: new join w/o source", __func__); 2121 imf_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE); 2122 } 2123 } 2124 2125 /* 2126 * Begin state merge transaction at IGMP layer. 2127 */ 2128 IN_MULTI_LOCK(); 2129 2130 if (is_new) { 2131 error = in_joingroup_locked(ifp, &gsa->sin.sin_addr, imf, 2132 &inm); 2133 if (error) { 2134 CTR1(KTR_IGMPV3, "%s: in_joingroup_locked failed", 2135 __func__); 2136 IN_MULTI_UNLOCK(); 2137 goto out_imo_free; 2138 } 2139 imo->imo_membership[idx] = inm; 2140 } else { 2141 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 2142 error = inm_merge(inm, imf); 2143 if (error) { 2144 CTR1(KTR_IGMPV3, "%s: failed to merge inm state", 2145 __func__); 2146 goto out_in_multi_locked; 2147 } 2148 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 2149 error = igmp_change_state(inm); 2150 if (error) { 2151 CTR1(KTR_IGMPV3, "%s: failed igmp downcall", 2152 __func__); 2153 goto out_in_multi_locked; 2154 } 2155 } 2156 2157out_in_multi_locked: 2158 2159 IN_MULTI_UNLOCK(); 2160 2161 INP_WLOCK_ASSERT(inp); 2162 if (error) { 2163 imf_rollback(imf); 2164 if (is_new) 2165 imf_purge(imf); 2166 else 2167 imf_reap(imf); 2168 } else { 2169 imf_commit(imf); 2170 } 2171 2172out_imo_free: 2173 if (error && is_new) { 2174 imo->imo_membership[idx] = NULL; 2175 --imo->imo_num_memberships; 2176 } 2177 2178out_inp_locked: 2179 INP_WUNLOCK(inp); 2180 return (error); 2181} 2182 2183/* 2184 * Leave an IPv4 multicast group on an inpcb, possibly with a source. 2185 */ 2186static int 2187inp_leave_group(struct inpcb *inp, struct sockopt *sopt) 2188{ 2189 struct group_source_req gsr; 2190 struct ip_mreq_source mreqs; 2191 sockunion_t *gsa, *ssa; 2192 struct ifnet *ifp; 2193 struct in_mfilter *imf; 2194 struct ip_moptions *imo; 2195 struct in_msource *ims; 2196 struct in_multi *inm; 2197 size_t idx; 2198 int error, is_final; 2199 2200 ifp = NULL; 2201 error = 0; 2202 is_final = 1; 2203 2204 memset(&gsr, 0, sizeof(struct group_source_req)); 2205 gsa = (sockunion_t *)&gsr.gsr_group; 2206 gsa->ss.ss_family = AF_UNSPEC; 2207 ssa = (sockunion_t *)&gsr.gsr_source; 2208 ssa->ss.ss_family = AF_UNSPEC; 2209 2210 switch (sopt->sopt_name) { 2211 case IP_DROP_MEMBERSHIP: 2212 case IP_DROP_SOURCE_MEMBERSHIP: 2213 if (sopt->sopt_name == IP_DROP_MEMBERSHIP) { 2214 error = sooptcopyin(sopt, &mreqs, 2215 sizeof(struct ip_mreq), 2216 sizeof(struct ip_mreq)); 2217 /* 2218 * Swap interface and sourceaddr arguments, 2219 * as ip_mreq and ip_mreq_source are laid 2220 * out differently. 2221 */ 2222 mreqs.imr_interface = mreqs.imr_sourceaddr; 2223 mreqs.imr_sourceaddr.s_addr = INADDR_ANY; 2224 } else if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { 2225 error = sooptcopyin(sopt, &mreqs, 2226 sizeof(struct ip_mreq_source), 2227 sizeof(struct ip_mreq_source)); 2228 } 2229 if (error) 2230 return (error); 2231 2232 gsa->sin.sin_family = AF_INET; 2233 gsa->sin.sin_len = sizeof(struct sockaddr_in); 2234 gsa->sin.sin_addr = mreqs.imr_multiaddr; 2235 2236 if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { 2237 ssa->sin.sin_family = AF_INET; 2238 ssa->sin.sin_len = sizeof(struct sockaddr_in); 2239 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 2240 } 2241 2242 /* 2243 * Attempt to look up hinted ifp from interface address. 2244 * Fallthrough with null ifp iff lookup fails, to 2245 * preserve 4.4BSD mcast API idempotence. 2246 * XXX NOTE WELL: The RFC 3678 API is preferred because 2247 * using an IPv4 address as a key is racy. 2248 */ 2249 if (!in_nullhost(mreqs.imr_interface)) 2250 INADDR_TO_IFP(mreqs.imr_interface, ifp); 2251 2252 CTR3(KTR_IGMPV3, "%s: imr_interface = %s, ifp = %p", 2253 __func__, inet_ntoa(mreqs.imr_interface), ifp); 2254 2255 break; 2256 2257 case MCAST_LEAVE_GROUP: 2258 case MCAST_LEAVE_SOURCE_GROUP: 2259 if (sopt->sopt_name == MCAST_LEAVE_GROUP) { 2260 error = sooptcopyin(sopt, &gsr, 2261 sizeof(struct group_req), 2262 sizeof(struct group_req)); 2263 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 2264 error = sooptcopyin(sopt, &gsr, 2265 sizeof(struct group_source_req), 2266 sizeof(struct group_source_req)); 2267 } 2268 if (error) 2269 return (error); 2270 2271 if (gsa->sin.sin_family != AF_INET || 2272 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 2273 return (EINVAL); 2274 2275 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 2276 if (ssa->sin.sin_family != AF_INET || 2277 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 2278 return (EINVAL); 2279 } 2280 2281 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 2282 return (EADDRNOTAVAIL); 2283 2284 ifp = ifnet_byindex(gsr.gsr_interface); 2285 2286 if (ifp == NULL) 2287 return (EADDRNOTAVAIL); 2288 break; 2289 2290 default: 2291 CTR2(KTR_IGMPV3, "%s: unknown sopt_name %d", 2292 __func__, sopt->sopt_name); 2293 return (EOPNOTSUPP); 2294 break; 2295 } 2296 2297 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 2298 return (EINVAL); 2299 2300 /* 2301 * Find the membership in the membership array. 2302 */ 2303 imo = inp_findmoptions(inp); 2304 idx = imo_match_group(imo, ifp, &gsa->sa); 2305 if (idx == -1) { 2306 error = EADDRNOTAVAIL; 2307 goto out_inp_locked; 2308 } 2309 inm = imo->imo_membership[idx]; 2310 imf = &imo->imo_mfilters[idx]; 2311 2312 if (ssa->ss.ss_family != AF_UNSPEC) 2313 is_final = 0; 2314 2315 /* 2316 * Begin state merge transaction at socket layer. 2317 */ 2318 INP_WLOCK_ASSERT(inp); 2319 2320 /* 2321 * If we were instructed only to leave a given source, do so. 2322 * MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships. 2323 */ 2324 if (is_final) { 2325 imf_leave(imf); 2326 } else { 2327 if (imf->imf_st[0] == MCAST_EXCLUDE) { 2328 error = EADDRNOTAVAIL; 2329 goto out_inp_locked; 2330 } 2331 ims = imo_match_source(imo, idx, &ssa->sa); 2332 if (ims == NULL) { 2333 CTR3(KTR_IGMPV3, "%s: source %s %spresent", __func__, 2334 inet_ntoa(ssa->sin.sin_addr), "not "); 2335 error = EADDRNOTAVAIL; 2336 goto out_inp_locked; 2337 } 2338 CTR2(KTR_IGMPV3, "%s: %s source", __func__, "block"); 2339 error = imf_prune(imf, &ssa->sin); 2340 if (error) { 2341 CTR1(KTR_IGMPV3, "%s: merge imf state failed", 2342 __func__); 2343 goto out_inp_locked; 2344 } 2345 } 2346 2347 /* 2348 * Begin state merge transaction at IGMP layer. 2349 */ 2350 IN_MULTI_LOCK(); 2351 2352 if (is_final) { 2353 /* 2354 * Give up the multicast address record to which 2355 * the membership points. 2356 */ 2357 (void)in_leavegroup_locked(inm, imf); 2358 } else { 2359 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 2360 error = inm_merge(inm, imf); 2361 if (error) { 2362 CTR1(KTR_IGMPV3, "%s: failed to merge inm state", 2363 __func__); 2364 goto out_in_multi_locked; 2365 } 2366 2367 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 2368 error = igmp_change_state(inm); 2369 if (error) { 2370 CTR1(KTR_IGMPV3, "%s: failed igmp downcall", 2371 __func__); 2372 } 2373 } 2374 2375out_in_multi_locked: 2376 2377 IN_MULTI_UNLOCK(); 2378 2379 if (error) 2380 imf_rollback(imf); 2381 else 2382 imf_commit(imf); 2383 2384 imf_reap(imf); 2385 2386 if (is_final) { 2387 /* Remove the gap in the membership and filter array. */ 2388 for (++idx; idx < imo->imo_num_memberships; ++idx) { 2389 imo->imo_membership[idx-1] = imo->imo_membership[idx]; 2390 imo->imo_mfilters[idx-1] = imo->imo_mfilters[idx]; 2391 } 2392 imo->imo_num_memberships--; 2393 } 2394 2395out_inp_locked: 2396 INP_WUNLOCK(inp); 2397 return (error); 2398} 2399 2400/* 2401 * Select the interface for transmitting IPv4 multicast datagrams. 2402 * 2403 * Either an instance of struct in_addr or an instance of struct ip_mreqn 2404 * may be passed to this socket option. An address of INADDR_ANY or an 2405 * interface index of 0 is used to remove a previous selection. 2406 * When no interface is selected, one is chosen for every send. 2407 */ 2408static int 2409inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt) 2410{ 2411 struct in_addr addr; 2412 struct ip_mreqn mreqn; 2413 struct ifnet *ifp; 2414 struct ip_moptions *imo; 2415 int error; 2416 2417 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) { 2418 /* 2419 * An interface index was specified using the 2420 * Linux-derived ip_mreqn structure. 2421 */ 2422 error = sooptcopyin(sopt, &mreqn, sizeof(struct ip_mreqn), 2423 sizeof(struct ip_mreqn)); 2424 if (error) 2425 return (error); 2426 2427 if (mreqn.imr_ifindex < 0 || V_if_index < mreqn.imr_ifindex) 2428 return (EINVAL); 2429 2430 if (mreqn.imr_ifindex == 0) { 2431 ifp = NULL; 2432 } else { 2433 ifp = ifnet_byindex(mreqn.imr_ifindex); 2434 if (ifp == NULL) 2435 return (EADDRNOTAVAIL); 2436 } 2437 } else { 2438 /* 2439 * An interface was specified by IPv4 address. 2440 * This is the traditional BSD usage. 2441 */ 2442 error = sooptcopyin(sopt, &addr, sizeof(struct in_addr), 2443 sizeof(struct in_addr)); 2444 if (error) 2445 return (error); 2446 if (in_nullhost(addr)) { 2447 ifp = NULL; 2448 } else { 2449 INADDR_TO_IFP(addr, ifp); 2450 if (ifp == NULL) 2451 return (EADDRNOTAVAIL); 2452 } 2453 CTR3(KTR_IGMPV3, "%s: ifp = %p, addr = %s", __func__, ifp, 2454 inet_ntoa(addr)); 2455 } 2456 2457 /* Reject interfaces which do not support multicast. */ 2458 if (ifp != NULL && (ifp->if_flags & IFF_MULTICAST) == 0) 2459 return (EOPNOTSUPP); 2460 2461 imo = inp_findmoptions(inp); 2462 imo->imo_multicast_ifp = ifp; 2463 imo->imo_multicast_addr.s_addr = INADDR_ANY; 2464 INP_WUNLOCK(inp); 2465 2466 return (0); 2467} 2468 2469/* 2470 * Atomically set source filters on a socket for an IPv4 multicast group. 2471 * 2472 * SMPng: NOTE: Potentially calls malloc(M_WAITOK) with Giant held. 2473 */ 2474static int 2475inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) 2476{ 2477 struct __msfilterreq msfr; 2478 sockunion_t *gsa; 2479 struct ifnet *ifp; 2480 struct in_mfilter *imf; 2481 struct ip_moptions *imo; 2482 struct in_multi *inm; 2483 size_t idx; 2484 int error; 2485 2486 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 2487 sizeof(struct __msfilterreq)); 2488 if (error) 2489 return (error); 2490 2491 if (msfr.msfr_nsrcs > in_mcast_maxsocksrc) 2492 return (ENOBUFS); 2493 2494 if ((msfr.msfr_fmode != MCAST_EXCLUDE && 2495 msfr.msfr_fmode != MCAST_INCLUDE)) 2496 return (EINVAL); 2497 2498 if (msfr.msfr_group.ss_family != AF_INET || 2499 msfr.msfr_group.ss_len != sizeof(struct sockaddr_in)) 2500 return (EINVAL); 2501 2502 gsa = (sockunion_t *)&msfr.msfr_group; 2503 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 2504 return (EINVAL); 2505 2506 gsa->sin.sin_port = 0; /* ignore port */ 2507 2508 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 2509 return (EADDRNOTAVAIL); 2510 2511 ifp = ifnet_byindex(msfr.msfr_ifindex); 2512 if (ifp == NULL) 2513 return (EADDRNOTAVAIL); 2514 2515 /* 2516 * Take the INP write lock. 2517 * Check if this socket is a member of this group. 2518 */ 2519 imo = inp_findmoptions(inp); 2520 idx = imo_match_group(imo, ifp, &gsa->sa); 2521 if (idx == -1 || imo->imo_mfilters == NULL) { 2522 error = EADDRNOTAVAIL; 2523 goto out_inp_locked; 2524 } 2525 inm = imo->imo_membership[idx]; 2526 imf = &imo->imo_mfilters[idx]; 2527 2528 /* 2529 * Begin state merge transaction at socket layer. 2530 */ 2531 INP_WLOCK_ASSERT(inp); 2532 2533 imf->imf_st[1] = msfr.msfr_fmode; 2534 2535 /* 2536 * Apply any new source filters, if present. 2537 * Make a copy of the user-space source vector so 2538 * that we may copy them with a single copyin. This 2539 * allows us to deal with page faults up-front. 2540 */ 2541 if (msfr.msfr_nsrcs > 0) { 2542 struct in_msource *lims; 2543 struct sockaddr_in *psin; 2544 struct sockaddr_storage *kss, *pkss; 2545 int i; 2546 2547 INP_WUNLOCK(inp); 2548 2549 CTR2(KTR_IGMPV3, "%s: loading %lu source list entries", 2550 __func__, (unsigned long)msfr.msfr_nsrcs); 2551 kss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 2552 M_TEMP, M_WAITOK); 2553 error = copyin(msfr.msfr_srcs, kss, 2554 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 2555 if (error) { 2556 free(kss, M_TEMP); 2557 return (error); 2558 } 2559 2560 INP_WLOCK(inp); 2561 2562 /* 2563 * Mark all source filters as UNDEFINED at t1. 2564 * Restore new group filter mode, as imf_leave() 2565 * will set it to INCLUDE. 2566 */ 2567 imf_leave(imf); 2568 imf->imf_st[1] = msfr.msfr_fmode; 2569 2570 /* 2571 * Update socket layer filters at t1, lazy-allocating 2572 * new entries. This saves a bunch of memory at the 2573 * cost of one RB_FIND() per source entry; duplicate 2574 * entries in the msfr_nsrcs vector are ignored. 2575 * If we encounter an error, rollback transaction. 2576 * 2577 * XXX This too could be replaced with a set-symmetric 2578 * difference like loop to avoid walking from root 2579 * every time, as the key space is common. 2580 */ 2581 for (i = 0, pkss = kss; i < msfr.msfr_nsrcs; i++, pkss++) { 2582 psin = (struct sockaddr_in *)pkss; 2583 if (psin->sin_family != AF_INET) { 2584 error = EAFNOSUPPORT; 2585 break; 2586 } 2587 if (psin->sin_len != sizeof(struct sockaddr_in)) { 2588 error = EINVAL; 2589 break; 2590 } 2591 error = imf_get_source(imf, psin, &lims); 2592 if (error) 2593 break; 2594 lims->imsl_st[1] = imf->imf_st[1]; 2595 } 2596 free(kss, M_TEMP); 2597 } 2598 2599 if (error) 2600 goto out_imf_rollback; 2601 2602 INP_WLOCK_ASSERT(inp); 2603 IN_MULTI_LOCK(); 2604 2605 /* 2606 * Begin state merge transaction at IGMP layer. 2607 */ 2608 CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); 2609 error = inm_merge(inm, imf); 2610 if (error) { 2611 CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__); 2612 goto out_in_multi_locked; 2613 } 2614 2615 CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); 2616 error = igmp_change_state(inm); 2617 if (error) 2618 CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); 2619 2620out_in_multi_locked: 2621 2622 IN_MULTI_UNLOCK(); 2623 2624out_imf_rollback: 2625 if (error) 2626 imf_rollback(imf); 2627 else 2628 imf_commit(imf); 2629 2630 imf_reap(imf); 2631 2632out_inp_locked: 2633 INP_WUNLOCK(inp); 2634 return (error); 2635} 2636 2637/* 2638 * Set the IP multicast options in response to user setsockopt(). 2639 * 2640 * Many of the socket options handled in this function duplicate the 2641 * functionality of socket options in the regular unicast API. However, 2642 * it is not possible to merge the duplicate code, because the idempotence 2643 * of the IPv4 multicast part of the BSD Sockets API must be preserved; 2644 * the effects of these options must be treated as separate and distinct. 2645 * 2646 * SMPng: XXX: Unlocked read of inp_socket believed OK. 2647 * FUTURE: The IP_MULTICAST_VIF option may be eliminated if MROUTING 2648 * is refactored to no longer use vifs. 2649 */ 2650int 2651inp_setmoptions(struct inpcb *inp, struct sockopt *sopt) 2652{ 2653 struct ip_moptions *imo; 2654 int error; 2655 2656 error = 0; 2657 2658 /* 2659 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 2660 * or is a divert socket, reject it. 2661 */ 2662 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 2663 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 2664 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) 2665 return (EOPNOTSUPP); 2666 2667 switch (sopt->sopt_name) { 2668 case IP_MULTICAST_VIF: { 2669 int vifi; 2670 /* 2671 * Select a multicast VIF for transmission. 2672 * Only useful if multicast forwarding is active. 2673 */ 2674 if (legal_vif_num == NULL) { 2675 error = EOPNOTSUPP; 2676 break; 2677 } 2678 error = sooptcopyin(sopt, &vifi, sizeof(int), sizeof(int)); 2679 if (error) 2680 break; 2681 if (!legal_vif_num(vifi) && (vifi != -1)) { 2682 error = EINVAL; 2683 break; 2684 } 2685 imo = inp_findmoptions(inp); 2686 imo->imo_multicast_vif = vifi; 2687 INP_WUNLOCK(inp); 2688 break; 2689 } 2690 2691 case IP_MULTICAST_IF: 2692 error = inp_set_multicast_if(inp, sopt); 2693 break; 2694 2695 case IP_MULTICAST_TTL: { 2696 u_char ttl; 2697 2698 /* 2699 * Set the IP time-to-live for outgoing multicast packets. 2700 * The original multicast API required a char argument, 2701 * which is inconsistent with the rest of the socket API. 2702 * We allow either a char or an int. 2703 */ 2704 if (sopt->sopt_valsize == sizeof(u_char)) { 2705 error = sooptcopyin(sopt, &ttl, sizeof(u_char), 2706 sizeof(u_char)); 2707 if (error) 2708 break; 2709 } else { 2710 u_int ittl; 2711 2712 error = sooptcopyin(sopt, &ittl, sizeof(u_int), 2713 sizeof(u_int)); 2714 if (error) 2715 break; 2716 if (ittl > 255) { 2717 error = EINVAL; 2718 break; 2719 } 2720 ttl = (u_char)ittl; 2721 } 2722 imo = inp_findmoptions(inp); 2723 imo->imo_multicast_ttl = ttl; 2724 INP_WUNLOCK(inp); 2725 break; 2726 } 2727 2728 case IP_MULTICAST_LOOP: { 2729 u_char loop; 2730 2731 /* 2732 * Set the loopback flag for outgoing multicast packets. 2733 * Must be zero or one. The original multicast API required a 2734 * char argument, which is inconsistent with the rest 2735 * of the socket API. We allow either a char or an int. 2736 */ 2737 if (sopt->sopt_valsize == sizeof(u_char)) { 2738 error = sooptcopyin(sopt, &loop, sizeof(u_char), 2739 sizeof(u_char)); 2740 if (error) 2741 break; 2742 } else { 2743 u_int iloop; 2744 2745 error = sooptcopyin(sopt, &iloop, sizeof(u_int), 2746 sizeof(u_int)); 2747 if (error) 2748 break; 2749 loop = (u_char)iloop; 2750 } 2751 imo = inp_findmoptions(inp); 2752 imo->imo_multicast_loop = !!loop; 2753 INP_WUNLOCK(inp); 2754 break; 2755 } 2756 2757 case IP_ADD_MEMBERSHIP: 2758 case IP_ADD_SOURCE_MEMBERSHIP: 2759 case MCAST_JOIN_GROUP: 2760 case MCAST_JOIN_SOURCE_GROUP: 2761 error = inp_join_group(inp, sopt); 2762 break; 2763 2764 case IP_DROP_MEMBERSHIP: 2765 case IP_DROP_SOURCE_MEMBERSHIP: 2766 case MCAST_LEAVE_GROUP: 2767 case MCAST_LEAVE_SOURCE_GROUP: 2768 error = inp_leave_group(inp, sopt); 2769 break; 2770 2771 case IP_BLOCK_SOURCE: 2772 case IP_UNBLOCK_SOURCE: 2773 case MCAST_BLOCK_SOURCE: 2774 case MCAST_UNBLOCK_SOURCE: 2775 error = inp_block_unblock_source(inp, sopt); 2776 break; 2777 2778 case IP_MSFILTER: 2779 error = inp_set_source_filters(inp, sopt); 2780 break; 2781 2782 default: 2783 error = EOPNOTSUPP; 2784 break; 2785 } 2786 2787 INP_UNLOCK_ASSERT(inp); 2788 2789 return (error); 2790} 2791 2792/* 2793 * Expose IGMP's multicast filter mode and source list(s) to userland, 2794 * keyed by (ifindex, group). 2795 * The filter mode is written out as a uint32_t, followed by 2796 * 0..n of struct in_addr. 2797 * For use by ifmcstat(8). 2798 * SMPng: NOTE: unlocked read of ifindex space. 2799 */ 2800static int 2801sysctl_ip_mcast_filters(SYSCTL_HANDLER_ARGS) 2802{ 2803 struct in_addr src, group; 2804 struct ifnet *ifp; 2805 struct ifmultiaddr *ifma; 2806 struct in_multi *inm; 2807 struct ip_msource *ims; 2808 int *name; 2809 int retval; 2810 u_int namelen; 2811 uint32_t fmode, ifindex; 2812 2813 name = (int *)arg1; 2814 namelen = arg2; 2815 2816 if (req->newptr != NULL) 2817 return (EPERM); 2818 2819 if (namelen != 2) 2820 return (EINVAL); 2821 2822 ifindex = name[0]; 2823 if (ifindex <= 0 || ifindex > V_if_index) { 2824 CTR2(KTR_IGMPV3, "%s: ifindex %u out of range", 2825 __func__, ifindex); 2826 return (ENOENT); 2827 } 2828 2829 group.s_addr = name[1]; 2830 if (!IN_MULTICAST(ntohl(group.s_addr))) { 2831 CTR2(KTR_IGMPV3, "%s: group %s is not multicast", 2832 __func__, inet_ntoa(group)); 2833 return (EINVAL); 2834 } 2835 2836 ifp = ifnet_byindex(ifindex); 2837 if (ifp == NULL) { 2838 CTR2(KTR_IGMPV3, "%s: no ifp for ifindex %u", 2839 __func__, ifindex); 2840 return (ENOENT); 2841 } 2842 2843 retval = sysctl_wire_old_buffer(req, 2844 sizeof(uint32_t) + (in_mcast_maxgrpsrc * sizeof(struct in_addr))); 2845 if (retval) 2846 return (retval); 2847 2848 IN_MULTI_LOCK(); 2849 2850 IF_ADDR_RLOCK(ifp); 2851 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2852 if (ifma->ifma_addr->sa_family != AF_INET || 2853 ifma->ifma_protospec == NULL) 2854 continue; 2855 inm = (struct in_multi *)ifma->ifma_protospec; 2856 if (!in_hosteq(inm->inm_addr, group)) 2857 continue; 2858 fmode = inm->inm_st[1].iss_fmode; 2859 retval = SYSCTL_OUT(req, &fmode, sizeof(uint32_t)); 2860 if (retval != 0) 2861 break; 2862 RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) { 2863#ifdef KTR 2864 struct in_addr ina; 2865 ina.s_addr = htonl(ims->ims_haddr); 2866 CTR2(KTR_IGMPV3, "%s: visit node %s", __func__, 2867 inet_ntoa(ina)); 2868#endif 2869 /* 2870 * Only copy-out sources which are in-mode. 2871 */ 2872 if (fmode != ims_get_mode(inm, ims, 1)) { 2873 CTR1(KTR_IGMPV3, "%s: skip non-in-mode", 2874 __func__); 2875 continue; 2876 } 2877 src.s_addr = htonl(ims->ims_haddr); 2878 retval = SYSCTL_OUT(req, &src, sizeof(struct in_addr)); 2879 if (retval != 0) 2880 break; 2881 } 2882 } 2883 IF_ADDR_RUNLOCK(ifp); 2884 2885 IN_MULTI_UNLOCK(); 2886 2887 return (retval); 2888} 2889 2890#ifdef KTR 2891 2892static const char *inm_modestrs[] = { "un", "in", "ex" }; 2893 2894static const char * 2895inm_mode_str(const int mode) 2896{ 2897 2898 if (mode >= MCAST_UNDEFINED && mode <= MCAST_EXCLUDE) 2899 return (inm_modestrs[mode]); 2900 return ("??"); 2901} 2902 2903static const char *inm_statestrs[] = { 2904 "not-member", 2905 "silent", 2906 "idle", 2907 "lazy", 2908 "sleeping", 2909 "awakening", 2910 "query-pending", 2911 "sg-query-pending", 2912 "leaving" 2913}; 2914 2915static const char * 2916inm_state_str(const int state) 2917{ 2918 2919 if (state >= IGMP_NOT_MEMBER && state <= IGMP_LEAVING_MEMBER) 2920 return (inm_statestrs[state]); 2921 return ("??"); 2922} 2923 2924/* 2925 * Dump an in_multi structure to the console. 2926 */ 2927void 2928inm_print(const struct in_multi *inm) 2929{ 2930 int t; 2931 2932 if ((ktr_mask & KTR_IGMPV3) == 0) 2933 return; 2934 2935 printf("%s: --- begin inm %p ---\n", __func__, inm); 2936 printf("addr %s ifp %p(%s) ifma %p\n", 2937 inet_ntoa(inm->inm_addr), 2938 inm->inm_ifp, 2939 inm->inm_ifp->if_xname, 2940 inm->inm_ifma); 2941 printf("timer %u state %s refcount %u scq.len %u\n", 2942 inm->inm_timer, 2943 inm_state_str(inm->inm_state), 2944 inm->inm_refcount, 2945 inm->inm_scq.ifq_len); 2946 printf("igi %p nsrc %lu sctimer %u scrv %u\n", 2947 inm->inm_igi, 2948 inm->inm_nsrc, 2949 inm->inm_sctimer, 2950 inm->inm_scrv); 2951 for (t = 0; t < 2; t++) { 2952 printf("t%d: fmode %s asm %u ex %u in %u rec %u\n", t, 2953 inm_mode_str(inm->inm_st[t].iss_fmode), 2954 inm->inm_st[t].iss_asm, 2955 inm->inm_st[t].iss_ex, 2956 inm->inm_st[t].iss_in, 2957 inm->inm_st[t].iss_rec); 2958 } 2959 printf("%s: --- end inm %p ---\n", __func__, inm); 2960} 2961 2962#else /* !KTR */ 2963 2964void 2965inm_print(const struct in_multi *inm) 2966{ 2967 2968} 2969 2970#endif /* KTR */ 2971 2972RB_GENERATE(ip_msource_tree, ip_msource, ims_link, ip_msource_cmp); 2973