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