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