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