File:  [DragonFly] / src / sys / netinet / tcp_usrreq.c
Revision 1.17: download - view: text, annotated - select for diffs
Wed Apr 21 18:13:56 2004 UTC (10 years, 7 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Fix a netmsg memory leak in the ARP code.  Adjust all ms_cmd function
dispatches to return a proper error code.

Reported-by: multiple people

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