Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/inet/tcp/tcp_socket.c
+++ new/usr/src/uts/common/inet/tcp/tcp_socket.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 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2015 Joyent, Inc.
25 25 */
26 26
27 27 /* This file contains all TCP kernel socket related functions. */
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/strlog.h>
31 31 #include <sys/policy.h>
32 32 #include <sys/sockio.h>
33 33 #include <sys/strsubr.h>
34 34 #include <sys/strsun.h>
35 35 #include <sys/squeue_impl.h>
36 36 #include <sys/squeue.h>
37 37 #define _SUN_TPI_VERSION 2
38 38 #include <sys/tihdr.h>
39 39 #include <sys/timod.h>
40 40 #include <sys/tpicommon.h>
41 41 #include <sys/socketvar.h>
42 42
43 43 #include <inet/common.h>
44 44 #include <inet/proto_set.h>
45 45 #include <inet/ip.h>
46 46 #include <inet/tcp.h>
47 47 #include <inet/tcp_impl.h>
48 48
49 49 static void tcp_activate(sock_lower_handle_t, sock_upper_handle_t,
50 50 sock_upcalls_t *, int, cred_t *);
51 51 static int tcp_accept(sock_lower_handle_t, sock_lower_handle_t,
52 52 sock_upper_handle_t, cred_t *);
53 53 static int tcp_bind(sock_lower_handle_t, struct sockaddr *,
54 54 socklen_t, cred_t *);
55 55 static int tcp_listen(sock_lower_handle_t, int, cred_t *);
56 56 static int tcp_connect(sock_lower_handle_t, const struct sockaddr *,
57 57 socklen_t, sock_connid_t *, cred_t *);
58 58 static int tcp_getpeername(sock_lower_handle_t, struct sockaddr *,
59 59 socklen_t *, cred_t *);
60 60 static int tcp_getsockname(sock_lower_handle_t, struct sockaddr *,
61 61 socklen_t *, cred_t *);
62 62 static int tcp_getsockopt(sock_lower_handle_t, int, int, void *,
63 63 socklen_t *, cred_t *);
64 64 static int tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
65 65 socklen_t, cred_t *);
66 66 static int tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
67 67 cred_t *);
68 68 static int tcp_shutdown(sock_lower_handle_t, int, cred_t *);
69 69 static void tcp_clr_flowctrl(sock_lower_handle_t);
70 70 static int tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
71 71 cred_t *);
72 72 static int tcp_close(sock_lower_handle_t, int, cred_t *);
73 73
74 74 sock_downcalls_t sock_tcp_downcalls = {
75 75 tcp_activate,
76 76 tcp_accept,
77 77 tcp_bind,
78 78 tcp_listen,
79 79 tcp_connect,
80 80 tcp_getpeername,
81 81 tcp_getsockname,
82 82 tcp_getsockopt,
83 83 tcp_setsockopt,
84 84 tcp_sendmsg,
85 85 NULL,
86 86 NULL,
87 87 NULL,
88 88 tcp_shutdown,
89 89 tcp_clr_flowctrl,
90 90 tcp_ioctl,
91 91 tcp_close,
92 92 };
93 93
94 94 /* ARGSUSED */
95 95 static void
96 96 tcp_activate(sock_lower_handle_t proto_handle, sock_upper_handle_t sock_handle,
97 97 sock_upcalls_t *sock_upcalls, int flags, cred_t *cr)
98 98 {
99 99 conn_t *connp = (conn_t *)proto_handle;
100 100 struct sock_proto_props sopp;
101 101 extern struct module_info tcp_rinfo;
102 102
103 103 ASSERT(connp->conn_upper_handle == NULL);
104 104
105 105 /* All Solaris components should pass a cred for this operation. */
106 106 ASSERT(cr != NULL);
107 107
108 108 sopp.sopp_flags = SOCKOPT_RCVHIWAT | SOCKOPT_RCVLOWAT |
109 109 SOCKOPT_MAXPSZ | SOCKOPT_MAXBLK | SOCKOPT_RCVTIMER |
110 110 SOCKOPT_RCVTHRESH | SOCKOPT_MAXADDRLEN | SOCKOPT_MINPSZ;
111 111
112 112 sopp.sopp_rxhiwat = SOCKET_RECVHIWATER;
113 113 sopp.sopp_rxlowat = SOCKET_RECVLOWATER;
114 114 sopp.sopp_maxpsz = INFPSZ;
115 115 sopp.sopp_maxblk = INFPSZ;
116 116 sopp.sopp_rcvtimer = SOCKET_TIMER_INTERVAL;
117 117 sopp.sopp_rcvthresh = SOCKET_RECVHIWATER >> 3;
118 118 sopp.sopp_maxaddrlen = sizeof (sin6_t);
119 119 sopp.sopp_minpsz = (tcp_rinfo.mi_minpsz == 1) ? 0 :
120 120 tcp_rinfo.mi_minpsz;
121 121
122 122 connp->conn_upcalls = sock_upcalls;
123 123 connp->conn_upper_handle = sock_handle;
124 124
125 125 ASSERT(connp->conn_rcvbuf != 0 &&
126 126 connp->conn_rcvbuf == connp->conn_tcp->tcp_rwnd);
127 127 (*sock_upcalls->su_set_proto_props)(sock_handle, &sopp);
128 128 }
129 129
130 130 /*ARGSUSED*/
131 131 static int
132 132 tcp_accept(sock_lower_handle_t lproto_handle,
133 133 sock_lower_handle_t eproto_handle, sock_upper_handle_t sock_handle,
134 134 cred_t *cr)
135 135 {
136 136 conn_t *lconnp, *econnp;
137 137 tcp_t *listener, *eager;
138 138
139 139 /*
140 140 * KSSL can move a socket from one listener to another, in which
141 141 * case `lproto_handle' points to the new listener. To ensure that
142 142 * the original listener is used the information is obtained from
143 143 * the eager.
144 144 */
145 145 econnp = (conn_t *)eproto_handle;
146 146 eager = econnp->conn_tcp;
147 147 ASSERT(IPCL_IS_NONSTR(econnp));
148 148 ASSERT(eager->tcp_listener != NULL);
149 149 listener = eager->tcp_listener;
150 150 lconnp = (conn_t *)listener->tcp_connp;
151 151 ASSERT(listener->tcp_state == TCPS_LISTEN);
152 152 ASSERT(lconnp->conn_upper_handle != NULL);
153 153
154 154 /*
155 155 * It is possible for the accept thread to race with the thread that
156 156 * made the su_newconn upcall in tcp_newconn_notify. Both
157 157 * tcp_newconn_notify and tcp_accept require that conn_upper_handle
158 158 * and conn_upcalls be set before returning, so they both write to
159 159 * them. However, we're guaranteed that the value written is the same
160 160 * for both threads.
161 161 */
162 162 ASSERT(econnp->conn_upper_handle == NULL ||
163 163 econnp->conn_upper_handle == sock_handle);
164 164 ASSERT(econnp->conn_upcalls == NULL ||
165 165 econnp->conn_upcalls == lconnp->conn_upcalls);
166 166 econnp->conn_upper_handle = sock_handle;
167 167 econnp->conn_upcalls = lconnp->conn_upcalls;
168 168
169 169 ASSERT(econnp->conn_netstack ==
170 170 listener->tcp_connp->conn_netstack);
171 171 ASSERT(eager->tcp_tcps == listener->tcp_tcps);
172 172
173 173 /*
174 174 * We should have a minimum of 2 references on the conn at this
175 175 * point. One for TCP and one for the newconn notification
176 176 * (which is now taken over by IP). In the normal case we would
177 177 * also have another reference (making a total of 3) for the conn
178 178 * being in the classifier hash list. However the eager could have
179 179 * received an RST subsequently and tcp_closei_local could have
180 180 * removed the eager from the classifier hash list, hence we can't
181 181 * assert that reference.
182 182 */
183 183 ASSERT(econnp->conn_ref >= 2);
184 184
185 185 mutex_enter(&listener->tcp_eager_lock);
186 186 /*
187 187 * Non-STREAMS listeners never defer the notification of new
188 188 * connections.
189 189 */
190 190 ASSERT(!listener->tcp_eager_prev_q0->tcp_conn_def_q0);
191 191 tcp_eager_unlink(eager);
192 192 mutex_exit(&listener->tcp_eager_lock);
193 193 CONN_DEC_REF(listener->tcp_connp);
194 194
195 195 return ((eager->tcp_state < TCPS_ESTABLISHED) ? ECONNABORTED : 0);
196 196 }
197 197
198 198 static int
199 199 tcp_bind(sock_lower_handle_t proto_handle, struct sockaddr *sa,
200 200 socklen_t len, cred_t *cr)
201 201 {
202 202 int error;
203 203 conn_t *connp = (conn_t *)proto_handle;
204 204
205 205 /* All Solaris components should pass a cred for this operation. */
206 206 ASSERT(cr != NULL);
207 207 ASSERT(connp->conn_upper_handle != NULL);
208 208
209 209 error = squeue_synch_enter(connp, NULL);
210 210 if (error != 0) {
211 211 /* failed to enter */
212 212 return (ENOSR);
213 213 }
214 214
215 215 /* binding to a NULL address really means unbind */
216 216 if (sa == NULL) {
217 217 if (connp->conn_tcp->tcp_state < TCPS_LISTEN)
218 218 error = tcp_do_unbind(connp);
219 219 else
220 220 error = EINVAL;
221 221 } else {
222 222 error = tcp_do_bind(connp, sa, len, cr, B_TRUE);
223 223 }
224 224
225 225 squeue_synch_exit(connp);
226 226
227 227 if (error < 0) {
228 228 if (error == -TOUTSTATE)
229 229 error = EINVAL;
230 230 else
231 231 error = proto_tlitosyserr(-error);
232 232 }
233 233
234 234 return (error);
235 235 }
236 236
237 237 /* ARGSUSED */
238 238 static int
239 239 tcp_listen(sock_lower_handle_t proto_handle, int backlog, cred_t *cr)
240 240 {
241 241 conn_t *connp = (conn_t *)proto_handle;
242 242 tcp_t *tcp = connp->conn_tcp;
243 243 int error;
244 244
245 245 ASSERT(connp->conn_upper_handle != NULL);
246 246
247 247 /* All Solaris components should pass a cred for this operation. */
248 248 ASSERT(cr != NULL);
249 249
250 250 error = squeue_synch_enter(connp, NULL);
251 251 if (error != 0) {
252 252 /* failed to enter */
253 253 return (ENOBUFS);
254 254 }
255 255
256 256 error = tcp_do_listen(connp, NULL, 0, backlog, cr, B_FALSE);
257 257 if (error == 0) {
258 258 /*
259 259 * sockfs needs to know what's the maximum number of socket
260 260 * that can be queued on the listener.
261 261 */
262 262 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
263 263 SOCK_OPCTL_ENAB_ACCEPT,
264 264 (uintptr_t)(tcp->tcp_conn_req_max +
265 265 tcp->tcp_tcps->tcps_conn_req_max_q0));
266 266 } else if (error < 0) {
267 267 if (error == -TOUTSTATE)
268 268 error = EINVAL;
269 269 else
270 270 error = proto_tlitosyserr(-error);
271 271 }
272 272 squeue_synch_exit(connp);
273 273 return (error);
274 274 }
275 275
276 276 static int
277 277 tcp_connect(sock_lower_handle_t proto_handle, const struct sockaddr *sa,
278 278 socklen_t len, sock_connid_t *id, cred_t *cr)
279 279 {
280 280 conn_t *connp = (conn_t *)proto_handle;
281 281 int error;
282 282
283 283 ASSERT(connp->conn_upper_handle != NULL);
284 284
285 285 /* All Solaris components should pass a cred for this operation. */
286 286 ASSERT(cr != NULL);
287 287
288 288 error = proto_verify_ip_addr(connp->conn_family, sa, len);
289 289 if (error != 0) {
290 290 return (error);
291 291 }
292 292
293 293 error = squeue_synch_enter(connp, NULL);
294 294 if (error != 0) {
295 295 /* failed to enter */
296 296 return (ENOSR);
297 297 }
298 298
299 299 /*
300 300 * TCP supports quick connect, so no need to do an implicit bind
301 301 */
302 302 error = tcp_do_connect(connp, sa, len, cr, curproc->p_pid);
303 303 if (error == 0) {
304 304 *id = connp->conn_tcp->tcp_connid;
305 305 } else if (error < 0) {
306 306 if (error == -TOUTSTATE) {
307 307 switch (connp->conn_tcp->tcp_state) {
308 308 case TCPS_SYN_SENT:
309 309 error = EALREADY;
310 310 break;
311 311 case TCPS_ESTABLISHED:
312 312 error = EISCONN;
313 313 break;
314 314 case TCPS_LISTEN:
315 315 error = EOPNOTSUPP;
316 316 break;
317 317 default:
318 318 error = EINVAL;
319 319 break;
320 320 }
321 321 } else {
322 322 error = proto_tlitosyserr(-error);
323 323 }
324 324 }
325 325
326 326 if (connp->conn_tcp->tcp_loopback) {
327 327 struct sock_proto_props sopp;
328 328
329 329 sopp.sopp_flags = SOCKOPT_LOOPBACK;
330 330 sopp.sopp_loopback = B_TRUE;
331 331
332 332 (*connp->conn_upcalls->su_set_proto_props)(
333 333 connp->conn_upper_handle, &sopp);
334 334 }
335 335 done:
336 336 squeue_synch_exit(connp);
337 337
338 338 return ((error == 0) ? EINPROGRESS : error);
339 339 }
340 340
341 341 /* ARGSUSED3 */
342 342 static int
343 343 tcp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
344 344 socklen_t *addrlenp, cred_t *cr)
345 345 {
346 346 conn_t *connp = (conn_t *)proto_handle;
347 347 tcp_t *tcp = connp->conn_tcp;
348 348
349 349 /* All Solaris components should pass a cred for this operation. */
350 350 ASSERT(cr != NULL);
351 351
352 352 ASSERT(tcp != NULL);
353 353 if (tcp->tcp_state < TCPS_SYN_RCVD)
354 354 return (ENOTCONN);
355 355
356 356 return (conn_getpeername(connp, addr, addrlenp));
357 357 }
358 358
359 359 /* ARGSUSED3 */
360 360 static int
361 361 tcp_getsockname(sock_lower_handle_t proto_handle, struct sockaddr *addr,
362 362 socklen_t *addrlenp, cred_t *cr)
363 363 {
364 364 conn_t *connp = (conn_t *)proto_handle;
365 365
366 366 /* All Solaris components should pass a cred for this operation. */
367 367 ASSERT(cr != NULL);
368 368
369 369 return (conn_getsockname(connp, addr, addrlenp));
370 370 }
371 371
372 372 /* returns UNIX error, the optlen is a value-result arg */
373 373 static int
374 374 tcp_getsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
375 375 void *optvalp, socklen_t *optlen, cred_t *cr)
376 376 {
377 377 conn_t *connp = (conn_t *)proto_handle;
378 378 int error;
379 379 t_uscalar_t max_optbuf_len;
380 380 void *optvalp_buf;
381 381 int len;
382 382
383 383 ASSERT(connp->conn_upper_handle != NULL);
384 384
385 385 error = proto_opt_check(level, option_name, *optlen, &max_optbuf_len,
386 386 tcp_opt_obj.odb_opt_des_arr,
387 387 tcp_opt_obj.odb_opt_arr_cnt,
388 388 B_FALSE, B_TRUE, cr);
389 389 if (error != 0) {
390 390 if (error < 0) {
391 391 error = proto_tlitosyserr(-error);
392 392 }
393 393 return (error);
394 394 }
395 395
396 396 optvalp_buf = kmem_alloc(max_optbuf_len, KM_SLEEP);
397 397
398 398 error = squeue_synch_enter(connp, NULL);
399 399 if (error == ENOMEM) {
400 400 kmem_free(optvalp_buf, max_optbuf_len);
401 401 return (ENOMEM);
402 402 }
403 403
404 404 len = tcp_opt_get(connp, level, option_name, optvalp_buf);
405 405 squeue_synch_exit(connp);
406 406
407 407 if (len == -1) {
408 408 kmem_free(optvalp_buf, max_optbuf_len);
409 409 return (EINVAL);
410 410 }
411 411
412 412 /*
413 413 * update optlen and copy option value
414 414 */
415 415 t_uscalar_t size = MIN(len, *optlen);
416 416
417 417 bcopy(optvalp_buf, optvalp, size);
418 418 bcopy(&size, optlen, sizeof (size));
419 419
420 420 kmem_free(optvalp_buf, max_optbuf_len);
421 421 return (0);
422 422 }
423 423
424 424 static int
425 425 tcp_setsockopt(sock_lower_handle_t proto_handle, int level, int option_name,
426 426 const void *optvalp, socklen_t optlen, cred_t *cr)
427 427 {
428 428 conn_t *connp = (conn_t *)proto_handle;
429 429 int error;
430 430
431 431 ASSERT(connp->conn_upper_handle != NULL);
432 432 /*
433 433 * Entering the squeue synchronously can result in a context switch,
434 434 * which can cause a rather sever performance degradation. So we try to
435 435 * handle whatever options we can without entering the squeue.
436 436 */
437 437 if (level == IPPROTO_TCP) {
438 438 switch (option_name) {
439 439 case TCP_NODELAY:
440 440 if (optlen != sizeof (int32_t))
441 441 return (EINVAL);
442 442 mutex_enter(&connp->conn_tcp->tcp_non_sq_lock);
443 443 connp->conn_tcp->tcp_naglim = *(int *)optvalp ? 1 :
444 444 connp->conn_tcp->tcp_mss;
445 445 mutex_exit(&connp->conn_tcp->tcp_non_sq_lock);
446 446 return (0);
447 447 default:
448 448 break;
449 449 }
450 450 }
451 451
452 452 error = squeue_synch_enter(connp, NULL);
453 453 if (error == ENOMEM) {
454 454 return (ENOMEM);
455 455 }
456 456
457 457 error = proto_opt_check(level, option_name, optlen, NULL,
458 458 tcp_opt_obj.odb_opt_des_arr,
459 459 tcp_opt_obj.odb_opt_arr_cnt,
460 460 B_TRUE, B_FALSE, cr);
461 461
462 462 if (error != 0) {
463 463 if (error < 0) {
464 464 error = proto_tlitosyserr(-error);
465 465 }
466 466 squeue_synch_exit(connp);
467 467 return (error);
468 468 }
469 469
470 470 error = tcp_opt_set(connp, SETFN_OPTCOM_NEGOTIATE, level, option_name,
471 471 optlen, (uchar_t *)optvalp, (uint_t *)&optlen, (uchar_t *)optvalp,
472 472 NULL, cr);
473 473 squeue_synch_exit(connp);
474 474
475 475 ASSERT(error >= 0);
476 476
477 477 return (error);
478 478 }
479 479
480 480 /* ARGSUSED */
481 481 static int
482 482 tcp_sendmsg(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
483 483 cred_t *cr)
484 484 {
485 485 tcp_t *tcp;
486 486 uint32_t msize;
487 487 conn_t *connp = (conn_t *)proto_handle;
488 488 int32_t tcpstate;
489 489
490 490 /* All Solaris components should pass a cred for this operation. */
491 491 ASSERT(cr != NULL);
492 492
493 493 ASSERT(connp->conn_ref >= 2);
494 494 ASSERT(connp->conn_upper_handle != NULL);
495 495
496 496 if (msg->msg_controllen != 0) {
497 497 freemsg(mp);
498 498 return (EOPNOTSUPP);
499 499 }
500 500
501 501 switch (DB_TYPE(mp)) {
502 502 case M_DATA:
503 503 tcp = connp->conn_tcp;
504 504 ASSERT(tcp != NULL);
505 505
506 506 tcpstate = tcp->tcp_state;
507 507 if (tcpstate < TCPS_ESTABLISHED) {
508 508 freemsg(mp);
509 509 /*
510 510 * We return ENOTCONN if the endpoint is trying to
511 511 * connect or has never been connected, and EPIPE if it
512 512 * has been disconnected. The connection id helps us
513 513 * distinguish between the last two cases.
514 514 */
515 515 return ((tcpstate == TCPS_SYN_SENT) ? ENOTCONN :
516 516 ((tcp->tcp_connid > 0) ? EPIPE : ENOTCONN));
517 517 } else if (tcpstate > TCPS_CLOSE_WAIT) {
518 518 freemsg(mp);
519 519 return (EPIPE);
520 520 }
521 521
522 522 msize = msgdsize(mp);
523 523
524 524 mutex_enter(&tcp->tcp_non_sq_lock);
525 525 tcp->tcp_squeue_bytes += msize;
526 526 /*
527 527 * Squeue Flow Control
528 528 */
529 529 if (TCP_UNSENT_BYTES(tcp) > connp->conn_sndbuf) {
530 530 tcp_setqfull(tcp);
531 531 }
532 532 mutex_exit(&tcp->tcp_non_sq_lock);
533 533
534 534 /*
535 535 * The application may pass in an address in the msghdr, but
536 536 * we ignore the address on connection-oriented sockets.
537 537 * Just like BSD this code does not generate an error for
538 538 * TCP (a CONNREQUIRED socket) when sending to an address
539 539 * passed in with sendto/sendmsg. Instead the data is
540 540 * delivered on the connection as if no address had been
541 541 * supplied.
542 542 */
543 543 CONN_INC_REF(connp);
544 544
545 545 if (msg->msg_flags & MSG_OOB) {
546 546 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, tcp_output_urgent,
547 547 connp, NULL, tcp_squeue_flag, SQTAG_TCP_OUTPUT);
548 548 } else {
549 549 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, tcp_output,
550 550 connp, NULL, tcp_squeue_flag, SQTAG_TCP_OUTPUT);
551 551 }
552 552
553 553 return (0);
554 554
555 555 default:
556 556 ASSERT(0);
557 557 }
558 558
559 559 freemsg(mp);
560 560 return (0);
561 561 }
562 562
563 563 /* ARGSUSED */
564 564 static int
565 565 tcp_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr)
566 566 {
567 567 conn_t *connp = (conn_t *)proto_handle;
568 568 tcp_t *tcp = connp->conn_tcp;
569 569
570 570 ASSERT(connp->conn_upper_handle != NULL);
571 571
572 572 /* All Solaris components should pass a cred for this operation. */
573 573 ASSERT(cr != NULL);
574 574
575 575 /*
576 576 * X/Open requires that we check the connected state.
577 577 */
578 578 if (tcp->tcp_state < TCPS_SYN_SENT)
579 579 return (ENOTCONN);
580 580
581 581 /* shutdown the send side */
582 582 if (how != SHUT_RD) {
583 583 mblk_t *bp;
584 584
585 585 bp = allocb_wait(0, BPRI_HI, STR_NOSIG, NULL);
586 586 CONN_INC_REF(connp);
587 587 SQUEUE_ENTER_ONE(connp->conn_sqp, bp, tcp_shutdown_output,
588 588 connp, NULL, SQ_NODRAIN, SQTAG_TCP_SHUTDOWN_OUTPUT);
589 589
590 590 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
591 591 SOCK_OPCTL_SHUT_SEND, 0);
592 592 }
593 593
594 594 /* shutdown the recv side */
595 595 if (how != SHUT_WR)
596 596 (*connp->conn_upcalls->su_opctl)(connp->conn_upper_handle,
597 597 SOCK_OPCTL_SHUT_RECV, 0);
598 598
599 599 return (0);
600 600 }
601 601
602 602 static void
603 603 tcp_clr_flowctrl(sock_lower_handle_t proto_handle)
604 604 {
605 605 conn_t *connp = (conn_t *)proto_handle;
606 606 tcp_t *tcp = connp->conn_tcp;
607 607 mblk_t *mp;
608 608 int error;
609 609
610 610 ASSERT(connp->conn_upper_handle != NULL);
611 611
612 612 /*
613 613 * If tcp->tcp_rsrv_mp == NULL, it means that tcp_clr_flowctrl()
614 614 * is currently running.
615 615 */
616 616 mutex_enter(&tcp->tcp_rsrv_mp_lock);
617 617 if ((mp = tcp->tcp_rsrv_mp) == NULL) {
618 618 mutex_exit(&tcp->tcp_rsrv_mp_lock);
619 619 return;
620 620 }
621 621 tcp->tcp_rsrv_mp = NULL;
622 622 mutex_exit(&tcp->tcp_rsrv_mp_lock);
623 623
624 624 error = squeue_synch_enter(connp, mp);
625 625 ASSERT(error == 0);
626 626
627 627 mutex_enter(&tcp->tcp_rsrv_mp_lock);
628 628 tcp->tcp_rsrv_mp = mp;
629 629 mutex_exit(&tcp->tcp_rsrv_mp_lock);
630 630
631 631 if (tcp->tcp_fused) {
632 632 tcp_fuse_backenable(tcp);
633 633 } else {
634 634 tcp->tcp_rwnd = connp->conn_rcvbuf;
635 635 /*
636 636 * Send back a window update immediately if TCP is above
637 637 * ESTABLISHED state and the increase of the rcv window
638 638 * that the other side knows is at least 1 MSS after flow
639 639 * control is lifted.
640 640 */
641 641 if (tcp->tcp_state >= TCPS_ESTABLISHED &&
642 642 tcp_rwnd_reopen(tcp) == TH_ACK_NEEDED) {
643 643 tcp_xmit_ctl(NULL, tcp,
644 644 (tcp->tcp_swnd == 0) ? tcp->tcp_suna :
645 645 tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
646 646 }
647 647 }
648 648
649 649 squeue_synch_exit(connp);
650 650 }
651 651
652 652 /* ARGSUSED */
653 653 static int
654 654 tcp_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
655 655 int mode, int32_t *rvalp, cred_t *cr)
656 656 {
657 657 conn_t *connp = (conn_t *)proto_handle;
658 658 int error;
659 659
660 660 ASSERT(connp->conn_upper_handle != NULL);
661 661
662 662 /* All Solaris components should pass a cred for this operation. */
663 663 ASSERT(cr != NULL);
664 664
665 665 /*
666 666 * If we don't have a helper stream then create one.
667 667 * ip_create_helper_stream takes care of locking the conn_t,
668 668 * so this check for NULL is just a performance optimization.
669 669 */
670 670 if (connp->conn_helper_info == NULL) {
671 671 tcp_stack_t *tcps = connp->conn_tcp->tcp_tcps;
672 672
673 673 /*
674 674 * Create a helper stream for non-STREAMS socket.
675 675 */
676 676 error = ip_create_helper_stream(connp, tcps->tcps_ldi_ident);
677 677 if (error != 0) {
678 678 ip0dbg(("tcp_ioctl: create of IP helper stream "
679 679 "failed %d\n", error));
680 680 return (error);
681 681 }
682 682 }
683 683
684 684 switch (cmd) {
685 685 case ND_SET:
686 686 case ND_GET:
687 687 case _SIOCSOCKFALLBACK:
688 688 case TCP_IOC_ABORT_CONN:
689 689 case TI_GETPEERNAME:
690 690 case TI_GETMYNAME:
691 691 ip1dbg(("tcp_ioctl: cmd 0x%x on non streams socket",
692 692 cmd));
693 693 error = EINVAL;
694 694 break;
695 695 default:
696 696 /*
697 697 * If the conn is not closing, pass on to IP using
698 698 * helper stream. Bump the ioctlref to prevent tcp_close
699 699 * from closing the rq/wq out from underneath the ioctl
700 700 * if it ends up queued or aborted/interrupted.
701 701 */
702 702 mutex_enter(&connp->conn_lock);
703 703 if (connp->conn_state_flags & (CONN_CLOSING)) {
704 704 mutex_exit(&connp->conn_lock);
705 705 error = EINVAL;
706 706 break;
707 707 }
708 708 CONN_INC_IOCTLREF_LOCKED(connp);
709 709 error = ldi_ioctl(connp->conn_helper_info->iphs_handle,
710 710 cmd, arg, mode, cr, rvalp);
711 711 CONN_DEC_IOCTLREF(connp);
712 712 break;
713 713 }
714 714 return (error);
715 715 }
716 716
717 717 /* ARGSUSED */
718 718 static int
719 719 tcp_close(sock_lower_handle_t proto_handle, int flags, cred_t *cr)
720 720 {
721 721 conn_t *connp = (conn_t *)proto_handle;
722 722
723 723 ASSERT(connp->conn_upper_handle != NULL);
724 724
725 725 /* All Solaris components should pass a cred for this operation. */
726 726 ASSERT(cr != NULL);
727 727
728 728 tcp_close_common(connp, flags);
729 729
730 730 ip_free_helper_stream(connp);
731 731
732 732 /*
733 733 * Drop IP's reference on the conn. This is the last reference
734 734 * on the connp if the state was less than established. If the
735 735 * connection has gone into timewait state, then we will have
736 736 * one ref for the TCP and one more ref (total of two) for the
737 737 * classifier connected hash list (a timewait connections stays
738 738 * in connected hash till closed).
739 739 *
740 740 * We can't assert the references because there might be other
741 741 * transient reference places because of some walkers or queued
742 742 * packets in squeue for the timewait state.
743 743 */
744 744 CONN_DEC_REF(connp);
745 745
746 746 /*
747 747 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
748 748 * freeing the socket.
749 749 */
750 750 return (EINPROGRESS);
751 751 }
752 752
753 753 /* ARGSUSED */
754 754 sock_lower_handle_t
755 755 tcp_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
756 756 uint_t *smodep, int *errorp, int flags, cred_t *credp)
757 757 {
758 758 conn_t *connp;
759 759 boolean_t isv6 = family == AF_INET6;
760 760
761 761 if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
762 762 (proto != 0 && proto != IPPROTO_TCP)) {
763 763 *errorp = EPROTONOSUPPORT;
764 764 return (NULL);
765 765 }
766 766
767 767 connp = tcp_create_common(credp, isv6, B_TRUE, errorp);
768 768 if (connp == NULL) {
769 769 return (NULL);
770 770 }
771 771
772 772 /*
773 773 * Put the ref for TCP. Ref for IP was already put
774 774 * by ipcl_conn_create. Also make the conn_t globally
775 775 * visible to walkers
776 776 */
777 777 mutex_enter(&connp->conn_lock);
778 778 CONN_INC_REF_LOCKED(connp);
779 779 ASSERT(connp->conn_ref == 2);
780 780 connp->conn_state_flags &= ~CONN_INCIPIENT;
781 781
782 782 connp->conn_flags |= IPCL_NONSTR;
783 783 mutex_exit(&connp->conn_lock);
784 784
785 785 ASSERT(errorp != NULL);
786 786 *errorp = 0;
787 787 *sock_downcalls = &sock_tcp_downcalls;
788 788 *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
789 789 SM_SENDFILESUPP;
790 790
791 791 return ((sock_lower_handle_t)connp);
792 792 }
793 793
794 794 /*
795 795 * tcp_fallback
796 796 *
797 797 * A direct socket is falling back to using STREAMS. The queue
798 798 * that is being passed down was created using tcp_open() with
799 799 * the SO_FALLBACK flag set. As a result, the queue is not
800 800 * associated with a conn, and the q_ptrs instead contain the
801 801 * dev and minor area that should be used.
802 802 *
803 803 * The 'issocket' flag indicates whether the FireEngine
804 804 * optimizations should be used. The common case would be that
805 805 * optimizations are enabled, and they might be subsequently
806 806 * disabled using the _SIOCSOCKFALLBACK ioctl.
807 807 */
808 808
809 809 /*
810 810 * An active connection is falling back to TPI. Gather all the information
811 811 * required by the STREAM head and TPI sonode and send it up.
812 812 */
813 813 static void
814 814 tcp_fallback_noneager(tcp_t *tcp, mblk_t *stropt_mp, queue_t *q,
815 815 boolean_t issocket, so_proto_quiesced_cb_t quiesced_cb,
816 816 sock_quiesce_arg_t *arg)
817 817 {
818 818 conn_t *connp = tcp->tcp_connp;
819 819 struct stroptions *stropt;
820 820 struct T_capability_ack tca;
821 821 struct sockaddr_in6 laddr, faddr;
822 822 socklen_t laddrlen, faddrlen;
823 823 short opts;
824 824 int error;
825 825 mblk_t *mp, *mpnext;
826 826
827 827 connp->conn_dev = (dev_t)RD(q)->q_ptr;
828 828 connp->conn_minor_arena = WR(q)->q_ptr;
829 829
830 830 RD(q)->q_ptr = WR(q)->q_ptr = connp;
831 831
832 832 connp->conn_rq = RD(q);
833 833 connp->conn_wq = WR(q);
834 834
835 835 WR(q)->q_qinfo = &tcp_sock_winit;
836 836
837 837 if (!issocket)
838 838 tcp_use_pure_tpi(tcp);
839 839
840 840 /*
841 841 * free the helper stream
842 842 */
843 843 ip_free_helper_stream(connp);
844 844
845 845 /*
846 846 * Notify the STREAM head about options
847 847 */
848 848 DB_TYPE(stropt_mp) = M_SETOPTS;
849 849 stropt = (struct stroptions *)stropt_mp->b_rptr;
850 850 stropt_mp->b_wptr += sizeof (struct stroptions);
851 851 stropt->so_flags = SO_HIWAT | SO_WROFF | SO_MAXBLK;
852 852
853 853 stropt->so_wroff = connp->conn_ht_iphc_len + (tcp->tcp_loopback ? 0 :
854 854 tcp->tcp_tcps->tcps_wroff_xtra);
855 855 if (tcp->tcp_snd_sack_ok)
856 856 stropt->so_wroff += TCPOPT_MAX_SACK_LEN;
857 857 stropt->so_hiwat = connp->conn_rcvbuf;
858 858 stropt->so_maxblk = tcp_maxpsz_set(tcp, B_FALSE);
859 859
860 860 putnext(RD(q), stropt_mp);
861 861
862 862 /*
863 863 * Collect the information needed to sync with the sonode
864 864 */
865 865 tcp_do_capability_ack(tcp, &tca, TC1_INFO|TC1_ACCEPTOR_ID);
866 866
867 867 laddrlen = faddrlen = sizeof (sin6_t);
868 868 (void) tcp_getsockname((sock_lower_handle_t)connp,
869 869 (struct sockaddr *)&laddr, &laddrlen, CRED());
870 870 error = tcp_getpeername((sock_lower_handle_t)connp,
871 871 (struct sockaddr *)&faddr, &faddrlen, CRED());
872 872 if (error != 0)
873 873 faddrlen = 0;
874 874
875 875 opts = 0;
876 876 if (connp->conn_oobinline)
877 877 opts |= SO_OOBINLINE;
878 878 if (connp->conn_ixa->ixa_flags & IXAF_DONTROUTE)
879 879 opts |= SO_DONTROUTE;
880 880
881 881 /*
882 882 * Notify the socket that the protocol is now quiescent,
883 883 * and it's therefore safe move data from the socket
884 884 * to the stream head.
885 885 */
886 886 mp = (*quiesced_cb)(connp->conn_upper_handle, arg, &tca,
887 887 (struct sockaddr *)&laddr, laddrlen,
888 888 (struct sockaddr *)&faddr, faddrlen, opts);
889 889
890 890 while (mp != NULL) {
891 891 mpnext = mp->b_next;
892 892 tcp->tcp_rcv_list = mp->b_next;
893 893 mp->b_next = NULL;
894 894 putnext(q, mp);
895 895 mp = mpnext;
896 896 }
897 897 ASSERT(tcp->tcp_rcv_last_head == NULL);
898 898 ASSERT(tcp->tcp_rcv_last_tail == NULL);
899 899 ASSERT(tcp->tcp_rcv_cnt == 0);
900 900
901 901 /*
902 902 * All eagers in q0 are marked as being non-STREAM, so they will
903 903 * make su_newconn upcalls when the handshake completes, which
904 904 * will fail (resulting in the conn being closed). So we just blow
905 905 * off everything in q0 instead of waiting for the inevitable.
906 906 */
907 907 if (tcp->tcp_conn_req_cnt_q0 != 0)
908 908 tcp_eager_cleanup(tcp, B_TRUE);
909 909 }
910 910
911 911 /*
912 912 * An eager is falling back to TPI. All we have to do is send
913 913 * up a T_CONN_IND.
914 914 */
915 915 static void
916 916 tcp_fallback_eager(tcp_t *eager, boolean_t issocket,
917 917 so_proto_quiesced_cb_t quiesced_cb, sock_quiesce_arg_t *arg)
918 918 {
919 919 conn_t *connp = eager->tcp_connp;
920 920 tcp_t *listener = eager->tcp_listener;
921 921 mblk_t *mp;
922 922
923 923 ASSERT(listener != NULL);
924 924
925 925 /*
926 926 * Notify the socket that the protocol is now quiescent,
927 927 * and it's therefore safe move data from the socket
928 928 * to tcp's rcv queue.
929 929 */
930 930 mp = (*quiesced_cb)(connp->conn_upper_handle, arg, NULL, NULL, 0,
931 931 NULL, 0, 0);
932 932
933 933 if (mp != NULL) {
934 934 ASSERT(eager->tcp_rcv_cnt == 0);
935 935
936 936 eager->tcp_rcv_list = mp;
937 937 eager->tcp_rcv_cnt = msgdsize(mp);
938 938 while (mp->b_next != NULL) {
939 939 mp = mp->b_next;
940 940 eager->tcp_rcv_cnt += msgdsize(mp);
941 941 }
942 942 eager->tcp_rcv_last_head = mp;
943 943 while (mp->b_cont)
944 944 mp = mp->b_cont;
945 945 eager->tcp_rcv_last_tail = mp;
946 946 if (eager->tcp_rcv_cnt > eager->tcp_rwnd)
947 947 eager->tcp_rwnd = 0;
948 948 else
949 949 eager->tcp_rwnd -= eager->tcp_rcv_cnt;
950 950 }
951 951
952 952 if (!issocket)
953 953 eager->tcp_issocket = B_FALSE;
954 954 /*
955 955 * The stream for this eager does not yet exist, so mark it as
956 956 * being detached.
957 957 */
958 958 eager->tcp_detached = B_TRUE;
959 959 eager->tcp_hard_binding = B_TRUE;
960 960 connp->conn_rq = listener->tcp_connp->conn_rq;
961 961 connp->conn_wq = listener->tcp_connp->conn_wq;
962 962
963 963 /* Send up the connection indication */
964 964 mp = eager->tcp_conn.tcp_eager_conn_ind;
965 965 ASSERT(mp != NULL);
966 966 eager->tcp_conn.tcp_eager_conn_ind = NULL;
967 967
968 968 /*
969 969 * TLI/XTI applications will get confused by
970 970 * sending eager as an option since it violates
971 971 * the option semantics. So remove the eager as
972 972 * option since TLI/XTI app doesn't need it anyway.
973 973 */
974 974 if (!issocket) {
975 975 struct T_conn_ind *conn_ind;
976 976
977 977 conn_ind = (struct T_conn_ind *)mp->b_rptr;
978 978 conn_ind->OPT_length = 0;
979 979 conn_ind->OPT_offset = 0;
980 980 }
981 981
982 982 /*
983 983 * Sockfs guarantees that the listener will not be closed
984 984 * during fallback. So we can safely use the listener's queue.
985 985 */
986 986 putnext(listener->tcp_connp->conn_rq, mp);
987 987 }
988 988
989 989
990 990 int
991 991 tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q,
992 992 boolean_t direct_sockfs, so_proto_quiesced_cb_t quiesced_cb,
993 993 sock_quiesce_arg_t *arg)
994 994 {
995 995 tcp_t *tcp;
996 996 conn_t *connp = (conn_t *)proto_handle;
997 997 int error;
998 998 mblk_t *stropt_mp;
999 999 mblk_t *ordrel_mp;
1000 1000
1001 1001 tcp = connp->conn_tcp;
1002 1002
1003 1003 stropt_mp = allocb_wait(sizeof (struct stroptions), BPRI_HI, STR_NOSIG,
1004 1004 NULL);
1005 1005
1006 1006 /* Pre-allocate the T_ordrel_ind mblk. */
1007 1007 ASSERT(tcp->tcp_ordrel_mp == NULL);
1008 1008 ordrel_mp = allocb_wait(sizeof (struct T_ordrel_ind), BPRI_HI,
1009 1009 STR_NOSIG, NULL);
1010 1010 ordrel_mp->b_datap->db_type = M_PROTO;
1011 1011 ((struct T_ordrel_ind *)ordrel_mp->b_rptr)->PRIM_type = T_ORDREL_IND;
1012 1012 ordrel_mp->b_wptr += sizeof (struct T_ordrel_ind);
1013 1013
1014 1014 /*
1015 1015 * Enter the squeue so that no new packets can come in
1016 1016 */
1017 1017 error = squeue_synch_enter(connp, NULL);
1018 1018 if (error != 0) {
1019 1019 /* failed to enter, free all the pre-allocated messages. */
1020 1020 freeb(stropt_mp);
1021 1021 freeb(ordrel_mp);
1022 1022 return (ENOMEM);
1023 1023 }
1024 1024
1025 1025 /*
1026 1026 * Do not allow fallback on connections making use of SO_REUSEPORT.
1027 1027 */
1028 1028 if (tcp->tcp_rg_bind != NULL) {
1029 1029 freeb(stropt_mp);
1030 1030 freeb(ordrel_mp);
1031 1031 squeue_synch_exit(connp);
1032 1032 return (EINVAL);
1033 1033 }
1034 1034
1035 1035 /*
1036 1036 * Both endpoints must be of the same type (either STREAMS or
1037 1037 * non-STREAMS) for fusion to be enabled. So if we are fused,
1038 1038 * we have to unfuse.
1039 1039 */
1040 1040 if (tcp->tcp_fused)
1041 1041 tcp_unfuse(tcp);
1042 1042
1043 1043 if (tcp->tcp_listener != NULL) {
1044 1044 /* The eager will deal with opts when accept() is called */
1045 1045 freeb(stropt_mp);
1046 1046 tcp_fallback_eager(tcp, direct_sockfs, quiesced_cb, arg);
1047 1047 } else {
1048 1048 tcp_fallback_noneager(tcp, stropt_mp, q, direct_sockfs,
1049 1049 quiesced_cb, arg);
1050 1050 }
1051 1051
1052 1052 /*
1053 1053 * No longer a direct socket
1054 1054 *
1055 1055 * Note that we intentionally leave the upper_handle and upcalls
1056 1056 * intact, since eagers may still be using them.
1057 1057 */
1058 1058 connp->conn_flags &= ~IPCL_NONSTR;
1059 1059 tcp->tcp_ordrel_mp = ordrel_mp;
1060 1060
1061 1061 /*
1062 1062 * There should be atleast two ref's (IP + TCP)
1063 1063 */
1064 1064 ASSERT(connp->conn_ref >= 2);
1065 1065 squeue_synch_exit(connp);
1066 1066
1067 1067 return (0);
1068 1068 }
1069 1069
1070 1070 /*
1071 1071 * Notifies a non-STREAMS based listener about a new connection. This
1072 1072 * function is executed on the *eager*'s squeue once the 3 way handshake
1073 1073 * has completed. Note that the behavior differs from STREAMS, where the
1074 1074 * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s
1075 1075 * squeue.
1076 1076 *
1077 1077 * Returns B_TRUE if the notification succeeded and an upper handle was
1078 1078 * obtained. `tcp' should be closed on failure.
1079 1079 */
1080 1080 boolean_t
1081 1081 tcp_newconn_notify(tcp_t *tcp, ip_recv_attr_t *ira)
1082 1082 {
1083 1083 tcp_t *listener = tcp->tcp_listener;
1084 1084 conn_t *lconnp = listener->tcp_connp;
1085 1085 conn_t *econnp = tcp->tcp_connp;
1086 1086 tcp_t *tail;
1087 1087 ipaddr_t *addr_cache;
1088 1088 sock_upper_handle_t upper;
1089 1089 struct sock_proto_props sopp;
1090 1090
1091 1091 mutex_enter(&listener->tcp_eager_lock);
1092 1092 /*
1093 1093 * Take the eager out, if it is in the list of droppable eagers
1094 1094 * as we are here because the 3W handshake is over.
1095 1095 */
1096 1096 MAKE_UNDROPPABLE(tcp);
1097 1097 /*
1098 1098 * The eager already has an extra ref put in tcp_input_data
1099 1099 * so that it stays till accept comes back even though it
1100 1100 * might get into TCPS_CLOSED as a result of a TH_RST etc.
1101 1101 */
1102 1102 ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
1103 1103 listener->tcp_conn_req_cnt_q0--;
1104 1104 listener->tcp_conn_req_cnt_q++;
1105 1105
1106 1106 /* Move from SYN_RCVD to ESTABLISHED list */
1107 1107 tcp->tcp_eager_next_q0->tcp_eager_prev_q0 = tcp->tcp_eager_prev_q0;
1108 1108 tcp->tcp_eager_prev_q0->tcp_eager_next_q0 = tcp->tcp_eager_next_q0;
1109 1109 tcp->tcp_eager_prev_q0 = NULL;
1110 1110 tcp->tcp_eager_next_q0 = NULL;
1111 1111
1112 1112 /*
1113 1113 * Insert at end of the queue because connections are accepted
1114 1114 * in chronological order. Leaving the older connections at front
1115 1115 * of the queue helps reducing search time.
1116 1116 */
1117 1117 tail = listener->tcp_eager_last_q;
1118 1118 if (tail != NULL)
1119 1119 tail->tcp_eager_next_q = tcp;
1120 1120 else
1121 1121 listener->tcp_eager_next_q = tcp;
1122 1122 listener->tcp_eager_last_q = tcp;
1123 1123 tcp->tcp_eager_next_q = NULL;
1124 1124
1125 1125 /* we have timed out before */
1126 1126 if (tcp->tcp_syn_rcvd_timeout != 0) {
1127 1127 tcp->tcp_syn_rcvd_timeout = 0;
1128 1128 listener->tcp_syn_rcvd_timeout--;
1129 1129 if (listener->tcp_syn_defense &&
1130 1130 listener->tcp_syn_rcvd_timeout <=
1131 1131 (listener->tcp_tcps->tcps_conn_req_max_q0 >> 5) &&
1132 1132 10*MINUTES < TICK_TO_MSEC(ddi_get_lbolt64() -
1133 1133 listener->tcp_last_rcv_lbolt)) {
1134 1134 /*
1135 1135 * Turn off the defense mode if we
1136 1136 * believe the SYN attack is over.
1137 1137 */
1138 1138 listener->tcp_syn_defense = B_FALSE;
1139 1139 if (listener->tcp_ip_addr_cache) {
1140 1140 kmem_free((void *)listener->tcp_ip_addr_cache,
1141 1141 IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
1142 1142 listener->tcp_ip_addr_cache = NULL;
1143 1143 }
1144 1144 }
1145 1145 }
1146 1146 addr_cache = (ipaddr_t *)(listener->tcp_ip_addr_cache);
1147 1147 if (addr_cache != NULL) {
1148 1148 /*
1149 1149 * We have finished a 3-way handshake with this
1150 1150 * remote host. This proves the IP addr is good.
1151 1151 * Cache it!
1152 1152 */
1153 1153 addr_cache[IP_ADDR_CACHE_HASH(tcp->tcp_connp->conn_faddr_v4)] =
1154 1154 tcp->tcp_connp->conn_faddr_v4;
1155 1155 }
1156 1156 mutex_exit(&listener->tcp_eager_lock);
1157 1157
1158 1158 /*
1159 1159 * Notify the ULP about the newconn. It is guaranteed that no
1160 1160 * tcp_accept() call will be made for the eager if the
1161 1161 * notification fails.
1162 1162 */
1163 1163 if ((upper = (*lconnp->conn_upcalls->su_newconn)
1164 1164 (lconnp->conn_upper_handle, (sock_lower_handle_t)econnp,
1165 1165 &sock_tcp_downcalls, ira->ira_cred, ira->ira_cpid,
1166 1166 &econnp->conn_upcalls)) == NULL) {
1167 1167 return (B_FALSE);
1168 1168 }
1169 1169 econnp->conn_upper_handle = upper;
1170 1170
1171 1171 tcp->tcp_detached = B_FALSE;
1172 1172 tcp->tcp_hard_binding = B_FALSE;
1173 1173 tcp->tcp_tconnind_started = B_TRUE;
1174 1174
1175 1175 if (econnp->conn_keepalive) {
1176 1176 tcp->tcp_ka_last_intrvl = 0;
1177 1177 tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_timer,
1178 1178 tcp->tcp_ka_interval);
1179 1179 }
1180 1180
1181 1181 /* Update the necessary parameters */
1182 1182 tcp_get_proto_props(tcp, &sopp);
1183 1183
1184 1184 (*econnp->conn_upcalls->su_set_proto_props)
1185 1185 (econnp->conn_upper_handle, &sopp);
1186 1186
1187 1187 return (B_TRUE);
1188 1188 }
|
↓ open down ↓ |
1188 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX