1 /*- 2 * Copyright (c) 2007 Bruce M. 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 * Until further notice, this file requires INET to compile. 34 * TODO: Make this infrastructure independent of address family. 35 * TODO: Teach netinet6 to use this code. 36 * TODO: Hook up SSM logic to IGMPv3/MLDv2. 37 */ 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include "opt_route.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/malloc.h> 48 #include <sys/mbuf.h> 49 #include <sys/protosw.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/sysctl.h> 53 #include <sys/vimage.h> 54 55 #include <net/if.h> 56 #include <net/if_dl.h> 57 #include <net/route.h> 58 #include <net/vnet.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/in_pcb.h> 63 #include <netinet/in_var.h> 64 #include <netinet/ip_var.h> 65 #include <netinet/igmp_var.h> 66 #include <netinet/vinet.h> 67 68 #ifndef __SOCKUNION_DECLARED 69 union sockunion { 70 struct sockaddr_storage ss; 71 struct sockaddr sa; 72 struct sockaddr_dl sdl; 73 struct sockaddr_in sin; 74 #ifdef INET6 75 struct sockaddr_in6 sin6; 76 #endif 77 }; 78 typedef union sockunion sockunion_t; 79 #define __SOCKUNION_DECLARED 80 #endif /* __SOCKUNION_DECLARED */ 81 82 static MALLOC_DEFINE(M_IPMADDR, "in_multi", "IPv4 multicast group"); 83 static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "IPv4 multicast options"); 84 static MALLOC_DEFINE(M_IPMSOURCE, "in_msource", "IPv4 multicast source filter"); 85 86 /* 87 * The IPv4 multicast list (in_multihead and associated structures) are 88 * protected by the global in_multi_mtx. See in_var.h for more details. For 89 * now, in_multi_mtx is marked as recursible due to IGMP's calling back into 90 * ip_output() to send IGMP packets while holding the lock; this probably is 91 * not quite desirable. 92 */ 93 #ifdef VIMAGE_GLOBALS 94 struct in_multihead in_multihead; /* XXX BSS initialization */ 95 #endif 96 struct mtx in_multi_mtx; 97 MTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF | MTX_RECURSE); 98 99 /* 100 * Functions with non-static linkage defined in this file should be 101 * declared in in_var.h: 102 * imo_match_group() 103 * imo_match_source() 104 * in_addmulti() 105 * in_delmulti() 106 * in_delmulti_locked() 107 * and ip_var.h: 108 * inp_freemoptions() 109 * inp_getmoptions() 110 * inp_setmoptions() 111 */ 112 static int imo_grow(struct ip_moptions *); 113 static int imo_join_source(struct ip_moptions *, size_t, sockunion_t *); 114 static int imo_leave_source(struct ip_moptions *, size_t, sockunion_t *); 115 static int inp_change_source_filter(struct inpcb *, struct sockopt *); 116 static struct ip_moptions * 117 inp_findmoptions(struct inpcb *); 118 static int inp_get_source_filters(struct inpcb *, struct sockopt *); 119 static int inp_join_group(struct inpcb *, struct sockopt *); 120 static int inp_leave_group(struct inpcb *, struct sockopt *); 121 static int inp_set_multicast_if(struct inpcb *, struct sockopt *); 122 static int inp_set_source_filters(struct inpcb *, struct sockopt *); 123 124 /* 125 * Resize the ip_moptions vector to the next power-of-two minus 1. 126 * May be called with locks held; do not sleep. 127 */ 128 static int 129 imo_grow(struct ip_moptions *imo) 130 { 131 struct in_multi **nmships; 132 struct in_multi **omships; 133 struct in_mfilter *nmfilters; 134 struct in_mfilter *omfilters; 135 size_t idx; 136 size_t newmax; 137 size_t oldmax; 138 139 nmships = NULL; 140 nmfilters = NULL; 141 omships = imo->imo_membership; 142 omfilters = imo->imo_mfilters; 143 oldmax = imo->imo_max_memberships; 144 newmax = ((oldmax + 1) * 2) - 1; 145 146 if (newmax <= IP_MAX_MEMBERSHIPS) { 147 nmships = (struct in_multi **)realloc(omships, 148 sizeof(struct in_multi *) * newmax, M_IPMOPTS, M_NOWAIT); 149 nmfilters = (struct in_mfilter *)realloc(omfilters, 150 sizeof(struct in_mfilter) * newmax, M_IPMSOURCE, M_NOWAIT); 151 if (nmships != NULL && nmfilters != NULL) { 152 /* Initialize newly allocated source filter heads. */ 153 for (idx = oldmax; idx < newmax; idx++) { 154 nmfilters[idx].imf_fmode = MCAST_EXCLUDE; 155 nmfilters[idx].imf_nsources = 0; 156 TAILQ_INIT(&nmfilters[idx].imf_sources); 157 } 158 imo->imo_max_memberships = newmax; 159 imo->imo_membership = nmships; 160 imo->imo_mfilters = nmfilters; 161 } 162 } 163 164 if (nmships == NULL || nmfilters == NULL) { 165 if (nmships != NULL) 166 free(nmships, M_IPMOPTS); 167 if (nmfilters != NULL) 168 free(nmfilters, M_IPMSOURCE); 169 return (ETOOMANYREFS); 170 } 171 172 return (0); 173 } 174 175 /* 176 * Add a source to a multicast filter list. 177 * Assumes the associated inpcb is locked. 178 */ 179 static int 180 imo_join_source(struct ip_moptions *imo, size_t gidx, sockunion_t *src) 181 { 182 struct in_msource *ims, *nims; 183 struct in_mfilter *imf; 184 185 KASSERT(src->ss.ss_family == AF_INET, ("%s: !AF_INET", __func__)); 186 KASSERT(imo->imo_mfilters != NULL, 187 ("%s: imo_mfilters vector not allocated", __func__)); 188 189 imf = &imo->imo_mfilters[gidx]; 190 if (imf->imf_nsources == IP_MAX_SOURCE_FILTER) 191 return (ENOBUFS); 192 193 ims = imo_match_source(imo, gidx, &src->sa); 194 if (ims != NULL) 195 return (EADDRNOTAVAIL); 196 197 /* Do not sleep with inp lock held. */ 198 nims = malloc(sizeof(struct in_msource), 199 M_IPMSOURCE, M_NOWAIT | M_ZERO); 200 if (nims == NULL) 201 return (ENOBUFS); 202 203 nims->ims_addr = src->ss; 204 TAILQ_INSERT_TAIL(&imf->imf_sources, nims, ims_next); 205 imf->imf_nsources++; 206 207 return (0); 208 } 209 210 static int 211 imo_leave_source(struct ip_moptions *imo, size_t gidx, sockunion_t *src) 212 { 213 struct in_msource *ims; 214 struct in_mfilter *imf; 215 216 KASSERT(src->ss.ss_family == AF_INET, ("%s: !AF_INET", __func__)); 217 KASSERT(imo->imo_mfilters != NULL, 218 ("%s: imo_mfilters vector not allocated", __func__)); 219 220 imf = &imo->imo_mfilters[gidx]; 221 if (imf->imf_nsources == IP_MAX_SOURCE_FILTER) 222 return (ENOBUFS); 223 224 ims = imo_match_source(imo, gidx, &src->sa); 225 if (ims == NULL) 226 return (EADDRNOTAVAIL); 227 228 TAILQ_REMOVE(&imf->imf_sources, ims, ims_next); 229 free(ims, M_IPMSOURCE); 230 imf->imf_nsources--; 231 232 return (0); 233 } 234 235 /* 236 * Find an IPv4 multicast group entry for this ip_moptions instance 237 * which matches the specified group, and optionally an interface. 238 * Return its index into the array, or -1 if not found. 239 */ 240 size_t 241 imo_match_group(struct ip_moptions *imo, struct ifnet *ifp, 242 struct sockaddr *group) 243 { 244 sockunion_t *gsa; 245 struct in_multi **pinm; 246 int idx; 247 int nmships; 248 249 gsa = (sockunion_t *)group; 250 251 /* The imo_membership array may be lazy allocated. */ 252 if (imo->imo_membership == NULL || imo->imo_num_memberships == 0) 253 return (-1); 254 255 nmships = imo->imo_num_memberships; 256 pinm = &imo->imo_membership[0]; 257 for (idx = 0; idx < nmships; idx++, pinm++) { 258 if (*pinm == NULL) 259 continue; 260 #if 0 261 printf("%s: trying ifp = %p, inaddr = %s ", __func__, 262 ifp, inet_ntoa(gsa->sin.sin_addr)); 263 printf("against %p, %s\n", 264 (*pinm)->inm_ifp, inet_ntoa((*pinm)->inm_addr)); 265 #endif 266 if ((ifp == NULL || ((*pinm)->inm_ifp == ifp)) && 267 (*pinm)->inm_addr.s_addr == gsa->sin.sin_addr.s_addr) { 268 break; 269 } 270 } 271 if (idx >= nmships) 272 idx = -1; 273 274 return (idx); 275 } 276 277 /* 278 * Find a multicast source entry for this imo which matches 279 * the given group index for this socket, and source address. 280 */ 281 struct in_msource * 282 imo_match_source(struct ip_moptions *imo, size_t gidx, struct sockaddr *src) 283 { 284 struct in_mfilter *imf; 285 struct in_msource *ims, *pims; 286 287 KASSERT(src->sa_family == AF_INET, ("%s: !AF_INET", __func__)); 288 KASSERT(gidx != -1 && gidx < imo->imo_num_memberships, 289 ("%s: invalid index %d\n", __func__, (int)gidx)); 290 291 /* The imo_mfilters array may be lazy allocated. */ 292 if (imo->imo_mfilters == NULL) 293 return (NULL); 294 295 pims = NULL; 296 imf = &imo->imo_mfilters[gidx]; 297 TAILQ_FOREACH(ims, &imf->imf_sources, ims_next) { 298 /* 299 * Perform bitwise comparison of two IPv4 addresses. 300 * TODO: Do the same for IPv6. 301 * Do not use sa_equal() for this as it is not aware of 302 * deeper structure in sockaddr_in or sockaddr_in6. 303 */ 304 if (((struct sockaddr_in *)&ims->ims_addr)->sin_addr.s_addr == 305 ((struct sockaddr_in *)src)->sin_addr.s_addr) { 306 pims = ims; 307 break; 308 } 309 } 310 311 return (pims); 312 } 313 314 /* 315 * Join an IPv4 multicast group. 316 */ 317 struct in_multi * 318 in_addmulti(struct in_addr *ap, struct ifnet *ifp) 319 { 320 INIT_VNET_INET(ifp->if_vnet); 321 struct in_multi *inm; 322 323 inm = NULL; 324 325 IFF_LOCKGIANT(ifp); 326 IN_MULTI_LOCK(); 327 328 IN_LOOKUP_MULTI(*ap, ifp, inm); 329 if (inm != NULL) { 330 /* 331 * If we already joined this group, just bump the 332 * refcount and return it. 333 */ 334 KASSERT(inm->inm_refcount >= 1, 335 ("%s: bad refcount %d", __func__, inm->inm_refcount)); 336 ++inm->inm_refcount; 337 } else do { 338 sockunion_t gsa; 339 struct ifmultiaddr *ifma; 340 struct in_multi *ninm; 341 int error; 342 343 memset(&gsa, 0, sizeof(gsa)); 344 gsa.sin.sin_family = AF_INET; 345 gsa.sin.sin_len = sizeof(struct sockaddr_in); 346 gsa.sin.sin_addr = *ap; 347 348 /* 349 * Check if a link-layer group is already associated 350 * with this network-layer group on the given ifnet. 351 * If so, bump the refcount on the existing network-layer 352 * group association and return it. 353 */ 354 error = if_addmulti(ifp, &gsa.sa, &ifma); 355 if (error) 356 break; 357 if (ifma->ifma_protospec != NULL) { 358 inm = (struct in_multi *)ifma->ifma_protospec; 359 #ifdef INVARIANTS 360 if (inm->inm_ifma != ifma || inm->inm_ifp != ifp || 361 inm->inm_addr.s_addr != ap->s_addr) 362 panic("%s: ifma is inconsistent", __func__); 363 #endif 364 ++inm->inm_refcount; 365 break; 366 } 367 368 /* 369 * A new membership is needed; construct it and 370 * perform the IGMP join. 371 */ 372 ninm = malloc(sizeof(*ninm), M_IPMADDR, M_NOWAIT | M_ZERO); 373 if (ninm == NULL) { 374 if_delmulti_ifma(ifma); 375 break; 376 } 377 ninm->inm_addr = *ap; 378 ninm->inm_ifp = ifp; 379 ninm->inm_ifma = ifma; 380 ninm->inm_refcount = 1; 381 ifma->ifma_protospec = ninm; 382 LIST_INSERT_HEAD(&V_in_multihead, ninm, inm_link); 383 384 igmp_joingroup(ninm); 385 386 inm = ninm; 387 } while (0); 388 389 IN_MULTI_UNLOCK(); 390 IFF_UNLOCKGIANT(ifp); 391 392 return (inm); 393 } 394 395 /* 396 * Leave an IPv4 multicast group. 397 * It is OK to call this routine if the underlying ifnet went away. 398 * 399 * XXX: To deal with the ifp going away, we cheat; the link-layer code in net 400 * will set ifma_ifp to NULL when the associated ifnet instance is detached 401 * from the system. 402 * 403 * The only reason we need to violate layers and check ifma_ifp here at all 404 * is because certain hardware drivers still require Giant to be held, 405 * and it must always be taken before other locks. 406 */ 407 void 408 in_delmulti(struct in_multi *inm) 409 { 410 struct ifnet *ifp; 411 412 KASSERT(inm != NULL, ("%s: inm is NULL", __func__)); 413 KASSERT(inm->inm_ifma != NULL, ("%s: no ifma", __func__)); 414 ifp = inm->inm_ifma->ifma_ifp; 415 416 if (ifp != NULL) { 417 /* 418 * Sanity check that netinet's notion of ifp is the 419 * same as net's. 420 */ 421 KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__)); 422 IFF_LOCKGIANT(ifp); 423 } 424 425 IN_MULTI_LOCK(); 426 in_delmulti_locked(inm); 427 IN_MULTI_UNLOCK(); 428 429 if (ifp != NULL) 430 IFF_UNLOCKGIANT(ifp); 431 } 432 433 /* 434 * Delete a multicast address record, with locks held. 435 * 436 * It is OK to call this routine if the ifp went away. 437 * Assumes that caller holds the IN_MULTI lock, and that 438 * Giant was taken before other locks if required by the hardware. 439 */ 440 void 441 in_delmulti_locked(struct in_multi *inm) 442 { 443 struct ifmultiaddr *ifma; 444 445 IN_MULTI_LOCK_ASSERT(); 446 KASSERT(inm->inm_refcount >= 1, ("%s: freeing freed inm", __func__)); 447 448 if (--inm->inm_refcount == 0) { 449 igmp_leavegroup(inm); 450 451 ifma = inm->inm_ifma; 452 #ifdef DIAGNOSTIC 453 if (bootverbose) 454 printf("%s: purging ifma %p\n", __func__, ifma); 455 #endif 456 KASSERT(ifma->ifma_protospec == inm, 457 ("%s: ifma_protospec != inm", __func__)); 458 ifma->ifma_protospec = NULL; 459 460 LIST_REMOVE(inm, inm_link); 461 free(inm, M_IPMADDR); 462 463 if_delmulti_ifma(ifma); 464 } 465 } 466 467 /* 468 * Block or unblock an ASM/SSM multicast source on an inpcb. 469 */ 470 static int 471 inp_change_source_filter(struct inpcb *inp, struct sockopt *sopt) 472 { 473 INIT_VNET_NET(curvnet); 474 INIT_VNET_INET(curvnet); 475 struct group_source_req gsr; 476 sockunion_t *gsa, *ssa; 477 struct ifnet *ifp; 478 struct in_mfilter *imf; 479 struct ip_moptions *imo; 480 struct in_msource *ims; 481 size_t idx; 482 int error; 483 int block; 484 485 ifp = NULL; 486 error = 0; 487 block = 0; 488 489 memset(&gsr, 0, sizeof(struct group_source_req)); 490 gsa = (sockunion_t *)&gsr.gsr_group; 491 ssa = (sockunion_t *)&gsr.gsr_source; 492 493 switch (sopt->sopt_name) { 494 case IP_BLOCK_SOURCE: 495 case IP_UNBLOCK_SOURCE: { 496 struct ip_mreq_source mreqs; 497 498 error = sooptcopyin(sopt, &mreqs, 499 sizeof(struct ip_mreq_source), 500 sizeof(struct ip_mreq_source)); 501 if (error) 502 return (error); 503 504 gsa->sin.sin_family = AF_INET; 505 gsa->sin.sin_len = sizeof(struct sockaddr_in); 506 gsa->sin.sin_addr = mreqs.imr_multiaddr; 507 508 ssa->sin.sin_family = AF_INET; 509 ssa->sin.sin_len = sizeof(struct sockaddr_in); 510 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 511 512 if (mreqs.imr_interface.s_addr != INADDR_ANY) 513 INADDR_TO_IFP(mreqs.imr_interface, ifp); 514 515 if (sopt->sopt_name == IP_BLOCK_SOURCE) 516 block = 1; 517 518 #ifdef DIAGNOSTIC 519 if (bootverbose) { 520 printf("%s: imr_interface = %s, ifp = %p\n", 521 __func__, inet_ntoa(mreqs.imr_interface), ifp); 522 } 523 #endif 524 break; 525 } 526 527 case MCAST_BLOCK_SOURCE: 528 case MCAST_UNBLOCK_SOURCE: 529 error = sooptcopyin(sopt, &gsr, 530 sizeof(struct group_source_req), 531 sizeof(struct group_source_req)); 532 if (error) 533 return (error); 534 535 if (gsa->sin.sin_family != AF_INET || 536 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 537 return (EINVAL); 538 539 if (ssa->sin.sin_family != AF_INET || 540 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 541 return (EINVAL); 542 543 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 544 return (EADDRNOTAVAIL); 545 546 ifp = ifnet_byindex(gsr.gsr_interface); 547 548 if (sopt->sopt_name == MCAST_BLOCK_SOURCE) 549 block = 1; 550 break; 551 552 default: 553 #ifdef DIAGNOSTIC 554 if (bootverbose) { 555 printf("%s: unknown sopt_name %d\n", __func__, 556 sopt->sopt_name); 557 } 558 #endif 559 return (EOPNOTSUPP); 560 break; 561 } 562 563 /* XXX INET6 */ 564 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 565 return (EINVAL); 566 567 /* 568 * Check if we are actually a member of this group. 569 */ 570 imo = inp_findmoptions(inp); 571 idx = imo_match_group(imo, ifp, &gsa->sa); 572 if (idx == -1 || imo->imo_mfilters == NULL) { 573 error = EADDRNOTAVAIL; 574 goto out_locked; 575 } 576 577 KASSERT(imo->imo_mfilters != NULL, 578 ("%s: imo_mfilters not allocated", __func__)); 579 imf = &imo->imo_mfilters[idx]; 580 581 /* 582 * SSM multicast truth table for block/unblock operations. 583 * 584 * Operation Filter Mode Entry exists? Action 585 * 586 * block exclude no add source to filter 587 * unblock include no add source to filter 588 * block include no EINVAL 589 * unblock exclude no EINVAL 590 * block exclude yes EADDRNOTAVAIL 591 * unblock include yes EADDRNOTAVAIL 592 * block include yes remove source from filter 593 * unblock exclude yes remove source from filter 594 * 595 * FreeBSD does not explicitly distinguish between ASM and SSM 596 * mode sockets; all sockets are assumed to have a filter list. 597 */ 598 #ifdef DIAGNOSTIC 599 if (bootverbose) { 600 printf("%s: imf_fmode is %s\n", __func__, 601 imf->imf_fmode == MCAST_INCLUDE ? "include" : "exclude"); 602 } 603 #endif 604 ims = imo_match_source(imo, idx, &ssa->sa); 605 if (ims == NULL) { 606 if ((block == 1 && imf->imf_fmode == MCAST_EXCLUDE) || 607 (block == 0 && imf->imf_fmode == MCAST_INCLUDE)) { 608 #ifdef DIAGNOSTIC 609 if (bootverbose) { 610 printf("%s: adding %s to filter list\n", 611 __func__, inet_ntoa(ssa->sin.sin_addr)); 612 } 613 #endif 614 error = imo_join_source(imo, idx, ssa); 615 } 616 if ((block == 1 && imf->imf_fmode == MCAST_INCLUDE) || 617 (block == 0 && imf->imf_fmode == MCAST_EXCLUDE)) { 618 /* 619 * If the socket is in inclusive mode: 620 * the source is already blocked as it has no entry. 621 * If the socket is in exclusive mode: 622 * the source is already unblocked as it has no entry. 623 */ 624 #ifdef DIAGNOSTIC 625 if (bootverbose) { 626 printf("%s: ims %p; %s already [un]blocked\n", 627 __func__, ims, 628 inet_ntoa(ssa->sin.sin_addr)); 629 } 630 #endif 631 error = EINVAL; 632 } 633 } else { 634 if ((block == 1 && imf->imf_fmode == MCAST_EXCLUDE) || 635 (block == 0 && imf->imf_fmode == MCAST_INCLUDE)) { 636 /* 637 * If the socket is in exclusive mode: 638 * the source is already blocked as it has an entry. 639 * If the socket is in inclusive mode: 640 * the source is already unblocked as it has an entry. 641 */ 642 #ifdef DIAGNOSTIC 643 if (bootverbose) { 644 printf("%s: ims %p; %s already [un]blocked\n", 645 __func__, ims, 646 inet_ntoa(ssa->sin.sin_addr)); 647 } 648 #endif 649 error = EADDRNOTAVAIL; 650 } 651 if ((block == 1 && imf->imf_fmode == MCAST_INCLUDE) || 652 (block == 0 && imf->imf_fmode == MCAST_EXCLUDE)) { 653 #ifdef DIAGNOSTIC 654 if (bootverbose) { 655 printf("%s: removing %s from filter list\n", 656 __func__, inet_ntoa(ssa->sin.sin_addr)); 657 } 658 #endif 659 error = imo_leave_source(imo, idx, ssa); 660 } 661 } 662 663 out_locked: 664 INP_WUNLOCK(inp); 665 return (error); 666 } 667 668 /* 669 * Given an inpcb, return its multicast options structure pointer. Accepts 670 * an unlocked inpcb pointer, but will return it locked. May sleep. 671 */ 672 static struct ip_moptions * 673 inp_findmoptions(struct inpcb *inp) 674 { 675 struct ip_moptions *imo; 676 struct in_multi **immp; 677 struct in_mfilter *imfp; 678 size_t idx; 679 680 INP_WLOCK(inp); 681 if (inp->inp_moptions != NULL) 682 return (inp->inp_moptions); 683 684 INP_WUNLOCK(inp); 685 686 imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS, 687 M_WAITOK); 688 immp = (struct in_multi **)malloc(sizeof(*immp) * IP_MIN_MEMBERSHIPS, 689 M_IPMOPTS, M_WAITOK | M_ZERO); 690 imfp = (struct in_mfilter *)malloc( 691 sizeof(struct in_mfilter) * IP_MIN_MEMBERSHIPS, 692 M_IPMSOURCE, M_WAITOK); 693 694 imo->imo_multicast_ifp = NULL; 695 imo->imo_multicast_addr.s_addr = INADDR_ANY; 696 imo->imo_multicast_vif = -1; 697 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; 698 imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; 699 imo->imo_num_memberships = 0; 700 imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; 701 imo->imo_membership = immp; 702 703 /* Initialize per-group source filters. */ 704 for (idx = 0; idx < IP_MIN_MEMBERSHIPS; idx++) { 705 imfp[idx].imf_fmode = MCAST_EXCLUDE; 706 imfp[idx].imf_nsources = 0; 707 TAILQ_INIT(&imfp[idx].imf_sources); 708 } 709 imo->imo_mfilters = imfp; 710 711 INP_WLOCK(inp); 712 if (inp->inp_moptions != NULL) { 713 free(imfp, M_IPMSOURCE); 714 free(immp, M_IPMOPTS); 715 free(imo, M_IPMOPTS); 716 return (inp->inp_moptions); 717 } 718 inp->inp_moptions = imo; 719 return (imo); 720 } 721 722 /* 723 * Discard the IP multicast options (and source filters). 724 */ 725 void 726 inp_freemoptions(struct ip_moptions *imo) 727 { 728 struct in_mfilter *imf; 729 struct in_msource *ims, *tims; 730 size_t idx, nmships; 731 732 KASSERT(imo != NULL, ("%s: ip_moptions is NULL", __func__)); 733 734 nmships = imo->imo_num_memberships; 735 for (idx = 0; idx < nmships; ++idx) { 736 in_delmulti(imo->imo_membership[idx]); 737 738 if (imo->imo_mfilters != NULL) { 739 imf = &imo->imo_mfilters[idx]; 740 TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, 741 ims_next, tims) { 742 TAILQ_REMOVE(&imf->imf_sources, ims, ims_next); 743 free(ims, M_IPMSOURCE); 744 imf->imf_nsources--; 745 } 746 KASSERT(imf->imf_nsources == 0, 747 ("%s: did not free all imf_nsources", __func__)); 748 } 749 } 750 751 if (imo->imo_mfilters != NULL) 752 free(imo->imo_mfilters, M_IPMSOURCE); 753 free(imo->imo_membership, M_IPMOPTS); 754 free(imo, M_IPMOPTS); 755 } 756 757 /* 758 * Atomically get source filters on a socket for an IPv4 multicast group. 759 * Called with INP lock held; returns with lock released. 760 */ 761 static int 762 inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt) 763 { 764 INIT_VNET_NET(curvnet); 765 struct __msfilterreq msfr; 766 sockunion_t *gsa; 767 struct ifnet *ifp; 768 struct ip_moptions *imo; 769 struct in_mfilter *imf; 770 struct in_msource *ims; 771 struct sockaddr_storage *ptss; 772 struct sockaddr_storage *tss; 773 int error; 774 size_t idx; 775 776 INP_WLOCK_ASSERT(inp); 777 778 imo = inp->inp_moptions; 779 KASSERT(imo != NULL, ("%s: null ip_moptions", __func__)); 780 781 INP_WUNLOCK(inp); 782 783 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 784 sizeof(struct __msfilterreq)); 785 if (error) 786 return (error); 787 788 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 789 return (EINVAL); 790 791 ifp = ifnet_byindex(msfr.msfr_ifindex); 792 if (ifp == NULL) 793 return (EINVAL); 794 795 INP_WLOCK(inp); 796 797 /* 798 * Lookup group on the socket. 799 */ 800 gsa = (sockunion_t *)&msfr.msfr_group; 801 idx = imo_match_group(imo, ifp, &gsa->sa); 802 if (idx == -1 || imo->imo_mfilters == NULL) { 803 INP_WUNLOCK(inp); 804 return (EADDRNOTAVAIL); 805 } 806 807 imf = &imo->imo_mfilters[idx]; 808 msfr.msfr_fmode = imf->imf_fmode; 809 msfr.msfr_nsrcs = imf->imf_nsources; 810 811 /* 812 * If the user specified a buffer, copy out the source filter 813 * entries to userland gracefully. 814 * msfr.msfr_nsrcs is always set to the total number of filter 815 * entries which the kernel currently has for this group. 816 */ 817 tss = NULL; 818 if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) { 819 /* 820 * Make a copy of the source vector so that we do not 821 * thrash the inpcb lock whilst copying it out. 822 * We only copy out the number of entries which userland 823 * has asked for, but we always tell userland how big the 824 * buffer really needs to be. 825 */ 826 tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 827 M_TEMP, M_NOWAIT); 828 if (tss == NULL) { 829 error = ENOBUFS; 830 } else { 831 ptss = tss; 832 TAILQ_FOREACH(ims, &imf->imf_sources, ims_next) { 833 memcpy(ptss++, &ims->ims_addr, 834 sizeof(struct sockaddr_storage)); 835 } 836 } 837 } 838 839 INP_WUNLOCK(inp); 840 841 if (tss != NULL) { 842 error = copyout(tss, msfr.msfr_srcs, 843 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 844 free(tss, M_TEMP); 845 } 846 847 if (error) 848 return (error); 849 850 error = sooptcopyout(sopt, &msfr, sizeof(struct __msfilterreq)); 851 852 return (error); 853 } 854 855 /* 856 * Return the IP multicast options in response to user getsockopt(). 857 */ 858 int 859 inp_getmoptions(struct inpcb *inp, struct sockopt *sopt) 860 { 861 INIT_VNET_INET(curvnet); 862 struct ip_mreqn mreqn; 863 struct ip_moptions *imo; 864 struct ifnet *ifp; 865 struct in_ifaddr *ia; 866 int error, optval; 867 u_char coptval; 868 869 INP_WLOCK(inp); 870 imo = inp->inp_moptions; 871 /* 872 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 873 * or is a divert socket, reject it. 874 */ 875 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 876 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 877 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) { 878 INP_WUNLOCK(inp); 879 return (EOPNOTSUPP); 880 } 881 882 error = 0; 883 switch (sopt->sopt_name) { 884 case IP_MULTICAST_VIF: 885 if (imo != NULL) 886 optval = imo->imo_multicast_vif; 887 else 888 optval = -1; 889 INP_WUNLOCK(inp); 890 error = sooptcopyout(sopt, &optval, sizeof(int)); 891 break; 892 893 case IP_MULTICAST_IF: 894 memset(&mreqn, 0, sizeof(struct ip_mreqn)); 895 if (imo != NULL) { 896 ifp = imo->imo_multicast_ifp; 897 if (imo->imo_multicast_addr.s_addr != INADDR_ANY) { 898 mreqn.imr_address = imo->imo_multicast_addr; 899 } else if (ifp != NULL) { 900 mreqn.imr_ifindex = ifp->if_index; 901 IFP_TO_IA(ifp, ia); 902 if (ia != NULL) { 903 mreqn.imr_address = 904 IA_SIN(ia)->sin_addr; 905 } 906 } 907 } 908 INP_WUNLOCK(inp); 909 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) { 910 error = sooptcopyout(sopt, &mreqn, 911 sizeof(struct ip_mreqn)); 912 } else { 913 error = sooptcopyout(sopt, &mreqn.imr_address, 914 sizeof(struct in_addr)); 915 } 916 break; 917 918 case IP_MULTICAST_TTL: 919 if (imo == 0) 920 optval = coptval = IP_DEFAULT_MULTICAST_TTL; 921 else 922 optval = coptval = imo->imo_multicast_ttl; 923 INP_WUNLOCK(inp); 924 if (sopt->sopt_valsize == sizeof(u_char)) 925 error = sooptcopyout(sopt, &coptval, sizeof(u_char)); 926 else 927 error = sooptcopyout(sopt, &optval, sizeof(int)); 928 break; 929 930 case IP_MULTICAST_LOOP: 931 if (imo == 0) 932 optval = coptval = IP_DEFAULT_MULTICAST_LOOP; 933 else 934 optval = coptval = imo->imo_multicast_loop; 935 INP_WUNLOCK(inp); 936 if (sopt->sopt_valsize == sizeof(u_char)) 937 error = sooptcopyout(sopt, &coptval, sizeof(u_char)); 938 else 939 error = sooptcopyout(sopt, &optval, sizeof(int)); 940 break; 941 942 case IP_MSFILTER: 943 if (imo == NULL) { 944 error = EADDRNOTAVAIL; 945 INP_WUNLOCK(inp); 946 } else { 947 error = inp_get_source_filters(inp, sopt); 948 } 949 break; 950 951 default: 952 INP_WUNLOCK(inp); 953 error = ENOPROTOOPT; 954 break; 955 } 956 957 INP_UNLOCK_ASSERT(inp); 958 959 return (error); 960 } 961 962 /* 963 * Join an IPv4 multicast group, possibly with a source. 964 */ 965 static int 966 inp_join_group(struct inpcb *inp, struct sockopt *sopt) 967 { 968 INIT_VNET_NET(curvnet); 969 INIT_VNET_INET(curvnet); 970 struct group_source_req gsr; 971 sockunion_t *gsa, *ssa; 972 struct ifnet *ifp; 973 struct in_mfilter *imf; 974 struct ip_moptions *imo; 975 struct in_multi *inm; 976 size_t idx; 977 int error; 978 979 ifp = NULL; 980 error = 0; 981 982 memset(&gsr, 0, sizeof(struct group_source_req)); 983 gsa = (sockunion_t *)&gsr.gsr_group; 984 gsa->ss.ss_family = AF_UNSPEC; 985 ssa = (sockunion_t *)&gsr.gsr_source; 986 ssa->ss.ss_family = AF_UNSPEC; 987 988 switch (sopt->sopt_name) { 989 case IP_ADD_MEMBERSHIP: 990 case IP_ADD_SOURCE_MEMBERSHIP: { 991 struct ip_mreq_source mreqs; 992 993 if (sopt->sopt_name == IP_ADD_MEMBERSHIP) { 994 error = sooptcopyin(sopt, &mreqs, 995 sizeof(struct ip_mreq), 996 sizeof(struct ip_mreq)); 997 /* 998 * Do argument switcharoo from ip_mreq into 999 * ip_mreq_source to avoid using two instances. 1000 */ 1001 mreqs.imr_interface = mreqs.imr_sourceaddr; 1002 mreqs.imr_sourceaddr.s_addr = INADDR_ANY; 1003 } else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { 1004 error = sooptcopyin(sopt, &mreqs, 1005 sizeof(struct ip_mreq_source), 1006 sizeof(struct ip_mreq_source)); 1007 } 1008 if (error) 1009 return (error); 1010 1011 gsa->sin.sin_family = AF_INET; 1012 gsa->sin.sin_len = sizeof(struct sockaddr_in); 1013 gsa->sin.sin_addr = mreqs.imr_multiaddr; 1014 1015 if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { 1016 ssa->sin.sin_family = AF_INET; 1017 ssa->sin.sin_len = sizeof(struct sockaddr_in); 1018 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 1019 } 1020 1021 /* 1022 * Obtain ifp. If no interface address was provided, 1023 * use the interface of the route in the unicast FIB for 1024 * the given multicast destination; usually, this is the 1025 * default route. 1026 * If this lookup fails, attempt to use the first non-loopback 1027 * interface with multicast capability in the system as a 1028 * last resort. The legacy IPv4 ASM API requires that we do 1029 * this in order to allow groups to be joined when the routing 1030 * table has not yet been populated during boot. 1031 * If all of these conditions fail, return EADDRNOTAVAIL, and 1032 * reject the IPv4 multicast join. 1033 */ 1034 if (mreqs.imr_interface.s_addr != INADDR_ANY) { 1035 INADDR_TO_IFP(mreqs.imr_interface, ifp); 1036 } else { 1037 struct route ro; 1038 1039 ro.ro_rt = NULL; 1040 *(struct sockaddr_in *)&ro.ro_dst = gsa->sin; 1041 in_rtalloc_ign(&ro, 0, 1042 inp->inp_inc.inc_fibnum); 1043 if (ro.ro_rt != NULL) { 1044 ifp = ro.ro_rt->rt_ifp; 1045 KASSERT(ifp != NULL, ("%s: null ifp", 1046 __func__)); 1047 RTFREE(ro.ro_rt); 1048 } else { 1049 struct in_ifaddr *ia; 1050 struct ifnet *mfp = NULL; 1051 TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { 1052 mfp = ia->ia_ifp; 1053 if (!(mfp->if_flags & IFF_LOOPBACK) && 1054 (mfp->if_flags & IFF_MULTICAST)) { 1055 ifp = mfp; 1056 break; 1057 } 1058 } 1059 } 1060 } 1061 #ifdef DIAGNOSTIC 1062 if (bootverbose) { 1063 printf("%s: imr_interface = %s, ifp = %p\n", 1064 __func__, inet_ntoa(mreqs.imr_interface), ifp); 1065 } 1066 #endif 1067 break; 1068 } 1069 1070 case MCAST_JOIN_GROUP: 1071 case MCAST_JOIN_SOURCE_GROUP: 1072 if (sopt->sopt_name == MCAST_JOIN_GROUP) { 1073 error = sooptcopyin(sopt, &gsr, 1074 sizeof(struct group_req), 1075 sizeof(struct group_req)); 1076 } else if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 1077 error = sooptcopyin(sopt, &gsr, 1078 sizeof(struct group_source_req), 1079 sizeof(struct group_source_req)); 1080 } 1081 if (error) 1082 return (error); 1083 1084 if (gsa->sin.sin_family != AF_INET || 1085 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 1086 return (EINVAL); 1087 1088 /* 1089 * Overwrite the port field if present, as the sockaddr 1090 * being copied in may be matched with a binary comparison. 1091 * XXX INET6 1092 */ 1093 gsa->sin.sin_port = 0; 1094 if (sopt->sopt_name == MCAST_JOIN_SOURCE_GROUP) { 1095 if (ssa->sin.sin_family != AF_INET || 1096 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 1097 return (EINVAL); 1098 ssa->sin.sin_port = 0; 1099 } 1100 1101 /* 1102 * Obtain the ifp. 1103 */ 1104 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 1105 return (EADDRNOTAVAIL); 1106 ifp = ifnet_byindex(gsr.gsr_interface); 1107 1108 break; 1109 1110 default: 1111 #ifdef DIAGNOSTIC 1112 if (bootverbose) { 1113 printf("%s: unknown sopt_name %d\n", __func__, 1114 sopt->sopt_name); 1115 } 1116 #endif 1117 return (EOPNOTSUPP); 1118 break; 1119 } 1120 1121 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1122 return (EINVAL); 1123 1124 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) 1125 return (EADDRNOTAVAIL); 1126 1127 /* 1128 * Check if we already hold membership of this group for this inpcb. 1129 * If so, we do not need to perform the initial join. 1130 */ 1131 imo = inp_findmoptions(inp); 1132 idx = imo_match_group(imo, ifp, &gsa->sa); 1133 if (idx != -1) { 1134 if (ssa->ss.ss_family != AF_UNSPEC) { 1135 /* 1136 * Attempting to join an ASM group (when already 1137 * an ASM or SSM member) is an error. 1138 */ 1139 error = EADDRNOTAVAIL; 1140 } else { 1141 imf = &imo->imo_mfilters[idx]; 1142 if (imf->imf_nsources == 0) { 1143 /* 1144 * Attempting to join an SSM group (when 1145 * already an ASM member) is an error. 1146 */ 1147 error = EINVAL; 1148 } else { 1149 /* 1150 * Attempting to join an SSM group (when 1151 * already an SSM member) means "add this 1152 * source to the inclusive filter list". 1153 */ 1154 error = imo_join_source(imo, idx, ssa); 1155 } 1156 } 1157 goto out_locked; 1158 } 1159 1160 /* 1161 * Call imo_grow() to reallocate the membership and source filter 1162 * vectors if they are full. If the size would exceed the hard limit, 1163 * then we know we've really run out of entries. We keep the INP 1164 * lock held to avoid introducing a race condition. 1165 */ 1166 if (imo->imo_num_memberships == imo->imo_max_memberships) { 1167 error = imo_grow(imo); 1168 if (error) 1169 goto out_locked; 1170 } 1171 1172 /* 1173 * So far, so good: perform the layer 3 join, layer 2 join, 1174 * and make an IGMP announcement if needed. 1175 */ 1176 inm = in_addmulti(&gsa->sin.sin_addr, ifp); 1177 if (inm == NULL) { 1178 error = ENOBUFS; 1179 goto out_locked; 1180 } 1181 idx = imo->imo_num_memberships; 1182 imo->imo_membership[idx] = inm; 1183 imo->imo_num_memberships++; 1184 1185 KASSERT(imo->imo_mfilters != NULL, 1186 ("%s: imf_mfilters vector was not allocated", __func__)); 1187 imf = &imo->imo_mfilters[idx]; 1188 KASSERT(TAILQ_EMPTY(&imf->imf_sources), 1189 ("%s: imf_sources not empty", __func__)); 1190 1191 /* 1192 * If this is a new SSM group join (i.e. a source was specified 1193 * with this group), add this source to the filter list. 1194 */ 1195 if (ssa->ss.ss_family != AF_UNSPEC) { 1196 /* 1197 * An initial SSM join implies that this socket's membership 1198 * of the multicast group is now in inclusive mode. 1199 */ 1200 imf->imf_fmode = MCAST_INCLUDE; 1201 1202 error = imo_join_source(imo, idx, ssa); 1203 if (error) { 1204 /* 1205 * Drop inp lock before calling in_delmulti(), 1206 * to prevent a lock order reversal. 1207 */ 1208 --imo->imo_num_memberships; 1209 INP_WUNLOCK(inp); 1210 in_delmulti(inm); 1211 return (error); 1212 } 1213 } 1214 1215 out_locked: 1216 INP_WUNLOCK(inp); 1217 return (error); 1218 } 1219 1220 /* 1221 * Leave an IPv4 multicast group on an inpcb, possibly with a source. 1222 */ 1223 static int 1224 inp_leave_group(struct inpcb *inp, struct sockopt *sopt) 1225 { 1226 INIT_VNET_NET(curvnet); 1227 INIT_VNET_INET(curvnet); 1228 struct group_source_req gsr; 1229 struct ip_mreq_source mreqs; 1230 sockunion_t *gsa, *ssa; 1231 struct ifnet *ifp; 1232 struct in_mfilter *imf; 1233 struct ip_moptions *imo; 1234 struct in_msource *ims, *tims; 1235 struct in_multi *inm; 1236 size_t idx; 1237 int error; 1238 1239 ifp = NULL; 1240 error = 0; 1241 1242 memset(&gsr, 0, sizeof(struct group_source_req)); 1243 gsa = (sockunion_t *)&gsr.gsr_group; 1244 gsa->ss.ss_family = AF_UNSPEC; 1245 ssa = (sockunion_t *)&gsr.gsr_source; 1246 ssa->ss.ss_family = AF_UNSPEC; 1247 1248 switch (sopt->sopt_name) { 1249 case IP_DROP_MEMBERSHIP: 1250 case IP_DROP_SOURCE_MEMBERSHIP: 1251 if (sopt->sopt_name == IP_DROP_MEMBERSHIP) { 1252 error = sooptcopyin(sopt, &mreqs, 1253 sizeof(struct ip_mreq), 1254 sizeof(struct ip_mreq)); 1255 /* 1256 * Swap interface and sourceaddr arguments, 1257 * as ip_mreq and ip_mreq_source are laid 1258 * out differently. 1259 */ 1260 mreqs.imr_interface = mreqs.imr_sourceaddr; 1261 mreqs.imr_sourceaddr.s_addr = INADDR_ANY; 1262 } else if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { 1263 error = sooptcopyin(sopt, &mreqs, 1264 sizeof(struct ip_mreq_source), 1265 sizeof(struct ip_mreq_source)); 1266 } 1267 if (error) 1268 return (error); 1269 1270 gsa->sin.sin_family = AF_INET; 1271 gsa->sin.sin_len = sizeof(struct sockaddr_in); 1272 gsa->sin.sin_addr = mreqs.imr_multiaddr; 1273 1274 if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { 1275 ssa->sin.sin_family = AF_INET; 1276 ssa->sin.sin_len = sizeof(struct sockaddr_in); 1277 ssa->sin.sin_addr = mreqs.imr_sourceaddr; 1278 } 1279 1280 if (gsa->sin.sin_addr.s_addr != INADDR_ANY) 1281 INADDR_TO_IFP(mreqs.imr_interface, ifp); 1282 1283 #ifdef DIAGNOSTIC 1284 if (bootverbose) { 1285 printf("%s: imr_interface = %s, ifp = %p\n", 1286 __func__, inet_ntoa(mreqs.imr_interface), ifp); 1287 } 1288 #endif 1289 break; 1290 1291 case MCAST_LEAVE_GROUP: 1292 case MCAST_LEAVE_SOURCE_GROUP: 1293 if (sopt->sopt_name == MCAST_LEAVE_GROUP) { 1294 error = sooptcopyin(sopt, &gsr, 1295 sizeof(struct group_req), 1296 sizeof(struct group_req)); 1297 } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 1298 error = sooptcopyin(sopt, &gsr, 1299 sizeof(struct group_source_req), 1300 sizeof(struct group_source_req)); 1301 } 1302 if (error) 1303 return (error); 1304 1305 if (gsa->sin.sin_family != AF_INET || 1306 gsa->sin.sin_len != sizeof(struct sockaddr_in)) 1307 return (EINVAL); 1308 1309 if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { 1310 if (ssa->sin.sin_family != AF_INET || 1311 ssa->sin.sin_len != sizeof(struct sockaddr_in)) 1312 return (EINVAL); 1313 } 1314 1315 if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) 1316 return (EADDRNOTAVAIL); 1317 1318 ifp = ifnet_byindex(gsr.gsr_interface); 1319 break; 1320 1321 default: 1322 #ifdef DIAGNOSTIC 1323 if (bootverbose) { 1324 printf("%s: unknown sopt_name %d\n", __func__, 1325 sopt->sopt_name); 1326 } 1327 #endif 1328 return (EOPNOTSUPP); 1329 break; 1330 } 1331 1332 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1333 return (EINVAL); 1334 1335 /* 1336 * Find the membership in the membership array. 1337 */ 1338 imo = inp_findmoptions(inp); 1339 idx = imo_match_group(imo, ifp, &gsa->sa); 1340 if (idx == -1) { 1341 error = EADDRNOTAVAIL; 1342 goto out_locked; 1343 } 1344 imf = &imo->imo_mfilters[idx]; 1345 1346 /* 1347 * If we were instructed only to leave a given source, do so. 1348 */ 1349 if (ssa->ss.ss_family != AF_UNSPEC) { 1350 if (imf->imf_nsources == 0 || 1351 imf->imf_fmode == MCAST_EXCLUDE) { 1352 /* 1353 * Attempting to SSM leave an ASM group 1354 * is an error; should use *_BLOCK_SOURCE instead. 1355 * Attempting to SSM leave a source in a group when 1356 * the socket is in 'exclude mode' is also an error. 1357 */ 1358 error = EINVAL; 1359 } else { 1360 error = imo_leave_source(imo, idx, ssa); 1361 } 1362 /* 1363 * If an error occurred, or this source is not the last 1364 * source in the group, do not leave the whole group. 1365 */ 1366 if (error || imf->imf_nsources > 0) 1367 goto out_locked; 1368 } 1369 1370 /* 1371 * Give up the multicast address record to which the membership points. 1372 */ 1373 inm = imo->imo_membership[idx]; 1374 in_delmulti(inm); 1375 1376 /* 1377 * Free any source filters for this group if they exist. 1378 * Revert inpcb to the default MCAST_EXCLUDE state. 1379 */ 1380 if (imo->imo_mfilters != NULL) { 1381 TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) { 1382 TAILQ_REMOVE(&imf->imf_sources, ims, ims_next); 1383 free(ims, M_IPMSOURCE); 1384 imf->imf_nsources--; 1385 } 1386 KASSERT(imf->imf_nsources == 0, 1387 ("%s: imf_nsources not 0", __func__)); 1388 KASSERT(TAILQ_EMPTY(&imf->imf_sources), 1389 ("%s: imf_sources not empty", __func__)); 1390 imf->imf_fmode = MCAST_EXCLUDE; 1391 } 1392 1393 /* 1394 * Remove the gap in the membership array. 1395 */ 1396 for (++idx; idx < imo->imo_num_memberships; ++idx) 1397 imo->imo_membership[idx-1] = imo->imo_membership[idx]; 1398 imo->imo_num_memberships--; 1399 1400 out_locked: 1401 INP_WUNLOCK(inp); 1402 return (error); 1403 } 1404 1405 /* 1406 * Select the interface for transmitting IPv4 multicast datagrams. 1407 * 1408 * Either an instance of struct in_addr or an instance of struct ip_mreqn 1409 * may be passed to this socket option. An address of INADDR_ANY or an 1410 * interface index of 0 is used to remove a previous selection. 1411 * When no interface is selected, one is chosen for every send. 1412 */ 1413 static int 1414 inp_set_multicast_if(struct inpcb *inp, struct sockopt *sopt) 1415 { 1416 INIT_VNET_NET(curvnet); 1417 struct in_addr addr; 1418 struct ip_mreqn mreqn; 1419 struct ifnet *ifp; 1420 struct ip_moptions *imo; 1421 int error; 1422 1423 if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) { 1424 /* 1425 * An interface index was specified using the 1426 * Linux-derived ip_mreqn structure. 1427 */ 1428 error = sooptcopyin(sopt, &mreqn, sizeof(struct ip_mreqn), 1429 sizeof(struct ip_mreqn)); 1430 if (error) 1431 return (error); 1432 1433 if (mreqn.imr_ifindex < 0 || V_if_index < mreqn.imr_ifindex) 1434 return (EINVAL); 1435 1436 if (mreqn.imr_ifindex == 0) { 1437 ifp = NULL; 1438 } else { 1439 ifp = ifnet_byindex(mreqn.imr_ifindex); 1440 if (ifp == NULL) 1441 return (EADDRNOTAVAIL); 1442 } 1443 } else { 1444 /* 1445 * An interface was specified by IPv4 address. 1446 * This is the traditional BSD usage. 1447 */ 1448 error = sooptcopyin(sopt, &addr, sizeof(struct in_addr), 1449 sizeof(struct in_addr)); 1450 if (error) 1451 return (error); 1452 if (addr.s_addr == INADDR_ANY) { 1453 ifp = NULL; 1454 } else { 1455 INADDR_TO_IFP(addr, ifp); 1456 if (ifp == NULL) 1457 return (EADDRNOTAVAIL); 1458 } 1459 #ifdef DIAGNOSTIC 1460 if (bootverbose) { 1461 printf("%s: ifp = %p, addr = %s\n", 1462 __func__, ifp, inet_ntoa(addr)); /* XXX INET6 */ 1463 } 1464 #endif 1465 } 1466 1467 /* Reject interfaces which do not support multicast. */ 1468 if (ifp != NULL && (ifp->if_flags & IFF_MULTICAST) == 0) 1469 return (EOPNOTSUPP); 1470 1471 imo = inp_findmoptions(inp); 1472 imo->imo_multicast_ifp = ifp; 1473 imo->imo_multicast_addr.s_addr = INADDR_ANY; 1474 INP_WUNLOCK(inp); 1475 1476 return (0); 1477 } 1478 1479 /* 1480 * Atomically set source filters on a socket for an IPv4 multicast group. 1481 */ 1482 static int 1483 inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt) 1484 { 1485 INIT_VNET_NET(curvnet); 1486 struct __msfilterreq msfr; 1487 sockunion_t *gsa; 1488 struct ifnet *ifp; 1489 struct in_mfilter *imf; 1490 struct ip_moptions *imo; 1491 struct in_msource *ims, *tims; 1492 size_t idx; 1493 int error; 1494 1495 error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq), 1496 sizeof(struct __msfilterreq)); 1497 if (error) 1498 return (error); 1499 1500 if (msfr.msfr_nsrcs > IP_MAX_SOURCE_FILTER || 1501 (msfr.msfr_fmode != MCAST_EXCLUDE && 1502 msfr.msfr_fmode != MCAST_INCLUDE)) 1503 return (EINVAL); 1504 1505 if (msfr.msfr_group.ss_family != AF_INET || 1506 msfr.msfr_group.ss_len != sizeof(struct sockaddr_in)) 1507 return (EINVAL); 1508 1509 gsa = (sockunion_t *)&msfr.msfr_group; 1510 if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) 1511 return (EINVAL); 1512 1513 gsa->sin.sin_port = 0; /* ignore port */ 1514 1515 if (msfr.msfr_ifindex == 0 || V_if_index < msfr.msfr_ifindex) 1516 return (EADDRNOTAVAIL); 1517 1518 ifp = ifnet_byindex(msfr.msfr_ifindex); 1519 if (ifp == NULL) 1520 return (EADDRNOTAVAIL); 1521 1522 /* 1523 * Take the INP lock. 1524 * Check if this socket is a member of this group. 1525 */ 1526 imo = inp_findmoptions(inp); 1527 idx = imo_match_group(imo, ifp, &gsa->sa); 1528 if (idx == -1 || imo->imo_mfilters == NULL) { 1529 error = EADDRNOTAVAIL; 1530 goto out_locked; 1531 } 1532 imf = &imo->imo_mfilters[idx]; 1533 1534 #ifdef DIAGNOSTIC 1535 if (bootverbose) 1536 printf("%s: clearing source list\n", __func__); 1537 #endif 1538 1539 /* 1540 * Remove any existing source filters. 1541 */ 1542 TAILQ_FOREACH_SAFE(ims, &imf->imf_sources, ims_next, tims) { 1543 TAILQ_REMOVE(&imf->imf_sources, ims, ims_next); 1544 free(ims, M_IPMSOURCE); 1545 imf->imf_nsources--; 1546 } 1547 KASSERT(imf->imf_nsources == 0, 1548 ("%s: source list not cleared", __func__)); 1549 1550 /* 1551 * Apply any new source filters, if present. 1552 */ 1553 if (msfr.msfr_nsrcs > 0) { 1554 struct in_msource **pnims; 1555 struct in_msource *nims; 1556 struct sockaddr_storage *kss; 1557 struct sockaddr_storage *pkss; 1558 sockunion_t *psu; 1559 int i, j; 1560 1561 /* 1562 * Drop the inp lock so we may sleep if we need to 1563 * in order to satisfy a malloc request. 1564 * We will re-take it before changing socket state. 1565 */ 1566 INP_WUNLOCK(inp); 1567 #ifdef DIAGNOSTIC 1568 if (bootverbose) { 1569 printf("%s: loading %lu source list entries\n", 1570 __func__, (unsigned long)msfr.msfr_nsrcs); 1571 } 1572 #endif 1573 /* 1574 * Make a copy of the user-space source vector so 1575 * that we may copy them with a single copyin. This 1576 * allows us to deal with page faults up-front. 1577 */ 1578 kss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, 1579 M_TEMP, M_WAITOK); 1580 error = copyin(msfr.msfr_srcs, kss, 1581 sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs); 1582 if (error) { 1583 free(kss, M_TEMP); 1584 return (error); 1585 } 1586 1587 /* 1588 * Perform argument checking on every sockaddr_storage 1589 * structure in the vector provided to us. Overwrite 1590 * fields which should not apply to source entries. 1591 * TODO: Check for duplicate sources on this pass. 1592 */ 1593 psu = (sockunion_t *)kss; 1594 for (i = 0; i < msfr.msfr_nsrcs; i++, psu++) { 1595 switch (psu->ss.ss_family) { 1596 case AF_INET: 1597 if (psu->sin.sin_len != 1598 sizeof(struct sockaddr_in)) { 1599 error = EINVAL; 1600 } else { 1601 psu->sin.sin_port = 0; 1602 } 1603 break; 1604 #ifdef notyet 1605 case AF_INET6; 1606 if (psu->sin6.sin6_len != 1607 sizeof(struct sockaddr_in6)) { 1608 error = EINVAL; 1609 } else { 1610 psu->sin6.sin6_port = 0; 1611 psu->sin6.sin6_flowinfo = 0; 1612 } 1613 break; 1614 #endif 1615 default: 1616 error = EAFNOSUPPORT; 1617 break; 1618 } 1619 if (error) 1620 break; 1621 } 1622 if (error) { 1623 free(kss, M_TEMP); 1624 return (error); 1625 } 1626 1627 /* 1628 * Allocate a block to track all the in_msource 1629 * entries we are about to allocate, in case we 1630 * abruptly need to free them. 1631 */ 1632 pnims = malloc(sizeof(struct in_msource *) * msfr.msfr_nsrcs, 1633 M_TEMP, M_WAITOK | M_ZERO); 1634 1635 /* 1636 * Allocate up to nsrcs individual chunks. 1637 * If we encounter an error, backtrack out of 1638 * all allocations cleanly; updates must be atomic. 1639 */ 1640 pkss = kss; 1641 nims = NULL; 1642 for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) { 1643 nims = malloc(sizeof(struct in_msource) * 1644 msfr.msfr_nsrcs, M_IPMSOURCE, M_WAITOK | M_ZERO); 1645 pnims[i] = nims; 1646 } 1647 if (i < msfr.msfr_nsrcs) { 1648 for (j = 0; j < i; j++) { 1649 if (pnims[j] != NULL) 1650 free(pnims[j], M_IPMSOURCE); 1651 } 1652 free(pnims, M_TEMP); 1653 free(kss, M_TEMP); 1654 return (ENOBUFS); 1655 } 1656 1657 INP_UNLOCK_ASSERT(inp); 1658 1659 /* 1660 * Finally, apply the filters to the socket. 1661 * Re-take the inp lock; we are changing socket state. 1662 */ 1663 pkss = kss; 1664 INP_WLOCK(inp); 1665 for (i = 0; i < msfr.msfr_nsrcs; i++, pkss++) { 1666 memcpy(&(pnims[i]->ims_addr), pkss, 1667 sizeof(struct sockaddr_storage)); 1668 TAILQ_INSERT_TAIL(&imf->imf_sources, pnims[i], 1669 ims_next); 1670 imf->imf_nsources++; 1671 } 1672 free(pnims, M_TEMP); 1673 free(kss, M_TEMP); 1674 } 1675 1676 /* 1677 * Update the filter mode on the socket before releasing the inpcb. 1678 */ 1679 INP_WLOCK_ASSERT(inp); 1680 imf->imf_fmode = msfr.msfr_fmode; 1681 1682 out_locked: 1683 INP_WUNLOCK(inp); 1684 return (error); 1685 } 1686 1687 /* 1688 * Set the IP multicast options in response to user setsockopt(). 1689 * 1690 * Many of the socket options handled in this function duplicate the 1691 * functionality of socket options in the regular unicast API. However, 1692 * it is not possible to merge the duplicate code, because the idempotence 1693 * of the IPv4 multicast part of the BSD Sockets API must be preserved; 1694 * the effects of these options must be treated as separate and distinct. 1695 */ 1696 int 1697 inp_setmoptions(struct inpcb *inp, struct sockopt *sopt) 1698 { 1699 struct ip_moptions *imo; 1700 int error; 1701 1702 error = 0; 1703 1704 /* 1705 * If socket is neither of type SOCK_RAW or SOCK_DGRAM, 1706 * or is a divert socket, reject it. 1707 * XXX Unlocked read of inp_socket believed OK. 1708 */ 1709 if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT || 1710 (inp->inp_socket->so_proto->pr_type != SOCK_RAW && 1711 inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) 1712 return (EOPNOTSUPP); 1713 1714 switch (sopt->sopt_name) { 1715 case IP_MULTICAST_VIF: { 1716 int vifi; 1717 /* 1718 * Select a multicast VIF for transmission. 1719 * Only useful if multicast forwarding is active. 1720 */ 1721 if (legal_vif_num == NULL) { 1722 error = EOPNOTSUPP; 1723 break; 1724 } 1725 error = sooptcopyin(sopt, &vifi, sizeof(int), sizeof(int)); 1726 if (error) 1727 break; 1728 if (!legal_vif_num(vifi) && (vifi != -1)) { 1729 error = EINVAL; 1730 break; 1731 } 1732 imo = inp_findmoptions(inp); 1733 imo->imo_multicast_vif = vifi; 1734 INP_WUNLOCK(inp); 1735 break; 1736 } 1737 1738 case IP_MULTICAST_IF: 1739 error = inp_set_multicast_if(inp, sopt); 1740 break; 1741 1742 case IP_MULTICAST_TTL: { 1743 u_char ttl; 1744 1745 /* 1746 * Set the IP time-to-live for outgoing multicast packets. 1747 * The original multicast API required a char argument, 1748 * which is inconsistent with the rest of the socket API. 1749 * We allow either a char or an int. 1750 */ 1751 if (sopt->sopt_valsize == sizeof(u_char)) { 1752 error = sooptcopyin(sopt, &ttl, sizeof(u_char), 1753 sizeof(u_char)); 1754 if (error) 1755 break; 1756 } else { 1757 u_int ittl; 1758 1759 error = sooptcopyin(sopt, &ittl, sizeof(u_int), 1760 sizeof(u_int)); 1761 if (error) 1762 break; 1763 if (ittl > 255) { 1764 error = EINVAL; 1765 break; 1766 } 1767 ttl = (u_char)ittl; 1768 } 1769 imo = inp_findmoptions(inp); 1770 imo->imo_multicast_ttl = ttl; 1771 INP_WUNLOCK(inp); 1772 break; 1773 } 1774 1775 case IP_MULTICAST_LOOP: { 1776 u_char loop; 1777 1778 /* 1779 * Set the loopback flag for outgoing multicast packets. 1780 * Must be zero or one. The original multicast API required a 1781 * char argument, which is inconsistent with the rest 1782 * of the socket API. We allow either a char or an int. 1783 */ 1784 if (sopt->sopt_valsize == sizeof(u_char)) { 1785 error = sooptcopyin(sopt, &loop, sizeof(u_char), 1786 sizeof(u_char)); 1787 if (error) 1788 break; 1789 } else { 1790 u_int iloop; 1791 1792 error = sooptcopyin(sopt, &iloop, sizeof(u_int), 1793 sizeof(u_int)); 1794 if (error) 1795 break; 1796 loop = (u_char)iloop; 1797 } 1798 imo = inp_findmoptions(inp); 1799 imo->imo_multicast_loop = !!loop; 1800 INP_WUNLOCK(inp); 1801 break; 1802 } 1803 1804 case IP_ADD_MEMBERSHIP: 1805 case IP_ADD_SOURCE_MEMBERSHIP: 1806 case MCAST_JOIN_GROUP: 1807 case MCAST_JOIN_SOURCE_GROUP: 1808 error = inp_join_group(inp, sopt); 1809 break; 1810 1811 case IP_DROP_MEMBERSHIP: 1812 case IP_DROP_SOURCE_MEMBERSHIP: 1813 case MCAST_LEAVE_GROUP: 1814 case MCAST_LEAVE_SOURCE_GROUP: 1815 error = inp_leave_group(inp, sopt); 1816 break; 1817 1818 case IP_BLOCK_SOURCE: 1819 case IP_UNBLOCK_SOURCE: 1820 case MCAST_BLOCK_SOURCE: 1821 case MCAST_UNBLOCK_SOURCE: 1822 error = inp_change_source_filter(inp, sopt); 1823 break; 1824 1825 case IP_MSFILTER: 1826 error = inp_set_source_filters(inp, sopt); 1827 break; 1828 1829 default: 1830 error = EOPNOTSUPP; 1831 break; 1832 } 1833 1834 INP_UNLOCK_ASSERT(inp); 1835 1836 return (error); 1837 } 1838