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