1 /* $NetBSD: tcp_usrreq.c,v 1.86 2003/12/04 19:38:24 atatat Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /*- 33 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to The NetBSD Foundation 37 * by Jason R. Thorpe and Kevin M. Lahey of the Numerical Aerospace Simulation 38 * Facility, NASA Ames Research Center. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. All advertising materials mentioning features or use of this software 49 * must display the following acknowledgement: 50 * This product includes software developed by the NetBSD 51 * Foundation, Inc. and its contributors. 52 * 4. Neither the name of The NetBSD Foundation nor the names of its 53 * contributors may be used to endorse or promote products derived 54 * from this software without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 57 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 58 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 60 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 61 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 62 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 64 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 65 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 66 * POSSIBILITY OF SUCH DAMAGE. 67 */ 68 69 /* 70 * Copyright (c) 1982, 1986, 1988, 1993, 1995 71 * The Regents of the University of California. All rights reserved. 72 * 73 * Redistribution and use in source and binary forms, with or without 74 * modification, are permitted provided that the following conditions 75 * are met: 76 * 1. Redistributions of source code must retain the above copyright 77 * notice, this list of conditions and the following disclaimer. 78 * 2. Redistributions in binary form must reproduce the above copyright 79 * notice, this list of conditions and the following disclaimer in the 80 * documentation and/or other materials provided with the distribution. 81 * 3. Neither the name of the University nor the names of its contributors 82 * may be used to endorse or promote products derived from this software 83 * without specific prior written permission. 84 * 85 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 86 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 88 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 89 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 91 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 92 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 93 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 94 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 95 * SUCH DAMAGE. 96 * 97 * @(#)tcp_usrreq.c 8.5 (Berkeley) 6/21/95 98 */ 99 100 #include <sys/cdefs.h> 101 __KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.86 2003/12/04 19:38:24 atatat Exp $"); 102 103 #include "opt_inet.h" 104 #include "opt_ipsec.h" 105 #include "opt_tcp_debug.h" 106 #include "opt_mbuftrace.h" 107 108 #include <sys/param.h> 109 #include <sys/systm.h> 110 #include <sys/kernel.h> 111 #include <sys/malloc.h> 112 #include <sys/mbuf.h> 113 #include <sys/socket.h> 114 #include <sys/socketvar.h> 115 #include <sys/protosw.h> 116 #include <sys/errno.h> 117 #include <sys/stat.h> 118 #include <sys/proc.h> 119 #include <sys/domain.h> 120 #include <sys/sysctl.h> 121 122 #include <net/if.h> 123 #include <net/route.h> 124 125 #include <netinet/in.h> 126 #include <netinet/in_systm.h> 127 #include <netinet/in_var.h> 128 #include <netinet/ip.h> 129 #include <netinet/in_pcb.h> 130 #include <netinet/ip_var.h> 131 132 #ifdef INET6 133 #ifndef INET 134 #include <netinet/in.h> 135 #endif 136 #include <netinet/ip6.h> 137 #include <netinet6/in6_pcb.h> 138 #include <netinet6/ip6_var.h> 139 #endif 140 141 #include <netinet/tcp.h> 142 #include <netinet/tcp_fsm.h> 143 #include <netinet/tcp_seq.h> 144 #include <netinet/tcp_timer.h> 145 #include <netinet/tcp_var.h> 146 #include <netinet/tcpip.h> 147 #include <netinet/tcp_debug.h> 148 149 #include "opt_tcp_space.h" 150 151 #ifdef IPSEC 152 #include <netinet6/ipsec.h> 153 #endif /*IPSEC*/ 154 155 /* 156 * TCP protocol interface to socket abstraction. 157 */ 158 extern char *tcpstates[]; 159 160 /* 161 * Process a TCP user request for TCP tb. If this is a send request 162 * then m is the mbuf chain of send data. If this is a timer expiration 163 * (called from the software clock routine), then timertype tells which timer. 164 */ 165 /*ARGSUSED*/ 166 int 167 tcp_usrreq(so, req, m, nam, control, p) 168 struct socket *so; 169 int req; 170 struct mbuf *m, *nam, *control; 171 struct proc *p; 172 { 173 struct inpcb *inp; 174 #ifdef INET6 175 struct in6pcb *in6p; 176 #endif 177 struct tcpcb *tp = NULL; 178 int s; 179 int error = 0; 180 #ifdef TCP_DEBUG 181 int ostate = 0; 182 #endif 183 int family; /* family of the socket */ 184 185 family = so->so_proto->pr_domain->dom_family; 186 187 if (req == PRU_CONTROL) { 188 switch (family) { 189 #ifdef INET 190 case PF_INET: 191 return (in_control(so, (long)m, (caddr_t)nam, 192 (struct ifnet *)control, p)); 193 #endif 194 #ifdef INET6 195 case PF_INET6: 196 return (in6_control(so, (long)m, (caddr_t)nam, 197 (struct ifnet *)control, p)); 198 #endif 199 default: 200 return EAFNOSUPPORT; 201 } 202 } 203 204 if (req == PRU_PURGEIF) { 205 switch (family) { 206 #ifdef INET 207 case PF_INET: 208 in_pcbpurgeif0(&tcbtable, (struct ifnet *)control); 209 in_purgeif((struct ifnet *)control); 210 in_pcbpurgeif(&tcbtable, (struct ifnet *)control); 211 break; 212 #endif 213 #ifdef INET6 214 case PF_INET6: 215 in6_pcbpurgeif0(&tcbtable, (struct ifnet *)control); 216 in6_purgeif((struct ifnet *)control); 217 in6_pcbpurgeif(&tcbtable, (struct ifnet *)control); 218 break; 219 #endif 220 default: 221 return (EAFNOSUPPORT); 222 } 223 return (0); 224 } 225 226 s = splsoftnet(); 227 switch (family) { 228 #ifdef INET 229 case PF_INET: 230 inp = sotoinpcb(so); 231 #ifdef INET6 232 in6p = NULL; 233 #endif 234 break; 235 #endif 236 #ifdef INET6 237 case PF_INET6: 238 inp = NULL; 239 in6p = sotoin6pcb(so); 240 break; 241 #endif 242 default: 243 splx(s); 244 return EAFNOSUPPORT; 245 } 246 247 #ifdef DIAGNOSTIC 248 #ifdef INET6 249 if (inp && in6p) 250 panic("tcp_usrreq: both inp and in6p set to non-NULL"); 251 #endif 252 if (req != PRU_SEND && req != PRU_SENDOOB && control) 253 panic("tcp_usrreq: unexpected control mbuf"); 254 #endif 255 /* 256 * When a TCP is attached to a socket, then there will be 257 * a (struct inpcb) pointed at by the socket, and this 258 * structure will point at a subsidary (struct tcpcb). 259 */ 260 #ifndef INET6 261 if (inp == 0 && req != PRU_ATTACH) 262 #else 263 if ((inp == 0 && in6p == 0) && req != PRU_ATTACH) 264 #endif 265 { 266 error = EINVAL; 267 goto release; 268 } 269 #ifdef INET 270 if (inp) { 271 tp = intotcpcb(inp); 272 /* WHAT IF TP IS 0? */ 273 #ifdef KPROF 274 tcp_acounts[tp->t_state][req]++; 275 #endif 276 #ifdef TCP_DEBUG 277 ostate = tp->t_state; 278 #endif 279 } 280 #endif 281 #ifdef INET6 282 if (in6p) { 283 tp = in6totcpcb(in6p); 284 /* WHAT IF TP IS 0? */ 285 #ifdef KPROF 286 tcp_acounts[tp->t_state][req]++; 287 #endif 288 #ifdef TCP_DEBUG 289 ostate = tp->t_state; 290 #endif 291 } 292 #endif 293 294 switch (req) { 295 296 /* 297 * TCP attaches to socket via PRU_ATTACH, reserving space, 298 * and an internet control block. 299 */ 300 case PRU_ATTACH: 301 #ifndef INET6 302 if (inp != 0) 303 #else 304 if (inp != 0 || in6p != 0) 305 #endif 306 { 307 error = EISCONN; 308 break; 309 } 310 error = tcp_attach(so); 311 if (error) 312 break; 313 if ((so->so_options & SO_LINGER) && so->so_linger == 0) 314 so->so_linger = TCP_LINGERTIME; 315 tp = sototcpcb(so); 316 break; 317 318 /* 319 * PRU_DETACH detaches the TCP protocol from the socket. 320 */ 321 case PRU_DETACH: 322 tp = tcp_disconnect(tp); 323 break; 324 325 /* 326 * Give the socket an address. 327 */ 328 case PRU_BIND: 329 switch (family) { 330 #ifdef INET 331 case PF_INET: 332 error = in_pcbbind(inp, nam, p); 333 break; 334 #endif 335 #ifdef INET6 336 case PF_INET6: 337 error = in6_pcbbind(in6p, nam, p); 338 if (!error) { 339 /* mapped addr case */ 340 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) 341 tp->t_family = AF_INET; 342 else 343 tp->t_family = AF_INET6; 344 } 345 break; 346 #endif 347 } 348 break; 349 350 /* 351 * Prepare to accept connections. 352 */ 353 case PRU_LISTEN: 354 #ifdef INET 355 if (inp && inp->inp_lport == 0) { 356 error = in_pcbbind(inp, (struct mbuf *)0, 357 (struct proc *)0); 358 if (error) 359 break; 360 } 361 #endif 362 #ifdef INET6 363 if (in6p && in6p->in6p_lport == 0) { 364 error = in6_pcbbind(in6p, (struct mbuf *)0, 365 (struct proc *)0); 366 if (error) 367 break; 368 } 369 #endif 370 tp->t_state = TCPS_LISTEN; 371 break; 372 373 /* 374 * Initiate connection to peer. 375 * Create a template for use in transmissions on this connection. 376 * Enter SYN_SENT state, and mark socket as connecting. 377 * Start keep-alive timer, and seed output sequence space. 378 * Send initial segment on connection. 379 */ 380 case PRU_CONNECT: 381 #ifdef INET 382 if (inp) { 383 if (inp->inp_lport == 0) { 384 error = in_pcbbind(inp, (struct mbuf *)0, 385 (struct proc *)0); 386 if (error) 387 break; 388 } 389 error = in_pcbconnect(inp, nam); 390 } 391 #endif 392 #ifdef INET6 393 if (in6p) { 394 if (in6p->in6p_lport == 0) { 395 error = in6_pcbbind(in6p, (struct mbuf *)0, 396 (struct proc *)0); 397 if (error) 398 break; 399 } 400 error = in6_pcbconnect(in6p, nam); 401 if (!error) { 402 /* mapped addr case */ 403 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) 404 tp->t_family = AF_INET; 405 else 406 tp->t_family = AF_INET6; 407 } 408 } 409 #endif 410 if (error) 411 break; 412 tp->t_template = tcp_template(tp); 413 if (tp->t_template == 0) { 414 #ifdef INET 415 if (inp) 416 in_pcbdisconnect(inp); 417 #endif 418 #ifdef INET6 419 if (in6p) 420 in6_pcbdisconnect(in6p); 421 #endif 422 error = ENOBUFS; 423 break; 424 } 425 /* Compute window scaling to request. */ 426 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 427 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) 428 tp->request_r_scale++; 429 soisconnecting(so); 430 tcpstat.tcps_connattempt++; 431 tp->t_state = TCPS_SYN_SENT; 432 TCP_TIMER_ARM(tp, TCPT_KEEP, TCPTV_KEEP_INIT); 433 tp->iss = tcp_new_iss(tp, 0); 434 tcp_sendseqinit(tp); 435 error = tcp_output(tp); 436 break; 437 438 /* 439 * Create a TCP connection between two sockets. 440 */ 441 case PRU_CONNECT2: 442 error = EOPNOTSUPP; 443 break; 444 445 /* 446 * Initiate disconnect from peer. 447 * If connection never passed embryonic stage, just drop; 448 * else if don't need to let data drain, then can just drop anyways, 449 * else have to begin TCP shutdown process: mark socket disconnecting, 450 * drain unread data, state switch to reflect user close, and 451 * send segment (e.g. FIN) to peer. Socket will be really disconnected 452 * when peer sends FIN and acks ours. 453 * 454 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 455 */ 456 case PRU_DISCONNECT: 457 tp = tcp_disconnect(tp); 458 break; 459 460 /* 461 * Accept a connection. Essentially all the work is 462 * done at higher levels; just return the address 463 * of the peer, storing through addr. 464 */ 465 case PRU_ACCEPT: 466 #ifdef INET 467 if (inp) 468 in_setpeeraddr(inp, nam); 469 #endif 470 #ifdef INET6 471 if (in6p) 472 in6_setpeeraddr(in6p, nam); 473 #endif 474 break; 475 476 /* 477 * Mark the connection as being incapable of further output. 478 */ 479 case PRU_SHUTDOWN: 480 socantsendmore(so); 481 tp = tcp_usrclosed(tp); 482 if (tp) 483 error = tcp_output(tp); 484 break; 485 486 /* 487 * After a receive, possibly send window update to peer. 488 */ 489 case PRU_RCVD: 490 /* 491 * soreceive() calls this function when a user receives 492 * ancillary data on a listening socket. We don't call 493 * tcp_output in such a case, since there is no header 494 * template for a listening socket and hence the kernel 495 * will panic. 496 */ 497 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) != 0) 498 (void) tcp_output(tp); 499 break; 500 501 /* 502 * Do a send by putting data in output queue and updating urgent 503 * marker if URG set. Possibly send more data. 504 */ 505 case PRU_SEND: 506 if (control && control->m_len) { 507 m_freem(control); 508 m_freem(m); 509 error = EINVAL; 510 break; 511 } 512 sbappendstream(&so->so_snd, m); 513 error = tcp_output(tp); 514 break; 515 516 /* 517 * Abort the TCP. 518 */ 519 case PRU_ABORT: 520 tp = tcp_drop(tp, ECONNABORTED); 521 break; 522 523 case PRU_SENSE: 524 /* 525 * stat: don't bother with a blocksize. 526 */ 527 splx(s); 528 return (0); 529 530 case PRU_RCVOOB: 531 if (control && control->m_len) { 532 m_freem(control); 533 m_freem(m); 534 error = EINVAL; 535 break; 536 } 537 if ((so->so_oobmark == 0 && 538 (so->so_state & SS_RCVATMARK) == 0) || 539 so->so_options & SO_OOBINLINE || 540 tp->t_oobflags & TCPOOB_HADDATA) { 541 error = EINVAL; 542 break; 543 } 544 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 545 error = EWOULDBLOCK; 546 break; 547 } 548 m->m_len = 1; 549 *mtod(m, caddr_t) = tp->t_iobc; 550 if (((long)nam & MSG_PEEK) == 0) 551 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 552 break; 553 554 case PRU_SENDOOB: 555 if (sbspace(&so->so_snd) < -512) { 556 m_freem(m); 557 error = ENOBUFS; 558 break; 559 } 560 /* 561 * According to RFC961 (Assigned Protocols), 562 * the urgent pointer points to the last octet 563 * of urgent data. We continue, however, 564 * to consider it to indicate the first octet 565 * of data past the urgent section. 566 * Otherwise, snd_up should be one lower. 567 */ 568 sbappendstream(&so->so_snd, m); 569 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 570 tp->t_force = 1; 571 error = tcp_output(tp); 572 tp->t_force = 0; 573 break; 574 575 case PRU_SOCKADDR: 576 #ifdef INET 577 if (inp) 578 in_setsockaddr(inp, nam); 579 #endif 580 #ifdef INET6 581 if (in6p) 582 in6_setsockaddr(in6p, nam); 583 #endif 584 break; 585 586 case PRU_PEERADDR: 587 #ifdef INET 588 if (inp) 589 in_setpeeraddr(inp, nam); 590 #endif 591 #ifdef INET6 592 if (in6p) 593 in6_setpeeraddr(in6p, nam); 594 #endif 595 break; 596 597 default: 598 panic("tcp_usrreq"); 599 } 600 #ifdef TCP_DEBUG 601 if (tp && (so->so_options & SO_DEBUG)) 602 tcp_trace(TA_USER, ostate, tp, NULL, req); 603 #endif 604 605 release: 606 splx(s); 607 return (error); 608 } 609 610 int 611 tcp_ctloutput(op, so, level, optname, mp) 612 int op; 613 struct socket *so; 614 int level, optname; 615 struct mbuf **mp; 616 { 617 int error = 0, s; 618 struct inpcb *inp; 619 #ifdef INET6 620 struct in6pcb *in6p; 621 #endif 622 struct tcpcb *tp; 623 struct mbuf *m; 624 int i; 625 int family; /* family of the socket */ 626 627 family = so->so_proto->pr_domain->dom_family; 628 629 s = splsoftnet(); 630 switch (family) { 631 #ifdef INET 632 case PF_INET: 633 inp = sotoinpcb(so); 634 #ifdef INET6 635 in6p = NULL; 636 #endif 637 break; 638 #endif 639 #ifdef INET6 640 case PF_INET6: 641 inp = NULL; 642 in6p = sotoin6pcb(so); 643 break; 644 #endif 645 default: 646 splx(s); 647 return EAFNOSUPPORT; 648 } 649 #ifndef INET6 650 if (inp == NULL) 651 #else 652 if (inp == NULL && in6p == NULL) 653 #endif 654 { 655 splx(s); 656 if (op == PRCO_SETOPT && *mp) 657 (void) m_free(*mp); 658 return (ECONNRESET); 659 } 660 if (level != IPPROTO_TCP) { 661 switch (family) { 662 #ifdef INET 663 case PF_INET: 664 error = ip_ctloutput(op, so, level, optname, mp); 665 break; 666 #endif 667 #ifdef INET6 668 case PF_INET6: 669 error = ip6_ctloutput(op, so, level, optname, mp); 670 break; 671 #endif 672 } 673 splx(s); 674 return (error); 675 } 676 if (inp) 677 tp = intotcpcb(inp); 678 #ifdef INET6 679 else if (in6p) 680 tp = in6totcpcb(in6p); 681 #endif 682 else 683 tp = NULL; 684 685 switch (op) { 686 687 case PRCO_SETOPT: 688 m = *mp; 689 switch (optname) { 690 691 case TCP_NODELAY: 692 if (m == NULL || m->m_len < sizeof (int)) 693 error = EINVAL; 694 else if (*mtod(m, int *)) 695 tp->t_flags |= TF_NODELAY; 696 else 697 tp->t_flags &= ~TF_NODELAY; 698 break; 699 700 case TCP_MAXSEG: 701 if (m && (i = *mtod(m, int *)) > 0 && 702 i <= tp->t_peermss) 703 tp->t_peermss = i; /* limit on send size */ 704 else 705 error = EINVAL; 706 break; 707 708 default: 709 error = ENOPROTOOPT; 710 break; 711 } 712 if (m) 713 (void) m_free(m); 714 break; 715 716 case PRCO_GETOPT: 717 *mp = m = m_get(M_WAIT, MT_SOOPTS); 718 m->m_len = sizeof(int); 719 MCLAIM(m, so->so_mowner); 720 721 switch (optname) { 722 case TCP_NODELAY: 723 *mtod(m, int *) = tp->t_flags & TF_NODELAY; 724 break; 725 case TCP_MAXSEG: 726 *mtod(m, int *) = tp->t_peermss; 727 break; 728 default: 729 error = ENOPROTOOPT; 730 break; 731 } 732 break; 733 } 734 splx(s); 735 return (error); 736 } 737 738 #ifndef TCP_SENDSPACE 739 #define TCP_SENDSPACE 1024*32 740 #endif 741 int tcp_sendspace = TCP_SENDSPACE; 742 #ifndef TCP_RECVSPACE 743 #define TCP_RECVSPACE 1024*32 744 #endif 745 int tcp_recvspace = TCP_RECVSPACE; 746 747 /* 748 * Attach TCP protocol to socket, allocating 749 * internet protocol control block, tcp control block, 750 * bufer space, and entering LISTEN state if to accept connections. 751 */ 752 int 753 tcp_attach(so) 754 struct socket *so; 755 { 756 struct tcpcb *tp; 757 struct inpcb *inp; 758 #ifdef INET6 759 struct in6pcb *in6p; 760 #endif 761 int error; 762 int family; /* family of the socket */ 763 764 family = so->so_proto->pr_domain->dom_family; 765 766 #ifdef MBUFTRACE 767 so->so_mowner = &tcp_mowner; 768 so->so_rcv.sb_mowner = &tcp_rx_mowner; 769 so->so_snd.sb_mowner = &tcp_tx_mowner; 770 #endif 771 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 772 error = soreserve(so, tcp_sendspace, tcp_recvspace); 773 if (error) 774 return (error); 775 } 776 switch (family) { 777 #ifdef INET 778 case PF_INET: 779 error = in_pcballoc(so, &tcbtable); 780 if (error) 781 return (error); 782 inp = sotoinpcb(so); 783 #ifdef INET6 784 in6p = NULL; 785 #endif 786 break; 787 #endif 788 #ifdef INET6 789 case PF_INET6: 790 error = in6_pcballoc(so, &tcbtable); 791 if (error) 792 return (error); 793 inp = NULL; 794 in6p = sotoin6pcb(so); 795 break; 796 #endif 797 default: 798 return EAFNOSUPPORT; 799 } 800 if (inp) 801 tp = tcp_newtcpcb(family, (void *)inp); 802 #ifdef INET6 803 else if (in6p) 804 tp = tcp_newtcpcb(family, (void *)in6p); 805 #endif 806 else 807 tp = NULL; 808 809 if (tp == 0) { 810 int nofd = so->so_state & SS_NOFDREF; /* XXX */ 811 812 so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */ 813 #ifdef INET 814 if (inp) 815 in_pcbdetach(inp); 816 #endif 817 #ifdef INET6 818 if (in6p) 819 in6_pcbdetach(in6p); 820 #endif 821 so->so_state |= nofd; 822 return (ENOBUFS); 823 } 824 tp->t_state = TCPS_CLOSED; 825 return (0); 826 } 827 828 /* 829 * Initiate (or continue) disconnect. 830 * If embryonic state, just send reset (once). 831 * If in ``let data drain'' option and linger null, just drop. 832 * Otherwise (hard), mark socket disconnecting and drop 833 * current input data; switch states based on user close, and 834 * send segment to peer (with FIN). 835 */ 836 struct tcpcb * 837 tcp_disconnect(tp) 838 struct tcpcb *tp; 839 { 840 struct socket *so; 841 842 if (tp->t_inpcb) 843 so = tp->t_inpcb->inp_socket; 844 #ifdef INET6 845 else if (tp->t_in6pcb) 846 so = tp->t_in6pcb->in6p_socket; 847 #endif 848 else 849 so = NULL; 850 851 if (TCPS_HAVEESTABLISHED(tp->t_state) == 0) 852 tp = tcp_close(tp); 853 else if ((so->so_options & SO_LINGER) && so->so_linger == 0) 854 tp = tcp_drop(tp, 0); 855 else { 856 soisdisconnecting(so); 857 sbflush(&so->so_rcv); 858 tp = tcp_usrclosed(tp); 859 if (tp) 860 (void) tcp_output(tp); 861 } 862 return (tp); 863 } 864 865 /* 866 * User issued close, and wish to trail through shutdown states: 867 * if never received SYN, just forget it. If got a SYN from peer, 868 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 869 * If already got a FIN from peer, then almost done; go to LAST_ACK 870 * state. In all other cases, have already sent FIN to peer (e.g. 871 * after PRU_SHUTDOWN), and just have to play tedious game waiting 872 * for peer to send FIN or not respond to keep-alives, etc. 873 * We can let the user exit from the close as soon as the FIN is acked. 874 */ 875 struct tcpcb * 876 tcp_usrclosed(tp) 877 struct tcpcb *tp; 878 { 879 880 switch (tp->t_state) { 881 882 case TCPS_CLOSED: 883 case TCPS_LISTEN: 884 case TCPS_SYN_SENT: 885 tp->t_state = TCPS_CLOSED; 886 tp = tcp_close(tp); 887 break; 888 889 case TCPS_SYN_RECEIVED: 890 case TCPS_ESTABLISHED: 891 tp->t_state = TCPS_FIN_WAIT_1; 892 break; 893 894 case TCPS_CLOSE_WAIT: 895 tp->t_state = TCPS_LAST_ACK; 896 break; 897 } 898 if (tp && tp->t_state >= TCPS_FIN_WAIT_2) { 899 struct socket *so; 900 if (tp->t_inpcb) 901 so = tp->t_inpcb->inp_socket; 902 #ifdef INET6 903 else if (tp->t_in6pcb) 904 so = tp->t_in6pcb->in6p_socket; 905 #endif 906 else 907 so = NULL; 908 soisdisconnected(so); 909 /* 910 * If we are in FIN_WAIT_2, we arrived here because the 911 * application did a shutdown of the send side. Like the 912 * case of a transition from FIN_WAIT_1 to FIN_WAIT_2 after 913 * a full close, we start a timer to make sure sockets are 914 * not left in FIN_WAIT_2 forever. 915 */ 916 if ((tp->t_state == TCPS_FIN_WAIT_2) && (tcp_maxidle > 0)) 917 TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_maxidle); 918 } 919 return (tp); 920 } 921 922 /* 923 * sysctl helper routine for net.inet.ip.mssdflt. it can't be less 924 * than 32. 925 */ 926 static int 927 sysctl_net_inet_tcp_mssdflt(SYSCTLFN_ARGS) 928 { 929 int error, mssdflt; 930 struct sysctlnode node; 931 932 mssdflt = tcp_mssdflt; 933 node = *rnode; 934 node.sysctl_data = &mssdflt; 935 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 936 if (error || newp == NULL) 937 return (error); 938 939 if (mssdflt < 32) 940 return (EINVAL); 941 tcp_mssdflt = mssdflt; 942 943 return (0); 944 } 945 946 /* 947 * sysctl helper routine for setting port related values under 948 * net.inet.ip and net.inet6.ip6. does basic range checking and does 949 * additional checks for each type. this code has placed in 950 * tcp_input.c since INET and INET6 both use the same tcp code. 951 * 952 * this helper is not static so that both inet and inet6 can use it. 953 */ 954 int 955 sysctl_net_inet_ip_ports(SYSCTLFN_ARGS) 956 { 957 int error, tmp; 958 int apmin, apmax; 959 #ifndef IPNOPRIVPORTS 960 int lpmin, lpmax; 961 #endif /* IPNOPRIVPORTS */ 962 struct sysctlnode node; 963 964 if (namelen != 0) 965 return (EINVAL); 966 967 switch (name[-3]) { 968 #ifdef INET 969 case PF_INET: 970 apmin = anonportmin; 971 apmax = anonportmax; 972 #ifndef IPNOPRIVPORTS 973 lpmin = lowportmin; 974 lpmax = lowportmax; 975 #endif /* IPNOPRIVPORTS */ 976 break; 977 #endif /* INET */ 978 #ifdef INET6 979 case PF_INET6: 980 apmin = ip6_anonportmin; 981 apmax = ip6_anonportmax; 982 #ifndef IPNOPRIVPORTS 983 lpmin = ip6_lowportmin; 984 lpmax = ip6_lowportmax; 985 #endif /* IPNOPRIVPORTS */ 986 break; 987 #endif /* INET6 */ 988 default: 989 return (EINVAL); 990 } 991 992 /* 993 * insert temporary copy into node, perform lookup on 994 * temporary, then restore pointer 995 */ 996 node = *rnode; 997 tmp = *(int*)rnode->sysctl_data; 998 node.sysctl_data = &tmp; 999 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1000 if (error || newp == NULL) 1001 return (error); 1002 1003 /* 1004 * simple port range check 1005 */ 1006 if (tmp < 0 || tmp > 65535) 1007 return (EINVAL); 1008 1009 /* 1010 * per-node range checks 1011 */ 1012 switch (rnode->sysctl_num) { 1013 case IPCTL_ANONPORTMIN: 1014 if (tmp >= apmax) 1015 return (EINVAL); 1016 #ifndef IPNOPRIVPORTS 1017 if (tmp < IPPORT_RESERVED) 1018 return (EINVAL); 1019 #endif /* IPNOPRIVPORTS */ 1020 break; 1021 1022 case IPCTL_ANONPORTMAX: 1023 if (apmin >= tmp) 1024 return (EINVAL); 1025 #ifndef IPNOPRIVPORTS 1026 if (tmp < IPPORT_RESERVED) 1027 return (EINVAL); 1028 #endif /* IPNOPRIVPORTS */ 1029 break; 1030 1031 #ifndef IPNOPRIVPORTS 1032 case IPCTL_LOWPORTMIN: 1033 if (tmp >= lpmax || 1034 tmp > IPPORT_RESERVEDMAX || 1035 tmp < IPPORT_RESERVEDMIN) 1036 return (EINVAL); 1037 break; 1038 1039 case IPCTL_LOWPORTMAX: 1040 if (lpmin >= tmp || 1041 tmp > IPPORT_RESERVEDMAX || 1042 tmp < IPPORT_RESERVEDMIN) 1043 return (EINVAL); 1044 break; 1045 #endif /* IPNOPRIVPORTS */ 1046 1047 default: 1048 return (EINVAL); 1049 } 1050 1051 *(int*)rnode->sysctl_data = tmp; 1052 1053 return (0); 1054 } 1055 1056 /* 1057 * sysctl helper routine for the net.inet.tcp.ident and 1058 * net.inet6.tcp6.ident nodes. contains backwards compat code for the 1059 * old way of looking up the ident information for ipv4 which involves 1060 * stuffing the port/addr pairs into the mib lookup. 1061 */ 1062 static int 1063 sysctl_net_inet_tcp_ident(SYSCTLFN_ARGS) 1064 { 1065 #ifdef INET 1066 struct inpcb *inb; 1067 struct sockaddr_in *si4[2]; 1068 #endif /* INET */ 1069 #ifdef INET6 1070 struct in6pcb *in6b; 1071 struct sockaddr_in6 *si6[2]; 1072 #endif /* INET6 */ 1073 struct in_addr laddr, raddr; 1074 struct sockaddr_storage sa[2]; 1075 struct socket *sockp; 1076 u_int lport, rport; 1077 size_t sz; 1078 uid_t uid; 1079 int error, pf; 1080 1081 if (namelen != 4 && namelen != 0) 1082 return (EINVAL); 1083 if (name[-2] != IPPROTO_TCP) 1084 return (EINVAL); 1085 pf = name[-3]; 1086 1087 /* old style lookup, ipv4 only */ 1088 if (namelen == 4) { 1089 #ifdef INET 1090 if (pf != PF_INET) 1091 return (EPROTONOSUPPORT); 1092 raddr.s_addr = (uint32_t)name[0]; 1093 rport = (u_int)name[1]; 1094 laddr.s_addr = (uint32_t)name[2]; 1095 lport = (u_int)name[3]; 1096 inb = in_pcblookup_connect(&tcbtable, raddr, rport, 1097 laddr, lport); 1098 if (inb == NULL || (sockp = inb->inp_socket) == NULL) 1099 return (ESRCH); 1100 uid = sockp->so_uid; 1101 if (oldp) { 1102 sz = MIN(sizeof(uid), *oldlenp); 1103 error = copyout(&uid, oldp, sz); 1104 if (error) 1105 return (error); 1106 } 1107 *oldlenp = sizeof(uid); 1108 return (0); 1109 #else /* INET */ 1110 return (EINVAL); 1111 #endif /* INET */ 1112 } 1113 1114 if (newp == NULL || newlen != sizeof(sa)) 1115 return (EINVAL); 1116 error = copyin(newp, &sa, newlen); 1117 if (error) 1118 return (error); 1119 1120 /* 1121 * requested families must match 1122 */ 1123 if (pf != sa[0].ss_family || sa[0].ss_family != sa[1].ss_family) 1124 return (EINVAL); 1125 1126 switch (pf) { 1127 #ifdef INET 1128 case PF_INET: 1129 si4[0] = (struct sockaddr_in*)&sa[0]; 1130 si4[1] = (struct sockaddr_in*)&sa[1]; 1131 if (si4[0]->sin_len != sizeof(*si4[0]) || 1132 si4[0]->sin_len != si4[1]->sin_len) 1133 return (EINVAL); 1134 inb = in_pcblookup_connect(&tcbtable, 1135 si4[0]->sin_addr, si4[0]->sin_port, 1136 si4[1]->sin_addr, si4[1]->sin_port); 1137 if (inb == NULL || (sockp = inb->inp_socket) == NULL) 1138 return (ESRCH); 1139 break; 1140 #endif /* INET */ 1141 #ifdef INET6 1142 case PF_INET6: 1143 si6[0] = (struct sockaddr_in6*)&sa[0]; 1144 si6[1] = (struct sockaddr_in6*)&sa[1]; 1145 if (si6[0]->sin6_len != sizeof(*si6[0]) || 1146 si6[0]->sin6_len != si6[1]->sin6_len) 1147 return (EINVAL); 1148 in6b = in6_pcblookup_connect(&tcbtable, 1149 &si6[0]->sin6_addr, si6[0]->sin6_port, 1150 &si6[1]->sin6_addr, si6[1]->sin6_port, 0); 1151 if (in6b == NULL || (sockp = in6b->in6p_socket) == NULL) 1152 return (ESRCH); 1153 break; 1154 #endif /* INET6 */ 1155 default: 1156 return (EPROTONOSUPPORT); 1157 } 1158 1159 uid = sockp->so_uid; 1160 if (oldp) { 1161 sz = MIN(sizeof(uid), *oldlenp); 1162 error = copyout(&uid, oldp, sz); 1163 if (error) 1164 return (error); 1165 } 1166 *oldlenp = sizeof(uid); 1167 1168 return (0); 1169 } 1170 1171 /* 1172 * this (second stage) setup routine is a replacement for tcp_sysctl() 1173 * (which is currently used for ipv4 and ipv6) 1174 */ 1175 static void 1176 sysctl_net_inet_tcp_setup2(int pf, const char *pfname, const char *tcpname) 1177 { 1178 1179 sysctl_createv(SYSCTL_PERMANENT, 1180 CTLTYPE_NODE, "net", NULL, 1181 NULL, 0, NULL, 0, 1182 CTL_NET, CTL_EOL); 1183 sysctl_createv(SYSCTL_PERMANENT, 1184 CTLTYPE_NODE, pfname, NULL, 1185 NULL, 0, NULL, 0, 1186 CTL_NET, pf, CTL_EOL); 1187 sysctl_createv(SYSCTL_PERMANENT, 1188 CTLTYPE_NODE, tcpname, NULL, 1189 NULL, 0, NULL, 0, 1190 CTL_NET, pf, IPPROTO_TCP, CTL_EOL); 1191 1192 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1193 CTLTYPE_INT, "rfc1323", NULL, 1194 NULL, 0, &tcp_do_rfc1323, 0, 1195 CTL_NET, pf, IPPROTO_TCP, TCPCTL_RFC1323, CTL_EOL); 1196 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1197 CTLTYPE_INT, "sendspace", NULL, 1198 NULL, 0, &tcp_sendspace, 0, 1199 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SENDSPACE, CTL_EOL); 1200 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1201 CTLTYPE_INT, "recvspace", NULL, 1202 NULL, 0, &tcp_recvspace, 0, 1203 CTL_NET, pf, IPPROTO_TCP, TCPCTL_RECVSPACE, CTL_EOL); 1204 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1205 CTLTYPE_INT, "mssdflt", NULL, 1206 sysctl_net_inet_tcp_mssdflt, 0, &tcp_mssdflt, 0, 1207 CTL_NET, pf, IPPROTO_TCP, TCPCTL_MSSDFLT, CTL_EOL); 1208 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1209 CTLTYPE_INT, "syn_cache_limit", NULL, 1210 NULL, 0, &tcp_syn_cache_limit, 0, 1211 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SYN_CACHE_LIMIT, 1212 CTL_EOL); 1213 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1214 CTLTYPE_INT, "syn_bucket_limit", NULL, 1215 NULL, 0, &tcp_syn_bucket_limit, 0, 1216 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SYN_BUCKET_LIMIT, 1217 CTL_EOL); 1218 #if 0 /* obsoleted */ 1219 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1220 CTLTYPE_INT, "syn_cache_interval", NULL, 1221 NULL, 0, &tcp_syn_cache_interval, 0, 1222 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SYN_CACHE_INTER, 1223 CTL_EOL); 1224 #endif 1225 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1226 CTLTYPE_INT, "init_win", NULL, 1227 NULL, 0, &tcp_init_win, 0, 1228 CTL_NET, pf, IPPROTO_TCP, TCPCTL_INIT_WIN, CTL_EOL); 1229 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1230 CTLTYPE_INT, "mss_ifmtu", NULL, 1231 NULL, 0, &tcp_mss_ifmtu, 0, 1232 CTL_NET, pf, IPPROTO_TCP, TCPCTL_MSS_IFMTU, CTL_EOL); 1233 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1234 CTLTYPE_INT, "sack", NULL, 1235 NULL, 0, &tcp_do_sack, 0, 1236 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SACK, CTL_EOL); 1237 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1238 CTLTYPE_INT, "win_scale", NULL, 1239 NULL, 0, &tcp_do_win_scale, 0, 1240 CTL_NET, pf, IPPROTO_TCP, TCPCTL_WSCALE, CTL_EOL); 1241 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1242 CTLTYPE_INT, "timestamps", NULL, 1243 NULL, 0, &tcp_do_timestamps, 0, 1244 CTL_NET, pf, IPPROTO_TCP, TCPCTL_TSTAMP, CTL_EOL); 1245 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1246 CTLTYPE_INT, "compat_42", NULL, 1247 NULL, 0, &tcp_compat_42, 0, 1248 CTL_NET, pf, IPPROTO_TCP, TCPCTL_COMPAT_42, CTL_EOL); 1249 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1250 CTLTYPE_INT, "cwm", NULL, 1251 NULL, 0, &tcp_cwm, 0, 1252 CTL_NET, pf, IPPROTO_TCP, TCPCTL_CWM, CTL_EOL); 1253 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1254 CTLTYPE_INT, "cwm_burstsize", NULL, 1255 NULL, 0, &tcp_cwm_burstsize, 0, 1256 CTL_NET, pf, IPPROTO_TCP, TCPCTL_CWM_BURSTSIZE, 1257 CTL_EOL); 1258 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1259 CTLTYPE_INT, "ack_on_push", NULL, 1260 NULL, 0, &tcp_ack_on_push, 0, 1261 CTL_NET, pf, IPPROTO_TCP, TCPCTL_ACK_ON_PUSH, CTL_EOL); 1262 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1263 CTLTYPE_INT, "keepidle", NULL, 1264 NULL, 0, &tcp_keepidle, 0, 1265 CTL_NET, pf, IPPROTO_TCP, TCPCTL_KEEPIDLE, CTL_EOL); 1266 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1267 CTLTYPE_INT, "keepintvl", NULL, 1268 NULL, 0, &tcp_keepintvl, 0, 1269 CTL_NET, pf, IPPROTO_TCP, TCPCTL_KEEPINTVL, CTL_EOL); 1270 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1271 CTLTYPE_INT, "keepcnt", NULL, 1272 NULL, 0, &tcp_keepcnt, 0, 1273 CTL_NET, pf, IPPROTO_TCP, TCPCTL_KEEPCNT, CTL_EOL); 1274 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 1275 CTLTYPE_INT, "slowhz", NULL, 1276 NULL, PR_SLOWHZ, NULL, 0, 1277 CTL_NET, pf, IPPROTO_TCP, TCPCTL_SLOWHZ, CTL_EOL); 1278 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1279 CTLTYPE_INT, "newreno", NULL, 1280 NULL, 0, &tcp_do_newreno, 0, 1281 CTL_NET, pf, IPPROTO_TCP, TCPCTL_NEWRENO, CTL_EOL); 1282 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1283 CTLTYPE_INT, "log_refused", NULL, 1284 NULL, 0, &tcp_log_refused, 0, 1285 CTL_NET, pf, IPPROTO_TCP, TCPCTL_LOG_REFUSED, CTL_EOL); 1286 #if 0 /* obsoleted */ 1287 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1288 CTLTYPE_INT, "rstratelimit", NULL, 1289 NULL, 0, &tcp_rst_ratelim, 0, 1290 CTL_NET, pf, IPPROTO_TCP, TCPCTL_RSTRATELIMIT, CTL_EOL); 1291 #endif 1292 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1293 CTLTYPE_INT, "rstppslimit", NULL, 1294 NULL, 0, &tcp_rst_ppslim, 0, 1295 CTL_NET, pf, IPPROTO_TCP, TCPCTL_RSTPPSLIMIT, CTL_EOL); 1296 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1297 CTLTYPE_INT, "delack_ticks", NULL, 1298 NULL, 0, &tcp_delack_ticks, 0, 1299 CTL_NET, pf, IPPROTO_TCP, TCPCTL_DELACK_TICKS, CTL_EOL); 1300 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1301 CTLTYPE_INT, "init_win_local", NULL, 1302 NULL, 0, &tcp_init_win_local, 0, 1303 CTL_NET, pf, IPPROTO_TCP, TCPCTL_INIT_WIN_LOCAL, 1304 CTL_EOL); 1305 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 1306 CTLTYPE_STRUCT, "ident", NULL, 1307 sysctl_net_inet_tcp_ident, 0, NULL, sizeof(uid_t), 1308 CTL_NET, pf, IPPROTO_TCP, TCPCTL_IDENT, CTL_EOL); 1309 } 1310 1311 /* 1312 * Sysctl for tcp variables. 1313 */ 1314 #ifdef INET 1315 SYSCTL_SETUP(sysctl_net_inet_tcp_setup, "sysctl net.inet.tcp subtree setup") 1316 { 1317 1318 sysctl_net_inet_tcp_setup2(PF_INET, "inet", "tcp"); 1319 } 1320 #endif /* INET */ 1321 1322 #ifdef INET6 1323 SYSCTL_SETUP(sysctl_net_inet6_tcp6_setup, "sysctl net.inet6.tcp6 subtree setup") 1324 { 1325 1326 sysctl_net_inet_tcp_setup2(PF_INET6, "inet6", "tcp6"); 1327 } 1328 #endif /* INET6 */ 1329 1330