xref: /illumos-gate/usr/src/uts/common/inet/tcp/tcp_opt_data.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
24  * Copyright 2019 Joyent, Inc.
25  * Copyright (c) 2016 by Delphix. All rights reserved.
26  */
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_xtiopt.h>
34 #include <sys/xti_inet.h>
35 #include <sys/policy.h>
36 
37 #include <inet/cc.h>
38 #include <inet/common.h>
39 #include <netinet/ip6.h>
40 #include <inet/ip.h>
41 
42 #include <netinet/in.h>
43 #include <netinet/tcp.h>
44 #include <inet/optcom.h>
45 #include <inet/proto_set.h>
46 #include <inet/tcp_impl.h>
47 
48 static int	tcp_opt_default(queue_t *, int, int, uchar_t *);
49 
50 /*
51  * Table of all known options handled on a TCP protocol stack.
52  *
53  * Note: This table contains options processed by both TCP and IP levels
54  *       and is the superset of options that can be performed on a TCP over IP
55  *       stack.
56  */
57 opdes_t	tcp_opt_arr[] = {
58 
59 { SO_LINGER,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
60 	sizeof (struct linger), 0 },
61 
62 { SO_DEBUG,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
63 { SO_KEEPALIVE,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
64 { SO_DONTROUTE,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
65 { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
66 	},
67 { SO_BROADCAST,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
68 { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
69 { SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
70 { SO_TYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
71 { SO_SNDBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
72 { SO_RCVBUF,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
73 { SO_SNDTIMEO,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
74 	sizeof (struct timeval), 0 },
75 { SO_RCVTIMEO,	SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
76 	sizeof (struct timeval), 0 },
77 { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
78 	},
79 { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
80 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
81 	0 },
82 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
83 	0 },
84 { SO_MAC_IMPLICIT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
85 	0 },
86 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
87 	0 },
88 { SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
89 
90 { SO_DOMAIN,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
91 
92 { SO_PROTOTYPE,	SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
93 
94 { TCP_NODELAY,	IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
95 	},
96 { TCP_MAXSEG,	IPPROTO_TCP, OA_R, OA_R, OP_NP, 0, sizeof (uint_t),
97 	536 },
98 
99 { TCP_NOTIFY_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
100 	OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
101 
102 { TCP_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
103 	OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
104 
105 { TCP_CONN_NOTIFY_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
106 	OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
107 
108 { TCP_CONN_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
109 	OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
110 
111 { TCP_RECVDSTADDR, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
112 	0 },
113 
114 { TCP_ANONPRIVBIND, IPPROTO_TCP, OA_R, OA_RW, OP_PRIVPORT, 0,
115 	sizeof (int), 0 },
116 
117 { TCP_EXCLBIND, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
118 	},
119 
120 { TCP_INIT_CWND, IPPROTO_TCP, OA_RW, OA_RW, OP_CONFIG, 0,
121 	sizeof (int), 0 },
122 
123 { TCP_KEEPALIVE_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0,
124 	sizeof (int), 0	},
125 
126 { TCP_KEEPIDLE, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
127 
128 { TCP_KEEPCNT, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
129 
130 { TCP_KEEPINTVL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
131 
132 { TCP_KEEPALIVE_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0,
133 	sizeof (int), 0	},
134 
135 { TCP_CORK, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
136 
137 { TCP_RTO_INITIAL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
138 
139 { TCP_RTO_MIN, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
140 
141 { TCP_RTO_MAX, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
142 
143 { TCP_LINGER2, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
144 
145 { TCP_CONGESTION, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
146 	OP_VARLEN, CC_ALGO_NAME_MAX, 0 },
147 
148 { IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
149 	(OP_VARLEN|OP_NODEFAULT),
150 	IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
151 { T_IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
152 	(OP_VARLEN|OP_NODEFAULT),
153 	IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
154 
155 { IP_TOS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
156 { T_IP_TOS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
157 { IP_TTL,	IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
158 	sizeof (int), -1 /* not initialized */ },
159 
160 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
161 	sizeof (ipsec_req_t), -1 /* not initialized */ },
162 
163 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
164 	sizeof (int),	0 /* no ifindex */ },
165 
166 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
167 	sizeof (int), 0 },
168 
169 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
170 	sizeof (int), -1 /* not initialized */ },
171 
172 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
173 	sizeof (int),	0 /* no ifindex */ },
174 
175 { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
176 
177 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
178 	sizeof (in_addr_t),	-1 /* not initialized  */ },
179 
180 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
181 	sizeof (int), 0 },
182 
183 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
184 	(OP_NODEFAULT|OP_VARLEN),
185 	sizeof (struct in6_pktinfo), -1 /* not initialized */ },
186 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
187 	OP_NODEFAULT,
188 	sizeof (sin6_t), -1 /* not initialized */ },
189 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
190 	(OP_VARLEN|OP_NODEFAULT), 255*8,
191 	-1 /* not initialized */ },
192 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
193 	(OP_VARLEN|OP_NODEFAULT), 255*8,
194 	-1 /* not initialized */ },
195 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
196 	(OP_VARLEN|OP_NODEFAULT), 255*8,
197 	-1 /* not initialized */ },
198 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
199 	(OP_VARLEN|OP_NODEFAULT), 255*8,
200 	-1 /* not initialized */ },
201 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
202 	OP_NODEFAULT,
203 	sizeof (int), -1 /* not initialized */ },
204 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
205 	OP_NODEFAULT,
206 	sizeof (struct ip6_mtuinfo), -1 /* not initialized */ },
207 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
208 	sizeof (int), 0 },
209 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
210 	sizeof (int), 0 },
211 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
212 	sizeof (int), 0 },
213 
214 /* Enable receipt of ancillary data */
215 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
216 	sizeof (int), 0 },
217 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
218 	sizeof (int), 0 },
219 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
220 	sizeof (int), 0 },
221 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
222 	sizeof (int), 0 },
223 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
224 	sizeof (int), 0 },
225 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
226 	sizeof (int), 0 },
227 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
228 	sizeof (int), 0 },
229 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
230 	sizeof (int), 0 },
231 
232 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
233 	sizeof (ipsec_req_t), -1 /* not initialized */ },
234 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
235 	sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
236 };
237 
238 /*
239  * Table of all supported levels
240  * Note: Some levels (e.g. XTI_GENERIC) may be valid but may not have
241  * any supported options so we need this info separately.
242  *
243  * This is needed only for topmost tpi providers and is used only by
244  * XTI interfaces.
245  */
246 optlevel_t	tcp_valid_levels_arr[] = {
247 	XTI_GENERIC,
248 	SOL_SOCKET,
249 	IPPROTO_TCP,
250 	IPPROTO_IP,
251 	IPPROTO_IPV6
252 };
253 
254 
255 #define	TCP_OPT_ARR_CNT		A_CNT(tcp_opt_arr)
256 #define	TCP_VALID_LEVELS_CNT	A_CNT(tcp_valid_levels_arr)
257 
258 uint_t tcp_max_optsize; /* initialized when TCP driver is loaded */
259 
260 /*
261  * Initialize option database object for TCP
262  *
263  * This object represents database of options to search passed to
264  * {sock,tpi}optcom_req() interface routine to take care of option
265  * management and associated methods.
266  */
267 
268 optdb_obj_t tcp_opt_obj = {
269 	tcp_opt_default,	/* TCP default value function pointer */
270 	tcp_tpi_opt_get,	/* TCP get function pointer */
271 	tcp_tpi_opt_set,	/* TCP set function pointer */
272 	TCP_OPT_ARR_CNT,	/* TCP option database count of entries */
273 	tcp_opt_arr,		/* TCP option database */
274 	TCP_VALID_LEVELS_CNT,	/* TCP valid level count of entries */
275 	tcp_valid_levels_arr	/* TCP valid level array */
276 };
277 
278 static int tcp_max_init_cwnd = TCP_MAX_INIT_CWND;
279 
280 /*
281  * Some TCP options can be "set" by requesting them in the option
282  * buffer. This is needed for XTI feature test though we do not
283  * allow it in general. We interpret that this mechanism is more
284  * applicable to OSI protocols and need not be allowed in general.
285  * This routine filters out options for which it is not allowed (most)
286  * and lets through those (few) for which it is. [ The XTI interface
287  * test suite specifics will imply that any XTI_GENERIC level XTI_* if
288  * ever implemented will have to be allowed here ].
289  */
290 static boolean_t
291 tcp_allow_connopt_set(int level, int name)
292 {
293 
294 	switch (level) {
295 	case IPPROTO_TCP:
296 		switch (name) {
297 		case TCP_NODELAY:
298 			return (B_TRUE);
299 		default:
300 			return (B_FALSE);
301 		}
302 		/*NOTREACHED*/
303 	default:
304 		return (B_FALSE);
305 	}
306 	/*NOTREACHED*/
307 }
308 
309 /*
310  * This routine gets default values of certain options whose default
311  * values are maintained by protocol specific code
312  */
313 /* ARGSUSED */
314 static int
315 tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
316 {
317 	int32_t	*i1 = (int32_t *)ptr;
318 	tcp_stack_t	*tcps = Q_TO_TCP(q)->tcp_tcps;
319 
320 	switch (level) {
321 	case IPPROTO_TCP:
322 		switch (name) {
323 		case TCP_NOTIFY_THRESHOLD:
324 			*i1 = tcps->tcps_ip_notify_interval;
325 			break;
326 		case TCP_ABORT_THRESHOLD:
327 			*i1 = tcps->tcps_ip_abort_interval;
328 			break;
329 		case TCP_CONN_NOTIFY_THRESHOLD:
330 			*i1 = tcps->tcps_ip_notify_cinterval;
331 			break;
332 		case TCP_CONN_ABORT_THRESHOLD:
333 			*i1 = tcps->tcps_ip_abort_cinterval;
334 			break;
335 		default:
336 			return (-1);
337 		}
338 		break;
339 	case IPPROTO_IP:
340 		switch (name) {
341 		case IP_TTL:
342 			*i1 = tcps->tcps_ipv4_ttl;
343 			break;
344 		default:
345 			return (-1);
346 		}
347 		break;
348 	case IPPROTO_IPV6:
349 		switch (name) {
350 		case IPV6_UNICAST_HOPS:
351 			*i1 = tcps->tcps_ipv6_hoplimit;
352 			break;
353 		default:
354 			return (-1);
355 		}
356 		break;
357 	default:
358 		return (-1);
359 	}
360 	return (sizeof (int));
361 }
362 
363 /*
364  * TCP routine to get the values of options.
365  */
366 int
367 tcp_opt_get(conn_t *connp, int level, int name, uchar_t *ptr)
368 {
369 	int		*i1 = (int *)ptr;
370 	tcp_t		*tcp = connp->conn_tcp;
371 	conn_opt_arg_t	coas;
372 	int		retval;
373 
374 	coas.coa_connp = connp;
375 	coas.coa_ixa = connp->conn_ixa;
376 	coas.coa_ipp = &connp->conn_xmit_ipp;
377 	coas.coa_ancillary = B_FALSE;
378 	coas.coa_changed = 0;
379 
380 	switch (level) {
381 	case SOL_SOCKET:
382 		switch (name) {
383 		case SO_SND_COPYAVOID:
384 			*i1 = tcp->tcp_snd_zcopy_on ?
385 			    SO_SND_COPYAVOID : 0;
386 			return (sizeof (int));
387 		case SO_ACCEPTCONN:
388 			*i1 = (tcp->tcp_state == TCPS_LISTEN);
389 			return (sizeof (int));
390 		}
391 		break;
392 	case IPPROTO_TCP:
393 		switch (name) {
394 		case TCP_NODELAY:
395 			*i1 = (tcp->tcp_naglim == 1) ? TCP_NODELAY : 0;
396 			return (sizeof (int));
397 		case TCP_MAXSEG:
398 			*i1 = tcp->tcp_mss;
399 			return (sizeof (int));
400 		case TCP_NOTIFY_THRESHOLD:
401 			*i1 = (int)tcp->tcp_first_timer_threshold;
402 			return (sizeof (int));
403 		case TCP_ABORT_THRESHOLD:
404 			*i1 = tcp->tcp_second_timer_threshold;
405 			return (sizeof (int));
406 		case TCP_CONN_NOTIFY_THRESHOLD:
407 			*i1 = tcp->tcp_first_ctimer_threshold;
408 			return (sizeof (int));
409 		case TCP_CONN_ABORT_THRESHOLD:
410 			*i1 = tcp->tcp_second_ctimer_threshold;
411 			return (sizeof (int));
412 		case TCP_INIT_CWND:
413 			*i1 = tcp->tcp_init_cwnd;
414 			return (sizeof (int));
415 		case TCP_KEEPALIVE_THRESHOLD:
416 			*i1 = tcp->tcp_ka_interval;
417 			return (sizeof (int));
418 
419 		/*
420 		 * TCP_KEEPIDLE expects value in seconds, but
421 		 * tcp_ka_interval is in milliseconds.
422 		 */
423 		case TCP_KEEPIDLE:
424 			*i1 = tcp->tcp_ka_interval / 1000;
425 			return (sizeof (int));
426 		case TCP_KEEPCNT:
427 			*i1 = tcp->tcp_ka_cnt;
428 			return (sizeof (int));
429 
430 		/*
431 		 * TCP_KEEPINTVL expects value in seconds, but
432 		 * tcp_ka_rinterval is in milliseconds.
433 		 */
434 		case TCP_KEEPINTVL:
435 			*i1 = tcp->tcp_ka_rinterval / 1000;
436 			return (sizeof (int));
437 		case TCP_KEEPALIVE_ABORT_THRESHOLD:
438 			*i1 = tcp->tcp_ka_abort_thres;
439 			return (sizeof (int));
440 		case TCP_CONGESTION: {
441 			size_t len = strlcpy((char *)ptr, CC_ALGO(tcp)->name,
442 			    CC_ALGO_NAME_MAX);
443 			if (len >= CC_ALGO_NAME_MAX)
444 				return (-1);
445 			return (len + 1);
446 		}
447 		case TCP_CORK:
448 			*i1 = tcp->tcp_cork;
449 			return (sizeof (int));
450 		case TCP_RTO_INITIAL:
451 			*i1 = tcp->tcp_rto_initial;
452 			return (sizeof (uint32_t));
453 		case TCP_RTO_MIN:
454 			*i1 = tcp->tcp_rto_min;
455 			return (sizeof (uint32_t));
456 		case TCP_RTO_MAX:
457 			*i1 = tcp->tcp_rto_max;
458 			return (sizeof (uint32_t));
459 		case TCP_LINGER2:
460 			*i1 = tcp->tcp_fin_wait_2_flush_interval / SECONDS;
461 			return (sizeof (int));
462 		}
463 		break;
464 	case IPPROTO_IP:
465 		if (connp->conn_family != AF_INET)
466 			return (-1);
467 		switch (name) {
468 		case IP_OPTIONS:
469 		case T_IP_OPTIONS:
470 			/* Caller ensures enough space */
471 			return (ip_opt_get_user(connp, ptr));
472 		default:
473 			break;
474 		}
475 		break;
476 
477 	case IPPROTO_IPV6:
478 		/*
479 		 * IPPROTO_IPV6 options are only supported for sockets
480 		 * that are using IPv6 on the wire.
481 		 */
482 		if (connp->conn_ipversion != IPV6_VERSION) {
483 			return (-1);
484 		}
485 		switch (name) {
486 		case IPV6_PATHMTU:
487 			if (tcp->tcp_state < TCPS_ESTABLISHED)
488 				return (-1);
489 			break;
490 		}
491 		break;
492 	}
493 	mutex_enter(&connp->conn_lock);
494 	retval = conn_opt_get(&coas, level, name, ptr);
495 	mutex_exit(&connp->conn_lock);
496 	return (retval);
497 }
498 
499 /*
500  * We declare as 'int' rather than 'void' to satisfy pfi_t arg requirements.
501  * Parameters are assumed to be verified by the caller.
502  */
503 /* ARGSUSED */
504 int
505 tcp_opt_set(conn_t *connp, uint_t optset_context, int level, int name,
506     uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
507     void *thisdg_attrs, cred_t *cr)
508 {
509 	tcp_t	*tcp = connp->conn_tcp;
510 	int	*i1 = (int *)invalp;
511 	boolean_t onoff = (*i1 == 0) ? 0 : 1;
512 	boolean_t checkonly;
513 	int	reterr;
514 	tcp_stack_t	*tcps = tcp->tcp_tcps;
515 	conn_opt_arg_t	coas;
516 	uint32_t	val = *((uint32_t *)invalp);
517 
518 	coas.coa_connp = connp;
519 	coas.coa_ixa = connp->conn_ixa;
520 	coas.coa_ipp = &connp->conn_xmit_ipp;
521 	coas.coa_ancillary = B_FALSE;
522 	coas.coa_changed = 0;
523 
524 	switch (optset_context) {
525 	case SETFN_OPTCOM_CHECKONLY:
526 		checkonly = B_TRUE;
527 		/*
528 		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
529 		 * inlen != 0 implies value supplied and
530 		 * 	we have to "pretend" to set it.
531 		 * inlen == 0 implies that there is no
532 		 * 	value part in T_CHECK request and just validation
533 		 * done elsewhere should be enough, we just return here.
534 		 */
535 		if (inlen == 0) {
536 			*outlenp = 0;
537 			return (0);
538 		}
539 		break;
540 	case SETFN_OPTCOM_NEGOTIATE:
541 		checkonly = B_FALSE;
542 		break;
543 	case SETFN_UD_NEGOTIATE: /* error on conn-oriented transports ? */
544 	case SETFN_CONN_NEGOTIATE:
545 		checkonly = B_FALSE;
546 		/*
547 		 * Negotiating local and "association-related" options
548 		 * from other (T_CONN_REQ, T_CONN_RES,T_UNITDATA_REQ)
549 		 * primitives is allowed by XTI, but we choose
550 		 * to not implement this style negotiation for Internet
551 		 * protocols (We interpret it is a must for OSI world but
552 		 * optional for Internet protocols) for all options.
553 		 * [ Will do only for the few options that enable test
554 		 * suites that our XTI implementation of this feature
555 		 * works for transports that do allow it ]
556 		 */
557 		if (!tcp_allow_connopt_set(level, name)) {
558 			*outlenp = 0;
559 			return (EINVAL);
560 		}
561 		break;
562 	default:
563 		/*
564 		 * We should never get here
565 		 */
566 		*outlenp = 0;
567 		return (EINVAL);
568 	}
569 
570 	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
571 	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
572 
573 	/*
574 	 * For TCP, we should have no ancillary data sent down
575 	 * (sendmsg isn't supported for SOCK_STREAM), so thisdg_attrs
576 	 * has to be zero.
577 	 */
578 	ASSERT(thisdg_attrs == NULL);
579 
580 	/*
581 	 * For fixed length options, no sanity check
582 	 * of passed in length is done. It is assumed *_optcom_req()
583 	 * routines do the right thing.
584 	 */
585 	switch (level) {
586 	case SOL_SOCKET:
587 		switch (name) {
588 		case SO_KEEPALIVE:
589 			if (checkonly) {
590 				/* check only case */
591 				break;
592 			}
593 
594 			if (!onoff) {
595 				if (connp->conn_keepalive) {
596 					if (tcp->tcp_ka_tid != 0) {
597 						(void) TCP_TIMER_CANCEL(tcp,
598 						    tcp->tcp_ka_tid);
599 						tcp->tcp_ka_tid = 0;
600 					}
601 					connp->conn_keepalive = 0;
602 				}
603 				break;
604 			}
605 			if (!connp->conn_keepalive) {
606 				/* Crank up the keepalive timer */
607 				tcp->tcp_ka_last_intrvl = 0;
608 				tcp->tcp_ka_tid = TCP_TIMER(tcp,
609 				    tcp_keepalive_timer, tcp->tcp_ka_interval);
610 				connp->conn_keepalive = 1;
611 			}
612 			break;
613 		case SO_SNDBUF: {
614 			if (*i1 > tcps->tcps_max_buf) {
615 				*outlenp = 0;
616 				return (ENOBUFS);
617 			}
618 			if (checkonly)
619 				break;
620 
621 			connp->conn_sndbuf = *i1;
622 			if (tcps->tcps_snd_lowat_fraction != 0) {
623 				connp->conn_sndlowat = connp->conn_sndbuf /
624 				    tcps->tcps_snd_lowat_fraction;
625 			}
626 			(void) tcp_maxpsz_set(tcp, B_TRUE);
627 			/*
628 			 * If we are flow-controlled, recheck the condition.
629 			 * There are apps that increase SO_SNDBUF size when
630 			 * flow-controlled (EWOULDBLOCK), and expect the flow
631 			 * control condition to be lifted right away.
632 			 */
633 			mutex_enter(&tcp->tcp_non_sq_lock);
634 			if (tcp->tcp_flow_stopped &&
635 			    TCP_UNSENT_BYTES(tcp) < connp->conn_sndbuf) {
636 				tcp_clrqfull(tcp);
637 			}
638 			mutex_exit(&tcp->tcp_non_sq_lock);
639 			*outlenp = inlen;
640 			return (0);
641 		}
642 		case SO_RCVBUF:
643 			if (*i1 > tcps->tcps_max_buf) {
644 				*outlenp = 0;
645 				return (ENOBUFS);
646 			}
647 			/* Silently ignore zero */
648 			if (!checkonly && *i1 != 0) {
649 				*i1 = MSS_ROUNDUP(*i1, tcp->tcp_mss);
650 				(void) tcp_rwnd_set(tcp, *i1);
651 			}
652 			/*
653 			 * XXX should we return the rwnd here
654 			 * and tcp_opt_get ?
655 			 */
656 			*outlenp = inlen;
657 			return (0);
658 		case SO_SND_COPYAVOID:
659 			if (!checkonly) {
660 				if (tcp->tcp_loopback ||
661 				    (onoff != 1) || !tcp_zcopy_check(tcp)) {
662 					*outlenp = 0;
663 					return (EOPNOTSUPP);
664 				}
665 				tcp->tcp_snd_zcopy_aware = 1;
666 			}
667 			*outlenp = inlen;
668 			return (0);
669 		}
670 		break;
671 	case IPPROTO_TCP:
672 		switch (name) {
673 		case TCP_NODELAY:
674 			if (!checkonly)
675 				tcp->tcp_naglim = *i1 ? 1 : tcp->tcp_mss;
676 			break;
677 		case TCP_NOTIFY_THRESHOLD:
678 			if (!checkonly)
679 				tcp->tcp_first_timer_threshold = *i1;
680 			break;
681 		case TCP_ABORT_THRESHOLD:
682 			if (!checkonly)
683 				tcp->tcp_second_timer_threshold = *i1;
684 			break;
685 		case TCP_CONN_NOTIFY_THRESHOLD:
686 			if (!checkonly)
687 				tcp->tcp_first_ctimer_threshold = *i1;
688 			break;
689 		case TCP_CONN_ABORT_THRESHOLD:
690 			if (!checkonly)
691 				tcp->tcp_second_ctimer_threshold = *i1;
692 			break;
693 		case TCP_RECVDSTADDR:
694 			if (tcp->tcp_state > TCPS_LISTEN) {
695 				*outlenp = 0;
696 				return (EOPNOTSUPP);
697 			}
698 			/* Setting done in conn_opt_set */
699 			break;
700 		case TCP_INIT_CWND:
701 			if (checkonly)
702 				break;
703 
704 			/*
705 			 * Only allow socket with network configuration
706 			 * privilege to set the initial cwnd to be larger
707 			 * than allowed by RFC 3390.
708 			 */
709 			if (val > MIN(4, MAX(2, 4380 / tcp->tcp_mss))) {
710 				if ((reterr = secpolicy_ip_config(cr, B_TRUE))
711 				    != 0) {
712 					*outlenp = 0;
713 					return (reterr);
714 				}
715 				if (val > tcp_max_init_cwnd) {
716 					*outlenp = 0;
717 					return (EINVAL);
718 				}
719 			}
720 
721 			tcp->tcp_init_cwnd = val;
722 
723 			/*
724 			 * If the socket is connected, AND no outbound data
725 			 * has been sent, reset the actual cwnd values.
726 			 */
727 			if (tcp->tcp_state == TCPS_ESTABLISHED &&
728 			    tcp->tcp_iss == tcp->tcp_snxt - 1) {
729 				tcp->tcp_cwnd =
730 				    MIN(tcp->tcp_rwnd, val * tcp->tcp_mss);
731 			}
732 			break;
733 
734 		/*
735 		 * TCP_KEEPIDLE is in seconds but TCP_KEEPALIVE_THRESHOLD
736 		 * is in milliseconds. TCP_KEEPIDLE is introduced for
737 		 * compatibility with other Unix flavors.
738 		 * We can fall through TCP_KEEPALIVE_THRESHOLD logic after
739 		 * converting the input to milliseconds.
740 		 */
741 		case TCP_KEEPIDLE:
742 			*i1 *= 1000;
743 			/* FALLTHRU */
744 
745 		case TCP_KEEPALIVE_THRESHOLD:
746 			if (checkonly)
747 				break;
748 
749 			if (*i1 < tcps->tcps_keepalive_interval_low ||
750 			    *i1 > tcps->tcps_keepalive_interval_high) {
751 				*outlenp = 0;
752 				return (EINVAL);
753 			}
754 			if (*i1 != tcp->tcp_ka_interval) {
755 				tcp->tcp_ka_interval = *i1;
756 				/*
757 				 * Check if we need to restart the
758 				 * keepalive timer.
759 				 */
760 				if (tcp->tcp_ka_tid != 0) {
761 					ASSERT(connp->conn_keepalive);
762 					(void) TCP_TIMER_CANCEL(tcp,
763 					    tcp->tcp_ka_tid);
764 					tcp->tcp_ka_last_intrvl = 0;
765 					tcp->tcp_ka_tid = TCP_TIMER(tcp,
766 					    tcp_keepalive_timer,
767 					    tcp->tcp_ka_interval);
768 				}
769 			}
770 			break;
771 
772 		/*
773 		 * tcp_ka_abort_thres = tcp_ka_rinterval * tcp_ka_cnt.
774 		 * So setting TCP_KEEPCNT or TCP_KEEPINTVL can affect all the
775 		 * three members - tcp_ka_abort_thres, tcp_ka_rinterval and
776 		 * tcp_ka_cnt.
777 		 */
778 		case TCP_KEEPCNT:
779 			if (checkonly)
780 				break;
781 
782 			if (*i1 == 0) {
783 				return (EINVAL);
784 			} else if (tcp->tcp_ka_rinterval == 0) {
785 				/*
786 				 * When TCP_KEEPCNT is specified without first
787 				 * specifying a TCP_KEEPINTVL, we infer an
788 				 * interval based on a tunable specific to our
789 				 * stack: the tcp_keepalive_abort_interval.
790 				 * (Or the TCP_KEEPALIVE_ABORT_THRESHOLD, in
791 				 * the unlikely event that that has been set.)
792 				 * Given the abort interval's default value of
793 				 * 480 seconds, low TCP_KEEPCNT values can
794 				 * result in intervals that exceed the default
795 				 * maximum RTO of 60 seconds.  Rather than
796 				 * fail in these cases, we (implicitly) clamp
797 				 * the interval at the maximum RTO; if the
798 				 * TCP_KEEPCNT is shortly followed by a
799 				 * TCP_KEEPINTVL (as we expect), the abort
800 				 * threshold will be recalculated correctly --
801 				 * and if a TCP_KEEPINTVL is not forthcoming,
802 				 * keep-alive will at least operate reasonably
803 				 * given the underconfigured state.
804 				 */
805 				uint32_t interval;
806 
807 				interval = tcp->tcp_ka_abort_thres / *i1;
808 
809 				if (interval < tcp->tcp_rto_min)
810 					interval = tcp->tcp_rto_min;
811 
812 				if (interval > tcp->tcp_rto_max)
813 					interval = tcp->tcp_rto_max;
814 
815 				tcp->tcp_ka_rinterval = interval;
816 			} else {
817 				if ((*i1 * tcp->tcp_ka_rinterval) <
818 				    tcps->tcps_keepalive_abort_interval_low ||
819 				    (*i1 * tcp->tcp_ka_rinterval) >
820 				    tcps->tcps_keepalive_abort_interval_high)
821 					return (EINVAL);
822 				tcp->tcp_ka_abort_thres =
823 				    (*i1 * tcp->tcp_ka_rinterval);
824 			}
825 			tcp->tcp_ka_cnt = *i1;
826 			break;
827 		case TCP_KEEPINTVL:
828 			/*
829 			 * TCP_KEEPINTVL is specified in seconds, but
830 			 * tcp_ka_rinterval is in milliseconds.
831 			 */
832 
833 			if (checkonly)
834 				break;
835 
836 			if ((*i1 * 1000) < tcp->tcp_rto_min ||
837 			    (*i1 * 1000) > tcp->tcp_rto_max)
838 				return (EINVAL);
839 
840 			if (tcp->tcp_ka_cnt == 0) {
841 				tcp->tcp_ka_cnt =
842 				    tcp->tcp_ka_abort_thres / (*i1 * 1000);
843 			} else {
844 				if ((*i1 * tcp->tcp_ka_cnt * 1000) <
845 				    tcps->tcps_keepalive_abort_interval_low ||
846 				    (*i1 * tcp->tcp_ka_cnt * 1000) >
847 				    tcps->tcps_keepalive_abort_interval_high)
848 					return (EINVAL);
849 				tcp->tcp_ka_abort_thres =
850 				    (*i1 * tcp->tcp_ka_cnt * 1000);
851 			}
852 			tcp->tcp_ka_rinterval = *i1 * 1000;
853 			break;
854 		case TCP_KEEPALIVE_ABORT_THRESHOLD:
855 			if (!checkonly) {
856 				if (*i1 <
857 				    tcps->tcps_keepalive_abort_interval_low ||
858 				    *i1 >
859 				    tcps->tcps_keepalive_abort_interval_high) {
860 					*outlenp = 0;
861 					return (EINVAL);
862 				}
863 				tcp->tcp_ka_abort_thres = *i1;
864 				tcp->tcp_ka_cnt = 0;
865 				tcp->tcp_ka_rinterval = 0;
866 			}
867 			break;
868 		case TCP_CONGESTION: {
869 			struct cc_algo *algo;
870 
871 			if (checkonly) {
872 				break;
873 			}
874 
875 			/*
876 			 * Make sure the string is NUL-terminated. Some
877 			 * consumers pass only the number of characters
878 			 * in the string, and don't include the NUL
879 			 * terminator, so we set it for them.
880 			 */
881 			if (inlen < CC_ALGO_NAME_MAX) {
882 				invalp[inlen] = '\0';
883 			}
884 			invalp[CC_ALGO_NAME_MAX - 1] = '\0';
885 
886 			if ((algo = cc_load_algo((char *)invalp)) == NULL) {
887 				return (ENOENT);
888 			}
889 
890 			if (CC_ALGO(tcp)->cb_destroy != NULL) {
891 				CC_ALGO(tcp)->cb_destroy(&tcp->tcp_ccv);
892 			}
893 
894 			CC_DATA(tcp) = NULL;
895 			CC_ALGO(tcp) = algo;
896 
897 			if (CC_ALGO(tcp)->cb_init != NULL) {
898 				VERIFY0(CC_ALGO(tcp)->cb_init(&tcp->tcp_ccv));
899 			}
900 
901 			break;
902 		}
903 		case TCP_CORK:
904 			if (!checkonly) {
905 				/*
906 				 * if tcp->tcp_cork was set and is now
907 				 * being unset, we have to make sure that
908 				 * the remaining data gets sent out. Also
909 				 * unset tcp->tcp_cork so that tcp_wput_data()
910 				 * can send data even if it is less than mss
911 				 */
912 				if (tcp->tcp_cork && onoff == 0 &&
913 				    tcp->tcp_unsent > 0) {
914 					tcp->tcp_cork = B_FALSE;
915 					tcp_wput_data(tcp, NULL, B_FALSE);
916 				}
917 				tcp->tcp_cork = onoff;
918 			}
919 			break;
920 		case TCP_RTO_INITIAL:
921 			if (checkonly || val == 0)
922 				break;
923 
924 			/*
925 			 * Sanity checks
926 			 *
927 			 * The initial RTO should be bounded by the minimum
928 			 * and maximum RTO.  And it should also be smaller
929 			 * than the connect attempt abort timeout.  Otherwise,
930 			 * the connection won't be aborted in a period
931 			 * reasonably close to that timeout.
932 			 */
933 			if (val < tcp->tcp_rto_min || val > tcp->tcp_rto_max ||
934 			    val > tcp->tcp_second_ctimer_threshold ||
935 			    val < tcps->tcps_rexmit_interval_initial_low ||
936 			    val > tcps->tcps_rexmit_interval_initial_high) {
937 				*outlenp = 0;
938 				return (EINVAL);
939 			}
940 			tcp->tcp_rto_initial = val;
941 
942 			/*
943 			 * If TCP has not sent anything, need to re-calculate
944 			 * tcp_rto.  Otherwise, this option change does not
945 			 * really affect anything.
946 			 */
947 			if (tcp->tcp_state >= TCPS_SYN_SENT)
948 				break;
949 
950 			tcp->tcp_rtt_sa = MSEC2NSEC(tcp->tcp_rto_initial) << 2;
951 			tcp->tcp_rtt_sd = MSEC2NSEC(tcp->tcp_rto_initial) >> 1;
952 			tcp->tcp_rto = tcp_calculate_rto(tcp, tcps,
953 			    tcps->tcps_conn_grace_period);
954 			break;
955 		case TCP_RTO_MIN:
956 			if (checkonly || val == 0)
957 				break;
958 
959 			if (val < tcps->tcps_rexmit_interval_min_low ||
960 			    val > tcps->tcps_rexmit_interval_min_high ||
961 			    val > tcp->tcp_rto_max) {
962 				*outlenp = 0;
963 				return (EINVAL);
964 			}
965 			tcp->tcp_rto_min = val;
966 			if (tcp->tcp_rto < val)
967 				tcp->tcp_rto = val;
968 			break;
969 		case TCP_RTO_MAX:
970 			if (checkonly || val == 0)
971 				break;
972 
973 			/*
974 			 * Sanity checks
975 			 *
976 			 * The maximum RTO should not be larger than the
977 			 * connection abort timeout.  Otherwise, the
978 			 * connection won't be aborted in a period reasonably
979 			 * close to that timeout.
980 			 */
981 			if (val < tcps->tcps_rexmit_interval_max_low ||
982 			    val > tcps->tcps_rexmit_interval_max_high ||
983 			    val < tcp->tcp_rto_min ||
984 			    val > tcp->tcp_second_timer_threshold) {
985 				*outlenp = 0;
986 				return (EINVAL);
987 			}
988 			tcp->tcp_rto_max = val;
989 			if (tcp->tcp_rto > val)
990 				tcp->tcp_rto = val;
991 			break;
992 		case TCP_LINGER2:
993 			if (checkonly || *i1 == 0)
994 				break;
995 
996 			/*
997 			 * Note that the option value's unit is second.  And
998 			 * the value should be bigger than the private
999 			 * parameter tcp_fin_wait_2_flush_interval's lower
1000 			 * bound and smaller than the current value of that
1001 			 * parameter.  It should be smaller than the current
1002 			 * value to avoid an app setting TCP_LINGER2 to a big
1003 			 * value, causing resource to be held up too long in
1004 			 * FIN-WAIT-2 state.
1005 			 */
1006 			if (*i1 < 0 ||
1007 			    tcps->tcps_fin_wait_2_flush_interval_low/SECONDS >
1008 			    *i1 ||
1009 			    tcps->tcps_fin_wait_2_flush_interval/SECONDS <
1010 			    *i1) {
1011 				*outlenp = 0;
1012 				return (EINVAL);
1013 			}
1014 			tcp->tcp_fin_wait_2_flush_interval = *i1 * SECONDS;
1015 			break;
1016 		default:
1017 			break;
1018 		}
1019 		break;
1020 	case IPPROTO_IP:
1021 		if (connp->conn_family != AF_INET) {
1022 			*outlenp = 0;
1023 			return (EINVAL);
1024 		}
1025 		switch (name) {
1026 		case IP_SEC_OPT:
1027 			/*
1028 			 * We should not allow policy setting after
1029 			 * we start listening for connections.
1030 			 */
1031 			if (tcp->tcp_state == TCPS_LISTEN) {
1032 				return (EINVAL);
1033 			}
1034 			break;
1035 		}
1036 		break;
1037 	case IPPROTO_IPV6:
1038 		/*
1039 		 * IPPROTO_IPV6 options are only supported for sockets
1040 		 * that are using IPv6 on the wire.
1041 		 */
1042 		if (connp->conn_ipversion != IPV6_VERSION) {
1043 			*outlenp = 0;
1044 			return (EINVAL);
1045 		}
1046 
1047 		switch (name) {
1048 		case IPV6_RECVPKTINFO:
1049 			if (!checkonly) {
1050 				/* Force it to be sent up with the next msg */
1051 				tcp->tcp_recvifindex = 0;
1052 			}
1053 			break;
1054 		case IPV6_RECVTCLASS:
1055 			if (!checkonly) {
1056 				/* Force it to be sent up with the next msg */
1057 				tcp->tcp_recvtclass = 0xffffffffU;
1058 			}
1059 			break;
1060 		case IPV6_RECVHOPLIMIT:
1061 			if (!checkonly) {
1062 				/* Force it to be sent up with the next msg */
1063 				tcp->tcp_recvhops = 0xffffffffU;
1064 			}
1065 			break;
1066 		case IPV6_PKTINFO:
1067 			/* This is an extra check for TCP */
1068 			if (inlen == sizeof (struct in6_pktinfo)) {
1069 				struct in6_pktinfo *pkti;
1070 
1071 				pkti = (struct in6_pktinfo *)invalp;
1072 				/*
1073 				 * RFC 3542 states that ipi6_addr must be
1074 				 * the unspecified address when setting the
1075 				 * IPV6_PKTINFO sticky socket option on a
1076 				 * TCP socket.
1077 				 */
1078 				if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr))
1079 					return (EINVAL);
1080 			}
1081 			break;
1082 		case IPV6_SEC_OPT:
1083 			/*
1084 			 * We should not allow policy setting after
1085 			 * we start listening for connections.
1086 			 */
1087 			if (tcp->tcp_state == TCPS_LISTEN) {
1088 				return (EINVAL);
1089 			}
1090 			break;
1091 		}
1092 		break;
1093 	}
1094 	reterr = conn_opt_set(&coas, level, name, inlen, invalp,
1095 	    checkonly, cr);
1096 	if (reterr != 0) {
1097 		*outlenp = 0;
1098 		return (reterr);
1099 	}
1100 
1101 	/*
1102 	 * Common case of OK return with outval same as inval
1103 	 */
1104 	if (invalp != outvalp) {
1105 		/* don't trust bcopy for identical src/dst */
1106 		(void) bcopy(invalp, outvalp, inlen);
1107 	}
1108 	*outlenp = inlen;
1109 
1110 	if (coas.coa_changed & COA_HEADER_CHANGED) {
1111 		/* If we are connected we rebuilt the headers */
1112 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
1113 		    !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
1114 			reterr = tcp_build_hdrs(tcp);
1115 			if (reterr != 0)
1116 				return (reterr);
1117 		}
1118 	}
1119 	if (coas.coa_changed & COA_ROUTE_CHANGED) {
1120 		in6_addr_t nexthop;
1121 
1122 		/*
1123 		 * If we are connected we re-cache the information.
1124 		 * We ignore errors to preserve BSD behavior.
1125 		 * Note that we don't redo IPsec policy lookup here
1126 		 * since the final destination (or source) didn't change.
1127 		 */
1128 		ip_attr_nexthop(&connp->conn_xmit_ipp, connp->conn_ixa,
1129 		    &connp->conn_faddr_v6, &nexthop);
1130 
1131 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
1132 		    !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
1133 			(void) ip_attr_connect(connp, connp->conn_ixa,
1134 			    &connp->conn_laddr_v6, &connp->conn_faddr_v6,
1135 			    &nexthop, connp->conn_fport, NULL, NULL,
1136 			    IPDF_VERIFY_DST);
1137 		}
1138 	}
1139 	if ((coas.coa_changed & COA_SNDBUF_CHANGED) && !IPCL_IS_NONSTR(connp)) {
1140 		connp->conn_wq->q_hiwat = connp->conn_sndbuf;
1141 	}
1142 	if (coas.coa_changed & COA_WROFF_CHANGED) {
1143 		connp->conn_wroff = connp->conn_ht_iphc_allocated +
1144 		    tcps->tcps_wroff_xtra;
1145 		(void) proto_set_tx_wroff(connp->conn_rq, connp,
1146 		    connp->conn_wroff);
1147 	}
1148 	if (coas.coa_changed & COA_OOBINLINE_CHANGED) {
1149 		if (IPCL_IS_NONSTR(connp))
1150 			proto_set_rx_oob_opt(connp, onoff);
1151 	}
1152 	return (0);
1153 }
1154