The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/tcp_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1988, 1993
    3  *      The Regents of the University of California.
    4  * Copyright (c) 2006-2007 Robert N. M. Watson
    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  * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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  *      From: @(#)tcp_usrreq.c  8.2 (Berkeley) 1/3/94
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include "opt_ddb.h"
   38 #include "opt_inet.h"
   39 #include "opt_inet6.h"
   40 #include "opt_tcpdebug.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/kernel.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/mbuf.h>
   48 #ifdef INET6
   49 #include <sys/domain.h>
   50 #endif /* INET6 */
   51 #include <sys/socket.h>
   52 #include <sys/socketvar.h>
   53 #include <sys/protosw.h>
   54 #include <sys/proc.h>
   55 #include <sys/jail.h>
   56 
   57 #ifdef DDB
   58 #include <ddb/ddb.h>
   59 #endif
   60 
   61 #include <net/if.h>
   62 #include <net/route.h>
   63 
   64 #include <netinet/in.h>
   65 #include <netinet/in_systm.h>
   66 #ifdef INET6
   67 #include <netinet/ip6.h>
   68 #endif
   69 #include <netinet/in_pcb.h>
   70 #ifdef INET6
   71 #include <netinet6/in6_pcb.h>
   72 #endif
   73 #include <netinet/in_var.h>
   74 #include <netinet/ip_var.h>
   75 #ifdef INET6
   76 #include <netinet6/ip6_var.h>
   77 #include <netinet6/scope6_var.h>
   78 #endif
   79 #include <netinet/tcp.h>
   80 #include <netinet/tcp_fsm.h>
   81 #include <netinet/tcp_seq.h>
   82 #include <netinet/tcp_timer.h>
   83 #include <netinet/tcp_var.h>
   84 #include <netinet/tcpip.h>
   85 #ifdef TCPDEBUG
   86 #include <netinet/tcp_debug.h>
   87 #endif
   88 
   89 /*
   90  * TCP protocol interface to socket abstraction.
   91  */
   92 static int      tcp_attach(struct socket *);
   93 static int      tcp_connect(struct tcpcb *, struct sockaddr *,
   94                     struct thread *td);
   95 #ifdef INET6
   96 static int      tcp6_connect(struct tcpcb *, struct sockaddr *,
   97                     struct thread *td);
   98 #endif /* INET6 */
   99 static void     tcp_disconnect(struct tcpcb *);
  100 static void     tcp_usrclosed(struct tcpcb *);
  101 static void     tcp_fill_info(struct tcpcb *, struct tcp_info *);
  102 
  103 #ifdef TCPDEBUG
  104 #define TCPDEBUG0       int ostate = 0
  105 #define TCPDEBUG1()     ostate = tp ? tp->t_state : 0
  106 #define TCPDEBUG2(req)  if (tp && (so->so_options & SO_DEBUG)) \
  107                                 tcp_trace(TA_USER, ostate, tp, 0, 0, req)
  108 #else
  109 #define TCPDEBUG0
  110 #define TCPDEBUG1()
  111 #define TCPDEBUG2(req)
  112 #endif
  113 
  114 /*
  115  * TCP attaches to socket via pru_attach(), reserving space,
  116  * and an internet control block.
  117  */
  118 static int
  119 tcp_usr_attach(struct socket *so, int proto, struct thread *td)
  120 {
  121         struct inpcb *inp;
  122         struct tcpcb *tp = NULL;
  123         int error;
  124         TCPDEBUG0;
  125 
  126         inp = sotoinpcb(so);
  127         KASSERT(inp == NULL, ("tcp_usr_attach: inp != NULL"));
  128         TCPDEBUG1();
  129 
  130         error = tcp_attach(so);
  131         if (error)
  132                 goto out;
  133 
  134         if ((so->so_options & SO_LINGER) && so->so_linger == 0)
  135                 so->so_linger = TCP_LINGERTIME;
  136 
  137         inp = sotoinpcb(so);
  138         tp = intotcpcb(inp);
  139 out:
  140         TCPDEBUG2(PRU_ATTACH);
  141         return error;
  142 }
  143 
  144 /*
  145  * tcp_detach is called when the socket layer loses its final reference
  146  * to the socket, be it a file descriptor reference, a reference from TCP,
  147  * etc.  At this point, there is only one case in which we will keep around
  148  * inpcb state: time wait.
  149  *
  150  * This function can probably be re-absorbed back into tcp_usr_detach() now
  151  * that there is a single detach path.
  152  */
  153 static void
  154 tcp_detach(struct socket *so, struct inpcb *inp)
  155 {
  156         struct tcpcb *tp;
  157 #ifdef INET6
  158         int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != 0;
  159 #endif
  160 
  161         INP_INFO_WLOCK_ASSERT(&tcbinfo);
  162         INP_LOCK_ASSERT(inp);
  163 
  164         KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp"));
  165         KASSERT(inp->inp_socket == so, ("tcp_detach: inp_socket != so"));
  166 
  167         tp = intotcpcb(inp);
  168 
  169         if (inp->inp_vflag & INP_TIMEWAIT) {
  170                 /*
  171                  * There are two cases to handle: one in which the time wait
  172                  * state is being discarded (INP_DROPPED), and one in which
  173                  * this connection will remain in timewait.  In the former,
  174                  * it is time to discard all state (except tcptw, which has
  175                  * already been discarded by the timewait close code, which
  176                  * should be further up the call stack somewhere).  In the
  177                  * latter case, we detach from the socket, but leave the pcb
  178                  * present until timewait ends.
  179                  *
  180                  * XXXRW: Would it be cleaner to free the tcptw here?
  181                  */
  182                 if (inp->inp_vflag & INP_DROPPED) {
  183                         KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && "
  184                             "INP_DROPPED && tp != NULL"));
  185 #ifdef INET6
  186                         if (isipv6) {
  187                                 in6_pcbdetach(inp);
  188                                 in6_pcbfree(inp);
  189                         } else {
  190 #endif
  191                                 in_pcbdetach(inp);
  192                                 in_pcbfree(inp);
  193 #ifdef INET6
  194                         }
  195 #endif
  196                 } else {
  197 #ifdef INET6
  198                         if (isipv6)
  199                                 in6_pcbdetach(inp);
  200                         else
  201 #endif
  202                                 in_pcbdetach(inp);
  203                         INP_UNLOCK(inp);
  204                 }
  205         } else {
  206                 /*
  207                  * If the connection is not in timewait, we consider two
  208                  * two conditions: one in which no further processing is
  209                  * necessary (dropped || embryonic), and one in which TCP is
  210                  * not yet done, but no longer requires the socket, so the
  211                  * pcb will persist for the time being.
  212                  *
  213                  * XXXRW: Does the second case still occur?
  214                  */
  215                 if (inp->inp_vflag & INP_DROPPED ||
  216                     tp->t_state < TCPS_SYN_SENT) {
  217                         tcp_discardcb(tp);
  218 #ifdef INET6
  219                         if (isipv6) {
  220                                 in6_pcbdetach(inp);
  221                                 in6_pcbfree(inp);
  222                         } else {
  223 #endif
  224                                 in_pcbdetach(inp);
  225                                 in_pcbfree(inp);
  226 #ifdef INET6
  227                         }
  228 #endif
  229                 } else {
  230 #ifdef INET6
  231                         if (isipv6)
  232                                 in6_pcbdetach(inp);
  233                         else
  234 #endif
  235                                 in_pcbdetach(inp);
  236                 }
  237         }
  238 }
  239 
  240 /*
  241  * pru_detach() detaches the TCP protocol from the socket.
  242  * If the protocol state is non-embryonic, then can't
  243  * do this directly: have to initiate a pru_disconnect(),
  244  * which may finish later; embryonic TCB's can just
  245  * be discarded here.
  246  */
  247 static void
  248 tcp_usr_detach(struct socket *so)
  249 {
  250         struct inpcb *inp;
  251 
  252         inp = sotoinpcb(so);
  253         KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL"));
  254         INP_INFO_WLOCK(&tcbinfo);
  255         INP_LOCK(inp);
  256         KASSERT(inp->inp_socket != NULL,
  257             ("tcp_usr_detach: inp_socket == NULL"));
  258         tcp_detach(so, inp);
  259         INP_INFO_WUNLOCK(&tcbinfo);
  260 }
  261 
  262 /*
  263  * Give the socket an address.
  264  */
  265 static int
  266 tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  267 {
  268         int error = 0;
  269         struct inpcb *inp;
  270         struct tcpcb *tp = NULL;
  271         struct sockaddr_in *sinp;
  272 
  273         sinp = (struct sockaddr_in *)nam;
  274         if (nam->sa_len != sizeof (*sinp))
  275                 return (EINVAL);
  276         /*
  277          * Must check for multicast addresses and disallow binding
  278          * to them.
  279          */
  280         if (sinp->sin_family == AF_INET &&
  281             IN_MULTICAST(ntohl(sinp->sin_addr.s_addr)))
  282                 return (EAFNOSUPPORT);
  283 
  284         TCPDEBUG0;
  285         INP_INFO_WLOCK(&tcbinfo);
  286         inp = sotoinpcb(so);
  287         KASSERT(inp != NULL, ("tcp_usr_bind: inp == NULL"));
  288         INP_LOCK(inp);
  289         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  290                 error = EINVAL;
  291                 goto out;
  292         }
  293         tp = intotcpcb(inp);
  294         TCPDEBUG1();
  295         error = in_pcbbind(inp, nam, td->td_ucred);
  296 out:
  297         TCPDEBUG2(PRU_BIND);
  298         INP_UNLOCK(inp);
  299         INP_INFO_WUNLOCK(&tcbinfo);
  300 
  301         return (error);
  302 }
  303 
  304 #ifdef INET6
  305 static int
  306 tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  307 {
  308         int error = 0;
  309         struct inpcb *inp;
  310         struct tcpcb *tp = NULL;
  311         struct sockaddr_in6 *sin6p;
  312 
  313         sin6p = (struct sockaddr_in6 *)nam;
  314         if (nam->sa_len != sizeof (*sin6p))
  315                 return (EINVAL);
  316         /*
  317          * Must check for multicast addresses and disallow binding
  318          * to them.
  319          */
  320         if (sin6p->sin6_family == AF_INET6 &&
  321             IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr))
  322                 return (EAFNOSUPPORT);
  323 
  324         TCPDEBUG0;
  325         INP_INFO_WLOCK(&tcbinfo);
  326         inp = sotoinpcb(so);
  327         KASSERT(inp != NULL, ("tcp6_usr_bind: inp == NULL"));
  328         INP_LOCK(inp);
  329         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  330                 error = EINVAL;
  331                 goto out;
  332         }
  333         tp = intotcpcb(inp);
  334         TCPDEBUG1();
  335         inp->inp_vflag &= ~INP_IPV4;
  336         inp->inp_vflag |= INP_IPV6;
  337         if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
  338                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr))
  339                         inp->inp_vflag |= INP_IPV4;
  340                 else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
  341                         struct sockaddr_in sin;
  342 
  343                         in6_sin6_2_sin(&sin, sin6p);
  344                         inp->inp_vflag |= INP_IPV4;
  345                         inp->inp_vflag &= ~INP_IPV6;
  346                         error = in_pcbbind(inp, (struct sockaddr *)&sin,
  347                             td->td_ucred);
  348                         goto out;
  349                 }
  350         }
  351         error = in6_pcbbind(inp, nam, td->td_ucred);
  352 out:
  353         TCPDEBUG2(PRU_BIND);
  354         INP_UNLOCK(inp);
  355         INP_INFO_WUNLOCK(&tcbinfo);
  356         return (error);
  357 }
  358 #endif /* INET6 */
  359 
  360 /*
  361  * Prepare to accept connections.
  362  */
  363 static int
  364 tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
  365 {
  366         int error = 0;
  367         struct inpcb *inp;
  368         struct tcpcb *tp = NULL;
  369 
  370         TCPDEBUG0;
  371         INP_INFO_WLOCK(&tcbinfo);
  372         inp = sotoinpcb(so);
  373         KASSERT(inp != NULL, ("tcp_usr_listen: inp == NULL"));
  374         INP_LOCK(inp);
  375         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  376                 error = EINVAL;
  377                 goto out;
  378         }
  379         tp = intotcpcb(inp);
  380         TCPDEBUG1();
  381         SOCK_LOCK(so);
  382         error = solisten_proto_check(so);
  383         if (error == 0 && inp->inp_lport == 0)
  384                 error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
  385         if (error == 0) {
  386                 tp->t_state = TCPS_LISTEN;
  387                 solisten_proto(so, backlog);
  388         }
  389         SOCK_UNLOCK(so);
  390 
  391 out:
  392         TCPDEBUG2(PRU_LISTEN);
  393         INP_UNLOCK(inp);
  394         INP_INFO_WUNLOCK(&tcbinfo);
  395         return (error);
  396 }
  397 
  398 #ifdef INET6
  399 static int
  400 tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
  401 {
  402         int error = 0;
  403         struct inpcb *inp;
  404         struct tcpcb *tp = NULL;
  405 
  406         TCPDEBUG0;
  407         INP_INFO_WLOCK(&tcbinfo);
  408         inp = sotoinpcb(so);
  409         KASSERT(inp != NULL, ("tcp6_usr_listen: inp == NULL"));
  410         INP_LOCK(inp);
  411         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  412                 error = EINVAL;
  413                 goto out;
  414         }
  415         tp = intotcpcb(inp);
  416         TCPDEBUG1();
  417         SOCK_LOCK(so);
  418         error = solisten_proto_check(so);
  419         if (error == 0 && inp->inp_lport == 0) {
  420                 inp->inp_vflag &= ~INP_IPV4;
  421                 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
  422                         inp->inp_vflag |= INP_IPV4;
  423                 error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
  424         }
  425         if (error == 0) {
  426                 tp->t_state = TCPS_LISTEN;
  427                 solisten_proto(so, backlog);
  428         }
  429         SOCK_UNLOCK(so);
  430 
  431 out:
  432         TCPDEBUG2(PRU_LISTEN);
  433         INP_UNLOCK(inp);
  434         INP_INFO_WUNLOCK(&tcbinfo);
  435         return (error);
  436 }
  437 #endif /* INET6 */
  438 
  439 /*
  440  * Initiate connection to peer.
  441  * Create a template for use in transmissions on this connection.
  442  * Enter SYN_SENT state, and mark socket as connecting.
  443  * Start keep-alive timer, and seed output sequence space.
  444  * Send initial segment on connection.
  445  */
  446 static int
  447 tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  448 {
  449         int error = 0;
  450         struct inpcb *inp;
  451         struct tcpcb *tp = NULL;
  452         struct sockaddr_in *sinp;
  453 
  454         sinp = (struct sockaddr_in *)nam;
  455         if (nam->sa_len != sizeof (*sinp))
  456                 return (EINVAL);
  457         /*
  458          * Must disallow TCP ``connections'' to multicast addresses.
  459          */
  460         if (sinp->sin_family == AF_INET
  461             && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr)))
  462                 return (EAFNOSUPPORT);
  463         if (jailed(td->td_ucred))
  464                 prison_remote_ip(td->td_ucred, 0, &sinp->sin_addr.s_addr);
  465 
  466         TCPDEBUG0;
  467         INP_INFO_WLOCK(&tcbinfo);
  468         inp = sotoinpcb(so);
  469         KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL"));
  470         INP_LOCK(inp);
  471         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  472                 error = EINVAL;
  473                 goto out;
  474         }
  475         tp = intotcpcb(inp);
  476         TCPDEBUG1();
  477         if ((error = tcp_connect(tp, nam, td)) != 0)
  478                 goto out;
  479         error = tcp_output(tp);
  480 out:
  481         TCPDEBUG2(PRU_CONNECT);
  482         INP_UNLOCK(inp);
  483         INP_INFO_WUNLOCK(&tcbinfo);
  484         return (error);
  485 }
  486 
  487 #ifdef INET6
  488 static int
  489 tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  490 {
  491         int error = 0;
  492         struct inpcb *inp;
  493         struct tcpcb *tp = NULL;
  494         struct sockaddr_in6 *sin6p;
  495 
  496         TCPDEBUG0;
  497 
  498         sin6p = (struct sockaddr_in6 *)nam;
  499         if (nam->sa_len != sizeof (*sin6p))
  500                 return (EINVAL);
  501         /*
  502          * Must disallow TCP ``connections'' to multicast addresses.
  503          */
  504         if (sin6p->sin6_family == AF_INET6
  505             && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr))
  506                 return (EAFNOSUPPORT);
  507 
  508         INP_INFO_WLOCK(&tcbinfo);
  509         inp = sotoinpcb(so);
  510         KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL"));
  511         INP_LOCK(inp);
  512         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  513                 error = EINVAL;
  514                 goto out;
  515         }
  516         tp = intotcpcb(inp);
  517         TCPDEBUG1();
  518         if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
  519                 struct sockaddr_in sin;
  520 
  521                 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) {
  522                         error = EINVAL;
  523                         goto out;
  524                 }
  525 
  526                 in6_sin6_2_sin(&sin, sin6p);
  527                 inp->inp_vflag |= INP_IPV4;
  528                 inp->inp_vflag &= ~INP_IPV6;
  529                 if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
  530                         goto out;
  531                 error = tcp_output(tp);
  532                 goto out;
  533         }
  534         inp->inp_vflag &= ~INP_IPV4;
  535         inp->inp_vflag |= INP_IPV6;
  536         inp->inp_inc.inc_isipv6 = 1;
  537         if ((error = tcp6_connect(tp, nam, td)) != 0)
  538                 goto out;
  539         error = tcp_output(tp);
  540 
  541 out:
  542         TCPDEBUG2(PRU_CONNECT);
  543         INP_UNLOCK(inp);
  544         INP_INFO_WUNLOCK(&tcbinfo);
  545         return (error);
  546 }
  547 #endif /* INET6 */
  548 
  549 /*
  550  * Initiate disconnect from peer.
  551  * If connection never passed embryonic stage, just drop;
  552  * else if don't need to let data drain, then can just drop anyways,
  553  * else have to begin TCP shutdown process: mark socket disconnecting,
  554  * drain unread data, state switch to reflect user close, and
  555  * send segment (e.g. FIN) to peer.  Socket will be really disconnected
  556  * when peer sends FIN and acks ours.
  557  *
  558  * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
  559  */
  560 static int
  561 tcp_usr_disconnect(struct socket *so)
  562 {
  563         struct inpcb *inp;
  564         struct tcpcb *tp = NULL;
  565         int error = 0;
  566 
  567         TCPDEBUG0;
  568         INP_INFO_WLOCK(&tcbinfo);
  569         inp = sotoinpcb(so);
  570         KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL"));
  571         INP_LOCK(inp);
  572         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  573                 error = ECONNRESET;
  574                 goto out;
  575         }
  576         tp = intotcpcb(inp);
  577         TCPDEBUG1();
  578         tcp_disconnect(tp);
  579 out:
  580         TCPDEBUG2(PRU_DISCONNECT);
  581         INP_UNLOCK(inp);
  582         INP_INFO_WUNLOCK(&tcbinfo);
  583         return (error);
  584 }
  585 
  586 /*
  587  * Accept a connection.  Essentially all the work is
  588  * done at higher levels; just return the address
  589  * of the peer, storing through addr.
  590  */
  591 static int
  592 tcp_usr_accept(struct socket *so, struct sockaddr **nam)
  593 {
  594         int error = 0;
  595         struct inpcb *inp = NULL;
  596         struct tcpcb *tp = NULL;
  597         struct in_addr addr;
  598         in_port_t port = 0;
  599         TCPDEBUG0;
  600 
  601         if (so->so_state & SS_ISDISCONNECTED)
  602                 return (ECONNABORTED);
  603 
  604         inp = sotoinpcb(so);
  605         KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
  606         INP_INFO_RLOCK(&tcbinfo);
  607         INP_LOCK(inp);
  608         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  609                 error = ECONNABORTED;
  610                 goto out;
  611         }
  612         tp = intotcpcb(inp);
  613         TCPDEBUG1();
  614 
  615         /*
  616          * We inline in_getpeeraddr and COMMON_END here, so that we can
  617          * copy the data of interest and defer the malloc until after we
  618          * release the lock.
  619          */
  620         port = inp->inp_fport;
  621         addr = inp->inp_faddr;
  622 
  623 out:
  624         TCPDEBUG2(PRU_ACCEPT);
  625         INP_UNLOCK(inp);
  626         INP_INFO_RUNLOCK(&tcbinfo);
  627         if (error == 0)
  628                 *nam = in_sockaddr(port, &addr);
  629         return error;
  630 }
  631 
  632 #ifdef INET6
  633 static int
  634 tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
  635 {
  636         struct inpcb *inp = NULL;
  637         int error = 0;
  638         struct tcpcb *tp = NULL;
  639         struct in_addr addr;
  640         struct in6_addr addr6;
  641         in_port_t port = 0;
  642         int v4 = 0;
  643         TCPDEBUG0;
  644 
  645         if (so->so_state & SS_ISDISCONNECTED)
  646                 return (ECONNABORTED);
  647 
  648         inp = sotoinpcb(so);
  649         KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL"));
  650         INP_LOCK(inp);
  651         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  652                 error = ECONNABORTED;
  653                 goto out;
  654         }
  655         tp = intotcpcb(inp);
  656         TCPDEBUG1();
  657 
  658         /*
  659          * We inline in6_mapped_peeraddr and COMMON_END here, so that we can
  660          * copy the data of interest and defer the malloc until after we
  661          * release the lock.
  662          */
  663         if (inp->inp_vflag & INP_IPV4) {
  664                 v4 = 1;
  665                 port = inp->inp_fport;
  666                 addr = inp->inp_faddr;
  667         } else {
  668                 port = inp->inp_fport;
  669                 addr6 = inp->in6p_faddr;
  670         }
  671 
  672 out:
  673         TCPDEBUG2(PRU_ACCEPT);
  674         INP_UNLOCK(inp);
  675         if (error == 0) {
  676                 if (v4)
  677                         *nam = in6_v4mapsin6_sockaddr(port, &addr);
  678                 else
  679                         *nam = in6_sockaddr(port, &addr6);
  680         }
  681         return error;
  682 }
  683 #endif /* INET6 */
  684 
  685 /*
  686  * Mark the connection as being incapable of further output.
  687  */
  688 static int
  689 tcp_usr_shutdown(struct socket *so)
  690 {
  691         int error = 0;
  692         struct inpcb *inp;
  693         struct tcpcb *tp = NULL;
  694 
  695         TCPDEBUG0;
  696         INP_INFO_WLOCK(&tcbinfo);
  697         inp = sotoinpcb(so);
  698         KASSERT(inp != NULL, ("inp == NULL"));
  699         INP_LOCK(inp);
  700         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  701                 error = ECONNRESET;
  702                 goto out;
  703         }
  704         tp = intotcpcb(inp);
  705         TCPDEBUG1();
  706         socantsendmore(so);
  707         tcp_usrclosed(tp);
  708         error = tcp_output(tp);
  709 
  710 out:
  711         TCPDEBUG2(PRU_SHUTDOWN);
  712         INP_UNLOCK(inp);
  713         INP_INFO_WUNLOCK(&tcbinfo);
  714 
  715         return (error);
  716 }
  717 
  718 /*
  719  * After a receive, possibly send window update to peer.
  720  */
  721 static int
  722 tcp_usr_rcvd(struct socket *so, int flags)
  723 {
  724         struct inpcb *inp;
  725         struct tcpcb *tp = NULL;
  726         int error = 0;
  727 
  728         TCPDEBUG0;
  729         inp = sotoinpcb(so);
  730         KASSERT(inp != NULL, ("tcp_usr_rcvd: inp == NULL"));
  731         INP_LOCK(inp);
  732         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  733                 error = ECONNRESET;
  734                 goto out;
  735         }
  736         tp = intotcpcb(inp);
  737         TCPDEBUG1();
  738         tcp_output(tp);
  739 
  740 out:
  741         TCPDEBUG2(PRU_RCVD);
  742         INP_UNLOCK(inp);
  743         return (error);
  744 }
  745 
  746 /*
  747  * Do a send by putting data in output queue and updating urgent
  748  * marker if URG set.  Possibly send more data.  Unlike the other
  749  * pru_*() routines, the mbuf chains are our responsibility.  We
  750  * must either enqueue them or free them.  The other pru_* routines
  751  * generally are caller-frees.
  752  */
  753 static int
  754 tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
  755     struct sockaddr *nam, struct mbuf *control, struct thread *td)
  756 {
  757         int error = 0;
  758         struct inpcb *inp;
  759         struct tcpcb *tp = NULL;
  760         int headlocked = 0;
  761 #ifdef INET6
  762         int isipv6;
  763 #endif
  764         TCPDEBUG0;
  765 
  766         /*
  767          * We require the pcbinfo lock in two cases:
  768          *
  769          * (1) An implied connect is taking place, which can result in
  770          *     binding IPs and ports and hence modification of the pcb hash
  771          *     chains.
  772          *
  773          * (2) PRUS_EOF is set, resulting in explicit close on the send.
  774          */
  775         if ((nam != NULL) || (flags & PRUS_EOF)) {
  776                 INP_INFO_WLOCK(&tcbinfo);
  777                 headlocked = 1;
  778         }
  779         inp = sotoinpcb(so);
  780         KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
  781         INP_LOCK(inp);
  782         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  783                 if (control)
  784                         m_freem(control);
  785                 if (m)
  786                         m_freem(m);
  787                 error = ECONNRESET;
  788                 goto out;
  789         }
  790 #ifdef INET6
  791         isipv6 = nam && nam->sa_family == AF_INET6;
  792 #endif /* INET6 */
  793         tp = intotcpcb(inp);
  794         TCPDEBUG1();
  795         if (control) {
  796                 /* TCP doesn't do control messages (rights, creds, etc) */
  797                 if (control->m_len) {
  798                         m_freem(control);
  799                         if (m)
  800                                 m_freem(m);
  801                         error = EINVAL;
  802                         goto out;
  803                 }
  804                 m_freem(control);       /* empty control, just free it */
  805         }
  806         if (!(flags & PRUS_OOB)) {
  807                 sbappendstream(&so->so_snd, m);
  808                 if (nam && tp->t_state < TCPS_SYN_SENT) {
  809                         /*
  810                          * Do implied connect if not yet connected,
  811                          * initialize window to default value, and
  812                          * initialize maxseg/maxopd using peer's cached
  813                          * MSS.
  814                          */
  815                         INP_INFO_WLOCK_ASSERT(&tcbinfo);
  816 #ifdef INET6
  817                         if (isipv6)
  818                                 error = tcp6_connect(tp, nam, td);
  819                         else
  820 #endif /* INET6 */
  821                         error = tcp_connect(tp, nam, td);
  822                         if (error)
  823                                 goto out;
  824                         tp->snd_wnd = TTCP_CLIENT_SND_WND;
  825                         tcp_mss(tp, -1);
  826                 }
  827                 if (flags & PRUS_EOF) {
  828                         /*
  829                          * Close the send side of the connection after
  830                          * the data is sent.
  831                          */
  832                         INP_INFO_WLOCK_ASSERT(&tcbinfo);
  833                         socantsendmore(so);
  834                         tcp_usrclosed(tp);
  835                 }
  836                 if (headlocked) {
  837                         INP_INFO_WUNLOCK(&tcbinfo);
  838                         headlocked = 0;
  839                 }
  840                 if (tp != NULL) {
  841                         if (flags & PRUS_MORETOCOME)
  842                                 tp->t_flags |= TF_MORETOCOME;
  843                         error = tcp_output(tp);
  844                         if (flags & PRUS_MORETOCOME)
  845                                 tp->t_flags &= ~TF_MORETOCOME;
  846                 }
  847         } else {
  848                 /*
  849                  * XXXRW: PRUS_EOF not implemented with PRUS_OOB?
  850                  */
  851                 SOCKBUF_LOCK(&so->so_snd);
  852                 if (sbspace(&so->so_snd) < -512) {
  853                         SOCKBUF_UNLOCK(&so->so_snd);
  854                         m_freem(m);
  855                         error = ENOBUFS;
  856                         goto out;
  857                 }
  858                 /*
  859                  * According to RFC961 (Assigned Protocols),
  860                  * the urgent pointer points to the last octet
  861                  * of urgent data.  We continue, however,
  862                  * to consider it to indicate the first octet
  863                  * of data past the urgent section.
  864                  * Otherwise, snd_up should be one lower.
  865                  */
  866                 sbappendstream_locked(&so->so_snd, m);
  867                 SOCKBUF_UNLOCK(&so->so_snd);
  868                 if (nam && tp->t_state < TCPS_SYN_SENT) {
  869                         /*
  870                          * Do implied connect if not yet connected,
  871                          * initialize window to default value, and
  872                          * initialize maxseg/maxopd using peer's cached
  873                          * MSS.
  874                          */
  875                         INP_INFO_WLOCK_ASSERT(&tcbinfo);
  876 #ifdef INET6
  877                         if (isipv6)
  878                                 error = tcp6_connect(tp, nam, td);
  879                         else
  880 #endif /* INET6 */
  881                         error = tcp_connect(tp, nam, td);
  882                         if (error)
  883                                 goto out;
  884                         tp->snd_wnd = TTCP_CLIENT_SND_WND;
  885                         tcp_mss(tp, -1);
  886                         INP_INFO_WUNLOCK(&tcbinfo);
  887                         headlocked = 0;
  888                 } else if (nam) {
  889                         INP_INFO_WUNLOCK(&tcbinfo);
  890                         headlocked = 0;
  891                 }
  892                 tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
  893                 tp->t_flags |= TF_FORCEDATA;
  894                 error = tcp_output(tp);
  895                 tp->t_flags &= ~TF_FORCEDATA;
  896         }
  897 out:
  898         TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
  899                   ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
  900         INP_UNLOCK(inp);
  901         if (headlocked)
  902                 INP_INFO_WUNLOCK(&tcbinfo);
  903         return (error);
  904 }
  905 
  906 /*
  907  * Abort the TCP.  Drop the connection abruptly.
  908  */
  909 static void
  910 tcp_usr_abort(struct socket *so)
  911 {
  912         struct inpcb *inp;
  913         struct tcpcb *tp = NULL;
  914         TCPDEBUG0;
  915 
  916         inp = sotoinpcb(so);
  917         KASSERT(inp != NULL, ("tcp_usr_abort: inp == NULL"));
  918 
  919         INP_INFO_WLOCK(&tcbinfo);
  920         INP_LOCK(inp);
  921         KASSERT(inp->inp_socket != NULL,
  922             ("tcp_usr_abort: inp_socket == NULL"));
  923 
  924         /*
  925          * If we still have full TCP state, and we're not dropped, drop.
  926          */
  927         if (!(inp->inp_vflag & INP_TIMEWAIT) &&
  928             !(inp->inp_vflag & INP_DROPPED)) {
  929                 tp = intotcpcb(inp);
  930                 TCPDEBUG1();
  931                 tcp_drop(tp, ECONNABORTED);
  932                 TCPDEBUG2(PRU_ABORT);
  933         }
  934         if (!(inp->inp_vflag & INP_DROPPED)) {
  935                 SOCK_LOCK(so);
  936                 so->so_state |= SS_PROTOREF;
  937                 SOCK_UNLOCK(so);
  938                 inp->inp_vflag |= INP_SOCKREF;
  939         }
  940         INP_UNLOCK(inp);
  941         INP_INFO_WUNLOCK(&tcbinfo);
  942 }
  943 
  944 /*
  945  * TCP socket is closed.  Start friendly disconnect.
  946  */
  947 static void
  948 tcp_usr_close(struct socket *so)
  949 {
  950         struct inpcb *inp;
  951         struct tcpcb *tp = NULL;
  952         TCPDEBUG0;
  953 
  954         inp = sotoinpcb(so);
  955         KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL"));
  956 
  957         INP_INFO_WLOCK(&tcbinfo);
  958         INP_LOCK(inp);
  959         KASSERT(inp->inp_socket != NULL,
  960             ("tcp_usr_close: inp_socket == NULL"));
  961 
  962         /*
  963          * If we still have full TCP state, and we're not dropped, initiate
  964          * a disconnect.
  965          */
  966         if (!(inp->inp_vflag & INP_TIMEWAIT) &&
  967             !(inp->inp_vflag & INP_DROPPED)) {
  968                 tp = intotcpcb(inp);
  969                 TCPDEBUG1();
  970                 tcp_disconnect(tp);
  971                 TCPDEBUG2(PRU_CLOSE);
  972         }
  973         if (!(inp->inp_vflag & INP_DROPPED)) {
  974                 SOCK_LOCK(so);
  975                 so->so_state |= SS_PROTOREF;
  976                 SOCK_UNLOCK(so);
  977                 inp->inp_vflag |= INP_SOCKREF;
  978         }
  979         INP_UNLOCK(inp);
  980         INP_INFO_WUNLOCK(&tcbinfo);
  981 }
  982 
  983 /*
  984  * Receive out-of-band data.
  985  */
  986 static int
  987 tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
  988 {
  989         int error = 0;
  990         struct inpcb *inp;
  991         struct tcpcb *tp = NULL;
  992 
  993         TCPDEBUG0;
  994         inp = sotoinpcb(so);
  995         KASSERT(inp != NULL, ("tcp_usr_rcvoob: inp == NULL"));
  996         INP_LOCK(inp);
  997         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
  998                 error = ECONNRESET;
  999                 goto out;
 1000         }
 1001         tp = intotcpcb(inp);
 1002         TCPDEBUG1();
 1003         if ((so->so_oobmark == 0 &&
 1004              (so->so_rcv.sb_state & SBS_RCVATMARK) == 0) ||
 1005             so->so_options & SO_OOBINLINE ||
 1006             tp->t_oobflags & TCPOOB_HADDATA) {
 1007                 error = EINVAL;
 1008                 goto out;
 1009         }
 1010         if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
 1011                 error = EWOULDBLOCK;
 1012                 goto out;
 1013         }
 1014         m->m_len = 1;
 1015         *mtod(m, caddr_t) = tp->t_iobc;
 1016         if ((flags & MSG_PEEK) == 0)
 1017                 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
 1018 
 1019 out:
 1020         TCPDEBUG2(PRU_RCVOOB);
 1021         INP_UNLOCK(inp);
 1022         return (error);
 1023 }
 1024 
 1025 struct pr_usrreqs tcp_usrreqs = {
 1026         .pru_abort =            tcp_usr_abort,
 1027         .pru_accept =           tcp_usr_accept,
 1028         .pru_attach =           tcp_usr_attach,
 1029         .pru_bind =             tcp_usr_bind,
 1030         .pru_connect =          tcp_usr_connect,
 1031         .pru_control =          in_control,
 1032         .pru_detach =           tcp_usr_detach,
 1033         .pru_disconnect =       tcp_usr_disconnect,
 1034         .pru_listen =           tcp_usr_listen,
 1035         .pru_peeraddr =         in_getpeeraddr,
 1036         .pru_rcvd =             tcp_usr_rcvd,
 1037         .pru_rcvoob =           tcp_usr_rcvoob,
 1038         .pru_send =             tcp_usr_send,
 1039         .pru_shutdown =         tcp_usr_shutdown,
 1040         .pru_sockaddr =         in_getsockaddr,
 1041         .pru_sosetlabel =       in_pcbsosetlabel,
 1042         .pru_close =            tcp_usr_close,
 1043 };
 1044 
 1045 #ifdef INET6
 1046 struct pr_usrreqs tcp6_usrreqs = {
 1047         .pru_abort =            tcp_usr_abort,
 1048         .pru_accept =           tcp6_usr_accept,
 1049         .pru_attach =           tcp_usr_attach,
 1050         .pru_bind =             tcp6_usr_bind,
 1051         .pru_connect =          tcp6_usr_connect,
 1052         .pru_control =          in6_control,
 1053         .pru_detach =           tcp_usr_detach,
 1054         .pru_disconnect =       tcp_usr_disconnect,
 1055         .pru_listen =           tcp6_usr_listen,
 1056         .pru_peeraddr =         in6_mapped_peeraddr,
 1057         .pru_rcvd =             tcp_usr_rcvd,
 1058         .pru_rcvoob =           tcp_usr_rcvoob,
 1059         .pru_send =             tcp_usr_send,
 1060         .pru_shutdown =         tcp_usr_shutdown,
 1061         .pru_sockaddr =         in6_mapped_sockaddr,
 1062         .pru_sosetlabel =       in_pcbsosetlabel,
 1063         .pru_close =            tcp_usr_close,
 1064 };
 1065 #endif /* INET6 */
 1066 
 1067 /*
 1068  * Common subroutine to open a TCP connection to remote host specified
 1069  * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
 1070  * port number if needed.  Call in_pcbconnect_setup to do the routing and
 1071  * to choose a local host address (interface).  If there is an existing
 1072  * incarnation of the same connection in TIME-WAIT state and if the remote
 1073  * host was sending CC options and if the connection duration was < MSL, then
 1074  * truncate the previous TIME-WAIT state and proceed.
 1075  * Initialize connection parameters and enter SYN-SENT state.
 1076  */
 1077 static int
 1078 tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
 1079 {
 1080         struct inpcb *inp = tp->t_inpcb, *oinp;
 1081         struct socket *so = inp->inp_socket;
 1082         struct in_addr laddr;
 1083         u_short lport;
 1084         int error;
 1085 
 1086         INP_INFO_WLOCK_ASSERT(&tcbinfo);
 1087         INP_LOCK_ASSERT(inp);
 1088 
 1089         if (inp->inp_lport == 0) {
 1090                 error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
 1091                 if (error)
 1092                         return error;
 1093         }
 1094 
 1095         /*
 1096          * Cannot simply call in_pcbconnect, because there might be an
 1097          * earlier incarnation of this same connection still in
 1098          * TIME_WAIT state, creating an ADDRINUSE error.
 1099          */
 1100         laddr = inp->inp_laddr;
 1101         lport = inp->inp_lport;
 1102         error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport,
 1103             &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred);
 1104         if (error && oinp == NULL)
 1105                 return error;
 1106         if (oinp)
 1107                 return EADDRINUSE;
 1108         inp->inp_laddr = laddr;
 1109         in_pcbrehash(inp);
 1110 
 1111         /*
 1112          * Compute window scaling to request:
 1113          * Scale to fit into sweet spot.  See tcp_syncache.c.
 1114          * XXX: This should move to tcp_output().
 1115          */
 1116         while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
 1117             (TCP_MAXWIN << tp->request_r_scale) < sb_max)
 1118                 tp->request_r_scale++;
 1119 
 1120         soisconnecting(so);
 1121         tcpstat.tcps_connattempt++;
 1122         tp->t_state = TCPS_SYN_SENT;
 1123         tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
 1124         tp->iss = tcp_new_isn(tp);
 1125         tp->t_bw_rtseq = tp->iss;
 1126         tcp_sendseqinit(tp);
 1127 
 1128         return 0;
 1129 }
 1130 
 1131 #ifdef INET6
 1132 static int
 1133 tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
 1134 {
 1135         struct inpcb *inp = tp->t_inpcb, *oinp;
 1136         struct socket *so = inp->inp_socket;
 1137         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
 1138         struct in6_addr *addr6;
 1139         int error;
 1140 
 1141         INP_INFO_WLOCK_ASSERT(&tcbinfo);
 1142         INP_LOCK_ASSERT(inp);
 1143 
 1144         if (inp->inp_lport == 0) {
 1145                 error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
 1146                 if (error)
 1147                         return error;
 1148         }
 1149 
 1150         /*
 1151          * Cannot simply call in_pcbconnect, because there might be an
 1152          * earlier incarnation of this same connection still in
 1153          * TIME_WAIT state, creating an ADDRINUSE error.
 1154          * in6_pcbladdr() also handles scope zone IDs.
 1155          */
 1156         error = in6_pcbladdr(inp, nam, &addr6);
 1157         if (error)
 1158                 return error;
 1159         oinp = in6_pcblookup_hash(inp->inp_pcbinfo,
 1160                                   &sin6->sin6_addr, sin6->sin6_port,
 1161                                   IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
 1162                                   ? addr6
 1163                                   : &inp->in6p_laddr,
 1164                                   inp->inp_lport,  0, NULL);
 1165         if (oinp)
 1166                 return EADDRINUSE;
 1167         if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
 1168                 inp->in6p_laddr = *addr6;
 1169         inp->in6p_faddr = sin6->sin6_addr;
 1170         inp->inp_fport = sin6->sin6_port;
 1171         /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
 1172         inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
 1173         if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
 1174                 inp->in6p_flowinfo |=
 1175                     (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
 1176         in_pcbrehash(inp);
 1177 
 1178         /* Compute window scaling to request.  */
 1179         while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
 1180             (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
 1181                 tp->request_r_scale++;
 1182 
 1183         soisconnecting(so);
 1184         tcpstat.tcps_connattempt++;
 1185         tp->t_state = TCPS_SYN_SENT;
 1186         tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
 1187         tp->iss = tcp_new_isn(tp);
 1188         tp->t_bw_rtseq = tp->iss;
 1189         tcp_sendseqinit(tp);
 1190 
 1191         return 0;
 1192 }
 1193 #endif /* INET6 */
 1194 
 1195 /*
 1196  * Export TCP internal state information via a struct tcp_info, based on the
 1197  * Linux 2.6 API.  Not ABI compatible as our constants are mapped differently
 1198  * (TCP state machine, etc).  We export all information using FreeBSD-native
 1199  * constants -- for example, the numeric values for tcpi_state will differ
 1200  * from Linux.
 1201  */
 1202 static void
 1203 tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
 1204 {
 1205 
 1206         INP_LOCK_ASSERT(tp->t_inpcb);
 1207         bzero(ti, sizeof(*ti));
 1208 
 1209         ti->tcpi_state = tp->t_state;
 1210         if ((tp->t_flags & TF_REQ_TSTMP) && (tp->t_flags & TF_RCVD_TSTMP))
 1211                 ti->tcpi_options |= TCPI_OPT_TIMESTAMPS;
 1212         if (tp->t_flags & TF_SACK_PERMIT)
 1213                 ti->tcpi_options |= TCPI_OPT_SACK;
 1214         if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) {
 1215                 ti->tcpi_options |= TCPI_OPT_WSCALE;
 1216                 ti->tcpi_snd_wscale = tp->snd_scale;
 1217                 ti->tcpi_rcv_wscale = tp->rcv_scale;
 1218         }
 1219 
 1220         ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT;
 1221         ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT;
 1222 
 1223         ti->tcpi_snd_ssthresh = tp->snd_ssthresh;
 1224         ti->tcpi_snd_cwnd = tp->snd_cwnd;
 1225 
 1226         /*
 1227          * FreeBSD-specific extension fields for tcp_info.
 1228          */
 1229         ti->tcpi_rcv_space = tp->rcv_wnd;
 1230         ti->tcpi_snd_wnd = tp->snd_wnd;
 1231         ti->tcpi_snd_bwnd = tp->snd_bwnd;
 1232 }
 1233 
 1234 /*
 1235  * The new sockopt interface makes it possible for us to block in the
 1236  * copyin/out step (if we take a page fault).  Taking a page fault at
 1237  * splnet() is probably a Bad Thing.  (Since sockets and pcbs both now
 1238  * use TSM, there probably isn't any need for this function to run at
 1239  * splnet() any more.  This needs more examination.)
 1240  *
 1241  * XXXRW: The locking here is wrong; we may take a page fault while holding
 1242  * the inpcb lock.
 1243  */
 1244 int
 1245 tcp_ctloutput(struct socket *so, struct sockopt *sopt)
 1246 {
 1247         int     error, opt, optval;
 1248         struct  inpcb *inp;
 1249         struct  tcpcb *tp;
 1250         struct  tcp_info ti;
 1251 
 1252         error = 0;
 1253         inp = sotoinpcb(so);
 1254         KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
 1255         INP_LOCK(inp);
 1256         if (sopt->sopt_level != IPPROTO_TCP) {
 1257                 INP_UNLOCK(inp);
 1258 #ifdef INET6
 1259                 if (INP_CHECK_SOCKAF(so, AF_INET6))
 1260                         error = ip6_ctloutput(so, sopt);
 1261                 else
 1262 #endif /* INET6 */
 1263                 error = ip_ctloutput(so, sopt);
 1264                 return (error);
 1265         }
 1266         if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
 1267                 error = ECONNRESET;
 1268                 goto out;
 1269         }
 1270         tp = intotcpcb(inp);
 1271 
 1272         switch (sopt->sopt_dir) {
 1273         case SOPT_SET:
 1274                 switch (sopt->sopt_name) {
 1275 #ifdef TCP_SIGNATURE
 1276                 case TCP_MD5SIG:
 1277                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1278                                             sizeof optval);
 1279                         if (error)
 1280                                 break;
 1281 
 1282                         if (optval > 0)
 1283                                 tp->t_flags |= TF_SIGNATURE;
 1284                         else
 1285                                 tp->t_flags &= ~TF_SIGNATURE;
 1286                         break;
 1287 #endif /* TCP_SIGNATURE */
 1288                 case TCP_NODELAY:
 1289                 case TCP_NOOPT:
 1290                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1291                                             sizeof optval);
 1292                         if (error)
 1293                                 break;
 1294 
 1295                         switch (sopt->sopt_name) {
 1296                         case TCP_NODELAY:
 1297                                 opt = TF_NODELAY;
 1298                                 break;
 1299                         case TCP_NOOPT:
 1300                                 opt = TF_NOOPT;
 1301                                 break;
 1302                         default:
 1303                                 opt = 0; /* dead code to fool gcc */
 1304                                 break;
 1305                         }
 1306 
 1307                         if (optval)
 1308                                 tp->t_flags |= opt;
 1309                         else
 1310                                 tp->t_flags &= ~opt;
 1311                         break;
 1312 
 1313                 case TCP_NOPUSH:
 1314                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1315                                             sizeof optval);
 1316                         if (error)
 1317                                 break;
 1318 
 1319                         if (optval)
 1320                                 tp->t_flags |= TF_NOPUSH;
 1321                         else {
 1322                                 tp->t_flags &= ~TF_NOPUSH;
 1323                                 error = tcp_output(tp);
 1324                         }
 1325                         break;
 1326 
 1327                 case TCP_MAXSEG:
 1328                         error = sooptcopyin(sopt, &optval, sizeof optval,
 1329                                             sizeof optval);
 1330                         if (error)
 1331                                 break;
 1332 
 1333                         if (optval > 0 && optval <= tp->t_maxseg &&
 1334                             optval + 40 >= tcp_minmss)
 1335                                 tp->t_maxseg = optval;
 1336                         else
 1337                                 error = EINVAL;
 1338                         break;
 1339 
 1340                 case TCP_INFO:
 1341                         error = EINVAL;
 1342                         break;
 1343 
 1344                 default:
 1345                         error = ENOPROTOOPT;
 1346                         break;
 1347                 }
 1348                 break;
 1349 
 1350         case SOPT_GET:
 1351                 switch (sopt->sopt_name) {
 1352 #ifdef TCP_SIGNATURE
 1353                 case TCP_MD5SIG:
 1354                         optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
 1355                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1356                         break;
 1357 #endif
 1358                 case TCP_NODELAY:
 1359                         optval = tp->t_flags & TF_NODELAY;
 1360                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1361                         break;
 1362                 case TCP_MAXSEG:
 1363                         optval = tp->t_maxseg;
 1364                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1365                         break;
 1366                 case TCP_NOOPT:
 1367                         optval = tp->t_flags & TF_NOOPT;
 1368                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1369                         break;
 1370                 case TCP_NOPUSH:
 1371                         optval = tp->t_flags & TF_NOPUSH;
 1372                         error = sooptcopyout(sopt, &optval, sizeof optval);
 1373                         break;
 1374                 case TCP_INFO:
 1375                         tcp_fill_info(tp, &ti);
 1376                         error = sooptcopyout(sopt, &ti, sizeof ti);
 1377                         break;
 1378                 default:
 1379                         error = ENOPROTOOPT;
 1380                         break;
 1381                 }
 1382                 break;
 1383         }
 1384 out:
 1385         INP_UNLOCK(inp);
 1386         return (error);
 1387 }
 1388 
 1389 /*
 1390  * tcp_sendspace and tcp_recvspace are the default send and receive window
 1391  * sizes, respectively.  These are obsolescent (this information should
 1392  * be set by the route).
 1393  */
 1394 u_long  tcp_sendspace = 1024*32;
 1395 SYSCTL_ULONG(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, CTLFLAG_RW,
 1396     &tcp_sendspace , 0, "Maximum outgoing TCP datagram size");
 1397 u_long  tcp_recvspace = 1024*64;
 1398 SYSCTL_ULONG(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
 1399     &tcp_recvspace , 0, "Maximum incoming TCP datagram size");
 1400 
 1401 /*
 1402  * Attach TCP protocol to socket, allocating
 1403  * internet protocol control block, tcp control block,
 1404  * bufer space, and entering LISTEN state if to accept connections.
 1405  */
 1406 static int
 1407 tcp_attach(struct socket *so)
 1408 {
 1409         struct tcpcb *tp;
 1410         struct inpcb *inp;
 1411         int error;
 1412 #ifdef INET6
 1413         int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != 0;
 1414 #endif
 1415 
 1416         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
 1417                 error = soreserve(so, tcp_sendspace, tcp_recvspace);
 1418                 if (error)
 1419                         return (error);
 1420         }
 1421         so->so_rcv.sb_flags |= SB_AUTOSIZE;
 1422         so->so_snd.sb_flags |= SB_AUTOSIZE;
 1423         INP_INFO_WLOCK(&tcbinfo);
 1424         error = in_pcballoc(so, &tcbinfo);
 1425         if (error) {
 1426                 INP_INFO_WUNLOCK(&tcbinfo);
 1427                 return (error);
 1428         }
 1429         inp = sotoinpcb(so);
 1430 #ifdef INET6
 1431         if (isipv6) {
 1432                 inp->inp_vflag |= INP_IPV6;
 1433                 inp->in6p_hops = -1;    /* use kernel default */
 1434         }
 1435         else
 1436 #endif
 1437         inp->inp_vflag |= INP_IPV4;
 1438         tp = tcp_newtcpcb(inp);
 1439         if (tp == NULL) {
 1440 #ifdef INET6
 1441                 if (isipv6) {
 1442                         in6_pcbdetach(inp);
 1443                         in6_pcbfree(inp);
 1444                 } else {
 1445 #endif
 1446                         in_pcbdetach(inp);
 1447                         in_pcbfree(inp);
 1448 #ifdef INET6
 1449                 }
 1450 #endif
 1451                 INP_INFO_WUNLOCK(&tcbinfo);
 1452                 return (ENOBUFS);
 1453         }
 1454         tp->t_state = TCPS_CLOSED;
 1455         INP_UNLOCK(inp);
 1456         INP_INFO_WUNLOCK(&tcbinfo);
 1457         return (0);
 1458 }
 1459 
 1460 /*
 1461  * Initiate (or continue) disconnect.
 1462  * If embryonic state, just send reset (once).
 1463  * If in ``let data drain'' option and linger null, just drop.
 1464  * Otherwise (hard), mark socket disconnecting and drop
 1465  * current input data; switch states based on user close, and
 1466  * send segment to peer (with FIN).
 1467  */
 1468 static void
 1469 tcp_disconnect(struct tcpcb *tp)
 1470 {
 1471         struct inpcb *inp = tp->t_inpcb;
 1472         struct socket *so = inp->inp_socket;
 1473 
 1474         INP_INFO_WLOCK_ASSERT(&tcbinfo);
 1475         INP_LOCK_ASSERT(inp);
 1476 
 1477         /*
 1478          * Neither tcp_close() nor tcp_drop() should return NULL, as the
 1479          * socket is still open.
 1480          */
 1481         if (tp->t_state < TCPS_ESTABLISHED) {
 1482                 tp = tcp_close(tp);
 1483                 KASSERT(tp != NULL,
 1484                     ("tcp_disconnect: tcp_close() returned NULL"));
 1485         } else if ((so->so_options & SO_LINGER) && so->so_linger == 0) {
 1486                 tp = tcp_drop(tp, 0);
 1487                 KASSERT(tp != NULL,
 1488                     ("tcp_disconnect: tcp_drop() returned NULL"));
 1489         } else {
 1490                 soisdisconnecting(so);
 1491                 sbflush(&so->so_rcv);
 1492                 tcp_usrclosed(tp);
 1493                 if (!(inp->inp_vflag & INP_DROPPED))
 1494                         tcp_output(tp);
 1495         }
 1496 }
 1497 
 1498 /*
 1499  * User issued close, and wish to trail through shutdown states:
 1500  * if never received SYN, just forget it.  If got a SYN from peer,
 1501  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
 1502  * If already got a FIN from peer, then almost done; go to LAST_ACK
 1503  * state.  In all other cases, have already sent FIN to peer (e.g.
 1504  * after PRU_SHUTDOWN), and just have to play tedious game waiting
 1505  * for peer to send FIN or not respond to keep-alives, etc.
 1506  * We can let the user exit from the close as soon as the FIN is acked.
 1507  */
 1508 static void
 1509 tcp_usrclosed(struct tcpcb *tp)
 1510 {
 1511 
 1512         INP_INFO_WLOCK_ASSERT(&tcbinfo);
 1513         INP_LOCK_ASSERT(tp->t_inpcb);
 1514 
 1515         switch (tp->t_state) {
 1516         case TCPS_CLOSED:
 1517         case TCPS_LISTEN:
 1518                 tp->t_state = TCPS_CLOSED;
 1519                 tp = tcp_close(tp);
 1520                 /*
 1521                  * tcp_close() should never return NULL here as the socket is
 1522                  * still open.
 1523                  */
 1524                 KASSERT(tp != NULL,
 1525                     ("tcp_usrclosed: tcp_close() returned NULL"));
 1526                 break;
 1527 
 1528         case TCPS_SYN_SENT:
 1529         case TCPS_SYN_RECEIVED:
 1530                 tp->t_flags |= TF_NEEDFIN;
 1531                 break;
 1532 
 1533         case TCPS_ESTABLISHED:
 1534                 tp->t_state = TCPS_FIN_WAIT_1;
 1535                 break;
 1536 
 1537         case TCPS_CLOSE_WAIT:
 1538                 tp->t_state = TCPS_LAST_ACK;
 1539                 break;
 1540         }
 1541         if (tp->t_state >= TCPS_FIN_WAIT_2) {
 1542                 soisdisconnected(tp->t_inpcb->inp_socket);
 1543                 /* Prevent the connection hanging in FIN_WAIT_2 forever. */
 1544                 if (tp->t_state == TCPS_FIN_WAIT_2) {
 1545                         int timeout;
 1546 
 1547                         timeout = (tcp_fast_finwait2_recycle) ? 
 1548                             tcp_finwait2_timeout : tcp_maxidle;
 1549                         tcp_timer_activate(tp, TT_2MSL, timeout);
 1550                 }
 1551         }
 1552 }
 1553 
 1554 #ifdef DDB
 1555 static void
 1556 db_print_indent(int indent)
 1557 {
 1558         int i;
 1559 
 1560         for (i = 0; i < indent; i++)
 1561                 db_printf(" ");
 1562 }
 1563 
 1564 static void
 1565 db_print_tstate(int t_state)
 1566 {
 1567 
 1568         switch (t_state) {
 1569         case TCPS_CLOSED:
 1570                 db_printf("TCPS_CLOSED");
 1571                 return;
 1572 
 1573         case TCPS_LISTEN:
 1574                 db_printf("TCPS_LISTEN");
 1575                 return;
 1576 
 1577         case TCPS_SYN_SENT:
 1578                 db_printf("TCPS_SYN_SENT");
 1579                 return;
 1580 
 1581         case TCPS_SYN_RECEIVED:
 1582                 db_printf("TCPS_SYN_RECEIVED");
 1583                 return;
 1584 
 1585         case TCPS_ESTABLISHED:
 1586                 db_printf("TCPS_ESTABLISHED");
 1587                 return;
 1588 
 1589         case TCPS_CLOSE_WAIT:
 1590                 db_printf("TCPS_CLOSE_WAIT");
 1591                 return;
 1592 
 1593         case TCPS_FIN_WAIT_1:
 1594                 db_printf("TCPS_FIN_WAIT_1");
 1595                 return;
 1596 
 1597         case TCPS_CLOSING:
 1598                 db_printf("TCPS_CLOSING");
 1599                 return;
 1600 
 1601         case TCPS_LAST_ACK:
 1602                 db_printf("TCPS_LAST_ACK");
 1603                 return;
 1604 
 1605         case TCPS_FIN_WAIT_2:
 1606                 db_printf("TCPS_FIN_WAIT_2");
 1607                 return;
 1608 
 1609         case TCPS_TIME_WAIT:
 1610                 db_printf("TCPS_TIME_WAIT");
 1611                 return;
 1612 
 1613         default:
 1614                 db_printf("unknown");
 1615                 return;
 1616         }
 1617 }
 1618 
 1619 static void
 1620 db_print_tflags(u_int t_flags)
 1621 {
 1622         int comma;
 1623 
 1624         comma = 0;
 1625         if (t_flags & TF_ACKNOW) {
 1626                 db_printf("%sTF_ACKNOW", comma ? ", " : "");
 1627                 comma = 1;
 1628         }
 1629         if (t_flags & TF_DELACK) {
 1630                 db_printf("%sTF_DELACK", comma ? ", " : "");
 1631                 comma = 1;
 1632         }
 1633         if (t_flags & TF_NODELAY) {
 1634                 db_printf("%sTF_NODELAY", comma ? ", " : "");
 1635                 comma = 1;
 1636         }
 1637         if (t_flags & TF_NOOPT) {
 1638                 db_printf("%sTF_NOOPT", comma ? ", " : "");
 1639                 comma = 1;
 1640         }
 1641         if (t_flags & TF_SENTFIN) {
 1642                 db_printf("%sTF_SENTFIN", comma ? ", " : "");
 1643                 comma = 1;
 1644         }
 1645         if (t_flags & TF_REQ_SCALE) {
 1646                 db_printf("%sTF_REQ_SCALE", comma ? ", " : "");
 1647                 comma = 1;
 1648         }
 1649         if (t_flags & TF_RCVD_SCALE) {
 1650                 db_printf("%sTF_RECVD_SCALE", comma ? ", " : "");
 1651                 comma = 1;
 1652         }
 1653         if (t_flags & TF_REQ_TSTMP) {
 1654                 db_printf("%sTF_REQ_TSTMP", comma ? ", " : "");
 1655                 comma = 1;
 1656         }
 1657         if (t_flags & TF_RCVD_TSTMP) {
 1658                 db_printf("%sTF_RCVD_TSTMP", comma ? ", " : "");
 1659                 comma = 1;
 1660         }
 1661         if (t_flags & TF_SACK_PERMIT) {
 1662                 db_printf("%sTF_SACK_PERMIT", comma ? ", " : "");
 1663                 comma = 1;
 1664         }
 1665         if (t_flags & TF_NEEDSYN) {
 1666                 db_printf("%sTF_NEEDSYN", comma ? ", " : "");
 1667                 comma = 1;
 1668         }
 1669         if (t_flags & TF_NEEDFIN) {
 1670                 db_printf("%sTF_NEEDFIN", comma ? ", " : "");
 1671                 comma = 1;
 1672         }
 1673         if (t_flags & TF_NOPUSH) {
 1674                 db_printf("%sTF_NOPUSH", comma ? ", " : "");
 1675                 comma = 1;
 1676         }
 1677         if (t_flags & TF_NOPUSH) {
 1678                 db_printf("%sTF_NOPUSH", comma ? ", " : "");
 1679                 comma = 1;
 1680         }
 1681         if (t_flags & TF_MORETOCOME) {
 1682                 db_printf("%sTF_MORETOCOME", comma ? ", " : "");
 1683                 comma = 1;
 1684         }
 1685         if (t_flags & TF_LQ_OVERFLOW) {
 1686                 db_printf("%sTF_LQ_OVERFLOW", comma ? ", " : "");
 1687                 comma = 1;
 1688         }
 1689         if (t_flags & TF_LASTIDLE) {
 1690                 db_printf("%sTF_LASTIDLE", comma ? ", " : "");
 1691                 comma = 1;
 1692         }
 1693         if (t_flags & TF_RXWIN0SENT) {
 1694                 db_printf("%sTF_RXWIN0SENT", comma ? ", " : "");
 1695                 comma = 1;
 1696         }
 1697         if (t_flags & TF_FASTRECOVERY) {
 1698                 db_printf("%sTF_FASTRECOVERY", comma ? ", " : "");
 1699                 comma = 1;
 1700         }
 1701         if (t_flags & TF_WASFRECOVERY) {
 1702                 db_printf("%sTF_WASFRECOVERY", comma ? ", " : "");
 1703                 comma = 1;
 1704         }
 1705         if (t_flags & TF_SIGNATURE) {
 1706                 db_printf("%sTF_SIGNATURE", comma ? ", " : "");
 1707                 comma = 1;
 1708         }
 1709         if (t_flags & TF_FORCEDATA) {
 1710                 db_printf("%sTF_FORCEDATA", comma ? ", " : "");
 1711                 comma = 1;
 1712         }
 1713         if (t_flags & TF_TSO) {
 1714                 db_printf("%sTF_TSO", comma ? ", " : "");
 1715                 comma = 1;
 1716         }
 1717 }
 1718 
 1719 static void
 1720 db_print_toobflags(char t_oobflags)
 1721 {
 1722         int comma;
 1723 
 1724         comma = 0;
 1725         if (t_oobflags & TCPOOB_HAVEDATA) {
 1726                 db_printf("%sTCPOOB_HAVEDATA", comma ? ", " : "");
 1727                 comma = 1;
 1728         }
 1729         if (t_oobflags & TCPOOB_HADDATA) {
 1730                 db_printf("%sTCPOOB_HADDATA", comma ? ", " : "");
 1731                 comma = 1;
 1732         }
 1733 }
 1734 
 1735 static void
 1736 db_print_tcpcb(struct tcpcb *tp, const char *name, int indent)
 1737 {
 1738 
 1739         db_print_indent(indent);
 1740         db_printf("%s at %p\n", name, tp);
 1741 
 1742         indent += 2;
 1743 
 1744         db_print_indent(indent);
 1745         db_printf("t_segq first: %p   t_segqlen: %d   t_dupacks: %d\n",
 1746            LIST_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks);
 1747 
 1748         db_print_indent(indent);
 1749         db_printf("tt_rexmt: %p   tt_persist: %p   tt_keep: %p\n",
 1750             &tp->t_timers->tt_rexmt, &tp->t_timers->tt_persist, &tp->t_timers->tt_keep);
 1751 
 1752         db_print_indent(indent);
 1753         db_printf("tt_2msl: %p   tt_delack: %p   t_inpcb: %p\n", &tp->t_timers->tt_2msl,
 1754             &tp->t_timers->tt_delack, tp->t_inpcb);
 1755 
 1756         db_print_indent(indent);
 1757         db_printf("t_state: %d (", tp->t_state);
 1758         db_print_tstate(tp->t_state);
 1759         db_printf(")\n");
 1760 
 1761         db_print_indent(indent);
 1762         db_printf("t_flags: 0x%x (", tp->t_flags);
 1763         db_print_tflags(tp->t_flags);
 1764         db_printf(")\n");
 1765 
 1766         db_print_indent(indent);
 1767         db_printf("snd_una: 0x%08x   snd_max: 0x%08x   snd_nxt: x0%08x\n",
 1768             tp->snd_una, tp->snd_max, tp->snd_nxt);
 1769 
 1770         db_print_indent(indent);
 1771         db_printf("snd_up: 0x%08x   snd_wl1: 0x%08x   snd_wl2: 0x%08x\n",
 1772            tp->snd_up, tp->snd_wl1, tp->snd_wl2);
 1773 
 1774         db_print_indent(indent);
 1775         db_printf("iss: 0x%08x   irs: 0x%08x   rcv_nxt: 0x%08x\n",
 1776             tp->iss, tp->irs, tp->rcv_nxt);
 1777 
 1778         db_print_indent(indent);
 1779         db_printf("rcv_adv: 0x%08x   rcv_wnd: %lu   rcv_up: 0x%08x\n",
 1780             tp->rcv_adv, tp->rcv_wnd, tp->rcv_up);
 1781 
 1782         db_print_indent(indent);
 1783         db_printf("snd_wnd: %lu   snd_cwnd: %lu   snd_bwnd: %lu\n",
 1784            tp->snd_wnd, tp->snd_cwnd, tp->snd_bwnd);
 1785 
 1786         db_print_indent(indent);
 1787         db_printf("snd_ssthresh: %lu   snd_bandwidth: %lu   snd_recover: "
 1788             "0x%08x\n", tp->snd_ssthresh, tp->snd_bandwidth,
 1789             tp->snd_recover);
 1790 
 1791         db_print_indent(indent);
 1792         db_printf("t_maxopd: %u   t_rcvtime: %lu   t_startime: %lu\n",
 1793             tp->t_maxopd, tp->t_rcvtime, tp->t_starttime);
 1794 
 1795         db_print_indent(indent);
 1796         db_printf("t_rttime: %d   t_rtsq: 0x%08x   t_bw_rtttime: %d\n",
 1797             tp->t_rtttime, tp->t_rtseq, tp->t_bw_rtttime);
 1798 
 1799         db_print_indent(indent);
 1800         db_printf("t_bw_rtseq: 0x%08x   t_rxtcur: %d   t_maxseg: %u   "
 1801             "t_srtt: %d\n", tp->t_bw_rtseq, tp->t_rxtcur, tp->t_maxseg,
 1802             tp->t_srtt);
 1803 
 1804         db_print_indent(indent);
 1805         db_printf("t_rttvar: %d   t_rxtshift: %d   t_rttmin: %u   "
 1806             "t_rttbest: %u\n", tp->t_rttvar, tp->t_rxtshift, tp->t_rttmin,
 1807             tp->t_rttbest);
 1808 
 1809         db_print_indent(indent);
 1810         db_printf("t_rttupdated: %lu   max_sndwnd: %lu   t_softerror: %d\n",
 1811             tp->t_rttupdated, tp->max_sndwnd, tp->t_softerror);
 1812 
 1813         db_print_indent(indent);
 1814         db_printf("t_oobflags: 0x%x (", tp->t_oobflags);
 1815         db_print_toobflags(tp->t_oobflags);
 1816         db_printf(")   t_iobc: 0x%02x\n", tp->t_iobc);
 1817 
 1818         db_print_indent(indent);
 1819         db_printf("snd_scale: %u   rcv_scale: %u   request_r_scale: %u\n",
 1820             tp->snd_scale, tp->rcv_scale, tp->request_r_scale);
 1821 
 1822         db_print_indent(indent);
 1823         db_printf("ts_recent: %u   ts_recent_age: %lu\n",
 1824             tp->ts_recent, tp->ts_recent_age);
 1825 
 1826         db_print_indent(indent);
 1827         db_printf("ts_offset: %u   last_ack_sent: 0x%08x   snd_cwnd_prev: "
 1828             "%lu\n", tp->ts_offset, tp->last_ack_sent, tp->snd_cwnd_prev);
 1829 
 1830         db_print_indent(indent);
 1831         db_printf("snd_ssthresh_prev: %lu   snd_recover_prev: 0x%08x   "
 1832             "t_badrxtwin: %lu\n", tp->snd_ssthresh_prev,
 1833             tp->snd_recover_prev, tp->t_badrxtwin);
 1834 
 1835         db_print_indent(indent);
 1836         db_printf("snd_numholes: %d  snd_holes first: %p\n",
 1837             tp->snd_numholes, TAILQ_FIRST(&tp->snd_holes));
 1838 
 1839         db_print_indent(indent);
 1840         db_printf("snd_fack: 0x%08x   rcv_numsacks: %d   sack_newdata: "
 1841             "0x%08x\n", tp->snd_fack, tp->rcv_numsacks, tp->sack_newdata);
 1842 
 1843         /* Skip sackblks, sackhint. */
 1844 
 1845         db_print_indent(indent);
 1846         db_printf("t_rttlow: %d   rfbuf_ts: %u   rfbuf_cnt: %d\n",
 1847             tp->t_rttlow, tp->rfbuf_ts, tp->rfbuf_cnt);
 1848 }
 1849 
 1850 DB_SHOW_COMMAND(tcpcb, db_show_tcpcb)
 1851 {
 1852         struct tcpcb *tp;
 1853 
 1854         if (!have_addr) {
 1855                 db_printf("usage: show tcpcb <addr>\n");
 1856                 return;
 1857         }
 1858         tp = (struct tcpcb *)addr;
 1859 
 1860         db_print_tcpcb(tp, "tcpcb", 0);
 1861 }
 1862 #endif

Cache object: af2d141248d7abc2f1c6452d64da1f23


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.