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