1 /* 2 * Copyright (c) 2003, 2004 Jeffrey M. Hsu. All rights reserved. 3 * Copyright (c) 2003, 2004 The DragonFly Project. All rights reserved. 4 * 5 * This code is derived from software contributed to The DragonFly Project 6 * by Jeffrey M. Hsu. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of The DragonFly Project nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific, prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1982, 1986, 1988, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the University of 49 * California, Berkeley and its contributors. 50 * 4. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 67 * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.17 2002/10/11 11:46:44 ume Exp $ 68 * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.42 2007/04/22 01:13:14 dillon Exp $ 69 */ 70 71 #include "opt_ipsec.h" 72 #include "opt_inet6.h" 73 #include "opt_tcpdebug.h" 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/kernel.h> 78 #include <sys/malloc.h> 79 #include <sys/sysctl.h> 80 #include <sys/globaldata.h> 81 #include <sys/thread.h> 82 83 #include <sys/mbuf.h> 84 #ifdef INET6 85 #include <sys/domain.h> 86 #endif /* INET6 */ 87 #include <sys/socket.h> 88 #include <sys/socketvar.h> 89 #include <sys/protosw.h> 90 91 #include <sys/thread2.h> 92 #include <sys/msgport2.h> 93 94 #include <net/if.h> 95 #include <net/netisr.h> 96 #include <net/route.h> 97 98 #include <netinet/in.h> 99 #include <netinet/in_systm.h> 100 #ifdef INET6 101 #include <netinet/ip6.h> 102 #endif 103 #include <netinet/in_pcb.h> 104 #ifdef INET6 105 #include <netinet6/in6_pcb.h> 106 #endif 107 #include <netinet/in_var.h> 108 #include <netinet/ip_var.h> 109 #ifdef INET6 110 #include <netinet6/ip6_var.h> 111 #endif 112 #include <netinet/tcp.h> 113 #include <netinet/tcp_fsm.h> 114 #include <netinet/tcp_seq.h> 115 #include <netinet/tcp_timer.h> 116 #include <netinet/tcp_var.h> 117 #include <netinet/tcpip.h> 118 #ifdef TCPDEBUG 119 #include <netinet/tcp_debug.h> 120 #endif 121 122 #ifdef IPSEC 123 #include <netinet6/ipsec.h> 124 #endif /*IPSEC*/ 125 126 /* 127 * TCP protocol interface to socket abstraction. 128 */ 129 extern char *tcpstates[]; /* XXX ??? */ 130 131 static int tcp_attach (struct socket *, struct pru_attach_info *); 132 static int tcp_connect (struct tcpcb *, struct sockaddr *, 133 struct thread *); 134 #ifdef INET6 135 static int tcp6_connect (struct tcpcb *, struct sockaddr *, 136 struct thread *); 137 #endif /* INET6 */ 138 static struct tcpcb * 139 tcp_disconnect (struct tcpcb *); 140 static struct tcpcb * 141 tcp_usrclosed (struct tcpcb *); 142 143 #ifdef TCPDEBUG 144 #define TCPDEBUG0 int ostate = 0 145 #define TCPDEBUG1() ostate = tp ? tp->t_state : 0 146 #define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \ 147 tcp_trace(TA_USER, ostate, tp, 0, 0, req) 148 #else 149 #define TCPDEBUG0 150 #define TCPDEBUG1() 151 #define TCPDEBUG2(req) 152 #endif 153 154 /* 155 * TCP attaches to socket via pru_attach(), reserving space, 156 * and an internet control block. 157 */ 158 static int 159 tcp_usr_attach(struct socket *so, int proto, struct pru_attach_info *ai) 160 { 161 int error; 162 struct inpcb *inp; 163 struct tcpcb *tp = 0; 164 TCPDEBUG0; 165 166 crit_enter(); 167 inp = so->so_pcb; 168 TCPDEBUG1(); 169 if (inp) { 170 error = EISCONN; 171 goto out; 172 } 173 174 error = tcp_attach(so, ai); 175 if (error) 176 goto out; 177 178 if ((so->so_options & SO_LINGER) && so->so_linger == 0) 179 so->so_linger = TCP_LINGERTIME; 180 tp = sototcpcb(so); 181 out: 182 TCPDEBUG2(PRU_ATTACH); 183 crit_exit(); 184 return error; 185 } 186 187 /* 188 * pru_detach() detaches the TCP protocol from the socket. 189 * If the protocol state is non-embryonic, then can't 190 * do this directly: have to initiate a pru_disconnect(), 191 * which may finish later; embryonic TCB's can just 192 * be discarded here. 193 */ 194 static int 195 tcp_usr_detach(struct socket *so) 196 { 197 int error = 0; 198 struct inpcb *inp; 199 struct tcpcb *tp; 200 TCPDEBUG0; 201 202 crit_enter(); 203 inp = so->so_pcb; 204 if (inp == NULL) { 205 crit_exit(); 206 return EINVAL; /* XXX */ 207 } 208 209 /* 210 * It's possible for the tcpcb (tp) to disconnect from the inp due 211 * to tcp_drop()->tcp_close() being called. This may occur *after* 212 * the detach message has been queued so we may find a NULL tp here. 213 */ 214 if ((tp = intotcpcb(inp)) != NULL) { 215 TCPDEBUG1(); 216 tp = tcp_disconnect(tp); 217 TCPDEBUG2(PRU_DETACH); 218 } 219 crit_exit(); 220 return error; 221 } 222 223 #define COMMON_START(so, inp) \ 224 TCPDEBUG0; \ 225 \ 226 crit_enter(); \ 227 inp = so->so_pcb; \ 228 do { \ 229 if (inp == 0) { \ 230 crit_exit(); \ 231 return EINVAL; \ 232 } \ 233 tp = intotcpcb(inp); \ 234 TCPDEBUG1(); \ 235 } while(0) 236 237 #define COMMON_END(req) out: TCPDEBUG2(req); crit_exit(); return error; goto out 238 239 240 /* 241 * Give the socket an address. 242 */ 243 static int 244 tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 245 { 246 int error = 0; 247 struct inpcb *inp; 248 struct tcpcb *tp; 249 struct sockaddr_in *sinp; 250 251 COMMON_START(so, inp); 252 253 /* 254 * Must check for multicast addresses and disallow binding 255 * to them. 256 */ 257 sinp = (struct sockaddr_in *)nam; 258 if (sinp->sin_family == AF_INET && 259 IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 260 error = EAFNOSUPPORT; 261 goto out; 262 } 263 error = in_pcbbind(inp, nam, td); 264 if (error) 265 goto out; 266 COMMON_END(PRU_BIND); 267 268 } 269 270 #ifdef INET6 271 static int 272 tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 273 { 274 int error = 0; 275 struct inpcb *inp; 276 struct tcpcb *tp; 277 struct sockaddr_in6 *sin6p; 278 279 COMMON_START(so, inp); 280 281 /* 282 * Must check for multicast addresses and disallow binding 283 * to them. 284 */ 285 sin6p = (struct sockaddr_in6 *)nam; 286 if (sin6p->sin6_family == AF_INET6 && 287 IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { 288 error = EAFNOSUPPORT; 289 goto out; 290 } 291 inp->inp_vflag &= ~INP_IPV4; 292 inp->inp_vflag |= INP_IPV6; 293 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { 294 if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) 295 inp->inp_vflag |= INP_IPV4; 296 else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { 297 struct sockaddr_in sin; 298 299 in6_sin6_2_sin(&sin, sin6p); 300 inp->inp_vflag |= INP_IPV4; 301 inp->inp_vflag &= ~INP_IPV6; 302 error = in_pcbbind(inp, (struct sockaddr *)&sin, td); 303 goto out; 304 } 305 } 306 error = in6_pcbbind(inp, nam, td); 307 if (error) 308 goto out; 309 COMMON_END(PRU_BIND); 310 } 311 #endif /* INET6 */ 312 313 #ifdef SMP 314 struct netmsg_inswildcard { 315 struct lwkt_msg nm_lmsg; 316 struct inpcb *nm_inp; 317 struct inpcbinfo *nm_pcbinfo; 318 }; 319 320 static int 321 in_pcbinswildcardhash_handler(struct lwkt_msg *msg0) 322 { 323 struct netmsg_inswildcard *msg = (struct netmsg_inswildcard *)msg0; 324 325 in_pcbinswildcardhash_oncpu(msg->nm_inp, msg->nm_pcbinfo); 326 lwkt_replymsg(&msg->nm_lmsg, 0); 327 return (EASYNC); 328 } 329 #endif 330 331 /* 332 * Prepare to accept connections. 333 */ 334 static int 335 tcp_usr_listen(struct socket *so, struct thread *td) 336 { 337 int error = 0; 338 struct inpcb *inp; 339 struct tcpcb *tp; 340 #ifdef SMP 341 int cpu; 342 #endif 343 344 COMMON_START(so, inp); 345 if (inp->inp_lport == 0) { 346 error = in_pcbbind(inp, NULL, td); 347 if (error != 0) 348 goto out; 349 } 350 351 tp->t_state = TCPS_LISTEN; 352 #ifdef SMP 353 /* 354 * We have to set the flag because we can't have other cpus 355 * messing with our inp's flags. 356 */ 357 inp->inp_flags |= INP_WILDCARD_MP; 358 for (cpu = 0; cpu < ncpus2; cpu++) { 359 struct netmsg_inswildcard *msg; 360 361 if (cpu == mycpu->gd_cpuid) { 362 in_pcbinswildcardhash(inp); 363 continue; 364 } 365 366 msg = kmalloc(sizeof(struct netmsg_inswildcard), M_LWKTMSG, 367 M_INTWAIT); 368 lwkt_initmsg(&msg->nm_lmsg, &netisr_afree_rport, 0, 369 lwkt_cmd_func(in_pcbinswildcardhash_handler), 370 lwkt_cmd_op_none); 371 msg->nm_inp = inp; 372 msg->nm_pcbinfo = &tcbinfo[cpu]; 373 lwkt_sendmsg(tcp_cport(cpu), &msg->nm_lmsg); 374 } 375 #else 376 in_pcbinswildcardhash(inp); 377 #endif 378 COMMON_END(PRU_LISTEN); 379 } 380 381 #ifdef INET6 382 static int 383 tcp6_usr_listen(struct socket *so, struct thread *td) 384 { 385 int error = 0; 386 struct inpcb *inp; 387 struct tcpcb *tp; 388 #ifdef SMP 389 int cpu; 390 #endif 391 392 COMMON_START(so, inp); 393 if (inp->inp_lport == 0) { 394 if (!(inp->inp_flags & IN6P_IPV6_V6ONLY)) 395 inp->inp_vflag |= INP_IPV4; 396 else 397 inp->inp_vflag &= ~INP_IPV4; 398 error = in6_pcbbind(inp, (struct sockaddr *)0, td); 399 } 400 if (error == 0) 401 tp->t_state = TCPS_LISTEN; 402 #ifdef SMP 403 /* 404 * We have to set the flag because we can't have other cpus 405 * messing with our inp's flags. 406 */ 407 inp->inp_flags |= INP_WILDCARD_MP; 408 for (cpu = 0; cpu < ncpus2; cpu++) { 409 struct netmsg_inswildcard *msg; 410 411 if (cpu == mycpu->gd_cpuid) { 412 in_pcbinswildcardhash(inp); 413 continue; 414 } 415 416 msg = kmalloc(sizeof(struct netmsg_inswildcard), M_LWKTMSG, 417 M_INTWAIT); 418 lwkt_initmsg(&msg->nm_lmsg, &netisr_afree_rport, 0, 419 lwkt_cmd_func(in_pcbinswildcardhash_handler), 420 lwkt_cmd_op_none); 421 msg->nm_inp = inp; 422 msg->nm_pcbinfo = &tcbinfo[cpu]; 423 lwkt_sendmsg(tcp_cport(cpu), &msg->nm_lmsg); 424 } 425 #else 426 in_pcbinswildcardhash(inp); 427 #endif 428 COMMON_END(PRU_LISTEN); 429 } 430 #endif /* INET6 */ 431 432 /* 433 * Initiate connection to peer. 434 * Create a template for use in transmissions on this connection. 435 * Enter SYN_SENT state, and mark socket as connecting. 436 * Start keep-alive timer, and seed output sequence space. 437 * Send initial segment on connection. 438 */ 439 static int 440 tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 441 { 442 int error = 0; 443 struct inpcb *inp; 444 struct tcpcb *tp; 445 struct sockaddr_in *sinp; 446 447 COMMON_START(so, inp); 448 449 /* 450 * Must disallow TCP ``connections'' to multicast addresses. 451 */ 452 sinp = (struct sockaddr_in *)nam; 453 if (sinp->sin_family == AF_INET 454 && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { 455 error = EAFNOSUPPORT; 456 goto out; 457 } 458 459 if (!prison_remote_ip(td, (struct sockaddr*)sinp)) { 460 error = EAFNOSUPPORT; /* IPv6 only jail */ 461 goto out; 462 } 463 464 if ((error = tcp_connect(tp, nam, td)) != 0) 465 goto out; 466 error = tcp_output(tp); 467 COMMON_END(PRU_CONNECT); 468 } 469 470 #ifdef INET6 471 static int 472 tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 473 { 474 int error = 0; 475 struct inpcb *inp; 476 struct tcpcb *tp; 477 struct sockaddr_in6 *sin6p; 478 479 COMMON_START(so, inp); 480 481 /* 482 * Must disallow TCP ``connections'' to multicast addresses. 483 */ 484 sin6p = (struct sockaddr_in6 *)nam; 485 if (sin6p->sin6_family == AF_INET6 486 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { 487 error = EAFNOSUPPORT; 488 goto out; 489 } 490 491 if (!prison_remote_ip(td, nam)) { 492 error = EAFNOSUPPORT; /* IPv4 only jail */ 493 goto out; 494 } 495 496 if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { 497 struct sockaddr_in sin; 498 499 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { 500 error = EINVAL; 501 goto out; 502 } 503 504 in6_sin6_2_sin(&sin, sin6p); 505 inp->inp_vflag |= INP_IPV4; 506 inp->inp_vflag &= ~INP_IPV6; 507 if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) 508 goto out; 509 error = tcp_output(tp); 510 goto out; 511 } 512 inp->inp_vflag &= ~INP_IPV4; 513 inp->inp_vflag |= INP_IPV6; 514 inp->inp_inc.inc_isipv6 = 1; 515 if ((error = tcp6_connect(tp, nam, td)) != 0) 516 goto out; 517 error = tcp_output(tp); 518 COMMON_END(PRU_CONNECT); 519 } 520 #endif /* INET6 */ 521 522 /* 523 * Initiate disconnect from peer. 524 * If connection never passed embryonic stage, just drop; 525 * else if don't need to let data drain, then can just drop anyways, 526 * else have to begin TCP shutdown process: mark socket disconnecting, 527 * drain unread data, state switch to reflect user close, and 528 * send segment (e.g. FIN) to peer. Socket will be really disconnected 529 * when peer sends FIN and acks ours. 530 * 531 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 532 */ 533 static int 534 tcp_usr_disconnect(struct socket *so) 535 { 536 int error = 0; 537 struct inpcb *inp; 538 struct tcpcb *tp; 539 540 COMMON_START(so, inp); 541 tp = tcp_disconnect(tp); 542 COMMON_END(PRU_DISCONNECT); 543 } 544 545 /* 546 * Accept a connection. Essentially all the work is 547 * done at higher levels; just return the address 548 * of the peer, storing through addr. 549 */ 550 static int 551 tcp_usr_accept(struct socket *so, struct sockaddr **nam) 552 { 553 int error = 0; 554 struct inpcb *inp; 555 struct tcpcb *tp = NULL; 556 TCPDEBUG0; 557 558 crit_enter(); 559 inp = so->so_pcb; 560 if (so->so_state & SS_ISDISCONNECTED) { 561 error = ECONNABORTED; 562 goto out; 563 } 564 if (inp == 0) { 565 crit_exit(); 566 return (EINVAL); 567 } 568 tp = intotcpcb(inp); 569 TCPDEBUG1(); 570 in_setpeeraddr(so, nam); 571 COMMON_END(PRU_ACCEPT); 572 } 573 574 #ifdef INET6 575 static int 576 tcp6_usr_accept(struct socket *so, struct sockaddr **nam) 577 { 578 int error = 0; 579 struct inpcb *inp; 580 struct tcpcb *tp = NULL; 581 TCPDEBUG0; 582 583 crit_enter(); 584 inp = so->so_pcb; 585 586 if (so->so_state & SS_ISDISCONNECTED) { 587 error = ECONNABORTED; 588 goto out; 589 } 590 if (inp == 0) { 591 crit_exit(); 592 return (EINVAL); 593 } 594 tp = intotcpcb(inp); 595 TCPDEBUG1(); 596 in6_mapped_peeraddr(so, nam); 597 COMMON_END(PRU_ACCEPT); 598 } 599 #endif /* INET6 */ 600 /* 601 * Mark the connection as being incapable of further output. 602 */ 603 static int 604 tcp_usr_shutdown(struct socket *so) 605 { 606 int error = 0; 607 struct inpcb *inp; 608 struct tcpcb *tp; 609 610 COMMON_START(so, inp); 611 socantsendmore(so); 612 tp = tcp_usrclosed(tp); 613 if (tp) 614 error = tcp_output(tp); 615 COMMON_END(PRU_SHUTDOWN); 616 } 617 618 /* 619 * After a receive, possibly send window update to peer. 620 */ 621 static int 622 tcp_usr_rcvd(struct socket *so, int flags) 623 { 624 int error = 0; 625 struct inpcb *inp; 626 struct tcpcb *tp; 627 628 COMMON_START(so, inp); 629 tcp_output(tp); 630 COMMON_END(PRU_RCVD); 631 } 632 633 /* 634 * Do a send by putting data in output queue and updating urgent 635 * marker if URG set. Possibly send more data. Unlike the other 636 * pru_*() routines, the mbuf chains are our responsibility. We 637 * must either enqueue them or free them. The other pru_* routines 638 * generally are caller-frees. 639 */ 640 static int 641 tcp_usr_send(struct socket *so, int flags, struct mbuf *m, 642 struct sockaddr *nam, struct mbuf *control, struct thread *td) 643 { 644 int error = 0; 645 struct inpcb *inp; 646 struct tcpcb *tp; 647 #ifdef INET6 648 int isipv6; 649 #endif 650 TCPDEBUG0; 651 652 crit_enter(); 653 inp = so->so_pcb; 654 655 if (inp == NULL) { 656 /* 657 * OOPS! we lost a race, the TCP session got reset after 658 * we checked SS_CANTSENDMORE, eg: while doing uiomove or a 659 * network interrupt in the non-critical section of sosend(). 660 */ 661 if (m) 662 m_freem(m); 663 if (control) 664 m_freem(control); 665 error = ECONNRESET; /* XXX EPIPE? */ 666 tp = NULL; 667 TCPDEBUG1(); 668 goto out; 669 } 670 #ifdef INET6 671 isipv6 = nam && nam->sa_family == AF_INET6; 672 #endif /* INET6 */ 673 tp = intotcpcb(inp); 674 TCPDEBUG1(); 675 if (control) { 676 /* TCP doesn't do control messages (rights, creds, etc) */ 677 if (control->m_len) { 678 m_freem(control); 679 if (m) 680 m_freem(m); 681 error = EINVAL; 682 goto out; 683 } 684 m_freem(control); /* empty control, just free it */ 685 } 686 if(!(flags & PRUS_OOB)) { 687 ssb_appendstream(&so->so_snd, m); 688 if (nam && tp->t_state < TCPS_SYN_SENT) { 689 /* 690 * Do implied connect if not yet connected, 691 * initialize window to default value, and 692 * initialize maxseg/maxopd using peer's cached 693 * MSS. 694 */ 695 #ifdef INET6 696 if (isipv6) 697 error = tcp6_connect(tp, nam, td); 698 else 699 #endif /* INET6 */ 700 error = tcp_connect(tp, nam, td); 701 if (error) 702 goto out; 703 tp->snd_wnd = TTCP_CLIENT_SND_WND; 704 tcp_mss(tp, -1); 705 } 706 707 if (flags & PRUS_EOF) { 708 /* 709 * Close the send side of the connection after 710 * the data is sent. 711 */ 712 socantsendmore(so); 713 tp = tcp_usrclosed(tp); 714 } 715 if (tp != NULL) { 716 if (flags & PRUS_MORETOCOME) 717 tp->t_flags |= TF_MORETOCOME; 718 error = tcp_output(tp); 719 if (flags & PRUS_MORETOCOME) 720 tp->t_flags &= ~TF_MORETOCOME; 721 } 722 } else { 723 if (ssb_space(&so->so_snd) < -512) { 724 m_freem(m); 725 error = ENOBUFS; 726 goto out; 727 } 728 /* 729 * According to RFC961 (Assigned Protocols), 730 * the urgent pointer points to the last octet 731 * of urgent data. We continue, however, 732 * to consider it to indicate the first octet 733 * of data past the urgent section. 734 * Otherwise, snd_up should be one lower. 735 */ 736 ssb_appendstream(&so->so_snd, m); 737 if (nam && tp->t_state < TCPS_SYN_SENT) { 738 /* 739 * Do implied connect if not yet connected, 740 * initialize window to default value, and 741 * initialize maxseg/maxopd using peer's cached 742 * MSS. 743 */ 744 #ifdef INET6 745 if (isipv6) 746 error = tcp6_connect(tp, nam, td); 747 else 748 #endif /* INET6 */ 749 error = tcp_connect(tp, nam, td); 750 if (error) 751 goto out; 752 tp->snd_wnd = TTCP_CLIENT_SND_WND; 753 tcp_mss(tp, -1); 754 } 755 tp->snd_up = tp->snd_una + so->so_snd.ssb_cc; 756 tp->t_flags |= TF_FORCE; 757 error = tcp_output(tp); 758 tp->t_flags &= ~TF_FORCE; 759 } 760 COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : 761 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); 762 } 763 764 /* 765 * Abort the TCP. 766 */ 767 static int 768 tcp_usr_abort(struct socket *so) 769 { 770 int error = 0; 771 struct inpcb *inp; 772 struct tcpcb *tp; 773 774 COMMON_START(so, inp); 775 tp = tcp_drop(tp, ECONNABORTED); 776 COMMON_END(PRU_ABORT); 777 } 778 779 /* 780 * Receive out-of-band data. 781 */ 782 static int 783 tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags) 784 { 785 int error = 0; 786 struct inpcb *inp; 787 struct tcpcb *tp; 788 789 COMMON_START(so, inp); 790 if ((so->so_oobmark == 0 && 791 (so->so_state & SS_RCVATMARK) == 0) || 792 so->so_options & SO_OOBINLINE || 793 tp->t_oobflags & TCPOOB_HADDATA) { 794 error = EINVAL; 795 goto out; 796 } 797 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 798 error = EWOULDBLOCK; 799 goto out; 800 } 801 m->m_len = 1; 802 *mtod(m, caddr_t) = tp->t_iobc; 803 if ((flags & MSG_PEEK) == 0) 804 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 805 COMMON_END(PRU_RCVOOB); 806 } 807 808 /* xxx - should be const */ 809 struct pr_usrreqs tcp_usrreqs = { 810 .pru_abort = tcp_usr_abort, 811 .pru_accept = tcp_usr_accept, 812 .pru_attach = tcp_usr_attach, 813 .pru_bind = tcp_usr_bind, 814 .pru_connect = tcp_usr_connect, 815 .pru_connect2 = pru_connect2_notsupp, 816 .pru_control = in_control, 817 .pru_detach = tcp_usr_detach, 818 .pru_disconnect = tcp_usr_disconnect, 819 .pru_listen = tcp_usr_listen, 820 .pru_peeraddr = in_setpeeraddr, 821 .pru_rcvd = tcp_usr_rcvd, 822 .pru_rcvoob = tcp_usr_rcvoob, 823 .pru_send = tcp_usr_send, 824 .pru_sense = pru_sense_null, 825 .pru_shutdown = tcp_usr_shutdown, 826 .pru_sockaddr = in_setsockaddr, 827 .pru_sosend = sosend, 828 .pru_soreceive = soreceive, 829 .pru_sopoll = sopoll 830 }; 831 832 #ifdef INET6 833 struct pr_usrreqs tcp6_usrreqs = { 834 .pru_abort = tcp_usr_abort, 835 .pru_accept = tcp6_usr_accept, 836 .pru_attach = tcp_usr_attach, 837 .pru_bind = tcp6_usr_bind, 838 .pru_connect = tcp6_usr_connect, 839 .pru_connect2 = pru_connect2_notsupp, 840 .pru_control = in6_control, 841 .pru_detach = tcp_usr_detach, 842 .pru_disconnect = tcp_usr_disconnect, 843 .pru_listen = tcp6_usr_listen, 844 .pru_peeraddr = in6_mapped_peeraddr, 845 .pru_rcvd = tcp_usr_rcvd, 846 .pru_rcvoob = tcp_usr_rcvoob, 847 .pru_send = tcp_usr_send, 848 .pru_sense = pru_sense_null, 849 .pru_shutdown = tcp_usr_shutdown, 850 .pru_sockaddr = in6_mapped_sockaddr, 851 .pru_sosend = sosend, 852 .pru_soreceive = soreceive, 853 .pru_sopoll = sopoll 854 }; 855 #endif /* INET6 */ 856 857 static int 858 tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin, 859 struct sockaddr_in *if_sin) 860 { 861 struct inpcb *inp = tp->t_inpcb, *oinp; 862 struct socket *so = inp->inp_socket; 863 struct tcpcb *otp; 864 struct rmxp_tao *taop; 865 struct rmxp_tao tao_noncached; 866 867 oinp = in_pcblookup_hash(&tcbinfo[mycpu->gd_cpuid], 868 sin->sin_addr, sin->sin_port, 869 inp->inp_laddr.s_addr != INADDR_ANY ? 870 inp->inp_laddr : if_sin->sin_addr, 871 inp->inp_lport, 0, NULL); 872 if (oinp != NULL) { 873 if (oinp != inp && (otp = intotcpcb(oinp)) != NULL && 874 otp->t_state == TCPS_TIME_WAIT && 875 (ticks - otp->t_starttime) < tcp_msl && 876 (otp->t_flags & TF_RCVD_CC)) 877 tcp_close(otp); 878 else 879 return (EADDRINUSE); 880 } 881 if (inp->inp_laddr.s_addr == INADDR_ANY) 882 inp->inp_laddr = if_sin->sin_addr; 883 inp->inp_faddr = sin->sin_addr; 884 inp->inp_fport = sin->sin_port; 885 inp->inp_cpcbinfo = &tcbinfo[mycpu->gd_cpuid]; 886 in_pcbinsconnhash(inp); 887 888 /* Compute window scaling to request. */ 889 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 890 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.ssb_hiwat) 891 tp->request_r_scale++; 892 893 soisconnecting(so); 894 tcpstat.tcps_connattempt++; 895 tp->t_state = TCPS_SYN_SENT; 896 callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); 897 tp->iss = tcp_new_isn(tp); 898 tcp_sendseqinit(tp); 899 900 /* 901 * Generate a CC value for this connection and 902 * check whether CC or CCnew should be used. 903 */ 904 if ((taop = tcp_gettaocache(&tp->t_inpcb->inp_inc)) == NULL) { 905 taop = &tao_noncached; 906 bzero(taop, sizeof *taop); 907 } 908 909 tp->cc_send = CC_INC(tcp_ccgen); 910 if (taop->tao_ccsent != 0 && 911 CC_GEQ(tp->cc_send, taop->tao_ccsent)) { 912 taop->tao_ccsent = tp->cc_send; 913 } else { 914 taop->tao_ccsent = 0; 915 tp->t_flags |= TF_SENDCCNEW; 916 } 917 918 return (0); 919 } 920 921 #ifdef SMP 922 923 struct netmsg_tcp_connect { 924 struct lwkt_msg nm_lmsg; 925 struct tcpcb *nm_tp; 926 struct sockaddr_in *nm_sin; 927 struct sockaddr_in *nm_ifsin; 928 }; 929 930 static int 931 tcp_connect_handler(lwkt_msg_t lmsg) 932 { 933 struct netmsg_tcp_connect *msg = (void *)lmsg; 934 int error; 935 936 error = tcp_connect_oncpu(msg->nm_tp, msg->nm_sin, msg->nm_ifsin); 937 lwkt_replymsg(lmsg, error); 938 return(EASYNC); 939 } 940 941 #endif 942 943 /* 944 * Common subroutine to open a TCP connection to remote host specified 945 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local 946 * port number if needed. Call in_pcbladdr to do the routing and to choose 947 * a local host address (interface). If there is an existing incarnation 948 * of the same connection in TIME-WAIT state and if the remote host was 949 * sending CC options and if the connection duration was < MSL, then 950 * truncate the previous TIME-WAIT state and proceed. 951 * Initialize connection parameters and enter SYN-SENT state. 952 */ 953 static int 954 tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) 955 { 956 struct inpcb *inp = tp->t_inpcb; 957 struct sockaddr_in *sin = (struct sockaddr_in *)nam; 958 struct sockaddr_in *if_sin; 959 int error; 960 #ifdef SMP 961 lwkt_port_t port; 962 #endif 963 964 if (inp->inp_lport == 0) { 965 error = in_pcbbind(inp, (struct sockaddr *)NULL, td); 966 if (error) 967 return (error); 968 } 969 970 /* 971 * Cannot simply call in_pcbconnect, because there might be an 972 * earlier incarnation of this same connection still in 973 * TIME_WAIT state, creating an ADDRINUSE error. 974 */ 975 error = in_pcbladdr(inp, nam, &if_sin, td); 976 if (error) 977 return (error); 978 979 #ifdef SMP 980 port = tcp_addrport(sin->sin_addr.s_addr, sin->sin_port, 981 inp->inp_laddr.s_addr ? 982 inp->inp_laddr.s_addr : if_sin->sin_addr.s_addr, 983 inp->inp_lport); 984 985 if (port->mp_td != curthread) { 986 struct netmsg_tcp_connect msg; 987 988 lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0, 989 lwkt_cmd_func(tcp_connect_handler), lwkt_cmd_op_none); 990 msg.nm_tp = tp; 991 msg.nm_sin = sin; 992 msg.nm_ifsin = if_sin; 993 error = lwkt_domsg(port, &msg.nm_lmsg); 994 } else 995 #endif 996 error = tcp_connect_oncpu(tp, sin, if_sin); 997 998 return (error); 999 } 1000 1001 #ifdef INET6 1002 static int 1003 tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) 1004 { 1005 struct inpcb *inp = tp->t_inpcb, *oinp; 1006 struct socket *so = inp->inp_socket; 1007 struct tcpcb *otp; 1008 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 1009 struct in6_addr *addr6; 1010 struct rmxp_tao *taop; 1011 struct rmxp_tao tao_noncached; 1012 int error; 1013 1014 if (inp->inp_lport == 0) { 1015 error = in6_pcbbind(inp, (struct sockaddr *)0, td); 1016 if (error) 1017 return error; 1018 } 1019 1020 /* 1021 * Cannot simply call in_pcbconnect, because there might be an 1022 * earlier incarnation of this same connection still in 1023 * TIME_WAIT state, creating an ADDRINUSE error. 1024 */ 1025 error = in6_pcbladdr(inp, nam, &addr6, td); 1026 if (error) 1027 return error; 1028 oinp = in6_pcblookup_hash(inp->inp_cpcbinfo, 1029 &sin6->sin6_addr, sin6->sin6_port, 1030 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) ? 1031 addr6 : &inp->in6p_laddr, 1032 inp->inp_lport, 0, NULL); 1033 if (oinp) { 1034 if (oinp != inp && (otp = intotcpcb(oinp)) != NULL && 1035 otp->t_state == TCPS_TIME_WAIT && 1036 (ticks - otp->t_starttime) < tcp_msl && 1037 (otp->t_flags & TF_RCVD_CC)) 1038 otp = tcp_close(otp); 1039 else 1040 return (EADDRINUSE); 1041 } 1042 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 1043 inp->in6p_laddr = *addr6; 1044 inp->in6p_faddr = sin6->sin6_addr; 1045 inp->inp_fport = sin6->sin6_port; 1046 if ((sin6->sin6_flowinfo & IPV6_FLOWINFO_MASK) != NULL) 1047 inp->in6p_flowinfo = sin6->sin6_flowinfo; 1048 in_pcbinsconnhash(inp); 1049 1050 /* Compute window scaling to request. */ 1051 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 1052 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.ssb_hiwat) 1053 tp->request_r_scale++; 1054 1055 soisconnecting(so); 1056 tcpstat.tcps_connattempt++; 1057 tp->t_state = TCPS_SYN_SENT; 1058 callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); 1059 tp->iss = tcp_new_isn(tp); 1060 tcp_sendseqinit(tp); 1061 1062 /* 1063 * Generate a CC value for this connection and 1064 * check whether CC or CCnew should be used. 1065 */ 1066 if ((taop = tcp_gettaocache(&tp->t_inpcb->inp_inc)) == NULL) { 1067 taop = &tao_noncached; 1068 bzero(taop, sizeof *taop); 1069 } 1070 1071 tp->cc_send = CC_INC(tcp_ccgen); 1072 if (taop->tao_ccsent != 0 && 1073 CC_GEQ(tp->cc_send, taop->tao_ccsent)) { 1074 taop->tao_ccsent = tp->cc_send; 1075 } else { 1076 taop->tao_ccsent = 0; 1077 tp->t_flags |= TF_SENDCCNEW; 1078 } 1079 1080 return (0); 1081 } 1082 #endif /* INET6 */ 1083 1084 /* 1085 * The new sockopt interface makes it possible for us to block in the 1086 * copyin/out step (if we take a page fault). Taking a page fault while 1087 * in a critical section is probably a Bad Thing. (Since sockets and pcbs 1088 * both now use TSM, there probably isn't any need for this function to 1089 * run in a critical section any more. This needs more examination.) 1090 */ 1091 int 1092 tcp_ctloutput(struct socket *so, struct sockopt *sopt) 1093 { 1094 int error, opt, optval; 1095 struct inpcb *inp; 1096 struct tcpcb *tp; 1097 1098 error = 0; 1099 crit_enter(); /* XXX */ 1100 inp = so->so_pcb; 1101 if (inp == NULL) { 1102 crit_exit(); 1103 return (ECONNRESET); 1104 } 1105 if (sopt->sopt_level != IPPROTO_TCP) { 1106 #ifdef INET6 1107 if (INP_CHECK_SOCKAF(so, AF_INET6)) 1108 error = ip6_ctloutput(so, sopt); 1109 else 1110 #endif /* INET6 */ 1111 error = ip_ctloutput(so, sopt); 1112 crit_exit(); 1113 return (error); 1114 } 1115 tp = intotcpcb(inp); 1116 1117 switch (sopt->sopt_dir) { 1118 case SOPT_SET: 1119 switch (sopt->sopt_name) { 1120 case TCP_NODELAY: 1121 case TCP_NOOPT: 1122 error = sooptcopyin(sopt, &optval, sizeof optval, 1123 sizeof optval); 1124 if (error) 1125 break; 1126 1127 switch (sopt->sopt_name) { 1128 case TCP_NODELAY: 1129 opt = TF_NODELAY; 1130 break; 1131 case TCP_NOOPT: 1132 opt = TF_NOOPT; 1133 break; 1134 default: 1135 opt = 0; /* dead code to fool gcc */ 1136 break; 1137 } 1138 1139 if (optval) 1140 tp->t_flags |= opt; 1141 else 1142 tp->t_flags &= ~opt; 1143 break; 1144 1145 case TCP_NOPUSH: 1146 error = sooptcopyin(sopt, &optval, sizeof optval, 1147 sizeof optval); 1148 if (error) 1149 break; 1150 1151 if (optval) 1152 tp->t_flags |= TF_NOPUSH; 1153 else { 1154 tp->t_flags &= ~TF_NOPUSH; 1155 error = tcp_output(tp); 1156 } 1157 break; 1158 1159 case TCP_MAXSEG: 1160 error = sooptcopyin(sopt, &optval, sizeof optval, 1161 sizeof optval); 1162 if (error) 1163 break; 1164 1165 if (optval > 0 && optval <= tp->t_maxseg) 1166 tp->t_maxseg = optval; 1167 else 1168 error = EINVAL; 1169 break; 1170 1171 default: 1172 error = ENOPROTOOPT; 1173 break; 1174 } 1175 break; 1176 1177 case SOPT_GET: 1178 switch (sopt->sopt_name) { 1179 case TCP_NODELAY: 1180 optval = tp->t_flags & TF_NODELAY; 1181 break; 1182 case TCP_MAXSEG: 1183 optval = tp->t_maxseg; 1184 break; 1185 case TCP_NOOPT: 1186 optval = tp->t_flags & TF_NOOPT; 1187 break; 1188 case TCP_NOPUSH: 1189 optval = tp->t_flags & TF_NOPUSH; 1190 break; 1191 default: 1192 error = ENOPROTOOPT; 1193 break; 1194 } 1195 if (error == 0) 1196 error = sooptcopyout(sopt, &optval, sizeof optval); 1197 break; 1198 } 1199 crit_exit(); 1200 return (error); 1201 } 1202 1203 /* 1204 * tcp_sendspace and tcp_recvspace are the default send and receive window 1205 * sizes, respectively. These are obsolescent (this information should 1206 * be set by the route). 1207 */ 1208 u_long tcp_sendspace = 1024*32; 1209 SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, CTLFLAG_RW, 1210 &tcp_sendspace , 0, "Maximum outgoing TCP datagram size"); 1211 u_long tcp_recvspace = 57344; /* largest multiple of PAGE_SIZE < 64k */ 1212 SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_RW, 1213 &tcp_recvspace , 0, "Maximum incoming TCP datagram size"); 1214 1215 /* 1216 * Attach TCP protocol to socket, allocating 1217 * internet protocol control block, tcp control block, 1218 * bufer space, and entering LISTEN state if to accept connections. 1219 */ 1220 static int 1221 tcp_attach(struct socket *so, struct pru_attach_info *ai) 1222 { 1223 struct tcpcb *tp; 1224 struct inpcb *inp; 1225 int error; 1226 int cpu; 1227 #ifdef INET6 1228 int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != NULL; 1229 #endif 1230 1231 if (so->so_snd.ssb_hiwat == 0 || so->so_rcv.ssb_hiwat == 0) { 1232 error = soreserve(so, tcp_sendspace, tcp_recvspace, 1233 ai->sb_rlimit); 1234 if (error) 1235 return (error); 1236 } 1237 cpu = mycpu->gd_cpuid; 1238 error = in_pcballoc(so, &tcbinfo[cpu]); 1239 if (error) 1240 return (error); 1241 inp = so->so_pcb; 1242 #ifdef INET6 1243 if (isipv6) { 1244 inp->inp_vflag |= INP_IPV6; 1245 inp->in6p_hops = -1; /* use kernel default */ 1246 } 1247 else 1248 #endif 1249 inp->inp_vflag |= INP_IPV4; 1250 tp = tcp_newtcpcb(inp); 1251 if (tp == 0) { 1252 int nofd = so->so_state & SS_NOFDREF; /* XXX */ 1253 1254 so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 1255 #ifdef INET6 1256 if (isipv6) 1257 in6_pcbdetach(inp); 1258 else 1259 #endif 1260 in_pcbdetach(inp); 1261 so->so_state |= nofd; 1262 return (ENOBUFS); 1263 } 1264 tp->t_state = TCPS_CLOSED; 1265 return (0); 1266 } 1267 1268 /* 1269 * Initiate (or continue) disconnect. 1270 * If embryonic state, just send reset (once). 1271 * If in ``let data drain'' option and linger null, just drop. 1272 * Otherwise (hard), mark socket disconnecting and drop 1273 * current input data; switch states based on user close, and 1274 * send segment to peer (with FIN). 1275 */ 1276 static struct tcpcb * 1277 tcp_disconnect(struct tcpcb *tp) 1278 { 1279 struct socket *so = tp->t_inpcb->inp_socket; 1280 1281 if (tp->t_state < TCPS_ESTABLISHED) 1282 tp = tcp_close(tp); 1283 else if ((so->so_options & SO_LINGER) && so->so_linger == 0) 1284 tp = tcp_drop(tp, 0); 1285 else { 1286 soisdisconnecting(so); 1287 sbflush(&so->so_rcv.sb); 1288 tp = tcp_usrclosed(tp); 1289 if (tp) 1290 tcp_output(tp); 1291 } 1292 return (tp); 1293 } 1294 1295 /* 1296 * User issued close, and wish to trail through shutdown states: 1297 * if never received SYN, just forget it. If got a SYN from peer, 1298 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 1299 * If already got a FIN from peer, then almost done; go to LAST_ACK 1300 * state. In all other cases, have already sent FIN to peer (e.g. 1301 * after PRU_SHUTDOWN), and just have to play tedious game waiting 1302 * for peer to send FIN or not respond to keep-alives, etc. 1303 * We can let the user exit from the close as soon as the FIN is acked. 1304 */ 1305 static struct tcpcb * 1306 tcp_usrclosed(struct tcpcb *tp) 1307 { 1308 1309 switch (tp->t_state) { 1310 1311 case TCPS_CLOSED: 1312 case TCPS_LISTEN: 1313 tp->t_state = TCPS_CLOSED; 1314 tp = tcp_close(tp); 1315 break; 1316 1317 case TCPS_SYN_SENT: 1318 case TCPS_SYN_RECEIVED: 1319 tp->t_flags |= TF_NEEDFIN; 1320 break; 1321 1322 case TCPS_ESTABLISHED: 1323 tp->t_state = TCPS_FIN_WAIT_1; 1324 break; 1325 1326 case TCPS_CLOSE_WAIT: 1327 tp->t_state = TCPS_LAST_ACK; 1328 break; 1329 } 1330 if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { 1331 soisdisconnected(tp->t_inpcb->inp_socket); 1332 /* To prevent the connection hanging in FIN_WAIT_2 forever. */ 1333 if (tp->t_state == TCPS_FIN_WAIT_2) 1334 callout_reset(tp->tt_2msl, tcp_maxidle, 1335 tcp_timer_2msl, tp); 1336 } 1337 return (tp); 1338 } 1339