1 #ifdef RCSIDENT
2 static char rcsident[] = "$Header: tcp_states.c,v 1.21 85/07/31 09:42:53 walsh Exp $";
3 #endif
4 
5 
6 #include "../h/param.h"
7 #include "../h/mbuf.h"
8 #include "../h/socket.h"
9 #include "../h/socketvar.h"
10 #include "../h/errno.h"
11 #include "../h/systm.h"
12 
13 #include "../net/if.h"
14 #include "../net/route.h"
15 
16 #include "../bbnnet/in.h"
17 #include "../bbnnet/in_pcb.h"
18 #include "../bbnnet/in_var.h"
19 #include "../bbnnet/net.h"
20 #include "../bbnnet/fsm.h"
21 #include "../bbnnet/tcp.h"
22 #include "../bbnnet/seq.h"
23 #include "../bbnnet/ip.h"
24 #include "../bbnnet/macros.h"
25 #include "../bbnnet/sws.h"
26 #ifdef HMPTRAPS
27 #include "../bbnnet/hmp_traps.h"
28 #endif
29 
30 extern struct rtentry *ip_route();
31 
32 /*
33  * These are the action routines of the TCP finite state machine.  They are
34  * called from the TCP fsm dispatcher action().  These routines call
35  * on the routines in tcp_procs.c to do the actual segment processing.
36  */
37 
38 /*
39  * UNOPENED x IUOPENA == passive open == listen()
40  */
41 lis_cls(wp)
42 struct work *wp;
43 {
44     register struct tcpcb *tp = wp->w_tcb;
45 
46     /* listen() system call */
47 
48     /*
49      * Don't know who we're talking to yet, so we don't have a route
50      * or mtu yet.
51      */
52     tp->t_maxseg = TCPMAXSND;
53     tp->t_timers[TINIT] = tp->t_itimeo;
54 
55     return(LISTEN);
56 }
57 
58 /*
59  * UNOPENED x IUOPENR == active open == connect()
60  */
61 sys_cls(wp)
62 register struct work *wp;
63 {
64     register struct tcpcb *tp;
65     register struct inpcb *inp;
66 
67     /* connect() system call */
68 
69     tp = wp->w_tcb;
70     inp = tp->t_in_pcb;
71     /*
72      * Know foreign host and have a route to there.
73      */
74 #ifdef NOTCPOPTS
75     tp->t_maxseg =  inp->inp_route.ro_rt->rt_ifp->if_mtu - TCPIPMAX;
76 #else
77     /*
78      * Best can do until other guy tells us otherwise.
79      */
80     tp->t_maxseg =
81 	MIN(inp->inp_route.ro_rt->rt_ifp->if_mtu - TCPIPMAX, TCPMAXSND);
82 #endif
83     tp->t_maxseg -= inp->inp_optlen;
84 
85     tp->t_timers[TINIT] = (tp->t_itimeo ? tp->t_itimeo : TCP_tvINIT);
86 
87     send_tcp(tp, TCP_CTL);	/* send SYN */
88     return(SYN_SENT);
89 }
90 
91 /*
92  * UNOPENED x IUCLOSE
93  * LISTEN   x IUCLOSE
94  * SYN_SENT x IUCLOSE
95  *
96  * User close request before receiving foreign SYN
97  */
98 cls_opn(wp)
99 struct work *wp;
100 {
101     t_close(wp->w_tcb, ECONNABORTED);
102     return(CLOSED);
103 }
104 
105 /*
106  * SYN_RCVD   x IUCLOSE
107  * L_SYN_RCVD x IUCLOSE
108  * ESTAB      x IUCLOSE
109  *
110  * close request on synched connection
111  */
112 fw1_syr(wp)
113 struct work *wp;
114 {
115     register struct tcpcb *tp = wp->w_tcb;
116 
117     tp->snd_fin = TRUE; /* send FIN */
118     send_tcp(tp, TCP_CTL);
119     tp->usr_closed = TRUE;
120     tp->t_noact = TCP_tvNOACT;
121     tp->t_timers[TNOACT] = TCP_tvNOACT;
122     return(FIN_W1);
123 }
124 
125 /*
126  * CLOSE_WAIT x IUCLOSE
127  *
128  * close request after received foreign FIN
129  */
130 cl2_clw(wp)
131 struct work *wp;
132 {
133     register struct tcpcb *tp = wp->w_tcb;
134 
135     tp->snd_fin = TRUE; /* send our own FIN */
136     send_tcp(tp, TCP_CTL);
137     tp->usr_closed = TRUE;
138     tp->t_noact = TCP_tvNOACT;
139     tp->t_timers[TNOACT] = TCP_tvNOACT;
140     return(CLOSING2);
141 }
142 
143 /*
144  * UNOPENED   x IUABORT
145  * LISTEN     x IUABORT
146  * SYN_SENT   x IUABORT
147  * SYN_RCVD   x IUABORT
148  * L_SYN_RCVD x IUABORT
149  *
150  * User abort request on unsynched connection
151  */
152 cls_nsy(wp)
153 struct work *wp;
154 {
155     t_close(wp->w_tcb, ECONNABORTED);
156     return(CLOSED);
157 }
158 
159 /*
160  * ESTAB      x IUABORT
161  * FIN_WAIT_1 x IUABORT
162  * FIN_WAIT_2 x IUABORT
163  * TIME_WAIT  x IUABORT
164  * CLOSE_WAIT x IUABORT
165  * CLOSING_1  x IUABORT
166  * CLOSING_2  x IUABORT
167  * RCV_WAIT   x IUABORT
168  *
169  * User abort request on synched connection
170  */
171 cls_syn(wp)
172 struct work *wp;
173 {
174     register struct tcpcb *tp = wp->w_tcb;
175 
176     tp->snd_rst = TRUE; /* send reset */
177     (void) send_pkt(tp, 0, 0);
178     /* tp->ack_due = FALSE; don't since about to throw tcpcb away */
179     t_close(tp, ECONNABORTED);
180     return(CLOSED);
181 }
182 
183 /*
184  * LISTEN x INRECV
185  *
186  * From tcp_input/netprepr, we know the packet is a well formed SYN
187  */
188 lis_netr(wp)
189 struct work *wp;
190 {
191     register struct tcpcb *tp;
192     register struct th *n;
193     register struct inpcb *inp;
194     register struct socket *so, *newso;
195     struct rtentry *rt;
196     struct tcpcb *newtp;
197     struct inpcb *newinp;
198 
199     struct in_addr firsthop;
200     extern int	ip_nhops;
201     extern struct in_addr ip_hops[];
202 
203     n = (struct th *)wp->w_dat;
204 
205     /*
206      * Need to route on basis of IP destination -- see ip_send()
207      * ### What if loose routing and 1st hop not on local net and reroute?
208      */
209     if (ip_nhops == 0)
210 	firsthop = n->t_s;
211     else
212 	/* source routed SYN packet */
213 	firsthop = ip_hops[ip_nhops];
214 
215     /*
216      * O.k., let's get a route back to him
217      */
218     if (!(rt = ip_route(&n->t_d, &firsthop)))
219     {
220 	/*
221 	 * Can't talk to him.  Leave socket in receive state
222 	 * so we can connect to someone else, since we haven't
223 	 * been committed to anything yet anyway.
224 	 * ### Drop his info on the floor.
225 	 * Let the other machine just figure out on it's own that
226 	 * it can't reach us that way.
227 	 */
228 	no_route ("tcp", n->t_d, firsthop);
229 	return(LISTEN);
230     }
231 
232     tp = wp->w_tcb;
233     inp = tp->t_in_pcb;
234     so = inp->inp_socket;
235 
236     /*
237      * This socket is in the listen state, so the socket should have
238      * so_options & SO_ACCEPTCONN set (solisten()).
239      *
240      * The order of sonewconn() and soisconnected() is
241      * important, in order for the process to be woken up
242      * at a time when the sleep condition is fulfilled.
243      * sonewconn() is done here on the original socket, and
244      * soisconnected() is done later in syr_netr() on the new
245      * socket.
246      */
247     if (newso = sonewconn(so))
248     {
249 	newinp = (struct inpcb *) newso->so_pcb;
250 	newtp = (struct tcpcb *) newinp->inp_ppcb;
251 	/*
252 	 * Remember our peer for this connection.
253 	 */
254 	newinp->inp_faddr = n->t_s;
255 	newinp->inp_fport = n->t_src;
256 	newinp->inp_laddr = n->t_d;
257 	if (ip_nhops > 0)
258 	{
259 	    /*
260 	     * optlen includes the source route to be copied
261 	     * to the outgoing IP header, not the firsthop
262 	     * which replaces ip_dst.
263 	     */
264 	    bcopy((caddr_t)ip_hops,newinp->inp_options, (unsigned)(ip_nhops+1)*4);
265 	    newinp->inp_optlen = ip_nhops * 4;
266 	}
267 	/*
268 	 * and copy fields into the new inpcb
269 	 */
270 	newinp->inp_lport = inp->inp_lport;
271 	newinp->inp_route.ro_rt = rt;
272 
273 	/*
274 	 * and copy fields to the new tcpcb
275 	 */
276 	newtp->t_maxfrag = tp->t_maxfrag;	/* set in tcp_input() */
277 	newtp->t_itimeo  = tp->t_itimeo;
278 	newtp->t_noact	 = tp->t_noact;
279 	newtp->t_push	 = tp->t_push;
280 	newtp->t_noactsig = tp->t_noactsig;
281 	newtp->t_noactprobe = tp->t_noactprobe;
282 
283 	/*
284 	 * and initialize others with new info
285 	 * Upward negotiation of t_maxseg in tcp_opt() done
286 	 * on socket in LISTEN.
287 	 */
288 	newtp->t_maxseg = MIN(rt->rt_ifp->if_mtu - TCPIPMAX, tp->t_maxseg);
289 	newtp->t_maxseg -= newinp->inp_optlen;
290 	/*
291 	 * In case next client doesn't negotiate maxseg.
292 	 */
293 	tp->t_maxseg = TCPMAXSND;
294 
295 
296 	if (!(newtp->t_template = tcp_template(newtp)))
297 	{
298 	    soabort (newso);
299 	    return (LISTEN);
300 	}
301 
302 	newtp->sws_qff = SWS_QFF_DEF;
303 
304 	/*
305 	 * So can debug connection problems without having to change
306 	 * every program or apply debugging flag to each program every
307 	 * time run it.
308 	 */
309 	dowedebug(newinp, newso, &tcp_dfilter);
310 
311 	/*
312 	 * rcv_tcp may set fin_rcvd.  If so, We went up and down or
313 	 * we got a garbage/misrouted packet.  If it's set, it's
314 	 * meant for some other socket or some other instantiation
315 	 * of it.  In any case, ignore it and listen for other
316 	 * talkers.
317 	 */
318 	rcv_tcp(newtp, n, TCP_DATA);
319 
320 	if (newtp->fin_rcvd)
321 	    soabort (newso);
322 	else
323 	{
324 	    /*
325 	     * no FIN (4)
326 	     * start init timer now that we have foreign host.
327 	     * Parent socket might have init timer as zero to
328 	     * avoid getting ETIMEDOUT, but we do want this
329 	     * child socket to time out on synchronization
330 	     * just in case other host just went down.
331 	     */
332 	    newtp->t_timers[TINIT] = (newtp->t_itimeo != 0
333 		? newtp->t_itimeo
334 		: TCP_tvINIT/2);
335 	    newtp->t_state = L_SYN_RCVD;
336 	}
337     }
338     else
339 	rtfree(rt);
340 
341     return(LISTEN);	/* original file descriptor stays in LISTEN state */
342 }
343 
344 /*
345  * SYN_SENT x INRECV
346  *
347  * from tcp_input/netprepr, we know its a SYN, with perhaps a well formed ACK
348  */
349 sys_netr(wp)
350 struct work *wp;
351 {
352     register struct tcpcb *tp = wp->w_tcb;
353     register struct th *n = (struct th *)wp->w_dat;
354 
355     rcv_tcp(tp, n, TCP_DATA);
356     if (tp->fin_rcvd)
357     {             /* got a FIN */
358 
359 	/* if good ACK, present any data */
360 
361 	if (n->t_flags&T_ACK)
362 	{
363 	    if (SEQ_GT(n->t_ackno, tp->iss))	/* 32 */
364 		present_data(tp);
365 	}
366 	else
367 	{                                /* 9 */
368 	    tp->t_timers[TFINACK] = TCP_tv2ML;
369 	    tp->waited_2_ml = FALSE;
370 	}
371 	tp->t_timers[TNOACT] = tp->t_noact;
372 	return (CLOSE_WAIT);
373     }
374     else                   /* no FIN */
375 	/* if good ACK, open connection, otherwise wait for one */
376 	if (n->t_flags&T_ACK)
377 	{			/* 11 */
378 	    present_data(tp);
379 	    tp->t_timers[TNOACT] = tp->t_noact;
380 	    soisconnected (tp->t_in_pcb->inp_socket);
381 	    return(ESTAB);
382 	}
383 
384     return(SYN_RCVD); /* 8 */
385 }
386 
387 /*
388  * SYN_RCVD   x INRECV
389  * L_SYN_RCVD x INRECV
390  *
391  * from tcp_input/netprepr, we know its an ACK of our SYN
392  */
393 syr_netr(wp)
394 struct work *wp;
395 {
396     register struct tcpcb *tp = wp->w_tcb;
397     register struct th *n = (struct th *)wp->w_dat;
398 
399     rcv_tcp(tp, n, TCP_DATA);
400     present_data(tp);
401 
402     /* if no FIN, open connection, otherwise wait for user close */
403 
404     tp->t_timers[TNOACT] = tp->t_noact;
405     if (tp->fin_rcvd)                               /* 33 */
406 	return(CLOSE_WAIT);
407     else
408     {
409 	/* 5 */
410 	soisconnected (tp->t_in_pcb->inp_socket);
411 	return(ESTAB);
412     }
413 }
414 
415 /*
416  * ESTAB x INRECV
417  */
418 est_netr(wp)
419 struct work *wp;
420 {
421     register struct tcpcb *tp = wp->w_tcb;
422 
423     rcv_tcp(tp, (struct th *)wp->w_dat, TCP_DATA);
424     PRESENT_DATA(tp);
425 
426     /* if no FIN, remain open, otherwise wait for user close */
427 
428     if (tp->fin_rcvd)                       /* 12 */
429 	return(CLOSE_WAIT);
430     else /* 39 */
431 	return(SAME);
432 }
433 
434 /*
435  * FIN_WAIT_1 x INRECV
436  *
437  * incoming segment after user has closed
438  */
439 fw1_netr(wp)
440 struct work *wp;
441 {
442     register struct tcpcb *tp = wp->w_tcb;
443     register struct th *n = (struct th *)wp->w_dat;
444 
445     /* process any incoming data, since we closed but they didn't */
446 
447     rcv_tcp(tp, n, TCP_DATA);
448     present_data(tp);
449 
450     /* send any data remaining on send buffer */
451 
452     send_tcp(tp, TCP_DATA);
453     if (ack_fin(tp, n))
454     {			/* our FIN got ACKed */
455 	if (tp->fin_rcvd)
456 	{                     /* got for FIN (28) */
457 	    tp->t_timers[TFINACK] = TCP_tv2ML;
458 	    tp->waited_2_ml = FALSE;
459 	    return(TIME_WAIT);
460 	}
461 	else                   /* no FIN, wait (27) */
462 	    return(FIN_W2);
463     }
464     else
465     {				/* no ACK of FIN */
466 	if (tp->fin_rcvd)
467 	{                     /* got for FIN (26) */
468 	    tp->t_timers[TFINACK] = TCP_tv2ML;
469 	    tp->waited_2_ml = FALSE;
470 	    return(CLOSING1);
471 	}
472     }
473     return(SAME); /* 39 */
474 }
475 
476 /*
477  * FIN_WAIT_2 x INRECV
478  *
479  * incoming segment while waiting for foreign FIN
480  */
481 fw2_netr(wp)
482 struct work *wp;
483 {
484     register struct tcpcb *tp = wp->w_tcb;
485     register struct th *n = (struct th *)wp->w_dat;
486 
487     /* process data since we closed, but they may not have */
488 
489     rcv_tcp(tp, n, TCP_DATA);
490     present_data(tp);
491 
492     /* if we get the FIN, start the finack timer, else keep waiting */
493 
494     if (tp->fin_rcvd)
495     {                     /* got for FIN (29) */
496 	tp->t_timers[TFINACK] = TCP_tv2ML;
497 	tp->waited_2_ml = FALSE;
498 	return(TIME_WAIT);
499     }
500     else                   /* 39 */
501 	return(SAME);
502 }
503 
504 /*
505  * TIME_WAIT x INRECV
506  *
507  * The close protocol (exchange of FINs) has progressed as far as it can.
508  * We do not enter CLOSED immediately, but use TIME_WAIT so that if our ack
509  * of other guys FIN didn't reach him, he can retransmit and we'll ack his
510  * fin rather than respond with an rst.
511  *
512  * Since we received a packet, apparently our ack of his fin didn't get
513  * there and we'll have to try again.  Restart finack timer in case this
514  * one fails too.
515  */
516 sss_syn(wp)
517 struct work *wp;
518 {
519     register struct tcpcb *tp = wp->w_tcb;
520 
521     rcv_tcp(tp, (struct th *) wp->w_dat, TCP_DATA);
522     present_data(tp);
523     tp->t_timers[TFINACK] = TCP_tv2ML;
524     return(SAME);
525 }
526 
527 /*
528  * CLOSE_WAIT x INRECV
529  *
530  * incoming segment after receipt of foreign FIN (local end still open)
531  */
532 cwt_netr(wp)
533 struct work *wp;
534 {
535     register struct tcpcb *tp = wp->w_tcb;
536     register struct th *n = (struct th *)wp->w_dat;
537 
538     /* either duplicate FIN or data */
539 
540     if (n->t_flags&T_FIN)
541     {
542 	if (n->t_flags&T_ACK && SEQ_LEQ(n->t_ackno, tp->seq_fin))
543 	{
544 	    rcv_tcp(tp, n, TCP_CTL);
545 	    tp->t_timers[TFINACK] = TCP_tv2ML;
546 	    tp->waited_2_ml = FALSE;
547 	}
548 	else                   /* 31 */
549 	    send_tcp(tp, TCP_CTL);
550     }
551     else
552     {				/* duplicate data (39) */
553 	rcv_tcp(tp, n, TCP_DATA);
554 	present_data(tp);
555     }
556     return(SAME);
557 }
558 
559 /*
560  * CLOSING_1 x INRECV
561  *
562  * incoming segment after we closed
563  */
564 cl1_netr(wp)
565 struct work *wp;
566 {
567     register struct tcpcb *tp = wp->w_tcb;
568     register struct th *n = (struct th *)wp->w_dat;
569 
570     if (ack_fin(tp, n))
571     {			/* got ACK of our FIN */
572 	if (n->t_flags&T_FIN)
573 	{		/* got for FIN (23) */
574 	    rcv_tcp(tp, n, TCP_CTL);
575 	    tp->t_timers[TFINACK] = TCP_tv2ML;
576 	    tp->waited_2_ml = FALSE;
577 	    return(TIME_WAIT);
578 	}
579 	else
580 	{
581 
582 	    /* if wait done, see if any data left for user */
583 
584 	    if (tp->waited_2_ml)
585 		if (rcv_empty(tp))
586 		{    /* 15 */
587 		    t_close(tp, ECONNABORTED);
588 		    return(CLOSED);
589 		}
590 		else
591 		    return(RCV_WAIT); /* 18 */
592 	    else
593 		return(TIME_WAIT); /* 22 */
594 	}
595     }
596     else
597     {				/* our FIN not ACKed yet */
598 	if (n->t_flags&T_FIN)
599 	{		/* rcvd for FIN (30) */
600 	    rcv_tcp(tp, n, TCP_CTL);
601 	    tp->t_timers[TFINACK] = TCP_tv2ML;
602 	    tp->waited_2_ml = FALSE;
603 	}
604 	else
605 	{		/* no FIN, just proc new data (39) */
606 	    rcv_tcp(tp, n, TCP_DATA);
607 	    present_data(tp);
608 	}
609     }
610     return(SAME);
611 }
612 
613 /*
614  * CLOSING_2 x INRECV
615  *
616  * incoming segment after both of us have started closing
617  */
618 cl2_netr(wp)
619 struct work *wp;
620 {
621     register struct tcpcb *tp = wp->w_tcb;
622     register struct th *n = (struct th *)wp->w_dat;
623 
624     if (ack_fin(tp, n))
625     {                   /* this is ACK of our fin */
626 
627 	/* if no data left for user, close; otherwise wait */
628 
629 	if (rcv_empty(tp))
630 	{                            /* 16 */
631 	    t_close(tp, ECONNABORTED);
632 	    return(CLOSED);
633 	}
634 	else                   /* 19 */
635 	    return(RCV_WAIT);
636     }
637     else
638     {				/* no ACK of our FIN */
639 	/* duplicate FIN or data */
640 
641 	if (n->t_flags&T_FIN)				/* 31 */
642 	    send_tcp(tp, TCP_CTL);	/* ACK duplicate FIN */
643 	else
644 	{
645 	    /* 39 */
646 	    rcv_tcp(tp, n, TCP_DATA);
647 	    present_data(tp);
648 	}
649     }
650     return(SAME);
651 }
652 
653 /*
654  * RCV_WAIT x INRECV
655  */
656 rwt_netr(wp)            /* incoming seg while waiting for user rcv (30,21) */
657 struct work *wp;
658 {
659     register struct tcpcb *tp = wp->w_tcb;
660     register struct th *n = (struct th *)wp->w_dat;
661 
662     /* handle duplicate ACK of our FIN */
663 
664     if (n->t_flags&T_FIN && n->t_flags&T_ACK && SEQ_LEQ(n->t_ackno, tp->seq_fin))
665     { 		/* 30 */
666 	rcv_tcp(tp, n, TCP_CTL);
667 	tp->t_timers[TFINACK] = TCP_tv2ML;
668 	tp->waited_2_ml = FALSE;
669     }
670     return(SAME);
671 }
672 
673 /*
674  *	ESTAB      x IURECV
675  *	CLOSE_WAIT x IURECV
676  *
677  * and allowing for shutdown()
678  *
679  *	FIN_WAIT_1 x IURECV
680  *	FIN_WAIT_2 x IURECV
681  *	TIME_WAIT  x IURECV
682  *	CLOSING_1  x IURECV
683  *	CLOSING_2  x IURECV
684  */
685 sss_rcv(wp)             /* rcv request on open connection (42) */
686 struct work *wp;
687 {
688     register struct tcpcb *tp = wp->w_tcb;
689 
690     PRESENT_DATA(tp);
691 
692     /* if last window sent was zero, send an ACK to update window */
693 
694     if (tp->sent_zero)
695     {
696 	tp->force_ack = TRUE;	/* don't delay ACK here */
697 	send_tcp(tp, TCP_CTL);
698     }
699     return(SAME);
700 }
701 
702 /*
703  * RCV_WAIT x IURECV
704  */
705 cls_rwt(wp)             /* rcv request after foreign close (20) */
706 struct work *wp;
707 {
708     register struct tcpcb *tp = wp->w_tcb;
709 
710     present_data(tp); /* present any remaining data */
711     if (rcv_empty(tp))
712     {
713 	t_close(tp, ECONNABORTED);
714 	return(CLOSED);
715     }
716     else
717 	return(RCV_WAIT);
718 }
719 
720 /*
721  * SYN_SENT   x IUSEND
722  * SYN_RCVD   x IUSEND
723  * ESTAB      x IUSEND
724  * CLOSE_WAIT x IUSEND
725  *
726  * For SYN_SENT and SYN_RCVD, just want to buffer data until connected.
727  */
728 sss_snd(wp)             /* send request on open connection (40,41) */
729 struct work *wp;
730 {
731     register struct tcpcb *tcp = wp->w_tcb;
732     register struct inpcb *inp = tcp->t_in_pcb;
733     sequence last;
734 
735     sbappend(&inp->inp_socket->so_snd, (struct mbuf *) wp->w_dat);
736     last = tcp->snd_una + inp->inp_socket->so_snd.sb_cc;
737 
738     if (tcp->t_push)
739 	tcp->snd_end = last;
740     if (tcp->t_urg)
741     {
742 	tcp->snd_urp = last;	/* this byte is not urgent */
743 	tcp->snd_urg = TRUE;
744     }
745     send_tcp(tcp, TCP_DATA);
746     return(SAME);
747 }
748 
749 cls_act(wp)             /* net closing open connection (47) */
750 struct work *wp;
751 {
752     t_close(wp->w_tcb, ECONNABORTED);
753     return(CLOSED);
754 }
755 
756 cls_err(wp)             /* invalid user request in closing states */
757 struct work *wp;
758 {
759     advise_user(tcpcbtoso(wp->w_tcb), ECONNABORTED);
760     return(SAME);
761 }
762 
763 
764 
765 timers(wp)              /* timer processor (14,17,34,35,36,37,38) */
766 struct work *wp;
767 {
768     register struct tcpcb *tp = wp->w_tcb;
769     register type = wp->w_stype;
770 
771     switch (type)
772     {
773 
774       case TINIT: /* initialization timer */
775 	/*
776 	 * Haven't got an ACK of our SYN yet
777 	 */
778 	if (tp->t_in_pcb->inp_socket->so_state & SS_NOFDREF)
779 	{
780 	    /*
781 	     * was a child socket of a listen(2)er trying to
782 	     * establish connection with other end.
783 	     * (state L_SYN_RCVD)
784 	     */
785 	    t_close(tp, ETIMEDOUT);
786 	    return(CLOSED);
787 	}
788 	/* socket in connect(2) */
789 	advise_user(tcpcbtoso(tp), ETIMEDOUT);
790 	tp->t_timers[TINIT] = tp->t_itimeo;
791 	break;
792 
793       case TFINACK: /* fin-ack timer */
794 
795 	if (tp->t_state == TIME_WAIT)
796 	{
797 
798 	    /* can be sure our ACK of for FIN was rcvd,
799 	       can close if no data left for user */
800 
801 	    if (rcv_empty(tp))
802 	    {            /* 14 */
803 		t_close(tp, ECONNABORTED);
804 		return(CLOSED);
805 	    }
806 	    else                   /* 17 */
807 		return(RCV_WAIT);
808 
809 	}
810 	else if (tp->t_state == CLOSING1)     /* 37 */
811 
812 	    /* safe to close */
813 
814 	    tp->waited_2_ml = TRUE;
815 
816 	break;
817 
818       case TREXMT: /* retransmission timer */
819 
820 	if (is_unacked(tp))
821 	{
822 	    /* statistics */
823 	    tp->t_rxtct++;
824 	    tcpstat.t_retransmit ++;
825 
826 	    /*
827 	     * If we're retransmitting, then the network
828 	     * may be dropping packets because it is overloaded.
829 	     * Therefore, increase the retransmission time for
830 	     * successive retransmissions.  When we get an ACK,
831 	     * the srtt and rxmitime will be recalculated.
832 	     */
833 	    tp->t_rxmitime = tp->t_rxmitime << 1;
834 	    if (tp->t_rxmitime > TCP_tvRXMAX)
835 		tp->t_rxmitime = TCP_tvRXMAX;
836 
837 	    tp->snd_nxt = tp->snd_una;
838 	    tp->rexmt = TRUE;
839 	    send_tcp(tp, TCP_DATA);
840 	    tp->rexmt = FALSE;
841 	}
842 	break;
843 
844       case TREXMTTL: /* retransmit too long */
845 
846 #ifdef HMPTRAPS
847 	/* hmp_trap(T_TCP_REXMTTL, (caddr_t)0, 0); */
848 #endif
849 	if (tp->usr_abort)
850 	{
851 	    /* user has already closed for r/w so abort connection
852 	     * usr_closed == closed for w (close or shutdown).
853 	     */
854 	    t_close(tp, ETIMEDOUT);
855 	    return(CLOSED);
856 	}
857 	advise_user(tcpcbtoso(tp), ETIMEDOUT);
858 	tp->t_timers[TREXMTTL] = tp->t_rttltimeo;
859 	break;
860 
861       case TPERSIST: /* persist timer */
862 
863 	/* force a byte send through closed window */
864 
865 	tp->force_one = TRUE; /* 38 */
866 	send_tcp(tp, TCP_DATA);	/* restarts timer */
867 	tp->force_one = FALSE;
868 	break;
869 
870       case TDELACK:	/* ack-delay timer */
871 
872 	/* make sure an ack gets sent now */
873 
874 	tp->force_ack = TRUE;
875 	send_tcp(tp, TCP_CTL);
876 	break;
877 
878       case TNOACT:	/* no activity timer */
879 	/*
880 	 * This timer is used for 2 reasons:
881 	 * 1) by the user to determine if the connection is idle or if the
882 	 *    other side has aborted/rebooted...  This is open states entry.
883 	 *    See tcp_newtcpcb()
884 	 * 2) by the system to timeout on receipt of ACK of our FIN.
885 	 *    This is separate from use of FINACK timer for other guy
886 	 *    to get our ACK of his FIN.  If closing has started, finish it.
887 	 */
888 
889 	/*
890 	 * if its a shutdown(),
891 	 *	usr_closed == TRUE, usr_abort == FALSE
892 	 *	the user will find out about any problems getting an ACK of our
893 	 *	    FIN through the retransmit took too long timer
894 	 *	the connection could be idle because it takes the remote end a
895 	 *	    while to compute and produce a reply
896 	 *	user only gets to crank up protocol close once, but he can
897 	 *	    shutdown and then close, thereby adjusting usr_abort so
898 	 *	    that things get cleaned up if the remote host died.
899 	 *
900 	 * if its a close(),
901 	 *	usr_closed == TRUE, usr_abort == TRUE
902 	 *	user could be lingering (and SS_NOFDREF will still be false)
903 	 *	connection could be idle because the other host failed, and it
904 	 *	    could be down for days.  We don't want to wait for it to
905 	 *	    come back up and give us a reset.  Release resources now.
906 	 */
907 	if (tp->usr_abort)
908 	{
909 	    t_close(tp, ETIMEDOUT);
910 	    return(CLOSED);
911 	}
912 
913 	if (tp->t_noactprobe)
914 	    send_tcp(tp, TCP_CTL);
915 
916 	if (tp->t_noactsig)
917 	    advise_user(tcpcbtoso(tp), ETIMEDOUT);
918 
919 	tp->t_timers[TNOACT] = tp->t_noact;
920 	break;
921 
922     }
923     return(SAME);
924 }
925