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