xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 4809)
1*4809Swnj /* tcp_usrreq.c 1.26 81/11/08 */
24567Swnj 
34497Swnj #include "../h/param.h"
44567Swnj #include "../h/systm.h"
54664Swnj #include "../h/mbuf.h"
64664Swnj #include "../h/socket.h"
7*4809Swnj #include "../h/socketvar.h"
8*4809Swnj #include "../h/protosw.h"
9*4809Swnj #include "../net/inet.h"
10*4809Swnj #include "../net/inet_systm.h"
11*4809Swnj #include "../net/imp.h"
12*4809Swnj #include "../net/ip.h"
13*4809Swnj #include "../net/tcp.h"
144567Swnj #define TCPFSTAB
154584Swnj #ifdef TCPDEBUG
164584Swnj #define TCPSTATES
174584Swnj #endif
18*4809Swnj #include "../net/tcp_fsm.h"
19*4809Swnj #include "../net/tcp_var.h"
20*4809Swnj #include "/usr/include/errno.h"
214497Swnj 
22*4809Swnj struct	tcb *tcp_attach();
23*4809Swnj 
244734Swnj /*
25*4809Swnj  * Tcp initialization
26*4809Swnj  */
27*4809Swnj tcp_init()
28*4809Swnj {
29*4809Swnj 
30*4809Swnj 	tcp_iss = 1;		/* wrong */
31*4809Swnj 	tcb.tcb_next = tcb.tcb_prev = (struct tcb *)&tcb;
32*4809Swnj }
33*4809Swnj 
34*4809Swnj /*
354734Swnj  * Tcp finite state machine entries for timer and user generated
364734Swnj  * requests.  These routines raise the ipl to that of the network
374734Swnj  * to prevent reentry.  In particluar, this requires that the software
384734Swnj  * clock interrupt have lower priority than the network so that
394734Swnj  * we can enter the network from timeout routines without improperly
404734Swnj  * nesting the interrupt stack.
414734Swnj  */
424734Swnj 
434734Swnj /*
44*4809Swnj  * Tcp protocol timeout routine called every 500 ms.
454734Swnj  * Updates the timers in all active tcb's and
464734Swnj  * causes finite state machine actions if timers expire.
474734Swnj  */
48*4809Swnj tcp_slowtimo()
494497Swnj {
504567Swnj 	register struct tcb *tp;
514567Swnj 	int s = splnet();
52*4809Swnj 	register short *tmp;
534731Swnj 	register int i;
544567Swnj COUNT(TCP_TIMEO);
554497Swnj 
564567Swnj 	/*
574567Swnj 	 * Search through tcb's and update active timers.
584567Swnj 	 */
59*4809Swnj 	tp = tcb.tcb_next;
60*4809Swnj 	for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) {
614731Swnj 		tmp = &tp->t_init;
624735Swnj 		for (i = 0; i < TNTIMERS; i++) {
634731Swnj 			if (*tmp && --*tmp == 0)
64*4809Swnj 				tcp_usrreq(tp->t_socket, PRU_SLOWTIMO, 0, i);
654735Swnj 			tmp++;
664735Swnj 		}
674567Swnj 		tp->t_xmt++;
684567Swnj 	}
69*4809Swnj 	tcp_iss += ISSINCR/2;		/* increment iss */
704567Swnj 	splx(s);
714497Swnj }
724497Swnj 
734731Swnj /*
744734Swnj  * Cancel all timers for tcp tp.
754734Swnj  */
764734Swnj tcp_tcancel(tp)
774734Swnj 	struct tcb *tp;
784734Swnj {
79*4809Swnj 	register short *tmp = &tp->t_init;
804734Swnj 	register int i;
814734Swnj 
824734Swnj 	for (i = 0; i < TNTIMERS; i++)
834734Swnj 		*tmp++ = 0;
844734Swnj }
854734Swnj 
864734Swnj /*
874731Swnj  * Process a TCP user request for tcp tb.  If this is a send request
884731Swnj  * then m is the mbuf chain of send data.  If this is a timer expiration
894731Swnj  * (called from the software clock routine), then timertype tells which timer.
904731Swnj  */
91*4809Swnj tcp_usrreq(so, req, m, addr)
92*4809Swnj 	struct socket *so;
93*4809Swnj 	int req;
944731Swnj 	struct mbuf *m;
95*4809Swnj 	caddr_t addr;
964497Swnj {
97*4809Swnj 	register struct tcb *tp = (struct tcb *)so->so_pcb;
984567Swnj 	int s = splnet();
994567Swnj 	register int nstate;
1004584Swnj #ifdef TCPDEBUG
1014584Swnj 	struct tcp_debug tdb;
1024584Swnj #endif
103*4809Swnj 	int error = 0;
1044567Swnj COUNT(TCP_USRREQ);
1054497Swnj 
106*4809Swnj 	if (tp) {
107*4809Swnj 		nstate = tp->t_state;
108*4809Swnj 		tp->tc_flags &= ~TC_NET_KEEP;
109*4809Swnj 	} else
110*4809Swnj 		if (req != PRU_ATTACH)
111*4809Swnj 			return (ENOTCONN);
1124731Swnj #ifdef KPROF
113*4809Swnj 	acounts[nstate][req]++;
1144731Swnj #endif
1154584Swnj #ifdef TCPDEBUG
116*4809Swnj 	if (tp && ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug)) {
117*4809Swnj 		tdb_setup(tp, (struct th *)0, req, &tdb);
1184584Swnj 		tdb.td_tim = timertype;
1194584Swnj 	} else
1204584Swnj 		tdb.td_tod = 0;
1214584Swnj #endif
122*4809Swnj 	switch (req) {
1234497Swnj 
1244731Swnj 	/*
125*4809Swnj 	 * Attach a tcp control block to this socket.
126*4809Swnj 	 * TCP is not multicast, so this is possible
127*4809Swnj 	 * only if no connection currently exists.
1284731Swnj 	 */
129*4809Swnj 	case PRU_ATTACH:
130*4809Swnj 		if (tp)
131*4809Swnj 			error = EISCONN;
132*4809Swnj 		else
133*4809Swnj 			tp = tcp_attach(so, &error);
134*4809Swnj 		nstate = CLOSED;
1354567Swnj 		break;
1364497Swnj 
1374731Swnj 	/*
138*4809Swnj 	 * Detach the TCP from this socket.  This
139*4809Swnj 	 * is possible only if a connection currently exists.
1404731Swnj 	 */
141*4809Swnj 	case PRU_DETACH:
142*4809Swnj 		so->so_pcb = 0;
143*4809Swnj 		break;
144*4809Swnj 
145*4809Swnj 	/*
146*4809Swnj 	 * Form connection: send a SYN.
147*4809Swnj 	 */
148*4809Swnj 	case PRU_CONNECT:
1494731Swnj 		if (nstate != 0 && nstate != CLOSED)
1504731Swnj 			goto bad;
1514676Swnj 		tcp_sndctl(tp);
1524567Swnj 		nstate = SYN_SENT;
1534567Swnj 		break;
1544497Swnj 
155*4809Swnj 	case PRU_DISCONNECT:
156*4809Swnj 		so->so_pcb = 0;
157*4809Swnj 		tcp_destroy(tp);
158*4809Swnj 		break;
159*4809Swnj 
1604731Swnj 	/*
161*4809Swnj 	 * Declare no further transmissions.
162*4809Swnj 	 * Can be generated by a user ioctl (half-close),
1634731Swnj 	 * or when higher level close occurs, if a close hasn't happened
1644731Swnj 	 * already.
1654731Swnj 	 */
166*4809Swnj 	case PRU_SHUTDOWN:
1674731Swnj 		switch (nstate) {
1684497Swnj 
1694731Swnj 		/*
1704731Swnj 		 * If we are aborting out of a listener or a active
1714731Swnj 		 * connection which has not yet completed we can just
1724731Swnj 		 * delete the tcb.
1734731Swnj 		 */
1744731Swnj 		case LISTEN:
1754734Swnj 		case SYN_SENT:
1764731Swnj 			nstate = CLOSED;
1774731Swnj 			break;
1784731Swnj 
1794731Swnj 		/*
1804731Swnj 		 * If we have gotten as far as receiving a syn from
1814731Swnj 		 * our foreign peer, we must be sure to send a FIN.
1824731Swnj 		 * If we have gotten a FIN from the foreign peer already
1834731Swnj 		 * (CLOSE_WAIT state), then all that remains is to wait
1844731Swnj 		 * for his ack of the FIN (LAST_ACK state).  If we have
1854731Swnj 		 * not gotten a FIN from the foreign peer then we need
1864731Swnj 		 * to either:
1874731Swnj 		 *	1. rcv ack of our FIN (to FIN_W2) and then
1884731Swnj 		 *	   send an ACK (to TIME_WAIT) and timeout at 2*MSL.
1894731Swnj 		 * or	2. receive hist FIN (to CLOSING), send an ACK
1904731Swnj 		 *	   (to TIME_WAIT), and then timeout.
1914731Swnj 		 * In any case this starts with a transition to FIN_W1 here.
1924731Swnj 		 */
1934734Swnj 		case SYN_RCVD:
1944731Swnj 		case L_SYN_RCVD:
1954731Swnj 		case ESTAB:
1964734Swnj 		case CLOSE_WAIT:
1974731Swnj 			tp->tc_flags |= TC_SND_FIN;
1984731Swnj 			tcp_sndctl(tp);
1994731Swnj 			tp->tc_flags |= TC_USR_CLOSED;
2004731Swnj 			nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
2014731Swnj 			break;
2024731Swnj 
2034731Swnj 		/*
2044731Swnj 		 * In these states the user has already closed;
2054731Swnj 		 * trying to close again is an error.
2064731Swnj 		 */
2074731Swnj 		case FIN_W1:
2084731Swnj 		case FIN_W2:
2094731Swnj 		case TIME_WAIT:
2104731Swnj 		case CLOSING:
2114731Swnj 		case LAST_ACK:
2124731Swnj 		case RCV_WAIT:
2134731Swnj 			break;
2144731Swnj 
2154731Swnj 		default:
2164731Swnj 			goto bad;
2174731Swnj 		}
2184567Swnj 		break;
2194497Swnj 
2204731Swnj 	/*
2214731Swnj 	 * User notification of more window availability after
2224731Swnj 	 * reading out data.  This should not happen before a connection
2234731Swnj 	 * is established or after it is closed.
2244731Swnj 	 * If the foreign peer has closed and the local entity
2254731Swnj 	 * has not, inform him of the FIN (give end of file).
2264731Swnj 	 * If the local entity is in RCV_WAIT state (draining data
2274731Swnj 	 * out of the TCP buffers after foreign close) and there
2284731Swnj 	 * is no more data, institute a close.
2294731Swnj 	 */
230*4809Swnj 	case PRU_RCVD:
2314731Swnj 		if (nstate < ESTAB || nstate == CLOSED)
2324731Swnj 			goto bad;
2334734Swnj 		tcp_sndwin(tp);
2344691Swnj 		if ((tp->tc_flags&TC_FIN_RCVD) &&
2354691Swnj 		    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
2364691Swnj 		    rcv_empty(tp))
237*4809Swnj 			tcp_error(tp, ESHUTDOWN);
238*4809Swnj 		if (nstate == RCV_WAIT && rcv_empty(tp))
2394567Swnj 			nstate = CLOSED;
2404567Swnj 		break;
2414497Swnj 
2424731Swnj 	/*
2434731Swnj 	 * Send request on open connection.
2444731Swnj 	 * Should not happen if the connection is not yet established.
2454731Swnj 	 * Allowed only on ESTAB connection and after FIN from
2464731Swnj 	 * foreign peer.
2474731Swnj 	 */
248*4809Swnj 	case PRU_SEND:
2494731Swnj 		switch (nstate) {
2504567Swnj 
2514731Swnj 		case ESTAB:
2524731Swnj 		case CLOSE_WAIT:
2534731Swnj 			nstate = tcp_usrsend(tp, m);
2544731Swnj 			break;
2554731Swnj 
2564731Swnj 		default:
2574731Swnj 			if (nstate < ESTAB)
2584731Swnj 				goto bad;
259*4809Swnj 			m_freem(m);
260*4809Swnj 			/* tcp_user(tp, UCLSERR); */
2614731Swnj 			break;
2624731Swnj 		}
2634567Swnj 		break;
2644567Swnj 
2654731Swnj 	/*
2664731Swnj 	 * User abort of connection.
2674731Swnj 	 * If a SYN has been received, but we have not exchanged FINs
2684731Swnj 	 * then we need to send an RST.  In any case we then
2694731Swnj 	 * enter closed state.
2704731Swnj 	 */
271*4809Swnj 	case PRU_ABORT:
2724731Swnj 		if (nstate == 0 || nstate == CLOSED)
2734731Swnj 			break;
2744731Swnj 		switch (nstate) {
2754567Swnj 
2764731Swnj 		case 0:
2774731Swnj 		case CLOSED:
2784731Swnj 			break;
2794567Swnj 
2804731Swnj 		case SYN_RCVD:
2814731Swnj 		case ESTAB:
2824731Swnj 		case FIN_W1:
2834731Swnj 		case FIN_W2:
2844731Swnj 		case CLOSE_WAIT:
2854731Swnj 			tp->tc_flags |= TC_SND_RST;
2864731Swnj 			tcp_sndnull(tp);
2874731Swnj 			/* fall into ... */
2884731Swnj 
2894731Swnj 		default:
2904731Swnj 			nstate = CLOSED;
2914731Swnj 		}
2924567Swnj 		break;
2934567Swnj 
2944731Swnj 	/*
2954731Swnj 	 * Network down entry.  Discard the tcb and force
2964731Swnj 	 * the state to be closed, ungracefully.
2974731Swnj 	 */
298*4809Swnj 	case PRU_CLEAR:
2994731Swnj 		if (nstate == 0 || nstate == CLOSED)
3004731Swnj 			break;
3014567Swnj 		nstate = CLOSED;
3024567Swnj 		break;
3034567Swnj 
304*4809Swnj 	/*
305*4809Swnj 	 * Ioctl on protocols.
306*4809Swnj 	 */
307*4809Swnj 	case PRU_CONTROL:
308*4809Swnj 		break;
309*4809Swnj 
310*4809Swnj 	/*
311*4809Swnj 	 * TCP Timer processing.
312*4809Swnj 	 * Timers should expire only on open connections
313*4809Swnj 	 * not in LISTEN state.
314*4809Swnj 	 */
315*4809Swnj 	case PRU_SLOWTIMO:
316*4809Swnj 		switch (nstate) {
317*4809Swnj 
318*4809Swnj 		case 0:
319*4809Swnj 		case CLOSED:
320*4809Swnj 		case LISTEN:
321*4809Swnj 			goto bad;
322*4809Swnj 
323*4809Swnj 		default:
324*4809Swnj 			nstate = tcp_timers(tp, (int)addr);
325*4809Swnj 		}
326*4809Swnj 		break;
327*4809Swnj 
3284731Swnj 	default:
3294731Swnj 		panic("tcp_usrreq");
3304731Swnj 	bad:
3314731Swnj 		printf("tcp: bad state: tcb=%x state=%d input=%d\n",
332*4809Swnj 		    tp, tp->t_state, req);
3334731Swnj 		nstate = EFAILEC;
3344567Swnj 		break;
3354567Swnj 	}
3364567Swnj #ifdef TCPDEBUG
3374605Swnj 	if (tdb.td_tod)
3384605Swnj 		tdb_stuff(&tdb, nstate);
3394567Swnj #endif
3404567Swnj 	/* YECH */
3414567Swnj 	switch (nstate) {
3424567Swnj 
3434584Swnj 	case CLOSED:
3444567Swnj 	case SAME:
3454567Swnj 		break;
3464567Swnj 
3474567Swnj 	case EFAILEC:
3484731Swnj 		if (m)
3494731Swnj 			m_freem(dtom(m));
3504567Swnj 		break;
3514567Swnj 
3524567Swnj 	default:
3534567Swnj 		tp->t_state = nstate;
3544567Swnj 		break;
3554567Swnj 	}
3564567Swnj 	splx(s);
3574497Swnj }
3584497Swnj 
359*4809Swnj tcp_sense()
360*4809Swnj {
361*4809Swnj 
362*4809Swnj }
363*4809Swnj 
3644682Swnj /*
3654682Swnj  * Open routine, called to initialize newly created tcb fields.
3664682Swnj  */
367*4809Swnj struct tcb *
368*4809Swnj tcp_attach(so)
369*4809Swnj 	register struct socket *so;
370*4809Swnj {
3714567Swnj 	register struct tcb *tp;
372*4809Swnj COUNT(TCP_ATTACH);
3734497Swnj 
3744682Swnj 	/*
3754682Swnj 	 * Link in tcb queue and make
3764682Swnj 	 * initialize empty reassembly queue.
3774682Swnj 	 */
378*4809Swnj 	tp->tcb_hd.tcb_next = tcb.tcb_next;
379*4809Swnj 	tcb.tcb_next->tcb_hd.tcb_prev = tp;
380*4809Swnj 	tp->tcb_hd.tcb_prev = (struct tcb *)&tcb;
3814682Swnj 	tcb.tcb_next = tp;
382*4809Swnj 	tp->tcb_hd.seg_next = tp->tcb_hd.seg_prev = (struct th *)tp;
3834497Swnj 
3844682Swnj 	/*
3854682Swnj 	 * Initialize sequence numbers and
3864682Swnj 	 * round trip retransmit timer.
3874682Swnj 	 * (Other fields were init'd to zero when tcb allocated.)
3884682Swnj 	 */
3894567Swnj 	tp->t_xmtime = T_REXMT;
3904682Swnj 	tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
3914682Swnj 	    tp->iss = tcp_iss;
3924567Swnj 	tp->snd_off = tp->iss + 1;
3934664Swnj 	tcp_iss += (ISSINCR >> 1) + 1;
3944497Swnj }
3954497Swnj 
3964682Swnj /*
397*4809Swnj  * Destroy a tcb.
3984682Swnj  */
399*4809Swnj tcp_detach(tp)
4004567Swnj 	register struct tcb *tp;
4014497Swnj {
402*4809Swnj 	register struct socket *so = tp->t_socket;
4034567Swnj 	register struct th *t;
4044567Swnj 	register struct mbuf *m;
405*4809Swnj COUNT(TCP_DETACH);
4064497Swnj 
4074682Swnj 	/*
4084734Swnj 	 * Remove from tcb queue and cancel timers.
4094682Swnj 	 */
410*4809Swnj 	tp->tcb_hd.tcb_prev->tcb_hd.tcb_next = tp->tcb_hd.tcb_next;
411*4809Swnj 	tp->tcb_hd.tcb_next->tcb_hd.tcb_prev = tp->tcb_hd.tcb_prev;
4124734Swnj 	tcp_tcancel(tp);
4134567Swnj 
4144682Swnj 	/*
4154734Swnj 	 * Discard all buffers.
4164682Swnj 	 */
417*4809Swnj 	for (t = tp->tcb_hd.seg_next; t != (struct th *)tp; t = t->t_next)
4184567Swnj 		m_freem(dtom(t));
419*4809Swnj 	if (so->so_rcv.sb_mb)
420*4809Swnj 	    { m_freem(so->so_rcv.sb_mb); so->so_rcv.sb_mb = 0; }
421*4809Swnj 	so->so_rcv.sb_cc = 0; so->so_rcv.sb_mbcnt = 0;
422*4809Swnj 	if (so->so_snd.sb_mb)
423*4809Swnj 	    { m_freem(so->so_snd.sb_mb); so->so_rcv.sb_mb = 0; }
424*4809Swnj 	so->so_snd.sb_cc = 0; so->so_snd.sb_mbcnt = 0;
425*4809Swnj 
426*4809Swnj 	for (m = tp->seg_unack; m; m = m->m_act)
4274567Swnj 		m_freem(m);
428*4809Swnj 	tp->seg_unack = 0;
429*4809Swnj 
430*4809Swnj 	/*
431*4809Swnj 	 * Free routing table entry.
432*4809Swnj 	 */
433*4809Swnj 	if (tp->t_host) {
434*4809Swnj 		h_free(tp->t_host);
435*4809Swnj 		tp->t_host = 0;
4364567Swnj 	}
4374682Swnj 
4384682Swnj 	/*
4394734Swnj 	 * Free tcp send template, the tcb itself,
440*4809Swnj 	 * and the space we had reserved in the meory pool.
4414682Swnj 	 */
4424734Swnj 	if (tp->t_template) {
4434734Swnj 		m_free(dtom(tp->t_template));
4444734Swnj 		tp->t_template = 0;
4454664Swnj 	}
4464670Swnj 	wmemfree((caddr_t)tp, 1024);
447*4809Swnj 	m_release(so->so_rcv.sb_hiwat + so->so_snd.sb_hiwat + 2 * MSIZE);
4484497Swnj }
4494497Swnj 
4504682Swnj /*
4514734Swnj  * Send data queue headed by m0 into the protocol.
4524682Swnj  */
4534678Swnj tcp_usrsend(tp, m0)
4544584Swnj 	register struct tcb *tp;
4554584Swnj 	struct mbuf *m0;
4564497Swnj {
4574497Swnj 	register struct mbuf *m, *n;
458*4809Swnj 	register struct socket *so = tp->t_socket;
4594497Swnj 	register off;
4604574Swnj 	seq_t last;
4614682Swnj COUNT(TCP_USRSEND);
4624497Swnj 
4634497Swnj 	last = tp->snd_off;
4644584Swnj 	for (m = n = m0; m != NULL; m = m->m_next) {
465*4809Swnj 		so->so_snd.sb_mbcnt++;
4664591Swnj 		if (m->m_off > MMAXOFF)
467*4809Swnj 			so->so_snd.sb_mbcnt += NMBPG;
4684497Swnj 		last += m->m_len;
4694497Swnj 	}
470*4809Swnj 	if ((m = so->so_snd.sb_mb) == NULL)
471*4809Swnj 		so->so_snd.sb_mb = n;
4724588Swnj 	else {
4734588Swnj 		while (m->m_next != NULL) {
4744497Swnj 			m = m->m_next;
4754497Swnj 			last += m->m_len;
4764497Swnj 		}
4774591Swnj 		if (m->m_off <= MMAXOFF) {
4784588Swnj 			last += m->m_len;
4794588Swnj 			off = m->m_off + m->m_len;
4804591Swnj 			while (n && n->m_off <= MMAXOFF &&
4814591Swnj 			    (MMAXOFF - off) >= n->m_len) {
4824588Swnj 				bcopy((caddr_t)((int)n + n->m_off),
4834588Swnj 				      (caddr_t)((int)m + off), n->m_len);
4844588Swnj 				m->m_len += n->m_len;
4854588Swnj 				off += n->m_len;
486*4809Swnj 				so->so_snd.sb_mbcnt--;
4874588Swnj 				n = m_free(n);
4884588Swnj 			}
4894497Swnj 		}
4904497Swnj 		m->m_next = n;
4914588Swnj 	}
492*4809Swnj 	if (tp->t_options & TO_EOL)
4934497Swnj 		tp->snd_end = last;
494*4809Swnj 	if (tp->t_options & TO_URG) {
4954497Swnj 		tp->snd_urp = last+1;
4964576Swnj 		tp->tc_flags |= TC_SND_URG;
4974567Swnj 	}
4984678Swnj 	tcp_send(tp);
4994567Swnj 	return (SAME);
5004497Swnj }
5014497Swnj 
5024682Swnj /*
5034682Swnj  * TCP timer went off processing.
5044682Swnj  */
5054584Swnj tcp_timers(tp, timertype)
5064584Swnj 	register struct tcb *tp;
5074584Swnj 	int timertype;
5084497Swnj {
5094497Swnj 
5104567Swnj COUNT(TCP_TIMERS);
5114584Swnj 	switch (timertype) {
5124497Swnj 
5134567Swnj 	case TINIT:		/* initialization timer */
5144576Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) == 0) {		/* 35 */
515*4809Swnj /* XXX */		/* tcp_close(tp, UINTIMO); */
5164567Swnj 			return (CLOSED);
5174567Swnj 		}
5184567Swnj 		return (SAME);
5194497Swnj 
5204567Swnj 	case TFINACK:		/* fin-ack timer */
5214567Swnj 		switch (tp->t_state) {
5224497Swnj 
5234567Swnj 		case TIME_WAIT:
5244567Swnj 			/*
5254567Swnj 			 * We can be sure our ACK of foreign FIN was rcvd,
5264567Swnj 			 * and can close if no data left for user.
5274567Swnj 			 */
5284567Swnj 			if (rcv_empty(tp)) {
529*4809Swnj /* XXX */			/* tcp_close(tp, UCLOSED); */	/* 14 */
5304567Swnj 				return (CLOSED);
5314567Swnj 			}
5324567Swnj 			return (RCV_WAIT);			/* 17 */
5334497Swnj 
5344731Swnj 		case CLOSING:
5354576Swnj 			tp->tc_flags |= TC_WAITED_2_ML;
5364567Swnj 			return (SAME);
5374497Swnj 
5384567Swnj 		default:
5394567Swnj 			return (SAME);
5404567Swnj 		}
5414497Swnj 
5424567Swnj 	case TREXMT:		/* retransmission timer */
5434567Swnj 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
5444567Swnj 			/*
545*4809Swnj 			 * Set so for a retransmission, increase rexmt time
5464567Swnj 			 * in case of multiple retransmissions.
5474567Swnj 			 */
5484567Swnj 			tp->snd_nxt = tp->snd_una;
5494576Swnj 			tp->tc_flags |= TC_REXMT;
5504567Swnj 			tp->t_xmtime = tp->t_xmtime << 1;
5514567Swnj 			if (tp->t_xmtime > T_REMAX)
5524567Swnj 				tp->t_xmtime = T_REMAX;
5534678Swnj 			tcp_send(tp);
5544567Swnj 		}
5554567Swnj 		return (SAME);
5564497Swnj 
5574567Swnj 	case TREXMTTL:		/* retransmit too long */
5584567Swnj 		if (tp->t_rtl_val > tp->snd_una)		/* 36 */
559*4809Swnj /* XXX */		/* to_user(tp->t_socket, URXTIMO); */;
5604567Swnj 		/*
5614567Swnj 		 * If user has already closed, abort the connection.
5624567Swnj 		 */
5634576Swnj 		if (tp->tc_flags & TC_USR_CLOSED) {
564*4809Swnj /* XXX */		/* tcp_close(tp, URXTIMO); */
5654567Swnj 			return (CLOSED);
5664567Swnj 		}
5674567Swnj 		return (SAME);
5684497Swnj 
5694567Swnj 	case TPERSIST:		/* persist timer */
5704567Swnj 		/*
5714567Swnj 		 * Force a byte send through closed window.
5724567Swnj 		 */
5734576Swnj 		tp->tc_flags |= TC_FORCE_ONE;
5744678Swnj 		tcp_send(tp);
5754567Swnj 		return (SAME);
5764567Swnj 	}
5774567Swnj 	panic("tcp_timers");
5784497Swnj }
5794497Swnj 
580*4809Swnj tcp_error(so, errno)
581*4809Swnj 	struct socket *so;
582*4809Swnj 	int errno;
5834497Swnj {
5844567Swnj COUNT(TO_USER);
5854497Swnj 
586*4809Swnj 	so->so_error = errno;
587*4809Swnj 	sowakeup(so);
5884497Swnj }
5894584Swnj 
5904584Swnj #ifdef TCPDEBUG
5914682Swnj /*
5924682Swnj  * TCP debugging utility subroutines.
5934682Swnj  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
5944682Swnj  */
5954670Swnj tdb_setup(tp, n, input, tdp)
5964670Swnj 	struct tcb *tp;
5974670Swnj 	register struct th *n;
5984670Swnj 	int input;
5994670Swnj 	register struct tcp_debug *tdp;
6004670Swnj {
6014670Swnj 
6024682Swnj COUNT(TDB_SETUP);
6034670Swnj 	tdp->td_tod = time;
6044670Swnj 	tdp->td_tcb = tp;
6054670Swnj 	tdp->td_old = tp->t_state;
6064670Swnj 	tdp->td_inp = input;
6074670Swnj 	tdp->td_tim = 0;
6084670Swnj 	tdp->td_new = -1;
6094670Swnj 	if (n) {
6104670Swnj 		tdp->td_sno = n->t_seq;
6114670Swnj 		tdp->td_ano = n->t_ackno;
6124670Swnj 		tdp->td_wno = n->t_win;
6134670Swnj 		tdp->td_lno = n->t_len;
6144670Swnj 		tdp->td_flg = n->th_flags;
6154670Swnj 	} else
6164670Swnj 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
6174670Swnj 		    tdp->td_flg = 0;
6184670Swnj }
6194670Swnj 
6204670Swnj tdb_stuff(tdp, nstate)
6214670Swnj 	struct tcp_debug *tdp;
6224670Swnj 	int nstate;
6234670Swnj {
6244682Swnj COUNT(TDB_STUFF);
6254670Swnj 
6264670Swnj 	tdp->td_new = nstate;
6274670Swnj 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
6284670Swnj 	if (tcpconsdebug & 2)
6294670Swnj 		tcp_prt(tdp);
6304670Swnj }
6314682Swnj 
6324682Swnj tcp_prt(tdp)
6334682Swnj 	register struct tcp_debug *tdp;
6344682Swnj {
6354682Swnj COUNT(TCP_PRT);
6364682Swnj 
6374698Swnj 	printf("%x ", ((int)tdp->td_tcb)&0xffffff);
6384698Swnj 	if (tdp->td_inp == INSEND) {
6394698Swnj 		printf("SEND #%x", tdp->td_sno);
6404698Swnj 		tdp->td_lno = ntohs(tdp->td_lno);
6414698Swnj 		tdp->td_wno = ntohs(tdp->td_wno);
6424698Swnj 	} else {
6434698Swnj 		if (tdp->td_inp == INRECV)
6444698Swnj 			printf("RCV #%x ", tdp->td_sno);
6454698Swnj 		printf("%s.%s",
6464698Swnj 		    tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
6474698Swnj 		if (tdp->td_inp == ISTIMER)
6484698Swnj 			printf("(%s)", tcptimers[tdp->td_tim]);
6494698Swnj 		printf(" -> %s",
6504698Swnj 		    tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
6514698Swnj 		if (tdp->td_new == -1)
6524698Swnj 			printf(" (FAILED)");
6534698Swnj 	}
6544682Swnj 	/* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
6554698Swnj 	if (tdp->td_lno)
6564698Swnj 		printf(" len=%d", tdp->td_lno);
6574698Swnj 	if (tdp->td_wno)
6584698Swnj 		printf(" win=%d", tdp->td_wno);
6594698Swnj 	if (tdp->td_flg & TH_FIN) printf(" FIN");
6604698Swnj 	if (tdp->td_flg & TH_SYN) printf(" SYN");
6614698Swnj 	if (tdp->td_flg & TH_RST) printf(" RST");
6624698Swnj 	if (tdp->td_flg & TH_EOL) printf(" EOL");
6634698Swnj 	if (tdp->td_flg & TH_ACK)  printf(" ACK %x", tdp->td_ano);
6644698Swnj 	if (tdp->td_flg & TH_URG) printf(" URG");
6654682Swnj 	printf("\n");
6664682Swnj }
6674670Swnj #endif
668