xref: /illumos-gate/usr/src/uts/common/inet/sctp/sctp_opt_data.c (revision 08292a06bdfa570d21571965b7bd0f053b3aaaa5)
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 /*
23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Copyright (c) 2018, Joyent, Inc.
28  * Copyright 2024 Oxide Computer Company
29  * Copyright 2026 Edgecast Cloud LLC.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/stream.h>
34 #define	_SUN_TPI_VERSION 2
35 #include <sys/tihdr.h>
36 #include <sys/socket.h>
37 #include <sys/xti_inet.h>
38 #include <sys/systm.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/kmem.h>
42 #include <sys/strsubr.h>
43 #include <sys/strsun.h>
44 #include <sys/policy.h>
45 
46 #include <inet/common.h>
47 #include <netinet/ip6.h>
48 #include <inet/ip.h>
49 #include <inet/ip_ire.h>
50 #include <inet/ip_if.h>
51 #include <inet/proto_set.h>
52 #include <inet/ipclassifier.h>
53 #include <inet/ipsec_impl.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/ip.h>
57 #include <netinet/tcp.h>
58 
59 #include <inet/common.h>
60 #include <inet/ip.h>
61 #include <inet/ip6.h>
62 #include <inet/sctp_itf.h>
63 #include "sctp_impl.h"
64 #include "sctp_asconf.h"
65 #include "sctp_addr.h"
66 
67 static int	sctp_getpeeraddrs(sctp_t *, void *, int *);
68 
69 static int
sctp_get_status(sctp_t * sctp,void * ptr)70 sctp_get_status(sctp_t *sctp, void *ptr)
71 {
72 	struct sctp_status *sstat = ptr;
73 	sctp_faddr_t *fp;
74 	struct sockaddr_in *sin;
75 	struct sockaddr_in6 *sin6;
76 	struct sctp_paddrinfo *sp;
77 	mblk_t *meta, *mp;
78 	int i;
79 	conn_t	*connp = sctp->sctp_connp;
80 
81 	sstat->sstat_state = sctp->sctp_state;
82 	sstat->sstat_rwnd = sctp->sctp_frwnd;
83 
84 	sp = &sstat->sstat_primary;
85 	if (!sctp->sctp_primary) {
86 		bzero(sp, sizeof (*sp));
87 		goto noprim;
88 	}
89 	fp = sctp->sctp_primary;
90 
91 	if (fp->sf_isv4) {
92 		sin = (struct sockaddr_in *)&sp->spinfo_address;
93 		sin->sin_family = AF_INET;
94 		sin->sin_port = connp->conn_fport;
95 		IN6_V4MAPPED_TO_INADDR(&fp->sf_faddr, &sin->sin_addr);
96 		sp->spinfo_mtu = sctp->sctp_hdr_len;
97 	} else {
98 		sin6 = (struct sockaddr_in6 *)&sp->spinfo_address;
99 		sin6->sin6_family = AF_INET6;
100 		sin6->sin6_port = connp->conn_fport;
101 		sin6->sin6_addr = fp->sf_faddr;
102 		sp->spinfo_mtu = sctp->sctp_hdr6_len;
103 	}
104 	sp->spinfo_state = fp->sf_state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE :
105 	    SCTP_INACTIVE;
106 	sp->spinfo_cwnd = fp->sf_cwnd;
107 	sp->spinfo_srtt = fp->sf_srtt;
108 	sp->spinfo_rto = fp->sf_rto;
109 	sp->spinfo_mtu += fp->sf_pmss;
110 
111 noprim:
112 	sstat->sstat_unackdata = 0;
113 	sstat->sstat_penddata = 0;
114 	sstat->sstat_instrms = sctp->sctp_num_istr;
115 	sstat->sstat_outstrms = sctp->sctp_num_ostr;
116 	sstat->sstat_fragmentation_point = sctp->sctp_mss -
117 	    sizeof (sctp_data_hdr_t);
118 
119 	/* count unack'd */
120 	for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) {
121 		for (mp = meta->b_cont; mp; mp = mp->b_next) {
122 			if (!SCTP_CHUNK_ISSENT(mp)) {
123 				break;
124 			}
125 			if (!SCTP_CHUNK_ISACKED(mp)) {
126 				sstat->sstat_unackdata++;
127 			}
128 		}
129 	}
130 
131 	/*
132 	 * Count penddata chunks. We can only count chunks in SCTP (not
133 	 * data already delivered to socket layer).
134 	 */
135 	if (sctp->sctp_instr != NULL) {
136 		for (i = 0; i < sctp->sctp_num_istr; i++) {
137 			for (meta = sctp->sctp_instr[i].istr_reass;
138 			    meta != NULL; meta = meta->b_next) {
139 				for (mp = meta->b_cont; mp; mp = mp->b_cont) {
140 					if (DB_TYPE(mp) != M_CTL) {
141 						sstat->sstat_penddata++;
142 					}
143 				}
144 			}
145 		}
146 	}
147 	/* Un-Ordered Frag list */
148 	for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next)
149 		sstat->sstat_penddata++;
150 
151 	return (sizeof (*sstat));
152 }
153 
154 /*
155  * SCTP_GET_PEER_ADDR_INFO
156  */
157 static int
sctp_get_paddrinfo(sctp_t * sctp,void * ptr,socklen_t * optlen)158 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen)
159 {
160 	struct sctp_paddrinfo	*infop = ptr;
161 	struct sockaddr_in	*sin4;
162 	struct sockaddr_in6	*sin6;
163 	in6_addr_t		faddr;
164 	sctp_faddr_t		*fp;
165 
166 	switch (infop->spinfo_address.ss_family) {
167 	case AF_INET:
168 		sin4 = (struct sockaddr_in *)&infop->spinfo_address;
169 		IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr);
170 		break;
171 	case AF_INET6:
172 		sin6 = (struct sockaddr_in6 *)&infop->spinfo_address;
173 		faddr = sin6->sin6_addr;
174 		break;
175 	default:
176 		return (EAFNOSUPPORT);
177 	}
178 
179 	if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL)
180 		return (EINVAL);
181 
182 	infop->spinfo_state = (fp->sf_state == SCTP_FADDRS_ALIVE) ?
183 	    SCTP_ACTIVE : SCTP_INACTIVE;
184 	infop->spinfo_cwnd = fp->sf_cwnd;
185 	infop->spinfo_srtt = TICK_TO_MSEC(fp->sf_srtt);
186 	infop->spinfo_rto = TICK_TO_MSEC(fp->sf_rto);
187 	infop->spinfo_mtu = fp->sf_pmss;
188 
189 	*optlen = sizeof (struct sctp_paddrinfo);
190 	return (0);
191 }
192 
193 /*
194  * SCTP_RTOINFO
195  */
196 static int
sctp_get_rtoinfo(sctp_t * sctp,void * ptr)197 sctp_get_rtoinfo(sctp_t *sctp, void *ptr)
198 {
199 	struct sctp_rtoinfo *srto = ptr;
200 
201 	srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial);
202 	srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max);
203 	srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min);
204 
205 	return (sizeof (*srto));
206 }
207 
208 static int
sctp_set_rtoinfo(sctp_t * sctp,const void * invalp)209 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp)
210 {
211 	const struct sctp_rtoinfo *srto;
212 	boolean_t ispriv;
213 	sctp_stack_t	*sctps = sctp->sctp_sctps;
214 	conn_t		*connp = sctp->sctp_connp;
215 	uint32_t	new_min, new_max;
216 
217 	srto = invalp;
218 
219 	ispriv = secpolicy_ip_config(connp->conn_cred, B_TRUE) == 0;
220 
221 	/*
222 	 * Bounds checking.  Priviledged user can set the RTO initial
223 	 * outside the ndd boundary.
224 	 */
225 	if (srto->srto_initial != 0 &&
226 	    (!ispriv && (srto->srto_initial < sctps->sctps_rto_initialg_low ||
227 	    srto->srto_initial > sctps->sctps_rto_initialg_high))) {
228 		return (EINVAL);
229 	}
230 	if (srto->srto_max != 0 &&
231 	    (!ispriv && (srto->srto_max < sctps->sctps_rto_maxg_low ||
232 	    srto->srto_max > sctps->sctps_rto_maxg_high))) {
233 		return (EINVAL);
234 	}
235 	if (srto->srto_min != 0 &&
236 	    (!ispriv && (srto->srto_min < sctps->sctps_rto_ming_low ||
237 	    srto->srto_min > sctps->sctps_rto_ming_high))) {
238 		return (EINVAL);
239 	}
240 
241 	new_min = (srto->srto_min != 0) ? srto->srto_min : sctp->sctp_rto_min;
242 	new_max = (srto->srto_max != 0) ? srto->srto_max : sctp->sctp_rto_max;
243 	if (new_max < new_min) {
244 		return (EINVAL);
245 	}
246 
247 	if (srto->srto_initial != 0) {
248 		sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial);
249 	}
250 
251 	/* Ensure that sctp_rto_max will never be zero. */
252 	if (srto->srto_max != 0) {
253 		sctp->sctp_rto_max = MAX(MSEC_TO_TICK(srto->srto_max), 1);
254 	}
255 	if (srto->srto_min != 0) {
256 		sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min);
257 	}
258 
259 	return (0);
260 }
261 
262 /*
263  * SCTP_ASSOCINFO
264  */
265 static int
sctp_get_assocparams(sctp_t * sctp,void * ptr)266 sctp_get_assocparams(sctp_t *sctp, void *ptr)
267 {
268 	struct sctp_assocparams *sap = ptr;
269 	sctp_faddr_t *fp;
270 	uint16_t i;
271 
272 	sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt;
273 
274 	/*
275 	 * Count the number of peer addresses
276 	 */
277 	for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
278 		i++;
279 	}
280 	sap->sasoc_number_peer_destinations = i;
281 	sap->sasoc_peer_rwnd = sctp->sctp_frwnd;
282 	sap->sasoc_local_rwnd = sctp->sctp_rwnd;
283 	sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime);
284 
285 	return (sizeof (*sap));
286 }
287 
288 static int
sctp_set_assocparams(sctp_t * sctp,const void * invalp)289 sctp_set_assocparams(sctp_t *sctp, const void *invalp)
290 {
291 	const struct sctp_assocparams *sap = invalp;
292 	uint32_t sum = 0;
293 	sctp_faddr_t *fp;
294 	sctp_stack_t	*sctps = sctp->sctp_sctps;
295 
296 	if (sap->sasoc_asocmaxrxt) {
297 		if (sctp->sctp_faddrs) {
298 			/*
299 			 * Bounds check: as per rfc2960, assoc max retr cannot
300 			 * exceed the sum of all individual path max retr's.
301 			 */
302 			for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
303 				sum += fp->sf_max_retr;
304 			}
305 			if (sap->sasoc_asocmaxrxt > sum) {
306 				return (EINVAL);
307 			}
308 		}
309 		if (sap->sasoc_asocmaxrxt < sctps->sctps_pa_max_retr_low ||
310 		    sap->sasoc_asocmaxrxt > sctps->sctps_pa_max_retr_high) {
311 			/*
312 			 * Out of bounds.
313 			 */
314 			return (EINVAL);
315 		}
316 	}
317 	if (sap->sasoc_cookie_life != 0 &&
318 	    (sap->sasoc_cookie_life < sctps->sctps_cookie_life_low ||
319 	    sap->sasoc_cookie_life > sctps->sctps_cookie_life_high)) {
320 		return (EINVAL);
321 	}
322 
323 	if (sap->sasoc_asocmaxrxt > 0) {
324 		sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt;
325 	}
326 	if (sap->sasoc_cookie_life > 0) {
327 		sctp->sctp_cookie_lifetime = MSEC_TO_TICK(
328 		    sap->sasoc_cookie_life);
329 	}
330 	return (0);
331 }
332 
333 /*
334  * SCTP_INITMSG
335  */
336 static int
sctp_get_initmsg(sctp_t * sctp,void * ptr)337 sctp_get_initmsg(sctp_t *sctp, void *ptr)
338 {
339 	struct sctp_initmsg *si = ptr;
340 
341 	si->sinit_num_ostreams = sctp->sctp_num_ostr;
342 	si->sinit_max_instreams = sctp->sctp_num_istr;
343 	si->sinit_max_attempts = sctp->sctp_max_init_rxt;
344 	si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_rto_max_init);
345 
346 	return (sizeof (*si));
347 }
348 
349 static int
sctp_set_initmsg(sctp_t * sctp,const void * invalp,uint_t inlen)350 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen)
351 {
352 	const struct sctp_initmsg *si = invalp;
353 	sctp_stack_t	*sctps = sctp->sctp_sctps;
354 	conn_t		*connp = sctp->sctp_connp;
355 
356 	if (sctp->sctp_state > SCTPS_LISTEN) {
357 		return (EINVAL);
358 	}
359 	if (inlen < sizeof (*si)) {
360 		return (EINVAL);
361 	}
362 	if (si->sinit_num_ostreams != 0 &&
363 	    (si->sinit_num_ostreams < sctps->sctps_initial_out_streams_low ||
364 	    si->sinit_num_ostreams >
365 	    sctps->sctps_initial_out_streams_high)) {
366 		/*
367 		 * Out of bounds.
368 		 */
369 		return (EINVAL);
370 	}
371 	if (si->sinit_max_instreams != 0 &&
372 	    (si->sinit_max_instreams < sctps->sctps_max_in_streams_low ||
373 	    si->sinit_max_instreams > sctps->sctps_max_in_streams_high)) {
374 		return (EINVAL);
375 	}
376 	if (si->sinit_max_attempts != 0 &&
377 	    (si->sinit_max_attempts < sctps->sctps_max_init_retr_low ||
378 	    si->sinit_max_attempts > sctps->sctps_max_init_retr_high)) {
379 		return (EINVAL);
380 	}
381 	if (si->sinit_max_init_timeo != 0 &&
382 	    (secpolicy_ip_config(connp->conn_cred, B_TRUE) != 0 &&
383 	    (si->sinit_max_init_timeo < sctps->sctps_rto_maxg_low ||
384 	    si->sinit_max_init_timeo > sctps->sctps_rto_maxg_high))) {
385 		return (EINVAL);
386 	}
387 	if (si->sinit_num_ostreams != 0)
388 		sctp->sctp_num_ostr = si->sinit_num_ostreams;
389 
390 	if (si->sinit_max_instreams != 0)
391 		sctp->sctp_num_istr = si->sinit_max_instreams;
392 
393 	if (si->sinit_max_attempts != 0)
394 		sctp->sctp_max_init_rxt = si->sinit_max_attempts;
395 
396 	if (si->sinit_max_init_timeo != 0) {
397 		sctp->sctp_rto_max_init =
398 		    MSEC_TO_TICK(si->sinit_max_init_timeo);
399 	}
400 	return (0);
401 }
402 
403 /*
404  * SCTP_PEER_ADDR_PARAMS
405  */
406 static int
sctp_find_peer_fp(sctp_t * sctp,const struct sockaddr_storage * ss,sctp_faddr_t ** fpp)407 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss,
408     sctp_faddr_t **fpp)
409 {
410 	struct sockaddr_in *sin;
411 	struct sockaddr_in6 *sin6;
412 	in6_addr_t addr;
413 
414 	if (ss->ss_family == AF_INET) {
415 		sin = (struct sockaddr_in *)ss;
416 		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
417 	} else if (ss->ss_family == AF_INET6) {
418 		sin6 = (struct sockaddr_in6 *)ss;
419 		addr = sin6->sin6_addr;
420 	} else if (ss->ss_family) {
421 		return (EAFNOSUPPORT);
422 	}
423 
424 	if (!ss->ss_family ||
425 	    SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) {
426 		*fpp = NULL;
427 	} else {
428 		*fpp = sctp_lookup_faddr(sctp, &addr);
429 		if (*fpp == NULL) {
430 			return (EINVAL);
431 		}
432 	}
433 	return (0);
434 }
435 
436 static int
sctp_get_peer_addr_params(sctp_t * sctp,void * ptr)437 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr)
438 {
439 	struct sctp_paddrparams *spp = ptr;
440 	sctp_faddr_t *fp;
441 	int retval;
442 
443 	retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
444 	if (retval) {
445 		return (retval);
446 	}
447 	if (fp) {
448 		spp->spp_hbinterval = TICK_TO_MSEC(fp->sf_hb_interval);
449 		spp->spp_pathmaxrxt = fp->sf_max_retr;
450 	} else {
451 		spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval);
452 		spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt;
453 	}
454 	return (sizeof (*spp));
455 }
456 
457 static int
sctp_set_peer_addr_params(sctp_t * sctp,const void * invalp)458 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp)
459 {
460 	const struct sctp_paddrparams *spp = invalp;
461 	sctp_faddr_t *fp, *fp2;
462 	int retval;
463 	uint32_t sum = 0;
464 	int64_t now;
465 	sctp_stack_t	*sctps = sctp->sctp_sctps;
466 
467 	retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
468 	if (retval != 0) {
469 		return (retval);
470 	}
471 
472 	if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX &&
473 	    (spp->spp_hbinterval < sctps->sctps_heartbeat_interval_low ||
474 	    spp->spp_hbinterval > sctps->sctps_heartbeat_interval_high)) {
475 		return (EINVAL);
476 	}
477 	if (spp->spp_pathmaxrxt &&
478 	    (spp->spp_pathmaxrxt < sctps->sctps_pp_max_retr_low ||
479 	    spp->spp_pathmaxrxt > sctps->sctps_pp_max_retr_high)) {
480 		return (EINVAL);
481 	}
482 	if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) {
483 		for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->sf_next) {
484 			if (!fp || fp2 == fp) {
485 				sum += spp->spp_pathmaxrxt;
486 			} else {
487 				sum += fp2->sf_max_retr;
488 			}
489 		}
490 		if (sctp->sctp_pa_max_rxt > sum) {
491 			return (EINVAL);
492 		}
493 	}
494 
495 	now = ddi_get_lbolt64();
496 	if (fp != NULL) {
497 		if (spp->spp_hbinterval == UINT32_MAX) {
498 			/*
499 			 * Send heartbeat immediatelly, don't modify the
500 			 * current setting.
501 			 */
502 			sctp_send_heartbeat(sctp, fp);
503 		} else {
504 			fp->sf_hb_interval = MSEC_TO_TICK(spp->spp_hbinterval);
505 			fp->sf_hb_expiry = now + SET_HB_INTVL(fp);
506 			/*
507 			 * Restart the heartbeat timer using the new intrvl.
508 			 * We need to call sctp_heartbeat_timer() to set
509 			 * the earliest heartbeat expiry time.
510 			 */
511 			sctp_heartbeat_timer(sctp);
512 		}
513 		if (spp->spp_pathmaxrxt) {
514 			fp->sf_max_retr = spp->spp_pathmaxrxt;
515 		}
516 	} else {
517 		for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->sf_next) {
518 			if (spp->spp_hbinterval == UINT32_MAX) {
519 				/*
520 				 * Send heartbeat immediatelly, don't modify
521 				 * the current setting.
522 				 */
523 				sctp_send_heartbeat(sctp, fp2);
524 			} else {
525 				fp2->sf_hb_interval = MSEC_TO_TICK(
526 				    spp->spp_hbinterval);
527 				fp2->sf_hb_expiry = now + SET_HB_INTVL(fp2);
528 			}
529 			if (spp->spp_pathmaxrxt) {
530 				fp2->sf_max_retr = spp->spp_pathmaxrxt;
531 			}
532 		}
533 		if (spp->spp_hbinterval != UINT32_MAX) {
534 			sctp->sctp_hb_interval = MSEC_TO_TICK(
535 			    spp->spp_hbinterval);
536 			/* Restart the heartbeat timer using the new intrvl. */
537 			sctp_timer(sctp, sctp->sctp_heartbeat_mp,
538 			    sctp->sctp_hb_interval);
539 		}
540 		if (spp->spp_pathmaxrxt) {
541 			sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt;
542 		}
543 	}
544 	return (0);
545 }
546 
547 /*
548  * SCTP_DEFAULT_SEND_PARAM
549  */
550 static int
sctp_get_def_send_params(sctp_t * sctp,void * ptr)551 sctp_get_def_send_params(sctp_t *sctp, void *ptr)
552 {
553 	struct sctp_sndrcvinfo *sinfo = ptr;
554 
555 	sinfo->sinfo_stream = sctp->sctp_def_stream;
556 	sinfo->sinfo_ssn = 0;
557 	sinfo->sinfo_flags = sctp->sctp_def_flags;
558 	sinfo->sinfo_ppid = sctp->sctp_def_ppid;
559 	sinfo->sinfo_context = sctp->sctp_def_context;
560 	sinfo->sinfo_timetolive = sctp->sctp_def_timetolive;
561 	sinfo->sinfo_tsn = 0;
562 	sinfo->sinfo_cumtsn = 0;
563 
564 	return (sizeof (*sinfo));
565 }
566 
567 static int
sctp_set_def_send_params(sctp_t * sctp,const void * invalp)568 sctp_set_def_send_params(sctp_t *sctp, const void *invalp)
569 {
570 	const struct sctp_sndrcvinfo *sinfo = invalp;
571 
572 	if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) {
573 		return (EINVAL);
574 	}
575 
576 	sctp->sctp_def_stream = sinfo->sinfo_stream;
577 	sctp->sctp_def_flags = sinfo->sinfo_flags;
578 	sctp->sctp_def_ppid = sinfo->sinfo_ppid;
579 	sctp->sctp_def_context = sinfo->sinfo_context;
580 	sctp->sctp_def_timetolive = sinfo->sinfo_timetolive;
581 
582 	return (0);
583 }
584 
585 static int
sctp_set_prim(sctp_t * sctp,const void * invalp)586 sctp_set_prim(sctp_t *sctp, const void *invalp)
587 {
588 	const struct	sctp_setpeerprim *pp = invalp;
589 	int		retval;
590 	sctp_faddr_t	*fp;
591 
592 	retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp);
593 	if (retval)
594 		return (retval);
595 
596 	if (fp == NULL)
597 		return (EINVAL);
598 	if (fp == sctp->sctp_primary)
599 		return (0);
600 	sctp->sctp_primary = fp;
601 
602 	/* Only switch current if fp is alive */
603 	if (fp->sf_state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) {
604 		return (0);
605 	}
606 	sctp_set_faddr_current(sctp, fp);
607 
608 	return (0);
609 }
610 
611 /*
612  * Table of all known options handled on a SCTP protocol stack.
613  *
614  * Note: This table contains options processed by both SCTP and IP levels
615  *       and is the superset of options that can be performed on a SCTP and IP
616  *       stack.
617  */
618 opdes_t	sctp_opt_arr[] = {
619 
620 { SO_LINGER,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
621 	sizeof (struct linger), 0 },
622 
623 { SO_DEBUG,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
624 { SO_KEEPALIVE,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
625 { SO_DONTROUTE,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
626 { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
627 	},
628 { SO_BROADCAST,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
629 { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
630 { SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
631 { SO_TYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
632 { SO_SNDBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
633 { SO_RCVBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
634 { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
635 	},
636 { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
637 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
638 	0 },
639 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
640 	0 },
641 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
642 	0 },
643 { SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
644 
645 { SO_DOMAIN,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
646 
647 { SO_PROTOTYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
648 
649 { SCTP_ADAPTATION_LAYER, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
650 	sizeof (struct sctp_setadaptation), 0 },
651 { SCTP_ADD_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
652 	sizeof (int), 0 },
653 { SCTP_ASSOCINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
654 	sizeof (struct sctp_assocparams), 0 },
655 { SCTP_AUTOCLOSE, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
656 { SCTP_DEFAULT_SEND_PARAM, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
657 	sizeof (struct sctp_sndrcvinfo), 0 },
658 { SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
659 	sizeof (int), 0 },
660 { SCTP_EVENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
661 	sizeof (struct sctp_event_subscribe), 0 },
662 { SCTP_GET_LADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
663 	sizeof (int), 0 },
664 { SCTP_GET_NLADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
665 { SCTP_GET_NPADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
666 { SCTP_GET_PADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
667 	sizeof (int), 0 },
668 { SCTP_GET_PEER_ADDR_INFO, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
669 	sizeof (struct sctp_paddrinfo), 0 },
670 { SCTP_INITMSG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
671 	sizeof (struct sctp_initmsg), 0 },
672 { SCTP_I_WANT_MAPPED_V4_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
673 	sizeof (int), 0 },
674 { SCTP_MAXSEG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
675 { SCTP_NODELAY, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
676 { SCTP_PEER_ADDR_PARAMS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
677 	sizeof (struct sctp_paddrparams), 0 },
678 { SCTP_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
679 	sizeof (struct sctp_setpeerprim), 0 },
680 { SCTP_PRSCTP, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
681 { SCTP_GET_ASSOC_STATS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
682 	sizeof (sctp_assoc_stats_t), 0 },
683 { SCTP_REM_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
684 	sizeof (int), 0 },
685 { SCTP_RTOINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
686 	sizeof (struct sctp_rtoinfo), 0 },
687 { SCTP_SET_PEER_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
688 	sizeof (struct sctp_setprim), 0 },
689 { SCTP_STATUS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
690 	sizeof (struct sctp_status), 0 },
691 { SCTP_UC_SWAP, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
692 	sizeof (struct sctp_uc_swap), 0 },
693 
694 { IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
695 	(OP_VARLEN|OP_NODEFAULT),
696 	40, -1 /* not initialized */ },
697 { T_IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
698 	(OP_VARLEN|OP_NODEFAULT),
699 	40, -1 /* not initialized */ },
700 
701 { IP_TOS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
702 { T_IP_TOS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
703 { IP_TTL,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
704 	sizeof (int), -1 /* not initialized */ },
705 
706 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
707 	sizeof (ipsec_req_t), -1 /* not initialized */ },
708 
709 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
710 	sizeof (int),	0 /* no ifindex */ },
711 
712 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
713 	sizeof (int), 0 },
714 
715 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
716 	sizeof (int), -1 /* not initialized */ },
717 
718 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
719 	sizeof (int),	0 /* no ifindex */ },
720 
721 { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
722 
723 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
724 	sizeof (in_addr_t),	-1 /* not initialized  */ },
725 
726 { IP_MINTTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
727 
728 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
729 	sizeof (int), 0 },
730 
731 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
732 	(OP_NODEFAULT|OP_VARLEN),
733 	sizeof (struct in6_pktinfo), -1 /* not initialized */ },
734 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
735 	OP_NODEFAULT,
736 	sizeof (sin6_t), -1 /* not initialized */ },
737 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
738 	(OP_VARLEN|OP_NODEFAULT), 255*8,
739 	-1 /* not initialized */ },
740 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
741 	(OP_VARLEN|OP_NODEFAULT), 255*8,
742 	-1 /* not initialized */ },
743 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
744 	(OP_VARLEN|OP_NODEFAULT), 255*8,
745 	-1 /* not initialized */ },
746 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
747 	(OP_VARLEN|OP_NODEFAULT), 255*8,
748 	-1 /* not initialized */ },
749 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
750 	OP_NODEFAULT,
751 	sizeof (int), -1 /* not initialized */ },
752 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
753 	OP_NODEFAULT,
754 	sizeof (struct ip6_mtuinfo), -1 /* not initialized */ },
755 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
756 	sizeof (int), 0 },
757 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
758 	sizeof (int), 0 },
759 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
760 	sizeof (int), 0 },
761 
762 /* Enable receipt of ancillary data */
763 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
764 	sizeof (int), 0 },
765 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
766 	sizeof (int), 0 },
767 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
768 	sizeof (int), 0 },
769 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
770 	sizeof (int), 0 },
771 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
772 	sizeof (int), 0 },
773 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
774 	sizeof (int), 0 },
775 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
776 	sizeof (int), 0 },
777 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
778 	sizeof (int), 0 },
779 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
780 	sizeof (int), 0 },
781 
782 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
783 	sizeof (ipsec_req_t), -1 /* not initialized */ },
784 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
785 	sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
786 
787 { IPV6_MINHOPCOUNT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
788 	sizeof (int), 0 },
789 };
790 
791 uint_t sctp_opt_arr_size = A_CNT(sctp_opt_arr);
792 
793 /* Handy on off switch for socket option processing. */
794 #define	ONOFF(x)	((x) == 0 ? 0 : 1)
795 
796 /*
797  * SCTP routine to get the values of options.
798  */
799 int
sctp_get_opt(sctp_t * sctp,int level,int name,void * ptr,socklen_t * optlen)800 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen)
801 {
802 	int	*i1 = (int *)ptr;
803 	int	retval = 0;
804 	int	buflen = *optlen;
805 	conn_t	*connp = sctp->sctp_connp;
806 	conn_opt_arg_t	coas;
807 
808 	coas.coa_connp = connp;
809 	coas.coa_ixa = connp->conn_ixa;
810 	coas.coa_ipp = &connp->conn_xmit_ipp;
811 
812 	/* In most cases, the return buffer is just an int */
813 	*optlen = sizeof (int32_t);
814 
815 	RUN_SCTP(sctp);
816 
817 	if (connp->conn_state_flags & CONN_CLOSING) {
818 		WAKE_SCTP(sctp);
819 		return (EINVAL);
820 	}
821 
822 	/*
823 	 * Check that the level and name are supported by SCTP, and that
824 	 * the length and credentials are ok.
825 	 */
826 	retval = proto_opt_check(level, name, buflen, NULL, sctp_opt_arr,
827 	    sctp_opt_arr_size, B_FALSE, B_TRUE, connp->conn_cred);
828 	if (retval != 0) {
829 		WAKE_SCTP(sctp);
830 		if (retval < 0) {
831 			retval = proto_tlitosyserr(-retval);
832 		}
833 		return (retval);
834 	}
835 
836 	switch (level) {
837 	case IPPROTO_SCTP:
838 		switch (name) {
839 		case SCTP_RTOINFO:
840 			*optlen = sctp_get_rtoinfo(sctp, ptr);
841 			break;
842 		case SCTP_ASSOCINFO:
843 			*optlen = sctp_get_assocparams(sctp, ptr);
844 			break;
845 		case SCTP_INITMSG:
846 			*optlen = sctp_get_initmsg(sctp, ptr);
847 			break;
848 		case SCTP_NODELAY:
849 			*i1 = sctp->sctp_ndelay;
850 			break;
851 		case SCTP_AUTOCLOSE:
852 			*i1 = TICK_TO_SEC(sctp->sctp_autoclose);
853 			break;
854 		case SCTP_ADAPTATION_LAYER:
855 			((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind =
856 			    sctp->sctp_tx_adaptation_code;
857 			break;
858 		case SCTP_PEER_ADDR_PARAMS:
859 			*optlen = sctp_get_peer_addr_params(sctp, ptr);
860 			break;
861 		case SCTP_DEFAULT_SEND_PARAM:
862 			*optlen = sctp_get_def_send_params(sctp, ptr);
863 			break;
864 		case SCTP_EVENTS: {
865 			struct sctp_event_subscribe *ev;
866 
867 			ev = (struct sctp_event_subscribe *)ptr;
868 			ev->sctp_data_io_event =
869 			    ONOFF(sctp->sctp_recvsndrcvinfo);
870 			ev->sctp_association_event =
871 			    ONOFF(sctp->sctp_recvassocevnt);
872 			ev->sctp_address_event =
873 			    ONOFF(sctp->sctp_recvpathevnt);
874 			ev->sctp_send_failure_event =
875 			    ONOFF(sctp->sctp_recvsendfailevnt);
876 			ev->sctp_peer_error_event =
877 			    ONOFF(sctp->sctp_recvpeererr);
878 			ev->sctp_shutdown_event =
879 			    ONOFF(sctp->sctp_recvshutdownevnt);
880 			ev->sctp_partial_delivery_event =
881 			    ONOFF(sctp->sctp_recvpdevnt);
882 			ev->sctp_adaptation_layer_event =
883 			    ONOFF(sctp->sctp_recvalevnt);
884 			*optlen = sizeof (struct sctp_event_subscribe);
885 			break;
886 		}
887 		case SCTP_STATUS:
888 			*optlen = sctp_get_status(sctp, ptr);
889 			break;
890 		case SCTP_GET_PEER_ADDR_INFO:
891 			retval = sctp_get_paddrinfo(sctp, ptr, optlen);
892 			break;
893 		case SCTP_GET_NLADDRS:
894 			*(int32_t *)ptr = sctp->sctp_nsaddrs;
895 			break;
896 		case SCTP_GET_LADDRS: {
897 			int addr_cnt;
898 			int addr_size;
899 
900 			if (connp->conn_family == AF_INET)
901 				addr_size = sizeof (struct sockaddr_in);
902 			else
903 				addr_size = sizeof (struct sockaddr_in6);
904 			addr_cnt = buflen / addr_size;
905 			retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt);
906 			if (retval == 0)
907 				*optlen = addr_cnt * addr_size;
908 			break;
909 		}
910 		case SCTP_GET_NPADDRS: {
911 			int i;
912 			sctp_faddr_t *fp;
913 
914 			for (i = 0, fp = sctp->sctp_faddrs; fp != NULL;
915 			    i++, fp = fp->sf_next)
916 				;
917 			*(int32_t *)ptr = i;
918 			break;
919 		}
920 		case SCTP_GET_PADDRS: {
921 			int addr_cnt;
922 			int addr_size;
923 
924 			if (connp->conn_family == AF_INET)
925 				addr_size = sizeof (struct sockaddr_in);
926 			else
927 				addr_size = sizeof (struct sockaddr_in6);
928 			addr_cnt = buflen / addr_size;
929 			retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt);
930 			if (retval == 0)
931 				*optlen = addr_cnt * addr_size;
932 			break;
933 		}
934 		case SCTP_PRSCTP:
935 			*i1 = sctp->sctp_prsctp_aware ? 1 : 0;
936 			break;
937 
938 		case SCTP_GET_ASSOC_STATS: {
939 			sctp_assoc_stats_t *sas;
940 
941 			sas = (sctp_assoc_stats_t *)ptr;
942 
943 			/*
944 			 * Copy the current stats to the stats struct.
945 			 * For stats which can be reset by snmp users
946 			 * add the cumulative and current stats for
947 			 * the raw totals to output to the user.
948 			 */
949 			sas->sas_gapcnt = sctp->sctp_gapcnt;
950 			sas->sas_outseqtsns = sctp->sctp_outseqtsns;
951 			sas->sas_osacks = sctp->sctp_osacks;
952 			sas->sas_isacks = sctp->sctp_isacks;
953 			sas->sas_idupchunks = sctp->sctp_idupchunks;
954 			sas->sas_rtxchunks =  sctp->sctp_rxtchunks +
955 			    sctp->sctp_cum_rxtchunks;
956 			sas->sas_octrlchunks = sctp->sctp_obchunks +
957 			    sctp->sctp_cum_obchunks;
958 			sas->sas_ictrlchunks = sctp->sctp_ibchunks +
959 			    sctp->sctp_cum_ibchunks;
960 			sas->sas_oodchunks = sctp->sctp_odchunks +
961 			    sctp->sctp_cum_odchunks;
962 			sas->sas_iodchunks = sctp->sctp_idchunks +
963 			    sctp->sctp_cum_idchunks;
964 			sas->sas_ouodchunks = sctp->sctp_oudchunks +
965 			    sctp->sctp_cum_oudchunks;
966 			sas->sas_iuodchunks = sctp->sctp_iudchunks +
967 			    sctp->sctp_cum_iudchunks;
968 
969 			/*
970 			 * Copy out the maximum observed RTO since the
971 			 * time this data was last requested
972 			 */
973 			if (sctp->sctp_maxrto == 0) {
974 				/* unchanged during obervation period */
975 				sas->sas_maxrto = sctp->sctp_prev_maxrto;
976 			} else {
977 				/* record new period maximum */
978 				sas->sas_maxrto = sctp->sctp_maxrto;
979 			}
980 			/* Record the value sent to the user this period */
981 			sctp->sctp_prev_maxrto = sas->sas_maxrto;
982 
983 			/* Mark beginning of a new observation period */
984 			sctp->sctp_maxrto = 0;
985 
986 			*optlen = sizeof (sctp_assoc_stats_t);
987 			break;
988 		}
989 		case SCTP_I_WANT_MAPPED_V4_ADDR:
990 		case SCTP_MAXSEG:
991 		case SCTP_DISABLE_FRAGMENTS:
992 		default:
993 			/* Not yet supported. */
994 			retval = ENOPROTOOPT;
995 			break;
996 		}
997 		WAKE_SCTP(sctp);
998 		return (retval);
999 	case IPPROTO_IP:
1000 		if (connp->conn_family != AF_INET) {
1001 			retval = EINVAL;
1002 			break;
1003 		}
1004 		switch (name) {
1005 		case IP_OPTIONS:
1006 		case T_IP_OPTIONS: {
1007 			/*
1008 			 * This is compatible with BSD in that in only return
1009 			 * the reverse source route with the final destination
1010 			 * as the last entry. The first 4 bytes of the option
1011 			 * will contain the final destination. Allocate a
1012 			 * buffer large enough to hold all the options, we
1013 			 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since
1014 			 * ip_opt_get_user() adds the final destination
1015 			 * at the start.
1016 			 */
1017 			int	opt_len;
1018 			uchar_t	obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN];
1019 
1020 			opt_len = ip_opt_get_user(connp, obuf);
1021 			ASSERT(opt_len <= sizeof (obuf));
1022 
1023 			if (buflen < opt_len) {
1024 				/* Silently truncate */
1025 				opt_len = buflen;
1026 			}
1027 			*optlen = opt_len;
1028 			bcopy(obuf, ptr, opt_len);
1029 			WAKE_SCTP(sctp);
1030 			return (0);
1031 		}
1032 		default:
1033 			break;
1034 		}
1035 		break;
1036 	}
1037 	mutex_enter(&connp->conn_lock);
1038 	retval = conn_opt_get(&coas, level, name, ptr);
1039 	mutex_exit(&connp->conn_lock);
1040 	WAKE_SCTP(sctp);
1041 	if (retval == -1)
1042 		return (EINVAL);
1043 	*optlen = retval;
1044 	return (0);
1045 }
1046 
1047 int
sctp_set_opt(sctp_t * sctp,int level,int name,const void * invalp,socklen_t inlen)1048 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp,
1049     socklen_t inlen)
1050 {
1051 	return (sctp_set_opt_common(sctp, level, name, invalp, inlen, B_FALSE));
1052 }
1053 
1054 int
sctp_set_opt_common(sctp_t * sctp,int level,int name,const void * invalp,socklen_t inlen,boolean_t kernel_special)1055 sctp_set_opt_common(sctp_t *sctp, int level, int name, const void *invalp,
1056     socklen_t inlen, boolean_t kernel_special)
1057 {
1058 	int		*i1 = (int *)invalp;
1059 	boolean_t	onoff;
1060 	int		retval = 0, addrcnt;
1061 	conn_t		*connp = sctp->sctp_connp;
1062 	sctp_stack_t	*sctps = sctp->sctp_sctps;
1063 	conn_opt_arg_t	coas;
1064 
1065 	coas.coa_connp = connp;
1066 	coas.coa_ixa = connp->conn_ixa;
1067 	coas.coa_ipp = &connp->conn_xmit_ipp;
1068 	coas.coa_ancillary = B_FALSE;
1069 	coas.coa_changed = 0;
1070 
1071 	/* In all cases, the size of the option must be bigger than int */
1072 	if (inlen >= sizeof (int32_t)) {
1073 		onoff = ONOFF(*i1);
1074 	} else {
1075 		return (EINVAL);
1076 	}
1077 
1078 	retval = 0;
1079 
1080 	RUN_SCTP(sctp);
1081 
1082 	if (connp->conn_state_flags & CONN_CLOSING) {
1083 		WAKE_SCTP(sctp);
1084 		return (EINVAL);
1085 	}
1086 
1087 	/*
1088 	 * Check that the level and name are supported by SCTP, and that
1089 	 * the length an credentials are ok.
1090 	 */
1091 	retval = proto_opt_check(level, name, inlen, NULL, sctp_opt_arr,
1092 	    sctp_opt_arr_size, B_TRUE, B_FALSE, connp->conn_cred);
1093 	if (retval != 0) {
1094 		if (retval < 0) {
1095 			retval = proto_tlitosyserr(-retval);
1096 		}
1097 		goto done;
1098 	}
1099 
1100 	/* Note: both SCTP and TCP interpret l_linger as being in seconds */
1101 	switch (level) {
1102 	case SOL_SOCKET:
1103 		switch (name) {
1104 		case SO_SNDBUF:
1105 			if (*i1 > sctps->sctps_max_buf) {
1106 				retval = ENOBUFS;
1107 				goto done;
1108 			}
1109 			if (*i1 < 0) {
1110 				retval = EINVAL;
1111 				goto done;
1112 			}
1113 			connp->conn_sndbuf = *i1;
1114 			if (sctps->sctps_snd_lowat_fraction != 0) {
1115 				connp->conn_sndlowat = connp->conn_sndbuf /
1116 				    sctps->sctps_snd_lowat_fraction;
1117 			}
1118 			goto done;
1119 		case SO_RCVBUF:
1120 			if (*i1 > sctps->sctps_max_buf) {
1121 				retval = ENOBUFS;
1122 				goto done;
1123 			}
1124 			/* Silently ignore zero */
1125 			if (*i1 != 0) {
1126 				struct sock_proto_props sopp;
1127 
1128 				/*
1129 				 * Insist on a receive window that is at least
1130 				 * sctp_recv_hiwat_minmss * MSS (default 4*MSS)
1131 				 * to avoid funny interactions of Nagle
1132 				 * algorithm, SWS avoidance and delayed
1133 				 * acknowledgement.
1134 				 */
1135 				*i1 = MAX(*i1,
1136 				    sctps->sctps_recv_hiwat_minmss *
1137 				    sctp->sctp_mss);
1138 				/*
1139 				 * Note that sctp_rwnd is modified by the
1140 				 * protocol and here we just whack it.
1141 				 */
1142 				connp->conn_rcvbuf = sctp->sctp_rwnd = *i1;
1143 				sctp->sctp_arwnd = sctp->sctp_rwnd;
1144 				sctp->sctp_pd_point = sctp->sctp_rwnd;
1145 
1146 				sopp.sopp_flags = SOCKOPT_RCVHIWAT;
1147 				sopp.sopp_rxhiwat = connp->conn_rcvbuf;
1148 				sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp);
1149 
1150 			}
1151 			/*
1152 			 * XXX should we return the rwnd here
1153 			 * and sctp_opt_get ?
1154 			 */
1155 			goto done;
1156 		case SO_ALLZONES:
1157 			if (sctp->sctp_state >= SCTPS_BOUND) {
1158 				retval = EINVAL;
1159 				goto done;
1160 			}
1161 			break;
1162 		case SO_MAC_EXEMPT:
1163 			if (sctp->sctp_state >= SCTPS_BOUND) {
1164 				retval = EINVAL;
1165 				goto done;
1166 			}
1167 			break;
1168 		}
1169 		break;
1170 
1171 	case IPPROTO_SCTP:
1172 		switch (name) {
1173 		case SCTP_RTOINFO:
1174 			retval = sctp_set_rtoinfo(sctp, invalp);
1175 			break;
1176 		case SCTP_ASSOCINFO:
1177 			retval = sctp_set_assocparams(sctp, invalp);
1178 			break;
1179 		case SCTP_INITMSG:
1180 			retval = sctp_set_initmsg(sctp, invalp, inlen);
1181 			break;
1182 		case SCTP_NODELAY:
1183 			sctp->sctp_ndelay = ONOFF(*i1);
1184 			break;
1185 		case SCTP_AUTOCLOSE:
1186 			if (SEC_TO_TICK(*i1) < 0) {
1187 				retval = EINVAL;
1188 				break;
1189 			}
1190 			/* Convert the number of seconds to ticks. */
1191 			sctp->sctp_autoclose = SEC_TO_TICK(*i1);
1192 			sctp_heartbeat_timer(sctp);
1193 			break;
1194 		case SCTP_SET_PEER_PRIMARY_ADDR:
1195 			retval = sctp_set_peerprim(sctp, invalp);
1196 			break;
1197 		case SCTP_PRIMARY_ADDR:
1198 			retval = sctp_set_prim(sctp, invalp);
1199 			break;
1200 		case SCTP_ADAPTATION_LAYER: {
1201 			struct sctp_setadaptation *ssb;
1202 
1203 			ssb = (struct sctp_setadaptation *)invalp;
1204 			sctp->sctp_send_adaptation = 1;
1205 			sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind;
1206 			break;
1207 		}
1208 		case SCTP_PEER_ADDR_PARAMS:
1209 			retval = sctp_set_peer_addr_params(sctp, invalp);
1210 			break;
1211 		case SCTP_DEFAULT_SEND_PARAM:
1212 			retval = sctp_set_def_send_params(sctp, invalp);
1213 			break;
1214 		case SCTP_EVENTS: {
1215 			struct sctp_event_subscribe *ev;
1216 
1217 			ev = (struct sctp_event_subscribe *)invalp;
1218 			sctp->sctp_recvsndrcvinfo =
1219 			    ONOFF(ev->sctp_data_io_event);
1220 			sctp->sctp_recvassocevnt =
1221 			    ONOFF(ev->sctp_association_event);
1222 			sctp->sctp_recvpathevnt =
1223 			    ONOFF(ev->sctp_address_event);
1224 			sctp->sctp_recvsendfailevnt =
1225 			    ONOFF(ev->sctp_send_failure_event);
1226 			sctp->sctp_recvpeererr =
1227 			    ONOFF(ev->sctp_peer_error_event);
1228 			sctp->sctp_recvshutdownevnt =
1229 			    ONOFF(ev->sctp_shutdown_event);
1230 			sctp->sctp_recvpdevnt =
1231 			    ONOFF(ev->sctp_partial_delivery_event);
1232 			sctp->sctp_recvalevnt =
1233 			    ONOFF(ev->sctp_adaptation_layer_event);
1234 			break;
1235 		}
1236 		case SCTP_ADD_ADDR:
1237 		case SCTP_REM_ADDR:
1238 			/*
1239 			 * The sctp_t has to be bound first before
1240 			 * the address list can be changed.
1241 			 */
1242 			if (sctp->sctp_state < SCTPS_BOUND) {
1243 				retval = EINVAL;
1244 				break;
1245 			}
1246 			if (connp->conn_family == AF_INET) {
1247 				addrcnt = inlen / sizeof (struct sockaddr_in);
1248 			} else {
1249 				ASSERT(connp->conn_family == AF_INET6);
1250 				addrcnt = inlen / sizeof (struct sockaddr_in6);
1251 			}
1252 			if (name == SCTP_ADD_ADDR) {
1253 				retval = sctp_bind_add(sctp, invalp, addrcnt,
1254 				    B_TRUE, connp->conn_lport);
1255 			} else {
1256 				retval = sctp_bind_del(sctp, invalp, addrcnt,
1257 				    B_TRUE);
1258 			}
1259 			break;
1260 		case SCTP_UC_SWAP:
1261 			if (kernel_special) {
1262 				struct sctp_uc_swap *us;
1263 
1264 				/*
1265 				 * Change handle & upcalls.
1266 				 */
1267 				us = (struct sctp_uc_swap *)invalp;
1268 				sctp->sctp_ulpd = us->sus_handle;
1269 				sctp->sctp_upcalls = us->sus_upcalls;
1270 			} else {
1271 				/*
1272 				 * We don't want ANYONE other than
1273 				 * our own kernel-ness mucking with this
1274 				 * socket option. Everyone else gets an error.
1275 				 */
1276 				retval = ENOPROTOOPT;
1277 			}
1278 			break;
1279 		case SCTP_PRSCTP:
1280 			sctp->sctp_prsctp_aware = onoff;
1281 			break;
1282 		case SCTP_I_WANT_MAPPED_V4_ADDR:
1283 		case SCTP_MAXSEG:
1284 		case SCTP_DISABLE_FRAGMENTS:
1285 			/* Not yet supported. */
1286 			retval = ENOPROTOOPT;
1287 			break;
1288 		}
1289 		goto done;
1290 
1291 	case IPPROTO_IP:
1292 		if (connp->conn_family != AF_INET) {
1293 			retval = EINVAL;
1294 			goto done;
1295 		}
1296 		switch (name) {
1297 		case IP_SEC_OPT:
1298 			/*
1299 			 * We should not allow policy setting after
1300 			 * we start listening for connections.
1301 			 */
1302 			if (sctp->sctp_state >= SCTPS_LISTEN) {
1303 				retval = EINVAL;
1304 				goto done;
1305 			}
1306 			break;
1307 		}
1308 		break;
1309 	case IPPROTO_IPV6:
1310 		if (connp->conn_family != AF_INET6) {
1311 			retval = EINVAL;
1312 			goto done;
1313 		}
1314 
1315 		switch (name) {
1316 		case IPV6_RECVPKTINFO:
1317 			/* Send it with the next msg */
1318 			sctp->sctp_recvifindex = 0;
1319 			break;
1320 		case IPV6_RECVTCLASS:
1321 			/* Force it to be sent up with the next msg */
1322 			sctp->sctp_recvtclass = 0xffffffffU;
1323 			break;
1324 		case IPV6_RECVHOPLIMIT:
1325 			/* Force it to be sent up with the next msg */
1326 			sctp->sctp_recvhops = 0xffffffffU;
1327 			break;
1328 		case IPV6_SEC_OPT:
1329 			/*
1330 			 * We should not allow policy setting after
1331 			 * we start listening for connections.
1332 			 */
1333 			if (sctp->sctp_state >= SCTPS_LISTEN) {
1334 				retval = EINVAL;
1335 				goto done;
1336 			}
1337 			break;
1338 		case IPV6_V6ONLY:
1339 			/*
1340 			 * After the bound state, setting the v6only option
1341 			 * is too late.
1342 			 */
1343 			if (sctp->sctp_state >= SCTPS_BOUND) {
1344 				retval = EINVAL;
1345 				goto done;
1346 			}
1347 			break;
1348 		}
1349 		break;
1350 	}
1351 
1352 	retval = conn_opt_set(&coas, level, name, inlen, (uchar_t *)invalp,
1353 	    B_FALSE, connp->conn_cred);
1354 	if (retval != 0)
1355 		goto done;
1356 
1357 	if (coas.coa_changed & COA_ROUTE_CHANGED) {
1358 		sctp_faddr_t *fp;
1359 		/*
1360 		 * We recache the information which might pick a different
1361 		 * source and redo IPsec as a result.
1362 		 */
1363 		for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next)
1364 			sctp_get_dest(sctp, fp);
1365 	}
1366 	if (coas.coa_changed & COA_HEADER_CHANGED) {
1367 		retval = sctp_build_hdrs(sctp, KM_NOSLEEP);
1368 		if (retval != 0)
1369 			goto done;
1370 	}
1371 	if (coas.coa_changed & COA_WROFF_CHANGED) {
1372 		connp->conn_wroff = connp->conn_ht_iphc_allocated +
1373 		    sctps->sctps_wroff_xtra;
1374 		if (sctp->sctp_current != NULL) {
1375 			/*
1376 			 * Could be setting options before setting up
1377 			 * connection.
1378 			 */
1379 			sctp_set_ulp_prop(sctp);
1380 		}
1381 	}
1382 done:
1383 	WAKE_SCTP(sctp);
1384 	return (retval);
1385 }
1386 
1387 /*
1388  * SCTP exported kernel interface for geting the first source address of
1389  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1390  * one socket address.
1391  */
1392 int
sctp_getsockname(sctp_t * sctp,struct sockaddr * addr,socklen_t * addrlen)1393 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1394 {
1395 	int	err = 0;
1396 	int	addrcnt = 1;
1397 	sin_t	*sin4;
1398 	sin6_t	*sin6;
1399 	conn_t	*connp = sctp->sctp_connp;
1400 
1401 	ASSERT(sctp != NULL);
1402 
1403 	RUN_SCTP(sctp);
1404 	addr->sa_family = connp->conn_family;
1405 	switch (connp->conn_family) {
1406 	case AF_INET:
1407 		sin4 = (sin_t *)addr;
1408 		if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1409 		    sctp->sctp_bound_to_all) {
1410 			sin4->sin_addr.s_addr = INADDR_ANY;
1411 			sin4->sin_port = connp->conn_lport;
1412 		} else {
1413 			err = sctp_getmyaddrs(sctp, sin4, &addrcnt);
1414 			if (err != 0) {
1415 				*addrlen = 0;
1416 				break;
1417 			}
1418 		}
1419 		*addrlen = sizeof (struct sockaddr_in);
1420 		break;
1421 	case AF_INET6:
1422 		sin6 = (sin6_t *)addr;
1423 		if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1424 		    sctp->sctp_bound_to_all) {
1425 			bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
1426 			sin6->sin6_port = connp->conn_lport;
1427 		} else {
1428 			err = sctp_getmyaddrs(sctp, sin6, &addrcnt);
1429 			if (err != 0) {
1430 				*addrlen = 0;
1431 				break;
1432 			}
1433 		}
1434 		*addrlen = sizeof (struct sockaddr_in6);
1435 		/* Note that flowinfo is only returned for getpeername */
1436 		break;
1437 	}
1438 	WAKE_SCTP(sctp);
1439 	return (err);
1440 }
1441 
1442 /*
1443  * SCTP exported kernel interface for geting the primary peer address of
1444  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1445  * one socket address.
1446  */
1447 int
sctp_getpeername(sctp_t * sctp,struct sockaddr * addr,socklen_t * addrlen)1448 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1449 {
1450 	int	err = 0;
1451 	int	addrcnt = 1;
1452 	sin6_t	*sin6;
1453 	conn_t	*connp = sctp->sctp_connp;
1454 
1455 	ASSERT(sctp != NULL);
1456 
1457 	RUN_SCTP(sctp);
1458 	addr->sa_family = connp->conn_family;
1459 	switch (connp->conn_family) {
1460 	case AF_INET:
1461 		err = sctp_getpeeraddrs(sctp, addr, &addrcnt);
1462 		if (err != 0) {
1463 			*addrlen = 0;
1464 			break;
1465 		}
1466 		*addrlen = sizeof (struct sockaddr_in);
1467 		break;
1468 	case AF_INET6:
1469 		sin6 = (sin6_t *)addr;
1470 		err = sctp_getpeeraddrs(sctp, sin6, &addrcnt);
1471 		if (err != 0) {
1472 			*addrlen = 0;
1473 			break;
1474 		}
1475 		*addrlen = sizeof (struct sockaddr_in6);
1476 		break;
1477 	}
1478 	WAKE_SCTP(sctp);
1479 	return (err);
1480 }
1481 
1482 /*
1483  * Return a list of IP addresses of the peer endpoint of this sctp_t.
1484  * The parameter paddrs is supposed to be either (struct sockaddr_in *) or
1485  * (struct sockaddr_in6 *) depending on the address family of the sctp_t.
1486  */
1487 int
sctp_getpeeraddrs(sctp_t * sctp,void * paddrs,int * addrcnt)1488 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt)
1489 {
1490 	int			family;
1491 	struct sockaddr_in	*sin4;
1492 	struct sockaddr_in6	*sin6;
1493 	int			max;
1494 	int			cnt;
1495 	sctp_faddr_t		*fp = sctp->sctp_faddrs;
1496 	in6_addr_t		addr;
1497 	conn_t			*connp = sctp->sctp_connp;
1498 
1499 	ASSERT(sctp != NULL);
1500 
1501 	if (sctp->sctp_faddrs == NULL)
1502 		return (ENOTCONN);
1503 
1504 	family = connp->conn_family;
1505 	max = *addrcnt;
1506 
1507 	/* If we want only one, give the primary */
1508 	if (max == 1) {
1509 		addr = sctp->sctp_primary->sf_faddr;
1510 		switch (family) {
1511 		case AF_INET:
1512 			sin4 = paddrs;
1513 			IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1514 			sin4->sin_port = connp->conn_fport;
1515 			sin4->sin_family = AF_INET;
1516 			break;
1517 
1518 		case AF_INET6:
1519 			sin6 = paddrs;
1520 			sin6->sin6_addr = addr;
1521 			sin6->sin6_port = connp->conn_fport;
1522 			sin6->sin6_family = AF_INET6;
1523 			sin6->sin6_flowinfo = connp->conn_flowinfo;
1524 			if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1525 			    (sctp->sctp_primary->sf_ixa->ixa_flags &
1526 			    IXAF_SCOPEID_SET)) {
1527 				sin6->sin6_scope_id =
1528 				    sctp->sctp_primary->sf_ixa->ixa_scopeid;
1529 			} else {
1530 				sin6->sin6_scope_id = 0;
1531 			}
1532 			sin6->__sin6_src_id = 0;
1533 			break;
1534 		}
1535 		return (0);
1536 	}
1537 
1538 	for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->sf_next) {
1539 		addr = fp->sf_faddr;
1540 		switch (family) {
1541 		case AF_INET:
1542 			ASSERT(IN6_IS_ADDR_V4MAPPED(&addr));
1543 			sin4 = (struct sockaddr_in *)paddrs + cnt;
1544 			IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1545 			sin4->sin_port = connp->conn_fport;
1546 			sin4->sin_family = AF_INET;
1547 			break;
1548 		case AF_INET6:
1549 			sin6 = (struct sockaddr_in6 *)paddrs + cnt;
1550 			sin6->sin6_addr = addr;
1551 			sin6->sin6_port = connp->conn_fport;
1552 			sin6->sin6_family = AF_INET6;
1553 			sin6->sin6_flowinfo = connp->conn_flowinfo;
1554 			if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1555 			    (fp->sf_ixa->ixa_flags & IXAF_SCOPEID_SET))
1556 				sin6->sin6_scope_id = fp->sf_ixa->ixa_scopeid;
1557 			else
1558 				sin6->sin6_scope_id = 0;
1559 			sin6->__sin6_src_id = 0;
1560 			break;
1561 		}
1562 	}
1563 	*addrcnt = cnt;
1564 	return (0);
1565 }
1566