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