1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/stream.h>
30 #define	_SUN_TPI_VERSION 2
31 #include <sys/tihdr.h>
32 #include <sys/socket.h>
33 #include <sys/xti_inet.h>
34 #include <sys/systm.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/kmem.h>
38 #include <sys/strsubr.h>
39 #include <sys/strsun.h>
40 #include <sys/policy.h>
41 
42 #include <inet/common.h>
43 #include <netinet/ip6.h>
44 #include <inet/ip.h>
45 #include <inet/ip_ire.h>
46 #include <inet/ip_if.h>
47 #include <inet/ipclassifier.h>
48 #include <inet/ipsec_impl.h>
49 
50 #include <netinet/in.h>
51 #include <netinet/ip.h>
52 #include <netinet/tcp.h>
53 
54 #include <inet/common.h>
55 #include <inet/ip.h>
56 #include <inet/ip6.h>
57 #include <inet/sctp_itf.h>
58 #include "sctp_impl.h"
59 #include "sctp_asconf.h"
60 #include "sctp_addr.h"
61 
62 static int	sctp_getpeeraddrs(sctp_t *, void *, int *);
63 
64 /*
65  * Copy the standard header into its new location,
66  * lay in the new options and then update the relevant
67  * fields in both sctp_t and the standard header.
68  * Returns 0 on success, errno otherwise.
69  */
70 static int
71 sctp_opt_set_header(sctp_t *sctp, const void *ptr, uint_t len)
72 {
73 	uint8_t *ip_optp;
74 	sctp_hdr_t *new_sctph;
75 
76 	if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
77 		return (EINVAL);
78 
79 	if (len > IP_MAX_OPT_LENGTH - sctp->sctp_v4label_len)
80 		return (EINVAL);
81 
82 	ip_optp = (uint8_t *)sctp->sctp_ipha + IP_SIMPLE_HDR_LENGTH;
83 
84 	if (sctp->sctp_v4label_len > 0) {
85 		int padlen;
86 		uint8_t opt;
87 
88 		/* convert list termination to no-ops as needed */
89 		padlen = sctp->sctp_v4label_len - ip_optp[IPOPT_OLEN];
90 		ip_optp += ip_optp[IPOPT_OLEN];
91 		opt = len > 0 ? IPOPT_NOP : IPOPT_EOL;
92 		while (--padlen >= 0)
93 			*ip_optp++ = opt;
94 		ASSERT(ip_optp == (uint8_t *)sctp->sctp_ipha +
95 		    IP_SIMPLE_HDR_LENGTH + sctp->sctp_v4label_len);
96 	}
97 
98 	/*
99 	 * Move the existing SCTP header out where it belongs.
100 	 */
101 	new_sctph = (sctp_hdr_t *)(ip_optp + len);
102 	ovbcopy(sctp->sctp_sctph, new_sctph, sizeof (sctp_hdr_t));
103 	sctp->sctp_sctph = new_sctph;
104 
105 	/*
106 	 * Insert the new user-supplied IP options.
107 	 */
108 	if (len > 0)
109 		bcopy(ptr, ip_optp, len);
110 
111 	len += sctp->sctp_v4label_len;
112 	sctp->sctp_ip_hdr_len = len;
113 	sctp->sctp_ipha->ipha_version_and_hdr_length =
114 	    (IP_VERSION << 4) | (len >> 2);
115 	sctp->sctp_hdr_len = len + sizeof (sctp_hdr_t);
116 
117 	if (sctp->sctp_current) {
118 		/*
119 		 * Could be setting options before setting up connection.
120 		 */
121 		sctp_set_ulp_prop(sctp);
122 	}
123 	return (0);
124 }
125 
126 static int
127 sctp_get_status(sctp_t *sctp, void *ptr)
128 {
129 	struct sctp_status *sstat = ptr;
130 	sctp_faddr_t *fp;
131 	struct sockaddr_in *sin;
132 	struct sockaddr_in6 *sin6;
133 	struct sctp_paddrinfo *sp;
134 	mblk_t *meta, *mp;
135 	int i;
136 
137 	sstat->sstat_state = sctp->sctp_state;
138 	sstat->sstat_rwnd = sctp->sctp_frwnd;
139 
140 	sp = &sstat->sstat_primary;
141 	if (!sctp->sctp_primary) {
142 		bzero(sp, sizeof (*sp));
143 		goto noprim;
144 	}
145 	fp = sctp->sctp_primary;
146 
147 	if (fp->isv4) {
148 		sin = (struct sockaddr_in *)&sp->spinfo_address;
149 		sin->sin_family = AF_INET;
150 		sin->sin_port = sctp->sctp_fport;
151 		IN6_V4MAPPED_TO_INADDR(&fp->faddr, &sin->sin_addr);
152 		sp->spinfo_mtu = sctp->sctp_hdr_len;
153 	} else {
154 		sin6 = (struct sockaddr_in6 *)&sp->spinfo_address;
155 		sin6->sin6_family = AF_INET6;
156 		sin6->sin6_port = sctp->sctp_fport;
157 		sin6->sin6_addr = fp->faddr;
158 		sp->spinfo_mtu = sctp->sctp_hdr6_len;
159 	}
160 	sp->spinfo_state = fp->state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE :
161 	    SCTP_INACTIVE;
162 	sp->spinfo_cwnd = fp->cwnd;
163 	sp->spinfo_srtt = fp->srtt;
164 	sp->spinfo_rto = fp->rto;
165 	sp->spinfo_mtu += fp->sfa_pmss;
166 
167 noprim:
168 	sstat->sstat_unackdata = 0;
169 	sstat->sstat_penddata = 0;
170 	sstat->sstat_instrms = sctp->sctp_num_istr;
171 	sstat->sstat_outstrms = sctp->sctp_num_ostr;
172 	sstat->sstat_fragmentation_point = sctp->sctp_mss -
173 	    sizeof (sctp_data_hdr_t);
174 
175 	/* count unack'd */
176 	for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) {
177 		for (mp = meta->b_cont; mp; mp = mp->b_next) {
178 			if (!SCTP_CHUNK_ISSENT(mp)) {
179 				break;
180 			}
181 			if (!SCTP_CHUNK_ISACKED(mp)) {
182 				sstat->sstat_unackdata++;
183 			}
184 		}
185 	}
186 
187 	/*
188 	 * Count penddata chunks. We can only count chunks in SCTP (not
189 	 * data already delivered to socket layer).
190 	 */
191 	if (sctp->sctp_instr != NULL) {
192 		for (i = 0; i < sctp->sctp_num_istr; i++) {
193 			for (meta = sctp->sctp_instr[i].istr_reass;
194 			    meta != NULL; meta = meta->b_next) {
195 				for (mp = meta->b_cont; mp; mp = mp->b_cont) {
196 					if (DB_TYPE(mp) != M_CTL) {
197 						sstat->sstat_penddata++;
198 					}
199 				}
200 			}
201 		}
202 	}
203 	/* Un-Ordered Frag list */
204 	for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next)
205 		sstat->sstat_penddata++;
206 
207 	return (sizeof (*sstat));
208 }
209 
210 /*
211  * SCTP_GET_PEER_ADDR_INFO
212  */
213 static int
214 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen)
215 {
216 	struct sctp_paddrinfo	*infop = ptr;
217 	struct sockaddr_in	*sin4;
218 	struct sockaddr_in6	*sin6;
219 	in6_addr_t		faddr;
220 	sctp_faddr_t		*fp;
221 
222 	switch (infop->spinfo_address.ss_family) {
223 	case AF_INET:
224 		sin4 = (struct sockaddr_in *)&infop->spinfo_address;
225 		IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr);
226 		break;
227 	case AF_INET6:
228 		sin6 = (struct sockaddr_in6 *)&infop->spinfo_address;
229 		faddr = sin6->sin6_addr;
230 		break;
231 	default:
232 		return (EAFNOSUPPORT);
233 	}
234 
235 	if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL)
236 		return (EINVAL);
237 
238 	infop->spinfo_state = (fp->state == SCTP_FADDRS_ALIVE) ? SCTP_ACTIVE :
239 	    SCTP_INACTIVE;
240 	infop->spinfo_cwnd = fp->cwnd;
241 	infop->spinfo_srtt = TICK_TO_MSEC(fp->srtt);
242 	infop->spinfo_rto = TICK_TO_MSEC(fp->rto);
243 	infop->spinfo_mtu = fp->sfa_pmss;
244 
245 	*optlen = sizeof (struct sctp_paddrinfo);
246 	return (0);
247 }
248 
249 /*
250  * SCTP_RTOINFO
251  */
252 static int
253 sctp_get_rtoinfo(sctp_t *sctp, void *ptr)
254 {
255 	struct sctp_rtoinfo *srto = ptr;
256 
257 	srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial);
258 	srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max);
259 	srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min);
260 
261 	return (sizeof (*srto));
262 }
263 
264 static int
265 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp, uint_t inlen)
266 {
267 	const struct sctp_rtoinfo *srto;
268 	boolean_t ispriv;
269 
270 	if (inlen < sizeof (*srto)) {
271 		return (EINVAL);
272 	}
273 	srto = invalp;
274 
275 	ispriv = secpolicy_net_config(CRED(), B_TRUE) == 0;
276 
277 	/*
278 	 * Bounds checking.  Priviledged user can set the RTO initial
279 	 * outside the ndd boundary.
280 	 */
281 	if (srto->srto_initial != 0 &&
282 	    (!ispriv && (srto->srto_initial < sctp_rto_initialg_low ||
283 		srto->srto_initial > sctp_rto_initialg_high))) {
284 		return (EINVAL);
285 	}
286 	if (srto->srto_max != 0 &&
287 	    (!ispriv && (srto->srto_max < sctp_rto_maxg_low ||
288 		srto->srto_max > sctp_rto_maxg_high))) {
289 		return (EINVAL);
290 	}
291 	if (srto->srto_min != 0 &&
292 	    (!ispriv && (srto->srto_min < sctp_rto_ming_low ||
293 		srto->srto_min > sctp_rto_ming_high))) {
294 		return (EINVAL);
295 	}
296 
297 	if (srto->srto_initial != 0) {
298 		sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial);
299 	}
300 	if (srto->srto_max != 0) {
301 		sctp->sctp_rto_max = MSEC_TO_TICK(srto->srto_max);
302 	}
303 	if (srto->srto_min != 0) {
304 		sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min);
305 	}
306 
307 	return (0);
308 }
309 
310 /*
311  * SCTP_ASSOCINFO
312  */
313 static int
314 sctp_get_assocparams(sctp_t *sctp, void *ptr)
315 {
316 	struct sctp_assocparams *sap = ptr;
317 	sctp_faddr_t *fp;
318 	uint16_t i;
319 
320 	sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt;
321 
322 	/*
323 	 * Count the number of peer addresses
324 	 */
325 	for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) {
326 		i++;
327 	}
328 	sap->sasoc_number_peer_destinations = i;
329 	sap->sasoc_peer_rwnd = sctp->sctp_frwnd;
330 	sap->sasoc_local_rwnd = sctp->sctp_rwnd;
331 	sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime);
332 
333 	return (sizeof (*sap));
334 }
335 
336 static int
337 sctp_set_assocparams(sctp_t *sctp, const void *invalp, uint_t inlen)
338 {
339 	const struct sctp_assocparams *sap = invalp;
340 	uint32_t sum = 0;
341 	sctp_faddr_t *fp;
342 
343 	if (inlen < sizeof (*sap)) {
344 		return (EINVAL);
345 	}
346 
347 	if (sap->sasoc_asocmaxrxt) {
348 		if (sctp->sctp_faddrs) {
349 			/*
350 			 * Bounds check: as per rfc2960, assoc max retr cannot
351 			 * exceed the sum of all individual path max retr's.
352 			 */
353 			for (fp = sctp->sctp_faddrs; fp; fp = fp->next) {
354 				sum += fp->max_retr;
355 			}
356 			if (sap->sasoc_asocmaxrxt > sum) {
357 				return (EINVAL);
358 			}
359 		}
360 		if (sap->sasoc_asocmaxrxt < sctp_pa_max_retr_low ||
361 		    sap->sasoc_asocmaxrxt > sctp_pa_max_retr_high) {
362 			/*
363 			 * Out of bounds.
364 			 */
365 			return (EINVAL);
366 		}
367 	}
368 	if (sap->sasoc_cookie_life != 0 &&
369 	    (sap->sasoc_cookie_life < sctp_cookie_life_low ||
370 		sap->sasoc_cookie_life > sctp_cookie_life_high)) {
371 			return (EINVAL);
372 	}
373 
374 	if (sap->sasoc_asocmaxrxt > 0) {
375 		sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt;
376 	}
377 	if (sap->sasoc_cookie_life > 0) {
378 		sctp->sctp_cookie_lifetime = MSEC_TO_TICK(
379 		    sap->sasoc_cookie_life);
380 	}
381 	return (0);
382 }
383 
384 /*
385  * SCTP_INITMSG
386  */
387 static int
388 sctp_get_initmsg(sctp_t *sctp, void *ptr)
389 {
390 	struct sctp_initmsg *si = ptr;
391 
392 	si->sinit_num_ostreams = sctp->sctp_num_ostr;
393 	si->sinit_max_instreams = sctp->sctp_num_istr;
394 	si->sinit_max_attempts = sctp->sctp_max_init_rxt;
395 	si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_init_rto_max);
396 
397 	return (sizeof (*si));
398 }
399 
400 static int
401 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen)
402 {
403 	const struct sctp_initmsg *si = invalp;
404 
405 	if (sctp->sctp_state > SCTPS_LISTEN) {
406 		return (EINVAL);
407 	}
408 	if (inlen < sizeof (*si)) {
409 		return (EINVAL);
410 	}
411 	if (si->sinit_num_ostreams != 0 &&
412 	    (si->sinit_num_ostreams < sctp_initial_out_streams_low ||
413 		si->sinit_num_ostreams > sctp_initial_out_streams_high)) {
414 		/*
415 		 * Out of bounds.
416 		 */
417 		return (EINVAL);
418 	}
419 	if (si->sinit_max_instreams != 0 &&
420 	    (si->sinit_max_instreams < sctp_max_in_streams_low ||
421 		si->sinit_max_instreams > sctp_max_in_streams_high)) {
422 		return (EINVAL);
423 	}
424 	if (si->sinit_max_attempts != 0 &&
425 	    (si->sinit_max_attempts < sctp_max_init_retr_low ||
426 		si->sinit_max_attempts > sctp_max_init_retr_high)) {
427 		return (EINVAL);
428 	}
429 	if (si->sinit_max_init_timeo != 0 &&
430 	    (secpolicy_net_config(CRED(), B_TRUE) != 0 &&
431 		(si->sinit_max_init_timeo < sctp_rto_maxg_low ||
432 		si->sinit_max_init_timeo > sctp_rto_maxg_high))) {
433 		return (EINVAL);
434 	}
435 	if (si->sinit_num_ostreams != 0)
436 		sctp->sctp_num_ostr = si->sinit_num_ostreams;
437 
438 	if (si->sinit_max_instreams != 0)
439 		sctp->sctp_num_istr = si->sinit_max_instreams;
440 
441 	if (si->sinit_max_attempts != 0)
442 		sctp->sctp_max_init_rxt = si->sinit_max_attempts;
443 
444 	if (si->sinit_max_init_timeo != 0) {
445 		sctp->sctp_init_rto_max =
446 		    MSEC_TO_TICK(si->sinit_max_init_timeo);
447 	}
448 	return (0);
449 }
450 
451 /*
452  * SCTP_PEER_ADDR_PARAMS
453  */
454 static int
455 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss,
456     sctp_faddr_t **fpp)
457 {
458 	struct sockaddr_in *sin;
459 	struct sockaddr_in6 *sin6;
460 	in6_addr_t addr;
461 
462 	if (ss->ss_family == AF_INET) {
463 		sin = (struct sockaddr_in *)ss;
464 		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
465 	} else if (ss->ss_family == AF_INET6) {
466 		sin6 = (struct sockaddr_in6 *)ss;
467 		addr = sin6->sin6_addr;
468 	} else if (ss->ss_family) {
469 		return (EAFNOSUPPORT);
470 	}
471 
472 	if (!ss->ss_family ||
473 	    SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) {
474 		*fpp = NULL;
475 	} else {
476 		*fpp = sctp_lookup_faddr(sctp, &addr);
477 		if (*fpp == NULL) {
478 			return (EINVAL);
479 		}
480 	}
481 	return (0);
482 }
483 
484 static int
485 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr)
486 {
487 	struct sctp_paddrparams *spp = ptr;
488 	sctp_faddr_t *fp;
489 	int retval;
490 
491 	retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
492 	if (retval) {
493 		return (retval);
494 	}
495 	if (fp) {
496 		spp->spp_hbinterval = TICK_TO_MSEC(fp->hb_interval);
497 		spp->spp_pathmaxrxt = fp->max_retr;
498 	} else {
499 		spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval);
500 		spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt;
501 	}
502 	return (sizeof (*spp));
503 }
504 
505 static int
506 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp, uint_t inlen)
507 {
508 	const struct sctp_paddrparams *spp = invalp;
509 	sctp_faddr_t *fp, *fp2;
510 	int retval;
511 	uint32_t sum = 0;
512 	int64_t now;
513 
514 	if (inlen < sizeof (*spp)) {
515 		return (EINVAL);
516 	}
517 
518 	retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
519 	if (retval != 0) {
520 		return (retval);
521 	}
522 
523 	if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX &&
524 	    (spp->spp_hbinterval < sctp_heartbeat_interval_low ||
525 		spp->spp_hbinterval > sctp_heartbeat_interval_high)) {
526 		return (EINVAL);
527 	}
528 	if (spp->spp_pathmaxrxt &&
529 	    (spp->spp_pathmaxrxt < sctp_pp_max_retr_low ||
530 		spp->spp_pathmaxrxt > sctp_pp_max_retr_high)) {
531 		return (EINVAL);
532 	}
533 	if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) {
534 		for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->next) {
535 			if (!fp || fp2 == fp) {
536 				sum += spp->spp_pathmaxrxt;
537 			} else {
538 				sum += fp2->max_retr;
539 			}
540 		}
541 		if (sctp->sctp_pa_max_rxt > sum) {
542 			return (EINVAL);
543 		}
544 	}
545 
546 	now = lbolt64;
547 	if (fp != NULL) {
548 		if (spp->spp_hbinterval == UINT32_MAX) {
549 			/*
550 			 * Send heartbeat immediatelly, don't modify the
551 			 * current setting.
552 			 */
553 			sctp_send_heartbeat(sctp, fp);
554 		} else {
555 			fp->hb_interval = MSEC_TO_TICK(spp->spp_hbinterval);
556 			fp->hb_expiry = now + SET_HB_INTVL(fp);
557 			/*
558 			 * Restart the heartbeat timer using the new intrvl.
559 			 * We need to call sctp_heartbeat_timer() to set
560 			 * the earliest heartbeat expiry time.
561 			 */
562 			sctp_heartbeat_timer(sctp);
563 		}
564 		if (spp->spp_pathmaxrxt) {
565 			fp->max_retr = spp->spp_pathmaxrxt;
566 		}
567 	} else {
568 		for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->next) {
569 			if (spp->spp_hbinterval == UINT32_MAX) {
570 				/*
571 				 * Send heartbeat immediatelly, don't modify
572 				 * the current setting.
573 				 */
574 				sctp_send_heartbeat(sctp, fp2);
575 			} else {
576 				fp2->hb_interval = MSEC_TO_TICK(
577 				    spp->spp_hbinterval);
578 				fp2->hb_expiry = now + SET_HB_INTVL(fp2);
579 			}
580 			if (spp->spp_pathmaxrxt) {
581 				fp2->max_retr = spp->spp_pathmaxrxt;
582 			}
583 		}
584 		if (spp->spp_hbinterval != UINT32_MAX) {
585 			sctp->sctp_hb_interval = MSEC_TO_TICK(
586 			    spp->spp_hbinterval);
587 			/* Restart the heartbeat timer using the new intrvl. */
588 			sctp_timer(sctp, sctp->sctp_heartbeat_mp,
589 			    sctp->sctp_hb_interval);
590 		}
591 		if (spp->spp_pathmaxrxt) {
592 			sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt;
593 		}
594 	}
595 	return (0);
596 }
597 
598 /*
599  * SCTP_DEFAULT_SEND_PARAM
600  */
601 static int
602 sctp_get_def_send_params(sctp_t *sctp, void *ptr)
603 {
604 	struct sctp_sndrcvinfo *sinfo = ptr;
605 
606 	sinfo->sinfo_stream = sctp->sctp_def_stream;
607 	sinfo->sinfo_ssn = 0;
608 	sinfo->sinfo_flags = sctp->sctp_def_flags;
609 	sinfo->sinfo_ppid = sctp->sctp_def_ppid;
610 	sinfo->sinfo_context = sctp->sctp_def_context;
611 	sinfo->sinfo_timetolive = sctp->sctp_def_timetolive;
612 	sinfo->sinfo_tsn = 0;
613 	sinfo->sinfo_cumtsn = 0;
614 
615 	return (sizeof (*sinfo));
616 }
617 
618 static int
619 sctp_set_def_send_params(sctp_t *sctp, const void *invalp, uint_t inlen)
620 {
621 	const struct sctp_sndrcvinfo *sinfo = invalp;
622 
623 	if (inlen < sizeof (*sinfo)) {
624 		return (EINVAL);
625 	}
626 	if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) {
627 		return (EINVAL);
628 	}
629 
630 	sctp->sctp_def_stream = sinfo->sinfo_stream;
631 	sctp->sctp_def_flags = sinfo->sinfo_flags;
632 	sctp->sctp_def_ppid = sinfo->sinfo_ppid;
633 	sctp->sctp_def_context = sinfo->sinfo_context;
634 	sctp->sctp_def_timetolive = sinfo->sinfo_timetolive;
635 
636 	return (0);
637 }
638 
639 static int
640 sctp_set_prim(sctp_t *sctp, const void *invalp, uint_t inlen)
641 {
642 	const struct	sctp_setpeerprim *pp = invalp;
643 	int		retval;
644 	sctp_faddr_t	*fp;
645 
646 	if (inlen < sizeof (*pp)) {
647 		return (EINVAL);
648 	}
649 
650 	retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp);
651 	if (retval)
652 		return (retval);
653 
654 	if (fp == NULL)
655 		return (EINVAL);
656 	if (fp == sctp->sctp_primary)
657 		return (0);
658 	sctp->sctp_primary = fp;
659 
660 	/* Only switch current if fp is alive */
661 	if (fp->state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) {
662 		return (0);
663 	}
664 	sctp->sctp_current = fp;
665 	sctp->sctp_mss = fp->sfa_pmss;
666 	/* Reset the addrs in the composite header */
667 	sctp_faddr2hdraddr(fp, sctp);
668 	sctp_set_ulp_prop(sctp);
669 
670 	return (0);
671 }
672 
673 /* Handy on off switch for socket option processing. */
674 #define	ONOFF(x)	((x) == 0 ? 0 : 1)
675 
676 /*
677  * SCTP routine to get the values of options.
678  */
679 int
680 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen)
681 {
682 	int	*i1 = (int *)ptr;
683 	int	retval = 0;
684 	int	buflen = *optlen;
685 	conn_t		*connp = sctp->sctp_connp;
686 	ip6_pkt_t	*ipp = &sctp->sctp_sticky_ipp;
687 	/* In most cases, the return buffer is just an int */
688 	*optlen = sizeof (int32_t);
689 
690 	RUN_SCTP(sctp);
691 
692 	switch (level) {
693 	case SOL_SOCKET:
694 		switch (name) {
695 		case SO_LINGER:	{
696 			struct linger *lgr = (struct linger *)ptr;
697 
698 			lgr->l_onoff = sctp->sctp_linger ? SO_LINGER : 0;
699 			lgr->l_linger = TICK_TO_MSEC(sctp->sctp_lingertime);
700 			*optlen = sizeof (struct linger);
701 			break;
702 		}
703 		case SO_DEBUG:
704 			*i1 = sctp->sctp_debug ? SO_DEBUG : 0;
705 			break;
706 		case SO_DONTROUTE:
707 			*i1 = sctp->sctp_dontroute ? SO_DONTROUTE : 0;
708 			break;
709 		case SO_USELOOPBACK:
710 			*i1 = sctp->sctp_useloopback ? SO_USELOOPBACK : 0;
711 			break;
712 		case SO_BROADCAST:
713 			*i1 = sctp->sctp_broadcast ? SO_BROADCAST : 0;
714 			break;
715 		case SO_REUSEADDR:
716 			*i1 = sctp->sctp_reuseaddr ? SO_REUSEADDR : 0;
717 			break;
718 		case SO_DGRAM_ERRIND:
719 			*i1 = sctp->sctp_dgram_errind ? SO_DGRAM_ERRIND : 0;
720 			break;
721 		case SO_SNDBUF:
722 			*i1 = sctp->sctp_xmit_hiwater;
723 			break;
724 		case SO_RCVBUF:
725 			*i1 = sctp->sctp_rwnd;
726 			break;
727 		case SO_MAC_EXEMPT:
728 			*i1 = sctp->sctp_mac_exempt ? SO_MAC_EXEMPT : 0;
729 			break;
730 		default:
731 			retval = EINVAL;
732 			break;
733 		}
734 		break;
735 
736 	case IPPROTO_SCTP:
737 		switch (name) {
738 		case SCTP_RTOINFO:
739 			if (buflen < sizeof (struct sctp_rtoinfo)) {
740 				retval = EINVAL;
741 				break;
742 			}
743 			*optlen = sctp_get_rtoinfo(sctp, ptr);
744 			break;
745 		case SCTP_ASSOCINFO:
746 			if (buflen < sizeof (struct sctp_assocparams)) {
747 				retval = EINVAL;
748 				break;
749 			}
750 			*optlen = sctp_get_assocparams(sctp, ptr);
751 			break;
752 		case SCTP_INITMSG:
753 			if (buflen < sizeof (struct sctp_initmsg)) {
754 				retval = EINVAL;
755 				break;
756 			}
757 			*optlen = sctp_get_initmsg(sctp, ptr);
758 			break;
759 		case SCTP_NODELAY:
760 			*i1 = sctp->sctp_ndelay;
761 			break;
762 		case SCTP_AUTOCLOSE:
763 			*i1 = TICK_TO_SEC(sctp->sctp_autoclose);
764 			break;
765 		case SCTP_ADAPTION_LAYER:
766 			if (buflen < sizeof (struct sctp_setadaption)) {
767 				retval = EINVAL;
768 				break;
769 			}
770 			((struct sctp_setadaption *)ptr)->ssb_adaption_ind =
771 			    sctp->sctp_tx_adaption_code;
772 			break;
773 		case SCTP_PEER_ADDR_PARAMS:
774 			if (buflen < sizeof (struct sctp_paddrparams)) {
775 				retval = EINVAL;
776 				break;
777 			}
778 			*optlen = sctp_get_peer_addr_params(sctp, ptr);
779 			break;
780 		case SCTP_DEFAULT_SEND_PARAM:
781 			if (buflen < sizeof (struct sctp_sndrcvinfo)) {
782 				retval = EINVAL;
783 				break;
784 			}
785 			*optlen = sctp_get_def_send_params(sctp, ptr);
786 			break;
787 		case SCTP_EVENTS: {
788 			struct sctp_event_subscribe *ev;
789 
790 			if (buflen < sizeof (struct sctp_event_subscribe)) {
791 				retval = EINVAL;
792 				break;
793 			}
794 			ev = (struct sctp_event_subscribe *)ptr;
795 			ev->sctp_data_io_event =
796 			    ONOFF(sctp->sctp_recvsndrcvinfo);
797 			ev->sctp_association_event =
798 			    ONOFF(sctp->sctp_recvassocevnt);
799 			ev->sctp_address_event =
800 			    ONOFF(sctp->sctp_recvpathevnt);
801 			ev->sctp_send_failure_event =
802 			    ONOFF(sctp->sctp_recvsendfailevnt);
803 			ev->sctp_peer_error_event =
804 			    ONOFF(sctp->sctp_recvpeererr);
805 			ev->sctp_shutdown_event =
806 			    ONOFF(sctp->sctp_recvshutdownevnt);
807 			ev->sctp_partial_delivery_event =
808 			    ONOFF(sctp->sctp_recvpdevnt);
809 			ev->sctp_adaption_layer_event =
810 				ONOFF(sctp->sctp_recvalevnt);
811 			*optlen = sizeof (struct sctp_event_subscribe);
812 			break;
813 		}
814 		case SCTP_STATUS:
815 			if (buflen < sizeof (struct sctp_status)) {
816 				retval = EINVAL;
817 				break;
818 			}
819 			*optlen = sctp_get_status(sctp, ptr);
820 			break;
821 		case SCTP_GET_PEER_ADDR_INFO:
822 			if (buflen < sizeof (struct sctp_paddrinfo)) {
823 				retval = EINVAL;
824 				break;
825 			}
826 			retval = sctp_get_paddrinfo(sctp, ptr, optlen);
827 			break;
828 		case SCTP_GET_NLADDRS:
829 			*(int32_t *)ptr = sctp->sctp_nsaddrs;
830 			break;
831 		case SCTP_GET_LADDRS: {
832 			int addr_cnt;
833 			int addr_size;
834 
835 			if (sctp->sctp_family == AF_INET)
836 				addr_size = sizeof (struct sockaddr_in);
837 			else
838 				addr_size = sizeof (struct sockaddr_in6);
839 			addr_cnt = buflen / addr_size;
840 			retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt);
841 			if (retval == 0)
842 				*optlen = addr_cnt * addr_size;
843 			break;
844 		}
845 		case SCTP_GET_NPADDRS: {
846 			int i;
847 			sctp_faddr_t *fp;
848 
849 			for (i = 0, fp = sctp->sctp_faddrs; fp != NULL;
850 			    i++, fp = fp->next)
851 				;
852 			*(int32_t *)ptr = i;
853 			break;
854 		}
855 		case SCTP_GET_PADDRS: {
856 			int addr_cnt;
857 			int addr_size;
858 
859 			if (sctp->sctp_family == AF_INET)
860 				addr_size = sizeof (struct sockaddr_in);
861 			else
862 				addr_size = sizeof (struct sockaddr_in6);
863 			addr_cnt = buflen / addr_size;
864 			retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt);
865 			if (retval == 0)
866 				*optlen = addr_cnt * addr_size;
867 			break;
868 		}
869 		case SCTP_PRSCTP:
870 			*i1 = sctp->sctp_prsctp_aware ? 1 : 0;
871 			break;
872 		case SCTP_I_WANT_MAPPED_V4_ADDR:
873 		case SCTP_MAXSEG:
874 		case SCTP_DISABLE_FRAGMENTS:
875 			/* Not yet supported. */
876 		default:
877 			retval = EINVAL;
878 			break;
879 		}
880 		break;
881 
882 	case IPPROTO_IP:
883 		if (sctp->sctp_family != AF_INET) {
884 			retval = EINVAL;
885 			break;
886 		}
887 		switch (name) {
888 		case IP_OPTIONS:
889 		case T_IP_OPTIONS: {
890 			/*
891 			 * This is compatible with BSD in that in only return
892 			 * the reverse source route with the final destination
893 			 * as the last entry. The first 4 bytes of the option
894 			 * will contain the final destination. Allocate a
895 			 * buffer large enough to hold all the options, we
896 			 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since
897 			 * ip_opt_get_user() adds the final destination
898 			 * at the start.
899 			 */
900 			char	*opt_ptr;
901 			int	opt_len;
902 			uchar_t	obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN];
903 
904 			opt_ptr = (char *)sctp->sctp_ipha +
905 			    IP_SIMPLE_HDR_LENGTH;
906 			opt_len = (char *)sctp->sctp_sctph - opt_ptr;
907 			/* Caller ensures enough space */
908 			if (opt_len > 0) {
909 				/*
910 				 * TODO: Do we have to handle getsockopt on an
911 				 * initiator as well?
912 				 */
913 				opt_len = ip_opt_get_user(sctp->sctp_ipha,
914 				    obuf);
915 				ASSERT(opt_len <= sizeof (obuf));
916 			} else {
917 				opt_len = 0;
918 			}
919 			if (buflen < opt_len) {
920 				/* Silently truncate */
921 				opt_len = buflen;
922 			}
923 			*optlen = opt_len;
924 			bcopy(obuf, ptr, opt_len);
925 			break;
926 		}
927 		case IP_TOS:
928 		case T_IP_TOS:
929 			*i1 = (int)sctp->sctp_ipha->ipha_type_of_service;
930 			break;
931 		case IP_TTL:
932 			*i1 = (int)sctp->sctp_ipha->ipha_ttl;
933 			break;
934 		case IP_NEXTHOP:
935 			if (connp->conn_nexthop_set) {
936 				*(ipaddr_t *)ptr = connp->conn_nexthop_v4;
937 				*optlen = sizeof (ipaddr_t);
938 			} else {
939 				*optlen = 0;
940 			}
941 			break;
942 		default:
943 			retval = EINVAL;
944 			break;
945 		}
946 		break;
947 	case IPPROTO_IPV6:
948 		if (sctp->sctp_family != AF_INET6) {
949 			retval = EINVAL;
950 			break;
951 		}
952 		switch (name) {
953 		case IPV6_UNICAST_HOPS:
954 			*i1 = (unsigned int) sctp->sctp_ip6h->ip6_hops;
955 			break;	/* goto sizeof (int) option return */
956 		case IPV6_RECVPKTINFO:
957 			if (sctp->sctp_ipv6_recvancillary &
958 			    SCTP_IPV6_RECVPKTINFO) {
959 				*i1 = 1;
960 			} else {
961 				*i1 = 0;
962 			}
963 			break;	/* goto sizeof (int) option return */
964 		case IPV6_RECVHOPLIMIT:
965 			if (sctp->sctp_ipv6_recvancillary &
966 			    SCTP_IPV6_RECVHOPLIMIT) {
967 				*i1 = 1;
968 			} else {
969 				*i1 = 0;
970 			}
971 			break;	/* goto sizeof (int) option return */
972 		case IPV6_RECVHOPOPTS:
973 			if (sctp->sctp_ipv6_recvancillary &
974 			    SCTP_IPV6_RECVHOPOPTS) {
975 				*i1 = 1;
976 			} else {
977 				*i1 = 0;
978 			}
979 			break;	/* goto sizeof (int) option return */
980 		case IPV6_RECVDSTOPTS:
981 			if (sctp->sctp_ipv6_recvancillary &
982 			    SCTP_IPV6_RECVDSTOPTS) {
983 				*i1 = 1;
984 			} else {
985 				*i1 = 0;
986 			}
987 			break;	/* goto sizeof (int) option return */
988 		case IPV6_RECVRTHDR:
989 			if (sctp->sctp_ipv6_recvancillary &
990 			    SCTP_IPV6_RECVRTHDR) {
991 				*i1 = 1;
992 			} else {
993 				*i1 = 0;
994 			}
995 			break;	/* goto sizeof (int) option return */
996 		case IPV6_RECVRTHDRDSTOPTS:
997 			if (sctp->sctp_ipv6_recvancillary &
998 			    SCTP_IPV6_RECVRTDSTOPTS) {
999 				*i1 = 1;
1000 			} else {
1001 				*i1 = 0;
1002 			}
1003 			break;	/* goto sizeof (int) option return */
1004 		case IPV6_PKTINFO: {
1005 			struct in6_pktinfo *pkti;
1006 
1007 			if (buflen < sizeof (struct in6_pktinfo)) {
1008 				retval = EINVAL;
1009 				break;
1010 			}
1011 			pkti = (struct in6_pktinfo *)ptr;
1012 			if (ipp->ipp_fields & IPPF_IFINDEX)
1013 				pkti->ipi6_ifindex = ipp->ipp_ifindex;
1014 			else
1015 				pkti->ipi6_ifindex = 0;
1016 			if (ipp->ipp_fields & IPPF_ADDR)
1017 				pkti->ipi6_addr = ipp->ipp_addr;
1018 			else
1019 				pkti->ipi6_addr = ipv6_all_zeros;
1020 			*optlen = sizeof (struct in6_pktinfo);
1021 			break;
1022 		}
1023 		case IPV6_NEXTHOP: {
1024 			sin6_t *sin6;
1025 
1026 			if (buflen < sizeof (sin6_t)) {
1027 				retval = EINVAL;
1028 				break;
1029 			}
1030 			sin6 = (sin6_t *)ptr;
1031 			if (!(ipp->ipp_fields & IPPF_NEXTHOP))
1032 				break;
1033 			*sin6 = sctp_sin6_null;
1034 			sin6->sin6_family = AF_INET6;
1035 			sin6->sin6_addr = ipp->ipp_nexthop;
1036 			*optlen = sizeof (sin6_t);
1037 			break;
1038 		}
1039 		case IPV6_HOPOPTS: {
1040 			int len;
1041 
1042 			if (!(ipp->ipp_fields & IPPF_HOPOPTS))
1043 				break;
1044 			len = ipp->ipp_hopoptslen - sctp->sctp_v6label_len;
1045 			if (len <= 0)
1046 				break;
1047 			if (buflen < len) {
1048 				retval = EINVAL;
1049 				break;
1050 			}
1051 			bcopy((char *)ipp->ipp_hopopts +
1052 			    sctp->sctp_v6label_len, ptr, len);
1053 			if (sctp->sctp_v6label_len > 0) {
1054 				char *cptr = ptr;
1055 
1056 				/*
1057 				 * If the label length is greater than zero,
1058 				 * then we need to hide the label from user.
1059 				 * Make it look as though a normal Hop-By-Hop
1060 				 * Options Header is present here.
1061 				 */
1062 				cptr[0] = ((char *)ipp->ipp_hopopts)[0];
1063 				cptr[1] = (len + 7) / 8 - 1;
1064 			}
1065 			*optlen = len;
1066 			break;
1067 		}
1068 		case IPV6_RTHDRDSTOPTS:
1069 			if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
1070 				break;
1071 			if (buflen < ipp->ipp_rtdstoptslen) {
1072 				retval = EINVAL;
1073 				break;
1074 			}
1075 			bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen);
1076 			*optlen  = ipp->ipp_rtdstoptslen;
1077 			break;
1078 		case IPV6_RTHDR:
1079 			if (!(ipp->ipp_fields & IPPF_RTHDR))
1080 				break;
1081 			if (buflen < ipp->ipp_rthdrlen) {
1082 				retval = EINVAL;
1083 				break;
1084 			}
1085 			bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen);
1086 			*optlen = ipp->ipp_rthdrlen;
1087 			break;
1088 		case IPV6_DSTOPTS:
1089 			if (!(ipp->ipp_fields & IPPF_DSTOPTS))
1090 				break;
1091 			if (buflen < ipp->ipp_dstoptslen) {
1092 				retval = EINVAL;
1093 				break;
1094 			}
1095 			bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen);
1096 			*optlen  = ipp->ipp_dstoptslen;
1097 			break;
1098 		case IPV6_V6ONLY:
1099 			*i1 = sctp->sctp_connp->conn_ipv6_v6only;
1100 			break;
1101 		default:
1102 			retval = EINVAL;
1103 			break;
1104 		}
1105 		break;
1106 
1107 	default:
1108 		retval = EINVAL;
1109 		break;
1110 	}
1111 	WAKE_SCTP(sctp);
1112 	return (retval);
1113 }
1114 
1115 int
1116 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp,
1117     socklen_t inlen)
1118 {
1119 	ip6_pkt_t	*ipp = &sctp->sctp_sticky_ipp;
1120 	int		*i1 = (int *)invalp;
1121 	boolean_t	onoff;
1122 	int		retval = 0, addrcnt;
1123 	conn_t		*connp = sctp->sctp_connp;
1124 
1125 	/* In all cases, the size of the option must be bigger than int */
1126 	if (inlen >= sizeof (int32_t)) {
1127 		onoff = ONOFF(*i1);
1128 	}
1129 	retval = 0;
1130 
1131 	RUN_SCTP(sctp);
1132 
1133 	switch (level) {
1134 	case SOL_SOCKET:
1135 		if (inlen < sizeof (int32_t)) {
1136 			retval = EINVAL;
1137 			break;
1138 		}
1139 		switch (name) {
1140 		case SO_LINGER: {
1141 			struct linger *lgr;
1142 
1143 			if (inlen != sizeof (struct linger)) {
1144 				retval = EINVAL;
1145 				break;
1146 			}
1147 			lgr = (struct linger *)invalp;
1148 			if (lgr->l_onoff != 0) {
1149 				sctp->sctp_linger = 1;
1150 				sctp->sctp_lingertime = MSEC_TO_TICK(
1151 				    lgr->l_linger);
1152 			} else {
1153 				sctp->sctp_linger = 0;
1154 				sctp->sctp_lingertime = 0;
1155 			}
1156 			break;
1157 		}
1158 		case SO_DEBUG:
1159 			sctp->sctp_debug = onoff;
1160 			break;
1161 		case SO_KEEPALIVE:
1162 			break;
1163 		case SO_DONTROUTE:
1164 			/*
1165 			 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are
1166 			 * only of interest to IP.  We track them here only so
1167 			 * that we can report their current value.
1168 			 */
1169 			sctp->sctp_dontroute = onoff;
1170 			connp->conn_dontroute = onoff;
1171 			break;
1172 		case SO_USELOOPBACK:
1173 			sctp->sctp_useloopback = onoff;
1174 			connp->conn_loopback = onoff;
1175 			break;
1176 		case SO_BROADCAST:
1177 			sctp->sctp_broadcast = onoff;
1178 			connp->conn_broadcast = onoff;
1179 			break;
1180 		case SO_REUSEADDR:
1181 			sctp->sctp_reuseaddr = onoff;
1182 			connp->conn_reuseaddr = onoff;
1183 			break;
1184 		case SO_DGRAM_ERRIND:
1185 			sctp->sctp_dgram_errind = onoff;
1186 			break;
1187 		case SO_SNDBUF:
1188 			if (*i1 > sctp_max_buf) {
1189 				retval = ENOBUFS;
1190 				break;
1191 			}
1192 			if (*i1 < 0) {
1193 				retval = EINVAL;
1194 				break;
1195 			}
1196 			sctp->sctp_xmit_hiwater = *i1;
1197 			if (sctp_snd_lowat_fraction != 0)
1198 				sctp->sctp_xmit_lowater =
1199 				    sctp->sctp_xmit_hiwater /
1200 				    sctp_snd_lowat_fraction;
1201 			break;
1202 		case SO_RCVBUF:
1203 			if (*i1 > sctp_max_buf) {
1204 				retval = ENOBUFS;
1205 				break;
1206 			}
1207 			/* Silently ignore zero */
1208 			if (*i1 != 0) {
1209 				/*
1210 				 * Insist on a receive window that is at least
1211 				 * sctp_recv_hiwat_minmss * MSS (default 4*MSS)
1212 				 * to avoid funny interactions of Nagle
1213 				 * algorithm, SWS avoidance and delayed
1214 				 * acknowledgement.
1215 				 */
1216 				*i1 = MAX(*i1,
1217 				    sctp_recv_hiwat_minmss * sctp->sctp_mss);
1218 				sctp->sctp_rwnd = *i1;
1219 				sctp->sctp_irwnd = sctp->sctp_rwnd;
1220 			}
1221 			/*
1222 			 * XXX should we return the rwnd here
1223 			 * and sctp_opt_get ?
1224 			 */
1225 			break;
1226 		case SO_MAC_EXEMPT:
1227 			if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0 ||
1228 			    sctp->sctp_state >= SCTPS_BOUND) {
1229 				retval = EACCES;
1230 			} else {
1231 				sctp->sctp_mac_exempt = onoff;
1232 				connp->conn_mac_exempt = onoff;
1233 			}
1234 			break;
1235 		default:
1236 			retval = EINVAL;
1237 			break;
1238 		}
1239 		break;
1240 
1241 	case IPPROTO_SCTP:
1242 		if (inlen < sizeof (int32_t)) {
1243 			retval = EINVAL;
1244 			break;
1245 		}
1246 		switch (name) {
1247 		case SCTP_RTOINFO:
1248 			retval = sctp_set_rtoinfo(sctp, invalp, inlen);
1249 			break;
1250 		case SCTP_ASSOCINFO:
1251 			retval = sctp_set_assocparams(sctp, invalp, inlen);
1252 			break;
1253 		case SCTP_INITMSG:
1254 			retval = sctp_set_initmsg(sctp, invalp, inlen);
1255 			break;
1256 		case SCTP_NODELAY:
1257 			sctp->sctp_ndelay = ONOFF(*i1);
1258 			break;
1259 		case SCTP_AUTOCLOSE:
1260 			if (SEC_TO_TICK(*i1) < 0) {
1261 				retval = EINVAL;
1262 				break;
1263 			}
1264 			/* Convert the number of seconds to ticks. */
1265 			sctp->sctp_autoclose = SEC_TO_TICK(*i1);
1266 			sctp_heartbeat_timer(sctp);
1267 			break;
1268 		case SCTP_SET_PEER_PRIMARY_ADDR:
1269 			retval = sctp_set_peerprim(sctp, invalp, inlen);
1270 			break;
1271 		case SCTP_PRIMARY_ADDR:
1272 			retval = sctp_set_prim(sctp, invalp, inlen);
1273 			break;
1274 		case SCTP_ADAPTION_LAYER: {
1275 			struct sctp_setadaption *ssb;
1276 
1277 			if (inlen < sizeof (struct sctp_setadaption)) {
1278 				retval = EINVAL;
1279 				break;
1280 			}
1281 			ssb = (struct sctp_setadaption *)invalp;
1282 			sctp->sctp_send_adaption = 1;
1283 			sctp->sctp_tx_adaption_code = ssb->ssb_adaption_ind;
1284 			break;
1285 		}
1286 		case SCTP_PEER_ADDR_PARAMS:
1287 			retval = sctp_set_peer_addr_params(sctp, invalp,
1288 			    inlen);
1289 			break;
1290 		case SCTP_DEFAULT_SEND_PARAM:
1291 			retval = sctp_set_def_send_params(sctp, invalp, inlen);
1292 			break;
1293 		case SCTP_EVENTS: {
1294 			struct sctp_event_subscribe *ev;
1295 
1296 			if (inlen < sizeof (struct sctp_event_subscribe)) {
1297 				retval = EINVAL;
1298 				break;
1299 			}
1300 			ev = (struct sctp_event_subscribe *)invalp;
1301 			sctp->sctp_recvsndrcvinfo =
1302 			    ONOFF(ev->sctp_data_io_event);
1303 			sctp->sctp_recvassocevnt =
1304 			    ONOFF(ev->sctp_association_event);
1305 			sctp->sctp_recvpathevnt =
1306 			    ONOFF(ev->sctp_address_event);
1307 			sctp->sctp_recvsendfailevnt =
1308 			    ONOFF(ev->sctp_send_failure_event);
1309 			sctp->sctp_recvpeererr =
1310 			    ONOFF(ev->sctp_peer_error_event);
1311 			sctp->sctp_recvshutdownevnt =
1312 			    ONOFF(ev->sctp_shutdown_event);
1313 			sctp->sctp_recvpdevnt =
1314 			    ONOFF(ev->sctp_partial_delivery_event);
1315 			sctp->sctp_recvalevnt =
1316 				ONOFF(ev->sctp_adaption_layer_event);
1317 			break;
1318 		}
1319 		case SCTP_ADD_ADDR:
1320 		case SCTP_REM_ADDR:
1321 			/*
1322 			 * The sctp_t has to be bound first before
1323 			 * the address list can be changed.
1324 			 */
1325 			if (sctp->sctp_state < SCTPS_BOUND) {
1326 				retval = EINVAL;
1327 				break;
1328 			}
1329 			if (sctp->sctp_family == AF_INET) {
1330 				addrcnt = inlen / sizeof (struct sockaddr_in);
1331 			} else {
1332 				ASSERT(sctp->sctp_family == AF_INET6);
1333 				addrcnt = inlen / sizeof (struct sockaddr_in6);
1334 			}
1335 			if (name == SCTP_ADD_ADDR) {
1336 				retval = sctp_bind_add(sctp, invalp, addrcnt,
1337 				    B_TRUE, sctp->sctp_lport);
1338 			} else {
1339 				retval = sctp_bind_del(sctp, invalp, addrcnt,
1340 				    B_TRUE);
1341 			}
1342 			break;
1343 		case SCTP_UC_SWAP: {
1344 			struct sctp_uc_swap *us;
1345 
1346 			/*
1347 			 * Change handle & upcalls.
1348 			 */
1349 			if (inlen < sizeof (*us)) {
1350 				retval = EINVAL;
1351 				break;
1352 			}
1353 			us = (struct sctp_uc_swap *)invalp;
1354 			sctp->sctp_ulpd = us->sus_handle;
1355 			bcopy(us->sus_upcalls, &sctp->sctp_upcalls,
1356 			    sizeof (sctp_upcalls_t));
1357 			break;
1358 		}
1359 		case SCTP_PRSCTP:
1360 			sctp->sctp_prsctp_aware = onoff;
1361 			break;
1362 		case SCTP_I_WANT_MAPPED_V4_ADDR:
1363 		case SCTP_MAXSEG:
1364 		case SCTP_DISABLE_FRAGMENTS:
1365 			/* Not yet supported. */
1366 		default:
1367 			retval = EINVAL;
1368 			break;
1369 		}
1370 		break;
1371 
1372 	case IPPROTO_IP:
1373 		if (sctp->sctp_family != AF_INET) {
1374 			retval = ENOPROTOOPT;
1375 			break;
1376 		}
1377 		if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) {
1378 			retval = EINVAL;
1379 			break;
1380 		}
1381 		switch (name) {
1382 		case IP_OPTIONS:
1383 		case T_IP_OPTIONS:
1384 			retval = sctp_opt_set_header(sctp, invalp, inlen);
1385 			break;
1386 		case IP_TOS:
1387 		case T_IP_TOS:
1388 			sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1;
1389 			break;
1390 		case IP_TTL:
1391 			sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1;
1392 			break;
1393 		case IP_SEC_OPT:
1394 			/*
1395 			 * We should not allow policy setting after
1396 			 * we start listening for connections.
1397 			 */
1398 			if (sctp->sctp_state >= SCTPS_LISTEN) {
1399 				retval = EINVAL;
1400 			} else {
1401 				retval = ipsec_set_req(sctp->sctp_credp,
1402 				    sctp->sctp_connp, (ipsec_req_t *)invalp);
1403 			}
1404 			break;
1405 		/* IP level options */
1406 		case IP_RECVIF:
1407 			connp->conn_recvif = onoff;
1408 			break;
1409 		case IP_RECVSLLA:
1410 			connp->conn_recvslla = onoff;
1411 			break;
1412 		case IP_UNSPEC_SRC:
1413 			connp->conn_unspec_src = onoff;
1414 			break;
1415 		case IP_NEXTHOP: {
1416 			ipaddr_t addr = *i1;
1417 			ipif_t *ipif = NULL;
1418 			ill_t *ill;
1419 
1420 			if (secpolicy_net(CRED(), OP_CONFIG, B_TRUE) == 0) {
1421 				ipif =
1422 				    ipif_lookup_onlink_addr(addr,
1423 				    connp->conn_zoneid);
1424 				if (ipif == NULL) {
1425 					retval = EHOSTUNREACH;
1426 					break;
1427 				}
1428 				ill = ipif->ipif_ill;
1429 				mutex_enter(&ill->ill_lock);
1430 				if ((ill->ill_state_flags & ILL_CONDEMNED) ||
1431 				    (ipif->ipif_state_flags & IPIF_CONDEMNED)) {
1432 					mutex_exit(&ill->ill_lock);
1433 					ipif_refrele(ipif);
1434 					retval =  EHOSTUNREACH;
1435 					break;
1436 				}
1437 				mutex_exit(&ill->ill_lock);
1438 				ipif_refrele(ipif);
1439 				mutex_enter(&connp->conn_lock);
1440 				connp->conn_nexthop_v4 = addr;
1441 				connp->conn_nexthop_set = B_TRUE;
1442 				mutex_exit(&connp->conn_lock);
1443 			}
1444 			break;
1445 		}
1446 		default:
1447 			retval = EINVAL;
1448 			break;
1449 		}
1450 		break;
1451 	case IPPROTO_IPV6: {
1452 		if (sctp->sctp_family != AF_INET6) {
1453 			retval = ENOPROTOOPT;
1454 			break;
1455 		}
1456 
1457 		switch (name) {
1458 		case IPV6_UNICAST_HOPS:
1459 			if (inlen < sizeof (int32_t)) {
1460 				retval = EINVAL;
1461 				break;
1462 			}
1463 			if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) {
1464 				retval = EINVAL;
1465 				break;
1466 			}
1467 			if (*i1 == -1) {
1468 				ipp->ipp_unicast_hops = sctp_ipv6_hoplimit;
1469 				ipp->ipp_fields &= ~IPPF_UNICAST_HOPS;
1470 			} else {
1471 				ipp->ipp_unicast_hops = (uint8_t)*i1;
1472 				ipp->ipp_fields |= IPPF_UNICAST_HOPS;
1473 			}
1474 			retval = sctp_build_hdrs(sctp);
1475 			break;
1476 		case IPV6_UNSPEC_SRC:
1477 			if (inlen < sizeof (int32_t)) {
1478 				retval = EINVAL;
1479 				break;
1480 			}
1481 			connp->conn_unspec_src = onoff;
1482 			break;
1483 		case IPV6_RECVPKTINFO:
1484 			if (inlen < sizeof (int32_t)) {
1485 				retval = EINVAL;
1486 				break;
1487 			}
1488 			if (onoff)
1489 				sctp->sctp_ipv6_recvancillary |=
1490 				    SCTP_IPV6_RECVPKTINFO;
1491 			else
1492 				sctp->sctp_ipv6_recvancillary &=
1493 				    ~SCTP_IPV6_RECVPKTINFO;
1494 			/* Send it with the next msg */
1495 			sctp->sctp_recvifindex = 0;
1496 			connp->conn_ipv6_recvpktinfo = onoff;
1497 			break;
1498 		case IPV6_RECVHOPLIMIT:
1499 			if (inlen < sizeof (int32_t)) {
1500 				retval = EINVAL;
1501 				break;
1502 			}
1503 			if (onoff)
1504 				sctp->sctp_ipv6_recvancillary |=
1505 				    SCTP_IPV6_RECVHOPLIMIT;
1506 			else
1507 				sctp->sctp_ipv6_recvancillary &=
1508 				    ~SCTP_IPV6_RECVHOPLIMIT;
1509 			sctp->sctp_recvhops = 0xffffffffU;
1510 			connp->conn_ipv6_recvhoplimit = onoff;
1511 			break;
1512 		case IPV6_RECVHOPOPTS:
1513 			if (inlen < sizeof (int32_t)) {
1514 				retval = EINVAL;
1515 				break;
1516 			}
1517 			if (onoff)
1518 				sctp->sctp_ipv6_recvancillary |=
1519 				    SCTP_IPV6_RECVHOPOPTS;
1520 			else
1521 				sctp->sctp_ipv6_recvancillary &=
1522 				    ~SCTP_IPV6_RECVHOPOPTS;
1523 			connp->conn_ipv6_recvhopopts = onoff;
1524 			break;
1525 		case IPV6_RECVDSTOPTS:
1526 			if (inlen < sizeof (int32_t)) {
1527 				retval = EINVAL;
1528 				break;
1529 			}
1530 			if (onoff)
1531 				sctp->sctp_ipv6_recvancillary |=
1532 				    SCTP_IPV6_RECVDSTOPTS;
1533 			else
1534 				sctp->sctp_ipv6_recvancillary &=
1535 				    ~SCTP_IPV6_RECVDSTOPTS;
1536 			connp->conn_ipv6_recvdstopts = onoff;
1537 			break;
1538 		case IPV6_RECVRTHDR:
1539 			if (inlen < sizeof (int32_t)) {
1540 				retval = EINVAL;
1541 				break;
1542 			}
1543 			if (onoff)
1544 				sctp->sctp_ipv6_recvancillary |=
1545 				    SCTP_IPV6_RECVRTHDR;
1546 			else
1547 				sctp->sctp_ipv6_recvancillary &=
1548 				    ~SCTP_IPV6_RECVRTHDR;
1549 			connp->conn_ipv6_recvrthdr = onoff;
1550 			break;
1551 		case IPV6_RECVRTHDRDSTOPTS:
1552 			if (inlen < sizeof (int32_t)) {
1553 				retval = EINVAL;
1554 				break;
1555 			}
1556 			if (onoff)
1557 				sctp->sctp_ipv6_recvancillary |=
1558 				    SCTP_IPV6_RECVRTDSTOPTS;
1559 			else
1560 				sctp->sctp_ipv6_recvancillary &=
1561 				    ~SCTP_IPV6_RECVRTDSTOPTS;
1562 			connp->conn_ipv6_recvrtdstopts = onoff;
1563 			break;
1564 		case IPV6_PKTINFO:
1565 			if (inlen != 0 &&
1566 			    inlen != sizeof (struct in6_pktinfo)) {
1567 				retval = EINVAL;
1568 				break;
1569 			}
1570 
1571 			if (inlen == 0) {
1572 				ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR);
1573 			} else  {
1574 				struct in6_pktinfo *pkti;
1575 
1576 				pkti = (struct in6_pktinfo *)invalp;
1577 				/* XXX Need to check if the index exists */
1578 				ipp->ipp_ifindex = pkti->ipi6_ifindex;
1579 				ipp->ipp_addr = pkti->ipi6_addr;
1580 				if (ipp->ipp_ifindex != 0)
1581 					ipp->ipp_fields |= IPPF_IFINDEX;
1582 				else
1583 					ipp->ipp_fields &= ~IPPF_IFINDEX;
1584 				if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr))
1585 					ipp->ipp_fields |= IPPF_ADDR;
1586 				else
1587 					ipp->ipp_fields &= ~IPPF_ADDR;
1588 			}
1589 			retval = sctp_build_hdrs(sctp);
1590 			break;
1591 		case IPV6_NEXTHOP: {
1592 			struct sockaddr_in6 *sin6;
1593 
1594 			if (inlen != 0 && inlen != sizeof (sin6_t)) {
1595 				retval = EINVAL;
1596 				break;
1597 			}
1598 
1599 			if (inlen == 0) {
1600 				ipp->ipp_fields &= ~IPPF_NEXTHOP;
1601 			} else {
1602 				sin6 = (struct sockaddr_in6 *)invalp;
1603 				if (sin6->sin6_family != AF_INET6) {
1604 					retval = EAFNOSUPPORT;
1605 					break;
1606 				}
1607 				if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1608 					retval = EADDRNOTAVAIL;
1609 					break;
1610 				}
1611 				ipp->ipp_nexthop = sin6->sin6_addr;
1612 				if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1613 					ipp->ipp_fields &= ~IPPF_NEXTHOP;
1614 				} else {
1615 					ire_t	*ire;
1616 
1617 					ire = ire_route_lookup_v6(
1618 					    &sin6->sin6_addr, NULL, NULL, 0,
1619 					    NULL, NULL, ALL_ZONES, NULL,
1620 					    MATCH_IRE_DEFAULT);
1621 					if (ire == NULL) {
1622 						retval = EHOSTUNREACH;
1623 						break;
1624 					}
1625 					ire_refrele(ire);
1626 					ipp->ipp_fields |= IPPF_NEXTHOP;
1627 				}
1628 			}
1629 			retval = sctp_build_hdrs(sctp);
1630 			break;
1631 		}
1632 		case IPV6_HOPOPTS: {
1633 			ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
1634 
1635 			if (inlen != 0 &&
1636 			    inlen != (8 * (hopts->ip6h_len + 1))) {
1637 				retval = EINVAL;
1638 				break;
1639 			}
1640 
1641 			retval = optcom_pkt_set((uchar_t *)invalp, inlen,
1642 			    B_TRUE, (uchar_t **)&ipp->ipp_hopopts,
1643 			    &ipp->ipp_hopoptslen, sctp->sctp_v6label_len);
1644 			if (retval != 0)
1645 				break;
1646 			if (ipp->ipp_hopoptslen == 0)
1647 				ipp->ipp_fields &= ~IPPF_HOPOPTS;
1648 			else
1649 				ipp->ipp_fields |= IPPF_HOPOPTS;
1650 			retval = sctp_build_hdrs(sctp);
1651 			break;
1652 		}
1653 		case IPV6_RTHDRDSTOPTS: {
1654 			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
1655 
1656 			if (inlen != 0 &&
1657 			    inlen != (8 * (dopts->ip6d_len + 1))) {
1658 				retval = EINVAL;
1659 				break;
1660 			}
1661 
1662 			retval = optcom_pkt_set((uchar_t *)invalp, inlen,
1663 			    B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts,
1664 			    &ipp->ipp_rtdstoptslen, 0);
1665 			if (retval != 0)
1666 				break;
1667 			if (ipp->ipp_rtdstoptslen == 0)
1668 				ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
1669 			else
1670 				ipp->ipp_fields |= IPPF_RTDSTOPTS;
1671 			retval = sctp_build_hdrs(sctp);
1672 			break;
1673 		}
1674 		case IPV6_DSTOPTS: {
1675 			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
1676 
1677 			if (inlen != 0 &&
1678 			    inlen != (8 * (dopts->ip6d_len + 1))) {
1679 				retval = EINVAL;
1680 				break;
1681 			}
1682 
1683 			retval = optcom_pkt_set((uchar_t *)invalp, inlen,
1684 			    B_TRUE, (uchar_t **)&ipp->ipp_dstopts,
1685 			    &ipp->ipp_dstoptslen, 0);
1686 			if (retval != 0)
1687 				break;
1688 			if (ipp->ipp_dstoptslen == 0)
1689 				ipp->ipp_fields &= ~IPPF_DSTOPTS;
1690 			else
1691 				ipp->ipp_fields |= IPPF_DSTOPTS;
1692 			retval = sctp_build_hdrs(sctp);
1693 			break;
1694 		}
1695 		case IPV6_RTHDR: {
1696 			ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp;
1697 
1698 			if (inlen != 0 &&
1699 			    inlen != (8 * (rt->ip6r_len + 1))) {
1700 				retval = EINVAL;
1701 				break;
1702 			}
1703 
1704 			retval = optcom_pkt_set((uchar_t *)invalp, inlen,
1705 			    B_TRUE, (uchar_t **)&ipp->ipp_rthdr,
1706 			    &ipp->ipp_rthdrlen, 0);
1707 			if (retval != 0)
1708 				break;
1709 			if (ipp->ipp_rthdrlen == 0)
1710 				ipp->ipp_fields &= ~IPPF_RTHDR;
1711 			else
1712 				ipp->ipp_fields |= IPPF_RTHDR;
1713 			retval = sctp_build_hdrs(sctp);
1714 			break;
1715 		}
1716 		case IPV6_SEC_OPT:
1717 			/*
1718 			 * We should not allow policy setting after
1719 			 * we start listening for connections.
1720 			 */
1721 			if (sctp->sctp_state >= SCTPS_LISTEN) {
1722 				retval = EINVAL;
1723 			} else {
1724 				retval = ipsec_set_req(sctp->sctp_credp,
1725 				    sctp->sctp_connp, (ipsec_req_t *)invalp);
1726 			}
1727 			break;
1728 		case IPV6_V6ONLY:
1729 			/*
1730 			 * After the bound state, setting the v6only option
1731 			 * is too late.
1732 			 */
1733 			if (sctp->sctp_state >= SCTPS_BOUND) {
1734 				retval = EINVAL;
1735 			} else {
1736 				sctp->sctp_connp->conn_ipv6_v6only = onoff;
1737 			}
1738 			break;
1739 		default:
1740 			retval = EINVAL;
1741 			break;
1742 		}
1743 		break;
1744 	}
1745 	default:
1746 		retval = EINVAL;
1747 		break;
1748 	}
1749 
1750 	WAKE_SCTP(sctp);
1751 	return (retval);
1752 }
1753 
1754 /*
1755  * SCTP exported kernel interface for geting the first source address of
1756  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1757  * one socket address.
1758  */
1759 int
1760 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1761 {
1762 	int	err = 0;
1763 	int	addrcnt = 1;
1764 	sin_t	*sin4;
1765 	sin6_t	*sin6;
1766 
1767 	ASSERT(sctp != NULL);
1768 
1769 	RUN_SCTP(sctp);
1770 	addr->sa_family = sctp->sctp_family;
1771 	switch (sctp->sctp_family) {
1772 	case AF_INET:
1773 		sin4 = (sin_t *)addr;
1774 		if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1775 		    sctp->sctp_bound_to_all) {
1776 			sin4->sin_addr.s_addr = INADDR_ANY;
1777 			sin4->sin_port = sctp->sctp_lport;
1778 		} else {
1779 			err = sctp_getmyaddrs(sctp, sin4, &addrcnt);
1780 			if (err != 0) {
1781 				*addrlen = 0;
1782 				break;
1783 			}
1784 		}
1785 		*addrlen = sizeof (struct sockaddr_in);
1786 		break;
1787 	case AF_INET6:
1788 		sin6 = (sin6_t *)addr;
1789 		if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1790 		    sctp->sctp_bound_to_all) {
1791 			bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
1792 			sin6->sin6_port = sctp->sctp_lport;
1793 		} else {
1794 			err = sctp_getmyaddrs(sctp, sin6, &addrcnt);
1795 			if (err != 0) {
1796 				*addrlen = 0;
1797 				break;
1798 			}
1799 		}
1800 		*addrlen = sizeof (struct sockaddr_in6);
1801 		sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf &
1802 		    ~IPV6_VERS_AND_FLOW_MASK;
1803 		sin6->sin6_scope_id = 0;
1804 		sin6->__sin6_src_id = 0;
1805 		break;
1806 	}
1807 	WAKE_SCTP(sctp);
1808 	return (err);
1809 }
1810 
1811 /*
1812  * SCTP exported kernel interface for geting the primary peer address of
1813  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1814  * one socket address.
1815  */
1816 int
1817 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1818 {
1819 	int	err = 0;
1820 	int	addrcnt = 1;
1821 	sin6_t	*sin6;
1822 
1823 	ASSERT(sctp != NULL);
1824 
1825 	RUN_SCTP(sctp);
1826 	addr->sa_family = sctp->sctp_family;
1827 	switch (sctp->sctp_family) {
1828 	case AF_INET:
1829 		err = sctp_getpeeraddrs(sctp, addr, &addrcnt);
1830 		if (err != 0) {
1831 			*addrlen = 0;
1832 			break;
1833 		}
1834 		*addrlen = sizeof (struct sockaddr_in);
1835 		break;
1836 	case AF_INET6:
1837 		sin6 = (sin6_t *)addr;
1838 		err = sctp_getpeeraddrs(sctp, sin6, &addrcnt);
1839 		if (err != 0) {
1840 			*addrlen = 0;
1841 			break;
1842 		}
1843 		*addrlen = sizeof (struct sockaddr_in6);
1844 		sin6->sin6_flowinfo = 0;
1845 		sin6->sin6_scope_id = 0;
1846 		sin6->__sin6_src_id = 0;
1847 		break;
1848 	}
1849 	WAKE_SCTP(sctp);
1850 	return (err);
1851 }
1852 
1853 /*
1854  * Return a list of IP addresses of the peer endpoint of this sctp_t.
1855  * The parameter paddrs is supposed to be either (struct sockaddr_in *) or
1856  * (struct sockaddr_in6 *) depending on the address family of the sctp_t.
1857  */
1858 int
1859 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt)
1860 {
1861 	int			family;
1862 	struct sockaddr_in	*sin4;
1863 	struct sockaddr_in6	*sin6;
1864 	int			max;
1865 	int			cnt;
1866 	sctp_faddr_t		*fp = sctp->sctp_faddrs;
1867 	in6_addr_t		addr;
1868 
1869 	ASSERT(sctp != NULL);
1870 
1871 	if (sctp->sctp_faddrs == NULL)
1872 		return (ENOTCONN);
1873 
1874 	family = sctp->sctp_family;
1875 	max = *addrcnt;
1876 
1877 	/* If we want only one, give the primary */
1878 	if (max == 1) {
1879 		addr = sctp->sctp_primary->faddr;
1880 		switch (family) {
1881 		case AF_INET:
1882 			sin4 = paddrs;
1883 			IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1884 			sin4->sin_port = sctp->sctp_fport;
1885 			sin4->sin_family = AF_INET;
1886 			break;
1887 
1888 		case AF_INET6:
1889 			sin6 = paddrs;
1890 			sin6->sin6_addr = addr;
1891 			sin6->sin6_port = sctp->sctp_fport;
1892 			sin6->sin6_family = AF_INET6;
1893 			break;
1894 		}
1895 		return (0);
1896 	}
1897 
1898 	for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) {
1899 		addr = fp->faddr;
1900 		switch (family) {
1901 		case AF_INET:
1902 			ASSERT(IN6_IS_ADDR_V4MAPPED(&addr));
1903 			sin4 = (struct sockaddr_in *)paddrs + cnt;
1904 			IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1905 			sin4->sin_port = sctp->sctp_fport;
1906 			sin4->sin_family = AF_INET;
1907 			break;
1908 		case AF_INET6:
1909 			sin6 = (struct sockaddr_in6 *)paddrs + cnt;
1910 			sin6->sin6_addr = addr;
1911 			sin6->sin6_port = sctp->sctp_fport;
1912 			sin6->sin6_family = AF_INET6;
1913 			break;
1914 		}
1915 	}
1916 	*addrcnt = cnt;
1917 	return (0);
1918 }
1919