1*4497Swnj /* tcp_usrreq.c 1.1 81/10/14 */ 2*4497Swnj #include "../h/param.h" 3*4497Swnj #include "../bbnnet/net.h" 4*4497Swnj #include "../bbnnet/tcp.h" 5*4497Swnj #include "../bbnnet/ip.h" 6*4497Swnj #include "../bbnnet/imp.h" 7*4497Swnj #include "../bbnnet/ucb.h" 8*4497Swnj #include "../bbnnet/fsm.h" 9*4497Swnj #include "../bbnnet/tcp_pred.h" 10*4497Swnj 11*4497Swnj lis_cls(wp) /* passive open (1) */ 12*4497Swnj struct work *wp; 13*4497Swnj { 14*4497Swnj 15*4497Swnj COUNT(LIS_CLS); 16*4497Swnj t_open(wp->w_tcb, PASSIVE); 17*4497Swnj 18*4497Swnj return(LISTEN); 19*4497Swnj } 20*4497Swnj 21*4497Swnj sys_cls(wp) /* active open (6) */ 22*4497Swnj register struct work *wp; 23*4497Swnj { 24*4497Swnj 25*4497Swnj COUNT(SYS_CLS); 26*4497Swnj t_open(wp->w_tcb, ACTIVE); 27*4497Swnj send_ctl(wp->w_tcb); /* send SYN */ 28*4497Swnj 29*4497Swnj return(SYN_SENT); 30*4497Swnj } 31*4497Swnj 32*4497Swnj cls_opn(wp) /* close request before receiving foreign SYN (10) */ 33*4497Swnj struct work *wp; 34*4497Swnj { 35*4497Swnj 36*4497Swnj COUNT(CLS_OPN); 37*4497Swnj t_close(wp->w_tcb, UCLOSED); 38*4497Swnj 39*4497Swnj return(CLOSED); 40*4497Swnj } 41*4497Swnj 42*4497Swnj cl2_clw(wp) /* close request after receiving foreign FIN (13) */ 43*4497Swnj struct work *wp; 44*4497Swnj { 45*4497Swnj register struct tcb *tp; 46*4497Swnj 47*4497Swnj COUNT(CL2_CLW); 48*4497Swnj tp = wp->w_tcb; 49*4497Swnj 50*4497Swnj tp->snd_fin = TRUE; /* send our own FIN */ 51*4497Swnj send_ctl(tp); 52*4497Swnj tp->usr_closed = TRUE; 53*4497Swnj 54*4497Swnj return(CLOSING2); 55*4497Swnj } 56*4497Swnj 57*4497Swnj cls_rwt(wp) /* rcv request after foreign close (20) */ 58*4497Swnj struct work *wp; 59*4497Swnj { 60*4497Swnj register struct tcb *tp; 61*4497Swnj 62*4497Swnj COUNT(CLS_RWT); 63*4497Swnj tp = wp->w_tcb; 64*4497Swnj 65*4497Swnj present_data(tp); /* present any remaining data */ 66*4497Swnj 67*4497Swnj if (rcv_empty(tp)) { 68*4497Swnj t_close(tp, UCLOSED); 69*4497Swnj return(CLOSED); 70*4497Swnj } else 71*4497Swnj return(RCV_WAIT); 72*4497Swnj 73*4497Swnj } 74*4497Swnj 75*4497Swnj fw1_syr(wp) /* close request on synced connection (24,25) */ 76*4497Swnj struct work *wp; 77*4497Swnj { 78*4497Swnj register struct tcb *tp; 79*4497Swnj 80*4497Swnj COUNT(FW1_SYR); 81*4497Swnj tp = wp->w_tcb; 82*4497Swnj 83*4497Swnj tp->snd_fin = TRUE; /* send FIN */ 84*4497Swnj send_ctl(tp); 85*4497Swnj tp->usr_closed = TRUE; 86*4497Swnj 87*4497Swnj return(FIN_W1); 88*4497Swnj } 89*4497Swnj 90*4497Swnj sss_syn(wp) /* incoming seq on open connection (39) */ 91*4497Swnj struct work *wp; 92*4497Swnj { 93*4497Swnj register struct tcb *tp; 94*4497Swnj 95*4497Swnj COUNT(SSS_SYN); 96*4497Swnj tp = wp->w_tcb; 97*4497Swnj 98*4497Swnj rcv_data(tp, wp->w_dat); 99*4497Swnj present_data(tp); 100*4497Swnj 101*4497Swnj return(SAME); 102*4497Swnj } 103*4497Swnj 104*4497Swnj sss_snd(wp) /* send request on open connection (40,41) */ 105*4497Swnj struct work *wp; 106*4497Swnj { 107*4497Swnj register struct tcb *tp; 108*4497Swnj register struct mbuf *m, *n; 109*4497Swnj register struct ucb *up; 110*4497Swnj register off; 111*4497Swnj sequence last; 112*4497Swnj 113*4497Swnj COUNT(SSS_SND); 114*4497Swnj tp = wp->w_tcb; 115*4497Swnj up = tp->t_ucb; 116*4497Swnj 117*4497Swnj last = tp->snd_off; 118*4497Swnj 119*4497Swnj /* count number of mbufs in send data */ 120*4497Swnj 121*4497Swnj for (m = n = (struct mbuf *)wp->w_dat; m != NULL; m = m->m_next) { 122*4497Swnj up->uc_ssize++; 123*4497Swnj last += m->m_len; 124*4497Swnj } 125*4497Swnj 126*4497Swnj /* find end of send buffer and append data */ 127*4497Swnj 128*4497Swnj if ((m = up->uc_sbuf) != NULL) { /* something in send buffer */ 129*4497Swnj while (m->m_next != NULL) { /* find the end */ 130*4497Swnj m = m->m_next; 131*4497Swnj last += m->m_len; 132*4497Swnj } 133*4497Swnj last += m->m_len; 134*4497Swnj 135*4497Swnj /* if there's room in old buffer for new data, consolidate */ 136*4497Swnj 137*4497Swnj off = m->m_off + m->m_len; 138*4497Swnj while (n != NULL && (MSIZE - off) >= n->m_len) { 139*4497Swnj bcopy((caddr_t)((int)n + n->m_off), 140*4497Swnj (caddr_t)((int)m + off), n->m_len); 141*4497Swnj m->m_len += n->m_len; 142*4497Swnj off += n->m_len; 143*4497Swnj up->uc_ssize--; 144*4497Swnj n = m_free(n); 145*4497Swnj } 146*4497Swnj m->m_next = n; 147*4497Swnj 148*4497Swnj } else /* nothing in send buffer */ 149*4497Swnj up->uc_sbuf = n; 150*4497Swnj 151*4497Swnj if (up->uc_flags & UEOL) { /* set EOL */ 152*4497Swnj tp->snd_end = last; 153*4497Swnj } 154*4497Swnj 155*4497Swnj if (up->uc_flags & UURG) { /* urgent data */ 156*4497Swnj tp->snd_urp = last+1; 157*4497Swnj tp->snd_urg = TRUE; 158*4497Swnj } 159*4497Swnj 160*4497Swnj send(tp); 161*4497Swnj 162*4497Swnj return(SAME); 163*4497Swnj } 164*4497Swnj 165*4497Swnj sss_rcv(wp) /* rcv request on open connection (42) */ 166*4497Swnj struct work *wp; 167*4497Swnj { 168*4497Swnj register struct tcb *tp; 169*4497Swnj 170*4497Swnj COUNT(SSS_RCV); 171*4497Swnj tp = wp->w_tcb; 172*4497Swnj 173*4497Swnj send_ctl(tp); /* send new window */ 174*4497Swnj present_data(tp); 175*4497Swnj 176*4497Swnj return(SAME); 177*4497Swnj } 178*4497Swnj 179*4497Swnj cls_nsy(wp) /* abort request on unsynced connection (44) */ 180*4497Swnj struct work *wp; 181*4497Swnj { 182*4497Swnj 183*4497Swnj COUNT(CLS_NSY); 184*4497Swnj t_close(wp->w_tcb, UABORT); 185*4497Swnj 186*4497Swnj return(CLOSED); 187*4497Swnj } 188*4497Swnj 189*4497Swnj cls_syn(wp) /* abort request on synced connection (45) */ 190*4497Swnj struct work *wp; 191*4497Swnj { 192*4497Swnj register struct tcb *tp; 193*4497Swnj 194*4497Swnj COUNT(CLS_SYN); 195*4497Swnj tp = wp->w_tcb; 196*4497Swnj 197*4497Swnj tp->snd_rst = TRUE; /* send reset */ 198*4497Swnj send_null(tp); 199*4497Swnj t_close(tp, UABORT); 200*4497Swnj 201*4497Swnj return(CLOSED); 202*4497Swnj } 203*4497Swnj 204*4497Swnj cls_act(wp) /* net closing open connection (47) */ 205*4497Swnj struct work *wp; 206*4497Swnj { 207*4497Swnj 208*4497Swnj COUNT(CLS_ACT); 209*4497Swnj t_close(wp->w_tcb, UNETDWN); 210*4497Swnj 211*4497Swnj return(CLOSED); 212*4497Swnj } 213*4497Swnj 214*4497Swnj cls_err(wp) /* invalid user request in closing states */ 215*4497Swnj struct work *wp; 216*4497Swnj { 217*4497Swnj COUNT(CLS_ERR); 218*4497Swnj to_user(wp->w_tcb->t_ucb, UCLSERR); 219*4497Swnj 220*4497Swnj return(SAME); 221*4497Swnj } 222*4497Swnj 223*4497Swnj lis_netr(wp) /* incoming seg in LISTEN (3,4) */ 224*4497Swnj struct work *wp; 225*4497Swnj { 226*4497Swnj register struct tcb *tp; 227*4497Swnj register struct th *n; 228*4497Swnj 229*4497Swnj COUNT(LIS_NETR); 230*4497Swnj tp = wp->w_tcb; 231*4497Swnj n = (struct th *)wp->w_dat; 232*4497Swnj 233*4497Swnj if (!syn_ok(tp, n)) /* must have good SYN */ 234*4497Swnj return(EFAILEC); 235*4497Swnj 236*4497Swnj /* fill in unspecified foreign host address. get/create entry 237*4497Swnj in foreign host table. if none available, ignore. probably 238*4497Swnj should send reset here. */ 239*4497Swnj 240*4497Swnj if ((tp->t_ucb->uc_host = h_make(&n->t_s)) == NULL) 241*4497Swnj return(EFAILEC); 242*4497Swnj 243*4497Swnj tp->t_fport = n->t_src; 244*4497Swnj 245*4497Swnj rcv_data(tp, n); 246*4497Swnj 247*4497Swnj if (!tp->fin_rcvd) { /* no FIN (4) */ 248*4497Swnj 249*4497Swnj /* start init timer now that we have foreign host */ 250*4497Swnj 251*4497Swnj tp->t_init = T_INIT/2; 252*4497Swnj return(L_SYN_RCVD); 253*4497Swnj 254*4497Swnj } else { /* got a FIN, start timer (3) */ 255*4497Swnj tp->t_finack = T_2ML; 256*4497Swnj tp->waited_2_ml = FALSE; 257*4497Swnj return(CLOSE_WAIT); 258*4497Swnj } 259*4497Swnj } 260*4497Swnj 261*4497Swnj sys_netr(wp) /* incoming segment after SYN sent (8,9,11,32) */ 262*4497Swnj struct work *wp; 263*4497Swnj { 264*4497Swnj register struct tcb *tp; 265*4497Swnj register struct th *n; 266*4497Swnj 267*4497Swnj COUNT(SYS_NETR); 268*4497Swnj tp = wp->w_tcb; 269*4497Swnj n = (struct th *)wp->w_dat; 270*4497Swnj 271*4497Swnj if (!syn_ok(tp, n)) /* must have good SYN */ 272*4497Swnj return(EFAILEC); 273*4497Swnj 274*4497Swnj rcv_data(tp, n); 275*4497Swnj 276*4497Swnj if (tp->fin_rcvd) { /* got a FIN */ 277*4497Swnj 278*4497Swnj /* if good ACK, present any data */ 279*4497Swnj 280*4497Swnj if (n->t_ack) { 281*4497Swnj 282*4497Swnj if (n->t_ackno > tp->iss) /* 32 */ 283*4497Swnj present_data(tp); 284*4497Swnj 285*4497Swnj } else { /* 9 */ 286*4497Swnj tp->t_finack = T_2ML; 287*4497Swnj tp->waited_2_ml = FALSE; 288*4497Swnj } 289*4497Swnj return (CLOSE_WAIT); 290*4497Swnj 291*4497Swnj } else /* no FIN */ 292*4497Swnj 293*4497Swnj /* if good ACK, open connection, otherwise wait for one */ 294*4497Swnj 295*4497Swnj if (n->t_ack) { /* 11 */ 296*4497Swnj present_data(tp); 297*4497Swnj return(ESTAB); 298*4497Swnj } else 299*4497Swnj return(SYN_RCVD); /* 8 */ 300*4497Swnj } 301*4497Swnj 302*4497Swnj cl1_netr(wp) /* incoming seg after we closed (15,18,22,23,30,39) */ 303*4497Swnj struct work *wp; 304*4497Swnj { 305*4497Swnj register struct tcb *tp; 306*4497Swnj register struct th *n; 307*4497Swnj 308*4497Swnj COUNT(CL1_NETR); 309*4497Swnj tp = wp->w_tcb; 310*4497Swnj n = (struct th *)wp->w_dat; 311*4497Swnj 312*4497Swnj if (ack_fin(tp, n)) /* got ACK of our FIN */ 313*4497Swnj 314*4497Swnj if (n->t_fin) { /* got for FIN (23) */ 315*4497Swnj 316*4497Swnj rcv_ctl(tp, n); 317*4497Swnj tp->t_finack = T_2ML; 318*4497Swnj tp->waited_2_ml = FALSE; 319*4497Swnj return(TIME_WAIT); 320*4497Swnj } else { 321*4497Swnj 322*4497Swnj /* if wait done, see if any data left for user */ 323*4497Swnj 324*4497Swnj if (tp->waited_2_ml) 325*4497Swnj 326*4497Swnj if (rcv_empty(tp)) { /* 15 */ 327*4497Swnj 328*4497Swnj t_close(tp, UCLOSED); 329*4497Swnj return(CLOSED); 330*4497Swnj } else 331*4497Swnj return(RCV_WAIT); /* 18 */ 332*4497Swnj 333*4497Swnj else 334*4497Swnj return(TIME_WAIT); /* 22 */ 335*4497Swnj } 336*4497Swnj 337*4497Swnj else /* our FIN not ACKed yet */ 338*4497Swnj 339*4497Swnj if (n->t_fin) { /* rcvd for FIN (30) */ 340*4497Swnj 341*4497Swnj rcv_ctl(tp, n); 342*4497Swnj tp->t_finack = T_2ML; 343*4497Swnj tp->waited_2_ml = FALSE; 344*4497Swnj 345*4497Swnj } else { /* no FIN, just proc new data (39) */ 346*4497Swnj 347*4497Swnj rcv_data(tp, n); 348*4497Swnj present_data(tp); 349*4497Swnj } 350*4497Swnj 351*4497Swnj return(SAME); 352*4497Swnj } 353*4497Swnj 354*4497Swnj cl2_netr(wp) /* incoming seg after foreign close (16,19,31,39) */ 355*4497Swnj struct work *wp; 356*4497Swnj { 357*4497Swnj register struct tcb *tp; 358*4497Swnj register struct th *n; 359*4497Swnj 360*4497Swnj COUNT(CL2_NETR); 361*4497Swnj tp = wp->w_tcb; 362*4497Swnj n = (struct th *)wp->w_dat; 363*4497Swnj 364*4497Swnj if (ack_fin(tp, n)) { /* this is ACK of our fin */ 365*4497Swnj 366*4497Swnj /* if no data left for user, close; otherwise wait */ 367*4497Swnj 368*4497Swnj if (rcv_empty(tp)) { /* 16 */ 369*4497Swnj 370*4497Swnj t_close(tp, UCLOSED); 371*4497Swnj return(CLOSED); 372*4497Swnj } else /* 19 */ 373*4497Swnj return(RCV_WAIT); 374*4497Swnj 375*4497Swnj } else /* no ACK of our FIN */ 376*4497Swnj 377*4497Swnj /* duplicate FIN or data */ 378*4497Swnj 379*4497Swnj if (n->t_fin) /* 31 */ 380*4497Swnj send_ctl(tp); /* ACK duplicate FIN */ 381*4497Swnj 382*4497Swnj else { /* 39 */ 383*4497Swnj rcv_data(tp, n); 384*4497Swnj present_data(tp); 385*4497Swnj } 386*4497Swnj 387*4497Swnj return(SAME); 388*4497Swnj } 389*4497Swnj 390*4497Swnj fw1_netr(wp) /* incoming seg after user close (26,27,28,39) */ 391*4497Swnj struct work *wp; 392*4497Swnj { 393*4497Swnj register struct tcb *tp; 394*4497Swnj register struct th *n; 395*4497Swnj 396*4497Swnj COUNT(FW1_NETR); 397*4497Swnj tp = wp->w_tcb; 398*4497Swnj n = (struct th *)wp->w_dat; 399*4497Swnj 400*4497Swnj /* process any incoming data, since we closed but they didn't */ 401*4497Swnj 402*4497Swnj rcv_data(tp, n); 403*4497Swnj present_data(tp); 404*4497Swnj 405*4497Swnj if (ack_fin(tp, n)) /* our FIN got ACKed */ 406*4497Swnj 407*4497Swnj if (tp->fin_rcvd) { /* got for FIN (28) */ 408*4497Swnj tp->t_finack = T_2ML; 409*4497Swnj tp->waited_2_ml = FALSE; 410*4497Swnj return(TIME_WAIT); 411*4497Swnj } else /* no FIN, wait (27) */ 412*4497Swnj return(FIN_W2); 413*4497Swnj 414*4497Swnj else /* no ACK of FIN */ 415*4497Swnj 416*4497Swnj if (tp->fin_rcvd) { /* got for FIN (26) */ 417*4497Swnj tp->t_finack = T_2ML; 418*4497Swnj tp->waited_2_ml = FALSE; 419*4497Swnj return(CLOSING1); 420*4497Swnj } 421*4497Swnj 422*4497Swnj return(SAME); /* 39 */ 423*4497Swnj } 424*4497Swnj 425*4497Swnj syr_netr(wp) /* incoming seg after SYN rcvd (5,33) */ 426*4497Swnj struct work *wp; 427*4497Swnj { 428*4497Swnj register struct tcb *tp; 429*4497Swnj register struct th *n; 430*4497Swnj 431*4497Swnj COUNT(SYR_NETR); 432*4497Swnj tp = wp->w_tcb; 433*4497Swnj n = (struct th *)wp->w_dat; 434*4497Swnj 435*4497Swnj if (!n->t_ack || (n->t_ack && n->t_ackno <= tp->iss)) /* must have ACK of our SYN */ 436*4497Swnj return(EFAILEC); 437*4497Swnj 438*4497Swnj rcv_data(tp, n); 439*4497Swnj present_data(tp); 440*4497Swnj 441*4497Swnj /* if no FIN, open connection, otherwise wait for user close */ 442*4497Swnj 443*4497Swnj if (tp->fin_rcvd) /* 33 */ 444*4497Swnj return(CLOSE_WAIT); 445*4497Swnj else /* 5 */ 446*4497Swnj return(ESTAB); 447*4497Swnj 448*4497Swnj } 449*4497Swnj 450*4497Swnj est_netr(wp) /* incoming seg on open connection (12,39) */ 451*4497Swnj struct work *wp; 452*4497Swnj { 453*4497Swnj register struct tcb *tp; 454*4497Swnj register struct th *n; 455*4497Swnj 456*4497Swnj COUNT(EST_NETR); 457*4497Swnj tp = wp->w_tcb; 458*4497Swnj n = (struct th *)wp->w_dat; 459*4497Swnj 460*4497Swnj rcv_data(tp, n); 461*4497Swnj present_data(tp); 462*4497Swnj 463*4497Swnj /* if no FIN, remain open, otherwise wait for user close */ 464*4497Swnj 465*4497Swnj if (tp->fin_rcvd) /* 12 */ 466*4497Swnj return(CLOSE_WAIT); 467*4497Swnj else /* 39 */ 468*4497Swnj return(SAME); 469*4497Swnj } 470*4497Swnj 471*4497Swnj fw2_netr(wp) /* incoming seg while waiting for for FIN (12,39) */ 472*4497Swnj struct work *wp; 473*4497Swnj { 474*4497Swnj register struct tcb *tp; 475*4497Swnj register struct th *n; 476*4497Swnj 477*4497Swnj COUNT(FW2_NETR); 478*4497Swnj tp = wp->w_tcb; 479*4497Swnj n = (struct th *)wp->w_dat; 480*4497Swnj 481*4497Swnj /* process data since we closed, but they may not have */ 482*4497Swnj 483*4497Swnj rcv_data(tp, n); 484*4497Swnj present_data(tp); 485*4497Swnj 486*4497Swnj /* if we get the FIN, start the finack timer, else keep waiting */ 487*4497Swnj 488*4497Swnj if (tp->fin_rcvd) { /* got for FIN (29) */ 489*4497Swnj tp->t_finack = T_2ML; 490*4497Swnj tp->waited_2_ml = FALSE; 491*4497Swnj return(TIME_WAIT); 492*4497Swnj } else /* 39 */ 493*4497Swnj return(SAME); 494*4497Swnj } 495*4497Swnj 496*4497Swnj cwt_netr(wp) /* incoming seg after exchange of FINs (30,31,39) */ 497*4497Swnj struct work *wp; 498*4497Swnj { 499*4497Swnj register struct tcb *tp; 500*4497Swnj register struct th *n; 501*4497Swnj 502*4497Swnj COUNT(CWT_NETR); 503*4497Swnj tp = wp->w_tcb; 504*4497Swnj n = (struct th *)wp->w_dat; 505*4497Swnj 506*4497Swnj /* either duplicate FIN or data */ 507*4497Swnj 508*4497Swnj if (n->t_fin) { 509*4497Swnj 510*4497Swnj if (n->t_ack && n->t_ackno <= tp->seq_fin) { /* dup ACK (30) */ 511*4497Swnj 512*4497Swnj rcv_ctl(tp, n); 513*4497Swnj tp->t_finack = T_2ML; 514*4497Swnj tp->waited_2_ml = FALSE; 515*4497Swnj } else /* 31 */ 516*4497Swnj send_ctl(tp); 517*4497Swnj 518*4497Swnj } else { /* duplicate data (39) */ 519*4497Swnj 520*4497Swnj rcv_data(tp, n); 521*4497Swnj present_data(tp); 522*4497Swnj } 523*4497Swnj 524*4497Swnj return(SAME); 525*4497Swnj } 526*4497Swnj 527*4497Swnj rwt_netr(wp) /* incoming seg while waiting for user rcv (30,21) */ 528*4497Swnj struct work *wp; 529*4497Swnj { 530*4497Swnj register struct tcb *tp; 531*4497Swnj register struct th *n; 532*4497Swnj 533*4497Swnj COUNT(RWT_NETR); 534*4497Swnj tp = wp->w_tcb; 535*4497Swnj n = (struct th *)wp->w_dat; 536*4497Swnj 537*4497Swnj /* handle duplicate ACK of our FIN */ 538*4497Swnj 539*4497Swnj if (n->t_fin && n->t_ack && n->t_ackno <= tp->seq_fin) { /* 30 */ 540*4497Swnj 541*4497Swnj rcv_ctl(tp, n); 542*4497Swnj tp->t_finack = T_2ML; 543*4497Swnj tp->waited_2_ml = FALSE; 544*4497Swnj } 545*4497Swnj 546*4497Swnj return(SAME); 547*4497Swnj } 548*4497Swnj 549*4497Swnj timers(wp) /* timer processor (14,17,34,35,36,37,38) */ 550*4497Swnj struct work *wp; 551*4497Swnj { 552*4497Swnj register struct tcb *tp; 553*4497Swnj register type; 554*4497Swnj 555*4497Swnj COUNT(TIMERS); 556*4497Swnj tp = wp->w_tcb; 557*4497Swnj type = wp->w_stype; 558*4497Swnj 559*4497Swnj switch (type) { 560*4497Swnj 561*4497Swnj case TINIT: /* initialization timer */ 562*4497Swnj 563*4497Swnj if (!tp->syn_acked) { /* haven't got ACK of our SYN (35) */ 564*4497Swnj 565*4497Swnj t_close(tp, UINTIMO); 566*4497Swnj return(CLOSED); 567*4497Swnj } 568*4497Swnj break; 569*4497Swnj 570*4497Swnj case TFINACK: /* fin-ack timer */ 571*4497Swnj 572*4497Swnj if (tp->t_state == TIME_WAIT) { 573*4497Swnj 574*4497Swnj /* can be sure our ACK of for FIN was rcvd, 575*4497Swnj can close if no data left for user */ 576*4497Swnj 577*4497Swnj if (rcv_empty(tp)) { /* 14 */ 578*4497Swnj t_close(tp, UCLOSED); 579*4497Swnj return(CLOSED); 580*4497Swnj } else /* 17 */ 581*4497Swnj return(RCV_WAIT); 582*4497Swnj 583*4497Swnj } else if (tp->t_state == CLOSING1) /* 37 */ 584*4497Swnj 585*4497Swnj /* safe to close */ 586*4497Swnj 587*4497Swnj tp->waited_2_ml = TRUE; 588*4497Swnj 589*4497Swnj break; 590*4497Swnj 591*4497Swnj case TREXMT: /* retransmission timer */ 592*4497Swnj 593*4497Swnj /* set up for a retransmission, increase rexmt time 594*4497Swnj in case of multiple retransmissions. */ 595*4497Swnj 596*4497Swnj if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 597*4497Swnj tp->snd_nxt = tp->snd_una; 598*4497Swnj tp->rexmt = TRUE; 599*4497Swnj tp->t_xmtime = tp->t_xmtime << 1; 600*4497Swnj if (tp->t_xmtime > T_REMAX) 601*4497Swnj tp->t_xmtime = T_REMAX; 602*4497Swnj send(tp); 603*4497Swnj } 604*4497Swnj break; 605*4497Swnj 606*4497Swnj case TREXMTTL: /* retransmit too long */ 607*4497Swnj 608*4497Swnj /* tell user */ 609*4497Swnj 610*4497Swnj if (tp->t_rtl_val > tp->snd_una) /* 36 */ 611*4497Swnj to_user(tp->t_ucb, URXTIMO); 612*4497Swnj 613*4497Swnj /* if user has already closed, abort the connection */ 614*4497Swnj 615*4497Swnj if (tp->usr_closed) { 616*4497Swnj t_close(tp, URXTIMO); 617*4497Swnj return(CLOSED); 618*4497Swnj } 619*4497Swnj break; 620*4497Swnj 621*4497Swnj case TPERSIST: /* persist timer */ 622*4497Swnj 623*4497Swnj /* force a byte send through closed window */ 624*4497Swnj 625*4497Swnj tp->force_one = TRUE; /* 38 */ 626*4497Swnj send(tp); 627*4497Swnj break; 628*4497Swnj } 629*4497Swnj 630*4497Swnj return(SAME); 631*4497Swnj } 632*4497Swnj 633*4497Swnj netprepr(tp, n) /* network preproc (66,67,68,69,70,71,72,73,74,75,76) */ 634*4497Swnj register struct tcb *tp; 635*4497Swnj register struct th *n; 636*4497Swnj { 637*4497Swnj 638*4497Swnj COUNT(NETPREPR); 639*4497Swnj switch (tp->t_state) { 640*4497Swnj 641*4497Swnj case LISTEN: 642*4497Swnj 643*4497Swnj if (n->t_ack || !syn_ok(tp, n)) 644*4497Swnj send_rst(tp, n); 645*4497Swnj else if (!n->t_rst) 646*4497Swnj return(0); 647*4497Swnj break; 648*4497Swnj 649*4497Swnj case SYN_SENT: 650*4497Swnj 651*4497Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) 652*4497Swnj 653*4497Swnj send_rst(tp, n); /* 71,72,75 */ 654*4497Swnj 655*4497Swnj else if (n->t_rst) { 656*4497Swnj 657*4497Swnj t_close(tp, URESET); /* 70 */ 658*4497Swnj return(CLOSED); 659*4497Swnj } else 660*4497Swnj return(0); 661*4497Swnj break; 662*4497Swnj 663*4497Swnj default: 664*4497Swnj 665*4497Swnj if (n->t_rst) { /* any resets? */ 666*4497Swnj 667*4497Swnj if (n->t_seq >= tp->rcv_nxt) { /* good reset */ 668*4497Swnj 669*4497Swnj if (tp->t_state == L_SYN_RCVD) { 670*4497Swnj 671*4497Swnj if (ack_ok(tp, n)) { /* 67 */ 672*4497Swnj t_cancel(tp, TREXMT); 673*4497Swnj t_cancel(tp, TREXMTTL); 674*4497Swnj t_cancel(tp, TPERSIST); 675*4497Swnj h_free(tp->t_ucb->uc_host); 676*4497Swnj return(LISTEN); 677*4497Swnj } 678*4497Swnj } else { /* 66 */ 679*4497Swnj t_close(tp, URESET); 680*4497Swnj return(CLOSED); 681*4497Swnj } 682*4497Swnj } /* else 69 */ 683*4497Swnj break; 684*4497Swnj } 685*4497Swnj 686*4497Swnj case SYN_RCVD: 687*4497Swnj 688*4497Swnj if (ack_ok(tp, n)) /* acceptable ack */ 689*4497Swnj 690*4497Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) 691*4497Swnj 692*4497Swnj /* bad syn (73,75,76) */ 693*4497Swnj 694*4497Swnj send_null(tp); 695*4497Swnj else 696*4497Swnj return(0); /* acceptable segment */ 697*4497Swnj else 698*4497Swnj send_rst(tp, n); /* bad ack (74) */ 699*4497Swnj 700*4497Swnj } 701*4497Swnj 702*4497Swnj return(-1); /* tell caller to eat segment (unacceptable) */ 703*4497Swnj } 704