1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* Copyright (c) 1990 Mentat Inc. */ 26 27 #include <sys/types.h> 28 #include <sys/stream.h> 29 #include <sys/dlpi.h> 30 #include <sys/stropts.h> 31 #include <sys/strsun.h> 32 #include <sys/ddi.h> 33 #include <sys/cmn_err.h> 34 #include <sys/sdt.h> 35 #include <sys/zone.h> 36 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 #include <sys/sockio.h> 40 #include <net/if.h> 41 #include <sys/systm.h> 42 #include <sys/strsubr.h> 43 #include <net/route.h> 44 #include <netinet/in.h> 45 #include <net/if_dl.h> 46 #include <netinet/ip6.h> 47 #include <netinet/icmp6.h> 48 49 #include <inet/common.h> 50 #include <inet/mi.h> 51 #include <inet/nd.h> 52 #include <inet/arp.h> 53 #include <inet/ip.h> 54 #include <inet/ip6.h> 55 #include <inet/ip_if.h> 56 #include <inet/ip_ndp.h> 57 #include <inet/ip_multi.h> 58 #include <inet/ipclassifier.h> 59 #include <inet/ipsec_impl.h> 60 #include <inet/sctp_ip.h> 61 #include <inet/ip_listutils.h> 62 #include <inet/udp_impl.h> 63 64 /* igmpv3/mldv2 source filter manipulation */ 65 static void ilm_bld_flists(conn_t *conn, void *arg); 66 static void ilm_gen_filter(ilm_t *ilm, mcast_record_t *fmode, 67 slist_t *flist); 68 69 static ilm_t *ilm_add(ill_t *ill, const in6_addr_t *group, 70 ilg_stat_t ilgstat, mcast_record_t ilg_fmode, slist_t *ilg_flist, 71 zoneid_t zoneid); 72 static void ilm_delete(ilm_t *ilm); 73 static int ilm_numentries(ill_t *, const in6_addr_t *); 74 75 static ilm_t *ip_addmulti_serial(const in6_addr_t *, ill_t *, zoneid_t, 76 ilg_stat_t, mcast_record_t, slist_t *, int *); 77 static ilm_t *ip_addmulti_impl(const in6_addr_t *, ill_t *, 78 zoneid_t, ilg_stat_t, mcast_record_t, slist_t *, int *); 79 static int ip_delmulti_serial(ilm_t *, boolean_t, boolean_t); 80 static int ip_delmulti_impl(ilm_t *, boolean_t, boolean_t); 81 82 static int ip_ll_multireq(ill_t *ill, const in6_addr_t *group, 83 t_uscalar_t); 84 static ilg_t *ilg_lookup(conn_t *, const in6_addr_t *, ipaddr_t ifaddr, 85 uint_t ifindex); 86 87 static int ilg_add(conn_t *connp, const in6_addr_t *group, 88 ipaddr_t ifaddr, uint_t ifindex, ill_t *ill, mcast_record_t fmode, 89 const in6_addr_t *v6src); 90 static void ilg_delete(conn_t *connp, ilg_t *ilg, const in6_addr_t *src); 91 static mblk_t *ill_create_dl(ill_t *ill, uint32_t dl_primitive, 92 uint32_t *addr_lenp, uint32_t *addr_offp); 93 static int ip_opt_delete_group_excl(conn_t *connp, 94 const in6_addr_t *v6group, ipaddr_t ifaddr, uint_t ifindex, 95 mcast_record_t fmode, const in6_addr_t *v6src); 96 97 static ilm_t *ilm_lookup(ill_t *, const in6_addr_t *, zoneid_t); 98 99 static int ip_msfilter_ill(conn_t *, mblk_t *, const ip_ioctl_cmd_t *, 100 ill_t **); 101 102 static void ilg_check_detach(conn_t *, ill_t *); 103 static void ilg_check_reattach(conn_t *); 104 105 /* 106 * MT notes: 107 * 108 * Multicast joins operate on both the ilg and ilm structures. Multiple 109 * threads operating on an conn (socket) trying to do multicast joins 110 * need to synchronize when operating on the ilg. Multiple threads 111 * potentially operating on different conn (socket endpoints) trying to 112 * do multicast joins could eventually end up trying to manipulate the 113 * ilm simulatenously and need to synchronize on the access to the ilm. 114 * The access and lookup of the ilm, as well as other ill multicast state, 115 * is under ill_mcast_lock. 116 * The modifications and lookup of ilg entries is serialized using conn_ilg_lock 117 * rwlock. An ilg will not be freed until ilg_refcnt drops to zero. 118 * 119 * In some cases we hold ill_mcast_lock and then acquire conn_ilg_lock, but 120 * never the other way around. 121 * 122 * An ilm is an IP data structure used to track multicast join/leave. 123 * An ilm is associated with a <multicast group, ipif> tuple in IPv4 and 124 * with just <multicast group> in IPv6. ilm_refcnt is the number of ilg's 125 * referencing the ilm. 126 * The modifications and lookup of ilm entries is serialized using the 127 * ill_mcast_lock rwlock; that lock handles all the igmp/mld modifications 128 * of the ilm state. 129 * ilms are created / destroyed only as writer. ilms 130 * are not passed around. The datapath (anything outside of this file 131 * and igmp.c) use functions that do not return ilms - just the number 132 * of members. So we don't need a dynamic refcount of the number 133 * of threads holding reference to an ilm. 134 * 135 * In the cases where we serially access the ilg and ilm, which happens when 136 * we handle the applications requests to join or leave groups and sources, 137 * we use the ill_mcast_serializer mutex to ensure that a multithreaded 138 * application which does concurrent joins and/or leaves on the same group on 139 * the same socket always results in a consistent order for the ilg and ilm 140 * modifications. 141 * 142 * When a multicast operation results in needing to send a message to 143 * the driver (to join/leave a L2 multicast address), we use ill_dlpi_queue() 144 * which serialized the DLPI requests. The IGMP/MLD code uses ill_mcast_queue() 145 * to send IGMP/MLD IP packet to avoid dropping the lock just to send a packet. 146 */ 147 148 #define GETSTRUCT(structure, number) \ 149 ((structure *)mi_zalloc(sizeof (structure) * (number))) 150 151 /* 152 * Caller must ensure that the ilg has not been condemned 153 * The condemned flag is only set in ilg_delete under conn_ilg_lock. 154 * 155 * The caller must hold conn_ilg_lock as writer. 156 */ 157 static void 158 ilg_refhold(ilg_t *ilg) 159 { 160 ASSERT(ilg->ilg_refcnt != 0); 161 ASSERT(!ilg->ilg_condemned); 162 ASSERT(RW_WRITE_HELD(&ilg->ilg_connp->conn_ilg_lock)); 163 164 ilg->ilg_refcnt++; 165 } 166 167 static void 168 ilg_inactive(ilg_t *ilg) 169 { 170 ASSERT(ilg->ilg_ill == NULL); 171 ASSERT(ilg->ilg_ilm == NULL); 172 ASSERT(ilg->ilg_filter == NULL); 173 ASSERT(ilg->ilg_condemned); 174 175 /* Unlink from list */ 176 *ilg->ilg_ptpn = ilg->ilg_next; 177 if (ilg->ilg_next != NULL) 178 ilg->ilg_next->ilg_ptpn = ilg->ilg_ptpn; 179 ilg->ilg_next = NULL; 180 ilg->ilg_ptpn = NULL; 181 182 ilg->ilg_connp = NULL; 183 kmem_free(ilg, sizeof (*ilg)); 184 } 185 186 /* 187 * The caller must hold conn_ilg_lock as writer. 188 */ 189 static void 190 ilg_refrele(ilg_t *ilg) 191 { 192 ASSERT(RW_WRITE_HELD(&ilg->ilg_connp->conn_ilg_lock)); 193 ASSERT(ilg->ilg_refcnt != 0); 194 if (--ilg->ilg_refcnt == 0) 195 ilg_inactive(ilg); 196 } 197 198 /* 199 * Acquire reference on ilg and drop reference on held_ilg. 200 * In the case when held_ilg is the same as ilg we already have 201 * a reference, but the held_ilg might be condemned. In that case 202 * we avoid the ilg_refhold/rele so that we can assert in ire_refhold 203 * that the ilg isn't condemned. 204 */ 205 static void 206 ilg_transfer_hold(ilg_t *held_ilg, ilg_t *ilg) 207 { 208 if (held_ilg == ilg) 209 return; 210 211 ilg_refhold(ilg); 212 if (held_ilg != NULL) 213 ilg_refrele(held_ilg); 214 } 215 216 /* 217 * Allocate a new ilg_t and links it into conn_ilg. 218 * Returns NULL on failure, in which case `*errp' will be 219 * filled in with the reason. 220 * 221 * Assumes connp->conn_ilg_lock is held. 222 */ 223 static ilg_t * 224 conn_ilg_alloc(conn_t *connp, int *errp) 225 { 226 ilg_t *ilg; 227 228 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 229 230 /* 231 * If CONN_CLOSING is set, conn_ilg cleanup has begun and we must not 232 * create any ilgs. 233 */ 234 if (connp->conn_state_flags & CONN_CLOSING) { 235 *errp = EINVAL; 236 return (NULL); 237 } 238 239 ilg = kmem_zalloc(sizeof (ilg_t), KM_NOSLEEP); 240 if (ilg == NULL) { 241 *errp = ENOMEM; 242 return (NULL); 243 } 244 245 ilg->ilg_refcnt = 1; 246 247 /* Insert at head */ 248 if (connp->conn_ilg != NULL) 249 connp->conn_ilg->ilg_ptpn = &ilg->ilg_next; 250 ilg->ilg_next = connp->conn_ilg; 251 ilg->ilg_ptpn = &connp->conn_ilg; 252 connp->conn_ilg = ilg; 253 254 ilg->ilg_connp = connp; 255 return (ilg); 256 } 257 258 typedef struct ilm_fbld_s { 259 ilm_t *fbld_ilm; 260 int fbld_in_cnt; 261 int fbld_ex_cnt; 262 slist_t fbld_in; 263 slist_t fbld_ex; 264 boolean_t fbld_in_overflow; 265 } ilm_fbld_t; 266 267 /* 268 * Caller must hold ill_mcast_lock 269 */ 270 static void 271 ilm_bld_flists(conn_t *connp, void *arg) 272 { 273 ilg_t *ilg; 274 ilm_fbld_t *fbld = (ilm_fbld_t *)(arg); 275 ilm_t *ilm = fbld->fbld_ilm; 276 in6_addr_t *v6group = &ilm->ilm_v6addr; 277 278 if (connp->conn_ilg == NULL) 279 return; 280 281 /* 282 * Since we can't break out of the ipcl_walk once started, we still 283 * have to look at every conn. But if we've already found one 284 * (EXCLUDE, NULL) list, there's no need to keep checking individual 285 * ilgs--that will be our state. 286 */ 287 if (fbld->fbld_ex_cnt > 0 && fbld->fbld_ex.sl_numsrc == 0) 288 return; 289 290 /* 291 * Check this conn's ilgs to see if any are interested in our 292 * ilm (group, interface match). If so, update the master 293 * include and exclude lists we're building in the fbld struct 294 * with this ilg's filter info. 295 * 296 * Note that the caller has already serialized on the ill we care 297 * about. 298 */ 299 ASSERT(MUTEX_HELD(&ilm->ilm_ill->ill_mcast_serializer)); 300 301 rw_enter(&connp->conn_ilg_lock, RW_READER); 302 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 303 if (ilg->ilg_condemned) 304 continue; 305 306 /* 307 * Since we are under the ill_mcast_serializer we know 308 * that any ilg+ilm operations on this ilm have either 309 * not started or completed, except for the last ilg 310 * (the one that caused us to be called) which doesn't 311 * have ilg_ilm set yet. Hence we compare using ilg_ill 312 * and the address. 313 */ 314 if ((ilg->ilg_ill == ilm->ilm_ill) && 315 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) { 316 if (ilg->ilg_fmode == MODE_IS_INCLUDE) { 317 fbld->fbld_in_cnt++; 318 if (!fbld->fbld_in_overflow) 319 l_union_in_a(&fbld->fbld_in, 320 ilg->ilg_filter, 321 &fbld->fbld_in_overflow); 322 } else { 323 fbld->fbld_ex_cnt++; 324 /* 325 * On the first exclude list, don't try to do 326 * an intersection, as the master exclude list 327 * is intentionally empty. If the master list 328 * is still empty on later iterations, that 329 * means we have at least one ilg with an empty 330 * exclude list, so that should be reflected 331 * when we take the intersection. 332 */ 333 if (fbld->fbld_ex_cnt == 1) { 334 if (ilg->ilg_filter != NULL) 335 l_copy(ilg->ilg_filter, 336 &fbld->fbld_ex); 337 } else { 338 l_intersection_in_a(&fbld->fbld_ex, 339 ilg->ilg_filter); 340 } 341 } 342 /* there will only be one match, so break now. */ 343 break; 344 } 345 } 346 rw_exit(&connp->conn_ilg_lock); 347 } 348 349 /* 350 * Caller must hold ill_mcast_lock 351 */ 352 static void 353 ilm_gen_filter(ilm_t *ilm, mcast_record_t *fmode, slist_t *flist) 354 { 355 ilm_fbld_t fbld; 356 ip_stack_t *ipst = ilm->ilm_ipst; 357 358 fbld.fbld_ilm = ilm; 359 fbld.fbld_in_cnt = fbld.fbld_ex_cnt = 0; 360 fbld.fbld_in.sl_numsrc = fbld.fbld_ex.sl_numsrc = 0; 361 fbld.fbld_in_overflow = B_FALSE; 362 363 /* first, construct our master include and exclude lists */ 364 ipcl_walk(ilm_bld_flists, (caddr_t)&fbld, ipst); 365 366 /* now use those master lists to generate the interface filter */ 367 368 /* if include list overflowed, filter is (EXCLUDE, NULL) */ 369 if (fbld.fbld_in_overflow) { 370 *fmode = MODE_IS_EXCLUDE; 371 flist->sl_numsrc = 0; 372 return; 373 } 374 375 /* if nobody interested, interface filter is (INCLUDE, NULL) */ 376 if (fbld.fbld_in_cnt == 0 && fbld.fbld_ex_cnt == 0) { 377 *fmode = MODE_IS_INCLUDE; 378 flist->sl_numsrc = 0; 379 return; 380 } 381 382 /* 383 * If there are no exclude lists, then the interface filter 384 * is INCLUDE, with its filter list equal to fbld_in. A single 385 * exclude list makes the interface filter EXCLUDE, with its 386 * filter list equal to (fbld_ex - fbld_in). 387 */ 388 if (fbld.fbld_ex_cnt == 0) { 389 *fmode = MODE_IS_INCLUDE; 390 l_copy(&fbld.fbld_in, flist); 391 } else { 392 *fmode = MODE_IS_EXCLUDE; 393 l_difference(&fbld.fbld_ex, &fbld.fbld_in, flist); 394 } 395 } 396 397 /* 398 * Caller must hold ill_mcast_lock 399 */ 400 static int 401 ilm_update_add(ilm_t *ilm, ilg_stat_t ilgstat, slist_t *ilg_flist) 402 { 403 mcast_record_t fmode; 404 slist_t *flist; 405 boolean_t fdefault; 406 char buf[INET6_ADDRSTRLEN]; 407 ill_t *ill = ilm->ilm_ill; 408 409 /* 410 * There are several cases where the ilm's filter state 411 * defaults to (EXCLUDE, NULL): 412 * - we've had previous joins without associated ilgs 413 * - this join has no associated ilg 414 * - the ilg's filter state is (EXCLUDE, NULL) 415 */ 416 fdefault = (ilm->ilm_no_ilg_cnt > 0) || 417 (ilgstat == ILGSTAT_NONE) || SLIST_IS_EMPTY(ilg_flist); 418 419 /* attempt mallocs (if needed) before doing anything else */ 420 if ((flist = l_alloc()) == NULL) 421 return (ENOMEM); 422 if (!fdefault && ilm->ilm_filter == NULL) { 423 ilm->ilm_filter = l_alloc(); 424 if (ilm->ilm_filter == NULL) { 425 l_free(flist); 426 return (ENOMEM); 427 } 428 } 429 430 if (ilgstat != ILGSTAT_CHANGE) 431 ilm->ilm_refcnt++; 432 433 if (ilgstat == ILGSTAT_NONE) 434 ilm->ilm_no_ilg_cnt++; 435 436 /* 437 * Determine new filter state. If it's not the default 438 * (EXCLUDE, NULL), we must walk the conn list to find 439 * any ilgs interested in this group, and re-build the 440 * ilm filter. 441 */ 442 if (fdefault) { 443 fmode = MODE_IS_EXCLUDE; 444 flist->sl_numsrc = 0; 445 } else { 446 ilm_gen_filter(ilm, &fmode, flist); 447 } 448 449 /* make sure state actually changed; nothing to do if not. */ 450 if ((ilm->ilm_fmode == fmode) && 451 !lists_are_different(ilm->ilm_filter, flist)) { 452 l_free(flist); 453 return (0); 454 } 455 456 /* send the state change report */ 457 if (!IS_LOOPBACK(ill)) { 458 if (ill->ill_isv6) 459 mld_statechange(ilm, fmode, flist); 460 else 461 igmp_statechange(ilm, fmode, flist); 462 } 463 464 /* update the ilm state */ 465 ilm->ilm_fmode = fmode; 466 if (flist->sl_numsrc > 0) 467 l_copy(flist, ilm->ilm_filter); 468 else 469 CLEAR_SLIST(ilm->ilm_filter); 470 471 ip1dbg(("ilm_update: new if filter mode %d, group %s\n", ilm->ilm_fmode, 472 inet_ntop(AF_INET6, &ilm->ilm_v6addr, buf, sizeof (buf)))); 473 474 l_free(flist); 475 return (0); 476 } 477 478 /* 479 * Caller must hold ill_mcast_lock 480 */ 481 static int 482 ilm_update_del(ilm_t *ilm) 483 { 484 mcast_record_t fmode; 485 slist_t *flist; 486 ill_t *ill = ilm->ilm_ill; 487 488 ip1dbg(("ilm_update_del: still %d left; updating state\n", 489 ilm->ilm_refcnt)); 490 491 if ((flist = l_alloc()) == NULL) 492 return (ENOMEM); 493 494 /* 495 * If present, the ilg in question has already either been 496 * updated or removed from our list; so all we need to do 497 * now is walk the list to update the ilm filter state. 498 * 499 * Skip the list walk if we have any no-ilg joins, which 500 * cause the filter state to revert to (EXCLUDE, NULL). 501 */ 502 if (ilm->ilm_no_ilg_cnt != 0) { 503 fmode = MODE_IS_EXCLUDE; 504 flist->sl_numsrc = 0; 505 } else { 506 ilm_gen_filter(ilm, &fmode, flist); 507 } 508 509 /* check to see if state needs to be updated */ 510 if ((ilm->ilm_fmode == fmode) && 511 (!lists_are_different(ilm->ilm_filter, flist))) { 512 l_free(flist); 513 return (0); 514 } 515 516 if (!IS_LOOPBACK(ill)) { 517 if (ill->ill_isv6) 518 mld_statechange(ilm, fmode, flist); 519 else 520 igmp_statechange(ilm, fmode, flist); 521 } 522 523 ilm->ilm_fmode = fmode; 524 if (flist->sl_numsrc > 0) { 525 if (ilm->ilm_filter == NULL) { 526 ilm->ilm_filter = l_alloc(); 527 if (ilm->ilm_filter == NULL) { 528 char buf[INET6_ADDRSTRLEN]; 529 ip1dbg(("ilm_update_del: failed to alloc ilm " 530 "filter; no source filtering for %s on %s", 531 inet_ntop(AF_INET6, &ilm->ilm_v6addr, 532 buf, sizeof (buf)), ill->ill_name)); 533 ilm->ilm_fmode = MODE_IS_EXCLUDE; 534 l_free(flist); 535 return (0); 536 } 537 } 538 l_copy(flist, ilm->ilm_filter); 539 } else { 540 CLEAR_SLIST(ilm->ilm_filter); 541 } 542 543 l_free(flist); 544 return (0); 545 } 546 547 /* 548 * Create/update the ilm for the group/ill. Used by other parts of IP to 549 * do the ILGSTAT_NONE (no ilg), MODE_IS_EXCLUDE, with no slist join. 550 * Returns with a refhold on the ilm. 551 * 552 * The unspecified address means all multicast addresses for in both the 553 * case of IPv4 and IPv6. 554 * 555 * The caller should have already mapped an IPMP under ill to the upper. 556 */ 557 ilm_t * 558 ip_addmulti(const in6_addr_t *v6group, ill_t *ill, zoneid_t zoneid, 559 int *errorp) 560 { 561 ilm_t *ilm; 562 563 /* Acquire serializer to keep assert in ilm_bld_flists happy */ 564 mutex_enter(&ill->ill_mcast_serializer); 565 ilm = ip_addmulti_serial(v6group, ill, zoneid, ILGSTAT_NONE, 566 MODE_IS_EXCLUDE, NULL, errorp); 567 mutex_exit(&ill->ill_mcast_serializer); 568 return (ilm); 569 } 570 571 /* 572 * Create/update the ilm for the group/ill. If ILGSTAT_CHANGE is not set 573 * then this returns with a refhold on the ilm. 574 * 575 * Internal routine which assumes the caller has already acquired 576 * ill_multi_serializer. 577 * 578 * The unspecified address means all multicast addresses for in both the 579 * case of IPv4 and IPv6. 580 * 581 * ilgstat tells us if there's an ilg associated with this join, 582 * and if so, if it's a new ilg or a change to an existing one. 583 * ilg_fmode and ilg_flist give us the current filter state of 584 * the ilg (and will be EXCLUDE {NULL} in the case of no ilg). 585 * 586 * The caller should have already mapped an IPMP under ill to the upper. 587 */ 588 static ilm_t * 589 ip_addmulti_serial(const in6_addr_t *v6group, ill_t *ill, zoneid_t zoneid, 590 ilg_stat_t ilgstat, mcast_record_t ilg_fmode, slist_t *ilg_flist, 591 int *errorp) 592 { 593 ilm_t *ilm; 594 595 ASSERT(MUTEX_HELD(&ill->ill_mcast_serializer)); 596 597 if (ill->ill_isv6) { 598 if (!IN6_IS_ADDR_MULTICAST(v6group) && 599 !IN6_IS_ADDR_UNSPECIFIED(v6group)) { 600 *errorp = EINVAL; 601 return (NULL); 602 } 603 } else { 604 if (IN6_IS_ADDR_V4MAPPED(v6group)) { 605 ipaddr_t v4group; 606 607 IN6_V4MAPPED_TO_IPADDR(v6group, v4group); 608 if (!CLASSD(v4group)) { 609 *errorp = EINVAL; 610 return (NULL); 611 } 612 } else if (!IN6_IS_ADDR_UNSPECIFIED(v6group)) { 613 *errorp = EINVAL; 614 return (NULL); 615 } 616 } 617 618 if (IS_UNDER_IPMP(ill)) { 619 *errorp = EINVAL; 620 return (NULL); 621 } 622 623 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 624 /* 625 * We do the equivalent of a lookup by checking after we get the lock 626 * This is needed since the ill could have been condemned after 627 * we looked it up, and we need to check condemned after we hold 628 * ill_mcast_lock to synchronize with the unplumb code. 629 */ 630 if (ill->ill_state_flags & ILL_CONDEMNED) { 631 rw_exit(&ill->ill_mcast_lock); 632 *errorp = ENXIO; 633 return (NULL); 634 } 635 ilm = ip_addmulti_impl(v6group, ill, zoneid, ilgstat, ilg_fmode, 636 ilg_flist, errorp); 637 rw_exit(&ill->ill_mcast_lock); 638 639 /* Send any deferred/queued DLPI or IP packets */ 640 ill_mcast_send_queued(ill); 641 ill_dlpi_send_queued(ill); 642 ill_mcast_timer_start(ill->ill_ipst); 643 return (ilm); 644 } 645 646 static ilm_t * 647 ip_addmulti_impl(const in6_addr_t *v6group, ill_t *ill, zoneid_t zoneid, 648 ilg_stat_t ilgstat, mcast_record_t ilg_fmode, slist_t *ilg_flist, 649 int *errorp) 650 { 651 ilm_t *ilm; 652 int ret = 0; 653 654 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 655 *errorp = 0; 656 657 /* 658 * An ilm is uniquely identified by the tuple of (group, ill) where 659 * `group' is the multicast group address, and `ill' is the interface 660 * on which it is currently joined. 661 */ 662 663 ilm = ilm_lookup(ill, v6group, zoneid); 664 if (ilm != NULL) { 665 /* ilm_update_add bumps ilm_refcnt unless ILGSTAT_CHANGE */ 666 ret = ilm_update_add(ilm, ilgstat, ilg_flist); 667 if (ret == 0) 668 return (ilm); 669 670 *errorp = ret; 671 return (NULL); 672 } 673 674 /* 675 * The callers checks on the ilg and the ilg+ilm consistency under 676 * ill_mcast_serializer ensures that we can not have ILGSTAT_CHANGE 677 * and no ilm. 678 */ 679 ASSERT(ilgstat != ILGSTAT_CHANGE); 680 ilm = ilm_add(ill, v6group, ilgstat, ilg_fmode, ilg_flist, zoneid); 681 if (ilm == NULL) { 682 *errorp = ENOMEM; 683 return (NULL); 684 } 685 686 if (IN6_IS_ADDR_UNSPECIFIED(v6group)) { 687 /* 688 * If we have more then one we should not tell the driver 689 * to join this time. 690 */ 691 if (ilm_numentries(ill, v6group) == 1) { 692 ret = ill_join_allmulti(ill); 693 } 694 } else { 695 if (!IS_LOOPBACK(ill)) { 696 if (ill->ill_isv6) 697 mld_joingroup(ilm); 698 else 699 igmp_joingroup(ilm); 700 } 701 702 /* 703 * If we have more then one we should not tell the driver 704 * to join this time. 705 */ 706 if (ilm_numentries(ill, v6group) == 1) { 707 ret = ip_ll_multireq(ill, v6group, DL_ENABMULTI_REQ); 708 } 709 } 710 if (ret != 0) { 711 if (ret == ENETDOWN) { 712 char buf[INET6_ADDRSTRLEN]; 713 714 ip0dbg(("ip_addmulti: ENETDOWN for %s on %s", 715 inet_ntop(AF_INET6, &ilm->ilm_v6addr, 716 buf, sizeof (buf)), ill->ill_name)); 717 } 718 ilm_delete(ilm); 719 *errorp = ret; 720 return (NULL); 721 } else { 722 return (ilm); 723 } 724 } 725 726 /* 727 * Send a multicast request to the driver for enabling or disabling 728 * multicast reception for v6groupp address. The caller has already 729 * checked whether it is appropriate to send one or not. 730 * 731 * For IPMP we switch to the cast_ill since it has the right hardware 732 * information. 733 */ 734 static int 735 ip_ll_send_multireq(ill_t *ill, const in6_addr_t *v6groupp, t_uscalar_t prim) 736 { 737 mblk_t *mp; 738 uint32_t addrlen, addroff; 739 ill_t *release_ill = NULL; 740 int err = 0; 741 742 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 743 744 if (IS_IPMP(ill)) { 745 /* On the upper IPMP ill. */ 746 release_ill = ipmp_illgrp_hold_cast_ill(ill->ill_grp); 747 if (release_ill == NULL) { 748 /* 749 * Avoid sending it down to the ipmpstub. 750 * We will be called again once the members of the 751 * group are in place 752 */ 753 ip1dbg(("ip_ll_send_multireq: no cast_ill for %s %d\n", 754 ill->ill_name, ill->ill_isv6)); 755 return (0); 756 } 757 ill = release_ill; 758 } 759 /* Create a DL_ENABMULTI_REQ or DL_DISABMULTI_REQ message. */ 760 mp = ill_create_dl(ill, prim, &addrlen, &addroff); 761 if (mp == NULL) { 762 err = ENOMEM; 763 goto done; 764 } 765 766 mp = ndp_mcastreq(ill, v6groupp, addrlen, addroff, mp); 767 if (mp == NULL) { 768 ip0dbg(("null from ndp_mcastreq(ill %s)\n", ill->ill_name)); 769 err = ENOMEM; 770 goto done; 771 } 772 773 switch (((union DL_primitives *)mp->b_rptr)->dl_primitive) { 774 case DL_ENABMULTI_REQ: 775 mutex_enter(&ill->ill_lock); 776 /* Track the state if this is the first enabmulti */ 777 if (ill->ill_dlpi_multicast_state == IDS_UNKNOWN) 778 ill->ill_dlpi_multicast_state = IDS_INPROGRESS; 779 mutex_exit(&ill->ill_lock); 780 break; 781 } 782 ill_dlpi_queue(ill, mp); 783 done: 784 if (release_ill != NULL) 785 ill_refrele(release_ill); 786 return (err); 787 } 788 789 /* 790 * Send a multicast request to the driver for enabling multicast 791 * membership for v6group if appropriate. 792 */ 793 static int 794 ip_ll_multireq(ill_t *ill, const in6_addr_t *v6groupp, t_uscalar_t prim) 795 { 796 if (ill->ill_net_type != IRE_IF_RESOLVER || 797 ill->ill_ipif->ipif_flags & IPIF_POINTOPOINT) { 798 ip1dbg(("ip_ll_multireq: not resolver\n")); 799 return (0); /* Must be IRE_IF_NORESOLVER */ 800 } 801 802 if (ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST) { 803 ip1dbg(("ip_ll_multireq: MULTI_BCAST\n")); 804 return (0); 805 } 806 return (ip_ll_send_multireq(ill, v6groupp, prim)); 807 } 808 809 /* 810 * Delete the ilm. Used by other parts of IP for the case of no_ilg/leaving 811 * being true. 812 */ 813 int 814 ip_delmulti(ilm_t *ilm) 815 { 816 ill_t *ill = ilm->ilm_ill; 817 int error; 818 819 /* Acquire serializer to keep assert in ilm_bld_flists happy */ 820 mutex_enter(&ill->ill_mcast_serializer); 821 error = ip_delmulti_serial(ilm, B_TRUE, B_TRUE); 822 mutex_exit(&ill->ill_mcast_serializer); 823 return (error); 824 } 825 826 827 /* 828 * Delete the ilm. 829 * Assumes ill_multi_serializer is held by the caller. 830 */ 831 static int 832 ip_delmulti_serial(ilm_t *ilm, boolean_t no_ilg, boolean_t leaving) 833 { 834 ill_t *ill = ilm->ilm_ill; 835 int ret; 836 837 ASSERT(MUTEX_HELD(&ill->ill_mcast_serializer)); 838 ASSERT(!(IS_UNDER_IPMP(ill))); 839 840 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 841 ret = ip_delmulti_impl(ilm, no_ilg, leaving); 842 rw_exit(&ill->ill_mcast_lock); 843 /* Send any deferred/queued DLPI or IP packets */ 844 ill_mcast_send_queued(ill); 845 ill_dlpi_send_queued(ill); 846 ill_mcast_timer_start(ill->ill_ipst); 847 848 return (ret); 849 } 850 851 static int 852 ip_delmulti_impl(ilm_t *ilm, boolean_t no_ilg, boolean_t leaving) 853 { 854 ill_t *ill = ilm->ilm_ill; 855 int error; 856 in6_addr_t v6group; 857 858 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 859 860 /* Update counters */ 861 if (no_ilg) 862 ilm->ilm_no_ilg_cnt--; 863 864 if (leaving) 865 ilm->ilm_refcnt--; 866 867 if (ilm->ilm_refcnt > 0) 868 return (ilm_update_del(ilm)); 869 870 v6group = ilm->ilm_v6addr; 871 872 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 873 ilm_delete(ilm); 874 /* 875 * If we have some left then one we should not tell the driver 876 * to leave. 877 */ 878 if (ilm_numentries(ill, &v6group) != 0) 879 return (0); 880 881 ill_leave_allmulti(ill); 882 883 return (0); 884 } 885 886 if (!IS_LOOPBACK(ill)) { 887 if (ill->ill_isv6) 888 mld_leavegroup(ilm); 889 else 890 igmp_leavegroup(ilm); 891 } 892 893 ilm_delete(ilm); 894 /* 895 * If we have some left then one we should not tell the driver 896 * to leave. 897 */ 898 if (ilm_numentries(ill, &v6group) != 0) 899 return (0); 900 901 error = ip_ll_multireq(ill, &v6group, DL_DISABMULTI_REQ); 902 /* We ignore the case when ill_dl_up is not set */ 903 if (error == ENETDOWN) { 904 char buf[INET6_ADDRSTRLEN]; 905 906 ip0dbg(("ip_delmulti: ENETDOWN for %s on %s", 907 inet_ntop(AF_INET6, &v6group, buf, sizeof (buf)), 908 ill->ill_name)); 909 } 910 return (error); 911 } 912 913 /* 914 * Make the driver pass up all multicast packets. 915 */ 916 int 917 ill_join_allmulti(ill_t *ill) 918 { 919 mblk_t *promiscon_mp, *promiscoff_mp = NULL; 920 uint32_t addrlen, addroff; 921 ill_t *release_ill = NULL; 922 923 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 924 925 if (IS_LOOPBACK(ill)) 926 return (0); 927 928 if (!ill->ill_dl_up) { 929 /* 930 * Nobody there. All multicast addresses will be re-joined 931 * when we get the DL_BIND_ACK bringing the interface up. 932 */ 933 return (ENETDOWN); 934 } 935 936 if (IS_IPMP(ill)) { 937 /* On the upper IPMP ill. */ 938 release_ill = ipmp_illgrp_hold_cast_ill(ill->ill_grp); 939 if (release_ill == NULL) { 940 /* 941 * Avoid sending it down to the ipmpstub. 942 * We will be called again once the members of the 943 * group are in place 944 */ 945 ip1dbg(("ill_join_allmulti: no cast_ill for %s %d\n", 946 ill->ill_name, ill->ill_isv6)); 947 return (0); 948 } 949 ill = release_ill; 950 if (!ill->ill_dl_up) { 951 ill_refrele(ill); 952 return (ENETDOWN); 953 } 954 } 955 956 /* 957 * Create a DL_PROMISCON_REQ message and send it directly to the DLPI 958 * provider. We don't need to do this for certain media types for 959 * which we never need to turn promiscuous mode on. While we're here, 960 * pre-allocate a DL_PROMISCOFF_REQ message to make sure that 961 * ill_leave_allmulti() will not fail due to low memory conditions. 962 */ 963 if ((ill->ill_net_type == IRE_IF_RESOLVER) && 964 !(ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST)) { 965 promiscon_mp = ill_create_dl(ill, DL_PROMISCON_REQ, 966 &addrlen, &addroff); 967 if (ill->ill_promiscoff_mp == NULL) 968 promiscoff_mp = ill_create_dl(ill, DL_PROMISCOFF_REQ, 969 &addrlen, &addroff); 970 if (promiscon_mp == NULL || 971 (ill->ill_promiscoff_mp == NULL && promiscoff_mp == NULL)) { 972 freemsg(promiscon_mp); 973 freemsg(promiscoff_mp); 974 if (release_ill != NULL) 975 ill_refrele(release_ill); 976 return (ENOMEM); 977 } 978 if (ill->ill_promiscoff_mp == NULL) 979 ill->ill_promiscoff_mp = promiscoff_mp; 980 ill_dlpi_queue(ill, promiscon_mp); 981 } 982 if (release_ill != NULL) 983 ill_refrele(release_ill); 984 return (0); 985 } 986 987 /* 988 * Make the driver stop passing up all multicast packets 989 */ 990 void 991 ill_leave_allmulti(ill_t *ill) 992 { 993 mblk_t *promiscoff_mp; 994 ill_t *release_ill = NULL; 995 996 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 997 998 if (IS_LOOPBACK(ill)) 999 return; 1000 1001 if (!ill->ill_dl_up) { 1002 /* 1003 * Nobody there. All multicast addresses will be re-joined 1004 * when we get the DL_BIND_ACK bringing the interface up. 1005 */ 1006 return; 1007 } 1008 1009 if (IS_IPMP(ill)) { 1010 /* On the upper IPMP ill. */ 1011 release_ill = ipmp_illgrp_hold_cast_ill(ill->ill_grp); 1012 if (release_ill == NULL) { 1013 /* 1014 * Avoid sending it down to the ipmpstub. 1015 * We will be called again once the members of the 1016 * group are in place 1017 */ 1018 ip1dbg(("ill_leave_allmulti: no cast_ill on %s %d\n", 1019 ill->ill_name, ill->ill_isv6)); 1020 return; 1021 } 1022 ill = release_ill; 1023 if (!ill->ill_dl_up) 1024 goto done; 1025 } 1026 1027 /* 1028 * In the case of IPMP and ill_dl_up not being set when we joined 1029 * we didn't allocate a promiscoff_mp. In that case we have 1030 * nothing to do when we leave. 1031 * Ditto for PHYI_MULTI_BCAST 1032 */ 1033 promiscoff_mp = ill->ill_promiscoff_mp; 1034 if (promiscoff_mp != NULL) { 1035 ill->ill_promiscoff_mp = NULL; 1036 ill_dlpi_queue(ill, promiscoff_mp); 1037 } 1038 done: 1039 if (release_ill != NULL) 1040 ill_refrele(release_ill); 1041 } 1042 1043 int 1044 ip_join_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1045 { 1046 ill_t *ill; 1047 int ret; 1048 ilm_t *ilm; 1049 1050 ill = ill_lookup_on_ifindex(ifindex, isv6, ipst); 1051 if (ill == NULL) 1052 return (ENODEV); 1053 1054 /* 1055 * The ip_addmulti() function doesn't allow IPMP underlying interfaces 1056 * to join allmulti since only the nominated underlying interface in 1057 * the group should receive multicast. We silently succeed to avoid 1058 * having to teach IPobs (currently the only caller of this routine) 1059 * to ignore failures in this case. 1060 */ 1061 if (IS_UNDER_IPMP(ill)) { 1062 ill_refrele(ill); 1063 return (0); 1064 } 1065 mutex_enter(&ill->ill_lock); 1066 if (ill->ill_ipallmulti_cnt > 0) { 1067 /* Already joined */ 1068 ASSERT(ill->ill_ipallmulti_ilm != NULL); 1069 ill->ill_ipallmulti_cnt++; 1070 mutex_exit(&ill->ill_lock); 1071 goto done; 1072 } 1073 mutex_exit(&ill->ill_lock); 1074 1075 ilm = ip_addmulti(&ipv6_all_zeros, ill, ill->ill_zoneid, &ret); 1076 if (ilm == NULL) { 1077 ASSERT(ret != 0); 1078 ill_refrele(ill); 1079 return (ret); 1080 } 1081 1082 mutex_enter(&ill->ill_lock); 1083 if (ill->ill_ipallmulti_cnt > 0) { 1084 /* Another thread added it concurrently */ 1085 (void) ip_delmulti(ilm); 1086 mutex_exit(&ill->ill_lock); 1087 goto done; 1088 } 1089 ASSERT(ill->ill_ipallmulti_ilm == NULL); 1090 ill->ill_ipallmulti_ilm = ilm; 1091 ill->ill_ipallmulti_cnt++; 1092 mutex_exit(&ill->ill_lock); 1093 done: 1094 ill_refrele(ill); 1095 return (0); 1096 } 1097 1098 int 1099 ip_leave_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1100 { 1101 ill_t *ill; 1102 ilm_t *ilm; 1103 1104 ill = ill_lookup_on_ifindex(ifindex, isv6, ipst); 1105 if (ill == NULL) 1106 return (ENODEV); 1107 1108 if (IS_UNDER_IPMP(ill)) { 1109 ill_refrele(ill); 1110 return (0); 1111 } 1112 1113 mutex_enter(&ill->ill_lock); 1114 if (ill->ill_ipallmulti_cnt == 0) { 1115 /* ip_purge_allmulti could have removed them all */ 1116 mutex_exit(&ill->ill_lock); 1117 goto done; 1118 } 1119 ill->ill_ipallmulti_cnt--; 1120 if (ill->ill_ipallmulti_cnt == 0) { 1121 /* Last one */ 1122 ilm = ill->ill_ipallmulti_ilm; 1123 ill->ill_ipallmulti_ilm = NULL; 1124 } else { 1125 ilm = NULL; 1126 } 1127 mutex_exit(&ill->ill_lock); 1128 if (ilm != NULL) 1129 (void) ip_delmulti(ilm); 1130 1131 done: 1132 ill_refrele(ill); 1133 return (0); 1134 } 1135 1136 /* 1137 * Delete the allmulti memberships that were added as part of 1138 * ip_join_allmulti(). 1139 */ 1140 void 1141 ip_purge_allmulti(ill_t *ill) 1142 { 1143 ilm_t *ilm; 1144 1145 ASSERT(IAM_WRITER_ILL(ill)); 1146 1147 mutex_enter(&ill->ill_lock); 1148 ilm = ill->ill_ipallmulti_ilm; 1149 ill->ill_ipallmulti_ilm = NULL; 1150 ill->ill_ipallmulti_cnt = 0; 1151 mutex_exit(&ill->ill_lock); 1152 1153 if (ilm != NULL) 1154 (void) ip_delmulti(ilm); 1155 } 1156 1157 /* 1158 * Create a dlpi message with room for phys+sap. Later 1159 * we will strip the sap for those primitives which 1160 * only need a physical address. 1161 */ 1162 static mblk_t * 1163 ill_create_dl(ill_t *ill, uint32_t dl_primitive, 1164 uint32_t *addr_lenp, uint32_t *addr_offp) 1165 { 1166 mblk_t *mp; 1167 uint32_t hw_addr_length; 1168 char *cp; 1169 uint32_t offset; 1170 uint32_t length; 1171 uint32_t size; 1172 1173 *addr_lenp = *addr_offp = 0; 1174 1175 hw_addr_length = ill->ill_phys_addr_length; 1176 if (!hw_addr_length) { 1177 ip0dbg(("ip_create_dl: hw addr length = 0\n")); 1178 return (NULL); 1179 } 1180 1181 switch (dl_primitive) { 1182 case DL_ENABMULTI_REQ: 1183 length = sizeof (dl_enabmulti_req_t); 1184 size = length + hw_addr_length; 1185 break; 1186 case DL_DISABMULTI_REQ: 1187 length = sizeof (dl_disabmulti_req_t); 1188 size = length + hw_addr_length; 1189 break; 1190 case DL_PROMISCON_REQ: 1191 case DL_PROMISCOFF_REQ: 1192 size = length = sizeof (dl_promiscon_req_t); 1193 break; 1194 default: 1195 return (NULL); 1196 } 1197 mp = allocb(size, BPRI_HI); 1198 if (!mp) 1199 return (NULL); 1200 mp->b_wptr += size; 1201 mp->b_datap->db_type = M_PROTO; 1202 1203 cp = (char *)mp->b_rptr; 1204 offset = length; 1205 1206 switch (dl_primitive) { 1207 case DL_ENABMULTI_REQ: { 1208 dl_enabmulti_req_t *dl = (dl_enabmulti_req_t *)cp; 1209 1210 dl->dl_primitive = dl_primitive; 1211 dl->dl_addr_offset = offset; 1212 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1213 *addr_offp = offset; 1214 break; 1215 } 1216 case DL_DISABMULTI_REQ: { 1217 dl_disabmulti_req_t *dl = (dl_disabmulti_req_t *)cp; 1218 1219 dl->dl_primitive = dl_primitive; 1220 dl->dl_addr_offset = offset; 1221 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1222 *addr_offp = offset; 1223 break; 1224 } 1225 case DL_PROMISCON_REQ: 1226 case DL_PROMISCOFF_REQ: { 1227 dl_promiscon_req_t *dl = (dl_promiscon_req_t *)cp; 1228 1229 dl->dl_primitive = dl_primitive; 1230 dl->dl_level = DL_PROMISC_MULTI; 1231 break; 1232 } 1233 } 1234 ip1dbg(("ill_create_dl: addr_len %d, addr_off %d\n", 1235 *addr_lenp, *addr_offp)); 1236 return (mp); 1237 } 1238 1239 /* 1240 * Rejoin any groups for which we have ilms. 1241 * 1242 * This is only needed for IPMP when the cast_ill changes since that 1243 * change is invisible to the ilm. Other interface changes are handled 1244 * by conn_update_ill. 1245 */ 1246 void 1247 ill_recover_multicast(ill_t *ill) 1248 { 1249 ilm_t *ilm; 1250 char addrbuf[INET6_ADDRSTRLEN]; 1251 1252 ill->ill_need_recover_multicast = 0; 1253 1254 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1255 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1256 /* 1257 * If we have more then one ilm for the group (e.g., with 1258 * different zoneid) then we should not tell the driver 1259 * to join unless this is the first ilm for the group. 1260 */ 1261 if (ilm_numentries(ill, &ilm->ilm_v6addr) > 1 && 1262 ilm_lookup(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) { 1263 continue; 1264 } 1265 1266 ip1dbg(("ill_recover_multicast: %s\n", inet_ntop(AF_INET6, 1267 &ilm->ilm_v6addr, addrbuf, sizeof (addrbuf)))); 1268 1269 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1270 (void) ill_join_allmulti(ill); 1271 } else { 1272 if (ill->ill_isv6) 1273 mld_joingroup(ilm); 1274 else 1275 igmp_joingroup(ilm); 1276 1277 (void) ip_ll_multireq(ill, &ilm->ilm_v6addr, 1278 DL_ENABMULTI_REQ); 1279 } 1280 } 1281 rw_exit(&ill->ill_mcast_lock); 1282 /* Send any deferred/queued DLPI or IP packets */ 1283 ill_mcast_send_queued(ill); 1284 ill_dlpi_send_queued(ill); 1285 ill_mcast_timer_start(ill->ill_ipst); 1286 } 1287 1288 /* 1289 * The opposite of ill_recover_multicast() -- leaves all multicast groups 1290 * that were explicitly joined. 1291 * 1292 * This is only needed for IPMP when the cast_ill changes since that 1293 * change is invisible to the ilm. Other interface changes are handled 1294 * by conn_update_ill. 1295 */ 1296 void 1297 ill_leave_multicast(ill_t *ill) 1298 { 1299 ilm_t *ilm; 1300 char addrbuf[INET6_ADDRSTRLEN]; 1301 1302 ill->ill_need_recover_multicast = 1; 1303 1304 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1305 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1306 /* 1307 * If we have more then one ilm for the group (e.g., with 1308 * different zoneid) then we should not tell the driver 1309 * to leave unless this is the first ilm for the group. 1310 */ 1311 if (ilm_numentries(ill, &ilm->ilm_v6addr) > 1 && 1312 ilm_lookup(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) { 1313 continue; 1314 } 1315 1316 ip1dbg(("ill_leave_multicast: %s\n", inet_ntop(AF_INET6, 1317 &ilm->ilm_v6addr, addrbuf, sizeof (addrbuf)))); 1318 1319 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1320 ill_leave_allmulti(ill); 1321 } else { 1322 if (ill->ill_isv6) 1323 mld_leavegroup(ilm); 1324 else 1325 igmp_leavegroup(ilm); 1326 1327 (void) ip_ll_multireq(ill, &ilm->ilm_v6addr, 1328 DL_DISABMULTI_REQ); 1329 } 1330 } 1331 rw_exit(&ill->ill_mcast_lock); 1332 /* Send any deferred/queued DLPI or IP packets */ 1333 ill_mcast_send_queued(ill); 1334 ill_dlpi_send_queued(ill); 1335 ill_mcast_timer_start(ill->ill_ipst); 1336 } 1337 1338 /* 1339 * Interface used by IP input/output. 1340 * Returns true if there is a member on the ill for any zoneid. 1341 */ 1342 boolean_t 1343 ill_hasmembers_v6(ill_t *ill, const in6_addr_t *v6group) 1344 { 1345 ilm_t *ilm; 1346 1347 rw_enter(&ill->ill_mcast_lock, RW_READER); 1348 ilm = ilm_lookup(ill, v6group, ALL_ZONES); 1349 rw_exit(&ill->ill_mcast_lock); 1350 return (ilm != NULL); 1351 } 1352 1353 /* 1354 * Interface used by IP input/output. 1355 * Returns true if there is a member on the ill for any zoneid. 1356 * 1357 * The group and source can't be INADDR_ANY here so no need to translate to 1358 * the unspecified IPv6 address. 1359 */ 1360 boolean_t 1361 ill_hasmembers_v4(ill_t *ill, ipaddr_t group) 1362 { 1363 in6_addr_t v6group; 1364 1365 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1366 return (ill_hasmembers_v6(ill, &v6group)); 1367 } 1368 1369 /* 1370 * Interface used by IP input/output. 1371 * Returns true if there is a member on the ill for any zoneid except skipzone. 1372 */ 1373 boolean_t 1374 ill_hasmembers_otherzones_v6(ill_t *ill, const in6_addr_t *v6group, 1375 zoneid_t skipzone) 1376 { 1377 ilm_t *ilm; 1378 1379 rw_enter(&ill->ill_mcast_lock, RW_READER); 1380 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1381 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1382 ilm->ilm_zoneid != skipzone) { 1383 rw_exit(&ill->ill_mcast_lock); 1384 return (B_TRUE); 1385 } 1386 } 1387 rw_exit(&ill->ill_mcast_lock); 1388 return (B_FALSE); 1389 } 1390 1391 /* 1392 * Interface used by IP input/output. 1393 * Returns true if there is a member on the ill for any zoneid except skipzone. 1394 * 1395 * The group and source can't be INADDR_ANY here so no need to translate to 1396 * the unspecified IPv6 address. 1397 */ 1398 boolean_t 1399 ill_hasmembers_otherzones_v4(ill_t *ill, ipaddr_t group, zoneid_t skipzone) 1400 { 1401 in6_addr_t v6group; 1402 1403 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1404 return (ill_hasmembers_otherzones_v6(ill, &v6group, skipzone)); 1405 } 1406 1407 /* 1408 * Interface used by IP input. 1409 * Returns the next numerically larger zoneid that has a member. If none exist 1410 * then returns -1 (ALL_ZONES). 1411 * The normal usage is for the caller to start with a -1 zoneid (ALL_ZONES) 1412 * to find the first zoneid which has a member, and then pass that in for 1413 * subsequent calls until ALL_ZONES is returned. 1414 * 1415 * The implementation of ill_hasmembers_nextzone() assumes the ilms 1416 * are sorted by zoneid for efficiency. 1417 */ 1418 zoneid_t 1419 ill_hasmembers_nextzone_v6(ill_t *ill, const in6_addr_t *v6group, 1420 zoneid_t zoneid) 1421 { 1422 ilm_t *ilm; 1423 1424 rw_enter(&ill->ill_mcast_lock, RW_READER); 1425 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1426 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1427 ilm->ilm_zoneid > zoneid) { 1428 zoneid = ilm->ilm_zoneid; 1429 rw_exit(&ill->ill_mcast_lock); 1430 return (zoneid); 1431 } 1432 } 1433 rw_exit(&ill->ill_mcast_lock); 1434 return (ALL_ZONES); 1435 } 1436 1437 /* 1438 * Interface used by IP input. 1439 * Returns the next numerically larger zoneid that has a member. If none exist 1440 * then returns -1 (ALL_ZONES). 1441 * 1442 * The group and source can't be INADDR_ANY here so no need to translate to 1443 * the unspecified IPv6 address. 1444 */ 1445 zoneid_t 1446 ill_hasmembers_nextzone_v4(ill_t *ill, ipaddr_t group, zoneid_t zoneid) 1447 { 1448 in6_addr_t v6group; 1449 1450 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1451 1452 return (ill_hasmembers_nextzone_v6(ill, &v6group, zoneid)); 1453 } 1454 1455 /* 1456 * Find an ilm matching the ill, group, and zoneid. 1457 */ 1458 static ilm_t * 1459 ilm_lookup(ill_t *ill, const in6_addr_t *v6group, zoneid_t zoneid) 1460 { 1461 ilm_t *ilm; 1462 1463 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1464 1465 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1466 if (!IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group)) 1467 continue; 1468 if (zoneid != ALL_ZONES && zoneid != ilm->ilm_zoneid) 1469 continue; 1470 1471 ASSERT(ilm->ilm_ill == ill); 1472 return (ilm); 1473 } 1474 return (NULL); 1475 } 1476 1477 /* 1478 * How many members on this ill? 1479 * Since each shared-IP zone has a separate ilm for the same group/ill 1480 * we can have several. 1481 */ 1482 static int 1483 ilm_numentries(ill_t *ill, const in6_addr_t *v6group) 1484 { 1485 ilm_t *ilm; 1486 int i = 0; 1487 1488 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1489 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1490 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group)) { 1491 i++; 1492 } 1493 } 1494 return (i); 1495 } 1496 1497 /* Caller guarantees that the group is not already on the list */ 1498 static ilm_t * 1499 ilm_add(ill_t *ill, const in6_addr_t *v6group, ilg_stat_t ilgstat, 1500 mcast_record_t ilg_fmode, slist_t *ilg_flist, zoneid_t zoneid) 1501 { 1502 ilm_t *ilm; 1503 ilm_t *ilm_cur; 1504 ilm_t **ilm_ptpn; 1505 1506 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1507 ilm = GETSTRUCT(ilm_t, 1); 1508 if (ilm == NULL) 1509 return (NULL); 1510 if (ilgstat != ILGSTAT_NONE && !SLIST_IS_EMPTY(ilg_flist)) { 1511 ilm->ilm_filter = l_alloc(); 1512 if (ilm->ilm_filter == NULL) { 1513 mi_free(ilm); 1514 return (NULL); 1515 } 1516 } 1517 ilm->ilm_v6addr = *v6group; 1518 ilm->ilm_refcnt = 1; 1519 ilm->ilm_zoneid = zoneid; 1520 ilm->ilm_timer = INFINITY; 1521 ilm->ilm_rtx.rtx_timer = INFINITY; 1522 1523 ilm->ilm_ill = ill; 1524 DTRACE_PROBE3(ill__incr__cnt, (ill_t *), ill, 1525 (char *), "ilm", (void *), ilm); 1526 ill->ill_ilm_cnt++; 1527 1528 ASSERT(ill->ill_ipst); 1529 ilm->ilm_ipst = ill->ill_ipst; /* No netstack_hold */ 1530 1531 /* The ill/ipif could have just been marked as condemned */ 1532 1533 /* 1534 * To make ill_hasmembers_nextzone_v6 work we keep the list 1535 * sorted by zoneid. 1536 */ 1537 ilm_cur = ill->ill_ilm; 1538 ilm_ptpn = &ill->ill_ilm; 1539 while (ilm_cur != NULL && ilm_cur->ilm_zoneid < ilm->ilm_zoneid) { 1540 ilm_ptpn = &ilm_cur->ilm_next; 1541 ilm_cur = ilm_cur->ilm_next; 1542 } 1543 ilm->ilm_next = ilm_cur; 1544 *ilm_ptpn = ilm; 1545 1546 /* 1547 * If we have an associated ilg, use its filter state; if not, 1548 * default to (EXCLUDE, NULL) and set no_ilg_cnt to track this. 1549 */ 1550 if (ilgstat != ILGSTAT_NONE) { 1551 if (!SLIST_IS_EMPTY(ilg_flist)) 1552 l_copy(ilg_flist, ilm->ilm_filter); 1553 ilm->ilm_fmode = ilg_fmode; 1554 } else { 1555 ilm->ilm_no_ilg_cnt = 1; 1556 ilm->ilm_fmode = MODE_IS_EXCLUDE; 1557 } 1558 1559 return (ilm); 1560 } 1561 1562 void 1563 ilm_inactive(ilm_t *ilm) 1564 { 1565 FREE_SLIST(ilm->ilm_filter); 1566 FREE_SLIST(ilm->ilm_pendsrcs); 1567 FREE_SLIST(ilm->ilm_rtx.rtx_allow); 1568 FREE_SLIST(ilm->ilm_rtx.rtx_block); 1569 ilm->ilm_ipst = NULL; 1570 mi_free((char *)ilm); 1571 } 1572 1573 /* 1574 * Unlink ilm and free it. 1575 */ 1576 static void 1577 ilm_delete(ilm_t *ilm) 1578 { 1579 ill_t *ill = ilm->ilm_ill; 1580 ilm_t **ilmp; 1581 boolean_t need_wakeup; 1582 1583 /* 1584 * Delete under lock protection so that readers don't stumble 1585 * on bad ilm_next 1586 */ 1587 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1588 1589 for (ilmp = &ill->ill_ilm; *ilmp != ilm; ilmp = &(*ilmp)->ilm_next) 1590 ; 1591 1592 *ilmp = ilm->ilm_next; 1593 1594 mutex_enter(&ill->ill_lock); 1595 /* 1596 * if we are the last reference to the ill, we may need to wakeup any 1597 * pending FREE or unplumb operations. This is because conn_update_ill 1598 * bails if there is a ilg_delete_all in progress. 1599 */ 1600 need_wakeup = B_FALSE; 1601 DTRACE_PROBE3(ill__decr__cnt, (ill_t *), ill, 1602 (char *), "ilm", (void *), ilm); 1603 ASSERT(ill->ill_ilm_cnt > 0); 1604 ill->ill_ilm_cnt--; 1605 if (ILL_FREE_OK(ill)) 1606 need_wakeup = B_TRUE; 1607 1608 ilm_inactive(ilm); /* frees this ilm */ 1609 1610 if (need_wakeup) { 1611 /* drops ill lock */ 1612 ipif_ill_refrele_tail(ill); 1613 } else { 1614 mutex_exit(&ill->ill_lock); 1615 } 1616 } 1617 1618 /* 1619 * Lookup an ill based on the group, ifindex, ifaddr, and zoneid. 1620 * Applies to both IPv4 and IPv6, although ifaddr is only used with 1621 * IPv4. 1622 * Returns an error for IS_UNDER_IPMP and VNI interfaces. 1623 * On error it sets *errorp. 1624 */ 1625 static ill_t * 1626 ill_mcast_lookup(const in6_addr_t *group, ipaddr_t ifaddr, uint_t ifindex, 1627 zoneid_t zoneid, ip_stack_t *ipst, int *errorp) 1628 { 1629 ill_t *ill; 1630 ipaddr_t v4group; 1631 1632 if (IN6_IS_ADDR_V4MAPPED(group)) { 1633 IN6_V4MAPPED_TO_IPADDR(group, v4group); 1634 1635 if (ifindex != 0) { 1636 ill = ill_lookup_on_ifindex_zoneid(ifindex, zoneid, 1637 B_FALSE, ipst); 1638 } else if (ifaddr != INADDR_ANY) { 1639 ipif_t *ipif; 1640 1641 ipif = ipif_lookup_addr(ifaddr, NULL, zoneid, ipst); 1642 if (ipif == NULL) { 1643 ill = NULL; 1644 } else { 1645 ill = ipif->ipif_ill; 1646 ill_refhold(ill); 1647 ipif_refrele(ipif); 1648 } 1649 } else { 1650 ill = ill_lookup_group_v4(v4group, zoneid, ipst, NULL, 1651 NULL); 1652 } 1653 } else { 1654 if (ifindex != 0) { 1655 ill = ill_lookup_on_ifindex_zoneid(ifindex, zoneid, 1656 B_TRUE, ipst); 1657 } else { 1658 ill = ill_lookup_group_v6(group, zoneid, ipst, NULL, 1659 NULL); 1660 } 1661 } 1662 if (ill == NULL) { 1663 if (ifindex != 0) 1664 *errorp = ENXIO; 1665 else 1666 *errorp = EADDRNOTAVAIL; 1667 return (NULL); 1668 } 1669 /* operation not supported on the virtual network interface */ 1670 if (IS_UNDER_IPMP(ill) || IS_VNI(ill)) { 1671 ill_refrele(ill); 1672 *errorp = EINVAL; 1673 return (NULL); 1674 } 1675 return (ill); 1676 } 1677 1678 /* 1679 * Looks up the appropriate ill given an interface index (or interface address) 1680 * and multicast group. On success, returns 0, with *illpp pointing to the 1681 * found struct. On failure, returns an errno and *illpp is set to NULL. 1682 * 1683 * Returns an error for IS_UNDER_IPMP and VNI interfaces. 1684 * 1685 * Handles both IPv4 and IPv6. The ifaddr argument only applies in the 1686 * case of IPv4. 1687 */ 1688 int 1689 ip_opt_check(conn_t *connp, const in6_addr_t *v6group, 1690 const in6_addr_t *v6src, ipaddr_t ifaddr, uint_t ifindex, ill_t **illpp) 1691 { 1692 boolean_t src_unspec; 1693 ill_t *ill = NULL; 1694 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 1695 int error = 0; 1696 1697 *illpp = NULL; 1698 1699 src_unspec = IN6_IS_ADDR_UNSPECIFIED(v6src); 1700 1701 if (IN6_IS_ADDR_V4MAPPED(v6group)) { 1702 ipaddr_t v4group; 1703 ipaddr_t v4src; 1704 1705 if (!IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 1706 return (EINVAL); 1707 IN6_V4MAPPED_TO_IPADDR(v6group, v4group); 1708 if (src_unspec) { 1709 v4src = INADDR_ANY; 1710 } else { 1711 IN6_V4MAPPED_TO_IPADDR(v6src, v4src); 1712 } 1713 if (!CLASSD(v4group) || CLASSD(v4src)) 1714 return (EINVAL); 1715 } else { 1716 if (IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 1717 return (EINVAL); 1718 if (!IN6_IS_ADDR_MULTICAST(v6group) || 1719 IN6_IS_ADDR_MULTICAST(v6src)) { 1720 return (EINVAL); 1721 } 1722 } 1723 1724 ill = ill_mcast_lookup(v6group, ifaddr, ifindex, IPCL_ZONEID(connp), 1725 ipst, &error); 1726 *illpp = ill; 1727 return (error); 1728 } 1729 1730 static int 1731 ip_get_srcfilter(conn_t *connp, struct group_filter *gf, 1732 struct ip_msfilter *imsf, const struct in6_addr *group, boolean_t issin6) 1733 { 1734 ilg_t *ilg; 1735 int i, numsrc, fmode, outsrcs; 1736 struct sockaddr_in *sin; 1737 struct sockaddr_in6 *sin6; 1738 struct in_addr *addrp; 1739 slist_t *fp; 1740 boolean_t is_v4only_api; 1741 ipaddr_t ifaddr; 1742 uint_t ifindex; 1743 1744 if (gf == NULL) { 1745 ASSERT(imsf != NULL); 1746 ASSERT(!issin6); 1747 is_v4only_api = B_TRUE; 1748 outsrcs = imsf->imsf_numsrc; 1749 ifaddr = imsf->imsf_interface.s_addr; 1750 ifindex = 0; 1751 } else { 1752 ASSERT(imsf == NULL); 1753 is_v4only_api = B_FALSE; 1754 outsrcs = gf->gf_numsrc; 1755 ifaddr = INADDR_ANY; 1756 ifindex = gf->gf_interface; 1757 } 1758 1759 /* No need to use ill_mcast_serializer for the reader */ 1760 rw_enter(&connp->conn_ilg_lock, RW_READER); 1761 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 1762 if (ilg == NULL) { 1763 rw_exit(&connp->conn_ilg_lock); 1764 return (EADDRNOTAVAIL); 1765 } 1766 1767 /* 1768 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 1769 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 1770 * So we need to translate here. 1771 */ 1772 fmode = (ilg->ilg_fmode == MODE_IS_INCLUDE) ? 1773 MCAST_INCLUDE : MCAST_EXCLUDE; 1774 if ((fp = ilg->ilg_filter) == NULL) { 1775 numsrc = 0; 1776 } else { 1777 for (i = 0; i < outsrcs; i++) { 1778 if (i == fp->sl_numsrc) 1779 break; 1780 if (issin6) { 1781 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 1782 sin6->sin6_family = AF_INET6; 1783 sin6->sin6_addr = fp->sl_addr[i]; 1784 } else { 1785 if (is_v4only_api) { 1786 addrp = &imsf->imsf_slist[i]; 1787 } else { 1788 sin = (struct sockaddr_in *) 1789 &gf->gf_slist[i]; 1790 sin->sin_family = AF_INET; 1791 addrp = &sin->sin_addr; 1792 } 1793 IN6_V4MAPPED_TO_INADDR(&fp->sl_addr[i], addrp); 1794 } 1795 } 1796 numsrc = fp->sl_numsrc; 1797 } 1798 1799 if (is_v4only_api) { 1800 imsf->imsf_numsrc = numsrc; 1801 imsf->imsf_fmode = fmode; 1802 } else { 1803 gf->gf_numsrc = numsrc; 1804 gf->gf_fmode = fmode; 1805 } 1806 1807 rw_exit(&connp->conn_ilg_lock); 1808 1809 return (0); 1810 } 1811 1812 /* 1813 * Common for IPv4 and IPv6. 1814 */ 1815 static int 1816 ip_set_srcfilter(conn_t *connp, struct group_filter *gf, 1817 struct ip_msfilter *imsf, const struct in6_addr *group, ill_t *ill, 1818 boolean_t issin6) 1819 { 1820 ilg_t *ilg; 1821 int i, err, infmode, new_fmode; 1822 uint_t insrcs; 1823 struct sockaddr_in *sin; 1824 struct sockaddr_in6 *sin6; 1825 struct in_addr *addrp; 1826 slist_t *orig_filter = NULL; 1827 slist_t *new_filter = NULL; 1828 mcast_record_t orig_fmode; 1829 boolean_t leave_group, is_v4only_api; 1830 ilg_stat_t ilgstat; 1831 ilm_t *ilm; 1832 ipaddr_t ifaddr; 1833 uint_t ifindex; 1834 1835 if (gf == NULL) { 1836 ASSERT(imsf != NULL); 1837 ASSERT(!issin6); 1838 is_v4only_api = B_TRUE; 1839 insrcs = imsf->imsf_numsrc; 1840 infmode = imsf->imsf_fmode; 1841 ifaddr = imsf->imsf_interface.s_addr; 1842 ifindex = 0; 1843 } else { 1844 ASSERT(imsf == NULL); 1845 is_v4only_api = B_FALSE; 1846 insrcs = gf->gf_numsrc; 1847 infmode = gf->gf_fmode; 1848 ifaddr = INADDR_ANY; 1849 ifindex = gf->gf_interface; 1850 } 1851 1852 /* Make sure we can handle the source list */ 1853 if (insrcs > MAX_FILTER_SIZE) 1854 return (ENOBUFS); 1855 1856 /* 1857 * setting the filter to (INCLUDE, NULL) is treated 1858 * as a request to leave the group. 1859 */ 1860 leave_group = (infmode == MCAST_INCLUDE && insrcs == 0); 1861 1862 mutex_enter(&ill->ill_mcast_serializer); 1863 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1864 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 1865 if (ilg == NULL) { 1866 /* 1867 * if the request was actually to leave, and we 1868 * didn't find an ilg, there's nothing to do. 1869 */ 1870 if (leave_group) { 1871 rw_exit(&connp->conn_ilg_lock); 1872 mutex_exit(&ill->ill_mcast_serializer); 1873 return (0); 1874 } 1875 ilg = conn_ilg_alloc(connp, &err); 1876 if (ilg == NULL) { 1877 rw_exit(&connp->conn_ilg_lock); 1878 mutex_exit(&ill->ill_mcast_serializer); 1879 return (err); 1880 } 1881 ilgstat = ILGSTAT_NEW; 1882 ilg->ilg_v6group = *group; 1883 ilg->ilg_ill = ill; 1884 ilg->ilg_ifaddr = ifaddr; 1885 ilg->ilg_ifindex = ifindex; 1886 } else if (leave_group) { 1887 /* 1888 * Make sure we have the correct serializer. The ill argument 1889 * might not match ilg_ill. 1890 */ 1891 ilg_refhold(ilg); 1892 mutex_exit(&ill->ill_mcast_serializer); 1893 ill = ilg->ilg_ill; 1894 rw_exit(&connp->conn_ilg_lock); 1895 1896 mutex_enter(&ill->ill_mcast_serializer); 1897 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1898 ilm = ilg->ilg_ilm; 1899 ilg->ilg_ilm = NULL; 1900 ilg_delete(connp, ilg, NULL); 1901 ilg_refrele(ilg); 1902 rw_exit(&connp->conn_ilg_lock); 1903 if (ilm != NULL) 1904 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 1905 mutex_exit(&ill->ill_mcast_serializer); 1906 return (0); 1907 } else { 1908 ilgstat = ILGSTAT_CHANGE; 1909 /* Preserve existing state in case ip_addmulti() fails */ 1910 orig_fmode = ilg->ilg_fmode; 1911 if (ilg->ilg_filter == NULL) { 1912 orig_filter = NULL; 1913 } else { 1914 orig_filter = l_alloc_copy(ilg->ilg_filter); 1915 if (orig_filter == NULL) { 1916 rw_exit(&connp->conn_ilg_lock); 1917 mutex_exit(&ill->ill_mcast_serializer); 1918 return (ENOMEM); 1919 } 1920 } 1921 } 1922 1923 /* 1924 * Alloc buffer to copy new state into (see below) before 1925 * we make any changes, so we can bail if it fails. 1926 */ 1927 if ((new_filter = l_alloc()) == NULL) { 1928 rw_exit(&connp->conn_ilg_lock); 1929 err = ENOMEM; 1930 goto free_and_exit; 1931 } 1932 1933 if (insrcs == 0) { 1934 CLEAR_SLIST(ilg->ilg_filter); 1935 } else { 1936 slist_t *fp; 1937 if (ilg->ilg_filter == NULL) { 1938 fp = l_alloc(); 1939 if (fp == NULL) { 1940 if (ilgstat == ILGSTAT_NEW) 1941 ilg_delete(connp, ilg, NULL); 1942 rw_exit(&connp->conn_ilg_lock); 1943 err = ENOMEM; 1944 goto free_and_exit; 1945 } 1946 } else { 1947 fp = ilg->ilg_filter; 1948 } 1949 for (i = 0; i < insrcs; i++) { 1950 if (issin6) { 1951 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 1952 fp->sl_addr[i] = sin6->sin6_addr; 1953 } else { 1954 if (is_v4only_api) { 1955 addrp = &imsf->imsf_slist[i]; 1956 } else { 1957 sin = (struct sockaddr_in *) 1958 &gf->gf_slist[i]; 1959 addrp = &sin->sin_addr; 1960 } 1961 IN6_INADDR_TO_V4MAPPED(addrp, &fp->sl_addr[i]); 1962 } 1963 } 1964 fp->sl_numsrc = insrcs; 1965 ilg->ilg_filter = fp; 1966 } 1967 /* 1968 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 1969 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 1970 * So we need to translate here. 1971 */ 1972 ilg->ilg_fmode = (infmode == MCAST_INCLUDE) ? 1973 MODE_IS_INCLUDE : MODE_IS_EXCLUDE; 1974 1975 /* 1976 * Save copy of ilg's filter state to pass to other functions, 1977 * so we can release conn_ilg_lock now. 1978 */ 1979 new_fmode = ilg->ilg_fmode; 1980 l_copy(ilg->ilg_filter, new_filter); 1981 1982 rw_exit(&connp->conn_ilg_lock); 1983 1984 /* 1985 * Now update the ill. We wait to do this until after the ilg 1986 * has been updated because we need to update the src filter 1987 * info for the ill, which involves looking at the status of 1988 * all the ilgs associated with this group/interface pair. 1989 */ 1990 ilm = ip_addmulti_serial(group, ill, connp->conn_zoneid, ilgstat, 1991 new_fmode, new_filter, &err); 1992 1993 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1994 /* 1995 * Must look up the ilg again since we've not been holding 1996 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 1997 * having called conn_update_ill, which can run once we dropped the 1998 * conn_ilg_lock above. 1999 */ 2000 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 2001 if (ilg == NULL) { 2002 rw_exit(&connp->conn_ilg_lock); 2003 if (ilm != NULL) { 2004 (void) ip_delmulti_serial(ilm, B_FALSE, 2005 (ilgstat == ILGSTAT_NEW)); 2006 } 2007 err = ENXIO; 2008 goto free_and_exit; 2009 } 2010 2011 if (ilm != NULL) { 2012 /* Succeeded. Update the ilg to point at the ilm */ 2013 if (ilgstat == ILGSTAT_NEW) { 2014 ASSERT(ilg->ilg_ilm == NULL); 2015 ilg->ilg_ilm = ilm; 2016 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 2017 } else { 2018 /* 2019 * ip_addmulti didn't get a held ilm for 2020 * ILGSTAT_CHANGE; ilm_refcnt was unchanged. 2021 */ 2022 ASSERT(ilg->ilg_ilm == ilm); 2023 } 2024 } else { 2025 ASSERT(err != 0); 2026 /* 2027 * Failed to allocate the ilm. 2028 * Restore the original filter state, or delete the 2029 * newly-created ilg. 2030 * If ENETDOWN just clear ill_ilg since so that we 2031 * will rejoin when the ill comes back; don't report ENETDOWN 2032 * to application. 2033 */ 2034 if (ilgstat == ILGSTAT_NEW) { 2035 if (err == ENETDOWN) { 2036 ilg->ilg_ill = NULL; 2037 err = 0; 2038 } else { 2039 ilg_delete(connp, ilg, NULL); 2040 } 2041 } else { 2042 ilg->ilg_fmode = orig_fmode; 2043 if (SLIST_IS_EMPTY(orig_filter)) { 2044 CLEAR_SLIST(ilg->ilg_filter); 2045 } else { 2046 /* 2047 * We didn't free the filter, even if we 2048 * were trying to make the source list empty; 2049 * so if orig_filter isn't empty, the ilg 2050 * must still have a filter alloc'd. 2051 */ 2052 l_copy(orig_filter, ilg->ilg_filter); 2053 } 2054 } 2055 } 2056 rw_exit(&connp->conn_ilg_lock); 2057 2058 free_and_exit: 2059 mutex_exit(&ill->ill_mcast_serializer); 2060 l_free(orig_filter); 2061 l_free(new_filter); 2062 2063 return (err); 2064 } 2065 2066 /* 2067 * Process the SIOC[GS]MSFILTER and SIOC[GS]IPMSFILTER ioctls. 2068 */ 2069 /* ARGSUSED */ 2070 int 2071 ip_sioctl_msfilter(ipif_t *ipif, sin_t *dummy_sin, queue_t *q, mblk_t *mp, 2072 ip_ioctl_cmd_t *ipip, void *ifreq) 2073 { 2074 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2075 /* existence verified in ip_wput_nondata() */ 2076 mblk_t *data_mp = mp->b_cont->b_cont; 2077 int datalen, err, cmd, minsize; 2078 uint_t expsize = 0; 2079 conn_t *connp; 2080 boolean_t isv6, is_v4only_api, getcmd; 2081 struct sockaddr_in *gsin; 2082 struct sockaddr_in6 *gsin6; 2083 ipaddr_t v4group; 2084 in6_addr_t v6group; 2085 struct group_filter *gf = NULL; 2086 struct ip_msfilter *imsf = NULL; 2087 mblk_t *ndp; 2088 ill_t *ill; 2089 2090 connp = Q_TO_CONN(q); 2091 err = ip_msfilter_ill(connp, mp, ipip, &ill); 2092 if (err != 0) 2093 return (err); 2094 2095 if (data_mp->b_cont != NULL) { 2096 if ((ndp = msgpullup(data_mp, -1)) == NULL) 2097 return (ENOMEM); 2098 freemsg(data_mp); 2099 data_mp = ndp; 2100 mp->b_cont->b_cont = data_mp; 2101 } 2102 2103 cmd = iocp->ioc_cmd; 2104 getcmd = (cmd == SIOCGIPMSFILTER || cmd == SIOCGMSFILTER); 2105 is_v4only_api = (cmd == SIOCGIPMSFILTER || cmd == SIOCSIPMSFILTER); 2106 minsize = (is_v4only_api) ? IP_MSFILTER_SIZE(0) : GROUP_FILTER_SIZE(0); 2107 datalen = MBLKL(data_mp); 2108 2109 if (datalen < minsize) 2110 return (EINVAL); 2111 2112 /* 2113 * now we know we have at least have the initial structure, 2114 * but need to check for the source list array. 2115 */ 2116 if (is_v4only_api) { 2117 imsf = (struct ip_msfilter *)data_mp->b_rptr; 2118 isv6 = B_FALSE; 2119 expsize = IP_MSFILTER_SIZE(imsf->imsf_numsrc); 2120 } else { 2121 gf = (struct group_filter *)data_mp->b_rptr; 2122 if (gf->gf_group.ss_family == AF_INET6) { 2123 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2124 isv6 = !(IN6_IS_ADDR_V4MAPPED(&gsin6->sin6_addr)); 2125 } else { 2126 isv6 = B_FALSE; 2127 } 2128 expsize = GROUP_FILTER_SIZE(gf->gf_numsrc); 2129 } 2130 if (datalen < expsize) 2131 return (EINVAL); 2132 2133 if (isv6) { 2134 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2135 v6group = gsin6->sin6_addr; 2136 if (getcmd) { 2137 err = ip_get_srcfilter(connp, gf, NULL, &v6group, 2138 B_TRUE); 2139 } else { 2140 err = ip_set_srcfilter(connp, gf, NULL, &v6group, ill, 2141 B_TRUE); 2142 } 2143 } else { 2144 boolean_t issin6 = B_FALSE; 2145 if (is_v4only_api) { 2146 v4group = (ipaddr_t)imsf->imsf_multiaddr.s_addr; 2147 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2148 } else { 2149 if (gf->gf_group.ss_family == AF_INET) { 2150 gsin = (struct sockaddr_in *)&gf->gf_group; 2151 v4group = (ipaddr_t)gsin->sin_addr.s_addr; 2152 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2153 } else { 2154 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2155 IN6_V4MAPPED_TO_IPADDR(&gsin6->sin6_addr, 2156 v4group); 2157 issin6 = B_TRUE; 2158 } 2159 } 2160 /* 2161 * INADDR_ANY is represented as the IPv6 unspecifed addr. 2162 */ 2163 if (v4group == INADDR_ANY) 2164 v6group = ipv6_all_zeros; 2165 else 2166 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2167 2168 if (getcmd) { 2169 err = ip_get_srcfilter(connp, gf, imsf, &v6group, 2170 issin6); 2171 } else { 2172 err = ip_set_srcfilter(connp, gf, imsf, &v6group, ill, 2173 issin6); 2174 } 2175 } 2176 ill_refrele(ill); 2177 2178 return (err); 2179 } 2180 2181 /* 2182 * Determine the ill for the SIOC*MSFILTER ioctls 2183 * 2184 * Returns an error for IS_UNDER_IPMP interfaces. 2185 * 2186 * Finds the ill based on information in the ioctl headers. 2187 */ 2188 static int 2189 ip_msfilter_ill(conn_t *connp, mblk_t *mp, const ip_ioctl_cmd_t *ipip, 2190 ill_t **illp) 2191 { 2192 int cmd = ipip->ipi_cmd; 2193 int err = 0; 2194 ill_t *ill; 2195 /* caller has verified this mblk exists */ 2196 char *dbuf = (char *)mp->b_cont->b_cont->b_rptr; 2197 struct ip_msfilter *imsf; 2198 struct group_filter *gf; 2199 ipaddr_t v4addr, v4group; 2200 in6_addr_t v6group; 2201 uint32_t index; 2202 ip_stack_t *ipst; 2203 2204 ipst = connp->conn_netstack->netstack_ip; 2205 2206 *illp = NULL; 2207 2208 /* don't allow multicast operations on a tcp conn */ 2209 if (IPCL_IS_TCP(connp)) 2210 return (ENOPROTOOPT); 2211 2212 if (cmd == SIOCSIPMSFILTER || cmd == SIOCGIPMSFILTER) { 2213 /* don't allow v4-specific ioctls on v6 socket */ 2214 if (connp->conn_family == AF_INET6) 2215 return (EAFNOSUPPORT); 2216 2217 imsf = (struct ip_msfilter *)dbuf; 2218 v4addr = imsf->imsf_interface.s_addr; 2219 v4group = imsf->imsf_multiaddr.s_addr; 2220 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2221 ill = ill_mcast_lookup(&v6group, v4addr, 0, IPCL_ZONEID(connp), 2222 ipst, &err); 2223 if (ill == NULL && v4addr != INADDR_ANY) 2224 err = ENXIO; 2225 } else { 2226 gf = (struct group_filter *)dbuf; 2227 index = gf->gf_interface; 2228 if (gf->gf_group.ss_family == AF_INET6) { 2229 struct sockaddr_in6 *sin6; 2230 2231 sin6 = (struct sockaddr_in6 *)&gf->gf_group; 2232 v6group = sin6->sin6_addr; 2233 } else if (gf->gf_group.ss_family == AF_INET) { 2234 struct sockaddr_in *sin; 2235 2236 sin = (struct sockaddr_in *)&gf->gf_group; 2237 v4group = sin->sin_addr.s_addr; 2238 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2239 } else { 2240 return (EAFNOSUPPORT); 2241 } 2242 ill = ill_mcast_lookup(&v6group, INADDR_ANY, index, 2243 IPCL_ZONEID(connp), ipst, &err); 2244 } 2245 *illp = ill; 2246 return (err); 2247 } 2248 2249 /* 2250 * The structures used for the SIOC*MSFILTER ioctls usually must be copied 2251 * in in two stages, as the first copyin tells us the size of the attached 2252 * source buffer. This function is called by ip_wput_nondata() after the 2253 * first copyin has completed; it figures out how big the second stage 2254 * needs to be, and kicks it off. 2255 * 2256 * In some cases (numsrc < 2), the second copyin is not needed as the 2257 * first one gets a complete structure containing 1 source addr. 2258 * 2259 * The function returns 0 if a second copyin has been started (i.e. there's 2260 * no more work to be done right now), or 1 if the second copyin is not 2261 * needed and ip_wput_nondata() can continue its processing. 2262 */ 2263 int 2264 ip_copyin_msfilter(queue_t *q, mblk_t *mp) 2265 { 2266 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2267 int cmd = iocp->ioc_cmd; 2268 /* validity of this checked in ip_wput_nondata() */ 2269 mblk_t *mp1 = mp->b_cont->b_cont; 2270 int copysize = 0; 2271 int offset; 2272 2273 if (cmd == SIOCSMSFILTER || cmd == SIOCGMSFILTER) { 2274 struct group_filter *gf = (struct group_filter *)mp1->b_rptr; 2275 if (gf->gf_numsrc >= 2) { 2276 offset = sizeof (struct group_filter); 2277 copysize = GROUP_FILTER_SIZE(gf->gf_numsrc) - offset; 2278 } 2279 } else { 2280 struct ip_msfilter *imsf = (struct ip_msfilter *)mp1->b_rptr; 2281 if (imsf->imsf_numsrc >= 2) { 2282 offset = sizeof (struct ip_msfilter); 2283 copysize = IP_MSFILTER_SIZE(imsf->imsf_numsrc) - offset; 2284 } 2285 } 2286 if (copysize > 0) { 2287 mi_copyin_n(q, mp, offset, copysize); 2288 return (0); 2289 } 2290 return (1); 2291 } 2292 2293 /* 2294 * Handle the following optmgmt: 2295 * IP_ADD_MEMBERSHIP must not have joined already 2296 * IPV6_JOIN_GROUP must not have joined already 2297 * MCAST_JOIN_GROUP must not have joined already 2298 * IP_BLOCK_SOURCE must have joined already 2299 * MCAST_BLOCK_SOURCE must have joined already 2300 * IP_JOIN_SOURCE_GROUP may have joined already 2301 * MCAST_JOIN_SOURCE_GROUP may have joined already 2302 * 2303 * fmode and src parameters may be used to determine which option is 2304 * being set, as follows (IPV6_JOIN_GROUP and MCAST_JOIN_GROUP options 2305 * are functionally equivalent): 2306 * opt fmode v6src 2307 * IP_ADD_MEMBERSHIP MODE_IS_EXCLUDE unspecified 2308 * IPV6_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2309 * MCAST_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2310 * IP_BLOCK_SOURCE MODE_IS_EXCLUDE IPv4-mapped addr 2311 * MCAST_BLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 2312 * IP_JOIN_SOURCE_GROUP MODE_IS_INCLUDE IPv4-mapped addr 2313 * MCAST_JOIN_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 2314 * 2315 * Changing the filter mode is not allowed; if a matching ilg already 2316 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2317 * 2318 * Verifies that there is a source address of appropriate scope for 2319 * the group; if not, EADDRNOTAVAIL is returned. 2320 * 2321 * The interface to be used may be identified by an IPv4 address or by an 2322 * interface index. 2323 * 2324 * Handles IPv4-mapped IPv6 multicast addresses by associating them 2325 * with the IPv4 address. Assumes that if v6group is v4-mapped, 2326 * v6src is also v4-mapped. 2327 */ 2328 int 2329 ip_opt_add_group(conn_t *connp, boolean_t checkonly, 2330 const in6_addr_t *v6group, ipaddr_t ifaddr, uint_t ifindex, 2331 mcast_record_t fmode, const in6_addr_t *v6src) 2332 { 2333 ill_t *ill; 2334 char buf[INET6_ADDRSTRLEN]; 2335 int err; 2336 2337 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, &ill); 2338 if (err != 0) { 2339 ip1dbg(("ip_opt_add_group: no ill for group %s/" 2340 "index %d\n", inet_ntop(AF_INET6, v6group, buf, 2341 sizeof (buf)), ifindex)); 2342 return (err); 2343 } 2344 2345 if (checkonly) { 2346 /* 2347 * do not do operation, just pretend to - new T_CHECK 2348 * semantics. The error return case above if encountered 2349 * considered a good enough "check" here. 2350 */ 2351 ill_refrele(ill); 2352 return (0); 2353 } 2354 2355 mutex_enter(&ill->ill_mcast_serializer); 2356 err = ilg_add(connp, v6group, ifaddr, ifindex, ill, fmode, v6src); 2357 mutex_exit(&ill->ill_mcast_serializer); 2358 ill_refrele(ill); 2359 return (err); 2360 } 2361 2362 /* 2363 * Common for IPv6 and IPv4. 2364 * Here we handle ilgs that are still attached to their original ill 2365 * (the one ifaddr/ifindex points at), as well as detached ones. 2366 * The detached ones might have been attached to some other ill. 2367 */ 2368 static int 2369 ip_opt_delete_group_excl(conn_t *connp, const in6_addr_t *v6group, 2370 ipaddr_t ifaddr, uint_t ifindex, mcast_record_t fmode, 2371 const in6_addr_t *v6src) 2372 { 2373 ilg_t *ilg; 2374 boolean_t leaving; 2375 ilm_t *ilm; 2376 ill_t *ill; 2377 int err = 0; 2378 2379 retry: 2380 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2381 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2382 if (ilg == NULL) { 2383 rw_exit(&connp->conn_ilg_lock); 2384 /* 2385 * Since we didn't have any ilg we now do the error checks 2386 * to determine the best errno. 2387 */ 2388 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, 2389 &ill); 2390 if (ill != NULL) { 2391 /* The only error was a missing ilg for the group */ 2392 ill_refrele(ill); 2393 err = EADDRNOTAVAIL; 2394 } 2395 return (err); 2396 } 2397 2398 /* If the ilg is attached then we serialize using that ill */ 2399 ill = ilg->ilg_ill; 2400 if (ill != NULL) { 2401 /* Prevent the ill and ilg from being freed */ 2402 ill_refhold(ill); 2403 ilg_refhold(ilg); 2404 rw_exit(&connp->conn_ilg_lock); 2405 mutex_enter(&ill->ill_mcast_serializer); 2406 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2407 if (ilg->ilg_condemned) { 2408 /* Disappeared */ 2409 ilg_refrele(ilg); 2410 rw_exit(&connp->conn_ilg_lock); 2411 mutex_exit(&ill->ill_mcast_serializer); 2412 ill_refrele(ill); 2413 goto retry; 2414 } 2415 } 2416 2417 /* 2418 * Decide if we're actually deleting the ilg or just removing a 2419 * source filter address; if just removing an addr, make sure we 2420 * aren't trying to change the filter mode, and that the addr is 2421 * actually in our filter list already. If we're removing the 2422 * last src in an include list, just delete the ilg. 2423 */ 2424 if (IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2425 leaving = B_TRUE; 2426 } else { 2427 if (fmode != ilg->ilg_fmode) 2428 err = EINVAL; 2429 else if (ilg->ilg_filter == NULL || 2430 !list_has_addr(ilg->ilg_filter, v6src)) 2431 err = EADDRNOTAVAIL; 2432 if (err != 0) { 2433 if (ill != NULL) 2434 ilg_refrele(ilg); 2435 rw_exit(&connp->conn_ilg_lock); 2436 goto done; 2437 } 2438 if (fmode == MODE_IS_INCLUDE && 2439 ilg->ilg_filter->sl_numsrc == 1) { 2440 leaving = B_TRUE; 2441 v6src = NULL; 2442 } else { 2443 leaving = B_FALSE; 2444 } 2445 } 2446 ilm = ilg->ilg_ilm; 2447 if (leaving) 2448 ilg->ilg_ilm = NULL; 2449 2450 ilg_delete(connp, ilg, v6src); 2451 if (ill != NULL) 2452 ilg_refrele(ilg); 2453 rw_exit(&connp->conn_ilg_lock); 2454 2455 if (ilm != NULL) { 2456 ASSERT(ill != NULL); 2457 (void) ip_delmulti_serial(ilm, B_FALSE, leaving); 2458 } 2459 done: 2460 if (ill != NULL) { 2461 mutex_exit(&ill->ill_mcast_serializer); 2462 ill_refrele(ill); 2463 } 2464 return (err); 2465 } 2466 2467 /* 2468 * Handle the following optmgmt: 2469 * IP_DROP_MEMBERSHIP will leave 2470 * IPV6_LEAVE_GROUP will leave 2471 * MCAST_LEAVE_GROUP will leave 2472 * IP_UNBLOCK_SOURCE will not leave 2473 * MCAST_UNBLOCK_SOURCE will not leave 2474 * IP_LEAVE_SOURCE_GROUP may leave (if leaving last source) 2475 * MCAST_LEAVE_SOURCE_GROUP may leave (if leaving last source) 2476 * 2477 * fmode and src parameters may be used to determine which option is 2478 * being set, as follows: 2479 * opt fmode v6src 2480 * IP_DROP_MEMBERSHIP MODE_IS_INCLUDE unspecified 2481 * IPV6_LEAVE_GROUP MODE_IS_INCLUDE unspecified 2482 * MCAST_LEAVE_GROUP MODE_IS_INCLUDE unspecified 2483 * IP_UNBLOCK_SOURCE MODE_IS_EXCLUDE IPv4-mapped addr 2484 * MCAST_UNBLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 2485 * IP_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE IPv4-mapped addr 2486 * MCAST_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 2487 * 2488 * Changing the filter mode is not allowed; if a matching ilg already 2489 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2490 * 2491 * The interface to be used may be identified by an IPv4 address or by an 2492 * interface index. 2493 * 2494 * Handles IPv4-mapped IPv6 multicast addresses by associating them 2495 * with the IPv4 address. Assumes that if v6group is v4-mapped, 2496 * v6src is also v4-mapped. 2497 */ 2498 int 2499 ip_opt_delete_group(conn_t *connp, boolean_t checkonly, 2500 const in6_addr_t *v6group, ipaddr_t ifaddr, uint_t ifindex, 2501 mcast_record_t fmode, const in6_addr_t *v6src) 2502 { 2503 2504 /* 2505 * In the normal case below we don't check for the ill existing. 2506 * Instead we look for an existing ilg in _excl. 2507 * If checkonly we sanity check the arguments 2508 */ 2509 if (checkonly) { 2510 ill_t *ill; 2511 int err; 2512 2513 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, 2514 &ill); 2515 /* 2516 * do not do operation, just pretend to - new T_CHECK semantics. 2517 * ip_opt_check is considered a good enough "check" here. 2518 */ 2519 if (ill != NULL) 2520 ill_refrele(ill); 2521 return (err); 2522 } 2523 return (ip_opt_delete_group_excl(connp, v6group, ifaddr, ifindex, 2524 fmode, v6src)); 2525 } 2526 2527 /* 2528 * Group mgmt for upper conn that passes things down 2529 * to the interface multicast list (and DLPI) 2530 * These routines can handle new style options that specify an interface name 2531 * as opposed to an interface address (needed for general handling of 2532 * unnumbered interfaces.) 2533 */ 2534 2535 /* 2536 * Add a group to an upper conn group data structure and pass things down 2537 * to the interface multicast list (and DLPI) 2538 * Common for IPv4 and IPv6; for IPv4 we can have an ifaddr. 2539 */ 2540 static int 2541 ilg_add(conn_t *connp, const in6_addr_t *v6group, ipaddr_t ifaddr, 2542 uint_t ifindex, ill_t *ill, mcast_record_t fmode, const in6_addr_t *v6src) 2543 { 2544 int error = 0; 2545 ilg_t *ilg; 2546 ilg_stat_t ilgstat; 2547 slist_t *new_filter = NULL; 2548 int new_fmode; 2549 ilm_t *ilm; 2550 2551 if (!(ill->ill_flags & ILLF_MULTICAST)) 2552 return (EADDRNOTAVAIL); 2553 2554 /* conn_ilg_lock protects the ilg list. */ 2555 ASSERT(MUTEX_HELD(&ill->ill_mcast_serializer)); 2556 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2557 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2558 2559 /* 2560 * Depending on the option we're handling, may or may not be okay 2561 * if group has already been added. Figure out our rules based 2562 * on fmode and src params. Also make sure there's enough room 2563 * in the filter if we're adding a source to an existing filter. 2564 */ 2565 if (IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2566 /* we're joining for all sources, must not have joined */ 2567 if (ilg != NULL) 2568 error = EADDRINUSE; 2569 } else { 2570 if (fmode == MODE_IS_EXCLUDE) { 2571 /* (excl {addr}) => block source, must have joined */ 2572 if (ilg == NULL) 2573 error = EADDRNOTAVAIL; 2574 } 2575 /* (incl {addr}) => join source, may have joined */ 2576 2577 if (ilg != NULL && 2578 SLIST_CNT(ilg->ilg_filter) == MAX_FILTER_SIZE) 2579 error = ENOBUFS; 2580 } 2581 if (error != 0) { 2582 rw_exit(&connp->conn_ilg_lock); 2583 return (error); 2584 } 2585 2586 /* 2587 * Alloc buffer to copy new state into (see below) before 2588 * we make any changes, so we can bail if it fails. 2589 */ 2590 if ((new_filter = l_alloc()) == NULL) { 2591 rw_exit(&connp->conn_ilg_lock); 2592 return (ENOMEM); 2593 } 2594 2595 if (ilg == NULL) { 2596 if ((ilg = conn_ilg_alloc(connp, &error)) == NULL) { 2597 rw_exit(&connp->conn_ilg_lock); 2598 l_free(new_filter); 2599 return (error); 2600 } 2601 ilg->ilg_ifindex = ifindex; 2602 ilg->ilg_ifaddr = ifaddr; 2603 if (!IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2604 ilg->ilg_filter = l_alloc(); 2605 if (ilg->ilg_filter == NULL) { 2606 ilg_delete(connp, ilg, NULL); 2607 rw_exit(&connp->conn_ilg_lock); 2608 l_free(new_filter); 2609 return (ENOMEM); 2610 } 2611 ilg->ilg_filter->sl_numsrc = 1; 2612 ilg->ilg_filter->sl_addr[0] = *v6src; 2613 } 2614 ilgstat = ILGSTAT_NEW; 2615 ilg->ilg_v6group = *v6group; 2616 ilg->ilg_fmode = fmode; 2617 ilg->ilg_ill = ill; 2618 } else { 2619 int index; 2620 if (ilg->ilg_fmode != fmode || IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2621 rw_exit(&connp->conn_ilg_lock); 2622 l_free(new_filter); 2623 return (EINVAL); 2624 } 2625 if (ilg->ilg_filter == NULL) { 2626 ilg->ilg_filter = l_alloc(); 2627 if (ilg->ilg_filter == NULL) { 2628 rw_exit(&connp->conn_ilg_lock); 2629 l_free(new_filter); 2630 return (ENOMEM); 2631 } 2632 } 2633 if (list_has_addr(ilg->ilg_filter, v6src)) { 2634 rw_exit(&connp->conn_ilg_lock); 2635 l_free(new_filter); 2636 return (EADDRNOTAVAIL); 2637 } 2638 ilgstat = ILGSTAT_CHANGE; 2639 index = ilg->ilg_filter->sl_numsrc++; 2640 ilg->ilg_filter->sl_addr[index] = *v6src; 2641 } 2642 2643 /* 2644 * Save copy of ilg's filter state to pass to other functions, 2645 * so we can release conn_ilg_lock now. 2646 */ 2647 new_fmode = ilg->ilg_fmode; 2648 l_copy(ilg->ilg_filter, new_filter); 2649 2650 rw_exit(&connp->conn_ilg_lock); 2651 2652 /* 2653 * Now update the ill. We wait to do this until after the ilg 2654 * has been updated because we need to update the src filter 2655 * info for the ill, which involves looking at the status of 2656 * all the ilgs associated with this group/interface pair. 2657 */ 2658 ilm = ip_addmulti_serial(v6group, ill, connp->conn_zoneid, ilgstat, 2659 new_fmode, new_filter, &error); 2660 2661 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2662 /* 2663 * Must look up the ilg again since we've not been holding 2664 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 2665 * having called conn_update_ill, which can run once we dropped the 2666 * conn_ilg_lock above. 2667 */ 2668 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2669 if (ilg == NULL) { 2670 rw_exit(&connp->conn_ilg_lock); 2671 if (ilm != NULL) { 2672 (void) ip_delmulti_serial(ilm, B_FALSE, 2673 (ilgstat == ILGSTAT_NEW)); 2674 } 2675 error = ENXIO; 2676 goto free_and_exit; 2677 } 2678 2679 if (ilm != NULL) { 2680 /* Succeeded. Update the ilg to point at the ilm */ 2681 if (ilgstat == ILGSTAT_NEW) { 2682 ASSERT(ilg->ilg_ilm == NULL); 2683 ilg->ilg_ilm = ilm; 2684 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 2685 } else { 2686 /* 2687 * ip_addmulti didn't get a held ilm for 2688 * ILGSTAT_CHANGE; ilm_refcnt was unchanged. 2689 */ 2690 ASSERT(ilg->ilg_ilm == ilm); 2691 } 2692 } else { 2693 ASSERT(error != 0); 2694 /* 2695 * Failed to allocate the ilm. 2696 * Need to undo what we did before calling ip_addmulti() 2697 * If ENETDOWN just clear ill_ilg since so that we 2698 * will rejoin when the ill comes back; don't report ENETDOWN 2699 * to application. 2700 */ 2701 if (ilgstat == ILGSTAT_NEW && error == ENETDOWN) { 2702 ilg->ilg_ill = NULL; 2703 error = 0; 2704 } else { 2705 in6_addr_t delsrc = 2706 (ilgstat == ILGSTAT_NEW) ? ipv6_all_zeros : *v6src; 2707 2708 ilg_delete(connp, ilg, &delsrc); 2709 } 2710 } 2711 rw_exit(&connp->conn_ilg_lock); 2712 2713 free_and_exit: 2714 l_free(new_filter); 2715 return (error); 2716 } 2717 2718 /* 2719 * Find an IPv4 ilg matching group, ill and source. 2720 * The group and source can't be INADDR_ANY here so no need to translate to 2721 * the unspecified IPv6 address. 2722 */ 2723 boolean_t 2724 conn_hasmembers_ill_withsrc_v4(conn_t *connp, ipaddr_t group, ipaddr_t src, 2725 ill_t *ill) 2726 { 2727 in6_addr_t v6group, v6src; 2728 int i; 2729 boolean_t isinlist; 2730 ilg_t *ilg; 2731 2732 rw_enter(&connp->conn_ilg_lock, RW_READER); 2733 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 2734 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2735 if (ilg->ilg_condemned) 2736 continue; 2737 2738 /* ilg_ill could be NULL if an add is in progress */ 2739 if (ilg->ilg_ill != ill) 2740 continue; 2741 2742 /* The callers use upper ill for IPMP */ 2743 ASSERT(!IS_UNDER_IPMP(ill)); 2744 if (IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, &v6group)) { 2745 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 2746 /* no source filter, so this is a match */ 2747 rw_exit(&connp->conn_ilg_lock); 2748 return (B_TRUE); 2749 } 2750 break; 2751 } 2752 } 2753 if (ilg == NULL) { 2754 rw_exit(&connp->conn_ilg_lock); 2755 return (B_FALSE); 2756 } 2757 2758 /* 2759 * we have an ilg with matching ill and group; but 2760 * the ilg has a source list that we must check. 2761 */ 2762 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 2763 isinlist = B_FALSE; 2764 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 2765 if (IN6_ARE_ADDR_EQUAL(&v6src, &ilg->ilg_filter->sl_addr[i])) { 2766 isinlist = B_TRUE; 2767 break; 2768 } 2769 } 2770 2771 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 2772 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) { 2773 rw_exit(&connp->conn_ilg_lock); 2774 return (B_TRUE); 2775 } 2776 rw_exit(&connp->conn_ilg_lock); 2777 return (B_FALSE); 2778 } 2779 2780 /* 2781 * Find an IPv6 ilg matching group, ill, and source 2782 */ 2783 boolean_t 2784 conn_hasmembers_ill_withsrc_v6(conn_t *connp, const in6_addr_t *v6group, 2785 const in6_addr_t *v6src, ill_t *ill) 2786 { 2787 int i; 2788 boolean_t isinlist; 2789 ilg_t *ilg; 2790 2791 rw_enter(&connp->conn_ilg_lock, RW_READER); 2792 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2793 if (ilg->ilg_condemned) 2794 continue; 2795 2796 /* ilg_ill could be NULL if an add is in progress */ 2797 if (ilg->ilg_ill != ill) 2798 continue; 2799 2800 /* The callers use upper ill for IPMP */ 2801 ASSERT(!IS_UNDER_IPMP(ill)); 2802 if (IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) { 2803 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 2804 /* no source filter, so this is a match */ 2805 rw_exit(&connp->conn_ilg_lock); 2806 return (B_TRUE); 2807 } 2808 break; 2809 } 2810 } 2811 if (ilg == NULL) { 2812 rw_exit(&connp->conn_ilg_lock); 2813 return (B_FALSE); 2814 } 2815 2816 /* 2817 * we have an ilg with matching ill and group; but 2818 * the ilg has a source list that we must check. 2819 */ 2820 isinlist = B_FALSE; 2821 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 2822 if (IN6_ARE_ADDR_EQUAL(v6src, &ilg->ilg_filter->sl_addr[i])) { 2823 isinlist = B_TRUE; 2824 break; 2825 } 2826 } 2827 2828 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 2829 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) { 2830 rw_exit(&connp->conn_ilg_lock); 2831 return (B_TRUE); 2832 } 2833 rw_exit(&connp->conn_ilg_lock); 2834 return (B_FALSE); 2835 } 2836 2837 /* 2838 * Find an ilg matching group and ifaddr/ifindex. 2839 * We check both ifaddr and ifindex even though at most one of them 2840 * will be non-zero; that way we always find the right one. 2841 */ 2842 static ilg_t * 2843 ilg_lookup(conn_t *connp, const in6_addr_t *v6group, ipaddr_t ifaddr, 2844 uint_t ifindex) 2845 { 2846 ilg_t *ilg; 2847 2848 ASSERT(RW_LOCK_HELD(&connp->conn_ilg_lock)); 2849 2850 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2851 if (ilg->ilg_condemned) 2852 continue; 2853 2854 if (ilg->ilg_ifaddr == ifaddr && 2855 ilg->ilg_ifindex == ifindex && 2856 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) 2857 return (ilg); 2858 } 2859 return (NULL); 2860 } 2861 2862 /* 2863 * If a source address is passed in (src != NULL and src is not 2864 * unspecified), remove the specified src addr from the given ilg's 2865 * filter list, else delete the ilg. 2866 */ 2867 static void 2868 ilg_delete(conn_t *connp, ilg_t *ilg, const in6_addr_t *src) 2869 { 2870 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 2871 ASSERT(ilg->ilg_ptpn != NULL); 2872 ASSERT(!ilg->ilg_condemned); 2873 2874 if (src == NULL || IN6_IS_ADDR_UNSPECIFIED(src)) { 2875 FREE_SLIST(ilg->ilg_filter); 2876 ilg->ilg_filter = NULL; 2877 2878 ASSERT(ilg->ilg_ilm == NULL); 2879 ilg->ilg_ill = NULL; 2880 ilg->ilg_condemned = B_TRUE; 2881 2882 /* ilg_inactive will unlink from the list */ 2883 ilg_refrele(ilg); 2884 } else { 2885 l_remove(ilg->ilg_filter, src); 2886 } 2887 } 2888 2889 /* 2890 * Called from conn close. No new ilg can be added or removed 2891 * because CONN_CLOSING has been set by ip_close. ilg_add / ilg_delete 2892 * will return error if conn has started closing. 2893 * 2894 * We handle locking as follows. 2895 * Under conn_ilg_lock we get the first ilg. As we drop the conn_ilg_lock to 2896 * proceed with the ilm part of the delete we hold a reference on both the ill 2897 * and the ilg. This doesn't prevent changes to the ilg, but prevents it from 2898 * being deleted. 2899 * 2900 * Since the ilg_add code path uses two locks (conn_ilg_lock for the ilg part, 2901 * and ill_mcast_lock for the ip_addmulti part) we can run at a point between 2902 * the two. At that point ilg_ill is set, but ilg_ilm hasn't yet been set. In 2903 * that case we delete the ilg here, which makes ilg_add discover that the ilg 2904 * has disappeared when ip_addmulti returns, so it will discard the ilm it just 2905 * added. 2906 */ 2907 void 2908 ilg_delete_all(conn_t *connp) 2909 { 2910 ilg_t *ilg, *next_ilg, *held_ilg; 2911 ilm_t *ilm; 2912 ill_t *ill; 2913 boolean_t need_refrele; 2914 2915 /* 2916 * Can not run if there is a conn_update_ill already running. 2917 * Wait for it to complete. Caller should have already set CONN_CLOSING 2918 * which prevents any new threads to run in conn_update_ill. 2919 */ 2920 mutex_enter(&connp->conn_lock); 2921 ASSERT(connp->conn_state_flags & CONN_CLOSING); 2922 while (connp->conn_state_flags & CONN_UPDATE_ILL) 2923 cv_wait(&connp->conn_cv, &connp->conn_lock); 2924 mutex_exit(&connp->conn_lock); 2925 2926 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2927 ilg = connp->conn_ilg; 2928 held_ilg = NULL; 2929 while (ilg != NULL) { 2930 if (ilg->ilg_condemned) { 2931 ilg = ilg->ilg_next; 2932 continue; 2933 } 2934 /* If the ilg is detached then no need to serialize */ 2935 if (ilg->ilg_ilm == NULL) { 2936 next_ilg = ilg->ilg_next; 2937 ilg_delete(connp, ilg, NULL); 2938 ilg = next_ilg; 2939 continue; 2940 } 2941 ill = ilg->ilg_ilm->ilm_ill; 2942 2943 /* 2944 * In order to serialize on the ill we try to enter 2945 * and if that fails we unlock and relock and then 2946 * check that we still have an ilm. 2947 */ 2948 need_refrele = B_FALSE; 2949 if (!mutex_tryenter(&ill->ill_mcast_serializer)) { 2950 ill_refhold(ill); 2951 need_refrele = B_TRUE; 2952 ilg_refhold(ilg); 2953 if (held_ilg != NULL) 2954 ilg_refrele(held_ilg); 2955 held_ilg = ilg; 2956 rw_exit(&connp->conn_ilg_lock); 2957 mutex_enter(&ill->ill_mcast_serializer); 2958 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2959 if (ilg->ilg_condemned) { 2960 ilg = ilg->ilg_next; 2961 goto next; 2962 } 2963 } 2964 ilm = ilg->ilg_ilm; 2965 ilg->ilg_ilm = NULL; 2966 next_ilg = ilg->ilg_next; 2967 ilg_delete(connp, ilg, NULL); 2968 ilg = next_ilg; 2969 rw_exit(&connp->conn_ilg_lock); 2970 2971 if (ilm != NULL) 2972 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 2973 2974 next: 2975 mutex_exit(&ill->ill_mcast_serializer); 2976 if (need_refrele) { 2977 /* Drop ill reference while we hold no locks */ 2978 ill_refrele(ill); 2979 } 2980 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2981 } 2982 if (held_ilg != NULL) 2983 ilg_refrele(held_ilg); 2984 rw_exit(&connp->conn_ilg_lock); 2985 } 2986 2987 /* 2988 * Attach the ilg to an ilm on the ill. If it fails we leave ilg_ill as NULL so 2989 * that a subsequent attempt can attach it. 2990 * Drops and reacquires conn_ilg_lock. 2991 */ 2992 static void 2993 ilg_attach(conn_t *connp, ilg_t *ilg, ill_t *ill) 2994 { 2995 ilg_stat_t ilgstat; 2996 slist_t *new_filter; 2997 int new_fmode; 2998 in6_addr_t v6group; 2999 ipaddr_t ifaddr; 3000 uint_t ifindex; 3001 ilm_t *ilm; 3002 int error = 0; 3003 3004 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 3005 /* 3006 * Alloc buffer to copy new state into (see below) before 3007 * we make any changes, so we can bail if it fails. 3008 */ 3009 if ((new_filter = l_alloc()) == NULL) 3010 return; 3011 3012 /* 3013 * Save copy of ilg's filter state to pass to other functions, so 3014 * we can release conn_ilg_lock now. 3015 * Set ilg_ill so that an unplumb can find us. 3016 */ 3017 new_fmode = ilg->ilg_fmode; 3018 l_copy(ilg->ilg_filter, new_filter); 3019 v6group = ilg->ilg_v6group; 3020 ifaddr = ilg->ilg_ifaddr; 3021 ifindex = ilg->ilg_ifindex; 3022 ilgstat = ILGSTAT_NEW; 3023 3024 ilg->ilg_ill = ill; 3025 ASSERT(ilg->ilg_ilm == NULL); 3026 rw_exit(&connp->conn_ilg_lock); 3027 3028 ilm = ip_addmulti_serial(&v6group, ill, connp->conn_zoneid, ilgstat, 3029 new_fmode, new_filter, &error); 3030 l_free(new_filter); 3031 3032 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3033 /* 3034 * Must look up the ilg again since we've not been holding 3035 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 3036 * having called conn_update_ill, which can run once we dropped the 3037 * conn_ilg_lock above. 3038 */ 3039 ilg = ilg_lookup(connp, &v6group, ifaddr, ifindex); 3040 if (ilg == NULL) { 3041 if (ilm != NULL) { 3042 rw_exit(&connp->conn_ilg_lock); 3043 (void) ip_delmulti_serial(ilm, B_FALSE, 3044 (ilgstat == ILGSTAT_NEW)); 3045 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3046 } 3047 return; 3048 } 3049 if (ilm == NULL) { 3050 ilg->ilg_ill = NULL; 3051 return; 3052 } 3053 ASSERT(ilg->ilg_ilm == NULL); 3054 ilg->ilg_ilm = ilm; 3055 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 3056 } 3057 3058 /* 3059 * Called when an ill is unplumbed to make sure that there are no 3060 * dangling conn references to that ill. In that case ill is non-NULL and 3061 * we make sure we remove all references to it. 3062 * Also called when we should revisit the ilg_ill used for multicast 3063 * memberships, in which case ill is NULL. 3064 * 3065 * conn is held by caller. 3066 * 3067 * Note that ipcl_walk only walks conns that are not yet condemned. 3068 * condemned conns can't be refheld. For this reason, conn must become clean 3069 * first, i.e. it must not refer to any ill/ire and then only set 3070 * condemned flag. 3071 * 3072 * We leave ixa_multicast_ifindex in place. We prefer dropping 3073 * packets instead of sending them out the wrong interface. 3074 * 3075 * We keep the ilg around in a detached state (with ilg_ill and ilg_ilm being 3076 * NULL) so that the application can leave it later. Also, if ilg_ifaddr and 3077 * ilg_ifindex are zero, indicating that the system should pick the interface, 3078 * then we attempt to reselect the ill and join on it. 3079 * 3080 * Locking notes: 3081 * Under conn_ilg_lock we get the first ilg. As we drop the conn_ilg_lock to 3082 * proceed with the ilm part of the delete we hold a reference on both the ill 3083 * and the ilg. This doesn't prevent changes to the ilg, but prevents it from 3084 * being deleted. 3085 * 3086 * Note: if this function is called when new ill/ipif's arrive or change status 3087 * (SIOCSLIFINDEX, SIOCSLIFADDR) then we will attempt to attach any ilgs with 3088 * a NULL ilg_ill to an ill/ilm. 3089 */ 3090 static void 3091 conn_update_ill(conn_t *connp, caddr_t arg) 3092 { 3093 ill_t *ill = (ill_t *)arg; 3094 3095 /* 3096 * We have to prevent ip_close/ilg_delete_all from running at 3097 * the same time. ip_close sets CONN_CLOSING before doing the ilg_delete 3098 * all, and we set CONN_UPDATE_ILL. That ensures that only one of 3099 * ilg_delete_all and conn_update_ill run at a time for a given conn. 3100 * If ilg_delete_all got here first, then we have nothing to do. 3101 */ 3102 mutex_enter(&connp->conn_lock); 3103 if (connp->conn_state_flags & (CONN_CLOSING|CONN_UPDATE_ILL)) { 3104 /* Caller has to wait for ill_ilm_cnt to drop to zero */ 3105 mutex_exit(&connp->conn_lock); 3106 return; 3107 } 3108 connp->conn_state_flags |= CONN_UPDATE_ILL; 3109 mutex_exit(&connp->conn_lock); 3110 3111 if (ill != NULL) 3112 ilg_check_detach(connp, ill); 3113 3114 ilg_check_reattach(connp); 3115 3116 /* Do we need to wake up a thread in ilg_delete_all? */ 3117 mutex_enter(&connp->conn_lock); 3118 connp->conn_state_flags &= ~CONN_UPDATE_ILL; 3119 if (connp->conn_state_flags & CONN_CLOSING) 3120 cv_broadcast(&connp->conn_cv); 3121 mutex_exit(&connp->conn_lock); 3122 } 3123 3124 /* Detach from an ill that is going away */ 3125 static void 3126 ilg_check_detach(conn_t *connp, ill_t *ill) 3127 { 3128 char group_buf[INET6_ADDRSTRLEN]; 3129 ilg_t *ilg, *held_ilg; 3130 ilm_t *ilm; 3131 3132 mutex_enter(&ill->ill_mcast_serializer); 3133 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3134 held_ilg = NULL; 3135 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 3136 if (ilg->ilg_condemned) 3137 continue; 3138 3139 if (ilg->ilg_ill != ill) 3140 continue; 3141 3142 /* Detach from current ill */ 3143 ip1dbg(("ilg_check_detach: detach %s on %s\n", 3144 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3145 group_buf, sizeof (group_buf)), 3146 ilg->ilg_ill->ill_name)); 3147 3148 /* Detach this ilg from the ill/ilm */ 3149 ilm = ilg->ilg_ilm; 3150 ilg->ilg_ilm = NULL; 3151 ilg->ilg_ill = NULL; 3152 if (ilm == NULL) 3153 continue; 3154 3155 /* Prevent ilg from disappearing */ 3156 ilg_transfer_hold(held_ilg, ilg); 3157 held_ilg = ilg; 3158 rw_exit(&connp->conn_ilg_lock); 3159 3160 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 3161 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3162 } 3163 if (held_ilg != NULL) 3164 ilg_refrele(held_ilg); 3165 rw_exit(&connp->conn_ilg_lock); 3166 mutex_exit(&ill->ill_mcast_serializer); 3167 } 3168 3169 /* 3170 * Check if there is a place to attach the conn_ilgs. We do this for both 3171 * detached ilgs and attached ones, since for the latter there could be 3172 * a better ill to attach them to. 3173 */ 3174 static void 3175 ilg_check_reattach(conn_t *connp) 3176 { 3177 ill_t *ill; 3178 char group_buf[INET6_ADDRSTRLEN]; 3179 ilg_t *ilg, *held_ilg; 3180 ilm_t *ilm; 3181 zoneid_t zoneid = IPCL_ZONEID(connp); 3182 int error; 3183 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 3184 3185 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3186 held_ilg = NULL; 3187 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 3188 if (ilg->ilg_condemned) 3189 continue; 3190 3191 /* Check if the conn_ill matches what we would pick now */ 3192 ill = ill_mcast_lookup(&ilg->ilg_v6group, ilg->ilg_ifaddr, 3193 ilg->ilg_ifindex, zoneid, ipst, &error); 3194 3195 /* 3196 * Make sure the ill is usable for multicast and that 3197 * we can send the DL_ADDMULTI_REQ before we create an 3198 * ilm. 3199 */ 3200 if (ill != NULL && 3201 (!(ill->ill_flags & ILLF_MULTICAST) || !ill->ill_dl_up)) { 3202 /* Drop locks across ill_refrele */ 3203 ilg_transfer_hold(held_ilg, ilg); 3204 held_ilg = ilg; 3205 rw_exit(&connp->conn_ilg_lock); 3206 ill_refrele(ill); 3207 ill = NULL; 3208 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3209 /* Note that ilg could have become condemned */ 3210 } 3211 3212 /* Is the ill unchanged, even if both are NULL? */ 3213 if (ill == ilg->ilg_ill) { 3214 if (ill != NULL) { 3215 /* Drop locks across ill_refrele */ 3216 ilg_transfer_hold(held_ilg, ilg); 3217 held_ilg = ilg; 3218 rw_exit(&connp->conn_ilg_lock); 3219 ill_refrele(ill); 3220 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3221 } 3222 continue; 3223 } 3224 3225 /* Something changed; detach from old first if needed */ 3226 if (ilg->ilg_ill != NULL) { 3227 ill_t *ill2 = ilg->ilg_ill; 3228 boolean_t need_refrele = B_FALSE; 3229 3230 /* 3231 * In order to serialize on the ill we try to enter 3232 * and if that fails we unlock and relock. 3233 */ 3234 if (!mutex_tryenter(&ill2->ill_mcast_serializer)) { 3235 ill_refhold(ill2); 3236 need_refrele = B_TRUE; 3237 ilg_transfer_hold(held_ilg, ilg); 3238 held_ilg = ilg; 3239 rw_exit(&connp->conn_ilg_lock); 3240 mutex_enter(&ill2->ill_mcast_serializer); 3241 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3242 /* Note that ilg could have become condemned */ 3243 } 3244 /* 3245 * Check that nobody else re-attached the ilg while we 3246 * dropped the lock. 3247 */ 3248 if (ilg->ilg_ill == ill2) { 3249 ASSERT(!ilg->ilg_condemned); 3250 /* Detach from current ill */ 3251 ip1dbg(("conn_check_reattach: detach %s/%s\n", 3252 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3253 group_buf, sizeof (group_buf)), 3254 ill2->ill_name)); 3255 3256 ilm = ilg->ilg_ilm; 3257 ilg->ilg_ilm = NULL; 3258 ilg->ilg_ill = NULL; 3259 } else { 3260 ilm = NULL; 3261 } 3262 rw_exit(&connp->conn_ilg_lock); 3263 if (ilm != NULL) 3264 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 3265 mutex_exit(&ill2->ill_mcast_serializer); 3266 if (need_refrele) { 3267 /* Drop ill reference while we hold no locks */ 3268 ill_refrele(ill2); 3269 } 3270 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3271 /* 3272 * While we dropped conn_ilg_lock some other thread 3273 * could have attached this ilg, thus we check again. 3274 */ 3275 if (ilg->ilg_ill != NULL) { 3276 if (ill != NULL) { 3277 /* Drop locks across ill_refrele */ 3278 ilg_transfer_hold(held_ilg, ilg); 3279 held_ilg = ilg; 3280 rw_exit(&connp->conn_ilg_lock); 3281 ill_refrele(ill); 3282 rw_enter(&connp->conn_ilg_lock, 3283 RW_WRITER); 3284 } 3285 continue; 3286 } 3287 } 3288 if (ill != NULL) { 3289 /* 3290 * In order to serialize on the ill we try to enter 3291 * and if that fails we unlock and relock. 3292 */ 3293 if (!mutex_tryenter(&ill->ill_mcast_serializer)) { 3294 /* Already have a refhold on ill */ 3295 ilg_transfer_hold(held_ilg, ilg); 3296 held_ilg = ilg; 3297 rw_exit(&connp->conn_ilg_lock); 3298 mutex_enter(&ill->ill_mcast_serializer); 3299 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3300 /* Note that ilg could have become condemned */ 3301 } 3302 3303 /* 3304 * Check that nobody else attached the ilg and that 3305 * it wasn't condemned while we dropped the lock. 3306 */ 3307 if (ilg->ilg_ill == NULL && !ilg->ilg_condemned) { 3308 /* 3309 * Attach to the new ill. Can fail in which 3310 * case ilg_ill will remain NULL. ilg_attach 3311 * drops and reacquires conn_ilg_lock. 3312 */ 3313 ip1dbg(("conn_check_reattach: attach %s/%s\n", 3314 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3315 group_buf, sizeof (group_buf)), 3316 ill->ill_name)); 3317 ilg_attach(connp, ilg, ill); 3318 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 3319 } 3320 mutex_exit(&ill->ill_mcast_serializer); 3321 /* Drop locks across ill_refrele */ 3322 ilg_transfer_hold(held_ilg, ilg); 3323 held_ilg = ilg; 3324 rw_exit(&connp->conn_ilg_lock); 3325 ill_refrele(ill); 3326 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3327 } 3328 } 3329 if (held_ilg != NULL) 3330 ilg_refrele(held_ilg); 3331 rw_exit(&connp->conn_ilg_lock); 3332 } 3333 3334 /* 3335 * Called when an ill is unplumbed to make sure that there are no 3336 * dangling conn references to that ill. In that case ill is non-NULL and 3337 * we make sure we remove all references to it. 3338 * Also called when we should revisit the ilg_ill used for multicast 3339 * memberships, in which case ill is NULL. 3340 */ 3341 void 3342 update_conn_ill(ill_t *ill, ip_stack_t *ipst) 3343 { 3344 ipcl_walk(conn_update_ill, (caddr_t)ill, ipst); 3345 } 3346