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