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