xref: /titanic_52/usr/src/uts/common/inet/sctp/sctp_addr.c (revision 946c3c722d7ae9fdb824ef1e5954d514773792f6)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/stream.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/kmem.h>
34 #include <sys/socket.h>
35 #include <sys/sysmacros.h>
36 #include <sys/list.h>
37 
38 #include <netinet/in.h>
39 #include <netinet/ip6.h>
40 #include <netinet/sctp.h>
41 
42 #include <inet/common.h>
43 #include <inet/ip.h>
44 #include <inet/ip6.h>
45 #include <inet/ip_if.h>
46 #include <inet/ipclassifier.h>
47 #include <inet/sctp_ip.h>
48 #include "sctp_impl.h"
49 #include "sctp_addr.h"
50 
51 static void		sctp_ipif_inactive(sctp_ipif_t *);
52 static sctp_ipif_t	*sctp_lookup_ipif_addr(in6_addr_t *, boolean_t,
53 			    sctp_t *, uint_t);
54 static int		sctp_get_all_ipifs(sctp_t *, int);
55 int			sctp_valid_addr_list(sctp_t *, const void *, uint32_t,
56 			    uchar_t *, size_t);
57 sctp_saddr_ipif_t	*sctp_ipif_lookup(sctp_t *, uint_t);
58 static int		sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int,
59 			    boolean_t dontsrc);
60 static void		sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *);
61 static int		sctp_compare_ipif_list(sctp_ipif_hash_t *,
62 			    sctp_ipif_hash_t *);
63 int			sctp_compare_saddrs(sctp_t *, sctp_t *);
64 static int		sctp_copy_ipifs(sctp_ipif_hash_t *, sctp_t *, int);
65 int			sctp_dup_saddrs(sctp_t *, sctp_t *, int);
66 void			sctp_free_saddrs(sctp_t *);
67 void			sctp_update_ill(ill_t *, int);
68 void			sctp_update_ipif(ipif_t *, int);
69 void			sctp_move_ipif(ipif_t *, ill_t *, ill_t *);
70 void			sctp_del_saddr(sctp_t *, sctp_saddr_ipif_t *);
71 void			sctp_del_saddr_list(sctp_t *, const void *, int,
72 			    boolean_t);
73 sctp_saddr_ipif_t	*sctp_saddr_lookup(sctp_t *, in6_addr_t *, uint_t);
74 in6_addr_t		sctp_get_valid_addr(sctp_t *, boolean_t);
75 int			sctp_getmyaddrs(void *, void *, int *);
76 void			sctp_saddr_init(sctp_stack_t *);
77 void			sctp_saddr_fini(sctp_stack_t *);
78 
79 #define	SCTP_IPIF_USABLE(sctp_ipif_state)	\
80 	((sctp_ipif_state) == SCTP_IPIFS_UP ||	\
81 	(sctp_ipif_state) ==  SCTP_IPIFS_DOWN)
82 
83 #define	SCTP_IPIF_DISCARD(sctp_ipif_flags)	\
84 	((sctp_ipif_flags) & (IPIF_PRIVATE | IPIF_DEPRECATED))
85 
86 #define	SCTP_IS_IPIF_LOOPBACK(ipif)		\
87 	((ipif)->sctp_ipif_ill->sctp_ill_flags & PHYI_LOOPBACK)
88 
89 #define	SCTP_IS_IPIF_LINKLOCAL(ipif)		\
90 	((ipif)->sctp_ipif_isv6 && 		\
91 	IN6_IS_ADDR_LINKLOCAL(&(ipif)->sctp_ipif_saddr))
92 
93 #define	SCTP_UNSUPP_AF(ipif, supp_af)	\
94 	((!(ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V4)) ||	\
95 	((ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V6)))
96 
97 #define	SCTP_IPIF_ZONE_MATCH(sctp, ipif) 				\
98 	IPCL_ZONE_MATCH((sctp)->sctp_connp, (ipif)->sctp_ipif_zoneid)
99 
100 #define	SCTP_ILL_HASH_FN(index)		((index) % SCTP_ILL_HASH)
101 #define	SCTP_IPIF_HASH_FN(seqid)	((seqid) % SCTP_IPIF_HASH)
102 #define	SCTP_ILL_TO_PHYINDEX(ill)	((ill)->ill_phyint->phyint_ifindex)
103 
104 /*
105  *
106  *
107  * SCTP Interface list manipulation functions, locking used.
108  *
109  *
110  */
111 
112 /*
113  * Delete an SCTP IPIF from the list if the refcount goes to 0 and it is
114  * marked as condemned. Also, check if the ILL needs to go away.
115  * Called with no locks held.
116  */
117 static void
118 sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
119 {
120 	sctp_ill_t	*sctp_ill;
121 	uint_t		ipif_index;
122 	uint_t		ill_index;
123 	sctp_stack_t	*sctps = sctp_ipif->sctp_ipif_ill->
124 	    sctp_ill_netstack->netstack_sctp;
125 
126 	rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
127 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
128 
129 	ipif_index = SCTP_IPIF_HASH_FN(sctp_ipif->sctp_ipif_id);
130 	sctp_ill = sctp_ipif->sctp_ipif_ill;
131 	ASSERT(sctp_ill != NULL);
132 	ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index);
133 	if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED ||
134 	    sctp_ipif->sctp_ipif_refcnt != 0) {
135 		rw_exit(&sctps->sctps_g_ipifs_lock);
136 		rw_exit(&sctps->sctps_g_ills_lock);
137 		return;
138 	}
139 	list_remove(&sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
140 	    sctp_ipif);
141 	sctps->sctps_g_ipifs[ipif_index].ipif_count--;
142 	sctps->sctps_g_ipifs_count--;
143 	rw_destroy(&sctp_ipif->sctp_ipif_lock);
144 	kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
145 
146 	(void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1);
147 	if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
148 		rw_downgrade(&sctps->sctps_g_ipifs_lock);
149 		if (sctp_ill->sctp_ill_ipifcnt == 0 &&
150 		    sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
151 			list_remove(&sctps->sctps_g_ills[ill_index].
152 			    sctp_ill_list, (void *)sctp_ill);
153 			sctps->sctps_g_ills[ill_index].ill_count--;
154 			sctps->sctps_ills_count--;
155 			kmem_free(sctp_ill->sctp_ill_name,
156 			    sctp_ill->sctp_ill_name_length);
157 			kmem_free(sctp_ill, sizeof (sctp_ill_t));
158 		}
159 	}
160 	rw_exit(&sctps->sctps_g_ipifs_lock);
161 	rw_exit(&sctps->sctps_g_ills_lock);
162 }
163 
164 /*
165  * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt.
166  * Called with no locks held.
167  */
168 static sctp_ipif_t *
169 sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, sctp_t *sctp,
170     uint_t ifindex)
171 {
172 	int		i;
173 	int		j;
174 	sctp_ipif_t	*sctp_ipif;
175 	sctp_stack_t	*sctps = sctp->sctp_sctps;
176 
177 	ASSERT(sctp->sctp_zoneid != ALL_ZONES);
178 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
179 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
180 		if (sctps->sctps_g_ipifs[i].ipif_count == 0)
181 			continue;
182 		sctp_ipif = list_head(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
183 		for (j = 0; j < sctps->sctps_g_ipifs[i].ipif_count; j++) {
184 			rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
185 			if (SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) &&
186 			    SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) &&
187 			    (ifindex == 0 || ifindex ==
188 			    sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
189 			    IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
190 			    addr)) {
191 				rw_exit(&sctp_ipif->sctp_ipif_lock);
192 				if (refhold)
193 					SCTP_IPIF_REFHOLD(sctp_ipif);
194 				rw_exit(&sctps->sctps_g_ipifs_lock);
195 				return (sctp_ipif);
196 			}
197 			rw_exit(&sctp_ipif->sctp_ipif_lock);
198 			sctp_ipif = list_next(
199 			    &sctps->sctps_g_ipifs[i].sctp_ipif_list, sctp_ipif);
200 		}
201 	}
202 	rw_exit(&sctps->sctps_g_ipifs_lock);
203 	return (NULL);
204 }
205 
206 /*
207  * Populate the list with all the SCTP ipifs for a given ipversion.
208  * Increments sctp_ipif refcnt.
209  * Called with no locks held.
210  */
211 static int
212 sctp_get_all_ipifs(sctp_t *sctp, int sleep)
213 {
214 	sctp_ipif_t		*sctp_ipif;
215 	int			i;
216 	int			j;
217 	int			error = 0;
218 	sctp_stack_t	*sctps = sctp->sctp_sctps;
219 
220 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
221 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
222 		if (sctps->sctps_g_ipifs[i].ipif_count == 0)
223 			continue;
224 		sctp_ipif = list_head(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
225 		for (j = 0; j < sctps->sctps_g_ipifs[i].ipif_count; j++) {
226 			rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
227 			if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
228 			    !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
229 			    !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
230 			    (sctp->sctp_ipversion == IPV4_VERSION &&
231 			    sctp_ipif->sctp_ipif_isv6) ||
232 			    (sctp->sctp_connp->conn_ipv6_v6only &&
233 			    !sctp_ipif->sctp_ipif_isv6)) {
234 				rw_exit(&sctp_ipif->sctp_ipif_lock);
235 				sctp_ipif = list_next(
236 				    &sctps->sctps_g_ipifs[i].sctp_ipif_list,
237 				    sctp_ipif);
238 				continue;
239 			}
240 			rw_exit(&sctp_ipif->sctp_ipif_lock);
241 			SCTP_IPIF_REFHOLD(sctp_ipif);
242 			error = sctp_ipif_hash_insert(sctp, sctp_ipif, sleep,
243 			    B_FALSE);
244 			if (error != 0)
245 				goto free_stuff;
246 			sctp_ipif = list_next(
247 			    &sctps->sctps_g_ipifs[i].sctp_ipif_list,
248 			    sctp_ipif);
249 		}
250 	}
251 	rw_exit(&sctps->sctps_g_ipifs_lock);
252 	return (0);
253 free_stuff:
254 	rw_exit(&sctps->sctps_g_ipifs_lock);
255 	sctp_free_saddrs(sctp);
256 	return (ENOMEM);
257 }
258 
259 /*
260  * Given a list of address, fills in the list of SCTP ipifs if all the addresses
261  * are present in the SCTP interface list, return number of addresses filled
262  * or error. If the caller wants the list of addresses, it sends a pre-allocated
263  * buffer - list. Currently, this list is only used on a clustered node when
264  * the SCTP is in the listen state (from sctp_bind_add()). When called on a
265  * clustered node, the input is always a list of addresses (even if the
266  * original bind() was to INADDR_ANY).
267  * Called with no locks held.
268  */
269 int
270 sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt,
271     uchar_t *list, size_t lsize)
272 {
273 	struct sockaddr_in	*sin4;
274 	struct sockaddr_in6	*sin6;
275 	struct in_addr		*addr4;
276 	in6_addr_t		addr;
277 	int			cnt;
278 	int			err = 0;
279 	int			saddr_cnt = 0;
280 	sctp_ipif_t		*ipif;
281 	boolean_t		bind_to_all = B_FALSE;
282 	boolean_t		check_addrs = B_FALSE;
283 	boolean_t		check_lport = B_FALSE;
284 	uchar_t			*p = list;
285 
286 	/*
287 	 * Need to check for port and address depending on the state.
288 	 * After a socket is bound, we need to make sure that subsequent
289 	 * bindx() has correct port.  After an association is established,
290 	 * we need to check for changing the bound address to invalid
291 	 * addresses.
292 	 */
293 	if (sctp->sctp_state >= SCTPS_BOUND) {
294 		check_lport = B_TRUE;
295 		if (sctp->sctp_state > SCTPS_LISTEN)
296 			check_addrs = B_TRUE;
297 	}
298 
299 	if (sctp->sctp_conn_tfp != NULL)
300 		mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
301 	if (sctp->sctp_listen_tfp != NULL)
302 		mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
303 	for (cnt = 0; cnt < addrcnt; cnt++) {
304 		boolean_t	lookup_saddr = B_TRUE;
305 		uint_t		ifindex = 0;
306 
307 		switch (sctp->sctp_family) {
308 		case AF_INET:
309 			sin4 = (struct sockaddr_in *)addrs + cnt;
310 			if (sin4->sin_family != AF_INET || (check_lport &&
311 			    sin4->sin_port != sctp->sctp_lport)) {
312 				err = EINVAL;
313 				goto free_ret;
314 			}
315 			addr4 = &sin4->sin_addr;
316 			if (check_addrs &&
317 			    (addr4->s_addr == INADDR_ANY ||
318 			    addr4->s_addr == INADDR_BROADCAST ||
319 			    IN_MULTICAST(addr4->s_addr))) {
320 				err = EINVAL;
321 				goto free_ret;
322 			}
323 			IN6_INADDR_TO_V4MAPPED(addr4, &addr);
324 			if (!check_addrs && addr4->s_addr == INADDR_ANY) {
325 				lookup_saddr = B_FALSE;
326 				bind_to_all = B_TRUE;
327 			}
328 
329 			break;
330 		case AF_INET6:
331 			sin6 = (struct sockaddr_in6 *)addrs + cnt;
332 			if (sin6->sin6_family != AF_INET6 || (check_lport &&
333 			    sin6->sin6_port != sctp->sctp_lport)) {
334 				err = EINVAL;
335 				goto free_ret;
336 			}
337 			addr = sin6->sin6_addr;
338 			/* Contains the interface index */
339 			ifindex = sin6->sin6_scope_id;
340 			if (sctp->sctp_connp->conn_ipv6_v6only &&
341 			    IN6_IS_ADDR_V4MAPPED(&addr)) {
342 				err = EAFNOSUPPORT;
343 				goto free_ret;
344 			}
345 			if (check_addrs &&
346 			    (IN6_IS_ADDR_LINKLOCAL(&addr) ||
347 			    IN6_IS_ADDR_MULTICAST(&addr) ||
348 			    IN6_IS_ADDR_UNSPECIFIED(&addr))) {
349 				err = EINVAL;
350 				goto free_ret;
351 			}
352 			if (!check_addrs && IN6_IS_ADDR_UNSPECIFIED(&addr)) {
353 				lookup_saddr = B_FALSE;
354 				bind_to_all = B_TRUE;
355 			}
356 
357 			break;
358 		default:
359 			err = EAFNOSUPPORT;
360 			goto free_ret;
361 		}
362 		if (lookup_saddr) {
363 			ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, sctp,
364 			    ifindex);
365 			if (ipif == NULL) {
366 				/* Address not in the list */
367 				err = EINVAL;
368 				goto free_ret;
369 			} else if (check_addrs && SCTP_IS_IPIF_LOOPBACK(ipif) &&
370 			    cl_sctp_check_addrs == NULL) {
371 				SCTP_IPIF_REFRELE(ipif);
372 				err = EINVAL;
373 				goto free_ret;
374 			}
375 		}
376 		if (!bind_to_all) {
377 			/*
378 			 * If an address is added after association setup,
379 			 * we need to wait for the peer to send us an ASCONF
380 			 * ACK before we can start using it.
381 			 * saddr_ipif_dontsrc will be reset (to 0) when we
382 			 * get the ASCONF ACK for this address.
383 			 */
384 			err = sctp_ipif_hash_insert(sctp, ipif, KM_SLEEP,
385 			    check_addrs ? B_TRUE : B_FALSE);
386 			if (err != 0) {
387 				SCTP_IPIF_REFRELE(ipif);
388 				if (check_addrs && err == EALREADY)
389 					err = EADDRINUSE;
390 				goto free_ret;
391 			}
392 			saddr_cnt++;
393 			if (lsize >= sizeof (addr)) {
394 				bcopy(&addr, p, sizeof (addr));
395 				p += sizeof (addr);
396 				lsize -= sizeof (addr);
397 			}
398 		}
399 	}
400 	if (bind_to_all) {
401 		/*
402 		 * Free whatever we might have added before encountering
403 		 * inaddr_any.
404 		 */
405 		if (sctp->sctp_nsaddrs > 0) {
406 			sctp_free_saddrs(sctp);
407 			ASSERT(sctp->sctp_nsaddrs == 0);
408 		}
409 		err = sctp_get_all_ipifs(sctp, KM_SLEEP);
410 		if (err != 0)
411 			return (err);
412 		sctp->sctp_bound_to_all = 1;
413 	}
414 	if (sctp->sctp_listen_tfp != NULL)
415 		mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
416 	if (sctp->sctp_conn_tfp != NULL)
417 		mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
418 	return (0);
419 free_ret:
420 	if (saddr_cnt != 0)
421 		sctp_del_saddr_list(sctp, addrs, saddr_cnt, B_TRUE);
422 	if (sctp->sctp_listen_tfp != NULL)
423 		mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
424 	if (sctp->sctp_conn_tfp != NULL)
425 		mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
426 	return (err);
427 }
428 
429 sctp_saddr_ipif_t *
430 sctp_ipif_lookup(sctp_t *sctp, uint_t ipif_index)
431 {
432 	int			cnt;
433 	int			seqid = SCTP_IPIF_HASH_FN(ipif_index);
434 	sctp_saddr_ipif_t	*ipif_obj;
435 
436 	if (sctp->sctp_saddrs[seqid].ipif_count == 0)
437 		return (NULL);
438 
439 	ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
440 	for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
441 		if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif_index)
442 			return (ipif_obj);
443 		ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
444 		    ipif_obj);
445 	}
446 	return (NULL);
447 }
448 
449 static int
450 sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep,
451     boolean_t dontsrc)
452 {
453 	int			cnt;
454 	sctp_saddr_ipif_t	*ipif_obj;
455 	int			seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id);
456 
457 	ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
458 	for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
459 		if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id)
460 			return (EALREADY);
461 		ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
462 		    ipif_obj);
463 	}
464 	ipif_obj = kmem_zalloc(sizeof (sctp_saddr_ipif_t), sleep);
465 	if (ipif_obj == NULL) {
466 		/* Need to do something */
467 		return (ENOMEM);
468 	}
469 	ipif_obj->saddr_ipifp = ipif;
470 	ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0;
471 	list_insert_tail(&sctp->sctp_saddrs[seqid].sctp_ipif_list, ipif_obj);
472 	sctp->sctp_saddrs[seqid].ipif_count++;
473 	sctp->sctp_nsaddrs++;
474 	return (0);
475 }
476 
477 static void
478 sctp_ipif_hash_remove(sctp_t *sctp, sctp_ipif_t *ipif)
479 {
480 	int			cnt;
481 	sctp_saddr_ipif_t	*ipif_obj;
482 	int			seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id);
483 
484 	ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list);
485 	for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) {
486 		if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id) {
487 			list_remove(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
488 			    ipif_obj);
489 			sctp->sctp_nsaddrs--;
490 			sctp->sctp_saddrs[seqid].ipif_count--;
491 			SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp);
492 			kmem_free(ipif_obj, sizeof (sctp_saddr_ipif_t));
493 			break;
494 		}
495 		ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list,
496 		    ipif_obj);
497 	}
498 }
499 
500 static int
501 sctp_compare_ipif_list(sctp_ipif_hash_t *list1, sctp_ipif_hash_t *list2)
502 {
503 	int			i;
504 	int			j;
505 	sctp_saddr_ipif_t	*obj1;
506 	sctp_saddr_ipif_t	*obj2;
507 	int			overlap = 0;
508 
509 	obj1 = list_head(&list1->sctp_ipif_list);
510 	for (i = 0; i < list1->ipif_count; i++) {
511 		obj2 = list_head(&list2->sctp_ipif_list);
512 		for (j = 0; j < list2->ipif_count; j++) {
513 			if (obj1->saddr_ipifp->sctp_ipif_id ==
514 			    obj2->saddr_ipifp->sctp_ipif_id) {
515 				overlap++;
516 				break;
517 			}
518 			obj2 = list_next(&list2->sctp_ipif_list,
519 			    obj2);
520 		}
521 		obj1 = list_next(&list1->sctp_ipif_list, obj1);
522 	}
523 	return (overlap);
524 }
525 
526 int
527 sctp_compare_saddrs(sctp_t *sctp1, sctp_t *sctp2)
528 {
529 	int		i;
530 	int		overlap = 0;
531 
532 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
533 		overlap += sctp_compare_ipif_list(&sctp1->sctp_saddrs[i],
534 		    &sctp2->sctp_saddrs[i]);
535 	}
536 
537 	if (sctp1->sctp_nsaddrs == sctp2->sctp_nsaddrs &&
538 	    overlap == sctp1->sctp_nsaddrs) {
539 		return (SCTP_ADDR_EQUAL);
540 	}
541 
542 	if (overlap == sctp1->sctp_nsaddrs)
543 		return (SCTP_ADDR_SUBSET);
544 
545 	if (overlap > 0)
546 		return (SCTP_ADDR_OVERLAP);
547 
548 	return (SCTP_ADDR_DISJOINT);
549 }
550 
551 static int
552 sctp_copy_ipifs(sctp_ipif_hash_t *list1, sctp_t *sctp2, int sleep)
553 {
554 	int			i;
555 	sctp_saddr_ipif_t	*obj;
556 	int			error = 0;
557 
558 	obj = list_head(&list1->sctp_ipif_list);
559 	for (i = 0; i < list1->ipif_count; i++) {
560 		SCTP_IPIF_REFHOLD(obj->saddr_ipifp);
561 		error = sctp_ipif_hash_insert(sctp2, obj->saddr_ipifp, sleep,
562 		    B_FALSE);
563 		if (error != 0)
564 			return (error);
565 		obj = list_next(&list1->sctp_ipif_list, obj);
566 	}
567 	return (error);
568 }
569 
570 int
571 sctp_dup_saddrs(sctp_t *sctp1, sctp_t *sctp2, int sleep)
572 {
573 	int	error = 0;
574 	int	i;
575 
576 	if (sctp1 == NULL || sctp1->sctp_bound_to_all == 1)
577 		return (sctp_get_all_ipifs(sctp2, sleep));
578 
579 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
580 		if (sctp1->sctp_saddrs[i].ipif_count == 0)
581 			continue;
582 		error = sctp_copy_ipifs(&sctp1->sctp_saddrs[i], sctp2, sleep);
583 		if (error != 0) {
584 			sctp_free_saddrs(sctp2);
585 			return (error);
586 		}
587 	}
588 	return (0);
589 }
590 
591 void
592 sctp_free_saddrs(sctp_t *sctp)
593 {
594 	int			i;
595 	int			l;
596 	sctp_saddr_ipif_t	*obj;
597 
598 	if (sctp->sctp_nsaddrs == 0)
599 		return;
600 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
601 		if (sctp->sctp_saddrs[i].ipif_count == 0)
602 			continue;
603 		obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list);
604 		for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
605 			list_remove(&sctp->sctp_saddrs[i].sctp_ipif_list, obj);
606 			SCTP_IPIF_REFRELE(obj->saddr_ipifp);
607 			sctp->sctp_nsaddrs--;
608 			kmem_free(obj, sizeof (sctp_saddr_ipif_t));
609 			obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list);
610 		}
611 		sctp->sctp_saddrs[i].ipif_count = 0;
612 	}
613 	if (sctp->sctp_bound_to_all == 1)
614 		sctp->sctp_bound_to_all = 0;
615 	ASSERT(sctp->sctp_nsaddrs == 0);
616 }
617 
618 /*
619  * Add/Delete the given ILL from the SCTP ILL list. Called with no locks
620  * held.
621  */
622 void
623 sctp_update_ill(ill_t *ill, int op)
624 {
625 	int		i;
626 	sctp_ill_t	*sctp_ill = NULL;
627 	uint_t		index;
628 	netstack_t	*ns = ill->ill_ipst->ips_netstack;
629 	sctp_stack_t	*sctps = ns->netstack_sctp;
630 
631 	ip2dbg(("sctp_update_ill: %s\n", ill->ill_name));
632 
633 	rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER);
634 
635 	index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
636 	sctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
637 	for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
638 		if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
639 			break;
640 		sctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
641 		    sctp_ill);
642 	}
643 
644 	switch (op) {
645 	case SCTP_ILL_INSERT:
646 		if (sctp_ill != NULL) {
647 			/* Unmark it if it is condemned */
648 			if (sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED)
649 				sctp_ill->sctp_ill_state = 0;
650 			rw_exit(&sctps->sctps_g_ills_lock);
651 			return;
652 		}
653 		sctp_ill = kmem_zalloc(sizeof (sctp_ill_t), KM_NOSLEEP);
654 		/* Need to re-try? */
655 		if (sctp_ill == NULL) {
656 			ip1dbg(("sctp_ill_insert: mem error..\n"));
657 			rw_exit(&sctps->sctps_g_ills_lock);
658 			return;
659 		}
660 		sctp_ill->sctp_ill_name =
661 		    kmem_zalloc(ill->ill_name_length, KM_NOSLEEP);
662 		if (sctp_ill->sctp_ill_name == NULL) {
663 			ip1dbg(("sctp_ill_insert: mem error..\n"));
664 			kmem_free(sctp_ill, sizeof (sctp_ill_t));
665 			rw_exit(&sctps->sctps_g_ills_lock);
666 			return;
667 		}
668 		bcopy(ill->ill_name, sctp_ill->sctp_ill_name,
669 		    ill->ill_name_length);
670 		sctp_ill->sctp_ill_name_length = ill->ill_name_length;
671 		sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill);
672 		sctp_ill->sctp_ill_flags = ill->ill_phyint->phyint_flags;
673 		sctp_ill->sctp_ill_netstack = ns;	/* No netstack_hold */
674 		list_insert_tail(&sctps->sctps_g_ills[index].sctp_ill_list,
675 		    (void *)sctp_ill);
676 		sctps->sctps_g_ills[index].ill_count++;
677 		sctps->sctps_ills_count++;
678 
679 		break;
680 
681 	case SCTP_ILL_REMOVE:
682 
683 		if (sctp_ill == NULL) {
684 			rw_exit(&sctps->sctps_g_ills_lock);
685 			return;
686 		}
687 		if (sctp_ill->sctp_ill_ipifcnt == 0) {
688 			list_remove(&sctps->sctps_g_ills[index].sctp_ill_list,
689 			    (void *)sctp_ill);
690 			sctps->sctps_g_ills[index].ill_count--;
691 			sctps->sctps_ills_count--;
692 			kmem_free(sctp_ill->sctp_ill_name,
693 			    ill->ill_name_length);
694 			kmem_free(sctp_ill, sizeof (sctp_ill_t));
695 		} else {
696 			sctp_ill->sctp_ill_state = SCTP_ILLS_CONDEMNED;
697 		}
698 
699 		break;
700 	}
701 	rw_exit(&sctps->sctps_g_ills_lock);
702 }
703 
704 /* move ipif from f_ill to t_ill */
705 void
706 sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
707 {
708 	sctp_ill_t	*fsctp_ill = NULL;
709 	sctp_ill_t	*tsctp_ill = NULL;
710 	sctp_ipif_t	*sctp_ipif;
711 	uint_t		index;
712 	int		i;
713 	netstack_t	*ns = ipif->ipif_ill->ill_ipst->ips_netstack;
714 	sctp_stack_t	*sctps = ns->netstack_sctp;
715 
716 	rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
717 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
718 
719 	index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill));
720 	fsctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
721 	for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
722 		if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill))
723 			break;
724 		fsctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
725 		    fsctp_ill);
726 	}
727 
728 	index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill));
729 	tsctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
730 	for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
731 		if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill))
732 			break;
733 		tsctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
734 		    tsctp_ill);
735 	}
736 
737 	index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid);
738 	sctp_ipif = list_head(&sctps->sctps_g_ipifs[index].sctp_ipif_list);
739 	for (i = 0; i < sctps->sctps_g_ipifs[index].ipif_count; i++) {
740 		if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
741 			break;
742 		sctp_ipif = list_next(
743 		    &sctps->sctps_g_ipifs[index].sctp_ipif_list, sctp_ipif);
744 	}
745 	/* Should be an ASSERT? */
746 	if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) {
747 		ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n",
748 		    (void *)ipif, (void *)f_ill, (void *)t_ill));
749 		rw_exit(&sctps->sctps_g_ipifs_lock);
750 		rw_exit(&sctps->sctps_g_ills_lock);
751 		return;
752 	}
753 	rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
754 	ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill);
755 	sctp_ipif->sctp_ipif_ill = tsctp_ill;
756 	rw_exit(&sctp_ipif->sctp_ipif_lock);
757 	(void) atomic_add_32_nv(&fsctp_ill->sctp_ill_ipifcnt, -1);
758 	atomic_add_32(&tsctp_ill->sctp_ill_ipifcnt, 1);
759 	rw_exit(&sctps->sctps_g_ipifs_lock);
760 	rw_exit(&sctps->sctps_g_ills_lock);
761 }
762 
763 /* Insert, Remove,  Mark up or Mark down the ipif */
764 void
765 sctp_update_ipif(ipif_t *ipif, int op)
766 {
767 	ill_t		*ill = ipif->ipif_ill;
768 	int		i;
769 	sctp_ill_t	*sctp_ill;
770 	sctp_ipif_t	*sctp_ipif;
771 	uint_t		ill_index;
772 	uint_t		ipif_index;
773 	netstack_t	*ns = ipif->ipif_ill->ill_ipst->ips_netstack;
774 	sctp_stack_t	*sctps = ns->netstack_sctp;
775 
776 	ip2dbg(("sctp_update_ipif: %s %d\n", ill->ill_name, ipif->ipif_seqid));
777 
778 	rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
779 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
780 
781 	ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
782 	sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
783 	for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
784 		if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill))
785 			break;
786 		sctp_ill = list_next(
787 		    &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
788 	}
789 	if (sctp_ill == NULL) {
790 		rw_exit(&sctps->sctps_g_ipifs_lock);
791 		rw_exit(&sctps->sctps_g_ills_lock);
792 		return;
793 	}
794 
795 	ipif_index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid);
796 	sctp_ipif = list_head(&sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list);
797 	for (i = 0; i < sctps->sctps_g_ipifs[ipif_index].ipif_count; i++) {
798 		if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
799 			break;
800 		sctp_ipif = list_next(
801 		    &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
802 		    sctp_ipif);
803 	}
804 	if (op != SCTP_IPIF_INSERT && sctp_ipif == NULL) {
805 		ip1dbg(("sctp_update_ipif: null sctp_ipif for %d\n", op));
806 		rw_exit(&sctps->sctps_g_ipifs_lock);
807 		rw_exit(&sctps->sctps_g_ills_lock);
808 		return;
809 	}
810 #ifdef	DEBUG
811 	if (sctp_ipif != NULL)
812 		ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
813 #endif
814 	switch (op) {
815 	case SCTP_IPIF_INSERT:
816 		if (sctp_ipif != NULL) {
817 			if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED)
818 				sctp_ipif->sctp_ipif_state = SCTP_IPIFS_INVALID;
819 			rw_exit(&sctps->sctps_g_ipifs_lock);
820 			rw_exit(&sctps->sctps_g_ills_lock);
821 			return;
822 		}
823 		sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
824 		/* Try again? */
825 		if (sctp_ipif == NULL) {
826 			ip1dbg(("sctp_ipif_insert: mem failure..\n"));
827 			rw_exit(&sctps->sctps_g_ipifs_lock);
828 			rw_exit(&sctps->sctps_g_ills_lock);
829 			return;
830 		}
831 		sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
832 		sctp_ipif->sctp_ipif_ill = sctp_ill;
833 		sctp_ipif->sctp_ipif_state = SCTP_IPIFS_INVALID;
834 		sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
835 		sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
836 		sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
837 		sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
838 		rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
839 		list_insert_tail(
840 		    &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list,
841 		    (void *)sctp_ipif);
842 		sctps->sctps_g_ipifs[ipif_index].ipif_count++;
843 		sctps->sctps_g_ipifs_count++;
844 		atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1);
845 
846 		break;
847 
848 	case SCTP_IPIF_REMOVE:
849 	{
850 		list_t		*ipif_list;
851 		list_t		*ill_list;
852 
853 		ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list;
854 		ipif_list = &sctps->sctps_g_ipifs[ipif_index].sctp_ipif_list;
855 		if (sctp_ipif->sctp_ipif_refcnt != 0) {
856 			sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
857 			rw_exit(&sctps->sctps_g_ipifs_lock);
858 			rw_exit(&sctps->sctps_g_ills_lock);
859 			return;
860 		}
861 		list_remove(ipif_list, (void *)sctp_ipif);
862 		sctps->sctps_g_ipifs[ipif_index].ipif_count--;
863 		sctps->sctps_g_ipifs_count--;
864 		rw_destroy(&sctp_ipif->sctp_ipif_lock);
865 		kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
866 		(void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1);
867 		if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
868 			rw_downgrade(&sctps->sctps_g_ipifs_lock);
869 			if (sctp_ill->sctp_ill_ipifcnt == 0 &&
870 			    sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
871 				list_remove(ill_list, (void *)sctp_ill);
872 				sctps->sctps_ills_count--;
873 				sctps->sctps_g_ills[ill_index].ill_count--;
874 				kmem_free(sctp_ill->sctp_ill_name,
875 				    sctp_ill->sctp_ill_name_length);
876 				kmem_free(sctp_ill, sizeof (sctp_ill_t));
877 			}
878 		}
879 		break;
880 	}
881 
882 	case SCTP_IPIF_UP:
883 
884 		rw_downgrade(&sctps->sctps_g_ipifs_lock);
885 		rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
886 		sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
887 		sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
888 		sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
889 		sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
890 		rw_exit(&sctp_ipif->sctp_ipif_lock);
891 
892 		break;
893 
894 	case SCTP_IPIF_UPDATE:
895 
896 		rw_downgrade(&sctps->sctps_g_ipifs_lock);
897 		rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
898 		sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu;
899 		sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
900 		sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
901 		sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
902 		rw_exit(&sctp_ipif->sctp_ipif_lock);
903 
904 		break;
905 
906 	case SCTP_IPIF_DOWN:
907 
908 		rw_downgrade(&sctps->sctps_g_ipifs_lock);
909 		rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
910 		sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
911 		rw_exit(&sctp_ipif->sctp_ipif_lock);
912 
913 		break;
914 	}
915 	rw_exit(&sctps->sctps_g_ipifs_lock);
916 	rw_exit(&sctps->sctps_g_ills_lock);
917 }
918 
919 /*
920  *
921  *
922  * SCTP source address list manipulaton, locking not used (except for
923  * sctp locking by the caller.
924  *
925  *
926  */
927 
928 /* Remove a specific saddr from the list */
929 void
930 sctp_del_saddr(sctp_t *sctp, sctp_saddr_ipif_t *sp)
931 {
932 	if (sctp->sctp_conn_tfp != NULL)
933 		mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
934 
935 	if (sctp->sctp_listen_tfp != NULL)
936 		mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
937 
938 	sctp_ipif_hash_remove(sctp, sp->saddr_ipifp);
939 
940 	if (sctp->sctp_bound_to_all == 1)
941 		sctp->sctp_bound_to_all = 0;
942 
943 	if (sctp->sctp_conn_tfp != NULL)
944 		mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
945 
946 	if (sctp->sctp_listen_tfp != NULL)
947 		mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
948 }
949 
950 /*
951  * Delete source address from the existing list. No error checking done here
952  * Called with no locks held.
953  */
954 void
955 sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt,
956     boolean_t fanout_locked)
957 {
958 	struct sockaddr_in	*sin4;
959 	struct sockaddr_in6	*sin6;
960 	int			cnt;
961 	in6_addr_t		addr;
962 	sctp_ipif_t		*sctp_ipif;
963 	int			ifindex = 0;
964 
965 	ASSERT(sctp->sctp_nsaddrs >= addcnt);
966 
967 	if (!fanout_locked) {
968 		if (sctp->sctp_conn_tfp != NULL)
969 			mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
970 		if (sctp->sctp_listen_tfp != NULL)
971 			mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
972 	}
973 
974 	for (cnt = 0; cnt < addcnt; cnt++) {
975 		switch (sctp->sctp_family) {
976 		case AF_INET:
977 			sin4 = (struct sockaddr_in *)addrs + cnt;
978 			IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &addr);
979 			break;
980 
981 		case AF_INET6:
982 			sin6 = (struct sockaddr_in6 *)addrs + cnt;
983 			addr = sin6->sin6_addr;
984 			ifindex = sin6->sin6_scope_id;
985 			break;
986 		}
987 		sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, sctp,
988 		    ifindex);
989 		ASSERT(sctp_ipif != NULL);
990 		sctp_ipif_hash_remove(sctp, sctp_ipif);
991 	}
992 	if (sctp->sctp_bound_to_all == 1)
993 		sctp->sctp_bound_to_all = 0;
994 
995 	if (!fanout_locked) {
996 		if (sctp->sctp_conn_tfp != NULL)
997 			mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
998 		if (sctp->sctp_listen_tfp != NULL)
999 			mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
1000 	}
1001 }
1002 
1003 /*
1004  * Given an address get the corresponding entry from the list
1005  * Called with no locks held.
1006  */
1007 sctp_saddr_ipif_t *
1008 sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex)
1009 {
1010 	sctp_saddr_ipif_t	*saddr_ipifs;
1011 	sctp_ipif_t		*sctp_ipif;
1012 
1013 	sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp, ifindex);
1014 	if (sctp_ipif == NULL)
1015 		return (NULL);
1016 
1017 	saddr_ipifs = sctp_ipif_lookup(sctp, sctp_ipif->sctp_ipif_id);
1018 	return (saddr_ipifs);
1019 }
1020 
1021 /* Given an address, add it to the source address list */
1022 int
1023 sctp_saddr_add_addr(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex)
1024 {
1025 	sctp_ipif_t		*sctp_ipif;
1026 
1027 	sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp, ifindex);
1028 	if (sctp_ipif == NULL)
1029 		return (EINVAL);
1030 
1031 	if (sctp_ipif_hash_insert(sctp, sctp_ipif, KM_NOSLEEP, B_FALSE) != 0) {
1032 		SCTP_IPIF_REFRELE(sctp_ipif);
1033 		return (EINVAL);
1034 	}
1035 	return (0);
1036 }
1037 
1038 /*
1039  * Remove or mark as dontsrc addresses that are currently not part of the
1040  * association. One would delete addresses when processing an INIT and
1041  * mark as dontsrc when processing an INIT-ACK.
1042  */
1043 void
1044 sctp_check_saddr(sctp_t *sctp, int supp_af, boolean_t delete)
1045 {
1046 	int			i;
1047 	int			l;
1048 	sctp_saddr_ipif_t	*obj;
1049 	int			scanned = 0;
1050 	int			naddr;
1051 	int			nsaddr;
1052 
1053 	ASSERT(!sctp->sctp_loopback && !sctp->sctp_linklocal && supp_af != 0);
1054 
1055 	/*
1056 	 * Irregardless of the supported address in the INIT, v4
1057 	 * must be supported.
1058 	 */
1059 	if (sctp->sctp_family == AF_INET)
1060 		supp_af = PARM_SUPP_V4;
1061 
1062 	nsaddr = sctp->sctp_nsaddrs;
1063 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1064 		if (sctp->sctp_saddrs[i].ipif_count == 0)
1065 			continue;
1066 		obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1067 		naddr = sctp->sctp_saddrs[i].ipif_count;
1068 		for (l = 0; l < naddr; l++) {
1069 			sctp_ipif_t	*ipif;
1070 
1071 			ipif = obj->saddr_ipifp;
1072 			scanned++;
1073 
1074 			/*
1075 			 * Delete/mark dontsrc loopback/linklocal addresses and
1076 			 * unsupported address.
1077 			 * On a clustered node, we trust the clustering module
1078 			 * to do the right thing w.r.t loopback addresses, so
1079 			 * we ignore loopback addresses in this check.
1080 			 */
1081 			if ((SCTP_IS_IPIF_LOOPBACK(ipif) &&
1082 			    cl_sctp_check_addrs == NULL) ||
1083 			    SCTP_IS_IPIF_LINKLOCAL(ipif) ||
1084 			    SCTP_UNSUPP_AF(ipif, supp_af)) {
1085 				if (!delete) {
1086 					obj->saddr_ipif_unconfirmed = 1;
1087 					goto next_obj;
1088 				}
1089 				if (sctp->sctp_bound_to_all == 1)
1090 					sctp->sctp_bound_to_all = 0;
1091 				if (scanned < nsaddr) {
1092 					obj = list_next(&sctp->sctp_saddrs[i].
1093 					    sctp_ipif_list, obj);
1094 					sctp_ipif_hash_remove(sctp, ipif);
1095 					continue;
1096 				}
1097 				sctp_ipif_hash_remove(sctp, ipif);
1098 			}
1099 	next_obj:
1100 			if (scanned >= nsaddr)
1101 				return;
1102 			obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1103 			    obj);
1104 		}
1105 	}
1106 }
1107 
1108 
1109 /* Get the first valid address from the list. Called with no locks held */
1110 in6_addr_t
1111 sctp_get_valid_addr(sctp_t *sctp, boolean_t isv6)
1112 {
1113 	int			i;
1114 	int			l;
1115 	sctp_saddr_ipif_t	*obj;
1116 	int			scanned = 0;
1117 	in6_addr_t		addr;
1118 
1119 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1120 		if (sctp->sctp_saddrs[i].ipif_count == 0)
1121 			continue;
1122 		obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1123 		for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
1124 			sctp_ipif_t	*ipif;
1125 
1126 			ipif = obj->saddr_ipifp;
1127 			if (!SCTP_DONT_SRC(obj) &&
1128 			    ipif->sctp_ipif_isv6 == isv6 &&
1129 			    ipif->sctp_ipif_state == SCTP_IPIFS_UP) {
1130 				return (ipif->sctp_ipif_saddr);
1131 			}
1132 			scanned++;
1133 			if (scanned >= sctp->sctp_nsaddrs)
1134 				goto got_none;
1135 			obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1136 			    obj);
1137 		}
1138 	}
1139 got_none:
1140 	/* Need to double check this */
1141 	if (isv6 == B_TRUE)
1142 		addr =  ipv6_all_zeros;
1143 	else
1144 		IN6_IPADDR_TO_V4MAPPED(0, &addr);
1145 
1146 	return (addr);
1147 }
1148 
1149 /*
1150  * Return the list of local addresses of an association.  The parameter
1151  * myaddrs is supposed to be either (struct sockaddr_in *) or (struct
1152  * sockaddr_in6 *) depending on the address family.
1153  */
1154 int
1155 sctp_getmyaddrs(void *conn, void *myaddrs, int *addrcnt)
1156 {
1157 	int			i;
1158 	int			l;
1159 	sctp_saddr_ipif_t	*obj;
1160 	sctp_t			*sctp = (sctp_t *)conn;
1161 	int			family = sctp->sctp_family;
1162 	int			max = *addrcnt;
1163 	size_t			added = 0;
1164 	struct sockaddr_in6	*sin6;
1165 	struct sockaddr_in	*sin4;
1166 	int			scanned = 0;
1167 	boolean_t		skip_lback = B_FALSE;
1168 
1169 	if (sctp->sctp_nsaddrs == 0)
1170 		return (EINVAL);
1171 
1172 	/*
1173 	 * Skip loopback addresses for non-loopback assoc., ignore
1174 	 * this on a clustered node.
1175 	 */
1176 	if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback &&
1177 	    (cl_sctp_check_addrs == NULL)) {
1178 		skip_lback = B_TRUE;
1179 	}
1180 
1181 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1182 		if (sctp->sctp_saddrs[i].ipif_count == 0)
1183 			continue;
1184 		obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1185 		for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
1186 			sctp_ipif_t	*ipif = obj->saddr_ipifp;
1187 			in6_addr_t	addr = ipif->sctp_ipif_saddr;
1188 
1189 			scanned++;
1190 			if ((ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) ||
1191 			    SCTP_DONT_SRC(obj) ||
1192 			    (SCTP_IS_IPIF_LOOPBACK(ipif) && skip_lback)) {
1193 				if (scanned >= sctp->sctp_nsaddrs)
1194 					goto done;
1195 				obj = list_next(&sctp->sctp_saddrs[i].
1196 				    sctp_ipif_list, obj);
1197 				continue;
1198 			}
1199 			switch (family) {
1200 			case AF_INET:
1201 				sin4 = (struct sockaddr_in *)myaddrs + added;
1202 				sin4->sin_family = AF_INET;
1203 				sin4->sin_port = sctp->sctp_lport;
1204 				IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1205 				break;
1206 
1207 			case AF_INET6:
1208 				sin6 = (struct sockaddr_in6 *)myaddrs + added;
1209 				sin6->sin6_family = AF_INET6;
1210 				sin6->sin6_port = sctp->sctp_lport;
1211 				sin6->sin6_addr = addr;
1212 				break;
1213 			}
1214 			added++;
1215 			if (added >= max || scanned >= sctp->sctp_nsaddrs)
1216 				goto done;
1217 			obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1218 			    obj);
1219 		}
1220 	}
1221 done:
1222 	*addrcnt = added;
1223 	return (0);
1224 }
1225 
1226 /*
1227  * Given the supported address family, walk through the source address list
1228  * and return the total length of the available addresses. If 'p' is not
1229  * null, construct the parameter list for the addresses in 'p'.
1230  * 'modify' will only be set when we want the source address list to
1231  * be modified. The source address list will be modified only when
1232  * generating an INIT chunk. For generating an INIT-ACK 'modify' will
1233  * be false since the 'sctp' will be that of the listener.
1234  */
1235 size_t
1236 sctp_saddr_info(sctp_t *sctp, int supp_af, uchar_t *p, boolean_t modify)
1237 {
1238 	int			i;
1239 	int			l;
1240 	sctp_saddr_ipif_t	*obj;
1241 	size_t			paramlen = 0;
1242 	sctp_parm_hdr_t		*hdr;
1243 	int			scanned = 0;
1244 	int			naddr;
1245 	int			nsaddr;
1246 	boolean_t		del_ll = B_FALSE;
1247 	boolean_t		del_lb = B_FALSE;
1248 
1249 
1250 	/*
1251 	 * On a clustered node don't bother changing anything
1252 	 * on the loopback interface.
1253 	 */
1254 	if (modify && !sctp->sctp_loopback && (cl_sctp_check_addrs == NULL))
1255 		del_lb = B_TRUE;
1256 
1257 	if (modify && !sctp->sctp_linklocal)
1258 		del_ll = B_TRUE;
1259 
1260 	nsaddr = sctp->sctp_nsaddrs;
1261 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1262 		if (sctp->sctp_saddrs[i].ipif_count == 0)
1263 			continue;
1264 		obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1265 		naddr = sctp->sctp_saddrs[i].ipif_count;
1266 		for (l = 0; l < naddr; l++) {
1267 			in6_addr_t	addr;
1268 			sctp_ipif_t	*ipif;
1269 			boolean_t	ipif_lb;
1270 			boolean_t	ipif_ll;
1271 			boolean_t	unsupp_af;
1272 
1273 			ipif = obj->saddr_ipifp;
1274 			scanned++;
1275 
1276 			ipif_lb = SCTP_IS_IPIF_LOOPBACK(ipif);
1277 			ipif_ll = SCTP_IS_IPIF_LINKLOCAL(ipif);
1278 			unsupp_af = SCTP_UNSUPP_AF(ipif, supp_af);
1279 			/*
1280 			 * We need to either delete or skip loopback/linklocal
1281 			 * or unsupported addresses, if required.
1282 			 */
1283 			if ((ipif_ll && del_ll) || (ipif_lb && del_lb) ||
1284 			    (unsupp_af && modify)) {
1285 				if (sctp->sctp_bound_to_all == 1)
1286 					sctp->sctp_bound_to_all = 0;
1287 				if (scanned < nsaddr) {
1288 					obj = list_next(&sctp->sctp_saddrs[i].
1289 					    sctp_ipif_list, obj);
1290 					sctp_ipif_hash_remove(sctp, ipif);
1291 					continue;
1292 				}
1293 				sctp_ipif_hash_remove(sctp, ipif);
1294 				goto next_addr;
1295 			} else if (ipif_ll || unsupp_af ||
1296 			    (ipif_lb && (cl_sctp_check_addrs == NULL))) {
1297 				goto next_addr;
1298 			}
1299 
1300 			if (!SCTP_IPIF_USABLE(ipif->sctp_ipif_state))
1301 				goto next_addr;
1302 			if (p != NULL)
1303 				hdr = (sctp_parm_hdr_t *)(p + paramlen);
1304 			addr = ipif->sctp_ipif_saddr;
1305 			if (!ipif->sctp_ipif_isv6) {
1306 				struct in_addr	*v4;
1307 
1308 				if (p != NULL) {
1309 					hdr->sph_type = htons(PARM_ADDR4);
1310 					hdr->sph_len = htons(PARM_ADDR4_LEN);
1311 					v4 = (struct in_addr *)(hdr + 1);
1312 					IN6_V4MAPPED_TO_INADDR(&addr, v4);
1313 				}
1314 				paramlen += PARM_ADDR4_LEN;
1315 			} else {
1316 				if (p != NULL) {
1317 					hdr->sph_type = htons(PARM_ADDR6);
1318 					hdr->sph_len = htons(PARM_ADDR6_LEN);
1319 					bcopy(&addr, hdr + 1, sizeof (addr));
1320 				}
1321 				paramlen += PARM_ADDR6_LEN;
1322 			}
1323 next_addr:
1324 			if (scanned >= nsaddr)
1325 				return (paramlen);
1326 			obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1327 			    obj);
1328 		}
1329 	}
1330 	return (paramlen);
1331 }
1332 
1333 /*
1334  * This is used on a clustered node to obtain a list of addresses, the list
1335  * consists of sockaddr_in structs for v4 and sockaddr_in6 for v6. The list
1336  * is then passed onto the clustering module which sends back the correct
1337  * list based on the port info. Regardless of the input, i.e INADDR_ANY
1338  * or specific address(es), we create the list since it could be modified by
1339  * the clustering module. When given a list of addresses, we simply
1340  * create the list of sockaddr_in or sockaddr_in6 structs using those
1341  * addresses. If there is an INADDR_ANY in the input list, or if the
1342  * input is INADDR_ANY, we create a list of sockaddr_in or sockaddr_in6
1343  * structs consisting all the addresses in the global interface list
1344  * except those that are hosted on the loopback interface. We create
1345  * a list of sockaddr_in[6] structs just so that it can be directly input
1346  * to sctp_valid_addr_list() once the clustering module has processed it.
1347  */
1348 int
1349 sctp_get_addrlist(sctp_t *sctp, const void *addrs, uint32_t *addrcnt,
1350     uchar_t **addrlist, int *uspec, size_t *size)
1351 {
1352 	int			cnt;
1353 	int			icnt;
1354 	sctp_ipif_t		*sctp_ipif;
1355 	struct sockaddr_in	*s4;
1356 	struct sockaddr_in6	*s6;
1357 	uchar_t			*p;
1358 	int			err = 0;
1359 	sctp_stack_t		*sctps = sctp->sctp_sctps;
1360 
1361 	*addrlist = NULL;
1362 	*size = 0;
1363 
1364 	/*
1365 	 * Create a list of sockaddr_in[6] structs using the input list.
1366 	 */
1367 	if (sctp->sctp_family == AF_INET) {
1368 		*size = sizeof (struct sockaddr_in) * *addrcnt;
1369 		*addrlist = kmem_zalloc(*size,  KM_SLEEP);
1370 		p = *addrlist;
1371 		for (cnt = 0; cnt < *addrcnt; cnt++) {
1372 			s4 = (struct sockaddr_in *)addrs + cnt;
1373 			/*
1374 			 * We need to create a list of all the available
1375 			 * addresses if there is an INADDR_ANY. However,
1376 			 * if we are beyond LISTEN, then this is invalid
1377 			 * (see sctp_valid_addr_list(). So, we just fail
1378 			 * it here rather than wait till it fails in
1379 			 * sctp_valid_addr_list().
1380 			 */
1381 			if (s4->sin_addr.s_addr == INADDR_ANY) {
1382 				kmem_free(*addrlist, *size);
1383 				*addrlist = NULL;
1384 				*size = 0;
1385 				if (sctp->sctp_state > SCTPS_LISTEN) {
1386 					*addrcnt = 0;
1387 					return (EINVAL);
1388 				}
1389 				if (uspec != NULL)
1390 					*uspec = 1;
1391 				goto get_all_addrs;
1392 			} else {
1393 				bcopy(s4, p, sizeof (*s4));
1394 				p += sizeof (*s4);
1395 			}
1396 		}
1397 	} else {
1398 		*size = sizeof (struct sockaddr_in6) * *addrcnt;
1399 		*addrlist = kmem_zalloc(*size, KM_SLEEP);
1400 		p = *addrlist;
1401 		for (cnt = 0; cnt < *addrcnt; cnt++) {
1402 			s6 = (struct sockaddr_in6 *)addrs + cnt;
1403 			/*
1404 			 * Comments for INADDR_ANY, above, apply here too.
1405 			 */
1406 			if (IN6_IS_ADDR_UNSPECIFIED(&s6->sin6_addr)) {
1407 				kmem_free(*addrlist, *size);
1408 				*size = 0;
1409 				*addrlist = NULL;
1410 				if (sctp->sctp_state > SCTPS_LISTEN) {
1411 					*addrcnt = 0;
1412 					return (EINVAL);
1413 				}
1414 				if (uspec != NULL)
1415 					*uspec = 1;
1416 				goto get_all_addrs;
1417 			} else {
1418 				bcopy(addrs, p, sizeof (*s6));
1419 				p += sizeof (*s6);
1420 			}
1421 		}
1422 	}
1423 	return (err);
1424 get_all_addrs:
1425 
1426 	/*
1427 	 * Allocate max possible size. We allocate the max. size here because
1428 	 * the clustering module could end up adding addresses to the list.
1429 	 * We allocate upfront so that the clustering module need to bother
1430 	 * re-sizing the list.
1431 	 */
1432 	if (sctp->sctp_family == AF_INET) {
1433 		*size = sizeof (struct sockaddr_in) *
1434 		    sctps->sctps_g_ipifs_count;
1435 	} else {
1436 		*size = sizeof (struct sockaddr_in6) *
1437 		    sctps->sctps_g_ipifs_count;
1438 	}
1439 	*addrlist = kmem_zalloc(*size, KM_SLEEP);
1440 	*addrcnt = 0;
1441 	p = *addrlist;
1442 	rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
1443 
1444 	/*
1445 	 * Walk through the global interface list and add all addresses,
1446 	 * except those that are hosted on loopback interfaces.
1447 	 */
1448 	for (cnt = 0; cnt <  SCTP_IPIF_HASH; cnt++) {
1449 		if (sctps->sctps_g_ipifs[cnt].ipif_count == 0)
1450 			continue;
1451 		sctp_ipif = list_head(
1452 		    &sctps->sctps_g_ipifs[cnt].sctp_ipif_list);
1453 		for (icnt = 0;
1454 		    icnt < sctps->sctps_g_ipifs[cnt].ipif_count;
1455 		    icnt++) {
1456 			in6_addr_t	addr;
1457 
1458 			rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
1459 			addr = sctp_ipif->sctp_ipif_saddr;
1460 			if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
1461 			    !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
1462 			    SCTP_IS_IPIF_LOOPBACK(sctp_ipif) ||
1463 			    SCTP_IS_IPIF_LINKLOCAL(sctp_ipif) ||
1464 			    !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
1465 			    (sctp->sctp_ipversion == IPV4_VERSION &&
1466 			    sctp_ipif->sctp_ipif_isv6) ||
1467 			    (sctp->sctp_connp->conn_ipv6_v6only &&
1468 			    !sctp_ipif->sctp_ipif_isv6)) {
1469 				rw_exit(&sctp_ipif->sctp_ipif_lock);
1470 				sctp_ipif = list_next(
1471 				    &sctps->sctps_g_ipifs[cnt].sctp_ipif_list,
1472 				    sctp_ipif);
1473 				continue;
1474 			}
1475 			rw_exit(&sctp_ipif->sctp_ipif_lock);
1476 			if (sctp->sctp_family == AF_INET) {
1477 				s4 = (struct sockaddr_in *)p;
1478 				IN6_V4MAPPED_TO_INADDR(&addr, &s4->sin_addr);
1479 				s4->sin_family = AF_INET;
1480 				p += sizeof (*s4);
1481 			} else {
1482 				s6 = (struct sockaddr_in6 *)p;
1483 				s6->sin6_addr = addr;
1484 				s6->sin6_family = AF_INET6;
1485 				s6->sin6_scope_id =
1486 				    sctp_ipif->sctp_ipif_ill->sctp_ill_index;
1487 				p += sizeof (*s6);
1488 			}
1489 			(*addrcnt)++;
1490 			sctp_ipif = list_next(
1491 			    &sctps->sctps_g_ipifs[cnt].sctp_ipif_list,
1492 			    sctp_ipif);
1493 		}
1494 	}
1495 	rw_exit(&sctps->sctps_g_ipifs_lock);
1496 	return (err);
1497 }
1498 
1499 /*
1500  * Get a list of addresses from the source address list. The  caller is
1501  * responsible for allocating sufficient buffer for this.
1502  */
1503 void
1504 sctp_get_saddr_list(sctp_t *sctp, uchar_t *p, size_t psize)
1505 {
1506 	int			cnt;
1507 	int			icnt;
1508 	sctp_saddr_ipif_t	*obj;
1509 	int			naddr;
1510 	int			scanned = 0;
1511 
1512 	for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) {
1513 		if (sctp->sctp_saddrs[cnt].ipif_count == 0)
1514 			continue;
1515 		obj = list_head(&sctp->sctp_saddrs[cnt].sctp_ipif_list);
1516 		naddr = sctp->sctp_saddrs[cnt].ipif_count;
1517 		for (icnt = 0; icnt < naddr; icnt++) {
1518 			sctp_ipif_t	*ipif;
1519 
1520 			if (psize < sizeof (ipif->sctp_ipif_saddr))
1521 				return;
1522 
1523 			scanned++;
1524 			ipif = obj->saddr_ipifp;
1525 			bcopy(&ipif->sctp_ipif_saddr, p,
1526 			    sizeof (ipif->sctp_ipif_saddr));
1527 			p += sizeof (ipif->sctp_ipif_saddr);
1528 			psize -= sizeof (ipif->sctp_ipif_saddr);
1529 			if (scanned >= sctp->sctp_nsaddrs)
1530 				return;
1531 			obj = list_next(
1532 			    &sctp->sctp_saddrs[icnt].sctp_ipif_list,
1533 			    obj);
1534 		}
1535 	}
1536 }
1537 
1538 /*
1539  * Get a list of addresses from the remote address list. The  caller is
1540  * responsible for allocating sufficient buffer for this.
1541  */
1542 void
1543 sctp_get_faddr_list(sctp_t *sctp, uchar_t *p, size_t psize)
1544 {
1545 	sctp_faddr_t	*fp;
1546 
1547 	for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) {
1548 		if (psize < sizeof (fp->faddr))
1549 			return;
1550 		bcopy(&fp->faddr, p, sizeof (fp->faddr));
1551 		p += sizeof (fp->faddr);
1552 		psize -= sizeof (fp->faddr);
1553 	}
1554 }
1555 
1556 static void
1557 sctp_free_ills(sctp_stack_t *sctps)
1558 {
1559 	int			i;
1560 	int			l;
1561 	sctp_ill_t	*sctp_ill;
1562 
1563 	if (sctps->sctps_ills_count == 0)
1564 		return;
1565 
1566 	for (i = 0; i < SCTP_ILL_HASH; i++) {
1567 		sctp_ill = list_tail(&sctps->sctps_g_ills[i].sctp_ill_list);
1568 		for (l = 0; l < sctps->sctps_g_ills[i].ill_count; l++) {
1569 			ASSERT(sctp_ill->sctp_ill_ipifcnt == 0);
1570 			list_remove(&sctps->sctps_g_ills[i].sctp_ill_list,
1571 			    sctp_ill);
1572 			sctps->sctps_ills_count--;
1573 			kmem_free(sctp_ill->sctp_ill_name,
1574 			    sctp_ill->sctp_ill_name_length);
1575 			kmem_free(sctp_ill, sizeof (sctp_ill_t));
1576 			sctp_ill =
1577 			    list_tail(&sctps->sctps_g_ills[i].sctp_ill_list);
1578 		}
1579 		sctps->sctps_g_ills[i].ill_count = 0;
1580 	}
1581 	ASSERT(sctps->sctps_ills_count == 0);
1582 }
1583 
1584 static void
1585 sctp_free_ipifs(sctp_stack_t *sctps)
1586 {
1587 	int			i;
1588 	int			l;
1589 	sctp_ipif_t	*sctp_ipif;
1590 	sctp_ill_t	*sctp_ill;
1591 
1592 	if (sctps->sctps_g_ipifs_count == 0)
1593 		return;
1594 
1595 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1596 		sctp_ipif = list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
1597 		for (l = 0; l < sctps->sctps_g_ipifs[i].ipif_count; l++) {
1598 			sctp_ill = sctp_ipif->sctp_ipif_ill;
1599 
1600 			list_remove(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
1601 			    sctp_ipif);
1602 			sctps->sctps_g_ipifs_count--;
1603 			(void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt,
1604 			    -1);
1605 			kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
1606 			sctp_ipif =
1607 			    list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
1608 		}
1609 		sctps->sctps_g_ipifs[i].ipif_count = 0;
1610 	}
1611 	ASSERT(sctps->sctps_g_ipifs_count == 0);
1612 }
1613 
1614 
1615 /* Initialize the SCTP ILL list and lock */
1616 void
1617 sctp_saddr_init(sctp_stack_t *sctps)
1618 {
1619 	int	i;
1620 
1621 	sctps->sctps_g_ills = kmem_zalloc(sizeof (sctp_ill_hash_t) *
1622 	    SCTP_ILL_HASH, KM_SLEEP);
1623 	sctps->sctps_g_ipifs = kmem_zalloc(sizeof (sctp_ipif_hash_t) *
1624 	    SCTP_IPIF_HASH, KM_SLEEP);
1625 
1626 	rw_init(&sctps->sctps_g_ills_lock, NULL, RW_DEFAULT, NULL);
1627 	rw_init(&sctps->sctps_g_ipifs_lock, NULL, RW_DEFAULT, NULL);
1628 
1629 	for (i = 0; i < SCTP_ILL_HASH; i++) {
1630 		sctps->sctps_g_ills[i].ill_count = 0;
1631 		list_create(&sctps->sctps_g_ills[i].sctp_ill_list,
1632 		    sizeof (sctp_ill_t),
1633 		    offsetof(sctp_ill_t, sctp_ills));
1634 	}
1635 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
1636 		sctps->sctps_g_ipifs[i].ipif_count = 0;
1637 		list_create(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
1638 		    sizeof (sctp_ipif_t), offsetof(sctp_ipif_t, sctp_ipifs));
1639 	}
1640 }
1641 
1642 void
1643 sctp_saddr_fini(sctp_stack_t *sctps)
1644 {
1645 	int	i;
1646 
1647 	sctp_free_ipifs(sctps);
1648 	sctp_free_ills(sctps);
1649 
1650 	for (i = 0; i < SCTP_ILL_HASH; i++)
1651 		list_destroy(&sctps->sctps_g_ills[i].sctp_ill_list);
1652 	for (i = 0; i < SCTP_IPIF_HASH; i++)
1653 		list_destroy(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
1654 
1655 	ASSERT(sctps->sctps_ills_count == 0 && sctps->sctps_g_ipifs_count == 0);
1656 	kmem_free(sctps->sctps_g_ills, sizeof (sctp_ill_hash_t) *
1657 	    SCTP_ILL_HASH);
1658 	sctps->sctps_g_ills = NULL;
1659 	kmem_free(sctps->sctps_g_ipifs, sizeof (sctp_ipif_hash_t) *
1660 	    SCTP_IPIF_HASH);
1661 	sctps->sctps_g_ipifs = NULL;
1662 	rw_destroy(&sctps->sctps_g_ills_lock);
1663 	rw_destroy(&sctps->sctps_g_ipifs_lock);
1664 }
1665