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 2008 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_v6(ipif_t *ipif, const in6_addr_t *group, 70 ilg_stat_t ilgstat, mcast_record_t ilg_fmode, slist_t *ilg_flist, 71 int orig_ifindex, zoneid_t zoneid); 72 static void ilm_delete(ilm_t *ilm); 73 static int ip_ll_addmulti_v6(ipif_t *ipif, const in6_addr_t *group); 74 static int ip_ll_delmulti_v6(ipif_t *ipif, const in6_addr_t *group); 75 static ilg_t *ilg_lookup_ill_index_v6(conn_t *connp, 76 const in6_addr_t *v6group, int index); 77 static ilg_t *ilg_lookup_ipif(conn_t *connp, ipaddr_t group, 78 ipif_t *ipif); 79 static int ilg_add(conn_t *connp, ipaddr_t group, ipif_t *ipif, 80 mcast_record_t fmode, ipaddr_t src); 81 static int ilg_add_v6(conn_t *connp, const in6_addr_t *group, ill_t *ill, 82 mcast_record_t fmode, const in6_addr_t *v6src); 83 static void ilg_delete(conn_t *connp, ilg_t *ilg, const in6_addr_t *src); 84 static mblk_t *ill_create_dl(ill_t *ill, uint32_t dl_primitive, 85 uint32_t length, uint32_t *addr_lenp, uint32_t *addr_offp); 86 static mblk_t *ill_create_squery(ill_t *ill, ipaddr_t ipaddr, 87 uint32_t addrlen, uint32_t addroff, mblk_t *mp_tail); 88 static void conn_ilg_reap(conn_t *connp); 89 static int ip_opt_delete_group_excl(conn_t *connp, ipaddr_t group, 90 ipif_t *ipif, mcast_record_t fmode, ipaddr_t src); 91 static int ip_opt_delete_group_excl_v6(conn_t *connp, 92 const in6_addr_t *v6group, ill_t *ill, mcast_record_t fmode, 93 const in6_addr_t *v6src); 94 95 /* 96 * MT notes: 97 * 98 * Multicast joins operate on both the ilg and ilm structures. Multiple 99 * threads operating on an conn (socket) trying to do multicast joins 100 * need to synchronize when operating on the ilg. Multiple threads 101 * potentially operating on different conn (socket endpoints) trying to 102 * do multicast joins could eventually end up trying to manipulate the 103 * ilm simulatenously and need to synchronize on the access to the ilm. 104 * Both are amenable to standard Solaris MT techniques, but it would be 105 * complex to handle a failover or failback which needs to manipulate 106 * ilg/ilms if an applications can also simultaenously join/leave 107 * multicast groups. Hence multicast join/leave also go through the ipsq_t 108 * serialization. 109 * 110 * Multicast joins and leaves are single-threaded per phyint/IPMP group 111 * using the ipsq serialization mechanism. 112 * 113 * An ilm is an IP data structure used to track multicast join/leave. 114 * An ilm is associated with a <multicast group, ipif> tuple in IPv4 and 115 * with just <multicast group> in IPv6. ilm_refcnt is the number of ilg's 116 * referencing the ilm. ilms are created / destroyed only as writer. ilms 117 * are not passed around, instead they are looked up and used under the 118 * ill_lock or as writer. So we don't need a dynamic refcount of the number 119 * of threads holding reference to an ilm. 120 * 121 * Multicast Join operation: 122 * 123 * The first step is to determine the ipif (v4) or ill (v6) on which 124 * the join operation is to be done. The join is done after becoming 125 * exclusive on the ipsq associated with the ipif or ill. The conn->conn_ilg 126 * and ill->ill_ilm are thus accessed and modified exclusively per ill. 127 * Multiple threads can attempt to join simultaneously on different ipif/ill 128 * on the same conn. In this case the ipsq serialization does not help in 129 * protecting the ilg. It is the conn_lock that is used to protect the ilg. 130 * The conn_lock also protects all the ilg_t members. 131 * 132 * Leave operation. 133 * 134 * Similar to the join operation, the first step is to determine the ipif 135 * or ill (v6) on which the leave operation is to be done. The leave operation 136 * is done after becoming exclusive on the ipsq associated with the ipif or ill. 137 * As with join ilg modification is done under the protection of the conn lock. 138 */ 139 140 #define IPSQ_ENTER_IPIF(ipif, connp, first_mp, func, ipsq, type) \ 141 ASSERT(connp != NULL); \ 142 (ipsq) = ipsq_try_enter((ipif), NULL, CONNP_TO_WQ(connp), \ 143 (first_mp), (func), (type), B_TRUE); \ 144 if ((ipsq) == NULL) { \ 145 ipif_refrele(ipif); \ 146 return (EINPROGRESS); \ 147 } 148 149 #define IPSQ_ENTER_ILL(ill, connp, first_mp, func, ipsq, type) \ 150 ASSERT(connp != NULL); \ 151 (ipsq) = ipsq_try_enter(NULL, ill, CONNP_TO_WQ(connp), \ 152 (first_mp), (func), (type), B_TRUE); \ 153 if ((ipsq) == NULL) { \ 154 ill_refrele(ill); \ 155 return (EINPROGRESS); \ 156 } 157 158 #define IPSQ_EXIT(ipsq) \ 159 if (ipsq != NULL) \ 160 ipsq_exit(ipsq); 161 162 #define ILG_WALKER_HOLD(connp) (connp)->conn_ilg_walker_cnt++ 163 164 #define ILG_WALKER_RELE(connp) \ 165 { \ 166 (connp)->conn_ilg_walker_cnt--; \ 167 if ((connp)->conn_ilg_walker_cnt == 0) \ 168 conn_ilg_reap(connp); \ 169 } 170 171 static void 172 conn_ilg_reap(conn_t *connp) 173 { 174 int to; 175 int from; 176 ilg_t *ilg; 177 178 ASSERT(MUTEX_HELD(&connp->conn_lock)); 179 180 to = 0; 181 from = 0; 182 while (from < connp->conn_ilg_inuse) { 183 if (connp->conn_ilg[from].ilg_flags & ILG_DELETED) { 184 ilg = &connp->conn_ilg[from]; 185 FREE_SLIST(ilg->ilg_filter); 186 ilg->ilg_flags &= ~ILG_DELETED; 187 from++; 188 continue; 189 } 190 if (to != from) 191 connp->conn_ilg[to] = connp->conn_ilg[from]; 192 to++; 193 from++; 194 } 195 196 connp->conn_ilg_inuse = to; 197 198 if (connp->conn_ilg_inuse == 0) { 199 mi_free((char *)connp->conn_ilg); 200 connp->conn_ilg = NULL; 201 cv_broadcast(&connp->conn_refcv); 202 } 203 } 204 205 #define GETSTRUCT(structure, number) \ 206 ((structure *)mi_zalloc(sizeof (structure) * (number))) 207 208 #define ILG_ALLOC_CHUNK 16 209 210 /* 211 * Returns a pointer to the next available ilg in conn_ilg. Allocs more 212 * buffers in size of ILG_ALLOC_CHUNK ilgs when needed, and updates conn's 213 * ilg tracking fields appropriately (conn_ilg_inuse reflects usage of the 214 * returned ilg). Returns NULL on failure (ENOMEM). 215 * 216 * Assumes connp->conn_lock is held. 217 */ 218 static ilg_t * 219 conn_ilg_alloc(conn_t *connp) 220 { 221 ilg_t *new, *ret; 222 int curcnt; 223 224 ASSERT(MUTEX_HELD(&connp->conn_lock)); 225 ASSERT(connp->conn_ilg_inuse <= connp->conn_ilg_allocated); 226 227 if (connp->conn_ilg == NULL) { 228 connp->conn_ilg = GETSTRUCT(ilg_t, ILG_ALLOC_CHUNK); 229 if (connp->conn_ilg == NULL) 230 return (NULL); 231 connp->conn_ilg_allocated = ILG_ALLOC_CHUNK; 232 connp->conn_ilg_inuse = 0; 233 } 234 if (connp->conn_ilg_inuse == connp->conn_ilg_allocated) { 235 if (connp->conn_ilg_walker_cnt != 0) { 236 /* 237 * XXX We cannot grow the array at this point 238 * because a list walker could be in progress, and 239 * we cannot wipe out the existing array until the 240 * walker is done. Just return NULL for now. 241 * ilg_delete_all() will have to be changed when 242 * this logic is changed. 243 */ 244 return (NULL); 245 } 246 curcnt = connp->conn_ilg_allocated; 247 new = GETSTRUCT(ilg_t, curcnt + ILG_ALLOC_CHUNK); 248 if (new == NULL) 249 return (NULL); 250 bcopy(connp->conn_ilg, new, sizeof (ilg_t) * curcnt); 251 mi_free((char *)connp->conn_ilg); 252 connp->conn_ilg = new; 253 connp->conn_ilg_allocated += ILG_ALLOC_CHUNK; 254 } 255 256 ret = &connp->conn_ilg[connp->conn_ilg_inuse++]; 257 ASSERT((ret->ilg_flags & ILG_DELETED) == 0); 258 bzero(ret, sizeof (*ret)); 259 return (ret); 260 } 261 262 typedef struct ilm_fbld_s { 263 ilm_t *fbld_ilm; 264 int fbld_in_cnt; 265 int fbld_ex_cnt; 266 slist_t fbld_in; 267 slist_t fbld_ex; 268 boolean_t fbld_in_overflow; 269 } ilm_fbld_t; 270 271 static void 272 ilm_bld_flists(conn_t *conn, void *arg) 273 { 274 int i; 275 ilm_fbld_t *fbld = (ilm_fbld_t *)(arg); 276 ilm_t *ilm = fbld->fbld_ilm; 277 in6_addr_t *v6group = &ilm->ilm_v6addr; 278 279 if (conn->conn_ilg_inuse == 0) 280 return; 281 282 /* 283 * Since we can't break out of the ipcl_walk once started, we still 284 * have to look at every conn. But if we've already found one 285 * (EXCLUDE, NULL) list, there's no need to keep checking individual 286 * ilgs--that will be our state. 287 */ 288 if (fbld->fbld_ex_cnt > 0 && fbld->fbld_ex.sl_numsrc == 0) 289 return; 290 291 /* 292 * Check this conn's ilgs to see if any are interested in our 293 * ilm (group, interface match). If so, update the master 294 * include and exclude lists we're building in the fbld struct 295 * with this ilg's filter info. 296 */ 297 mutex_enter(&conn->conn_lock); 298 for (i = 0; i < conn->conn_ilg_inuse; i++) { 299 ilg_t *ilg = &conn->conn_ilg[i]; 300 if ((ilg->ilg_ill == ilm->ilm_ill) && 301 (ilg->ilg_ipif == ilm->ilm_ipif) && 302 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) { 303 if (ilg->ilg_fmode == MODE_IS_INCLUDE) { 304 fbld->fbld_in_cnt++; 305 if (!fbld->fbld_in_overflow) 306 l_union_in_a(&fbld->fbld_in, 307 ilg->ilg_filter, 308 &fbld->fbld_in_overflow); 309 } else { 310 fbld->fbld_ex_cnt++; 311 /* 312 * On the first exclude list, don't try to do 313 * an intersection, as the master exclude list 314 * is intentionally empty. If the master list 315 * is still empty on later iterations, that 316 * means we have at least one ilg with an empty 317 * exclude list, so that should be reflected 318 * when we take the intersection. 319 */ 320 if (fbld->fbld_ex_cnt == 1) { 321 if (ilg->ilg_filter != NULL) 322 l_copy(ilg->ilg_filter, 323 &fbld->fbld_ex); 324 } else { 325 l_intersection_in_a(&fbld->fbld_ex, 326 ilg->ilg_filter); 327 } 328 } 329 /* there will only be one match, so break now. */ 330 break; 331 } 332 } 333 mutex_exit(&conn->conn_lock); 334 } 335 336 static void 337 ilm_gen_filter(ilm_t *ilm, mcast_record_t *fmode, slist_t *flist) 338 { 339 ilm_fbld_t fbld; 340 ip_stack_t *ipst = ilm->ilm_ipst; 341 342 fbld.fbld_ilm = ilm; 343 fbld.fbld_in_cnt = fbld.fbld_ex_cnt = 0; 344 fbld.fbld_in.sl_numsrc = fbld.fbld_ex.sl_numsrc = 0; 345 fbld.fbld_in_overflow = B_FALSE; 346 347 /* first, construct our master include and exclude lists */ 348 ipcl_walk(ilm_bld_flists, (caddr_t)&fbld, ipst); 349 350 /* now use those master lists to generate the interface filter */ 351 352 /* if include list overflowed, filter is (EXCLUDE, NULL) */ 353 if (fbld.fbld_in_overflow) { 354 *fmode = MODE_IS_EXCLUDE; 355 flist->sl_numsrc = 0; 356 return; 357 } 358 359 /* if nobody interested, interface filter is (INCLUDE, NULL) */ 360 if (fbld.fbld_in_cnt == 0 && fbld.fbld_ex_cnt == 0) { 361 *fmode = MODE_IS_INCLUDE; 362 flist->sl_numsrc = 0; 363 return; 364 } 365 366 /* 367 * If there are no exclude lists, then the interface filter 368 * is INCLUDE, with its filter list equal to fbld_in. A single 369 * exclude list makes the interface filter EXCLUDE, with its 370 * filter list equal to (fbld_ex - fbld_in). 371 */ 372 if (fbld.fbld_ex_cnt == 0) { 373 *fmode = MODE_IS_INCLUDE; 374 l_copy(&fbld.fbld_in, flist); 375 } else { 376 *fmode = MODE_IS_EXCLUDE; 377 l_difference(&fbld.fbld_ex, &fbld.fbld_in, flist); 378 } 379 } 380 381 /* 382 * If the given interface has failed, choose a new one to join on so 383 * that we continue to receive packets. ilg_orig_ifindex remembers 384 * what the application used to join on so that we know the ilg to 385 * delete even though we change the ill here. Callers will store the 386 * ilg returned from this function in ilg_ill. Thus when we receive 387 * a packet on ilg_ill, conn_wantpacket_v6 will deliver the packets. 388 * 389 * This function must be called as writer so we can walk the group 390 * list and examine flags without holding a lock. 391 */ 392 ill_t * 393 ip_choose_multi_ill(ill_t *ill, const in6_addr_t *grp) 394 { 395 ill_t *till; 396 ill_group_t *illgrp = ill->ill_group; 397 398 ASSERT(IAM_WRITER_ILL(ill)); 399 400 if (IN6_IS_ADDR_UNSPECIFIED(grp) || illgrp == NULL) 401 return (ill); 402 403 if ((ill->ill_phyint->phyint_flags & (PHYI_FAILED|PHYI_INACTIVE)) == 0) 404 return (ill); 405 406 till = illgrp->illgrp_ill; 407 while (till != NULL && 408 (till->ill_phyint->phyint_flags & (PHYI_FAILED|PHYI_INACTIVE))) { 409 till = till->ill_group_next; 410 } 411 if (till != NULL) 412 return (till); 413 414 return (ill); 415 } 416 417 static int 418 ilm_update_add(ilm_t *ilm, ilg_stat_t ilgstat, slist_t *ilg_flist, 419 boolean_t isv6) 420 { 421 mcast_record_t fmode; 422 slist_t *flist; 423 boolean_t fdefault; 424 char buf[INET6_ADDRSTRLEN]; 425 ill_t *ill = isv6 ? ilm->ilm_ill : ilm->ilm_ipif->ipif_ill; 426 427 /* 428 * There are several cases where the ilm's filter state 429 * defaults to (EXCLUDE, NULL): 430 * - we've had previous joins without associated ilgs 431 * - this join has no associated ilg 432 * - the ilg's filter state is (EXCLUDE, NULL) 433 */ 434 fdefault = (ilm->ilm_no_ilg_cnt > 0) || 435 (ilgstat == ILGSTAT_NONE) || SLIST_IS_EMPTY(ilg_flist); 436 437 /* attempt mallocs (if needed) before doing anything else */ 438 if ((flist = l_alloc()) == NULL) 439 return (ENOMEM); 440 if (!fdefault && ilm->ilm_filter == NULL) { 441 ilm->ilm_filter = l_alloc(); 442 if (ilm->ilm_filter == NULL) { 443 l_free(flist); 444 return (ENOMEM); 445 } 446 } 447 448 if (ilgstat != ILGSTAT_CHANGE) 449 ilm->ilm_refcnt++; 450 451 if (ilgstat == ILGSTAT_NONE) 452 ilm->ilm_no_ilg_cnt++; 453 454 /* 455 * Determine new filter state. If it's not the default 456 * (EXCLUDE, NULL), we must walk the conn list to find 457 * any ilgs interested in this group, and re-build the 458 * ilm filter. 459 */ 460 if (fdefault) { 461 fmode = MODE_IS_EXCLUDE; 462 flist->sl_numsrc = 0; 463 } else { 464 ilm_gen_filter(ilm, &fmode, flist); 465 } 466 467 /* make sure state actually changed; nothing to do if not. */ 468 if ((ilm->ilm_fmode == fmode) && 469 !lists_are_different(ilm->ilm_filter, flist)) { 470 l_free(flist); 471 return (0); 472 } 473 474 /* send the state change report */ 475 if (!IS_LOOPBACK(ill)) { 476 if (isv6) 477 mld_statechange(ilm, fmode, flist); 478 else 479 igmp_statechange(ilm, fmode, flist); 480 } 481 482 /* update the ilm state */ 483 ilm->ilm_fmode = fmode; 484 if (flist->sl_numsrc > 0) 485 l_copy(flist, ilm->ilm_filter); 486 else 487 CLEAR_SLIST(ilm->ilm_filter); 488 489 ip1dbg(("ilm_update: new if filter mode %d, group %s\n", ilm->ilm_fmode, 490 inet_ntop(AF_INET6, &ilm->ilm_v6addr, buf, sizeof (buf)))); 491 492 l_free(flist); 493 return (0); 494 } 495 496 static int 497 ilm_update_del(ilm_t *ilm, boolean_t isv6) 498 { 499 mcast_record_t fmode; 500 slist_t *flist; 501 ill_t *ill = isv6 ? ilm->ilm_ill : ilm->ilm_ipif->ipif_ill; 502 503 ip1dbg(("ilm_update_del: still %d left; updating state\n", 504 ilm->ilm_refcnt)); 505 506 if ((flist = l_alloc()) == NULL) 507 return (ENOMEM); 508 509 /* 510 * If present, the ilg in question has already either been 511 * updated or removed from our list; so all we need to do 512 * now is walk the list to update the ilm filter state. 513 * 514 * Skip the list walk if we have any no-ilg joins, which 515 * cause the filter state to revert to (EXCLUDE, NULL). 516 */ 517 if (ilm->ilm_no_ilg_cnt != 0) { 518 fmode = MODE_IS_EXCLUDE; 519 flist->sl_numsrc = 0; 520 } else { 521 ilm_gen_filter(ilm, &fmode, flist); 522 } 523 524 /* check to see if state needs to be updated */ 525 if ((ilm->ilm_fmode == fmode) && 526 (!lists_are_different(ilm->ilm_filter, flist))) { 527 l_free(flist); 528 return (0); 529 } 530 531 if (!IS_LOOPBACK(ill)) { 532 if (isv6) 533 mld_statechange(ilm, fmode, flist); 534 else 535 igmp_statechange(ilm, fmode, flist); 536 } 537 538 ilm->ilm_fmode = fmode; 539 if (flist->sl_numsrc > 0) { 540 if (ilm->ilm_filter == NULL) { 541 ilm->ilm_filter = l_alloc(); 542 if (ilm->ilm_filter == NULL) { 543 char buf[INET6_ADDRSTRLEN]; 544 ip1dbg(("ilm_update_del: failed to alloc ilm " 545 "filter; no source filtering for %s on %s", 546 inet_ntop(AF_INET6, &ilm->ilm_v6addr, 547 buf, sizeof (buf)), ill->ill_name)); 548 ilm->ilm_fmode = MODE_IS_EXCLUDE; 549 l_free(flist); 550 return (0); 551 } 552 } 553 l_copy(flist, ilm->ilm_filter); 554 } else { 555 CLEAR_SLIST(ilm->ilm_filter); 556 } 557 558 l_free(flist); 559 return (0); 560 } 561 562 /* 563 * INADDR_ANY means all multicast addresses. This is only used 564 * by the multicast router. 565 * INADDR_ANY is stored as IPv6 unspecified addr. 566 */ 567 int 568 ip_addmulti(ipaddr_t group, ipif_t *ipif, ilg_stat_t ilgstat, 569 mcast_record_t ilg_fmode, slist_t *ilg_flist) 570 { 571 ill_t *ill = ipif->ipif_ill; 572 ilm_t *ilm; 573 in6_addr_t v6group; 574 int ret; 575 576 ASSERT(IAM_WRITER_IPIF(ipif)); 577 578 if (!CLASSD(group) && group != INADDR_ANY) 579 return (EINVAL); 580 581 /* 582 * INADDR_ANY is represented as the IPv6 unspecifed addr. 583 */ 584 if (group == INADDR_ANY) 585 v6group = ipv6_all_zeros; 586 else 587 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 588 589 mutex_enter(&ill->ill_lock); 590 ilm = ilm_lookup_ipif(ipif, group); 591 mutex_exit(&ill->ill_lock); 592 /* 593 * Since we are writer, we know the ilm_flags itself cannot 594 * change at this point, and ilm_lookup_ipif would not have 595 * returned a DELETED ilm. However, the data path can free 596 * ilm->next via ilm_walker_cleanup() so we can safely 597 * access anything in ilm except ilm_next (for safe access to 598 * ilm_next we'd have to take the ill_lock). 599 */ 600 if (ilm != NULL) 601 return (ilm_update_add(ilm, ilgstat, ilg_flist, B_FALSE)); 602 603 /* 604 * ilms are associated with ipifs in IPv4. It moves with the 605 * ipif if the ipif moves to a new ill when the interface 606 * fails. Thus we really don't check whether the ipif_ill 607 * has failed like in IPv6. If it has FAILED the ipif 608 * will move (daemon will move it) and hence the ilm, if the 609 * ipif is not IPIF_NOFAILOVER. For the IPIF_NOFAILOVER ipifs, 610 * we continue to receive in the same place even if the 611 * interface fails. 612 */ 613 ilm = ilm_add_v6(ipif, &v6group, ilgstat, ilg_fmode, ilg_flist, 614 ill->ill_phyint->phyint_ifindex, ipif->ipif_zoneid); 615 if (ilm == NULL) 616 return (ENOMEM); 617 618 if (group == INADDR_ANY) { 619 /* 620 * Check how many ipif's have members in this group - 621 * if more then one we should not tell the driver to join 622 * this time 623 */ 624 if (ilm_numentries_v6(ill, &v6group) > 1) 625 return (0); 626 if (ill->ill_group == NULL) 627 ret = ill_join_allmulti(ill); 628 else 629 ret = ill_nominate_mcast_rcv(ill->ill_group); 630 if (ret != 0) 631 ilm_delete(ilm); 632 return (ret); 633 } 634 635 if (!IS_LOOPBACK(ill)) 636 igmp_joingroup(ilm); 637 638 if (ilm_numentries_v6(ill, &v6group) > 1) 639 return (0); 640 641 ret = ip_ll_addmulti_v6(ipif, &v6group); 642 if (ret != 0) 643 ilm_delete(ilm); 644 return (ret); 645 } 646 647 /* 648 * The unspecified address means all multicast addresses. 649 * This is only used by the multicast router. 650 * 651 * ill identifies the interface to join on; it may not match the 652 * interface requested by the application of a failover has taken 653 * place. orig_ifindex always identifies the interface requested 654 * by the app. 655 * 656 * ilgstat tells us if there's an ilg associated with this join, 657 * and if so, if it's a new ilg or a change to an existing one. 658 * ilg_fmode and ilg_flist give us the current filter state of 659 * the ilg (and will be EXCLUDE {NULL} in the case of no ilg). 660 */ 661 int 662 ip_addmulti_v6(const in6_addr_t *v6group, ill_t *ill, int orig_ifindex, 663 zoneid_t zoneid, ilg_stat_t ilgstat, mcast_record_t ilg_fmode, 664 slist_t *ilg_flist) 665 { 666 ilm_t *ilm; 667 int ret; 668 669 ASSERT(IAM_WRITER_ILL(ill)); 670 671 if (!IN6_IS_ADDR_MULTICAST(v6group) && 672 !IN6_IS_ADDR_UNSPECIFIED(v6group)) { 673 return (EINVAL); 674 } 675 676 /* 677 * An ilm is uniquely identified by the tuple of (group, ill, 678 * orig_ill). group is the multicast group address, ill is 679 * the interface on which it is currently joined, and orig_ill 680 * is the interface on which the application requested the 681 * join. orig_ill and ill are the same unless orig_ill has 682 * failed over. 683 * 684 * Both orig_ill and ill are required, which means we may have 685 * 2 ilms on an ill for the same group, but with different 686 * orig_ills. These must be kept separate, so that when failback 687 * occurs, the appropriate ilms are moved back to their orig_ill 688 * without disrupting memberships on the ill to which they had 689 * been moved. 690 * 691 * In order to track orig_ill, we store orig_ifindex in the 692 * ilm and ilg. 693 */ 694 mutex_enter(&ill->ill_lock); 695 ilm = ilm_lookup_ill_index_v6(ill, v6group, orig_ifindex, zoneid); 696 mutex_exit(&ill->ill_lock); 697 if (ilm != NULL) 698 return (ilm_update_add(ilm, ilgstat, ilg_flist, B_TRUE)); 699 700 /* 701 * We need to remember where the application really wanted 702 * to join. This will be used later if we want to failback 703 * to the original interface. 704 */ 705 ilm = ilm_add_v6(ill->ill_ipif, v6group, ilgstat, ilg_fmode, 706 ilg_flist, orig_ifindex, zoneid); 707 if (ilm == NULL) 708 return (ENOMEM); 709 710 if (IN6_IS_ADDR_UNSPECIFIED(v6group)) { 711 /* 712 * Check how many ipif's that have members in this group - 713 * if more then one we should not tell the driver to join 714 * this time 715 */ 716 if (ilm_numentries_v6(ill, v6group) > 1) 717 return (0); 718 if (ill->ill_group == NULL) 719 ret = ill_join_allmulti(ill); 720 else 721 ret = ill_nominate_mcast_rcv(ill->ill_group); 722 723 if (ret != 0) 724 ilm_delete(ilm); 725 return (ret); 726 } 727 728 if (!IS_LOOPBACK(ill)) 729 mld_joingroup(ilm); 730 731 /* 732 * If we have more then one we should not tell the driver 733 * to join this time. 734 */ 735 if (ilm_numentries_v6(ill, v6group) > 1) 736 return (0); 737 738 ret = ip_ll_addmulti_v6(ill->ill_ipif, v6group); 739 if (ret != 0) 740 ilm_delete(ilm); 741 return (ret); 742 } 743 744 /* 745 * Send a multicast request to the driver for enabling multicast reception 746 * for v6groupp address. The caller has already checked whether it is 747 * appropriate to send one or not. 748 */ 749 int 750 ip_ll_send_enabmulti_req(ill_t *ill, const in6_addr_t *v6groupp) 751 { 752 mblk_t *mp; 753 uint32_t addrlen, addroff; 754 char group_buf[INET6_ADDRSTRLEN]; 755 756 ASSERT(IAM_WRITER_ILL(ill)); 757 758 /* 759 * Create a AR_ENTRY_SQUERY message with a dl_enabmulti_req tacked 760 * on. 761 */ 762 mp = ill_create_dl(ill, DL_ENABMULTI_REQ, sizeof (dl_enabmulti_req_t), 763 &addrlen, &addroff); 764 if (!mp) 765 return (ENOMEM); 766 if (IN6_IS_ADDR_V4MAPPED(v6groupp)) { 767 ipaddr_t v4group; 768 769 IN6_V4MAPPED_TO_IPADDR(v6groupp, v4group); 770 /* 771 * NOTE!!! 772 * The "addroff" passed in here was calculated by 773 * ill_create_dl(), and will be used by ill_create_squery() 774 * to perform some twisted coding magic. It is the offset 775 * into the dl_xxx_req of the hw addr. Here, it will be 776 * added to b_wptr - b_rptr to create a magic number that 777 * is not an offset into this squery mblk. 778 * The actual hardware address will be accessed only in the 779 * dl_xxx_req, not in the squery. More importantly, 780 * that hardware address can *only* be accessed in this 781 * mblk chain by calling mi_offset_param_c(), which uses 782 * the magic number in the squery hw offset field to go 783 * to the *next* mblk (the dl_xxx_req), subtract the 784 * (b_wptr - b_rptr), and find the actual offset into 785 * the dl_xxx_req. 786 * Any method that depends on using the 787 * offset field in the dl_disabmulti_req or squery 788 * to find either hardware address will similarly fail. 789 * 790 * Look in ar_entry_squery() in arp.c to see how this offset 791 * is used. 792 */ 793 mp = ill_create_squery(ill, v4group, addrlen, addroff, mp); 794 if (!mp) 795 return (ENOMEM); 796 ip1dbg(("ip_ll_send_enabmulti_req: IPv4 putnext %s on %s\n", 797 inet_ntop(AF_INET6, v6groupp, group_buf, 798 sizeof (group_buf)), 799 ill->ill_name)); 800 putnext(ill->ill_rq, mp); 801 } else { 802 ip1dbg(("ip_ll_send_enabmulti_req: IPv6 ndp_mcastreq %s on" 803 " %s\n", 804 inet_ntop(AF_INET6, v6groupp, group_buf, 805 sizeof (group_buf)), 806 ill->ill_name)); 807 return (ndp_mcastreq(ill, v6groupp, addrlen, addroff, mp)); 808 } 809 return (0); 810 } 811 812 /* 813 * Send a multicast request to the driver for enabling multicast 814 * membership for v6group if appropriate. 815 */ 816 static int 817 ip_ll_addmulti_v6(ipif_t *ipif, const in6_addr_t *v6groupp) 818 { 819 ill_t *ill = ipif->ipif_ill; 820 821 ASSERT(IAM_WRITER_IPIF(ipif)); 822 823 if (ill->ill_net_type != IRE_IF_RESOLVER || 824 ipif->ipif_flags & IPIF_POINTOPOINT) { 825 ip1dbg(("ip_ll_addmulti_v6: not resolver\n")); 826 return (0); /* Must be IRE_IF_NORESOLVER */ 827 } 828 829 if (ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST) { 830 ip1dbg(("ip_ll_addmulti_v6: MULTI_BCAST\n")); 831 return (0); 832 } 833 if (!ill->ill_dl_up) { 834 /* 835 * Nobody there. All multicast addresses will be re-joined 836 * when we get the DL_BIND_ACK bringing the interface up. 837 */ 838 ip1dbg(("ip_ll_addmulti_v6: nobody up\n")); 839 return (0); 840 } 841 return (ip_ll_send_enabmulti_req(ill, v6groupp)); 842 } 843 844 /* 845 * INADDR_ANY means all multicast addresses. This is only used 846 * by the multicast router. 847 * INADDR_ANY is stored as the IPv6 unspecifed addr. 848 */ 849 int 850 ip_delmulti(ipaddr_t group, ipif_t *ipif, boolean_t no_ilg, boolean_t leaving) 851 { 852 ill_t *ill = ipif->ipif_ill; 853 ilm_t *ilm; 854 in6_addr_t v6group; 855 856 ASSERT(IAM_WRITER_IPIF(ipif)); 857 858 if (!CLASSD(group) && group != INADDR_ANY) 859 return (EINVAL); 860 861 /* 862 * INADDR_ANY is represented as the IPv6 unspecifed addr. 863 */ 864 if (group == INADDR_ANY) 865 v6group = ipv6_all_zeros; 866 else 867 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 868 869 /* 870 * Look for a match on the ipif. 871 * (IP_DROP_MEMBERSHIP specifies an ipif using an IP address). 872 */ 873 mutex_enter(&ill->ill_lock); 874 ilm = ilm_lookup_ipif(ipif, group); 875 mutex_exit(&ill->ill_lock); 876 if (ilm == NULL) 877 return (ENOENT); 878 879 /* Update counters */ 880 if (no_ilg) 881 ilm->ilm_no_ilg_cnt--; 882 883 if (leaving) 884 ilm->ilm_refcnt--; 885 886 if (ilm->ilm_refcnt > 0) 887 return (ilm_update_del(ilm, B_FALSE)); 888 889 if (group == INADDR_ANY) { 890 ilm_delete(ilm); 891 /* 892 * Check how many ipif's that have members in this group - 893 * if there are still some left then don't tell the driver 894 * to drop it. 895 */ 896 if (ilm_numentries_v6(ill, &v6group) != 0) 897 return (0); 898 899 /* If we never joined, then don't leave. */ 900 if (ill->ill_join_allmulti) { 901 ill_leave_allmulti(ill); 902 if (ill->ill_group != NULL) 903 (void) ill_nominate_mcast_rcv(ill->ill_group); 904 } 905 return (0); 906 } 907 908 if (!IS_LOOPBACK(ill)) 909 igmp_leavegroup(ilm); 910 911 ilm_delete(ilm); 912 /* 913 * Check how many ipif's that have members in this group - 914 * if there are still some left then don't tell the driver 915 * to drop it. 916 */ 917 if (ilm_numentries_v6(ill, &v6group) != 0) 918 return (0); 919 return (ip_ll_delmulti_v6(ipif, &v6group)); 920 } 921 922 /* 923 * The unspecified address means all multicast addresses. 924 * This is only used by the multicast router. 925 */ 926 int 927 ip_delmulti_v6(const in6_addr_t *v6group, ill_t *ill, int orig_ifindex, 928 zoneid_t zoneid, boolean_t no_ilg, boolean_t leaving) 929 { 930 ipif_t *ipif; 931 ilm_t *ilm; 932 933 ASSERT(IAM_WRITER_ILL(ill)); 934 935 if (!IN6_IS_ADDR_MULTICAST(v6group) && 936 !IN6_IS_ADDR_UNSPECIFIED(v6group)) 937 return (EINVAL); 938 939 /* 940 * Look for a match on the ill. 941 * (IPV6_LEAVE_GROUP specifies an ill using an ifindex). 942 * 943 * Similar to ip_addmulti_v6, we should always look using 944 * the orig_ifindex. 945 * 946 * 1) If orig_ifindex is different from ill's ifindex 947 * we should have an ilm with orig_ifindex created in 948 * ip_addmulti_v6. We should delete that here. 949 * 950 * 2) If orig_ifindex is same as ill's ifindex, we should 951 * not delete the ilm that is temporarily here because of 952 * a FAILOVER. Those ilms will have a ilm_orig_ifindex 953 * different from ill's ifindex. 954 * 955 * Thus, always lookup using orig_ifindex. 956 */ 957 mutex_enter(&ill->ill_lock); 958 ilm = ilm_lookup_ill_index_v6(ill, v6group, orig_ifindex, zoneid); 959 mutex_exit(&ill->ill_lock); 960 if (ilm == NULL) 961 return (ENOENT); 962 963 ASSERT(ilm->ilm_ill == ill); 964 965 ipif = ill->ill_ipif; 966 967 /* Update counters */ 968 if (no_ilg) 969 ilm->ilm_no_ilg_cnt--; 970 971 if (leaving) 972 ilm->ilm_refcnt--; 973 974 if (ilm->ilm_refcnt > 0) 975 return (ilm_update_del(ilm, B_TRUE)); 976 977 if (IN6_IS_ADDR_UNSPECIFIED(v6group)) { 978 ilm_delete(ilm); 979 /* 980 * Check how many ipif's that have members in this group - 981 * if there are still some left then don't tell the driver 982 * to drop it. 983 */ 984 if (ilm_numentries_v6(ill, v6group) != 0) 985 return (0); 986 987 /* If we never joined, then don't leave. */ 988 if (ill->ill_join_allmulti) { 989 ill_leave_allmulti(ill); 990 if (ill->ill_group != NULL) 991 (void) ill_nominate_mcast_rcv(ill->ill_group); 992 } 993 return (0); 994 } 995 996 if (!IS_LOOPBACK(ill)) 997 mld_leavegroup(ilm); 998 999 ilm_delete(ilm); 1000 /* 1001 * Check how many ipif's that have members in this group - 1002 * if there are still some left then don't tell the driver 1003 * to drop it. 1004 */ 1005 if (ilm_numentries_v6(ill, v6group) != 0) 1006 return (0); 1007 return (ip_ll_delmulti_v6(ipif, v6group)); 1008 } 1009 1010 /* 1011 * Send a multicast request to the driver for disabling multicast reception 1012 * for v6groupp address. The caller has already checked whether it is 1013 * appropriate to send one or not. 1014 */ 1015 int 1016 ip_ll_send_disabmulti_req(ill_t *ill, const in6_addr_t *v6groupp) 1017 { 1018 mblk_t *mp; 1019 char group_buf[INET6_ADDRSTRLEN]; 1020 uint32_t addrlen, addroff; 1021 1022 ASSERT(IAM_WRITER_ILL(ill)); 1023 /* 1024 * Create a AR_ENTRY_SQUERY message with a dl_disabmulti_req tacked 1025 * on. 1026 */ 1027 mp = ill_create_dl(ill, DL_DISABMULTI_REQ, 1028 sizeof (dl_disabmulti_req_t), &addrlen, &addroff); 1029 1030 if (!mp) 1031 return (ENOMEM); 1032 1033 if (IN6_IS_ADDR_V4MAPPED(v6groupp)) { 1034 ipaddr_t v4group; 1035 1036 IN6_V4MAPPED_TO_IPADDR(v6groupp, v4group); 1037 /* 1038 * NOTE!!! 1039 * The "addroff" passed in here was calculated by 1040 * ill_create_dl(), and will be used by ill_create_squery() 1041 * to perform some twisted coding magic. It is the offset 1042 * into the dl_xxx_req of the hw addr. Here, it will be 1043 * added to b_wptr - b_rptr to create a magic number that 1044 * is not an offset into this mblk. 1045 * 1046 * Please see the comment in ip_ll_send)enabmulti_req() 1047 * for a complete explanation. 1048 * 1049 * Look in ar_entry_squery() in arp.c to see how this offset 1050 * is used. 1051 */ 1052 mp = ill_create_squery(ill, v4group, addrlen, addroff, mp); 1053 if (!mp) 1054 return (ENOMEM); 1055 ip1dbg(("ip_ll_send_disabmulti_req: IPv4 putnext %s on %s\n", 1056 inet_ntop(AF_INET6, v6groupp, group_buf, 1057 sizeof (group_buf)), 1058 ill->ill_name)); 1059 putnext(ill->ill_rq, mp); 1060 } else { 1061 ip1dbg(("ip_ll_send_disabmulti_req: IPv6 ndp_mcastreq %s on" 1062 " %s\n", 1063 inet_ntop(AF_INET6, v6groupp, group_buf, 1064 sizeof (group_buf)), 1065 ill->ill_name)); 1066 return (ndp_mcastreq(ill, v6groupp, addrlen, addroff, mp)); 1067 } 1068 return (0); 1069 } 1070 1071 /* 1072 * Send a multicast request to the driver for disabling multicast 1073 * membership for v6group if appropriate. 1074 */ 1075 static int 1076 ip_ll_delmulti_v6(ipif_t *ipif, const in6_addr_t *v6group) 1077 { 1078 ill_t *ill = ipif->ipif_ill; 1079 1080 ASSERT(IAM_WRITER_IPIF(ipif)); 1081 1082 if (ill->ill_net_type != IRE_IF_RESOLVER || 1083 ipif->ipif_flags & IPIF_POINTOPOINT) { 1084 return (0); /* Must be IRE_IF_NORESOLVER */ 1085 } 1086 if (ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST) { 1087 ip1dbg(("ip_ll_delmulti_v6: MULTI_BCAST\n")); 1088 return (0); 1089 } 1090 if (!ill->ill_dl_up) { 1091 /* 1092 * Nobody there. All multicast addresses will be re-joined 1093 * when we get the DL_BIND_ACK bringing the interface up. 1094 */ 1095 ip1dbg(("ip_ll_delmulti_v6: nobody up\n")); 1096 return (0); 1097 } 1098 return (ip_ll_send_disabmulti_req(ill, v6group)); 1099 } 1100 1101 /* 1102 * Make the driver pass up all multicast packets 1103 * 1104 * With ill groups, the caller makes sure that there is only 1105 * one ill joining the allmulti group. 1106 */ 1107 int 1108 ill_join_allmulti(ill_t *ill) 1109 { 1110 mblk_t *promiscon_mp, *promiscoff_mp; 1111 uint32_t addrlen, addroff; 1112 1113 ASSERT(IAM_WRITER_ILL(ill)); 1114 1115 if (!ill->ill_dl_up) { 1116 /* 1117 * Nobody there. All multicast addresses will be re-joined 1118 * when we get the DL_BIND_ACK bringing the interface up. 1119 */ 1120 return (0); 1121 } 1122 1123 ASSERT(!ill->ill_join_allmulti); 1124 1125 /* 1126 * Create a DL_PROMISCON_REQ message and send it directly to the DLPI 1127 * provider. We don't need to do this for certain media types for 1128 * which we never need to turn promiscuous mode on. While we're here, 1129 * pre-allocate a DL_PROMISCOFF_REQ message to make sure that 1130 * ill_leave_allmulti() will not fail due to low memory conditions. 1131 */ 1132 if ((ill->ill_net_type == IRE_IF_RESOLVER) && 1133 !(ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST)) { 1134 promiscon_mp = ill_create_dl(ill, DL_PROMISCON_REQ, 1135 sizeof (dl_promiscon_req_t), &addrlen, &addroff); 1136 promiscoff_mp = ill_create_dl(ill, DL_PROMISCOFF_REQ, 1137 sizeof (dl_promiscoff_req_t), &addrlen, &addroff); 1138 if (promiscon_mp == NULL || promiscoff_mp == NULL) { 1139 freemsg(promiscon_mp); 1140 freemsg(promiscoff_mp); 1141 return (ENOMEM); 1142 } 1143 ill->ill_promiscoff_mp = promiscoff_mp; 1144 ill_dlpi_send(ill, promiscon_mp); 1145 } 1146 1147 ill->ill_join_allmulti = B_TRUE; 1148 return (0); 1149 } 1150 1151 /* 1152 * Make the driver stop passing up all multicast packets 1153 * 1154 * With ill groups, we need to nominate some other ill as 1155 * this ipif->ipif_ill is leaving the group. 1156 */ 1157 void 1158 ill_leave_allmulti(ill_t *ill) 1159 { 1160 mblk_t *promiscoff_mp = ill->ill_promiscoff_mp; 1161 1162 ASSERT(IAM_WRITER_ILL(ill)); 1163 1164 if (!ill->ill_dl_up) { 1165 /* 1166 * Nobody there. All multicast addresses will be re-joined 1167 * when we get the DL_BIND_ACK bringing the interface up. 1168 */ 1169 return; 1170 } 1171 1172 ASSERT(ill->ill_join_allmulti); 1173 1174 /* 1175 * Create a DL_PROMISCOFF_REQ message and send it directly to 1176 * the DLPI provider. We don't need to do this for certain 1177 * media types for which we never need to turn promiscuous 1178 * mode on. 1179 */ 1180 if ((ill->ill_net_type == IRE_IF_RESOLVER) && 1181 !(ill->ill_phyint->phyint_flags & PHYI_MULTI_BCAST)) { 1182 ASSERT(promiscoff_mp != NULL); 1183 ill->ill_promiscoff_mp = NULL; 1184 ill_dlpi_send(ill, promiscoff_mp); 1185 } 1186 1187 ill->ill_join_allmulti = B_FALSE; 1188 } 1189 1190 static ill_t * 1191 ipsq_enter_byifindex(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1192 { 1193 ill_t *ill; 1194 boolean_t in_ipsq; 1195 1196 ill = ill_lookup_on_ifindex(ifindex, isv6, NULL, NULL, NULL, NULL, 1197 ipst); 1198 if (ill != NULL) { 1199 if (!ill_waiter_inc(ill)) { 1200 ill_refrele(ill); 1201 return (NULL); 1202 } 1203 ill_refrele(ill); 1204 in_ipsq = ipsq_enter(ill, B_FALSE, NEW_OP); 1205 ill_waiter_dcr(ill); 1206 if (!in_ipsq) 1207 ill = NULL; 1208 } 1209 return (ill); 1210 } 1211 1212 int 1213 ip_join_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1214 { 1215 ill_t *ill; 1216 int ret; 1217 1218 if ((ill = ipsq_enter_byifindex(ifindex, isv6, ipst)) == NULL) 1219 return (ENODEV); 1220 if (isv6) { 1221 ret = ip_addmulti_v6(&ipv6_all_zeros, ill, ifindex, 1222 ill->ill_zoneid, ILGSTAT_NONE, MODE_IS_EXCLUDE, NULL); 1223 } else { 1224 ret = ip_addmulti(INADDR_ANY, ill->ill_ipif, ILGSTAT_NONE, 1225 MODE_IS_EXCLUDE, NULL); 1226 } 1227 ill->ill_ipallmulti_cnt++; 1228 ipsq_exit(ill->ill_phyint->phyint_ipsq); 1229 return (ret); 1230 } 1231 1232 int 1233 ip_leave_allmulti(uint_t ifindex, boolean_t isv6, ip_stack_t *ipst) 1234 { 1235 ill_t *ill; 1236 1237 if ((ill = ipsq_enter_byifindex(ifindex, isv6, ipst)) == NULL) 1238 return (ENODEV); 1239 ASSERT(ill->ill_ipallmulti_cnt != 0); 1240 if (isv6) { 1241 (void) ip_delmulti_v6(&ipv6_all_zeros, ill, ifindex, 1242 ill->ill_zoneid, B_TRUE, B_TRUE); 1243 } else { 1244 (void) ip_delmulti(INADDR_ANY, ill->ill_ipif, B_TRUE, B_TRUE); 1245 } 1246 ill->ill_ipallmulti_cnt--; 1247 ipsq_exit(ill->ill_phyint->phyint_ipsq); 1248 return (0); 1249 } 1250 1251 /* 1252 * Delete the allmulti memberships that were added as part of 1253 * ip_join_allmulti(). 1254 */ 1255 void 1256 ip_purge_allmulti(ill_t *ill) 1257 { 1258 ASSERT(IAM_WRITER_ILL(ill)); 1259 1260 for (; ill->ill_ipallmulti_cnt > 0; ill->ill_ipallmulti_cnt--) { 1261 if (ill->ill_isv6) { 1262 (void) ip_delmulti_v6(&ipv6_all_zeros, ill, 1263 ill->ill_phyint->phyint_ifindex, ill->ill_zoneid, 1264 B_TRUE, B_TRUE); 1265 } else { 1266 (void) ip_delmulti(INADDR_ANY, ill->ill_ipif, B_TRUE, 1267 B_TRUE); 1268 } 1269 } 1270 } 1271 1272 /* 1273 * Copy mp_orig and pass it in as a local message. 1274 */ 1275 void 1276 ip_multicast_loopback(queue_t *q, ill_t *ill, mblk_t *mp_orig, int fanout_flags, 1277 zoneid_t zoneid) 1278 { 1279 mblk_t *mp; 1280 mblk_t *ipsec_mp; 1281 ipha_t *iph; 1282 ip_stack_t *ipst = ill->ill_ipst; 1283 1284 if (DB_TYPE(mp_orig) == M_DATA && 1285 ((ipha_t *)mp_orig->b_rptr)->ipha_protocol == IPPROTO_UDP) { 1286 uint_t hdrsz; 1287 1288 hdrsz = IPH_HDR_LENGTH((ipha_t *)mp_orig->b_rptr) + 1289 sizeof (udpha_t); 1290 ASSERT(MBLKL(mp_orig) >= hdrsz); 1291 1292 if (((mp = allocb(hdrsz, BPRI_MED)) != NULL) && 1293 (mp_orig = dupmsg(mp_orig)) != NULL) { 1294 bcopy(mp_orig->b_rptr, mp->b_rptr, hdrsz); 1295 mp->b_wptr += hdrsz; 1296 mp->b_cont = mp_orig; 1297 mp_orig->b_rptr += hdrsz; 1298 if (is_system_labeled() && DB_CRED(mp_orig) != NULL) 1299 mblk_setcred(mp, DB_CRED(mp_orig)); 1300 if (MBLKL(mp_orig) == 0) { 1301 mp->b_cont = mp_orig->b_cont; 1302 mp_orig->b_cont = NULL; 1303 freeb(mp_orig); 1304 } 1305 } else if (mp != NULL) { 1306 freeb(mp); 1307 mp = NULL; 1308 } 1309 } else { 1310 mp = ip_copymsg(mp_orig); /* No refcnt on ipsec_out netstack */ 1311 } 1312 1313 if (mp == NULL) 1314 return; 1315 if (DB_TYPE(mp) == M_CTL) { 1316 ipsec_mp = mp; 1317 mp = mp->b_cont; 1318 } else { 1319 ipsec_mp = mp; 1320 } 1321 1322 iph = (ipha_t *)mp->b_rptr; 1323 1324 /* 1325 * DTrace this as ip:::send. A blocked packet will fire the send 1326 * probe, but not the receive probe. 1327 */ 1328 DTRACE_IP7(send, mblk_t *, ipsec_mp, conn_t *, NULL, void_ip_t *, iph, 1329 __dtrace_ipsr_ill_t *, ill, ipha_t *, iph, ip6_t *, NULL, int, 1); 1330 1331 DTRACE_PROBE4(ip4__loopback__out__start, 1332 ill_t *, NULL, ill_t *, ill, 1333 ipha_t *, iph, mblk_t *, ipsec_mp); 1334 1335 FW_HOOKS(ipst->ips_ip4_loopback_out_event, 1336 ipst->ips_ipv4firewall_loopback_out, 1337 NULL, ill, iph, ipsec_mp, mp, HPE_MULTICAST, ipst); 1338 1339 DTRACE_PROBE1(ip4__loopback__out__end, mblk_t *, ipsec_mp); 1340 1341 if (ipsec_mp != NULL) 1342 ip_wput_local(q, ill, iph, ipsec_mp, NULL, 1343 fanout_flags, zoneid); 1344 } 1345 1346 static area_t ip_aresq_template = { 1347 AR_ENTRY_SQUERY, /* cmd */ 1348 sizeof (area_t)+IP_ADDR_LEN, /* name offset */ 1349 sizeof (area_t), /* name len (filled by ill_arp_alloc) */ 1350 IP_ARP_PROTO_TYPE, /* protocol, from arps perspective */ 1351 sizeof (area_t), /* proto addr offset */ 1352 IP_ADDR_LEN, /* proto addr_length */ 1353 0, /* proto mask offset */ 1354 /* Rest is initialized when used */ 1355 0, /* flags */ 1356 0, /* hw addr offset */ 1357 0, /* hw addr length */ 1358 }; 1359 1360 static mblk_t * 1361 ill_create_squery(ill_t *ill, ipaddr_t ipaddr, uint32_t addrlen, 1362 uint32_t addroff, mblk_t *mp_tail) 1363 { 1364 mblk_t *mp; 1365 area_t *area; 1366 1367 mp = ill_arp_alloc(ill, (uchar_t *)&ip_aresq_template, 1368 (caddr_t)&ipaddr); 1369 if (!mp) { 1370 freemsg(mp_tail); 1371 return (NULL); 1372 } 1373 area = (area_t *)mp->b_rptr; 1374 area->area_hw_addr_length = addrlen; 1375 area->area_hw_addr_offset = mp->b_wptr - mp->b_rptr + addroff; 1376 /* 1377 * NOTE! 1378 * 1379 * The area_hw_addr_offset, as can be seen, does not hold the 1380 * actual hardware address offset. Rather, it holds the offset 1381 * to the hw addr in the dl_xxx_req in mp_tail, modified by 1382 * adding (mp->b_wptr - mp->b_rptr). This allows the function 1383 * mi_offset_paramc() to find the hardware address in the 1384 * *second* mblk (dl_xxx_req), not this mblk. 1385 * 1386 * Using mi_offset_paramc() is thus the *only* way to access 1387 * the dl_xxx_hw address. 1388 * 1389 * The squery hw address should *not* be accessed. 1390 * 1391 * See ar_entry_squery() in arp.c for an example of how all this works. 1392 */ 1393 1394 mp->b_cont = mp_tail; 1395 return (mp); 1396 } 1397 1398 /* 1399 * Create a DLPI message; for DL_{ENAB,DISAB}MULTI_REQ, room is left for 1400 * the hardware address. 1401 */ 1402 static mblk_t * 1403 ill_create_dl(ill_t *ill, uint32_t dl_primitive, uint32_t length, 1404 uint32_t *addr_lenp, uint32_t *addr_offp) 1405 { 1406 mblk_t *mp; 1407 uint32_t hw_addr_length; 1408 char *cp; 1409 uint32_t offset; 1410 uint32_t size; 1411 1412 *addr_lenp = *addr_offp = 0; 1413 1414 hw_addr_length = ill->ill_phys_addr_length; 1415 if (!hw_addr_length) { 1416 ip0dbg(("ip_create_dl: hw addr length = 0\n")); 1417 return (NULL); 1418 } 1419 1420 size = length; 1421 switch (dl_primitive) { 1422 case DL_ENABMULTI_REQ: 1423 case DL_DISABMULTI_REQ: 1424 size += hw_addr_length; 1425 break; 1426 case DL_PROMISCON_REQ: 1427 case DL_PROMISCOFF_REQ: 1428 break; 1429 default: 1430 return (NULL); 1431 } 1432 mp = allocb(size, BPRI_HI); 1433 if (!mp) 1434 return (NULL); 1435 mp->b_wptr += size; 1436 mp->b_datap->db_type = M_PROTO; 1437 1438 cp = (char *)mp->b_rptr; 1439 offset = length; 1440 1441 switch (dl_primitive) { 1442 case DL_ENABMULTI_REQ: { 1443 dl_enabmulti_req_t *dl = (dl_enabmulti_req_t *)cp; 1444 1445 dl->dl_primitive = dl_primitive; 1446 dl->dl_addr_offset = offset; 1447 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1448 *addr_offp = offset; 1449 break; 1450 } 1451 case DL_DISABMULTI_REQ: { 1452 dl_disabmulti_req_t *dl = (dl_disabmulti_req_t *)cp; 1453 1454 dl->dl_primitive = dl_primitive; 1455 dl->dl_addr_offset = offset; 1456 *addr_lenp = dl->dl_addr_length = hw_addr_length; 1457 *addr_offp = offset; 1458 break; 1459 } 1460 case DL_PROMISCON_REQ: 1461 case DL_PROMISCOFF_REQ: { 1462 dl_promiscon_req_t *dl = (dl_promiscon_req_t *)cp; 1463 1464 dl->dl_primitive = dl_primitive; 1465 dl->dl_level = DL_PROMISC_MULTI; 1466 break; 1467 } 1468 } 1469 ip1dbg(("ill_create_dl: addr_len %d, addr_off %d\n", 1470 *addr_lenp, *addr_offp)); 1471 return (mp); 1472 } 1473 1474 /* 1475 * Writer processing for ip_wput_ctl(): send the DL_{ENAB,DISAB}MULTI_REQ 1476 * messages that had been delayed until we'd heard back from ARP. One catch: 1477 * we need to ensure that no one else becomes writer on the IPSQ before we've 1478 * received the replies, or they'll incorrectly process our replies as part of 1479 * their unrelated IPSQ operation. To do this, we start a new IPSQ operation, 1480 * which will complete when we process the reply in ip_rput_dlpi_writer(). 1481 */ 1482 /* ARGSUSED */ 1483 static void 1484 ip_wput_ctl_writer(ipsq_t *ipsq, queue_t *q, mblk_t *mp, void *arg) 1485 { 1486 ill_t *ill = q->q_ptr; 1487 t_uscalar_t prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive; 1488 1489 ASSERT(IAM_WRITER_ILL(ill)); 1490 ASSERT(prim == DL_ENABMULTI_REQ || prim == DL_DISABMULTI_REQ); 1491 ip1dbg(("ip_wput_ctl_writer: %s\n", dl_primstr(prim))); 1492 1493 if (prim == DL_ENABMULTI_REQ) { 1494 /* Track the state if this is the first enabmulti */ 1495 if (ill->ill_dlpi_multicast_state == IDS_UNKNOWN) 1496 ill->ill_dlpi_multicast_state = IDS_INPROGRESS; 1497 } 1498 1499 ipsq_current_start(ipsq, ill->ill_ipif, 0); 1500 ill_dlpi_send(ill, mp); 1501 } 1502 1503 void 1504 ip_wput_ctl(queue_t *q, mblk_t *mp) 1505 { 1506 ill_t *ill = q->q_ptr; 1507 mblk_t *dlmp = mp->b_cont; 1508 area_t *area = (area_t *)mp->b_rptr; 1509 t_uscalar_t prim; 1510 1511 /* Check that we have an AR_ENTRY_SQUERY with a tacked on mblk */ 1512 if (MBLKL(mp) < sizeof (area_t) || area->area_cmd != AR_ENTRY_SQUERY || 1513 dlmp == NULL) { 1514 putnext(q, mp); 1515 return; 1516 } 1517 1518 /* Check that the tacked on mblk is a DL_{DISAB,ENAB}MULTI_REQ */ 1519 prim = ((union DL_primitives *)dlmp->b_rptr)->dl_primitive; 1520 if (prim != DL_DISABMULTI_REQ && prim != DL_ENABMULTI_REQ) { 1521 putnext(q, mp); 1522 return; 1523 } 1524 freeb(mp); 1525 1526 /* See comments above ip_wput_ctl_writer() for details */ 1527 ill_refhold(ill); 1528 qwriter_ip(ill, ill->ill_wq, dlmp, ip_wput_ctl_writer, NEW_OP, B_FALSE); 1529 } 1530 1531 /* 1532 * Rejoin any groups which have been explicitly joined by the application (we 1533 * left all explicitly joined groups as part of ill_leave_multicast() prior to 1534 * bringing the interface down). Note that because groups can be joined and 1535 * left while an interface is down, this may not be the same set of groups 1536 * that we left in ill_leave_multicast(). 1537 */ 1538 void 1539 ill_recover_multicast(ill_t *ill) 1540 { 1541 ilm_t *ilm; 1542 char addrbuf[INET6_ADDRSTRLEN]; 1543 1544 ASSERT(IAM_WRITER_ILL(ill)); 1545 1546 ill->ill_need_recover_multicast = 0; 1547 1548 ILM_WALKER_HOLD(ill); 1549 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1550 /* 1551 * Check how many ipif's that have members in this group - 1552 * if more then one we make sure that this entry is first 1553 * in the list. 1554 */ 1555 if (ilm_numentries_v6(ill, &ilm->ilm_v6addr) > 1 && 1556 ilm_lookup_ill_v6(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) 1557 continue; 1558 ip1dbg(("ill_recover_multicast: %s\n", 1559 inet_ntop(AF_INET6, &ilm->ilm_v6addr, addrbuf, 1560 sizeof (addrbuf)))); 1561 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1562 if (ill->ill_group == NULL) { 1563 (void) ill_join_allmulti(ill); 1564 } else { 1565 /* 1566 * We don't want to join on this ill, 1567 * if somebody else in the group has 1568 * already been nominated. 1569 */ 1570 (void) ill_nominate_mcast_rcv(ill->ill_group); 1571 } 1572 } else { 1573 (void) ip_ll_addmulti_v6(ill->ill_ipif, 1574 &ilm->ilm_v6addr); 1575 } 1576 } 1577 ILM_WALKER_RELE(ill); 1578 } 1579 1580 /* 1581 * The opposite of ill_recover_multicast() -- leaves all multicast groups 1582 * that were explicitly joined. Note that both these functions could be 1583 * disposed of if we enhanced ARP to allow us to handle DL_DISABMULTI_REQ 1584 * and DL_ENABMULTI_REQ messages when an interface is down. 1585 */ 1586 void 1587 ill_leave_multicast(ill_t *ill) 1588 { 1589 ilm_t *ilm; 1590 char addrbuf[INET6_ADDRSTRLEN]; 1591 1592 ASSERT(IAM_WRITER_ILL(ill)); 1593 1594 ill->ill_need_recover_multicast = 1; 1595 1596 ILM_WALKER_HOLD(ill); 1597 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1598 /* 1599 * Check how many ipif's that have members in this group - 1600 * if more then one we make sure that this entry is first 1601 * in the list. 1602 */ 1603 if (ilm_numentries_v6(ill, &ilm->ilm_v6addr) > 1 && 1604 ilm_lookup_ill_v6(ill, &ilm->ilm_v6addr, ALL_ZONES) != ilm) 1605 continue; 1606 ip1dbg(("ill_leave_multicast: %s\n", 1607 inet_ntop(AF_INET6, &ilm->ilm_v6addr, addrbuf, 1608 sizeof (addrbuf)))); 1609 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr)) { 1610 ill_leave_allmulti(ill); 1611 /* 1612 * If we were part of an IPMP group, then 1613 * ill_handoff_responsibility() has already 1614 * nominated a new member (so we don't). 1615 */ 1616 ASSERT(ill->ill_group == NULL); 1617 } else { 1618 (void) ip_ll_delmulti_v6(ill->ill_ipif, 1619 &ilm->ilm_v6addr); 1620 } 1621 } 1622 ILM_WALKER_RELE(ill); 1623 } 1624 1625 /* Find an ilm for matching the ill */ 1626 ilm_t * 1627 ilm_lookup_ill(ill_t *ill, ipaddr_t group, zoneid_t zoneid) 1628 { 1629 in6_addr_t v6group; 1630 1631 ASSERT(ill->ill_ilm_walker_cnt != 0 || MUTEX_HELD(&ill->ill_lock)); 1632 /* 1633 * INADDR_ANY is represented as the IPv6 unspecifed addr. 1634 */ 1635 if (group == INADDR_ANY) 1636 v6group = ipv6_all_zeros; 1637 else 1638 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1639 1640 return (ilm_lookup_ill_v6(ill, &v6group, zoneid)); 1641 } 1642 1643 /* 1644 * Find an ilm for matching the ill. All the ilm lookup functions 1645 * ignore ILM_DELETED ilms. These have been logically deleted, and 1646 * igmp and linklayer disable multicast have been done. Only mi_free 1647 * yet to be done. Still there in the list due to ilm_walkers. The 1648 * last walker will release it. 1649 */ 1650 ilm_t * 1651 ilm_lookup_ill_v6(ill_t *ill, const in6_addr_t *v6group, zoneid_t zoneid) 1652 { 1653 ilm_t *ilm; 1654 1655 ASSERT(ill->ill_ilm_walker_cnt != 0 || MUTEX_HELD(&ill->ill_lock)); 1656 1657 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1658 if (ilm->ilm_flags & ILM_DELETED) 1659 continue; 1660 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1661 (zoneid == ALL_ZONES || zoneid == ilm->ilm_zoneid)) 1662 return (ilm); 1663 } 1664 return (NULL); 1665 } 1666 1667 ilm_t * 1668 ilm_lookup_ill_index_v6(ill_t *ill, const in6_addr_t *v6group, int index, 1669 zoneid_t zoneid) 1670 { 1671 ilm_t *ilm; 1672 1673 ASSERT(ill->ill_ilm_walker_cnt != 0 || MUTEX_HELD(&ill->ill_lock)); 1674 1675 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 1676 if (ilm->ilm_flags & ILM_DELETED) 1677 continue; 1678 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group) && 1679 (zoneid == ALL_ZONES || zoneid == ilm->ilm_zoneid) && 1680 ilm->ilm_orig_ifindex == index) { 1681 return (ilm); 1682 } 1683 } 1684 return (NULL); 1685 } 1686 1687 1688 /* 1689 * Found an ilm for the ipif. Only needed for IPv4 which does 1690 * ipif specific socket options. 1691 */ 1692 ilm_t * 1693 ilm_lookup_ipif(ipif_t *ipif, ipaddr_t group) 1694 { 1695 ill_t *ill = ipif->ipif_ill; 1696 ilm_t *ilm; 1697 in6_addr_t v6group; 1698 1699 ASSERT(ill->ill_ilm_walker_cnt != 0 || MUTEX_HELD(&ill->ill_lock)); 1700 /* 1701 * INADDR_ANY is represented as the IPv6 unspecifed addr. 1702 */ 1703 if (group == INADDR_ANY) 1704 v6group = ipv6_all_zeros; 1705 else 1706 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 1707 1708 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1709 if (ilm->ilm_flags & ILM_DELETED) 1710 continue; 1711 if (ilm->ilm_ipif == ipif && 1712 IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, &v6group)) 1713 return (ilm); 1714 } 1715 return (NULL); 1716 } 1717 1718 /* 1719 * How many members on this ill? 1720 */ 1721 int 1722 ilm_numentries_v6(ill_t *ill, const in6_addr_t *v6group) 1723 { 1724 ilm_t *ilm; 1725 int i = 0; 1726 1727 mutex_enter(&ill->ill_lock); 1728 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 1729 if (ilm->ilm_flags & ILM_DELETED) 1730 continue; 1731 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group)) { 1732 i++; 1733 } 1734 } 1735 mutex_exit(&ill->ill_lock); 1736 return (i); 1737 } 1738 1739 /* Caller guarantees that the group is not already on the list */ 1740 static ilm_t * 1741 ilm_add_v6(ipif_t *ipif, const in6_addr_t *v6group, ilg_stat_t ilgstat, 1742 mcast_record_t ilg_fmode, slist_t *ilg_flist, int orig_ifindex, 1743 zoneid_t zoneid) 1744 { 1745 ill_t *ill = ipif->ipif_ill; 1746 ilm_t *ilm; 1747 ilm_t *ilm_cur; 1748 ilm_t **ilm_ptpn; 1749 1750 ASSERT(IAM_WRITER_IPIF(ipif)); 1751 1752 ilm = GETSTRUCT(ilm_t, 1); 1753 if (ilm == NULL) 1754 return (NULL); 1755 if (ilgstat != ILGSTAT_NONE && !SLIST_IS_EMPTY(ilg_flist)) { 1756 ilm->ilm_filter = l_alloc(); 1757 if (ilm->ilm_filter == NULL) { 1758 mi_free(ilm); 1759 return (NULL); 1760 } 1761 } 1762 ilm->ilm_v6addr = *v6group; 1763 ilm->ilm_refcnt = 1; 1764 ilm->ilm_zoneid = zoneid; 1765 ilm->ilm_timer = INFINITY; 1766 ilm->ilm_rtx.rtx_timer = INFINITY; 1767 1768 /* 1769 * IPv4 Multicast groups are joined using ipif. 1770 * IPv6 Multicast groups are joined using ill. 1771 */ 1772 if (ill->ill_isv6) { 1773 ilm->ilm_ill = ill; 1774 ilm->ilm_ipif = NULL; 1775 DTRACE_PROBE3(ill__incr__cnt, (ill_t *), ill, 1776 (char *), "ilm", (void *), ilm); 1777 ill->ill_ilm_cnt++; 1778 } else { 1779 ASSERT(ilm->ilm_zoneid == ipif->ipif_zoneid); 1780 ilm->ilm_ipif = ipif; 1781 ilm->ilm_ill = NULL; 1782 DTRACE_PROBE3(ipif__incr__cnt, (ipif_t *), ipif, 1783 (char *), "ilm", (void *), ilm); 1784 ipif->ipif_ilm_cnt++; 1785 } 1786 ASSERT(ill->ill_ipst); 1787 ilm->ilm_ipst = ill->ill_ipst; /* No netstack_hold */ 1788 1789 /* 1790 * After this if ilm moves to a new ill, we don't change 1791 * the ilm_orig_ifindex. Thus, if ill_index != ilm_orig_ifindex, 1792 * it has been moved. Indexes don't match even when the application 1793 * wants to join on a FAILED/INACTIVE interface because we choose 1794 * a new interface to join in. This is considered as an implicit 1795 * move. 1796 */ 1797 ilm->ilm_orig_ifindex = orig_ifindex; 1798 1799 ASSERT(!(ipif->ipif_state_flags & IPIF_CONDEMNED)); 1800 ASSERT(!(ill->ill_state_flags & ILL_CONDEMNED)); 1801 1802 /* 1803 * Grab lock to give consistent view to readers 1804 */ 1805 mutex_enter(&ill->ill_lock); 1806 /* 1807 * All ilms in the same zone are contiguous in the ill_ilm list. 1808 * The loops in ip_proto_input() and ip_wput_local() use this to avoid 1809 * sending duplicates up when two applications in the same zone join the 1810 * same group on different logical interfaces. 1811 */ 1812 ilm_cur = ill->ill_ilm; 1813 ilm_ptpn = &ill->ill_ilm; 1814 while (ilm_cur != NULL && ilm_cur->ilm_zoneid != ilm->ilm_zoneid) { 1815 ilm_ptpn = &ilm_cur->ilm_next; 1816 ilm_cur = ilm_cur->ilm_next; 1817 } 1818 ilm->ilm_next = ilm_cur; 1819 *ilm_ptpn = ilm; 1820 1821 /* 1822 * If we have an associated ilg, use its filter state; if not, 1823 * default to (EXCLUDE, NULL) and set no_ilg_cnt to track this. 1824 */ 1825 if (ilgstat != ILGSTAT_NONE) { 1826 if (!SLIST_IS_EMPTY(ilg_flist)) 1827 l_copy(ilg_flist, ilm->ilm_filter); 1828 ilm->ilm_fmode = ilg_fmode; 1829 } else { 1830 ilm->ilm_no_ilg_cnt = 1; 1831 ilm->ilm_fmode = MODE_IS_EXCLUDE; 1832 } 1833 1834 mutex_exit(&ill->ill_lock); 1835 return (ilm); 1836 } 1837 1838 void 1839 ilm_inactive(ilm_t *ilm) 1840 { 1841 FREE_SLIST(ilm->ilm_filter); 1842 FREE_SLIST(ilm->ilm_pendsrcs); 1843 FREE_SLIST(ilm->ilm_rtx.rtx_allow); 1844 FREE_SLIST(ilm->ilm_rtx.rtx_block); 1845 ilm->ilm_ipst = NULL; 1846 mi_free((char *)ilm); 1847 } 1848 1849 void 1850 ilm_walker_cleanup(ill_t *ill) 1851 { 1852 ilm_t **ilmp; 1853 ilm_t *ilm; 1854 boolean_t need_wakeup = B_FALSE; 1855 1856 ASSERT(MUTEX_HELD(&ill->ill_lock)); 1857 ASSERT(ill->ill_ilm_walker_cnt == 0); 1858 1859 ilmp = &ill->ill_ilm; 1860 while (*ilmp != NULL) { 1861 if ((*ilmp)->ilm_flags & ILM_DELETED) { 1862 ilm = *ilmp; 1863 *ilmp = ilm->ilm_next; 1864 /* 1865 * check if there are any pending FREE or unplumb 1866 * operations that need to be restarted. 1867 */ 1868 if (ilm->ilm_ipif != NULL) { 1869 /* 1870 * IPv4 ilms hold a ref on the ipif. 1871 */ 1872 DTRACE_PROBE3(ipif__decr__cnt, 1873 (ipif_t *), ilm->ilm_ipif, 1874 (char *), "ilm", (void *), ilm); 1875 ilm->ilm_ipif->ipif_ilm_cnt--; 1876 if (IPIF_FREE_OK(ilm->ilm_ipif)) 1877 need_wakeup = B_TRUE; 1878 } else { 1879 /* 1880 * IPv6 ilms hold a ref on the ill. 1881 */ 1882 ASSERT(ilm->ilm_ill == ill); 1883 DTRACE_PROBE3(ill__decr__cnt, 1884 (ill_t *), ill, 1885 (char *), "ilm", (void *), ilm); 1886 ASSERT(ill->ill_ilm_cnt > 0); 1887 ill->ill_ilm_cnt--; 1888 if (ILL_FREE_OK(ill)) 1889 need_wakeup = B_TRUE; 1890 } 1891 ilm_inactive(ilm); /* frees ilm */ 1892 } else { 1893 ilmp = &(*ilmp)->ilm_next; 1894 } 1895 } 1896 ill->ill_ilm_cleanup_reqd = 0; 1897 if (need_wakeup) 1898 ipif_ill_refrele_tail(ill); 1899 else 1900 mutex_exit(&ill->ill_lock); 1901 } 1902 1903 /* 1904 * Unlink ilm and free it. 1905 */ 1906 static void 1907 ilm_delete(ilm_t *ilm) 1908 { 1909 ill_t *ill; 1910 ilm_t **ilmp; 1911 boolean_t need_wakeup; 1912 1913 1914 if (ilm->ilm_ipif != NULL) { 1915 ASSERT(IAM_WRITER_IPIF(ilm->ilm_ipif)); 1916 ASSERT(ilm->ilm_ill == NULL); 1917 ill = ilm->ilm_ipif->ipif_ill; 1918 ASSERT(!ill->ill_isv6); 1919 } else { 1920 ASSERT(IAM_WRITER_ILL(ilm->ilm_ill)); 1921 ASSERT(ilm->ilm_ipif == NULL); 1922 ill = ilm->ilm_ill; 1923 ASSERT(ill->ill_isv6); 1924 } 1925 /* 1926 * Delete under lock protection so that readers don't stumble 1927 * on bad ilm_next 1928 */ 1929 mutex_enter(&ill->ill_lock); 1930 if (ill->ill_ilm_walker_cnt != 0) { 1931 ilm->ilm_flags |= ILM_DELETED; 1932 ill->ill_ilm_cleanup_reqd = 1; 1933 mutex_exit(&ill->ill_lock); 1934 return; 1935 } 1936 1937 for (ilmp = &ill->ill_ilm; *ilmp != ilm; ilmp = &(*ilmp)->ilm_next) 1938 ; 1939 *ilmp = ilm->ilm_next; 1940 1941 /* 1942 * if we are the last reference to the ipif (for IPv4 ilms) 1943 * or the ill (for IPv6 ilms), we may need to wakeup any 1944 * pending FREE or unplumb operations. 1945 */ 1946 need_wakeup = B_FALSE; 1947 if (ilm->ilm_ipif != NULL) { 1948 DTRACE_PROBE3(ipif__decr__cnt, (ipif_t *), ilm->ilm_ipif, 1949 (char *), "ilm", (void *), ilm); 1950 ilm->ilm_ipif->ipif_ilm_cnt--; 1951 if (IPIF_FREE_OK(ilm->ilm_ipif)) 1952 need_wakeup = B_TRUE; 1953 } else { 1954 DTRACE_PROBE3(ill__decr__cnt, (ill_t *), ill, 1955 (char *), "ilm", (void *), ilm); 1956 ASSERT(ill->ill_ilm_cnt > 0); 1957 ill->ill_ilm_cnt--; 1958 if (ILL_FREE_OK(ill)) 1959 need_wakeup = B_TRUE; 1960 } 1961 1962 ilm_inactive(ilm); /* frees this ilm */ 1963 1964 if (need_wakeup) { 1965 /* drops ill lock */ 1966 ipif_ill_refrele_tail(ill); 1967 } else { 1968 mutex_exit(&ill->ill_lock); 1969 } 1970 } 1971 1972 1973 /* 1974 * Looks up the appropriate ipif given a v4 multicast group and interface 1975 * address. On success, returns 0, with *ipifpp pointing to the found 1976 * struct. On failure, returns an errno and *ipifpp is NULL. 1977 */ 1978 int 1979 ip_opt_check(conn_t *connp, ipaddr_t group, ipaddr_t src, ipaddr_t ifaddr, 1980 uint_t *ifindexp, mblk_t *first_mp, ipsq_func_t func, ipif_t **ipifpp) 1981 { 1982 ipif_t *ipif; 1983 int err = 0; 1984 zoneid_t zoneid; 1985 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 1986 1987 if (!CLASSD(group) || CLASSD(src)) { 1988 return (EINVAL); 1989 } 1990 *ipifpp = NULL; 1991 1992 zoneid = IPCL_ZONEID(connp); 1993 1994 ASSERT(!(ifaddr != INADDR_ANY && ifindexp != NULL && *ifindexp != 0)); 1995 if (ifaddr != INADDR_ANY) { 1996 ipif = ipif_lookup_addr(ifaddr, NULL, zoneid, 1997 CONNP_TO_WQ(connp), first_mp, func, &err, ipst); 1998 if (err != 0 && err != EINPROGRESS) 1999 err = EADDRNOTAVAIL; 2000 } else if (ifindexp != NULL && *ifindexp != 0) { 2001 ipif = ipif_lookup_on_ifindex(*ifindexp, B_FALSE, zoneid, 2002 CONNP_TO_WQ(connp), first_mp, func, &err, ipst); 2003 } else { 2004 ipif = ipif_lookup_group(group, zoneid, ipst); 2005 if (ipif == NULL) 2006 return (EADDRNOTAVAIL); 2007 } 2008 if (ipif == NULL) 2009 return (err); 2010 2011 *ipifpp = ipif; 2012 return (0); 2013 } 2014 2015 /* 2016 * Looks up the appropriate ill (or ipif if v4mapped) given an interface 2017 * index and IPv6 multicast group. On success, returns 0, with *illpp (or 2018 * *ipifpp if v4mapped) pointing to the found struct. On failure, returns 2019 * an errno and *illpp and *ipifpp are undefined. 2020 */ 2021 int 2022 ip_opt_check_v6(conn_t *connp, const in6_addr_t *v6group, ipaddr_t *v4group, 2023 const in6_addr_t *v6src, ipaddr_t *v4src, boolean_t *isv6, int ifindex, 2024 mblk_t *first_mp, ipsq_func_t func, ill_t **illpp, ipif_t **ipifpp) 2025 { 2026 boolean_t src_unspec; 2027 ill_t *ill = NULL; 2028 ipif_t *ipif = NULL; 2029 int err; 2030 zoneid_t zoneid = connp->conn_zoneid; 2031 queue_t *wq = CONNP_TO_WQ(connp); 2032 ip_stack_t *ipst = connp->conn_netstack->netstack_ip; 2033 2034 src_unspec = IN6_IS_ADDR_UNSPECIFIED(v6src); 2035 2036 if (IN6_IS_ADDR_V4MAPPED(v6group)) { 2037 if (!IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 2038 return (EINVAL); 2039 IN6_V4MAPPED_TO_IPADDR(v6group, *v4group); 2040 if (src_unspec) { 2041 *v4src = INADDR_ANY; 2042 } else { 2043 IN6_V4MAPPED_TO_IPADDR(v6src, *v4src); 2044 } 2045 if (!CLASSD(*v4group) || CLASSD(*v4src)) 2046 return (EINVAL); 2047 *ipifpp = NULL; 2048 *isv6 = B_FALSE; 2049 } else { 2050 if (IN6_IS_ADDR_V4MAPPED(v6src) && !src_unspec) 2051 return (EINVAL); 2052 if (!IN6_IS_ADDR_MULTICAST(v6group) || 2053 IN6_IS_ADDR_MULTICAST(v6src)) { 2054 return (EINVAL); 2055 } 2056 *illpp = NULL; 2057 *isv6 = B_TRUE; 2058 } 2059 2060 if (ifindex == 0) { 2061 if (*isv6) 2062 ill = ill_lookup_group_v6(v6group, zoneid, ipst); 2063 else 2064 ipif = ipif_lookup_group(*v4group, zoneid, ipst); 2065 if (ill == NULL && ipif == NULL) 2066 return (EADDRNOTAVAIL); 2067 } else { 2068 if (*isv6) { 2069 ill = ill_lookup_on_ifindex(ifindex, B_TRUE, 2070 wq, first_mp, func, &err, ipst); 2071 if (ill != NULL && 2072 !ipif_lookup_zoneid(ill, zoneid, 0, NULL)) { 2073 ill_refrele(ill); 2074 ill = NULL; 2075 err = EADDRNOTAVAIL; 2076 } 2077 } else { 2078 ipif = ipif_lookup_on_ifindex(ifindex, B_FALSE, 2079 zoneid, wq, first_mp, func, &err, ipst); 2080 } 2081 if (ill == NULL && ipif == NULL) 2082 return (err); 2083 } 2084 2085 *ipifpp = ipif; 2086 *illpp = ill; 2087 return (0); 2088 } 2089 2090 static int 2091 ip_get_srcfilter(conn_t *connp, struct group_filter *gf, 2092 struct ip_msfilter *imsf, ipaddr_t grp, ipif_t *ipif, boolean_t isv4mapped) 2093 { 2094 ilg_t *ilg; 2095 int i, numsrc, fmode, outsrcs; 2096 struct sockaddr_in *sin; 2097 struct sockaddr_in6 *sin6; 2098 struct in_addr *addrp; 2099 slist_t *fp; 2100 boolean_t is_v4only_api; 2101 2102 mutex_enter(&connp->conn_lock); 2103 2104 ilg = ilg_lookup_ipif(connp, grp, ipif); 2105 if (ilg == NULL) { 2106 mutex_exit(&connp->conn_lock); 2107 return (EADDRNOTAVAIL); 2108 } 2109 2110 if (gf == NULL) { 2111 ASSERT(imsf != NULL); 2112 ASSERT(!isv4mapped); 2113 is_v4only_api = B_TRUE; 2114 outsrcs = imsf->imsf_numsrc; 2115 } else { 2116 ASSERT(imsf == NULL); 2117 is_v4only_api = B_FALSE; 2118 outsrcs = gf->gf_numsrc; 2119 } 2120 2121 /* 2122 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 2123 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 2124 * So we need to translate here. 2125 */ 2126 fmode = (ilg->ilg_fmode == MODE_IS_INCLUDE) ? 2127 MCAST_INCLUDE : MCAST_EXCLUDE; 2128 if ((fp = ilg->ilg_filter) == NULL) { 2129 numsrc = 0; 2130 } else { 2131 for (i = 0; i < outsrcs; i++) { 2132 if (i == fp->sl_numsrc) 2133 break; 2134 if (isv4mapped) { 2135 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 2136 sin6->sin6_family = AF_INET6; 2137 sin6->sin6_addr = fp->sl_addr[i]; 2138 } else { 2139 if (is_v4only_api) { 2140 addrp = &imsf->imsf_slist[i]; 2141 } else { 2142 sin = (struct sockaddr_in *) 2143 &gf->gf_slist[i]; 2144 sin->sin_family = AF_INET; 2145 addrp = &sin->sin_addr; 2146 } 2147 IN6_V4MAPPED_TO_INADDR(&fp->sl_addr[i], addrp); 2148 } 2149 } 2150 numsrc = fp->sl_numsrc; 2151 } 2152 2153 if (is_v4only_api) { 2154 imsf->imsf_numsrc = numsrc; 2155 imsf->imsf_fmode = fmode; 2156 } else { 2157 gf->gf_numsrc = numsrc; 2158 gf->gf_fmode = fmode; 2159 } 2160 2161 mutex_exit(&connp->conn_lock); 2162 2163 return (0); 2164 } 2165 2166 static int 2167 ip_get_srcfilter_v6(conn_t *connp, struct group_filter *gf, 2168 const struct in6_addr *grp, ill_t *ill) 2169 { 2170 ilg_t *ilg; 2171 int i; 2172 struct sockaddr_storage *sl; 2173 struct sockaddr_in6 *sin6; 2174 slist_t *fp; 2175 2176 mutex_enter(&connp->conn_lock); 2177 2178 ilg = ilg_lookup_ill_v6(connp, grp, ill); 2179 if (ilg == NULL) { 2180 mutex_exit(&connp->conn_lock); 2181 return (EADDRNOTAVAIL); 2182 } 2183 2184 /* 2185 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 2186 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 2187 * So we need to translate here. 2188 */ 2189 gf->gf_fmode = (ilg->ilg_fmode == MODE_IS_INCLUDE) ? 2190 MCAST_INCLUDE : MCAST_EXCLUDE; 2191 if ((fp = ilg->ilg_filter) == NULL) { 2192 gf->gf_numsrc = 0; 2193 } else { 2194 for (i = 0, sl = gf->gf_slist; i < gf->gf_numsrc; i++, sl++) { 2195 if (i == fp->sl_numsrc) 2196 break; 2197 sin6 = (struct sockaddr_in6 *)sl; 2198 sin6->sin6_family = AF_INET6; 2199 sin6->sin6_addr = fp->sl_addr[i]; 2200 } 2201 gf->gf_numsrc = fp->sl_numsrc; 2202 } 2203 2204 mutex_exit(&connp->conn_lock); 2205 2206 return (0); 2207 } 2208 2209 static int 2210 ip_set_srcfilter(conn_t *connp, struct group_filter *gf, 2211 struct ip_msfilter *imsf, ipaddr_t grp, ipif_t *ipif, boolean_t isv4mapped) 2212 { 2213 ilg_t *ilg; 2214 int i, err, infmode, new_fmode; 2215 uint_t insrcs; 2216 struct sockaddr_in *sin; 2217 struct sockaddr_in6 *sin6; 2218 struct in_addr *addrp; 2219 slist_t *orig_filter = NULL; 2220 slist_t *new_filter = NULL; 2221 mcast_record_t orig_fmode; 2222 boolean_t leave_grp, is_v4only_api; 2223 ilg_stat_t ilgstat; 2224 2225 if (gf == NULL) { 2226 ASSERT(imsf != NULL); 2227 ASSERT(!isv4mapped); 2228 is_v4only_api = B_TRUE; 2229 insrcs = imsf->imsf_numsrc; 2230 infmode = imsf->imsf_fmode; 2231 } else { 2232 ASSERT(imsf == NULL); 2233 is_v4only_api = B_FALSE; 2234 insrcs = gf->gf_numsrc; 2235 infmode = gf->gf_fmode; 2236 } 2237 2238 /* Make sure we can handle the source list */ 2239 if (insrcs > MAX_FILTER_SIZE) 2240 return (ENOBUFS); 2241 2242 /* 2243 * setting the filter to (INCLUDE, NULL) is treated 2244 * as a request to leave the group. 2245 */ 2246 leave_grp = (infmode == MCAST_INCLUDE && insrcs == 0); 2247 2248 ASSERT(IAM_WRITER_IPIF(ipif)); 2249 2250 mutex_enter(&connp->conn_lock); 2251 2252 ilg = ilg_lookup_ipif(connp, grp, ipif); 2253 if (ilg == NULL) { 2254 /* 2255 * if the request was actually to leave, and we 2256 * didn't find an ilg, there's nothing to do. 2257 */ 2258 if (!leave_grp) 2259 ilg = conn_ilg_alloc(connp); 2260 if (leave_grp || ilg == NULL) { 2261 mutex_exit(&connp->conn_lock); 2262 return (leave_grp ? 0 : ENOMEM); 2263 } 2264 ilgstat = ILGSTAT_NEW; 2265 IN6_IPADDR_TO_V4MAPPED(grp, &ilg->ilg_v6group); 2266 ilg->ilg_ipif = ipif; 2267 ilg->ilg_ill = NULL; 2268 ilg->ilg_orig_ifindex = 0; 2269 } else if (leave_grp) { 2270 ilg_delete(connp, ilg, NULL); 2271 mutex_exit(&connp->conn_lock); 2272 (void) ip_delmulti(grp, ipif, B_FALSE, B_TRUE); 2273 return (0); 2274 } else { 2275 ilgstat = ILGSTAT_CHANGE; 2276 /* Preserve existing state in case ip_addmulti() fails */ 2277 orig_fmode = ilg->ilg_fmode; 2278 if (ilg->ilg_filter == NULL) { 2279 orig_filter = NULL; 2280 } else { 2281 orig_filter = l_alloc_copy(ilg->ilg_filter); 2282 if (orig_filter == NULL) { 2283 mutex_exit(&connp->conn_lock); 2284 return (ENOMEM); 2285 } 2286 } 2287 } 2288 2289 /* 2290 * Alloc buffer to copy new state into (see below) before 2291 * we make any changes, so we can bail if it fails. 2292 */ 2293 if ((new_filter = l_alloc()) == NULL) { 2294 mutex_exit(&connp->conn_lock); 2295 err = ENOMEM; 2296 goto free_and_exit; 2297 } 2298 2299 if (insrcs == 0) { 2300 CLEAR_SLIST(ilg->ilg_filter); 2301 } else { 2302 slist_t *fp; 2303 if (ilg->ilg_filter == NULL) { 2304 fp = l_alloc(); 2305 if (fp == NULL) { 2306 if (ilgstat == ILGSTAT_NEW) 2307 ilg_delete(connp, ilg, NULL); 2308 mutex_exit(&connp->conn_lock); 2309 err = ENOMEM; 2310 goto free_and_exit; 2311 } 2312 } else { 2313 fp = ilg->ilg_filter; 2314 } 2315 for (i = 0; i < insrcs; i++) { 2316 if (isv4mapped) { 2317 sin6 = (struct sockaddr_in6 *)&gf->gf_slist[i]; 2318 fp->sl_addr[i] = sin6->sin6_addr; 2319 } else { 2320 if (is_v4only_api) { 2321 addrp = &imsf->imsf_slist[i]; 2322 } else { 2323 sin = (struct sockaddr_in *) 2324 &gf->gf_slist[i]; 2325 addrp = &sin->sin_addr; 2326 } 2327 IN6_INADDR_TO_V4MAPPED(addrp, &fp->sl_addr[i]); 2328 } 2329 } 2330 fp->sl_numsrc = insrcs; 2331 ilg->ilg_filter = fp; 2332 } 2333 /* 2334 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 2335 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 2336 * So we need to translate here. 2337 */ 2338 ilg->ilg_fmode = (infmode == MCAST_INCLUDE) ? 2339 MODE_IS_INCLUDE : MODE_IS_EXCLUDE; 2340 2341 /* 2342 * Save copy of ilg's filter state to pass to other functions, 2343 * so we can release conn_lock now. 2344 */ 2345 new_fmode = ilg->ilg_fmode; 2346 l_copy(ilg->ilg_filter, new_filter); 2347 2348 mutex_exit(&connp->conn_lock); 2349 2350 err = ip_addmulti(grp, ipif, ilgstat, new_fmode, new_filter); 2351 if (err != 0) { 2352 /* 2353 * Restore the original filter state, or delete the 2354 * newly-created ilg. We need to look up the ilg 2355 * again, though, since we've not been holding the 2356 * conn_lock. 2357 */ 2358 mutex_enter(&connp->conn_lock); 2359 ilg = ilg_lookup_ipif(connp, grp, ipif); 2360 ASSERT(ilg != NULL); 2361 if (ilgstat == ILGSTAT_NEW) { 2362 ilg_delete(connp, ilg, NULL); 2363 } else { 2364 ilg->ilg_fmode = orig_fmode; 2365 if (SLIST_IS_EMPTY(orig_filter)) { 2366 CLEAR_SLIST(ilg->ilg_filter); 2367 } else { 2368 /* 2369 * We didn't free the filter, even if we 2370 * were trying to make the source list empty; 2371 * so if orig_filter isn't empty, the ilg 2372 * must still have a filter alloc'd. 2373 */ 2374 l_copy(orig_filter, ilg->ilg_filter); 2375 } 2376 } 2377 mutex_exit(&connp->conn_lock); 2378 } 2379 2380 free_and_exit: 2381 l_free(orig_filter); 2382 l_free(new_filter); 2383 2384 return (err); 2385 } 2386 2387 static int 2388 ip_set_srcfilter_v6(conn_t *connp, struct group_filter *gf, 2389 const struct in6_addr *grp, ill_t *ill) 2390 { 2391 ilg_t *ilg; 2392 int i, orig_ifindex, orig_fmode, new_fmode, err; 2393 slist_t *orig_filter = NULL; 2394 slist_t *new_filter = NULL; 2395 struct sockaddr_storage *sl; 2396 struct sockaddr_in6 *sin6; 2397 boolean_t leave_grp; 2398 ilg_stat_t ilgstat; 2399 2400 /* Make sure we can handle the source list */ 2401 if (gf->gf_numsrc > MAX_FILTER_SIZE) 2402 return (ENOBUFS); 2403 2404 /* 2405 * setting the filter to (INCLUDE, NULL) is treated 2406 * as a request to leave the group. 2407 */ 2408 leave_grp = (gf->gf_fmode == MCAST_INCLUDE && gf->gf_numsrc == 0); 2409 2410 ASSERT(IAM_WRITER_ILL(ill)); 2411 2412 /* 2413 * Use the ifindex to do the lookup. We can't use the ill 2414 * directly because ilg_ill could point to a different ill 2415 * if things have moved. 2416 */ 2417 orig_ifindex = ill->ill_phyint->phyint_ifindex; 2418 2419 mutex_enter(&connp->conn_lock); 2420 ilg = ilg_lookup_ill_index_v6(connp, grp, orig_ifindex); 2421 if (ilg == NULL) { 2422 /* 2423 * if the request was actually to leave, and we 2424 * didn't find an ilg, there's nothing to do. 2425 */ 2426 if (!leave_grp) 2427 ilg = conn_ilg_alloc(connp); 2428 if (leave_grp || ilg == NULL) { 2429 mutex_exit(&connp->conn_lock); 2430 return (leave_grp ? 0 : ENOMEM); 2431 } 2432 ilgstat = ILGSTAT_NEW; 2433 ilg->ilg_v6group = *grp; 2434 ilg->ilg_ipif = NULL; 2435 /* 2436 * Choose our target ill to join on. This might be 2437 * different from the ill we've been given if it's 2438 * currently down and part of a group. 2439 * 2440 * new ill is not refheld; we are writer. 2441 */ 2442 ill = ip_choose_multi_ill(ill, grp); 2443 ASSERT(!(ill->ill_state_flags & ILL_CONDEMNED)); 2444 ilg->ilg_ill = ill; 2445 /* 2446 * Remember the index that we joined on, so that we can 2447 * successfully delete them later on and also search for 2448 * duplicates if the application wants to join again. 2449 */ 2450 ilg->ilg_orig_ifindex = orig_ifindex; 2451 } else if (leave_grp) { 2452 /* 2453 * Use the ilg's current ill for the deletion, 2454 * we might have failed over. 2455 */ 2456 ill = ilg->ilg_ill; 2457 ilg_delete(connp, ilg, NULL); 2458 mutex_exit(&connp->conn_lock); 2459 (void) ip_delmulti_v6(grp, ill, orig_ifindex, 2460 connp->conn_zoneid, B_FALSE, B_TRUE); 2461 return (0); 2462 } else { 2463 ilgstat = ILGSTAT_CHANGE; 2464 /* 2465 * The current ill might be different from the one we were 2466 * asked to join on (if failover has occurred); we should 2467 * join on the ill stored in the ilg. The original ill 2468 * is noted in ilg_orig_ifindex, which matched our request. 2469 */ 2470 ill = ilg->ilg_ill; 2471 /* preserve existing state in case ip_addmulti() fails */ 2472 orig_fmode = ilg->ilg_fmode; 2473 if (ilg->ilg_filter == NULL) { 2474 orig_filter = NULL; 2475 } else { 2476 orig_filter = l_alloc_copy(ilg->ilg_filter); 2477 if (orig_filter == NULL) { 2478 mutex_exit(&connp->conn_lock); 2479 return (ENOMEM); 2480 } 2481 } 2482 } 2483 2484 /* 2485 * Alloc buffer to copy new state into (see below) before 2486 * we make any changes, so we can bail if it fails. 2487 */ 2488 if ((new_filter = l_alloc()) == NULL) { 2489 mutex_exit(&connp->conn_lock); 2490 err = ENOMEM; 2491 goto free_and_exit; 2492 } 2493 2494 if (gf->gf_numsrc == 0) { 2495 CLEAR_SLIST(ilg->ilg_filter); 2496 } else { 2497 slist_t *fp; 2498 if (ilg->ilg_filter == NULL) { 2499 fp = l_alloc(); 2500 if (fp == NULL) { 2501 if (ilgstat == ILGSTAT_NEW) 2502 ilg_delete(connp, ilg, NULL); 2503 mutex_exit(&connp->conn_lock); 2504 err = ENOMEM; 2505 goto free_and_exit; 2506 } 2507 } else { 2508 fp = ilg->ilg_filter; 2509 } 2510 for (i = 0, sl = gf->gf_slist; i < gf->gf_numsrc; i++, sl++) { 2511 sin6 = (struct sockaddr_in6 *)sl; 2512 fp->sl_addr[i] = sin6->sin6_addr; 2513 } 2514 fp->sl_numsrc = gf->gf_numsrc; 2515 ilg->ilg_filter = fp; 2516 } 2517 /* 2518 * In the kernel, we use the state definitions MODE_IS_[IN|EX]CLUDE 2519 * to identify the filter mode; but the API uses MCAST_[IN|EX]CLUDE. 2520 * So we need to translate here. 2521 */ 2522 ilg->ilg_fmode = (gf->gf_fmode == MCAST_INCLUDE) ? 2523 MODE_IS_INCLUDE : MODE_IS_EXCLUDE; 2524 2525 /* 2526 * Save copy of ilg's filter state to pass to other functions, 2527 * so we can release conn_lock now. 2528 */ 2529 new_fmode = ilg->ilg_fmode; 2530 l_copy(ilg->ilg_filter, new_filter); 2531 2532 mutex_exit(&connp->conn_lock); 2533 2534 err = ip_addmulti_v6(grp, ill, orig_ifindex, connp->conn_zoneid, 2535 ilgstat, new_fmode, new_filter); 2536 if (err != 0) { 2537 /* 2538 * Restore the original filter state, or delete the 2539 * newly-created ilg. We need to look up the ilg 2540 * again, though, since we've not been holding the 2541 * conn_lock. 2542 */ 2543 mutex_enter(&connp->conn_lock); 2544 ilg = ilg_lookup_ill_index_v6(connp, grp, orig_ifindex); 2545 ASSERT(ilg != NULL); 2546 if (ilgstat == ILGSTAT_NEW) { 2547 ilg_delete(connp, ilg, NULL); 2548 } else { 2549 ilg->ilg_fmode = orig_fmode; 2550 if (SLIST_IS_EMPTY(orig_filter)) { 2551 CLEAR_SLIST(ilg->ilg_filter); 2552 } else { 2553 /* 2554 * We didn't free the filter, even if we 2555 * were trying to make the source list empty; 2556 * so if orig_filter isn't empty, the ilg 2557 * must still have a filter alloc'd. 2558 */ 2559 l_copy(orig_filter, ilg->ilg_filter); 2560 } 2561 } 2562 mutex_exit(&connp->conn_lock); 2563 } 2564 2565 free_and_exit: 2566 l_free(orig_filter); 2567 l_free(new_filter); 2568 2569 return (err); 2570 } 2571 2572 /* 2573 * Process the SIOC[GS]MSFILTER and SIOC[GS]IPMSFILTER ioctls. 2574 */ 2575 /* ARGSUSED */ 2576 int 2577 ip_sioctl_msfilter(ipif_t *ipif, sin_t *dummy_sin, queue_t *q, mblk_t *mp, 2578 ip_ioctl_cmd_t *ipip, void *ifreq) 2579 { 2580 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2581 /* existence verified in ip_wput_nondata() */ 2582 mblk_t *data_mp = mp->b_cont->b_cont; 2583 int datalen, err, cmd, minsize; 2584 uint_t expsize = 0; 2585 conn_t *connp; 2586 boolean_t isv6, is_v4only_api, getcmd; 2587 struct sockaddr_in *gsin; 2588 struct sockaddr_in6 *gsin6; 2589 ipaddr_t v4grp; 2590 in6_addr_t v6grp; 2591 struct group_filter *gf = NULL; 2592 struct ip_msfilter *imsf = NULL; 2593 mblk_t *ndp; 2594 2595 if (data_mp->b_cont != NULL) { 2596 if ((ndp = msgpullup(data_mp, -1)) == NULL) 2597 return (ENOMEM); 2598 freemsg(data_mp); 2599 data_mp = ndp; 2600 mp->b_cont->b_cont = data_mp; 2601 } 2602 2603 cmd = iocp->ioc_cmd; 2604 getcmd = (cmd == SIOCGIPMSFILTER || cmd == SIOCGMSFILTER); 2605 is_v4only_api = (cmd == SIOCGIPMSFILTER || cmd == SIOCSIPMSFILTER); 2606 minsize = (is_v4only_api) ? IP_MSFILTER_SIZE(0) : GROUP_FILTER_SIZE(0); 2607 datalen = MBLKL(data_mp); 2608 2609 if (datalen < minsize) 2610 return (EINVAL); 2611 2612 /* 2613 * now we know we have at least have the initial structure, 2614 * but need to check for the source list array. 2615 */ 2616 if (is_v4only_api) { 2617 imsf = (struct ip_msfilter *)data_mp->b_rptr; 2618 isv6 = B_FALSE; 2619 expsize = IP_MSFILTER_SIZE(imsf->imsf_numsrc); 2620 } else { 2621 gf = (struct group_filter *)data_mp->b_rptr; 2622 if (gf->gf_group.ss_family == AF_INET6) { 2623 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2624 isv6 = !(IN6_IS_ADDR_V4MAPPED(&gsin6->sin6_addr)); 2625 } else { 2626 isv6 = B_FALSE; 2627 } 2628 expsize = GROUP_FILTER_SIZE(gf->gf_numsrc); 2629 } 2630 if (datalen < expsize) 2631 return (EINVAL); 2632 2633 connp = Q_TO_CONN(q); 2634 2635 /* operation not supported on the virtual network interface */ 2636 if (IS_VNI(ipif->ipif_ill)) 2637 return (EINVAL); 2638 2639 if (isv6) { 2640 ill_t *ill = ipif->ipif_ill; 2641 ill_refhold(ill); 2642 2643 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2644 v6grp = gsin6->sin6_addr; 2645 if (getcmd) 2646 err = ip_get_srcfilter_v6(connp, gf, &v6grp, ill); 2647 else 2648 err = ip_set_srcfilter_v6(connp, gf, &v6grp, ill); 2649 2650 ill_refrele(ill); 2651 } else { 2652 boolean_t isv4mapped = B_FALSE; 2653 if (is_v4only_api) { 2654 v4grp = (ipaddr_t)imsf->imsf_multiaddr.s_addr; 2655 } else { 2656 if (gf->gf_group.ss_family == AF_INET) { 2657 gsin = (struct sockaddr_in *)&gf->gf_group; 2658 v4grp = (ipaddr_t)gsin->sin_addr.s_addr; 2659 } else { 2660 gsin6 = (struct sockaddr_in6 *)&gf->gf_group; 2661 IN6_V4MAPPED_TO_IPADDR(&gsin6->sin6_addr, 2662 v4grp); 2663 isv4mapped = B_TRUE; 2664 } 2665 } 2666 if (getcmd) 2667 err = ip_get_srcfilter(connp, gf, imsf, v4grp, ipif, 2668 isv4mapped); 2669 else 2670 err = ip_set_srcfilter(connp, gf, imsf, v4grp, ipif, 2671 isv4mapped); 2672 } 2673 2674 return (err); 2675 } 2676 2677 /* 2678 * Finds the ipif based on information in the ioctl headers. Needed to make 2679 * ip_process_ioctl() happy (it needs to know the ipif for IPI_WR-flagged 2680 * ioctls prior to calling the ioctl's handler function). 2681 */ 2682 int 2683 ip_extract_msfilter(queue_t *q, mblk_t *mp, const ip_ioctl_cmd_t *ipip, 2684 cmd_info_t *ci, ipsq_func_t func) 2685 { 2686 int cmd = ipip->ipi_cmd; 2687 int err = 0; 2688 conn_t *connp; 2689 ipif_t *ipif; 2690 /* caller has verified this mblk exists */ 2691 char *dbuf = (char *)mp->b_cont->b_cont->b_rptr; 2692 struct ip_msfilter *imsf; 2693 struct group_filter *gf; 2694 ipaddr_t v4addr, v4grp; 2695 in6_addr_t v6grp; 2696 uint32_t index; 2697 zoneid_t zoneid; 2698 ip_stack_t *ipst; 2699 2700 connp = Q_TO_CONN(q); 2701 zoneid = connp->conn_zoneid; 2702 ipst = connp->conn_netstack->netstack_ip; 2703 2704 /* don't allow multicast operations on a tcp conn */ 2705 if (IPCL_IS_TCP(connp)) 2706 return (ENOPROTOOPT); 2707 2708 if (cmd == SIOCSIPMSFILTER || cmd == SIOCGIPMSFILTER) { 2709 /* don't allow v4-specific ioctls on v6 socket */ 2710 if (connp->conn_af_isv6) 2711 return (EAFNOSUPPORT); 2712 2713 imsf = (struct ip_msfilter *)dbuf; 2714 v4addr = imsf->imsf_interface.s_addr; 2715 v4grp = imsf->imsf_multiaddr.s_addr; 2716 if (v4addr == INADDR_ANY) { 2717 ipif = ipif_lookup_group(v4grp, zoneid, ipst); 2718 if (ipif == NULL) 2719 err = EADDRNOTAVAIL; 2720 } else { 2721 ipif = ipif_lookup_addr(v4addr, NULL, zoneid, q, mp, 2722 func, &err, ipst); 2723 } 2724 } else { 2725 boolean_t isv6 = B_FALSE; 2726 gf = (struct group_filter *)dbuf; 2727 index = gf->gf_interface; 2728 if (gf->gf_group.ss_family == AF_INET6) { 2729 struct sockaddr_in6 *sin6; 2730 sin6 = (struct sockaddr_in6 *)&gf->gf_group; 2731 v6grp = sin6->sin6_addr; 2732 if (IN6_IS_ADDR_V4MAPPED(&v6grp)) 2733 IN6_V4MAPPED_TO_IPADDR(&v6grp, v4grp); 2734 else 2735 isv6 = B_TRUE; 2736 } else if (gf->gf_group.ss_family == AF_INET) { 2737 struct sockaddr_in *sin; 2738 sin = (struct sockaddr_in *)&gf->gf_group; 2739 v4grp = sin->sin_addr.s_addr; 2740 } else { 2741 return (EAFNOSUPPORT); 2742 } 2743 if (index == 0) { 2744 if (isv6) { 2745 ipif = ipif_lookup_group_v6(&v6grp, zoneid, 2746 ipst); 2747 } else { 2748 ipif = ipif_lookup_group(v4grp, zoneid, ipst); 2749 } 2750 if (ipif == NULL) 2751 err = EADDRNOTAVAIL; 2752 } else { 2753 ipif = ipif_lookup_on_ifindex(index, isv6, zoneid, 2754 q, mp, func, &err, ipst); 2755 } 2756 } 2757 2758 ci->ci_ipif = ipif; 2759 return (err); 2760 } 2761 2762 /* 2763 * The structures used for the SIOC*MSFILTER ioctls usually must be copied 2764 * in in two stages, as the first copyin tells us the size of the attached 2765 * source buffer. This function is called by ip_wput_nondata() after the 2766 * first copyin has completed; it figures out how big the second stage 2767 * needs to be, and kicks it off. 2768 * 2769 * In some cases (numsrc < 2), the second copyin is not needed as the 2770 * first one gets a complete structure containing 1 source addr. 2771 * 2772 * The function returns 0 if a second copyin has been started (i.e. there's 2773 * no more work to be done right now), or 1 if the second copyin is not 2774 * needed and ip_wput_nondata() can continue its processing. 2775 */ 2776 int 2777 ip_copyin_msfilter(queue_t *q, mblk_t *mp) 2778 { 2779 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2780 int cmd = iocp->ioc_cmd; 2781 /* validity of this checked in ip_wput_nondata() */ 2782 mblk_t *mp1 = mp->b_cont->b_cont; 2783 int copysize = 0; 2784 int offset; 2785 2786 if (cmd == SIOCSMSFILTER || cmd == SIOCGMSFILTER) { 2787 struct group_filter *gf = (struct group_filter *)mp1->b_rptr; 2788 if (gf->gf_numsrc >= 2) { 2789 offset = sizeof (struct group_filter); 2790 copysize = GROUP_FILTER_SIZE(gf->gf_numsrc) - offset; 2791 } 2792 } else { 2793 struct ip_msfilter *imsf = (struct ip_msfilter *)mp1->b_rptr; 2794 if (imsf->imsf_numsrc >= 2) { 2795 offset = sizeof (struct ip_msfilter); 2796 copysize = IP_MSFILTER_SIZE(imsf->imsf_numsrc) - offset; 2797 } 2798 } 2799 if (copysize > 0) { 2800 mi_copyin_n(q, mp, offset, copysize); 2801 return (0); 2802 } 2803 return (1); 2804 } 2805 2806 /* 2807 * Handle the following optmgmt: 2808 * IP_ADD_MEMBERSHIP must not have joined already 2809 * MCAST_JOIN_GROUP must not have joined already 2810 * IP_BLOCK_SOURCE must have joined already 2811 * MCAST_BLOCK_SOURCE must have joined already 2812 * IP_JOIN_SOURCE_GROUP may have joined already 2813 * MCAST_JOIN_SOURCE_GROUP may have joined already 2814 * 2815 * fmode and src parameters may be used to determine which option is 2816 * being set, as follows (the IP_* and MCAST_* versions of each option 2817 * are functionally equivalent): 2818 * opt fmode src 2819 * IP_ADD_MEMBERSHIP MODE_IS_EXCLUDE INADDR_ANY 2820 * MCAST_JOIN_GROUP MODE_IS_EXCLUDE INADDR_ANY 2821 * IP_BLOCK_SOURCE MODE_IS_EXCLUDE v4 addr 2822 * MCAST_BLOCK_SOURCE MODE_IS_EXCLUDE v4 addr 2823 * IP_JOIN_SOURCE_GROUP MODE_IS_INCLUDE v4 addr 2824 * MCAST_JOIN_SOURCE_GROUP MODE_IS_INCLUDE v4 addr 2825 * 2826 * Changing the filter mode is not allowed; if a matching ilg already 2827 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2828 * 2829 * Verifies that there is a source address of appropriate scope for 2830 * the group; if not, EADDRNOTAVAIL is returned. 2831 * 2832 * The interface to be used may be identified by an address or by an 2833 * index. A pointer to the index is passed; if it is NULL, use the 2834 * address, otherwise, use the index. 2835 */ 2836 int 2837 ip_opt_add_group(conn_t *connp, boolean_t checkonly, ipaddr_t group, 2838 ipaddr_t ifaddr, uint_t *ifindexp, mcast_record_t fmode, ipaddr_t src, 2839 mblk_t *first_mp) 2840 { 2841 ipif_t *ipif; 2842 ipsq_t *ipsq; 2843 int err = 0; 2844 ill_t *ill; 2845 2846 err = ip_opt_check(connp, group, src, ifaddr, ifindexp, first_mp, 2847 ip_restart_optmgmt, &ipif); 2848 if (err != 0) { 2849 if (err != EINPROGRESS) { 2850 ip1dbg(("ip_opt_add_group: no ipif for group 0x%x, " 2851 "ifaddr 0x%x, ifindex %d\n", ntohl(group), 2852 ntohl(ifaddr), (ifindexp == NULL) ? 0 : *ifindexp)); 2853 } 2854 return (err); 2855 } 2856 ASSERT(ipif != NULL); 2857 2858 ill = ipif->ipif_ill; 2859 /* Operation not supported on a virtual network interface */ 2860 if (IS_VNI(ill)) { 2861 ipif_refrele(ipif); 2862 return (EINVAL); 2863 } 2864 2865 if (checkonly) { 2866 /* 2867 * do not do operation, just pretend to - new T_CHECK 2868 * semantics. The error return case above if encountered 2869 * considered a good enough "check" here. 2870 */ 2871 ipif_refrele(ipif); 2872 return (0); 2873 } 2874 2875 IPSQ_ENTER_IPIF(ipif, connp, first_mp, ip_restart_optmgmt, ipsq, 2876 NEW_OP); 2877 2878 /* unspecified source addr => no source filtering */ 2879 err = ilg_add(connp, group, ipif, fmode, src); 2880 2881 IPSQ_EXIT(ipsq); 2882 2883 ipif_refrele(ipif); 2884 return (err); 2885 } 2886 2887 /* 2888 * Handle the following optmgmt: 2889 * IPV6_JOIN_GROUP must not have joined already 2890 * MCAST_JOIN_GROUP must not have joined already 2891 * MCAST_BLOCK_SOURCE must have joined already 2892 * MCAST_JOIN_SOURCE_GROUP may have joined already 2893 * 2894 * fmode and src parameters may be used to determine which option is 2895 * being set, as follows (IPV6_JOIN_GROUP and MCAST_JOIN_GROUP options 2896 * are functionally equivalent): 2897 * opt fmode v6src 2898 * IPV6_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2899 * MCAST_JOIN_GROUP MODE_IS_EXCLUDE unspecified 2900 * MCAST_BLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 2901 * MCAST_JOIN_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 2902 * 2903 * Changing the filter mode is not allowed; if a matching ilg already 2904 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 2905 * 2906 * Verifies that there is a source address of appropriate scope for 2907 * the group; if not, EADDRNOTAVAIL is returned. 2908 * 2909 * Handles IPv4-mapped IPv6 multicast addresses by associating them 2910 * with the link-local ipif. Assumes that if v6group is v4-mapped, 2911 * v6src is also v4-mapped. 2912 */ 2913 int 2914 ip_opt_add_group_v6(conn_t *connp, boolean_t checkonly, 2915 const in6_addr_t *v6group, int ifindex, mcast_record_t fmode, 2916 const in6_addr_t *v6src, mblk_t *first_mp) 2917 { 2918 ill_t *ill; 2919 ipif_t *ipif; 2920 char buf[INET6_ADDRSTRLEN]; 2921 ipaddr_t v4group, v4src; 2922 boolean_t isv6; 2923 ipsq_t *ipsq; 2924 int err; 2925 2926 err = ip_opt_check_v6(connp, v6group, &v4group, v6src, &v4src, &isv6, 2927 ifindex, first_mp, ip_restart_optmgmt, &ill, &ipif); 2928 if (err != 0) { 2929 if (err != EINPROGRESS) { 2930 ip1dbg(("ip_opt_add_group_v6: no ill for group %s/" 2931 "index %d\n", inet_ntop(AF_INET6, v6group, buf, 2932 sizeof (buf)), ifindex)); 2933 } 2934 return (err); 2935 } 2936 ASSERT((!isv6 && ipif != NULL) || (isv6 && ill != NULL)); 2937 2938 /* operation is not supported on the virtual network interface */ 2939 if (isv6) { 2940 if (IS_VNI(ill)) { 2941 ill_refrele(ill); 2942 return (EINVAL); 2943 } 2944 } else { 2945 if (IS_VNI(ipif->ipif_ill)) { 2946 ipif_refrele(ipif); 2947 return (EINVAL); 2948 } 2949 } 2950 2951 if (checkonly) { 2952 /* 2953 * do not do operation, just pretend to - new T_CHECK 2954 * semantics. The error return case above if encountered 2955 * considered a good enough "check" here. 2956 */ 2957 if (isv6) 2958 ill_refrele(ill); 2959 else 2960 ipif_refrele(ipif); 2961 return (0); 2962 } 2963 2964 if (!isv6) { 2965 IPSQ_ENTER_IPIF(ipif, connp, first_mp, ip_restart_optmgmt, 2966 ipsq, NEW_OP); 2967 err = ilg_add(connp, v4group, ipif, fmode, v4src); 2968 IPSQ_EXIT(ipsq); 2969 ipif_refrele(ipif); 2970 } else { 2971 IPSQ_ENTER_ILL(ill, connp, first_mp, ip_restart_optmgmt, 2972 ipsq, NEW_OP); 2973 err = ilg_add_v6(connp, v6group, ill, fmode, v6src); 2974 IPSQ_EXIT(ipsq); 2975 ill_refrele(ill); 2976 } 2977 2978 return (err); 2979 } 2980 2981 static int 2982 ip_opt_delete_group_excl(conn_t *connp, ipaddr_t group, ipif_t *ipif, 2983 mcast_record_t fmode, ipaddr_t src) 2984 { 2985 ilg_t *ilg; 2986 in6_addr_t v6src; 2987 boolean_t leaving = B_FALSE; 2988 2989 ASSERT(IAM_WRITER_IPIF(ipif)); 2990 2991 /* 2992 * The ilg is valid only while we hold the conn lock. Once we drop 2993 * the lock, another thread can locate another ilg on this connp, 2994 * but on a different ipif, and delete it, and cause the ilg array 2995 * to be reallocated and copied. Hence do the ilg_delete before 2996 * dropping the lock. 2997 */ 2998 mutex_enter(&connp->conn_lock); 2999 ilg = ilg_lookup_ipif(connp, group, ipif); 3000 if ((ilg == NULL) || (ilg->ilg_flags & ILG_DELETED)) { 3001 mutex_exit(&connp->conn_lock); 3002 return (EADDRNOTAVAIL); 3003 } 3004 3005 /* 3006 * Decide if we're actually deleting the ilg or just removing a 3007 * source filter address; if just removing an addr, make sure we 3008 * aren't trying to change the filter mode, and that the addr is 3009 * actually in our filter list already. If we're removing the 3010 * last src in an include list, just delete the ilg. 3011 */ 3012 if (src == INADDR_ANY) { 3013 v6src = ipv6_all_zeros; 3014 leaving = B_TRUE; 3015 } else { 3016 int err = 0; 3017 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 3018 if (fmode != ilg->ilg_fmode) 3019 err = EINVAL; 3020 else if (ilg->ilg_filter == NULL || 3021 !list_has_addr(ilg->ilg_filter, &v6src)) 3022 err = EADDRNOTAVAIL; 3023 if (err != 0) { 3024 mutex_exit(&connp->conn_lock); 3025 return (err); 3026 } 3027 if (fmode == MODE_IS_INCLUDE && 3028 ilg->ilg_filter->sl_numsrc == 1) { 3029 v6src = ipv6_all_zeros; 3030 leaving = B_TRUE; 3031 } 3032 } 3033 3034 ilg_delete(connp, ilg, &v6src); 3035 mutex_exit(&connp->conn_lock); 3036 3037 (void) ip_delmulti(group, ipif, B_FALSE, leaving); 3038 return (0); 3039 } 3040 3041 static int 3042 ip_opt_delete_group_excl_v6(conn_t *connp, const in6_addr_t *v6group, 3043 ill_t *ill, mcast_record_t fmode, const in6_addr_t *v6src) 3044 { 3045 ilg_t *ilg; 3046 ill_t *ilg_ill; 3047 uint_t ilg_orig_ifindex; 3048 boolean_t leaving = B_TRUE; 3049 3050 ASSERT(IAM_WRITER_ILL(ill)); 3051 3052 /* 3053 * Use the index that we originally used to join. We can't 3054 * use the ill directly because ilg_ill could point to 3055 * a new ill if things have moved. 3056 */ 3057 mutex_enter(&connp->conn_lock); 3058 ilg = ilg_lookup_ill_index_v6(connp, v6group, 3059 ill->ill_phyint->phyint_ifindex); 3060 if ((ilg == NULL) || (ilg->ilg_flags & ILG_DELETED)) { 3061 mutex_exit(&connp->conn_lock); 3062 return (EADDRNOTAVAIL); 3063 } 3064 3065 /* 3066 * Decide if we're actually deleting the ilg or just removing a 3067 * source filter address; if just removing an addr, make sure we 3068 * aren't trying to change the filter mode, and that the addr is 3069 * actually in our filter list already. If we're removing the 3070 * last src in an include list, just delete the ilg. 3071 */ 3072 if (!IN6_IS_ADDR_UNSPECIFIED(v6src)) { 3073 int err = 0; 3074 if (fmode != ilg->ilg_fmode) 3075 err = EINVAL; 3076 else if (ilg->ilg_filter == NULL || 3077 !list_has_addr(ilg->ilg_filter, v6src)) 3078 err = EADDRNOTAVAIL; 3079 if (err != 0) { 3080 mutex_exit(&connp->conn_lock); 3081 return (err); 3082 } 3083 if (fmode == MODE_IS_INCLUDE && 3084 ilg->ilg_filter->sl_numsrc == 1) 3085 v6src = NULL; 3086 else 3087 leaving = B_FALSE; 3088 } 3089 3090 ilg_ill = ilg->ilg_ill; 3091 ilg_orig_ifindex = ilg->ilg_orig_ifindex; 3092 ilg_delete(connp, ilg, v6src); 3093 mutex_exit(&connp->conn_lock); 3094 (void) ip_delmulti_v6(v6group, ilg_ill, ilg_orig_ifindex, 3095 connp->conn_zoneid, B_FALSE, leaving); 3096 3097 return (0); 3098 } 3099 3100 /* 3101 * Handle the following optmgmt: 3102 * IP_DROP_MEMBERSHIP will leave 3103 * MCAST_LEAVE_GROUP will leave 3104 * IP_UNBLOCK_SOURCE will not leave 3105 * MCAST_UNBLOCK_SOURCE will not leave 3106 * IP_LEAVE_SOURCE_GROUP may leave (if leaving last source) 3107 * MCAST_LEAVE_SOURCE_GROUP may leave (if leaving last source) 3108 * 3109 * fmode and src parameters may be used to determine which option is 3110 * being set, as follows (the IP_* and MCAST_* versions of each option 3111 * are functionally equivalent): 3112 * opt fmode src 3113 * IP_DROP_MEMBERSHIP MODE_IS_INCLUDE INADDR_ANY 3114 * MCAST_LEAVE_GROUP MODE_IS_INCLUDE INADDR_ANY 3115 * IP_UNBLOCK_SOURCE MODE_IS_EXCLUDE v4 addr 3116 * MCAST_UNBLOCK_SOURCE MODE_IS_EXCLUDE v4 addr 3117 * IP_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE v4 addr 3118 * MCAST_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE v4 addr 3119 * 3120 * Changing the filter mode is not allowed; if a matching ilg already 3121 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 3122 * 3123 * The interface to be used may be identified by an address or by an 3124 * index. A pointer to the index is passed; if it is NULL, use the 3125 * address, otherwise, use the index. 3126 */ 3127 int 3128 ip_opt_delete_group(conn_t *connp, boolean_t checkonly, ipaddr_t group, 3129 ipaddr_t ifaddr, uint_t *ifindexp, mcast_record_t fmode, ipaddr_t src, 3130 mblk_t *first_mp) 3131 { 3132 ipif_t *ipif; 3133 ipsq_t *ipsq; 3134 int err; 3135 ill_t *ill; 3136 3137 err = ip_opt_check(connp, group, src, ifaddr, ifindexp, first_mp, 3138 ip_restart_optmgmt, &ipif); 3139 if (err != 0) { 3140 if (err != EINPROGRESS) { 3141 ip1dbg(("ip_opt_delete_group: no ipif for group " 3142 "0x%x, ifaddr 0x%x\n", 3143 (int)ntohl(group), (int)ntohl(ifaddr))); 3144 } 3145 return (err); 3146 } 3147 ASSERT(ipif != NULL); 3148 3149 ill = ipif->ipif_ill; 3150 /* Operation not supported on a virtual network interface */ 3151 if (IS_VNI(ill)) { 3152 ipif_refrele(ipif); 3153 return (EINVAL); 3154 } 3155 3156 if (checkonly) { 3157 /* 3158 * do not do operation, just pretend to - new T_CHECK 3159 * semantics. The error return case above if encountered 3160 * considered a good enough "check" here. 3161 */ 3162 ipif_refrele(ipif); 3163 return (0); 3164 } 3165 3166 IPSQ_ENTER_IPIF(ipif, connp, first_mp, ip_restart_optmgmt, ipsq, 3167 NEW_OP); 3168 err = ip_opt_delete_group_excl(connp, group, ipif, fmode, src); 3169 IPSQ_EXIT(ipsq); 3170 3171 ipif_refrele(ipif); 3172 return (err); 3173 } 3174 3175 /* 3176 * Handle the following optmgmt: 3177 * IPV6_LEAVE_GROUP will leave 3178 * MCAST_LEAVE_GROUP will leave 3179 * MCAST_UNBLOCK_SOURCE will not leave 3180 * MCAST_LEAVE_SOURCE_GROUP may leave (if leaving last source) 3181 * 3182 * fmode and src parameters may be used to determine which option is 3183 * being set, as follows (IPV6_LEAVE_GROUP and MCAST_LEAVE_GROUP options 3184 * are functionally equivalent): 3185 * opt fmode v6src 3186 * IPV6_LEAVE_GROUP MODE_IS_INCLUDE unspecified 3187 * MCAST_LEAVE_GROUP MODE_IS_INCLUDE unspecified 3188 * MCAST_UNBLOCK_SOURCE MODE_IS_EXCLUDE v6 addr 3189 * MCAST_LEAVE_SOURCE_GROUP MODE_IS_INCLUDE v6 addr 3190 * 3191 * Changing the filter mode is not allowed; if a matching ilg already 3192 * exists and fmode != ilg->ilg_fmode, EINVAL is returned. 3193 * 3194 * Handles IPv4-mapped IPv6 multicast addresses by associating them 3195 * with the link-local ipif. Assumes that if v6group is v4-mapped, 3196 * v6src is also v4-mapped. 3197 */ 3198 int 3199 ip_opt_delete_group_v6(conn_t *connp, boolean_t checkonly, 3200 const in6_addr_t *v6group, int ifindex, mcast_record_t fmode, 3201 const in6_addr_t *v6src, mblk_t *first_mp) 3202 { 3203 ill_t *ill; 3204 ipif_t *ipif; 3205 char buf[INET6_ADDRSTRLEN]; 3206 ipaddr_t v4group, v4src; 3207 boolean_t isv6; 3208 ipsq_t *ipsq; 3209 int err; 3210 3211 err = ip_opt_check_v6(connp, v6group, &v4group, v6src, &v4src, &isv6, 3212 ifindex, first_mp, ip_restart_optmgmt, &ill, &ipif); 3213 if (err != 0) { 3214 if (err != EINPROGRESS) { 3215 ip1dbg(("ip_opt_delete_group_v6: no ill for group %s/" 3216 "index %d\n", inet_ntop(AF_INET6, v6group, buf, 3217 sizeof (buf)), ifindex)); 3218 } 3219 return (err); 3220 } 3221 ASSERT((isv6 && ill != NULL) || (!isv6 && ipif != NULL)); 3222 3223 /* operation is not supported on the virtual network interface */ 3224 if (isv6) { 3225 if (IS_VNI(ill)) { 3226 ill_refrele(ill); 3227 return (EINVAL); 3228 } 3229 } else { 3230 if (IS_VNI(ipif->ipif_ill)) { 3231 ipif_refrele(ipif); 3232 return (EINVAL); 3233 } 3234 } 3235 3236 if (checkonly) { 3237 /* 3238 * do not do operation, just pretend to - new T_CHECK 3239 * semantics. The error return case above if encountered 3240 * considered a good enough "check" here. 3241 */ 3242 if (isv6) 3243 ill_refrele(ill); 3244 else 3245 ipif_refrele(ipif); 3246 return (0); 3247 } 3248 3249 if (!isv6) { 3250 IPSQ_ENTER_IPIF(ipif, connp, first_mp, ip_restart_optmgmt, 3251 ipsq, NEW_OP); 3252 err = ip_opt_delete_group_excl(connp, v4group, ipif, fmode, 3253 v4src); 3254 IPSQ_EXIT(ipsq); 3255 ipif_refrele(ipif); 3256 } else { 3257 IPSQ_ENTER_ILL(ill, connp, first_mp, ip_restart_optmgmt, 3258 ipsq, NEW_OP); 3259 err = ip_opt_delete_group_excl_v6(connp, v6group, ill, fmode, 3260 v6src); 3261 IPSQ_EXIT(ipsq); 3262 ill_refrele(ill); 3263 } 3264 3265 return (err); 3266 } 3267 3268 /* 3269 * Group mgmt for upper conn that passes things down 3270 * to the interface multicast list (and DLPI) 3271 * These routines can handle new style options that specify an interface name 3272 * as opposed to an interface address (needed for general handling of 3273 * unnumbered interfaces.) 3274 */ 3275 3276 /* 3277 * Add a group to an upper conn group data structure and pass things down 3278 * to the interface multicast list (and DLPI) 3279 */ 3280 static int 3281 ilg_add(conn_t *connp, ipaddr_t group, ipif_t *ipif, mcast_record_t fmode, 3282 ipaddr_t src) 3283 { 3284 int error = 0; 3285 ill_t *ill; 3286 ilg_t *ilg; 3287 ilg_stat_t ilgstat; 3288 slist_t *new_filter = NULL; 3289 int new_fmode; 3290 3291 ASSERT(IAM_WRITER_IPIF(ipif)); 3292 3293 ill = ipif->ipif_ill; 3294 3295 if (!(ill->ill_flags & ILLF_MULTICAST)) 3296 return (EADDRNOTAVAIL); 3297 3298 /* 3299 * conn_ilg[] is protected by conn_lock. Need to hold the conn_lock 3300 * to walk the conn_ilg[] list in ilg_lookup_ipif(); also needed to 3301 * serialize 2 threads doing join (sock, group1, hme0:0) and 3302 * (sock, group2, hme1:0) where hme0 and hme1 map to different ipsqs, 3303 * but both operations happen on the same conn. 3304 */ 3305 mutex_enter(&connp->conn_lock); 3306 ilg = ilg_lookup_ipif(connp, group, ipif); 3307 3308 /* 3309 * Depending on the option we're handling, may or may not be okay 3310 * if group has already been added. Figure out our rules based 3311 * on fmode and src params. Also make sure there's enough room 3312 * in the filter if we're adding a source to an existing filter. 3313 */ 3314 if (src == INADDR_ANY) { 3315 /* we're joining for all sources, must not have joined */ 3316 if (ilg != NULL) 3317 error = EADDRINUSE; 3318 } else { 3319 if (fmode == MODE_IS_EXCLUDE) { 3320 /* (excl {addr}) => block source, must have joined */ 3321 if (ilg == NULL) 3322 error = EADDRNOTAVAIL; 3323 } 3324 /* (incl {addr}) => join source, may have joined */ 3325 3326 if (ilg != NULL && 3327 SLIST_CNT(ilg->ilg_filter) == MAX_FILTER_SIZE) 3328 error = ENOBUFS; 3329 } 3330 if (error != 0) { 3331 mutex_exit(&connp->conn_lock); 3332 return (error); 3333 } 3334 3335 ASSERT(!(ipif->ipif_state_flags & IPIF_CONDEMNED)); 3336 3337 /* 3338 * Alloc buffer to copy new state into (see below) before 3339 * we make any changes, so we can bail if it fails. 3340 */ 3341 if ((new_filter = l_alloc()) == NULL) { 3342 mutex_exit(&connp->conn_lock); 3343 return (ENOMEM); 3344 } 3345 3346 if (ilg == NULL) { 3347 ilgstat = ILGSTAT_NEW; 3348 if ((ilg = conn_ilg_alloc(connp)) == NULL) { 3349 mutex_exit(&connp->conn_lock); 3350 l_free(new_filter); 3351 return (ENOMEM); 3352 } 3353 if (src != INADDR_ANY) { 3354 ilg->ilg_filter = l_alloc(); 3355 if (ilg->ilg_filter == NULL) { 3356 ilg_delete(connp, ilg, NULL); 3357 mutex_exit(&connp->conn_lock); 3358 l_free(new_filter); 3359 return (ENOMEM); 3360 } 3361 ilg->ilg_filter->sl_numsrc = 1; 3362 IN6_IPADDR_TO_V4MAPPED(src, 3363 &ilg->ilg_filter->sl_addr[0]); 3364 } 3365 if (group == INADDR_ANY) { 3366 ilg->ilg_v6group = ipv6_all_zeros; 3367 } else { 3368 IN6_IPADDR_TO_V4MAPPED(group, &ilg->ilg_v6group); 3369 } 3370 ilg->ilg_ipif = ipif; 3371 ilg->ilg_ill = NULL; 3372 ilg->ilg_orig_ifindex = 0; 3373 ilg->ilg_fmode = fmode; 3374 } else { 3375 int index; 3376 in6_addr_t v6src; 3377 ilgstat = ILGSTAT_CHANGE; 3378 if (ilg->ilg_fmode != fmode || src == INADDR_ANY) { 3379 mutex_exit(&connp->conn_lock); 3380 l_free(new_filter); 3381 return (EINVAL); 3382 } 3383 if (ilg->ilg_filter == NULL) { 3384 ilg->ilg_filter = l_alloc(); 3385 if (ilg->ilg_filter == NULL) { 3386 mutex_exit(&connp->conn_lock); 3387 l_free(new_filter); 3388 return (ENOMEM); 3389 } 3390 } 3391 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 3392 if (list_has_addr(ilg->ilg_filter, &v6src)) { 3393 mutex_exit(&connp->conn_lock); 3394 l_free(new_filter); 3395 return (EADDRNOTAVAIL); 3396 } 3397 index = ilg->ilg_filter->sl_numsrc++; 3398 ilg->ilg_filter->sl_addr[index] = v6src; 3399 } 3400 3401 /* 3402 * Save copy of ilg's filter state to pass to other functions, 3403 * so we can release conn_lock now. 3404 */ 3405 new_fmode = ilg->ilg_fmode; 3406 l_copy(ilg->ilg_filter, new_filter); 3407 3408 mutex_exit(&connp->conn_lock); 3409 3410 error = ip_addmulti(group, ipif, ilgstat, new_fmode, new_filter); 3411 if (error != 0) { 3412 /* 3413 * Need to undo what we did before calling ip_addmulti()! 3414 * Must look up the ilg again since we've not been holding 3415 * conn_lock. 3416 */ 3417 in6_addr_t v6src; 3418 if (ilgstat == ILGSTAT_NEW) 3419 v6src = ipv6_all_zeros; 3420 else 3421 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 3422 mutex_enter(&connp->conn_lock); 3423 ilg = ilg_lookup_ipif(connp, group, ipif); 3424 ASSERT(ilg != NULL); 3425 ilg_delete(connp, ilg, &v6src); 3426 mutex_exit(&connp->conn_lock); 3427 l_free(new_filter); 3428 return (error); 3429 } 3430 3431 l_free(new_filter); 3432 return (0); 3433 } 3434 3435 static int 3436 ilg_add_v6(conn_t *connp, const in6_addr_t *v6group, ill_t *ill, 3437 mcast_record_t fmode, const in6_addr_t *v6src) 3438 { 3439 int error = 0; 3440 int orig_ifindex; 3441 ilg_t *ilg; 3442 ilg_stat_t ilgstat; 3443 slist_t *new_filter = NULL; 3444 int new_fmode; 3445 3446 ASSERT(IAM_WRITER_ILL(ill)); 3447 3448 if (!(ill->ill_flags & ILLF_MULTICAST)) 3449 return (EADDRNOTAVAIL); 3450 3451 /* 3452 * conn_lock protects the ilg list. Serializes 2 threads doing 3453 * join (sock, group1, hme0) and (sock, group2, hme1) where hme0 3454 * and hme1 map to different ipsq's, but both operations happen 3455 * on the same conn. 3456 */ 3457 mutex_enter(&connp->conn_lock); 3458 3459 /* 3460 * Use the ifindex to do the lookup. We can't use the ill 3461 * directly because ilg_ill could point to a different ill if 3462 * things have moved. 3463 */ 3464 orig_ifindex = ill->ill_phyint->phyint_ifindex; 3465 ilg = ilg_lookup_ill_index_v6(connp, v6group, orig_ifindex); 3466 3467 /* 3468 * Depending on the option we're handling, may or may not be okay 3469 * if group has already been added. Figure out our rules based 3470 * on fmode and src params. Also make sure there's enough room 3471 * in the filter if we're adding a source to an existing filter. 3472 */ 3473 if (IN6_IS_ADDR_UNSPECIFIED(v6src)) { 3474 /* we're joining for all sources, must not have joined */ 3475 if (ilg != NULL) 3476 error = EADDRINUSE; 3477 } else { 3478 if (fmode == MODE_IS_EXCLUDE) { 3479 /* (excl {addr}) => block source, must have joined */ 3480 if (ilg == NULL) 3481 error = EADDRNOTAVAIL; 3482 } 3483 /* (incl {addr}) => join source, may have joined */ 3484 3485 if (ilg != NULL && 3486 SLIST_CNT(ilg->ilg_filter) == MAX_FILTER_SIZE) 3487 error = ENOBUFS; 3488 } 3489 if (error != 0) { 3490 mutex_exit(&connp->conn_lock); 3491 return (error); 3492 } 3493 3494 /* 3495 * Alloc buffer to copy new state into (see below) before 3496 * we make any changes, so we can bail if it fails. 3497 */ 3498 if ((new_filter = l_alloc()) == NULL) { 3499 mutex_exit(&connp->conn_lock); 3500 return (ENOMEM); 3501 } 3502 3503 if (ilg == NULL) { 3504 if ((ilg = conn_ilg_alloc(connp)) == NULL) { 3505 mutex_exit(&connp->conn_lock); 3506 l_free(new_filter); 3507 return (ENOMEM); 3508 } 3509 if (!IN6_IS_ADDR_UNSPECIFIED(v6src)) { 3510 ilg->ilg_filter = l_alloc(); 3511 if (ilg->ilg_filter == NULL) { 3512 ilg_delete(connp, ilg, NULL); 3513 mutex_exit(&connp->conn_lock); 3514 l_free(new_filter); 3515 return (ENOMEM); 3516 } 3517 ilg->ilg_filter->sl_numsrc = 1; 3518 ilg->ilg_filter->sl_addr[0] = *v6src; 3519 } 3520 ilgstat = ILGSTAT_NEW; 3521 ilg->ilg_v6group = *v6group; 3522 ilg->ilg_fmode = fmode; 3523 ilg->ilg_ipif = NULL; 3524 /* 3525 * Choose our target ill to join on. This might be different 3526 * from the ill we've been given if it's currently down and 3527 * part of a group. 3528 * 3529 * new ill is not refheld; we are writer. 3530 */ 3531 ill = ip_choose_multi_ill(ill, v6group); 3532 ASSERT(!(ill->ill_state_flags & ILL_CONDEMNED)); 3533 ilg->ilg_ill = ill; 3534 /* 3535 * Remember the orig_ifindex that we joined on, so that we 3536 * can successfully delete them later on and also search 3537 * for duplicates if the application wants to join again. 3538 */ 3539 ilg->ilg_orig_ifindex = orig_ifindex; 3540 } else { 3541 int index; 3542 if (ilg->ilg_fmode != fmode || IN6_IS_ADDR_UNSPECIFIED(v6src)) { 3543 mutex_exit(&connp->conn_lock); 3544 l_free(new_filter); 3545 return (EINVAL); 3546 } 3547 if (ilg->ilg_filter == NULL) { 3548 ilg->ilg_filter = l_alloc(); 3549 if (ilg->ilg_filter == NULL) { 3550 mutex_exit(&connp->conn_lock); 3551 l_free(new_filter); 3552 return (ENOMEM); 3553 } 3554 } 3555 if (list_has_addr(ilg->ilg_filter, v6src)) { 3556 mutex_exit(&connp->conn_lock); 3557 l_free(new_filter); 3558 return (EADDRNOTAVAIL); 3559 } 3560 ilgstat = ILGSTAT_CHANGE; 3561 index = ilg->ilg_filter->sl_numsrc++; 3562 ilg->ilg_filter->sl_addr[index] = *v6src; 3563 /* 3564 * The current ill might be different from the one we were 3565 * asked to join on (if failover has occurred); we should 3566 * join on the ill stored in the ilg. The original ill 3567 * is noted in ilg_orig_ifindex, which matched our request. 3568 */ 3569 ill = ilg->ilg_ill; 3570 } 3571 3572 /* 3573 * Save copy of ilg's filter state to pass to other functions, 3574 * so we can release conn_lock now. 3575 */ 3576 new_fmode = ilg->ilg_fmode; 3577 l_copy(ilg->ilg_filter, new_filter); 3578 3579 mutex_exit(&connp->conn_lock); 3580 3581 /* 3582 * Now update the ill. We wait to do this until after the ilg 3583 * has been updated because we need to update the src filter 3584 * info for the ill, which involves looking at the status of 3585 * all the ilgs associated with this group/interface pair. 3586 */ 3587 error = ip_addmulti_v6(v6group, ill, orig_ifindex, connp->conn_zoneid, 3588 ilgstat, new_fmode, new_filter); 3589 if (error != 0) { 3590 /* 3591 * But because we waited, we have to undo the ilg update 3592 * if ip_addmulti_v6() fails. We also must lookup ilg 3593 * again, since we've not been holding conn_lock. 3594 */ 3595 in6_addr_t delsrc = 3596 (ilgstat == ILGSTAT_NEW) ? ipv6_all_zeros : *v6src; 3597 mutex_enter(&connp->conn_lock); 3598 ilg = ilg_lookup_ill_index_v6(connp, v6group, orig_ifindex); 3599 ASSERT(ilg != NULL); 3600 ilg_delete(connp, ilg, &delsrc); 3601 mutex_exit(&connp->conn_lock); 3602 l_free(new_filter); 3603 return (error); 3604 } 3605 3606 l_free(new_filter); 3607 3608 return (0); 3609 } 3610 3611 /* 3612 * Find an IPv4 ilg matching group, ill and source 3613 */ 3614 ilg_t * 3615 ilg_lookup_ill_withsrc(conn_t *connp, ipaddr_t group, ipaddr_t src, ill_t *ill) 3616 { 3617 in6_addr_t v6group, v6src; 3618 int i; 3619 boolean_t isinlist; 3620 ilg_t *ilg; 3621 ipif_t *ipif; 3622 ill_t *ilg_ill; 3623 3624 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3625 3626 /* 3627 * INADDR_ANY is represented as the IPv6 unspecified addr. 3628 */ 3629 if (group == INADDR_ANY) 3630 v6group = ipv6_all_zeros; 3631 else 3632 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 3633 3634 for (i = 0; i < connp->conn_ilg_inuse; i++) { 3635 ilg = &connp->conn_ilg[i]; 3636 if ((ipif = ilg->ilg_ipif) == NULL || 3637 (ilg->ilg_flags & ILG_DELETED) != 0) 3638 continue; 3639 ASSERT(ilg->ilg_ill == NULL); 3640 ilg_ill = ipif->ipif_ill; 3641 ASSERT(!ilg_ill->ill_isv6); 3642 if (ilg_ill == ill && 3643 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, &v6group)) { 3644 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 3645 /* no source filter, so this is a match */ 3646 return (ilg); 3647 } 3648 break; 3649 } 3650 } 3651 if (i == connp->conn_ilg_inuse) 3652 return (NULL); 3653 3654 /* 3655 * we have an ilg with matching ill and group; but 3656 * the ilg has a source list that we must check. 3657 */ 3658 IN6_IPADDR_TO_V4MAPPED(src, &v6src); 3659 isinlist = B_FALSE; 3660 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 3661 if (IN6_ARE_ADDR_EQUAL(&v6src, &ilg->ilg_filter->sl_addr[i])) { 3662 isinlist = B_TRUE; 3663 break; 3664 } 3665 } 3666 3667 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 3668 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) 3669 return (ilg); 3670 3671 return (NULL); 3672 } 3673 3674 /* 3675 * Find an IPv6 ilg matching group, ill, and source 3676 */ 3677 ilg_t * 3678 ilg_lookup_ill_withsrc_v6(conn_t *connp, const in6_addr_t *v6group, 3679 const in6_addr_t *v6src, ill_t *ill) 3680 { 3681 int i; 3682 boolean_t isinlist; 3683 ilg_t *ilg; 3684 ill_t *ilg_ill; 3685 3686 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3687 3688 for (i = 0; i < connp->conn_ilg_inuse; i++) { 3689 ilg = &connp->conn_ilg[i]; 3690 if ((ilg_ill = ilg->ilg_ill) == NULL || 3691 (ilg->ilg_flags & ILG_DELETED) != 0) 3692 continue; 3693 ASSERT(ilg->ilg_ipif == NULL); 3694 ASSERT(ilg_ill->ill_isv6); 3695 if (ilg_ill == ill && 3696 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) { 3697 if (SLIST_IS_EMPTY(ilg->ilg_filter)) { 3698 /* no source filter, so this is a match */ 3699 return (ilg); 3700 } 3701 break; 3702 } 3703 } 3704 if (i == connp->conn_ilg_inuse) 3705 return (NULL); 3706 3707 /* 3708 * we have an ilg with matching ill and group; but 3709 * the ilg has a source list that we must check. 3710 */ 3711 isinlist = B_FALSE; 3712 for (i = 0; i < ilg->ilg_filter->sl_numsrc; i++) { 3713 if (IN6_ARE_ADDR_EQUAL(v6src, &ilg->ilg_filter->sl_addr[i])) { 3714 isinlist = B_TRUE; 3715 break; 3716 } 3717 } 3718 3719 if ((isinlist && ilg->ilg_fmode == MODE_IS_INCLUDE) || 3720 (!isinlist && ilg->ilg_fmode == MODE_IS_EXCLUDE)) 3721 return (ilg); 3722 3723 return (NULL); 3724 } 3725 3726 /* 3727 * Get the ilg whose ilg_orig_ifindex is associated with ifindex. 3728 * This is useful when the interface fails and we have moved 3729 * to a new ill, but still would like to locate using the index 3730 * that we originally used to join. Used only for IPv6 currently. 3731 */ 3732 static ilg_t * 3733 ilg_lookup_ill_index_v6(conn_t *connp, const in6_addr_t *v6group, int ifindex) 3734 { 3735 ilg_t *ilg; 3736 int i; 3737 3738 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3739 for (i = 0; i < connp->conn_ilg_inuse; i++) { 3740 ilg = &connp->conn_ilg[i]; 3741 if (ilg->ilg_ill == NULL || 3742 (ilg->ilg_flags & ILG_DELETED) != 0) 3743 continue; 3744 /* ilg_ipif is NULL for V6 */ 3745 ASSERT(ilg->ilg_ipif == NULL); 3746 ASSERT(ilg->ilg_orig_ifindex != 0); 3747 if (IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group) && 3748 ilg->ilg_orig_ifindex == ifindex) { 3749 return (ilg); 3750 } 3751 } 3752 return (NULL); 3753 } 3754 3755 /* 3756 * Find an IPv6 ilg matching group and ill 3757 */ 3758 ilg_t * 3759 ilg_lookup_ill_v6(conn_t *connp, const in6_addr_t *v6group, ill_t *ill) 3760 { 3761 ilg_t *ilg; 3762 int i; 3763 ill_t *mem_ill; 3764 3765 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3766 3767 for (i = 0; i < connp->conn_ilg_inuse; i++) { 3768 ilg = &connp->conn_ilg[i]; 3769 if ((mem_ill = ilg->ilg_ill) == NULL || 3770 (ilg->ilg_flags & ILG_DELETED) != 0) 3771 continue; 3772 ASSERT(ilg->ilg_ipif == NULL); 3773 ASSERT(mem_ill->ill_isv6); 3774 if (mem_ill == ill && 3775 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, v6group)) 3776 return (ilg); 3777 } 3778 return (NULL); 3779 } 3780 3781 /* 3782 * Find an IPv4 ilg matching group and ipif 3783 */ 3784 static ilg_t * 3785 ilg_lookup_ipif(conn_t *connp, ipaddr_t group, ipif_t *ipif) 3786 { 3787 in6_addr_t v6group; 3788 int i; 3789 ilg_t *ilg; 3790 3791 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3792 ASSERT(!ipif->ipif_ill->ill_isv6); 3793 3794 if (group == INADDR_ANY) 3795 v6group = ipv6_all_zeros; 3796 else 3797 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 3798 3799 for (i = 0; i < connp->conn_ilg_inuse; i++) { 3800 ilg = &connp->conn_ilg[i]; 3801 if ((ilg->ilg_flags & ILG_DELETED) == 0 && 3802 IN6_ARE_ADDR_EQUAL(&ilg->ilg_v6group, &v6group) && 3803 ilg->ilg_ipif == ipif) 3804 return (ilg); 3805 } 3806 return (NULL); 3807 } 3808 3809 /* 3810 * If a source address is passed in (src != NULL and src is not 3811 * unspecified), remove the specified src addr from the given ilg's 3812 * filter list, else delete the ilg. 3813 */ 3814 static void 3815 ilg_delete(conn_t *connp, ilg_t *ilg, const in6_addr_t *src) 3816 { 3817 int i; 3818 3819 ASSERT((ilg->ilg_ipif != NULL) ^ (ilg->ilg_ill != NULL)); 3820 ASSERT(ilg->ilg_ipif == NULL || IAM_WRITER_IPIF(ilg->ilg_ipif)); 3821 ASSERT(ilg->ilg_ill == NULL || IAM_WRITER_ILL(ilg->ilg_ill)); 3822 ASSERT(MUTEX_HELD(&connp->conn_lock)); 3823 ASSERT(!(ilg->ilg_flags & ILG_DELETED)); 3824 3825 if (src == NULL || IN6_IS_ADDR_UNSPECIFIED(src)) { 3826 if (connp->conn_ilg_walker_cnt != 0) { 3827 ilg->ilg_flags |= ILG_DELETED; 3828 return; 3829 } 3830 3831 FREE_SLIST(ilg->ilg_filter); 3832 3833 i = ilg - &connp->conn_ilg[0]; 3834 ASSERT(i >= 0 && i < connp->conn_ilg_inuse); 3835 3836 /* Move other entries up one step */ 3837 connp->conn_ilg_inuse--; 3838 for (; i < connp->conn_ilg_inuse; i++) 3839 connp->conn_ilg[i] = connp->conn_ilg[i+1]; 3840 3841 if (connp->conn_ilg_inuse == 0) { 3842 mi_free((char *)connp->conn_ilg); 3843 connp->conn_ilg = NULL; 3844 cv_broadcast(&connp->conn_refcv); 3845 } 3846 } else { 3847 l_remove(ilg->ilg_filter, src); 3848 } 3849 } 3850 3851 /* 3852 * Called from conn close. No new ilg can be added or removed. 3853 * because CONN_CLOSING has been set by ip_close. ilg_add / ilg_delete 3854 * will return error if conn has started closing. 3855 */ 3856 void 3857 ilg_delete_all(conn_t *connp) 3858 { 3859 int i; 3860 ipif_t *ipif = NULL; 3861 ill_t *ill = NULL; 3862 ilg_t *ilg; 3863 in6_addr_t v6group; 3864 boolean_t success; 3865 ipsq_t *ipsq; 3866 int orig_ifindex; 3867 3868 mutex_enter(&connp->conn_lock); 3869 retry: 3870 ILG_WALKER_HOLD(connp); 3871 for (i = connp->conn_ilg_inuse - 1; i >= 0; ) { 3872 ilg = &connp->conn_ilg[i]; 3873 /* 3874 * Since this walk is not atomic (we drop the 3875 * conn_lock and wait in ipsq_enter) we need 3876 * to check for the ILG_DELETED flag. 3877 */ 3878 if (ilg->ilg_flags & ILG_DELETED) { 3879 /* Go to the next ilg */ 3880 i--; 3881 continue; 3882 } 3883 v6group = ilg->ilg_v6group; 3884 3885 if (IN6_IS_ADDR_V4MAPPED(&v6group)) { 3886 ipif = ilg->ilg_ipif; 3887 ill = ipif->ipif_ill; 3888 } else { 3889 ipif = NULL; 3890 ill = ilg->ilg_ill; 3891 } 3892 /* 3893 * We may not be able to refhold the ill if the ill/ipif 3894 * is changing. But we need to make sure that the ill will 3895 * not vanish. So we just bump up the ill_waiter count. 3896 * If we are unable to do even that, then the ill is closing, 3897 * in which case the unplumb thread will handle the cleanup, 3898 * and we move on to the next ilg. 3899 */ 3900 if (!ill_waiter_inc(ill)) { 3901 /* Go to the next ilg */ 3902 i--; 3903 continue; 3904 } 3905 mutex_exit(&connp->conn_lock); 3906 /* 3907 * To prevent deadlock between ill close which waits inside 3908 * the perimeter, and conn close, ipsq_enter returns error, 3909 * the moment ILL_CONDEMNED is set, in which case ill close 3910 * takes responsibility to cleanup the ilgs. Note that we 3911 * have not yet set condemned flag, otherwise the conn can't 3912 * be refheld for cleanup by those routines and it would be 3913 * a mutual deadlock. 3914 */ 3915 success = ipsq_enter(ill, B_FALSE, NEW_OP); 3916 ipsq = ill->ill_phyint->phyint_ipsq; 3917 ill_waiter_dcr(ill); 3918 mutex_enter(&connp->conn_lock); 3919 if (!success) { 3920 /* Go to the next ilg */ 3921 i--; 3922 continue; 3923 } 3924 3925 /* 3926 * Make sure that nothing has changed under. For eg. 3927 * a failover/failback can change ilg_ill while we were 3928 * waiting to become exclusive above 3929 */ 3930 if (IN6_IS_ADDR_V4MAPPED(&v6group)) { 3931 ipif = ilg->ilg_ipif; 3932 ill = ipif->ipif_ill; 3933 } else { 3934 ipif = NULL; 3935 ill = ilg->ilg_ill; 3936 } 3937 if (!IAM_WRITER_ILL(ill) || (ilg->ilg_flags & ILG_DELETED)) { 3938 /* 3939 * The ilg has changed under us probably due 3940 * to a failover or unplumb. Retry on the same ilg. 3941 */ 3942 mutex_exit(&connp->conn_lock); 3943 ipsq_exit(ipsq); 3944 mutex_enter(&connp->conn_lock); 3945 continue; 3946 } 3947 v6group = ilg->ilg_v6group; 3948 orig_ifindex = ilg->ilg_orig_ifindex; 3949 ilg_delete(connp, ilg, NULL); 3950 mutex_exit(&connp->conn_lock); 3951 3952 if (ipif != NULL) 3953 (void) ip_delmulti(V4_PART_OF_V6(v6group), ipif, 3954 B_FALSE, B_TRUE); 3955 3956 else 3957 (void) ip_delmulti_v6(&v6group, ill, orig_ifindex, 3958 connp->conn_zoneid, B_FALSE, B_TRUE); 3959 3960 ipsq_exit(ipsq); 3961 mutex_enter(&connp->conn_lock); 3962 /* Go to the next ilg */ 3963 i--; 3964 } 3965 ILG_WALKER_RELE(connp); 3966 3967 /* If any ill was skipped above wait and retry */ 3968 if (connp->conn_ilg_inuse != 0) { 3969 cv_wait(&connp->conn_refcv, &connp->conn_lock); 3970 goto retry; 3971 } 3972 mutex_exit(&connp->conn_lock); 3973 } 3974 3975 /* 3976 * Called from ill close by ipcl_walk for clearing conn_ilg and 3977 * conn_multicast_ipif for a given ipif. conn is held by caller. 3978 * Note that ipcl_walk only walks conns that are not yet condemned. 3979 * condemned conns can't be refheld. For this reason, conn must become clean 3980 * first, i.e. it must not refer to any ill/ire/ipif and then only set 3981 * condemned flag. 3982 */ 3983 static void 3984 conn_delete_ipif(conn_t *connp, caddr_t arg) 3985 { 3986 ipif_t *ipif = (ipif_t *)arg; 3987 int i; 3988 char group_buf1[INET6_ADDRSTRLEN]; 3989 char group_buf2[INET6_ADDRSTRLEN]; 3990 ipaddr_t group; 3991 ilg_t *ilg; 3992 3993 /* 3994 * Even though conn_ilg_inuse can change while we are in this loop, 3995 * i.e.ilgs can be created or deleted on this connp, no new ilgs can 3996 * be created or deleted for this connp, on this ill, since this ill 3997 * is the perimeter. So we won't miss any ilg in this cleanup. 3998 */ 3999 mutex_enter(&connp->conn_lock); 4000 4001 /* 4002 * Increment the walker count, so that ilg repacking does not 4003 * occur while we are in the loop. 4004 */ 4005 ILG_WALKER_HOLD(connp); 4006 for (i = connp->conn_ilg_inuse - 1; i >= 0; i--) { 4007 ilg = &connp->conn_ilg[i]; 4008 if (ilg->ilg_ipif != ipif || (ilg->ilg_flags & ILG_DELETED)) 4009 continue; 4010 /* 4011 * ip_close cannot be cleaning this ilg at the same time. 4012 * since it also has to execute in this ill's perimeter which 4013 * we are now holding. Only a clean conn can be condemned. 4014 */ 4015 ASSERT(!(connp->conn_state_flags & CONN_CONDEMNED)); 4016 4017 /* Blow away the membership */ 4018 ip1dbg(("conn_delete_ilg_ipif: %s on %s (%s)\n", 4019 inet_ntop(AF_INET6, &connp->conn_ilg[i].ilg_v6group, 4020 group_buf1, sizeof (group_buf1)), 4021 inet_ntop(AF_INET6, &ipif->ipif_v6lcl_addr, 4022 group_buf2, sizeof (group_buf2)), 4023 ipif->ipif_ill->ill_name)); 4024 4025 /* ilg_ipif is NULL for V6, so we won't be here */ 4026 ASSERT(IN6_IS_ADDR_V4MAPPED(&ilg->ilg_v6group)); 4027 4028 group = V4_PART_OF_V6(ilg->ilg_v6group); 4029 ilg_delete(connp, &connp->conn_ilg[i], NULL); 4030 mutex_exit(&connp->conn_lock); 4031 4032 (void) ip_delmulti(group, ipif, B_FALSE, B_TRUE); 4033 mutex_enter(&connp->conn_lock); 4034 } 4035 4036 /* 4037 * If we are the last walker, need to physically delete the 4038 * ilgs and repack. 4039 */ 4040 ILG_WALKER_RELE(connp); 4041 4042 if (connp->conn_multicast_ipif == ipif) { 4043 /* Revert to late binding */ 4044 connp->conn_multicast_ipif = NULL; 4045 } 4046 mutex_exit(&connp->conn_lock); 4047 4048 conn_delete_ire(connp, (caddr_t)ipif); 4049 } 4050 4051 /* 4052 * Called from ill close by ipcl_walk for clearing conn_ilg and 4053 * conn_multicast_ill for a given ill. conn is held by caller. 4054 * Note that ipcl_walk only walks conns that are not yet condemned. 4055 * condemned conns can't be refheld. For this reason, conn must become clean 4056 * first, i.e. it must not refer to any ill/ire/ipif and then only set 4057 * condemned flag. 4058 */ 4059 static void 4060 conn_delete_ill(conn_t *connp, caddr_t arg) 4061 { 4062 ill_t *ill = (ill_t *)arg; 4063 int i; 4064 char group_buf[INET6_ADDRSTRLEN]; 4065 in6_addr_t v6group; 4066 int orig_ifindex; 4067 ilg_t *ilg; 4068 4069 /* 4070 * Even though conn_ilg_inuse can change while we are in this loop, 4071 * no new ilgs can be created/deleted for this connp, on this 4072 * ill, since this ill is the perimeter. So we won't miss any ilg 4073 * in this cleanup. 4074 */ 4075 mutex_enter(&connp->conn_lock); 4076 4077 /* 4078 * Increment the walker count, so that ilg repacking does not 4079 * occur while we are in the loop. 4080 */ 4081 ILG_WALKER_HOLD(connp); 4082 for (i = connp->conn_ilg_inuse - 1; i >= 0; i--) { 4083 ilg = &connp->conn_ilg[i]; 4084 if ((ilg->ilg_ill == ill) && !(ilg->ilg_flags & ILG_DELETED)) { 4085 /* 4086 * ip_close cannot be cleaning this ilg at the same 4087 * time, since it also has to execute in this ill's 4088 * perimeter which we are now holding. Only a clean 4089 * conn can be condemned. 4090 */ 4091 ASSERT(!(connp->conn_state_flags & CONN_CONDEMNED)); 4092 4093 /* Blow away the membership */ 4094 ip1dbg(("conn_delete_ilg_ill: %s on %s\n", 4095 inet_ntop(AF_INET6, &ilg->ilg_v6group, 4096 group_buf, sizeof (group_buf)), 4097 ill->ill_name)); 4098 4099 v6group = ilg->ilg_v6group; 4100 orig_ifindex = ilg->ilg_orig_ifindex; 4101 ilg_delete(connp, ilg, NULL); 4102 mutex_exit(&connp->conn_lock); 4103 4104 (void) ip_delmulti_v6(&v6group, ill, orig_ifindex, 4105 connp->conn_zoneid, B_FALSE, B_TRUE); 4106 mutex_enter(&connp->conn_lock); 4107 } 4108 } 4109 /* 4110 * If we are the last walker, need to physically delete the 4111 * ilgs and repack. 4112 */ 4113 ILG_WALKER_RELE(connp); 4114 4115 if (connp->conn_multicast_ill == ill) { 4116 /* Revert to late binding */ 4117 connp->conn_multicast_ill = NULL; 4118 connp->conn_orig_multicast_ifindex = 0; 4119 } 4120 mutex_exit(&connp->conn_lock); 4121 } 4122 4123 /* 4124 * Called when an ipif is unplumbed to make sure that there are no 4125 * dangling conn references to that ipif. 4126 * Handles ilg_ipif and conn_multicast_ipif 4127 */ 4128 void 4129 reset_conn_ipif(ipif) 4130 ipif_t *ipif; 4131 { 4132 ip_stack_t *ipst = ipif->ipif_ill->ill_ipst; 4133 4134 ipcl_walk(conn_delete_ipif, (caddr_t)ipif, ipst); 4135 } 4136 4137 /* 4138 * Called when an ill is unplumbed to make sure that there are no 4139 * dangling conn references to that ill. 4140 * Handles ilg_ill, conn_multicast_ill. 4141 */ 4142 void 4143 reset_conn_ill(ill_t *ill) 4144 { 4145 ip_stack_t *ipst = ill->ill_ipst; 4146 4147 ipcl_walk(conn_delete_ill, (caddr_t)ill, ipst); 4148 } 4149 4150 #ifdef DEBUG 4151 /* 4152 * Walk functions walk all the interfaces in the system to make 4153 * sure that there is no refernece to the ipif or ill that is 4154 * going away. 4155 */ 4156 int 4157 ilm_walk_ill(ill_t *ill) 4158 { 4159 int cnt = 0; 4160 ill_t *till; 4161 ilm_t *ilm; 4162 ill_walk_context_t ctx; 4163 ip_stack_t *ipst = ill->ill_ipst; 4164 4165 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 4166 till = ILL_START_WALK_ALL(&ctx, ipst); 4167 for (; till != NULL; till = ill_next(&ctx, till)) { 4168 mutex_enter(&till->ill_lock); 4169 for (ilm = till->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 4170 if (ilm->ilm_ill == ill) { 4171 cnt++; 4172 } 4173 } 4174 mutex_exit(&till->ill_lock); 4175 } 4176 rw_exit(&ipst->ips_ill_g_lock); 4177 4178 return (cnt); 4179 } 4180 4181 /* 4182 * This function is called before the ipif is freed. 4183 */ 4184 int 4185 ilm_walk_ipif(ipif_t *ipif) 4186 { 4187 int cnt = 0; 4188 ill_t *till; 4189 ilm_t *ilm; 4190 ill_walk_context_t ctx; 4191 ip_stack_t *ipst = ipif->ipif_ill->ill_ipst; 4192 4193 till = ILL_START_WALK_ALL(&ctx, ipst); 4194 for (; till != NULL; till = ill_next(&ctx, till)) { 4195 mutex_enter(&till->ill_lock); 4196 for (ilm = till->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 4197 if (ilm->ilm_ipif == ipif) { 4198 cnt++; 4199 } 4200 } 4201 mutex_exit(&till->ill_lock); 4202 } 4203 return (cnt); 4204 } 4205 #endif 4206