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 (!ill->ill_dl_up) { 926 /* 927 * Nobody there. All multicast addresses will be re-joined 928 * when we get the DL_BIND_ACK bringing the interface up. 929 */ 930 return (ENETDOWN); 931 } 932 933 if (IS_IPMP(ill)) { 934 /* On the upper IPMP ill. */ 935 release_ill = ipmp_illgrp_hold_cast_ill(ill->ill_grp); 936 if (release_ill == NULL) { 937 /* 938 * Avoid sending it down to the ipmpstub. 939 * We will be called again once the members of the 940 * group are in place 941 */ 942 ip1dbg(("ill_join_allmulti: no cast_ill for %s %d\n", 943 ill->ill_name, ill->ill_isv6)); 944 return (0); 945 } 946 ill = release_ill; 947 if (!ill->ill_dl_up) { 948 ill_refrele(ill); 949 return (ENETDOWN); 950 } 951 } 952 953 /* 954 * Create a DL_PROMISCON_REQ message and send it directly to the DLPI 955 * provider. We don't need to do this for certain media types for 956 * which we never need to turn promiscuous mode on. While we're here, 957 * pre-allocate a DL_PROMISCOFF_REQ message to make sure that 958 * ill_leave_allmulti() will not fail due to low memory conditions. 959 */ 960 if ((ill->ill_net_type == IRE_IF_RESOLVER) && 961 !(ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST)) { 962 promiscon_mp = ill_create_dl(ill, DL_PROMISCON_REQ, 963 &addrlen, &addroff); 964 if (ill->ill_promiscoff_mp == NULL) 965 promiscoff_mp = ill_create_dl(ill, DL_PROMISCOFF_REQ, 966 &addrlen, &addroff); 967 if (promiscon_mp == NULL || 968 (ill->ill_promiscoff_mp == NULL && promiscoff_mp == NULL)) { 969 freemsg(promiscon_mp); 970 freemsg(promiscoff_mp); 971 if (release_ill != NULL) 972 ill_refrele(release_ill); 973 return (ENOMEM); 974 } 975 if (ill->ill_promiscoff_mp == NULL) 976 ill->ill_promiscoff_mp = promiscoff_mp; 977 ill_dlpi_queue(ill, promiscon_mp); 978 } 979 if (release_ill != NULL) 980 ill_refrele(release_ill); 981 return (0); 982 } 983 984 /* 985 * Make the driver stop passing up all multicast packets 986 */ 987 void 988 ill_leave_allmulti(ill_t *ill) 989 { 990 mblk_t *promiscoff_mp; 991 ill_t *release_ill = NULL; 992 993 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 994 995 if (!ill->ill_dl_up) { 996 /* 997 * Nobody there. All multicast addresses will be re-joined 998 * when we get the DL_BIND_ACK bringing the interface up. 999 */ 1000 return; 1001 } 1002 1003 if (IS_IPMP(ill)) { 1004 /* On the upper IPMP ill. */ 1005 release_ill = ipmp_illgrp_hold_cast_ill(ill->ill_grp); 1006 if (release_ill == NULL) { 1007 /* 1008 * Avoid sending it down to the ipmpstub. 1009 * We will be called again once the members of the 1010 * group are in place 1011 */ 1012 ip1dbg(("ill_leave_allmulti: no cast_ill on %s %d\n", 1013 ill->ill_name, ill->ill_isv6)); 1014 return; 1015 } 1016 ill = release_ill; 1017 if (!ill->ill_dl_up) 1018 goto done; 1019 } 1020 1021 /* 1022 * In the case of IPMP and ill_dl_up not being set when we joined 1023 * we didn't allocate a promiscoff_mp. In that case we have 1024 * nothing to do when we leave. 1025 * Ditto for PHYI_MULTI_BCAST 1026 */ 1027 promiscoff_mp = ill->ill_promiscoff_mp; 1028 if (promiscoff_mp != NULL) { 1029 ill->ill_promiscoff_mp = NULL; 1030 ill_dlpi_queue(ill, promiscoff_mp); 1031 } 1032 done: 1033 if (release_ill != NULL) 1034 ill_refrele(release_ill); 1035 } 1036 1037 int 1038 ip_join_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1039 { 1040 ill_t *ill; 1041 int ret; 1042 ilm_t *ilm; 1043 1044 ill = ill_lookup_on_ifindex(ifindex, isv6, ipst); 1045 if (ill == NULL) 1046 return (ENODEV); 1047 1048 /* 1049 * The ip_addmulti() function doesn't allow IPMP underlying interfaces 1050 * to join allmulti since only the nominated underlying interface in 1051 * the group should receive multicast. We silently succeed to avoid 1052 * having to teach IPobs (currently the only caller of this routine) 1053 * to ignore failures in this case. 1054 */ 1055 if (IS_UNDER_IPMP(ill)) { 1056 ill_refrele(ill); 1057 return (0); 1058 } 1059 mutex_enter(&ill->ill_lock); 1060 if (ill->ill_ipallmulti_cnt > 0) { 1061 /* Already joined */ 1062 ASSERT(ill->ill_ipallmulti_ilm != NULL); 1063 ill->ill_ipallmulti_cnt++; 1064 mutex_exit(&ill->ill_lock); 1065 goto done; 1066 } 1067 mutex_exit(&ill->ill_lock); 1068 1069 ilm = ip_addmulti(&ipv6_all_zeros, ill, ill->ill_zoneid, &ret); 1070 if (ilm == NULL) { 1071 ASSERT(ret != 0); 1072 ill_refrele(ill); 1073 return (ret); 1074 } 1075 1076 mutex_enter(&ill->ill_lock); 1077 if (ill->ill_ipallmulti_cnt > 0) { 1078 /* Another thread added it concurrently */ 1079 (void) ip_delmulti(ilm); 1080 mutex_exit(&ill->ill_lock); 1081 goto done; 1082 } 1083 ASSERT(ill->ill_ipallmulti_ilm == NULL); 1084 ill->ill_ipallmulti_ilm = ilm; 1085 ill->ill_ipallmulti_cnt++; 1086 mutex_exit(&ill->ill_lock); 1087 done: 1088 ill_refrele(ill); 1089 return (0); 1090 } 1091 1092 int 1093 ip_leave_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1094 { 1095 ill_t *ill; 1096 ilm_t *ilm; 1097 1098 ill = ill_lookup_on_ifindex(ifindex, isv6, ipst); 1099 if (ill == NULL) 1100 return (ENODEV); 1101 1102 if (IS_UNDER_IPMP(ill)) { 1103 ill_refrele(ill); 1104 return (0); 1105 } 1106 1107 mutex_enter(&ill->ill_lock); 1108 if (ill->ill_ipallmulti_cnt == 0) { 1109 /* ip_purge_allmulti could have removed them all */ 1110 mutex_exit(&ill->ill_lock); 1111 goto done; 1112 } 1113 ill->ill_ipallmulti_cnt--; 1114 if (ill->ill_ipallmulti_cnt == 0) { 1115 /* Last one */ 1116 ilm = ill->ill_ipallmulti_ilm; 1117 ill->ill_ipallmulti_ilm = NULL; 1118 } else { 1119 ilm = NULL; 1120 } 1121 mutex_exit(&ill->ill_lock); 1122 if (ilm != NULL) 1123 (void) ip_delmulti(ilm); 1124 1125 done: 1126 ill_refrele(ill); 1127 return (0); 1128 } 1129 1130 /* 1131 * Delete the allmulti memberships that were added as part of 1132 * ip_join_allmulti(). 1133 */ 1134 void 1135 ip_purge_allmulti(ill_t *ill) 1136 { 1137 ilm_t *ilm; 1138 1139 ASSERT(IAM_WRITER_ILL(ill)); 1140 1141 mutex_enter(&ill->ill_lock); 1142 ilm = ill->ill_ipallmulti_ilm; 1143 ill->ill_ipallmulti_ilm = NULL; 1144 ill->ill_ipallmulti_cnt = 0; 1145 mutex_exit(&ill->ill_lock); 1146 1147 if (ilm != NULL) 1148 (void) ip_delmulti(ilm); 1149 } 1150 1151 /* 1152 * Create a dlpi message with room for phys+sap. Later 1153 * we will strip the sap for those primitives which 1154 * only need a physical address. 1155 */ 1156 static mblk_t * 1157 ill_create_dl(ill_t *ill, uint32_t dl_primitive, 1158 uint32_t *addr_lenp, uint32_t *addr_offp) 1159 { 1160 mblk_t *mp; 1161 uint32_t hw_addr_length; 1162 char *cp; 1163 uint32_t offset; 1164 uint32_t length; 1165 uint32_t size; 1166 1167 *addr_lenp = *addr_offp = 0; 1168 1169 hw_addr_length = ill->ill_phys_addr_length; 1170 if (!hw_addr_length) { 1171 ip0dbg(("ip_create_dl: hw addr length = 0\n")); 1172 return (NULL); 1173 } 1174 1175 switch (dl_primitive) { 1176 case DL_ENABMULTI_REQ: 1177 length = sizeof (dl_enabmulti_req_t); 1178 size = length + hw_addr_length; 1179 break; 1180 case DL_DISABMULTI_REQ: 1181 length = sizeof (dl_disabmulti_req_t); 1182 size = length + hw_addr_length; 1183 break; 1184 case DL_PROMISCON_REQ: 1185 case DL_PROMISCOFF_REQ: 1186 size = length = sizeof (dl_promiscon_req_t); 1187 break; 1188 default: 1189 return (NULL); 1190 } 1191 mp = allocb(size, BPRI_HI); 1192 if (!mp) 1193 return (NULL); 1194 mp->b_wptr += size; 1195 mp->b_datap->db_type = M_PROTO; 1196 1197 cp = (char *)mp->b_rptr; 1198 offset = length; 1199 1200 switch (dl_primitive) { 1201 case DL_ENABMULTI_REQ: { 1202 dl_enabmulti_req_t *dl = (dl_enabmulti_req_t *)cp; 1203 1204 dl->dl_primitive = dl_primitive; 1205 dl->dl_addr_offset = offset; 1206 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1207 *addr_offp = offset; 1208 break; 1209 } 1210 case DL_DISABMULTI_REQ: { 1211 dl_disabmulti_req_t *dl = (dl_disabmulti_req_t *)cp; 1212 1213 dl->dl_primitive = dl_primitive; 1214 dl->dl_addr_offset = offset; 1215 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1216 *addr_offp = offset; 1217 break; 1218 } 1219 case DL_PROMISCON_REQ: 1220 case DL_PROMISCOFF_REQ: { 1221 dl_promiscon_req_t *dl = (dl_promiscon_req_t *)cp; 1222 1223 dl->dl_primitive = dl_primitive; 1224 dl->dl_level = DL_PROMISC_MULTI; 1225 break; 1226 } 1227 } 1228 ip1dbg(("ill_create_dl: addr_len %d, addr_off %d\n", 1229 *addr_lenp, *addr_offp)); 1230 return (mp); 1231 } 1232 1233 /* 1234 * Rejoin any groups for which we have ilms. 1235 * 1236 * This is only needed for IPMP when the cast_ill changes since that 1237 * change is invisible to the ilm. Other interface changes are handled 1238 * by conn_update_ill. 1239 */ 1240 void 1241 ill_recover_multicast(ill_t *ill) 1242 { 1243 ilm_t *ilm; 1244 char addrbuf[INET6_ADDRSTRLEN]; 1245 1246 ill->ill_need_recover_multicast = 0; 1247 1248 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1249 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1250 /* 1251 * If we have more then one ilm for the group (e.g., with 1252 * different zoneid) then we should not tell the driver 1253 * to join unless this is the first ilm for the group. 1254 */ 1255 if (ilm_numentries(ill, &ilm->ilm_v6addr) > 1 && 1256 ilm_lookup(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) { 1257 continue; 1258 } 1259 1260 ip1dbg(("ill_recover_multicast: %s\n", inet_ntop(AF_INET6, 1261 &ilm->ilm_v6addr, addrbuf, sizeof (addrbuf)))); 1262 1263 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1264 (void) ill_join_allmulti(ill); 1265 } else { 1266 if (ill->ill_isv6) 1267 mld_joingroup(ilm); 1268 else 1269 igmp_joingroup(ilm); 1270 1271 (void) ip_ll_multireq(ill, &ilm->ilm_v6addr, 1272 DL_ENABMULTI_REQ); 1273 } 1274 } 1275 rw_exit(&ill->ill_mcast_lock); 1276 /* Send any deferred/queued DLPI or IP packets */ 1277 ill_mcast_send_queued(ill); 1278 ill_dlpi_send_queued(ill); 1279 ill_mcast_timer_start(ill->ill_ipst); 1280 } 1281 1282 /* 1283 * The opposite of ill_recover_multicast() -- leaves all multicast groups 1284 * that were explicitly joined. 1285 * 1286 * This is only needed for IPMP when the cast_ill changes since that 1287 * change is invisible to the ilm. Other interface changes are handled 1288 * by conn_update_ill. 1289 */ 1290 void 1291 ill_leave_multicast(ill_t *ill) 1292 { 1293 ilm_t *ilm; 1294 char addrbuf[INET6_ADDRSTRLEN]; 1295 1296 ill->ill_need_recover_multicast = 1; 1297 1298 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1299 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1300 /* 1301 * If we have more then one ilm for the group (e.g., with 1302 * different zoneid) then we should not tell the driver 1303 * to leave unless this is the first ilm for the group. 1304 */ 1305 if (ilm_numentries(ill, &ilm->ilm_v6addr) > 1 && 1306 ilm_lookup(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) { 1307 continue; 1308 } 1309 1310 ip1dbg(("ill_leave_multicast: %s\n", inet_ntop(AF_INET6, 1311 &ilm->ilm_v6addr, addrbuf, sizeof (addrbuf)))); 1312 1313 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1314 ill_leave_allmulti(ill); 1315 } else { 1316 if (ill->ill_isv6) 1317 mld_leavegroup(ilm); 1318 else 1319 igmp_leavegroup(ilm); 1320 1321 (void) ip_ll_multireq(ill, &ilm->ilm_v6addr, 1322 DL_DISABMULTI_REQ); 1323 } 1324 } 1325 rw_exit(&ill->ill_mcast_lock); 1326 /* Send any deferred/queued DLPI or IP packets */ 1327 ill_mcast_send_queued(ill); 1328 ill_dlpi_send_queued(ill); 1329 ill_mcast_timer_start(ill->ill_ipst); 1330 } 1331 1332 /* 1333 * Interface used by IP input/output. 1334 * Returns true if there is a member on the ill for any zoneid. 1335 */ 1336 boolean_t 1337 ill_hasmembers_v6(ill_t *ill, const in6_addr_t *v6group) 1338 { 1339 ilm_t *ilm; 1340 1341 rw_enter(&ill->ill_mcast_lock, RW_READER); 1342 ilm = ilm_lookup(ill, v6group, ALL_ZONES); 1343 rw_exit(&ill->ill_mcast_lock); 1344 return (ilm != NULL); 1345 } 1346 1347 /* 1348 * Interface used by IP input/output. 1349 * Returns true if there is a member on the ill for any zoneid. 1350 * 1351 * The group and source can't be INADDR_ANY here so no need to translate to 1352 * the unspecified IPv6 address. 1353 */ 1354 boolean_t 1355 ill_hasmembers_v4(ill_t *ill, ipaddr_t group) 1356 { 1357 in6_addr_t v6group; 1358 1359 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1360 return (ill_hasmembers_v6(ill, &v6group)); 1361 } 1362 1363 /* 1364 * Interface used by IP input/output. 1365 * Returns true if there is a member on the ill for any zoneid except skipzone. 1366 */ 1367 boolean_t 1368 ill_hasmembers_otherzones_v6(ill_t *ill, const in6_addr_t *v6group, 1369 zoneid_t skipzone) 1370 { 1371 ilm_t *ilm; 1372 1373 rw_enter(&ill->ill_mcast_lock, RW_READER); 1374 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1375 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1376 ilm->ilm_zoneid != skipzone) { 1377 rw_exit(&ill->ill_mcast_lock); 1378 return (B_TRUE); 1379 } 1380 } 1381 rw_exit(&ill->ill_mcast_lock); 1382 return (B_FALSE); 1383 } 1384 1385 /* 1386 * Interface used by IP input/output. 1387 * Returns true if there is a member on the ill for any zoneid except skipzone. 1388 * 1389 * The group and source can't be INADDR_ANY here so no need to translate to 1390 * the unspecified IPv6 address. 1391 */ 1392 boolean_t 1393 ill_hasmembers_otherzones_v4(ill_t *ill, ipaddr_t group, zoneid_t skipzone) 1394 { 1395 in6_addr_t v6group; 1396 1397 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1398 return (ill_hasmembers_otherzones_v6(ill, &v6group, skipzone)); 1399 } 1400 1401 /* 1402 * Interface used by IP input. 1403 * Returns the next numerically larger zoneid that has a member. If none exist 1404 * then returns -1 (ALL_ZONES). 1405 * The normal usage is for the caller to start with a -1 zoneid (ALL_ZONES) 1406 * to find the first zoneid which has a member, and then pass that in for 1407 * subsequent calls until ALL_ZONES is returned. 1408 * 1409 * The implementation of ill_hasmembers_nextzone() assumes the ilms 1410 * are sorted by zoneid for efficiency. 1411 */ 1412 zoneid_t 1413 ill_hasmembers_nextzone_v6(ill_t *ill, const in6_addr_t *v6group, 1414 zoneid_t zoneid) 1415 { 1416 ilm_t *ilm; 1417 1418 rw_enter(&ill->ill_mcast_lock, RW_READER); 1419 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1420 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1421 ilm->ilm_zoneid > zoneid) { 1422 zoneid = ilm->ilm_zoneid; 1423 rw_exit(&ill->ill_mcast_lock); 1424 return (zoneid); 1425 } 1426 } 1427 rw_exit(&ill->ill_mcast_lock); 1428 return (ALL_ZONES); 1429 } 1430 1431 /* 1432 * Interface used by IP input. 1433 * Returns the next numerically larger zoneid that has a member. If none exist 1434 * then returns -1 (ALL_ZONES). 1435 * 1436 * The group and source can't be INADDR_ANY here so no need to translate to 1437 * the unspecified IPv6 address. 1438 */ 1439 zoneid_t 1440 ill_hasmembers_nextzone_v4(ill_t *ill, ipaddr_t group, zoneid_t zoneid) 1441 { 1442 in6_addr_t v6group; 1443 1444 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1445 1446 return (ill_hasmembers_nextzone_v6(ill, &v6group, zoneid)); 1447 } 1448 1449 /* 1450 * Find an ilm matching the ill, group, and zoneid. 1451 */ 1452 static ilm_t * 1453 ilm_lookup(ill_t *ill, const in6_addr_t *v6group, zoneid_t zoneid) 1454 { 1455 ilm_t *ilm; 1456 1457 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1458 1459 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1460 if (!IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group)) 1461 continue; 1462 if (zoneid != ALL_ZONES && zoneid != ilm->ilm_zoneid) 1463 continue; 1464 1465 ASSERT(ilm->ilm_ill == ill); 1466 return (ilm); 1467 } 1468 return (NULL); 1469 } 1470 1471 /* 1472 * How many members on this ill? 1473 * Since each shared-IP zone has a separate ilm for the same group/ill 1474 * we can have several. 1475 */ 1476 static int 1477 ilm_numentries(ill_t *ill, const in6_addr_t *v6group) 1478 { 1479 ilm_t *ilm; 1480 int i = 0; 1481 1482 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1483 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1484 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group)) { 1485 i++; 1486 } 1487 } 1488 return (i); 1489 } 1490 1491 /* Caller guarantees that the group is not already on the list */ 1492 static ilm_t * 1493 ilm_add(ill_t *ill, const in6_addr_t *v6group, ilg_stat_t ilgstat, 1494 mcast_record_t ilg_fmode, slist_t *ilg_flist, zoneid_t zoneid) 1495 { 1496 ilm_t *ilm; 1497 ilm_t *ilm_cur; 1498 ilm_t **ilm_ptpn; 1499 1500 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1501 ilm = GETSTRUCT(ilm_t, 1); 1502 if (ilm == NULL) 1503 return (NULL); 1504 if (ilgstat != ILGSTAT_NONE && !SLIST_IS_EMPTY(ilg_flist)) { 1505 ilm->ilm_filter = l_alloc(); 1506 if (ilm->ilm_filter == NULL) { 1507 mi_free(ilm); 1508 return (NULL); 1509 } 1510 } 1511 ilm->ilm_v6addr = *v6group; 1512 ilm->ilm_refcnt = 1; 1513 ilm->ilm_zoneid = zoneid; 1514 ilm->ilm_timer = INFINITY; 1515 ilm->ilm_rtx.rtx_timer = INFINITY; 1516 1517 ilm->ilm_ill = ill; 1518 DTRACE_PROBE3(ill__incr__cnt, (ill_t *), ill, 1519 (char *), "ilm", (void *), ilm); 1520 ill->ill_ilm_cnt++; 1521 1522 ASSERT(ill->ill_ipst); 1523 ilm->ilm_ipst = ill->ill_ipst; /* No netstack_hold */ 1524 1525 /* The ill/ipif could have just been marked as condemned */ 1526 1527 /* 1528 * To make ill_hasmembers_nextzone_v6 work we keep the list 1529 * sorted by zoneid. 1530 */ 1531 ilm_cur = ill->ill_ilm; 1532 ilm_ptpn = &ill->ill_ilm; 1533 while (ilm_cur != NULL && ilm_cur->ilm_zoneid < ilm->ilm_zoneid) { 1534 ilm_ptpn = &ilm_cur->ilm_next; 1535 ilm_cur = ilm_cur->ilm_next; 1536 } 1537 ilm->ilm_next = ilm_cur; 1538 *ilm_ptpn = ilm; 1539 1540 /* 1541 * If we have an associated ilg, use its filter state; if not, 1542 * default to (EXCLUDE, NULL) and set no_ilg_cnt to track this. 1543 */ 1544 if (ilgstat != ILGSTAT_NONE) { 1545 if (!SLIST_IS_EMPTY(ilg_flist)) 1546 l_copy(ilg_flist, ilm->ilm_filter); 1547 ilm->ilm_fmode = ilg_fmode; 1548 } else { 1549 ilm->ilm_no_ilg_cnt = 1; 1550 ilm->ilm_fmode = MODE_IS_EXCLUDE; 1551 } 1552 1553 return (ilm); 1554 } 1555 1556 void 1557 ilm_inactive(ilm_t *ilm) 1558 { 1559 FREE_SLIST(ilm->ilm_filter); 1560 FREE_SLIST(ilm->ilm_pendsrcs); 1561 FREE_SLIST(ilm->ilm_rtx.rtx_allow); 1562 FREE_SLIST(ilm->ilm_rtx.rtx_block); 1563 ilm->ilm_ipst = NULL; 1564 mi_free((char *)ilm); 1565 } 1566 1567 /* 1568 * Unlink ilm and free it. 1569 */ 1570 static void 1571 ilm_delete(ilm_t *ilm) 1572 { 1573 ill_t *ill = ilm->ilm_ill; 1574 ilm_t **ilmp; 1575 boolean_t need_wakeup; 1576 1577 /* 1578 * Delete under lock protection so that readers don't stumble 1579 * on bad ilm_next 1580 */ 1581 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1582 1583 for (ilmp = &ill->ill_ilm; *ilmp != ilm; ilmp = &(*ilmp)->ilm_next) 1584 ; 1585 1586 *ilmp = ilm->ilm_next; 1587 1588 mutex_enter(&ill->ill_lock); 1589 /* 1590 * if we are the last reference to the ill, we may need to wakeup any 1591 * pending FREE or unplumb operations. This is because conn_update_ill 1592 * bails if there is a ilg_delete_all in progress. 1593 */ 1594 need_wakeup = B_FALSE; 1595 DTRACE_PROBE3(ill__decr__cnt, (ill_t *), ill, 1596 (char *), "ilm", (void *), ilm); 1597 ASSERT(ill->ill_ilm_cnt > 0); 1598 ill->ill_ilm_cnt--; 1599 if (ILL_FREE_OK(ill)) 1600 need_wakeup = B_TRUE; 1601 1602 ilm_inactive(ilm); /* frees this ilm */ 1603 1604 if (need_wakeup) { 1605 /* drops ill lock */ 1606 ipif_ill_refrele_tail(ill); 1607 } else { 1608 mutex_exit(&ill->ill_lock); 1609 } 1610 } 1611 1612 /* 1613 * Lookup an ill based on the group, ifindex, ifaddr, and zoneid. 1614 * Applies to both IPv4 and IPv6, although ifaddr is only used with 1615 * IPv4. 1616 * Returns an error for IS_UNDER_IPMP and VNI interfaces. 1617 * On error it sets *errorp. 1618 */ 1619 static ill_t * 1620 ill_mcast_lookup(const in6_addr_t *group, ipaddr_t ifaddr, uint_t ifindex, 1621 zoneid_t zoneid, ip_stack_t *ipst, int *errorp) 1622 { 1623 ill_t *ill; 1624 ipaddr_t v4group; 1625 1626 if (IN6_IS_ADDR_V4MAPPED(group)) { 1627 IN6_V4MAPPED_TO_IPADDR(group, v4group); 1628 1629 if (ifindex != 0) { 1630 ill = ill_lookup_on_ifindex_zoneid(ifindex, zoneid, 1631 B_FALSE, ipst); 1632 } else if (ifaddr != INADDR_ANY) { 1633 ipif_t *ipif; 1634 1635 ipif = ipif_lookup_addr(ifaddr, NULL, zoneid, ipst); 1636 if (ipif == NULL) { 1637 ill = NULL; 1638 } else { 1639 ill = ipif->ipif_ill; 1640 ill_refhold(ill); 1641 ipif_refrele(ipif); 1642 } 1643 } else { 1644 ill = ill_lookup_group_v4(v4group, zoneid, ipst, NULL, 1645 NULL); 1646 } 1647 } else { 1648 if (ifindex != 0) { 1649 ill = ill_lookup_on_ifindex_zoneid(ifindex, zoneid, 1650 B_TRUE, ipst); 1651 } else { 1652 ill = ill_lookup_group_v6(group, zoneid, ipst, NULL, 1653 NULL); 1654 } 1655 } 1656 if (ill == NULL) { 1657 if (ifindex != 0) 1658 *errorp = ENXIO; 1659 else 1660 *errorp = EADDRNOTAVAIL; 1661 return (NULL); 1662 } 1663 /* operation not supported on the virtual network interface */ 1664 if (IS_UNDER_IPMP(ill) || IS_VNI(ill)) { 1665 ill_refrele(ill); 1666 *errorp = EINVAL; 1667 return (NULL); 1668 } 1669 return (ill); 1670 } 1671 1672 /* 1673 * Looks up the appropriate ill given an interface index (or interface address) 1674 * and multicast group. On success, returns 0, with *illpp pointing to the 1675 * found struct. On failure, returns an errno and *illpp is set to NULL. 1676 * 1677 * Returns an error for IS_UNDER_IPMP and VNI interfaces. 1678 * 1679 * Handles both IPv4 and IPv6. The ifaddr argument only applies in the 1680 * case of IPv4. 1681 */ 1682 int 1683 ip_opt_check(conn_t *connp, const in6_addr_t *v6group, 1684 const in6_addr_t *v6src, ipaddr_t ifaddr, uint_t ifindex, ill_t **illpp) 1685 { 1686 boolean_t src_unspec; 1687 ill_t *ill = NULL; 1688 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 1689 int error = 0; 1690 1691 *illpp = NULL; 1692 1693 src_unspec = IN6_IS_ADDR_UNSPECIFIED(v6src); 1694 1695 if (IN6_IS_ADDR_V4MAPPED(v6group)) { 1696 ipaddr_t v4group; 1697 ipaddr_t v4src; 1698 1699 if (!IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 1700 return (EINVAL); 1701 IN6_V4MAPPED_TO_IPADDR(v6group, v4group); 1702 if (src_unspec) { 1703 v4src = INADDR_ANY; 1704 } else { 1705 IN6_V4MAPPED_TO_IPADDR(v6src, v4src); 1706 } 1707 if (!CLASSD(v4group) || CLASSD(v4src)) 1708 return (EINVAL); 1709 } else { 1710 if (IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 1711 return (EINVAL); 1712 if (!IN6_IS_ADDR_MULTICAST(v6group) || 1713 IN6_IS_ADDR_MULTICAST(v6src)) { 1714 return (EINVAL); 1715 } 1716 } 1717 1718 ill = ill_mcast_lookup(v6group, ifaddr, ifindex, IPCL_ZONEID(connp), 1719 ipst, &error); 1720 *illpp = ill; 1721 return (error); 1722 } 1723 1724 static int 1725 ip_get_srcfilter(conn_t *connp, struct group_filter *gf, 1726 struct ip_msfilter *imsf, const struct in6_addr *group, boolean_t issin6) 1727 { 1728 ilg_t *ilg; 1729 int i, numsrc, fmode, outsrcs; 1730 struct sockaddr_in *sin; 1731 struct sockaddr_in6 *sin6; 1732 struct in_addr *addrp; 1733 slist_t *fp; 1734 boolean_t is_v4only_api; 1735 ipaddr_t ifaddr; 1736 uint_t ifindex; 1737 1738 if (gf == NULL) { 1739 ASSERT(imsf != NULL); 1740 ASSERT(!issin6); 1741 is_v4only_api = B_TRUE; 1742 outsrcs = imsf->imsf_numsrc; 1743 ifaddr = imsf->imsf_interface.s_addr; 1744 ifindex = 0; 1745 } else { 1746 ASSERT(imsf == NULL); 1747 is_v4only_api = B_FALSE; 1748 outsrcs = gf->gf_numsrc; 1749 ifaddr = INADDR_ANY; 1750 ifindex = gf->gf_interface; 1751 } 1752 1753 /* No need to use ill_mcast_serializer for the reader */ 1754 rw_enter(&connp->conn_ilg_lock, RW_READER); 1755 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 1756 if (ilg == NULL) { 1757 rw_exit(&connp->conn_ilg_lock); 1758 return (EADDRNOTAVAIL); 1759 } 1760 1761 /* 1762 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 1763 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 1764 * So we need to translate here. 1765 */ 1766 fmode = (ilg->ilg_fmode == MODE_IS_INCLUDE) ? 1767 MCAST_INCLUDE : MCAST_EXCLUDE; 1768 if ((fp = ilg->ilg_filter) == NULL) { 1769 numsrc = 0; 1770 } else { 1771 for (i = 0; i < outsrcs; i++) { 1772 if (i == fp->sl_numsrc) 1773 break; 1774 if (issin6) { 1775 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 1776 sin6->sin6_family = AF_INET6; 1777 sin6->sin6_addr = fp->sl_addr[i]; 1778 } else { 1779 if (is_v4only_api) { 1780 addrp = &imsf->imsf_slist[i]; 1781 } else { 1782 sin = (struct sockaddr_in *) 1783 &gf->gf_slist[i]; 1784 sin->sin_family = AF_INET; 1785 addrp = &sin->sin_addr; 1786 } 1787 IN6_V4MAPPED_TO_INADDR(&fp->sl_addr[i], addrp); 1788 } 1789 } 1790 numsrc = fp->sl_numsrc; 1791 } 1792 1793 if (is_v4only_api) { 1794 imsf->imsf_numsrc = numsrc; 1795 imsf->imsf_fmode = fmode; 1796 } else { 1797 gf->gf_numsrc = numsrc; 1798 gf->gf_fmode = fmode; 1799 } 1800 1801 rw_exit(&connp->conn_ilg_lock); 1802 1803 return (0); 1804 } 1805 1806 /* 1807 * Common for IPv4 and IPv6. 1808 */ 1809 static int 1810 ip_set_srcfilter(conn_t *connp, struct group_filter *gf, 1811 struct ip_msfilter *imsf, const struct in6_addr *group, ill_t *ill, 1812 boolean_t issin6) 1813 { 1814 ilg_t *ilg; 1815 int i, err, infmode, new_fmode; 1816 uint_t insrcs; 1817 struct sockaddr_in *sin; 1818 struct sockaddr_in6 *sin6; 1819 struct in_addr *addrp; 1820 slist_t *orig_filter = NULL; 1821 slist_t *new_filter = NULL; 1822 mcast_record_t orig_fmode; 1823 boolean_t leave_group, is_v4only_api; 1824 ilg_stat_t ilgstat; 1825 ilm_t *ilm; 1826 ipaddr_t ifaddr; 1827 uint_t ifindex; 1828 1829 if (gf == NULL) { 1830 ASSERT(imsf != NULL); 1831 ASSERT(!issin6); 1832 is_v4only_api = B_TRUE; 1833 insrcs = imsf->imsf_numsrc; 1834 infmode = imsf->imsf_fmode; 1835 ifaddr = imsf->imsf_interface.s_addr; 1836 ifindex = 0; 1837 } else { 1838 ASSERT(imsf == NULL); 1839 is_v4only_api = B_FALSE; 1840 insrcs = gf->gf_numsrc; 1841 infmode = gf->gf_fmode; 1842 ifaddr = INADDR_ANY; 1843 ifindex = gf->gf_interface; 1844 } 1845 1846 /* Make sure we can handle the source list */ 1847 if (insrcs > MAX_FILTER_SIZE) 1848 return (ENOBUFS); 1849 1850 /* 1851 * setting the filter to (INCLUDE, NULL) is treated 1852 * as a request to leave the group. 1853 */ 1854 leave_group = (infmode == MCAST_INCLUDE && insrcs == 0); 1855 1856 mutex_enter(&ill->ill_mcast_serializer); 1857 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1858 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 1859 if (ilg == NULL) { 1860 /* 1861 * if the request was actually to leave, and we 1862 * didn't find an ilg, there's nothing to do. 1863 */ 1864 if (leave_group) { 1865 rw_exit(&connp->conn_ilg_lock); 1866 mutex_exit(&ill->ill_mcast_serializer); 1867 return (0); 1868 } 1869 ilg = conn_ilg_alloc(connp, &err); 1870 if (ilg == NULL) { 1871 rw_exit(&connp->conn_ilg_lock); 1872 mutex_exit(&ill->ill_mcast_serializer); 1873 return (err); 1874 } 1875 ilgstat = ILGSTAT_NEW; 1876 ilg->ilg_v6group = *group; 1877 ilg->ilg_ill = ill; 1878 ilg->ilg_ifaddr = ifaddr; 1879 ilg->ilg_ifindex = ifindex; 1880 } else if (leave_group) { 1881 /* 1882 * Make sure we have the correct serializer. The ill argument 1883 * might not match ilg_ill. 1884 */ 1885 ilg_refhold(ilg); 1886 mutex_exit(&ill->ill_mcast_serializer); 1887 ill = ilg->ilg_ill; 1888 rw_exit(&connp->conn_ilg_lock); 1889 1890 mutex_enter(&ill->ill_mcast_serializer); 1891 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1892 ilm = ilg->ilg_ilm; 1893 ilg->ilg_ilm = NULL; 1894 ilg_delete(connp, ilg, NULL); 1895 ilg_refrele(ilg); 1896 rw_exit(&connp->conn_ilg_lock); 1897 if (ilm != NULL) 1898 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 1899 mutex_exit(&ill->ill_mcast_serializer); 1900 return (0); 1901 } else { 1902 ilgstat = ILGSTAT_CHANGE; 1903 /* Preserve existing state in case ip_addmulti() fails */ 1904 orig_fmode = ilg->ilg_fmode; 1905 if (ilg->ilg_filter == NULL) { 1906 orig_filter = NULL; 1907 } else { 1908 orig_filter = l_alloc_copy(ilg->ilg_filter); 1909 if (orig_filter == NULL) { 1910 rw_exit(&connp->conn_ilg_lock); 1911 mutex_exit(&ill->ill_mcast_serializer); 1912 return (ENOMEM); 1913 } 1914 } 1915 } 1916 1917 /* 1918 * Alloc buffer to copy new state into (see below) before 1919 * we make any changes, so we can bail if it fails. 1920 */ 1921 if ((new_filter = l_alloc()) == NULL) { 1922 rw_exit(&connp->conn_ilg_lock); 1923 err = ENOMEM; 1924 goto free_and_exit; 1925 } 1926 1927 if (insrcs == 0) { 1928 CLEAR_SLIST(ilg->ilg_filter); 1929 } else { 1930 slist_t *fp; 1931 if (ilg->ilg_filter == NULL) { 1932 fp = l_alloc(); 1933 if (fp == NULL) { 1934 if (ilgstat == ILGSTAT_NEW) 1935 ilg_delete(connp, ilg, NULL); 1936 rw_exit(&connp->conn_ilg_lock); 1937 err = ENOMEM; 1938 goto free_and_exit; 1939 } 1940 } else { 1941 fp = ilg->ilg_filter; 1942 } 1943 for (i = 0; i < insrcs; i++) { 1944 if (issin6) { 1945 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 1946 fp->sl_addr[i] = sin6->sin6_addr; 1947 } else { 1948 if (is_v4only_api) { 1949 addrp = &imsf->imsf_slist[i]; 1950 } else { 1951 sin = (struct sockaddr_in *) 1952 &gf->gf_slist[i]; 1953 addrp = &sin->sin_addr; 1954 } 1955 IN6_INADDR_TO_V4MAPPED(addrp, &fp->sl_addr[i]); 1956 } 1957 } 1958 fp->sl_numsrc = insrcs; 1959 ilg->ilg_filter = fp; 1960 } 1961 /* 1962 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 1963 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 1964 * So we need to translate here. 1965 */ 1966 ilg->ilg_fmode = (infmode == MCAST_INCLUDE) ? 1967 MODE_IS_INCLUDE : MODE_IS_EXCLUDE; 1968 1969 /* 1970 * Save copy of ilg's filter state to pass to other functions, 1971 * so we can release conn_ilg_lock now. 1972 */ 1973 new_fmode = ilg->ilg_fmode; 1974 l_copy(ilg->ilg_filter, new_filter); 1975 1976 rw_exit(&connp->conn_ilg_lock); 1977 1978 /* 1979 * Now update the ill. We wait to do this until after the ilg 1980 * has been updated because we need to update the src filter 1981 * info for the ill, which involves looking at the status of 1982 * all the ilgs associated with this group/interface pair. 1983 */ 1984 ilm = ip_addmulti_serial(group, ill, connp->conn_zoneid, ilgstat, 1985 new_fmode, new_filter, &err); 1986 1987 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 1988 /* 1989 * Must look up the ilg again since we've not been holding 1990 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 1991 * having called conn_update_ill, which can run once we dropped the 1992 * conn_ilg_lock above. 1993 */ 1994 ilg = ilg_lookup(connp, group, ifaddr, ifindex); 1995 if (ilg == NULL) { 1996 rw_exit(&connp->conn_ilg_lock); 1997 if (ilm != NULL) { 1998 (void) ip_delmulti_serial(ilm, B_FALSE, 1999 (ilgstat == ILGSTAT_NEW)); 2000 } 2001 err = ENXIO; 2002 goto free_and_exit; 2003 } 2004 2005 if (ilm != NULL) { 2006 /* Succeeded. Update the ilg to point at the ilm */ 2007 if (ilgstat == ILGSTAT_NEW) { 2008 ASSERT(ilg->ilg_ilm == NULL); 2009 ilg->ilg_ilm = ilm; 2010 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 2011 } else { 2012 /* 2013 * ip_addmulti didn't get a held ilm for 2014 * ILGSTAT_CHANGE; ilm_refcnt was unchanged. 2015 */ 2016 ASSERT(ilg->ilg_ilm == ilm); 2017 } 2018 } else { 2019 ASSERT(err != 0); 2020 /* 2021 * Failed to allocate the ilm. 2022 * Restore the original filter state, or delete the 2023 * newly-created ilg. 2024 * If ENETDOWN just clear ill_ilg since so that we 2025 * will rejoin when the ill comes back; don't report ENETDOWN 2026 * to application. 2027 */ 2028 if (ilgstat == ILGSTAT_NEW) { 2029 if (err == ENETDOWN) { 2030 ilg->ilg_ill = NULL; 2031 err = 0; 2032 } else { 2033 ilg_delete(connp, ilg, NULL); 2034 } 2035 } else { 2036 ilg->ilg_fmode = orig_fmode; 2037 if (SLIST_IS_EMPTY(orig_filter)) { 2038 CLEAR_SLIST(ilg->ilg_filter); 2039 } else { 2040 /* 2041 * We didn't free the filter, even if we 2042 * were trying to make the source list empty; 2043 * so if orig_filter isn't empty, the ilg 2044 * must still have a filter alloc'd. 2045 */ 2046 l_copy(orig_filter, ilg->ilg_filter); 2047 } 2048 } 2049 } 2050 rw_exit(&connp->conn_ilg_lock); 2051 2052 free_and_exit: 2053 mutex_exit(&ill->ill_mcast_serializer); 2054 l_free(orig_filter); 2055 l_free(new_filter); 2056 2057 return (err); 2058 } 2059 2060 /* 2061 * Process the SIOC[GS]MSFILTER and SIOC[GS]IPMSFILTER ioctls. 2062 */ 2063 /* ARGSUSED */ 2064 int 2065 ip_sioctl_msfilter(ipif_t *ipif, sin_t *dummy_sin, queue_t *q, mblk_t *mp, 2066 ip_ioctl_cmd_t *ipip, void *ifreq) 2067 { 2068 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2069 /* existence verified in ip_wput_nondata() */ 2070 mblk_t *data_mp = mp->b_cont->b_cont; 2071 int datalen, err, cmd, minsize; 2072 uint_t expsize = 0; 2073 conn_t *connp; 2074 boolean_t isv6, is_v4only_api, getcmd; 2075 struct sockaddr_in *gsin; 2076 struct sockaddr_in6 *gsin6; 2077 ipaddr_t v4group; 2078 in6_addr_t v6group; 2079 struct group_filter *gf = NULL; 2080 struct ip_msfilter *imsf = NULL; 2081 mblk_t *ndp; 2082 ill_t *ill; 2083 2084 connp = Q_TO_CONN(q); 2085 err = ip_msfilter_ill(connp, mp, ipip, &ill); 2086 if (err != 0) 2087 return (err); 2088 2089 if (data_mp->b_cont != NULL) { 2090 if ((ndp = msgpullup(data_mp, -1)) == NULL) 2091 return (ENOMEM); 2092 freemsg(data_mp); 2093 data_mp = ndp; 2094 mp->b_cont->b_cont = data_mp; 2095 } 2096 2097 cmd = iocp->ioc_cmd; 2098 getcmd = (cmd == SIOCGIPMSFILTER || cmd == SIOCGMSFILTER); 2099 is_v4only_api = (cmd == SIOCGIPMSFILTER || cmd == SIOCSIPMSFILTER); 2100 minsize = (is_v4only_api) ? IP_MSFILTER_SIZE(0) : GROUP_FILTER_SIZE(0); 2101 datalen = MBLKL(data_mp); 2102 2103 if (datalen < minsize) 2104 return (EINVAL); 2105 2106 /* 2107 * now we know we have at least have the initial structure, 2108 * but need to check for the source list array. 2109 */ 2110 if (is_v4only_api) { 2111 imsf = (struct ip_msfilter *)data_mp->b_rptr; 2112 isv6 = B_FALSE; 2113 expsize = IP_MSFILTER_SIZE(imsf->imsf_numsrc); 2114 } else { 2115 gf = (struct group_filter *)data_mp->b_rptr; 2116 if (gf->gf_group.ss_family == AF_INET6) { 2117 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2118 isv6 = !(IN6_IS_ADDR_V4MAPPED(&gsin6->sin6_addr)); 2119 } else { 2120 isv6 = B_FALSE; 2121 } 2122 expsize = GROUP_FILTER_SIZE(gf->gf_numsrc); 2123 } 2124 if (datalen < expsize) 2125 return (EINVAL); 2126 2127 if (isv6) { 2128 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2129 v6group = gsin6->sin6_addr; 2130 if (getcmd) { 2131 err = ip_get_srcfilter(connp, gf, NULL, &v6group, 2132 B_TRUE); 2133 } else { 2134 err = ip_set_srcfilter(connp, gf, NULL, &v6group, ill, 2135 B_TRUE); 2136 } 2137 } else { 2138 boolean_t issin6 = B_FALSE; 2139 if (is_v4only_api) { 2140 v4group = (ipaddr_t)imsf->imsf_multiaddr.s_addr; 2141 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2142 } else { 2143 if (gf->gf_group.ss_family == AF_INET) { 2144 gsin = (struct sockaddr_in *)&gf->gf_group; 2145 v4group = (ipaddr_t)gsin->sin_addr.s_addr; 2146 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2147 } else { 2148 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2149 IN6_V4MAPPED_TO_IPADDR(&gsin6->sin6_addr, 2150 v4group); 2151 issin6 = B_TRUE; 2152 } 2153 } 2154 /* 2155 * INADDR_ANY is represented as the IPv6 unspecifed addr. 2156 */ 2157 if (v4group == INADDR_ANY) 2158 v6group = ipv6_all_zeros; 2159 else 2160 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2161 2162 if (getcmd) { 2163 err = ip_get_srcfilter(connp, gf, imsf, &v6group, 2164 issin6); 2165 } else { 2166 err = ip_set_srcfilter(connp, gf, imsf, &v6group, ill, 2167 issin6); 2168 } 2169 } 2170 ill_refrele(ill); 2171 2172 return (err); 2173 } 2174 2175 /* 2176 * Determine the ill for the SIOC*MSFILTER ioctls 2177 * 2178 * Returns an error for IS_UNDER_IPMP interfaces. 2179 * 2180 * Finds the ill based on information in the ioctl headers. 2181 */ 2182 static int 2183 ip_msfilter_ill(conn_t *connp, mblk_t *mp, const ip_ioctl_cmd_t *ipip, 2184 ill_t **illp) 2185 { 2186 int cmd = ipip->ipi_cmd; 2187 int err = 0; 2188 ill_t *ill; 2189 /* caller has verified this mblk exists */ 2190 char *dbuf = (char *)mp->b_cont->b_cont->b_rptr; 2191 struct ip_msfilter *imsf; 2192 struct group_filter *gf; 2193 ipaddr_t v4addr, v4group; 2194 in6_addr_t v6group; 2195 uint32_t index; 2196 ip_stack_t *ipst; 2197 2198 ipst = connp->conn_netstack->netstack_ip; 2199 2200 *illp = NULL; 2201 2202 /* don't allow multicast operations on a tcp conn */ 2203 if (IPCL_IS_TCP(connp)) 2204 return (ENOPROTOOPT); 2205 2206 if (cmd == SIOCSIPMSFILTER || cmd == SIOCGIPMSFILTER) { 2207 /* don't allow v4-specific ioctls on v6 socket */ 2208 if (connp->conn_family == AF_INET6) 2209 return (EAFNOSUPPORT); 2210 2211 imsf = (struct ip_msfilter *)dbuf; 2212 v4addr = imsf->imsf_interface.s_addr; 2213 v4group = imsf->imsf_multiaddr.s_addr; 2214 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2215 ill = ill_mcast_lookup(&v6group, v4addr, 0, IPCL_ZONEID(connp), 2216 ipst, &err); 2217 if (ill == NULL && v4addr != INADDR_ANY) 2218 err = ENXIO; 2219 } else { 2220 gf = (struct group_filter *)dbuf; 2221 index = gf->gf_interface; 2222 if (gf->gf_group.ss_family == AF_INET6) { 2223 struct sockaddr_in6 *sin6; 2224 2225 sin6 = (struct sockaddr_in6 *)&gf->gf_group; 2226 v6group = sin6->sin6_addr; 2227 } else if (gf->gf_group.ss_family == AF_INET) { 2228 struct sockaddr_in *sin; 2229 2230 sin = (struct sockaddr_in *)&gf->gf_group; 2231 v4group = sin->sin_addr.s_addr; 2232 IN6_IPADDR_TO_V4MAPPED(v4group, &v6group); 2233 } else { 2234 return (EAFNOSUPPORT); 2235 } 2236 ill = ill_mcast_lookup(&v6group, INADDR_ANY, index, 2237 IPCL_ZONEID(connp), ipst, &err); 2238 } 2239 *illp = ill; 2240 return (err); 2241 } 2242 2243 /* 2244 * The structures used for the SIOC*MSFILTER ioctls usually must be copied 2245 * in in two stages, as the first copyin tells us the size of the attached 2246 * source buffer. This function is called by ip_wput_nondata() after the 2247 * first copyin has completed; it figures out how big the second stage 2248 * needs to be, and kicks it off. 2249 * 2250 * In some cases (numsrc < 2), the second copyin is not needed as the 2251 * first one gets a complete structure containing 1 source addr. 2252 * 2253 * The function returns 0 if a second copyin has been started (i.e. there's 2254 * no more work to be done right now), or 1 if the second copyin is not 2255 * needed and ip_wput_nondata() can continue its processing. 2256 */ 2257 int 2258 ip_copyin_msfilter(queue_t *q, mblk_t *mp) 2259 { 2260 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2261 int cmd = iocp->ioc_cmd; 2262 /* validity of this checked in ip_wput_nondata() */ 2263 mblk_t *mp1 = mp->b_cont->b_cont; 2264 int copysize = 0; 2265 int offset; 2266 2267 if (cmd == SIOCSMSFILTER || cmd == SIOCGMSFILTER) { 2268 struct group_filter *gf = (struct group_filter *)mp1->b_rptr; 2269 if (gf->gf_numsrc >= 2) { 2270 offset = sizeof (struct group_filter); 2271 copysize = GROUP_FILTER_SIZE(gf->gf_numsrc) - offset; 2272 } 2273 } else { 2274 struct ip_msfilter *imsf = (struct ip_msfilter *)mp1->b_rptr; 2275 if (imsf->imsf_numsrc >= 2) { 2276 offset = sizeof (struct ip_msfilter); 2277 copysize = IP_MSFILTER_SIZE(imsf->imsf_numsrc) - offset; 2278 } 2279 } 2280 if (copysize > 0) { 2281 mi_copyin_n(q, mp, offset, copysize); 2282 return (0); 2283 } 2284 return (1); 2285 } 2286 2287 /* 2288 * Handle the following optmgmt: 2289 * IP_ADD_MEMBERSHIP must not have joined already 2290 * IPV6_JOIN_GROUP must not have joined already 2291 * MCAST_JOIN_GROUP must not have joined already 2292 * IP_BLOCK_SOURCE must have joined already 2293 * MCAST_BLOCK_SOURCE must have joined already 2294 * IP_JOIN_SOURCE_GROUP may have joined already 2295 * MCAST_JOIN_SOURCE_GROUP may have joined already 2296 * 2297 * fmode and src parameters may be used to determine which option is 2298 * being set, as follows (IPV6_JOIN_GROUP and MCAST_JOIN_GROUP options 2299 * are functionally equivalent): 2300 * opt fmode v6src 2301 * IP_ADD_MEMBERSHIP MODE_IS_EXCLUDE unspecified 2302 * IPV6_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2303 * MCAST_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2304 * IP_BLOCK_SOURCE MODE_IS_EXCLUDE IPv4-mapped addr 2305 * MCAST_BLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 2306 * IP_JOIN_SOURCE_GROUP MODE_IS_INCLUDE IPv4-mapped addr 2307 * MCAST_JOIN_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 2308 * 2309 * Changing the filter mode is not allowed; if a matching ilg already 2310 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2311 * 2312 * Verifies that there is a source address of appropriate scope for 2313 * the group; if not, EADDRNOTAVAIL is returned. 2314 * 2315 * The interface to be used may be identified by an IPv4 address or by an 2316 * interface index. 2317 * 2318 * Handles IPv4-mapped IPv6 multicast addresses by associating them 2319 * with the IPv4 address. Assumes that if v6group is v4-mapped, 2320 * v6src is also v4-mapped. 2321 */ 2322 int 2323 ip_opt_add_group(conn_t *connp, boolean_t checkonly, 2324 const in6_addr_t *v6group, ipaddr_t ifaddr, uint_t ifindex, 2325 mcast_record_t fmode, const in6_addr_t *v6src) 2326 { 2327 ill_t *ill; 2328 char buf[INET6_ADDRSTRLEN]; 2329 int err; 2330 2331 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, &ill); 2332 if (err != 0) { 2333 ip1dbg(("ip_opt_add_group: no ill for group %s/" 2334 "index %d\n", inet_ntop(AF_INET6, v6group, buf, 2335 sizeof (buf)), ifindex)); 2336 return (err); 2337 } 2338 2339 if (checkonly) { 2340 /* 2341 * do not do operation, just pretend to - new T_CHECK 2342 * semantics. The error return case above if encountered 2343 * considered a good enough "check" here. 2344 */ 2345 ill_refrele(ill); 2346 return (0); 2347 } 2348 2349 mutex_enter(&ill->ill_mcast_serializer); 2350 err = ilg_add(connp, v6group, ifaddr, ifindex, ill, fmode, v6src); 2351 mutex_exit(&ill->ill_mcast_serializer); 2352 ill_refrele(ill); 2353 return (err); 2354 } 2355 2356 /* 2357 * Common for IPv6 and IPv4. 2358 * Here we handle ilgs that are still attached to their original ill 2359 * (the one ifaddr/ifindex points at), as well as detached ones. 2360 * The detached ones might have been attached to some other ill. 2361 */ 2362 static int 2363 ip_opt_delete_group_excl(conn_t *connp, const in6_addr_t *v6group, 2364 ipaddr_t ifaddr, uint_t ifindex, mcast_record_t fmode, 2365 const in6_addr_t *v6src) 2366 { 2367 ilg_t *ilg; 2368 boolean_t leaving; 2369 ilm_t *ilm; 2370 ill_t *ill; 2371 int err = 0; 2372 2373 retry: 2374 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2375 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2376 if (ilg == NULL) { 2377 rw_exit(&connp->conn_ilg_lock); 2378 /* 2379 * Since we didn't have any ilg we now do the error checks 2380 * to determine the best errno. 2381 */ 2382 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, 2383 &ill); 2384 if (ill != NULL) { 2385 /* The only error was a missing ilg for the group */ 2386 ill_refrele(ill); 2387 err = EADDRNOTAVAIL; 2388 } 2389 return (err); 2390 } 2391 2392 /* If the ilg is attached then we serialize using that ill */ 2393 ill = ilg->ilg_ill; 2394 if (ill != NULL) { 2395 /* Prevent the ill and ilg from being freed */ 2396 ill_refhold(ill); 2397 ilg_refhold(ilg); 2398 rw_exit(&connp->conn_ilg_lock); 2399 mutex_enter(&ill->ill_mcast_serializer); 2400 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2401 if (ilg->ilg_condemned) { 2402 /* Disappeared */ 2403 ilg_refrele(ilg); 2404 rw_exit(&connp->conn_ilg_lock); 2405 mutex_exit(&ill->ill_mcast_serializer); 2406 ill_refrele(ill); 2407 goto retry; 2408 } 2409 } 2410 2411 /* 2412 * Decide if we're actually deleting the ilg or just removing a 2413 * source filter address; if just removing an addr, make sure we 2414 * aren't trying to change the filter mode, and that the addr is 2415 * actually in our filter list already. If we're removing the 2416 * last src in an include list, just delete the ilg. 2417 */ 2418 if (IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2419 leaving = B_TRUE; 2420 } else { 2421 if (fmode != ilg->ilg_fmode) 2422 err = EINVAL; 2423 else if (ilg->ilg_filter == NULL || 2424 !list_has_addr(ilg->ilg_filter, v6src)) 2425 err = EADDRNOTAVAIL; 2426 if (err != 0) { 2427 if (ill != NULL) 2428 ilg_refrele(ilg); 2429 rw_exit(&connp->conn_ilg_lock); 2430 goto done; 2431 } 2432 if (fmode == MODE_IS_INCLUDE && 2433 ilg->ilg_filter->sl_numsrc == 1) { 2434 leaving = B_TRUE; 2435 v6src = NULL; 2436 } else { 2437 leaving = B_FALSE; 2438 } 2439 } 2440 ilm = ilg->ilg_ilm; 2441 if (leaving) 2442 ilg->ilg_ilm = NULL; 2443 2444 ilg_delete(connp, ilg, v6src); 2445 if (ill != NULL) 2446 ilg_refrele(ilg); 2447 rw_exit(&connp->conn_ilg_lock); 2448 2449 if (ilm != NULL) { 2450 ASSERT(ill != NULL); 2451 (void) ip_delmulti_serial(ilm, B_FALSE, leaving); 2452 } 2453 done: 2454 if (ill != NULL) { 2455 mutex_exit(&ill->ill_mcast_serializer); 2456 ill_refrele(ill); 2457 } 2458 return (err); 2459 } 2460 2461 /* 2462 * Handle the following optmgmt: 2463 * IP_DROP_MEMBERSHIP will leave 2464 * IPV6_LEAVE_GROUP will leave 2465 * MCAST_LEAVE_GROUP will leave 2466 * IP_UNBLOCK_SOURCE will not leave 2467 * MCAST_UNBLOCK_SOURCE will not leave 2468 * IP_LEAVE_SOURCE_GROUP may leave (if leaving last source) 2469 * MCAST_LEAVE_SOURCE_GROUP may leave (if leaving last source) 2470 * 2471 * fmode and src parameters may be used to determine which option is 2472 * being set, as follows: 2473 * opt fmode v6src 2474 * IP_DROP_MEMBERSHIP MODE_IS_INCLUDE unspecified 2475 * IPV6_LEAVE_GROUP MODE_IS_INCLUDE unspecified 2476 * MCAST_LEAVE_GROUP MODE_IS_INCLUDE unspecified 2477 * IP_UNBLOCK_SOURCE MODE_IS_EXCLUDE IPv4-mapped addr 2478 * MCAST_UNBLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 2479 * IP_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE IPv4-mapped addr 2480 * MCAST_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 2481 * 2482 * Changing the filter mode is not allowed; if a matching ilg already 2483 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2484 * 2485 * The interface to be used may be identified by an IPv4 address or by an 2486 * interface index. 2487 * 2488 * Handles IPv4-mapped IPv6 multicast addresses by associating them 2489 * with the IPv4 address. Assumes that if v6group is v4-mapped, 2490 * v6src is also v4-mapped. 2491 */ 2492 int 2493 ip_opt_delete_group(conn_t *connp, boolean_t checkonly, 2494 const in6_addr_t *v6group, ipaddr_t ifaddr, uint_t ifindex, 2495 mcast_record_t fmode, const in6_addr_t *v6src) 2496 { 2497 2498 /* 2499 * In the normal case below we don't check for the ill existing. 2500 * Instead we look for an existing ilg in _excl. 2501 * If checkonly we sanity check the arguments 2502 */ 2503 if (checkonly) { 2504 ill_t *ill; 2505 int err; 2506 2507 err = ip_opt_check(connp, v6group, v6src, ifaddr, ifindex, 2508 &ill); 2509 /* 2510 * do not do operation, just pretend to - new T_CHECK semantics. 2511 * ip_opt_check is considered a good enough "check" here. 2512 */ 2513 if (ill != NULL) 2514 ill_refrele(ill); 2515 return (err); 2516 } 2517 return (ip_opt_delete_group_excl(connp, v6group, ifaddr, ifindex, 2518 fmode, v6src)); 2519 } 2520 2521 /* 2522 * Group mgmt for upper conn that passes things down 2523 * to the interface multicast list (and DLPI) 2524 * These routines can handle new style options that specify an interface name 2525 * as opposed to an interface address (needed for general handling of 2526 * unnumbered interfaces.) 2527 */ 2528 2529 /* 2530 * Add a group to an upper conn group data structure and pass things down 2531 * to the interface multicast list (and DLPI) 2532 * Common for IPv4 and IPv6; for IPv4 we can have an ifaddr. 2533 */ 2534 static int 2535 ilg_add(conn_t *connp, const in6_addr_t *v6group, ipaddr_t ifaddr, 2536 uint_t ifindex, ill_t *ill, mcast_record_t fmode, const in6_addr_t *v6src) 2537 { 2538 int error = 0; 2539 ilg_t *ilg; 2540 ilg_stat_t ilgstat; 2541 slist_t *new_filter = NULL; 2542 int new_fmode; 2543 ilm_t *ilm; 2544 2545 if (!(ill->ill_flags & ILLF_MULTICAST)) 2546 return (EADDRNOTAVAIL); 2547 2548 /* conn_ilg_lock protects the ilg list. */ 2549 ASSERT(MUTEX_HELD(&ill->ill_mcast_serializer)); 2550 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2551 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2552 2553 /* 2554 * Depending on the option we're handling, may or may not be okay 2555 * if group has already been added. Figure out our rules based 2556 * on fmode and src params. Also make sure there's enough room 2557 * in the filter if we're adding a source to an existing filter. 2558 */ 2559 if (IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2560 /* we're joining for all sources, must not have joined */ 2561 if (ilg != NULL) 2562 error = EADDRINUSE; 2563 } else { 2564 if (fmode == MODE_IS_EXCLUDE) { 2565 /* (excl {addr}) => block source, must have joined */ 2566 if (ilg == NULL) 2567 error = EADDRNOTAVAIL; 2568 } 2569 /* (incl {addr}) => join source, may have joined */ 2570 2571 if (ilg != NULL && 2572 SLIST_CNT(ilg->ilg_filter) == MAX_FILTER_SIZE) 2573 error = ENOBUFS; 2574 } 2575 if (error != 0) { 2576 rw_exit(&connp->conn_ilg_lock); 2577 return (error); 2578 } 2579 2580 /* 2581 * Alloc buffer to copy new state into (see below) before 2582 * we make any changes, so we can bail if it fails. 2583 */ 2584 if ((new_filter = l_alloc()) == NULL) { 2585 rw_exit(&connp->conn_ilg_lock); 2586 return (ENOMEM); 2587 } 2588 2589 if (ilg == NULL) { 2590 if ((ilg = conn_ilg_alloc(connp, &error)) == NULL) { 2591 rw_exit(&connp->conn_ilg_lock); 2592 l_free(new_filter); 2593 return (error); 2594 } 2595 ilg->ilg_ifindex = ifindex; 2596 ilg->ilg_ifaddr = ifaddr; 2597 if (!IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2598 ilg->ilg_filter = l_alloc(); 2599 if (ilg->ilg_filter == NULL) { 2600 ilg_delete(connp, ilg, NULL); 2601 rw_exit(&connp->conn_ilg_lock); 2602 l_free(new_filter); 2603 return (ENOMEM); 2604 } 2605 ilg->ilg_filter->sl_numsrc = 1; 2606 ilg->ilg_filter->sl_addr[0] = *v6src; 2607 } 2608 ilgstat = ILGSTAT_NEW; 2609 ilg->ilg_v6group = *v6group; 2610 ilg->ilg_fmode = fmode; 2611 ilg->ilg_ill = ill; 2612 } else { 2613 int index; 2614 if (ilg->ilg_fmode != fmode || IN6_IS_ADDR_UNSPECIFIED(v6src)) { 2615 rw_exit(&connp->conn_ilg_lock); 2616 l_free(new_filter); 2617 return (EINVAL); 2618 } 2619 if (ilg->ilg_filter == NULL) { 2620 ilg->ilg_filter = l_alloc(); 2621 if (ilg->ilg_filter == NULL) { 2622 rw_exit(&connp->conn_ilg_lock); 2623 l_free(new_filter); 2624 return (ENOMEM); 2625 } 2626 } 2627 if (list_has_addr(ilg->ilg_filter, v6src)) { 2628 rw_exit(&connp->conn_ilg_lock); 2629 l_free(new_filter); 2630 return (EADDRNOTAVAIL); 2631 } 2632 ilgstat = ILGSTAT_CHANGE; 2633 index = ilg->ilg_filter->sl_numsrc++; 2634 ilg->ilg_filter->sl_addr[index] = *v6src; 2635 } 2636 2637 /* 2638 * Save copy of ilg's filter state to pass to other functions, 2639 * so we can release conn_ilg_lock now. 2640 */ 2641 new_fmode = ilg->ilg_fmode; 2642 l_copy(ilg->ilg_filter, new_filter); 2643 2644 rw_exit(&connp->conn_ilg_lock); 2645 2646 /* 2647 * Now update the ill. We wait to do this until after the ilg 2648 * has been updated because we need to update the src filter 2649 * info for the ill, which involves looking at the status of 2650 * all the ilgs associated with this group/interface pair. 2651 */ 2652 ilm = ip_addmulti_serial(v6group, ill, connp->conn_zoneid, ilgstat, 2653 new_fmode, new_filter, &error); 2654 2655 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2656 /* 2657 * Must look up the ilg again since we've not been holding 2658 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 2659 * having called conn_update_ill, which can run once we dropped the 2660 * conn_ilg_lock above. 2661 */ 2662 ilg = ilg_lookup(connp, v6group, ifaddr, ifindex); 2663 if (ilg == NULL) { 2664 rw_exit(&connp->conn_ilg_lock); 2665 if (ilm != NULL) { 2666 (void) ip_delmulti_serial(ilm, B_FALSE, 2667 (ilgstat == ILGSTAT_NEW)); 2668 } 2669 error = ENXIO; 2670 goto free_and_exit; 2671 } 2672 2673 if (ilm != NULL) { 2674 /* Succeeded. Update the ilg to point at the ilm */ 2675 if (ilgstat == ILGSTAT_NEW) { 2676 ASSERT(ilg->ilg_ilm == NULL); 2677 ilg->ilg_ilm = ilm; 2678 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 2679 } else { 2680 /* 2681 * ip_addmulti didn't get a held ilm for 2682 * ILGSTAT_CHANGE; ilm_refcnt was unchanged. 2683 */ 2684 ASSERT(ilg->ilg_ilm == ilm); 2685 } 2686 } else { 2687 ASSERT(error != 0); 2688 /* 2689 * Failed to allocate the ilm. 2690 * Need to undo what we did before calling ip_addmulti() 2691 * If ENETDOWN just clear ill_ilg since so that we 2692 * will rejoin when the ill comes back; don't report ENETDOWN 2693 * to application. 2694 */ 2695 if (ilgstat == ILGSTAT_NEW && error == ENETDOWN) { 2696 ilg->ilg_ill = NULL; 2697 error = 0; 2698 } else { 2699 in6_addr_t delsrc = 2700 (ilgstat == ILGSTAT_NEW) ? ipv6_all_zeros : *v6src; 2701 2702 ilg_delete(connp, ilg, &delsrc); 2703 } 2704 } 2705 rw_exit(&connp->conn_ilg_lock); 2706 2707 free_and_exit: 2708 l_free(new_filter); 2709 return (error); 2710 } 2711 2712 /* 2713 * Find an IPv4 ilg matching group, ill and source. 2714 * The group and source can't be INADDR_ANY here so no need to translate to 2715 * the unspecified IPv6 address. 2716 */ 2717 boolean_t 2718 conn_hasmembers_ill_withsrc_v4(conn_t *connp, ipaddr_t group, ipaddr_t src, 2719 ill_t *ill) 2720 { 2721 in6_addr_t v6group, v6src; 2722 int i; 2723 boolean_t isinlist; 2724 ilg_t *ilg; 2725 2726 rw_enter(&connp->conn_ilg_lock, RW_READER); 2727 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 2728 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2729 if (ilg->ilg_condemned) 2730 continue; 2731 2732 /* ilg_ill could be NULL if an add is in progress */ 2733 if (ilg->ilg_ill != ill) 2734 continue; 2735 2736 /* The callers use upper ill for IPMP */ 2737 ASSERT(!IS_UNDER_IPMP(ill)); 2738 if (IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, &v6group)) { 2739 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 2740 /* no source filter, so this is a match */ 2741 rw_exit(&connp->conn_ilg_lock); 2742 return (B_TRUE); 2743 } 2744 break; 2745 } 2746 } 2747 if (ilg == NULL) { 2748 rw_exit(&connp->conn_ilg_lock); 2749 return (B_FALSE); 2750 } 2751 2752 /* 2753 * we have an ilg with matching ill and group; but 2754 * the ilg has a source list that we must check. 2755 */ 2756 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 2757 isinlist = B_FALSE; 2758 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 2759 if (IN6_ARE_ADDR_EQUAL(&v6src, &ilg->ilg_filter->sl_addr[i])) { 2760 isinlist = B_TRUE; 2761 break; 2762 } 2763 } 2764 2765 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 2766 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) { 2767 rw_exit(&connp->conn_ilg_lock); 2768 return (B_TRUE); 2769 } 2770 rw_exit(&connp->conn_ilg_lock); 2771 return (B_FALSE); 2772 } 2773 2774 /* 2775 * Find an IPv6 ilg matching group, ill, and source 2776 */ 2777 boolean_t 2778 conn_hasmembers_ill_withsrc_v6(conn_t *connp, const in6_addr_t *v6group, 2779 const in6_addr_t *v6src, ill_t *ill) 2780 { 2781 int i; 2782 boolean_t isinlist; 2783 ilg_t *ilg; 2784 2785 rw_enter(&connp->conn_ilg_lock, RW_READER); 2786 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2787 if (ilg->ilg_condemned) 2788 continue; 2789 2790 /* ilg_ill could be NULL if an add is in progress */ 2791 if (ilg->ilg_ill != ill) 2792 continue; 2793 2794 /* The callers use upper ill for IPMP */ 2795 ASSERT(!IS_UNDER_IPMP(ill)); 2796 if (IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) { 2797 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 2798 /* no source filter, so this is a match */ 2799 rw_exit(&connp->conn_ilg_lock); 2800 return (B_TRUE); 2801 } 2802 break; 2803 } 2804 } 2805 if (ilg == NULL) { 2806 rw_exit(&connp->conn_ilg_lock); 2807 return (B_FALSE); 2808 } 2809 2810 /* 2811 * we have an ilg with matching ill and group; but 2812 * the ilg has a source list that we must check. 2813 */ 2814 isinlist = B_FALSE; 2815 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 2816 if (IN6_ARE_ADDR_EQUAL(v6src, &ilg->ilg_filter->sl_addr[i])) { 2817 isinlist = B_TRUE; 2818 break; 2819 } 2820 } 2821 2822 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 2823 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) { 2824 rw_exit(&connp->conn_ilg_lock); 2825 return (B_TRUE); 2826 } 2827 rw_exit(&connp->conn_ilg_lock); 2828 return (B_FALSE); 2829 } 2830 2831 /* 2832 * Find an ilg matching group and ifaddr/ifindex. 2833 * We check both ifaddr and ifindex even though at most one of them 2834 * will be non-zero; that way we always find the right one. 2835 */ 2836 static ilg_t * 2837 ilg_lookup(conn_t *connp, const in6_addr_t *v6group, ipaddr_t ifaddr, 2838 uint_t ifindex) 2839 { 2840 ilg_t *ilg; 2841 2842 ASSERT(RW_LOCK_HELD(&connp->conn_ilg_lock)); 2843 2844 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 2845 if (ilg->ilg_condemned) 2846 continue; 2847 2848 if (ilg->ilg_ifaddr == ifaddr && 2849 ilg->ilg_ifindex == ifindex && 2850 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) 2851 return (ilg); 2852 } 2853 return (NULL); 2854 } 2855 2856 /* 2857 * If a source address is passed in (src != NULL and src is not 2858 * unspecified), remove the specified src addr from the given ilg's 2859 * filter list, else delete the ilg. 2860 */ 2861 static void 2862 ilg_delete(conn_t *connp, ilg_t *ilg, const in6_addr_t *src) 2863 { 2864 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 2865 ASSERT(ilg->ilg_ptpn != NULL); 2866 ASSERT(!ilg->ilg_condemned); 2867 2868 if (src == NULL || IN6_IS_ADDR_UNSPECIFIED(src)) { 2869 FREE_SLIST(ilg->ilg_filter); 2870 ilg->ilg_filter = NULL; 2871 2872 ASSERT(ilg->ilg_ilm == NULL); 2873 ilg->ilg_ill = NULL; 2874 ilg->ilg_condemned = B_TRUE; 2875 2876 /* ilg_inactive will unlink from the list */ 2877 ilg_refrele(ilg); 2878 } else { 2879 l_remove(ilg->ilg_filter, src); 2880 } 2881 } 2882 2883 /* 2884 * Called from conn close. No new ilg can be added or removed 2885 * because CONN_CLOSING has been set by ip_close. ilg_add / ilg_delete 2886 * will return error if conn has started closing. 2887 * 2888 * We handle locking as follows. 2889 * Under conn_ilg_lock we get the first ilg. As we drop the conn_ilg_lock to 2890 * proceed with the ilm part of the delete we hold a reference on both the ill 2891 * and the ilg. This doesn't prevent changes to the ilg, but prevents it from 2892 * being deleted. 2893 * 2894 * Since the ilg_add code path uses two locks (conn_ilg_lock for the ilg part, 2895 * and ill_mcast_lock for the ip_addmulti part) we can run at a point between 2896 * the two. At that point ilg_ill is set, but ilg_ilm hasn't yet been set. In 2897 * that case we delete the ilg here, which makes ilg_add discover that the ilg 2898 * has disappeared when ip_addmulti returns, so it will discard the ilm it just 2899 * added. 2900 */ 2901 void 2902 ilg_delete_all(conn_t *connp) 2903 { 2904 ilg_t *ilg, *next_ilg, *held_ilg; 2905 ilm_t *ilm; 2906 ill_t *ill; 2907 boolean_t need_refrele; 2908 2909 /* 2910 * Can not run if there is a conn_update_ill already running. 2911 * Wait for it to complete. Caller should have already set CONN_CLOSING 2912 * which prevents any new threads to run in conn_update_ill. 2913 */ 2914 mutex_enter(&connp->conn_lock); 2915 ASSERT(connp->conn_state_flags & CONN_CLOSING); 2916 while (connp->conn_state_flags & CONN_UPDATE_ILL) 2917 cv_wait(&connp->conn_cv, &connp->conn_lock); 2918 mutex_exit(&connp->conn_lock); 2919 2920 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2921 ilg = connp->conn_ilg; 2922 held_ilg = NULL; 2923 while (ilg != NULL) { 2924 if (ilg->ilg_condemned) { 2925 ilg = ilg->ilg_next; 2926 continue; 2927 } 2928 /* If the ilg is detached then no need to serialize */ 2929 if (ilg->ilg_ilm == NULL) { 2930 next_ilg = ilg->ilg_next; 2931 ilg_delete(connp, ilg, NULL); 2932 ilg = next_ilg; 2933 continue; 2934 } 2935 ill = ilg->ilg_ilm->ilm_ill; 2936 2937 /* 2938 * In order to serialize on the ill we try to enter 2939 * and if that fails we unlock and relock and then 2940 * check that we still have an ilm. 2941 */ 2942 need_refrele = B_FALSE; 2943 if (!mutex_tryenter(&ill->ill_mcast_serializer)) { 2944 ill_refhold(ill); 2945 need_refrele = B_TRUE; 2946 ilg_refhold(ilg); 2947 if (held_ilg != NULL) 2948 ilg_refrele(held_ilg); 2949 held_ilg = ilg; 2950 rw_exit(&connp->conn_ilg_lock); 2951 mutex_enter(&ill->ill_mcast_serializer); 2952 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2953 if (ilg->ilg_condemned) { 2954 ilg = ilg->ilg_next; 2955 goto next; 2956 } 2957 } 2958 ilm = ilg->ilg_ilm; 2959 ilg->ilg_ilm = NULL; 2960 next_ilg = ilg->ilg_next; 2961 ilg_delete(connp, ilg, NULL); 2962 ilg = next_ilg; 2963 rw_exit(&connp->conn_ilg_lock); 2964 2965 if (ilm != NULL) 2966 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 2967 2968 next: 2969 mutex_exit(&ill->ill_mcast_serializer); 2970 if (need_refrele) { 2971 /* Drop ill reference while we hold no locks */ 2972 ill_refrele(ill); 2973 } 2974 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 2975 } 2976 if (held_ilg != NULL) 2977 ilg_refrele(held_ilg); 2978 rw_exit(&connp->conn_ilg_lock); 2979 } 2980 2981 /* 2982 * Attach the ilg to an ilm on the ill. If it fails we leave ilg_ill as NULL so 2983 * that a subsequent attempt can attach it. 2984 * Drops and reacquires conn_ilg_lock. 2985 */ 2986 static void 2987 ilg_attach(conn_t *connp, ilg_t *ilg, ill_t *ill) 2988 { 2989 ilg_stat_t ilgstat; 2990 slist_t *new_filter; 2991 int new_fmode; 2992 in6_addr_t v6group; 2993 ipaddr_t ifaddr; 2994 uint_t ifindex; 2995 ilm_t *ilm; 2996 int error = 0; 2997 2998 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 2999 /* 3000 * Alloc buffer to copy new state into (see below) before 3001 * we make any changes, so we can bail if it fails. 3002 */ 3003 if ((new_filter = l_alloc()) == NULL) 3004 return; 3005 3006 /* 3007 * Save copy of ilg's filter state to pass to other functions, so 3008 * we can release conn_ilg_lock now. 3009 * Set ilg_ill so that an unplumb can find us. 3010 */ 3011 new_fmode = ilg->ilg_fmode; 3012 l_copy(ilg->ilg_filter, new_filter); 3013 v6group = ilg->ilg_v6group; 3014 ifaddr = ilg->ilg_ifaddr; 3015 ifindex = ilg->ilg_ifindex; 3016 ilgstat = ILGSTAT_NEW; 3017 3018 ilg->ilg_ill = ill; 3019 ASSERT(ilg->ilg_ilm == NULL); 3020 rw_exit(&connp->conn_ilg_lock); 3021 3022 ilm = ip_addmulti_serial(&v6group, ill, connp->conn_zoneid, ilgstat, 3023 new_fmode, new_filter, &error); 3024 l_free(new_filter); 3025 3026 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3027 /* 3028 * Must look up the ilg again since we've not been holding 3029 * conn_ilg_lock. The ilg could have disappeared due to an unplumb 3030 * having called conn_update_ill, which can run once we dropped the 3031 * conn_ilg_lock above. 3032 */ 3033 ilg = ilg_lookup(connp, &v6group, ifaddr, ifindex); 3034 if (ilg == NULL) { 3035 if (ilm != NULL) { 3036 rw_exit(&connp->conn_ilg_lock); 3037 (void) ip_delmulti_serial(ilm, B_FALSE, 3038 (ilgstat == ILGSTAT_NEW)); 3039 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3040 } 3041 return; 3042 } 3043 if (ilm == NULL) { 3044 ilg->ilg_ill = NULL; 3045 return; 3046 } 3047 ASSERT(ilg->ilg_ilm == NULL); 3048 ilg->ilg_ilm = ilm; 3049 ilm->ilm_ifaddr = ifaddr; /* For netstat */ 3050 } 3051 3052 /* 3053 * Called when an ill is unplumbed to make sure that there are no 3054 * dangling conn references to that ill. In that case ill is non-NULL and 3055 * we make sure we remove all references to it. 3056 * Also called when we should revisit the ilg_ill used for multicast 3057 * memberships, in which case ill is NULL. 3058 * 3059 * conn is held by caller. 3060 * 3061 * Note that ipcl_walk only walks conns that are not yet condemned. 3062 * condemned conns can't be refheld. For this reason, conn must become clean 3063 * first, i.e. it must not refer to any ill/ire and then only set 3064 * condemned flag. 3065 * 3066 * We leave ixa_multicast_ifindex in place. We prefer dropping 3067 * packets instead of sending them out the wrong interface. 3068 * 3069 * We keep the ilg around in a detached state (with ilg_ill and ilg_ilm being 3070 * NULL) so that the application can leave it later. Also, if ilg_ifaddr and 3071 * ilg_ifindex are zero, indicating that the system should pick the interface, 3072 * then we attempt to reselect the ill and join on it. 3073 * 3074 * Locking notes: 3075 * Under conn_ilg_lock we get the first ilg. As we drop the conn_ilg_lock to 3076 * proceed with the ilm part of the delete we hold a reference on both the ill 3077 * and the ilg. This doesn't prevent changes to the ilg, but prevents it from 3078 * being deleted. 3079 * 3080 * Note: if this function is called when new ill/ipif's arrive or change status 3081 * (SIOCSLIFINDEX, SIOCSLIFADDR) then we will attempt to attach any ilgs with 3082 * a NULL ilg_ill to an ill/ilm. 3083 */ 3084 static void 3085 conn_update_ill(conn_t *connp, caddr_t arg) 3086 { 3087 ill_t *ill = (ill_t *)arg; 3088 3089 /* 3090 * We have to prevent ip_close/ilg_delete_all from running at 3091 * the same time. ip_close sets CONN_CLOSING before doing the ilg_delete 3092 * all, and we set CONN_UPDATE_ILL. That ensures that only one of 3093 * ilg_delete_all and conn_update_ill run at a time for a given conn. 3094 * If ilg_delete_all got here first, then we have nothing to do. 3095 */ 3096 mutex_enter(&connp->conn_lock); 3097 if (connp->conn_state_flags & (CONN_CLOSING|CONN_UPDATE_ILL)) { 3098 /* Caller has to wait for ill_ilm_cnt to drop to zero */ 3099 mutex_exit(&connp->conn_lock); 3100 return; 3101 } 3102 connp->conn_state_flags |= CONN_UPDATE_ILL; 3103 mutex_exit(&connp->conn_lock); 3104 3105 if (ill != NULL) 3106 ilg_check_detach(connp, ill); 3107 3108 ilg_check_reattach(connp); 3109 3110 /* Do we need to wake up a thread in ilg_delete_all? */ 3111 mutex_enter(&connp->conn_lock); 3112 connp->conn_state_flags &= ~CONN_UPDATE_ILL; 3113 if (connp->conn_state_flags & CONN_CLOSING) 3114 cv_broadcast(&connp->conn_cv); 3115 mutex_exit(&connp->conn_lock); 3116 } 3117 3118 /* Detach from an ill that is going away */ 3119 static void 3120 ilg_check_detach(conn_t *connp, ill_t *ill) 3121 { 3122 char group_buf[INET6_ADDRSTRLEN]; 3123 ilg_t *ilg, *held_ilg; 3124 ilm_t *ilm; 3125 3126 mutex_enter(&ill->ill_mcast_serializer); 3127 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3128 held_ilg = NULL; 3129 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 3130 if (ilg->ilg_condemned) 3131 continue; 3132 3133 if (ilg->ilg_ill != ill) 3134 continue; 3135 3136 /* Detach from current ill */ 3137 ip1dbg(("ilg_check_detach: detach %s on %s\n", 3138 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3139 group_buf, sizeof (group_buf)), 3140 ilg->ilg_ill->ill_name)); 3141 3142 /* Detach this ilg from the ill/ilm */ 3143 ilm = ilg->ilg_ilm; 3144 ilg->ilg_ilm = NULL; 3145 ilg->ilg_ill = NULL; 3146 if (ilm == NULL) 3147 continue; 3148 3149 /* Prevent ilg from disappearing */ 3150 ilg_transfer_hold(held_ilg, ilg); 3151 held_ilg = ilg; 3152 rw_exit(&connp->conn_ilg_lock); 3153 3154 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 3155 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3156 } 3157 if (held_ilg != NULL) 3158 ilg_refrele(held_ilg); 3159 rw_exit(&connp->conn_ilg_lock); 3160 mutex_exit(&ill->ill_mcast_serializer); 3161 } 3162 3163 /* 3164 * Check if there is a place to attach the conn_ilgs. We do this for both 3165 * detached ilgs and attached ones, since for the latter there could be 3166 * a better ill to attach them to. 3167 */ 3168 static void 3169 ilg_check_reattach(conn_t *connp) 3170 { 3171 ill_t *ill; 3172 char group_buf[INET6_ADDRSTRLEN]; 3173 ilg_t *ilg, *held_ilg; 3174 ilm_t *ilm; 3175 zoneid_t zoneid = IPCL_ZONEID(connp); 3176 int error; 3177 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 3178 3179 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3180 held_ilg = NULL; 3181 for (ilg = connp->conn_ilg; ilg != NULL; ilg = ilg->ilg_next) { 3182 if (ilg->ilg_condemned) 3183 continue; 3184 3185 /* Check if the conn_ill matches what we would pick now */ 3186 ill = ill_mcast_lookup(&ilg->ilg_v6group, ilg->ilg_ifaddr, 3187 ilg->ilg_ifindex, zoneid, ipst, &error); 3188 3189 /* 3190 * Make sure the ill is usable for multicast and that 3191 * we can send the DL_ADDMULTI_REQ before we create an 3192 * ilm. 3193 */ 3194 if (ill != NULL && 3195 (!(ill->ill_flags & ILLF_MULTICAST) || !ill->ill_dl_up)) { 3196 /* Drop locks across ill_refrele */ 3197 ilg_transfer_hold(held_ilg, ilg); 3198 held_ilg = ilg; 3199 rw_exit(&connp->conn_ilg_lock); 3200 ill_refrele(ill); 3201 ill = NULL; 3202 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3203 /* Note that ilg could have become condemned */ 3204 } 3205 3206 /* Is the ill unchanged, even if both are NULL? */ 3207 if (ill == ilg->ilg_ill) { 3208 if (ill != NULL) { 3209 /* Drop locks across ill_refrele */ 3210 ilg_transfer_hold(held_ilg, ilg); 3211 held_ilg = ilg; 3212 rw_exit(&connp->conn_ilg_lock); 3213 ill_refrele(ill); 3214 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3215 } 3216 continue; 3217 } 3218 3219 /* Something changed; detach from old first if needed */ 3220 if (ilg->ilg_ill != NULL) { 3221 ill_t *ill2 = ilg->ilg_ill; 3222 boolean_t need_refrele = B_FALSE; 3223 3224 /* 3225 * In order to serialize on the ill we try to enter 3226 * and if that fails we unlock and relock. 3227 */ 3228 if (!mutex_tryenter(&ill2->ill_mcast_serializer)) { 3229 ill_refhold(ill2); 3230 need_refrele = B_TRUE; 3231 ilg_transfer_hold(held_ilg, ilg); 3232 held_ilg = ilg; 3233 rw_exit(&connp->conn_ilg_lock); 3234 mutex_enter(&ill2->ill_mcast_serializer); 3235 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3236 /* Note that ilg could have become condemned */ 3237 } 3238 /* 3239 * Check that nobody else re-attached the ilg while we 3240 * dropped the lock. 3241 */ 3242 if (ilg->ilg_ill == ill2) { 3243 ASSERT(!ilg->ilg_condemned); 3244 /* Detach from current ill */ 3245 ip1dbg(("conn_check_reattach: detach %s/%s\n", 3246 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3247 group_buf, sizeof (group_buf)), 3248 ill2->ill_name)); 3249 3250 ilm = ilg->ilg_ilm; 3251 ilg->ilg_ilm = NULL; 3252 ilg->ilg_ill = NULL; 3253 } else { 3254 ilm = NULL; 3255 } 3256 rw_exit(&connp->conn_ilg_lock); 3257 if (ilm != NULL) 3258 (void) ip_delmulti_serial(ilm, B_FALSE, B_TRUE); 3259 mutex_exit(&ill2->ill_mcast_serializer); 3260 if (need_refrele) { 3261 /* Drop ill reference while we hold no locks */ 3262 ill_refrele(ill2); 3263 } 3264 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3265 /* 3266 * While we dropped conn_ilg_lock some other thread 3267 * could have attached this ilg, thus we check again. 3268 */ 3269 if (ilg->ilg_ill != NULL) { 3270 if (ill != NULL) { 3271 /* Drop locks across ill_refrele */ 3272 ilg_transfer_hold(held_ilg, ilg); 3273 held_ilg = ilg; 3274 rw_exit(&connp->conn_ilg_lock); 3275 ill_refrele(ill); 3276 rw_enter(&connp->conn_ilg_lock, 3277 RW_WRITER); 3278 } 3279 continue; 3280 } 3281 } 3282 if (ill != NULL) { 3283 /* 3284 * In order to serialize on the ill we try to enter 3285 * and if that fails we unlock and relock. 3286 */ 3287 if (!mutex_tryenter(&ill->ill_mcast_serializer)) { 3288 /* Already have a refhold on ill */ 3289 ilg_transfer_hold(held_ilg, ilg); 3290 held_ilg = ilg; 3291 rw_exit(&connp->conn_ilg_lock); 3292 mutex_enter(&ill->ill_mcast_serializer); 3293 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3294 /* Note that ilg could have become condemned */ 3295 } 3296 3297 /* 3298 * Check that nobody else attached the ilg and that 3299 * it wasn't condemned while we dropped the lock. 3300 */ 3301 if (ilg->ilg_ill == NULL && !ilg->ilg_condemned) { 3302 /* 3303 * Attach to the new ill. Can fail in which 3304 * case ilg_ill will remain NULL. ilg_attach 3305 * drops and reacquires conn_ilg_lock. 3306 */ 3307 ip1dbg(("conn_check_reattach: attach %s/%s\n", 3308 inet_ntop(AF_INET6, &ilg->ilg_v6group, 3309 group_buf, sizeof (group_buf)), 3310 ill->ill_name)); 3311 ilg_attach(connp, ilg, ill); 3312 ASSERT(RW_WRITE_HELD(&connp->conn_ilg_lock)); 3313 } 3314 mutex_exit(&ill->ill_mcast_serializer); 3315 /* Drop locks across ill_refrele */ 3316 ilg_transfer_hold(held_ilg, ilg); 3317 held_ilg = ilg; 3318 rw_exit(&connp->conn_ilg_lock); 3319 ill_refrele(ill); 3320 rw_enter(&connp->conn_ilg_lock, RW_WRITER); 3321 } 3322 } 3323 if (held_ilg != NULL) 3324 ilg_refrele(held_ilg); 3325 rw_exit(&connp->conn_ilg_lock); 3326 } 3327 3328 /* 3329 * Called when an ill is unplumbed to make sure that there are no 3330 * dangling conn references to that ill. In that case ill is non-NULL and 3331 * we make sure we remove all references to it. 3332 * Also called when we should revisit the ilg_ill used for multicast 3333 * memberships, in which case ill is NULL. 3334 */ 3335 void 3336 update_conn_ill(ill_t *ill, ip_stack_t *ipst) 3337 { 3338 ipcl_walk(conn_update_ill, (caddr_t)ill, ipst); 3339 } 3340