1*4601Swnj /* tcp_input.c 1.1 81/10/24 */ 2*4601Swnj 3*4601Swnj #include "../h/param.h" 4*4601Swnj #include "../h/systm.h" 5*4601Swnj #include "../bbnnet/net.h" 6*4601Swnj #include "../bbnnet/mbuf.h" 7*4601Swnj #include "../bbnnet/host.h" 8*4601Swnj #include "../bbnnet/imp.h" 9*4601Swnj #include "../bbnnet/ucb.h" 10*4601Swnj #include "../bbnnet/tcp.h" 11*4601Swnj #include "../bbnnet/ip.h" 12*4601Swnj #include "../h/dir.h" 13*4601Swnj #include "../h/user.h" 14*4601Swnj #include "../h/inode.h" 15*4601Swnj #include "../bbnnet/fsm.h" 16*4601Swnj 17*4601Swnj extern int nosum; 18*4601Swnj 19*4601Swnj tcp_input(mp) 20*4601Swnj register struct mbuf *mp; 21*4601Swnj { 22*4601Swnj register struct tcb *tp; 23*4601Swnj register struct th *n; 24*4601Swnj int nstate; 25*4601Swnj struct mbuf *m; 26*4601Swnj struct ucb *up; 27*4601Swnj int hlen, tlen, j; 28*4601Swnj u_short lport, fport; 29*4601Swnj #ifdef TCPDEBUG 30*4601Swnj struct tcp_debug tdb; 31*4601Swnj #endif 32*4601Swnj COUNT(TCP_INPUT); 33*4601Swnj 34*4601Swnj /* 35*4601Swnj * Build extended tcp header 36*4601Swnj */ 37*4601Swnj n = (struct th *)((int)mp + mp->m_off); 38*4601Swnj tlen = ((struct ip *)n)->ip_len; 39*4601Swnj n->t_len = htons(tlen); 40*4601Swnj n->t_next = NULL; 41*4601Swnj n->t_prev = NULL; 42*4601Swnj n->t_x1 = 0; 43*4601Swnj lport = ntohs(n->t_dst); 44*4601Swnj fport = ntohs(n->t_src); 45*4601Swnj 46*4601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 47*4601Swnj if ((hlen = n->t_off << 2) > mp->m_len) 48*4601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 49*4601Swnj 50*4601Swnj /* 51*4601Swnj * Checksum extended header and data 52*4601Swnj */ 53*4601Swnj j = n->t_sum; n->t_sum = 0; 54*4601Swnj if (j != cksum(mp, sizeof (struct ip) + tlen)) { 55*4601Swnj netstat.t_badsum++; 56*4601Swnj if (nosum == 0) { 57*4601Swnj m_freem(mp); 58*4601Swnj return; 59*4601Swnj } 60*4601Swnj } 61*4601Swnj 62*4601Swnj /* 63*4601Swnj * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 64*4601Swnj */ 65*4601Swnj for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 66*4601Swnj if (tp->t_lport == lport && tp->t_fport == fport && 67*4601Swnj tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr) 68*4601Swnj goto found; 69*4601Swnj for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 70*4601Swnj if (tp->t_lport == lport && 71*4601Swnj (tp->t_fport==fport || tp->t_fport==0) && 72*4601Swnj (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr || 73*4601Swnj tp->t_ucb->uc_host->h_addr.s_addr == 0)) 74*4601Swnj goto found; 75*4601Swnj goto notwanted; 76*4601Swnj found: 77*4601Swnj 78*4601Swnj /* 79*4601Swnj * Byte swap header 80*4601Swnj */ 81*4601Swnj n->t_len = tlen - hlen; 82*4601Swnj n->t_src = fport; 83*4601Swnj n->t_dst = lport; 84*4601Swnj n->t_seq = ntohl(n->t_seq); 85*4601Swnj n->t_ackno = ntohl(n->t_ackno); 86*4601Swnj n->t_win = ntohs(n->t_win); 87*4601Swnj n->t_urp = ntohs(n->t_urp); 88*4601Swnj 89*4601Swnj /* 90*4601Swnj * Check segment seq # and do rst processing 91*4601Swnj */ 92*4601Swnj switch (tp->t_state) { 93*4601Swnj 94*4601Swnj case LISTEN: 95*4601Swnj if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) { 96*4601Swnj send_rst(tp, n); 97*4601Swnj goto badseg; 98*4601Swnj } 99*4601Swnj if (n->th_flags&TH_RST) 100*4601Swnj goto badseg; 101*4601Swnj goto goodseg; 102*4601Swnj 103*4601Swnj case SYN_SENT: 104*4601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 105*4601Swnj send_rst(tp, n); /* 71,72,75 */ 106*4601Swnj goto badseg; 107*4601Swnj } 108*4601Swnj if (n->th_flags&TH_RST) { 109*4601Swnj t_close(tp, URESET); /* 70 */ 110*4601Swnj tp->t_state = CLOSED; 111*4601Swnj goto badseg; 112*4601Swnj } 113*4601Swnj goto goodseg; 114*4601Swnj 115*4601Swnj default: 116*4601Swnj if ((n->th_flags&TH_RST) == 0) 117*4601Swnj goto common; 118*4601Swnj if (n->t_seq < tp->rcv_nxt) /* bad rst */ 119*4601Swnj goto badseg; /* 69 */ 120*4601Swnj switch (tp->t_state) { 121*4601Swnj 122*4601Swnj case L_SYN_RCVD: 123*4601Swnj if (ack_ok(tp, n) == 0) 124*4601Swnj goto badseg; /* 69 */ 125*4601Swnj tp->t_rexmt = 0; 126*4601Swnj tp->t_rexmttl = 0; 127*4601Swnj tp->t_persist = 0; 128*4601Swnj h_free(tp->t_ucb->uc_host); 129*4601Swnj tp->t_state = LISTEN; 130*4601Swnj goto badseg; 131*4601Swnj 132*4601Swnj default: 133*4601Swnj t_close(tp, URESET); /* 66 */ 134*4601Swnj tp->t_state = CLOSED; 135*4601Swnj goto badseg; 136*4601Swnj } 137*4601Swnj /*NOTREACHED*/ 138*4601Swnj 139*4601Swnj case SYN_RCVD: 140*4601Swnj common: 141*4601Swnj if (ack_ok(tp, n) == 0) { 142*4601Swnj send_rst(tp, n); /* 74 */ 143*4601Swnj goto badseg; 144*4601Swnj } 145*4601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 146*4601Swnj send_null(tp); /* 74 */ 147*4601Swnj goto badseg; 148*4601Swnj } 149*4601Swnj goto goodseg; 150*4601Swnj } 151*4601Swnj badseg: 152*4601Swnj m_freem(mp); 153*4601Swnj return; 154*4601Swnj 155*4601Swnj goodseg: 156*4601Swnj #ifdef notdef 157*4601Swnj /* 158*4601Swnj * Defer processing if no buffer space for this connection. 159*4601Swnj */ 160*4601Swnj up = tp->t_ucb; 161*4601Swnj if ((int)up->uc_rcv - (int)up->uc_rsize <= 0 162*4601Swnj && n->t_len != 0 && netcb.n_bufs < netcb.n_lowat) { 163*4601Swnj mp->m_act = (struct mbuf *)0; 164*4601Swnj if ((m = tp->t_rcv_unack) != NULL) { 165*4601Swnj while (m->m_act != NULL) 166*4601Swnj m = m->m_act; 167*4601Swnj m->m_act = mp; 168*4601Swnj } else 169*4601Swnj tp->t_rcv_unack = mp; 170*4601Swnj 171*4601Swnj return; 172*4601Swnj } 173*4601Swnj #endif 174*4601Swnj 175*4601Swnj /* 176*4601Swnj * Discard ip header, and do tcp input processing. 177*4601Swnj */ 178*4601Swnj hlen += sizeof(struct ip); 179*4601Swnj mp->m_off += hlen; 180*4601Swnj mp->m_len -= hlen; 181*4601Swnj nstate = tp->t_state; 182*4601Swnj tp->tc_flags &= ~TC_NET_KEEP; 183*4601Swnj acounts[tp->t_state][INRECV]++; 184*4601Swnj #ifdef TCPDEBUG 185*4601Swnj if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 186*4601Swnj tdb.td_tod = time; 187*4601Swnj tdb.td_tcb = tp; 188*4601Swnj tdb.td_old = nstate; 189*4601Swnj tdb.td_inp = INRECV; 190*4601Swnj tdb.td_tim = 0; 191*4601Swnj tdb.td_sno = n->t_seq; 192*4601Swnj tdb.td_ano = n->t_ackno; 193*4601Swnj tdb.td_wno = n->t_win; 194*4601Swnj tdb.td_lno = n->t_len; 195*4601Swnj tdb.td_flg = n->th_flags; 196*4601Swnj } else 197*4601Swnj tdb.td_tod = 0; 198*4601Swnj #endif 199*4601Swnj switch (tp->t_state) { 200*4601Swnj 201*4601Swnj case LISTEN: 202*4601Swnj if (!syn_ok(tp, n) || 203*4601Swnj ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 204*4601Swnj nstate = EFAILEC; 205*4601Swnj goto done; 206*4601Swnj } 207*4601Swnj tp->t_fport = n->t_src; 208*4601Swnj rcv_ctldat(tp, n, 1); 209*4601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 210*4601Swnj tp->t_finack = T_2ML; /* 3 */ 211*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 212*4601Swnj nstate = CLOSE_WAIT; 213*4601Swnj } else { 214*4601Swnj tp->t_init = T_INIT / 2; /* 4 */ 215*4601Swnj nstate = L_SYN_RCVD; 216*4601Swnj } 217*4601Swnj goto done; 218*4601Swnj 219*4601Swnj case SYN_SENT: 220*4601Swnj if (!syn_ok(tp, n)) { 221*4601Swnj nstate = EFAILEC; 222*4601Swnj goto done; 223*4601Swnj } 224*4601Swnj rcv_ctldat(tp, n, 1); 225*4601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 226*4601Swnj if (n->th_flags&TH_ACK) { 227*4601Swnj if (n->t_ackno > tp->iss) 228*4601Swnj present_data(tp); /* 32 */ 229*4601Swnj } else { 230*4601Swnj tp->t_finack = T_2ML; /* 9 */ 231*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 232*4601Swnj } 233*4601Swnj nstate = CLOSE_WAIT; 234*4601Swnj goto done; 235*4601Swnj } 236*4601Swnj if (n->th_flags&TH_ACK) { 237*4601Swnj present_data(tp); /* 11 */ 238*4601Swnj nstate = ESTAB; 239*4601Swnj } else 240*4601Swnj nstate = SYN_RCVD; /* 8 */ 241*4601Swnj goto done; 242*4601Swnj 243*4601Swnj case SYN_RCVD: 244*4601Swnj case L_SYN_RCVD: 245*4601Swnj if ((n->th_flags&TH_ACK) == 0 || 246*4601Swnj (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 247*4601Swnj nstate = EFAILEC; 248*4601Swnj goto done; 249*4601Swnj } 250*4601Swnj goto input; 251*4601Swnj 252*4601Swnj case ESTAB: 253*4601Swnj case FIN_W1: 254*4601Swnj case FIN_W2: 255*4601Swnj case TIME_WAIT: 256*4601Swnj input: 257*4601Swnj rcv_ctldat(tp, n, 1); /* 39 */ 258*4601Swnj present_data(tp); 259*4601Swnj switch (tp->t_state) { 260*4601Swnj 261*4601Swnj case ESTAB: 262*4601Swnj if (tp->tc_flags&TC_FIN_RCVD) 263*4601Swnj nstate = CLOSE_WAIT; 264*4601Swnj break; 265*4601Swnj 266*4601Swnj case SYN_RCVD: 267*4601Swnj case L_SYN_RCVD: 268*4601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 269*4601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 270*4601Swnj break; 271*4601Swnj 272*4601Swnj case FIN_W1: 273*4601Swnj j = ack_fin(tp, n); 274*4601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 275*4601Swnj if (j) 276*4601Swnj nstate = FIN_W2; /* 27 */ 277*4601Swnj break; 278*4601Swnj } 279*4601Swnj tp->t_finack = T_2ML; 280*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 281*4601Swnj nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 282*4601Swnj break; 283*4601Swnj 284*4601Swnj case FIN_W2: 285*4601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 286*4601Swnj tp->t_finack = T_2ML; /* 29 */ 287*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 288*4601Swnj nstate = TIME_WAIT; 289*4601Swnj break; 290*4601Swnj } 291*4601Swnj break; 292*4601Swnj } 293*4601Swnj goto done; 294*4601Swnj 295*4601Swnj case CLOSE_WAIT: 296*4601Swnj if (n->th_flags&TH_FIN) { 297*4601Swnj if ((n->th_flags&TH_ACK) && 298*4601Swnj n->t_ackno <= tp->seq_fin) { 299*4601Swnj rcv_ctldat(tp, n, 0); /* 30 */ 300*4601Swnj tp->t_finack = T_2ML; 301*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 302*4601Swnj } else 303*4601Swnj send_ctl(tp); /* 31 */ 304*4601Swnj goto done; 305*4601Swnj } 306*4601Swnj goto input; 307*4601Swnj 308*4601Swnj case CLOSING1: 309*4601Swnj j = ack_fin(tp, n); 310*4601Swnj if (n->th_flags&TH_FIN) { 311*4601Swnj rcv_ctldat(tp, n, 0); 312*4601Swnj tp->t_finack = T_2ML; 313*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 314*4601Swnj if (j) 315*4601Swnj nstate = TIME_WAIT; /* 23 */ 316*4601Swnj goto done; 317*4601Swnj } 318*4601Swnj if (j) { 319*4601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 320*4601Swnj if (rcv_empty(tp)) { 321*4601Swnj t_close(tp, UCLOSED); /* 15 */ 322*4601Swnj nstate = CLOSED; 323*4601Swnj } else 324*4601Swnj nstate = RCV_WAIT; /* 18 */ 325*4601Swnj else 326*4601Swnj nstate = TIME_WAIT; 327*4601Swnj goto done; 328*4601Swnj } 329*4601Swnj goto input; 330*4601Swnj 331*4601Swnj case CLOSING2: 332*4601Swnj if (ack_fin(tp, n)) { 333*4601Swnj if (rcv_empty(tp)) { /* 16 */ 334*4601Swnj t_close(tp, UCLOSED); 335*4601Swnj nstate = CLOSED; 336*4601Swnj } else 337*4601Swnj nstate = RCV_WAIT; /* 19 */ 338*4601Swnj goto done; 339*4601Swnj } 340*4601Swnj if (n->th_flags&TH_FIN) { 341*4601Swnj send_ctl(tp); /* 31 */ 342*4601Swnj goto done; 343*4601Swnj } 344*4601Swnj goto input; 345*4601Swnj 346*4601Swnj case RCV_WAIT: 347*4601Swnj if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 348*4601Swnj n->t_ackno <= tp->seq_fin) { 349*4601Swnj rcv_ctldat(tp, n, 0); 350*4601Swnj tp->t_finack = T_2ML; 351*4601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 352*4601Swnj } 353*4601Swnj goto done; 354*4601Swnj } 355*4601Swnj panic("tcp_input"); 356*4601Swnj done: 357*4601Swnj 358*4601Swnj /* 359*4601Swnj * Done with state*input specific processing. 360*4601Swnj * Form trace records, free input if not needed, 361*4601Swnj * and enter new state. 362*4601Swnj */ 363*4601Swnj #ifdef TCPDEBUG 364*4601Swnj if (tdb.td_tod) { 365*4601Swnj tdb.td_new = nstate; 366*4601Swnj tcp_debug[tdbx++ % TDBSIZE] = tdb; 367*4601Swnj if (tcpconsdebug) 368*4601Swnj tcp_prt(&tdb); 369*4601Swnj } 370*4601Swnj #endif 371*4601Swnj switch (nstate) { 372*4601Swnj 373*4601Swnj case EFAILEC: 374*4601Swnj m_freem(mp); 375*4601Swnj return; 376*4601Swnj 377*4601Swnj default: 378*4601Swnj tp->t_state = nstate; 379*4601Swnj /* fall into ... */ 380*4601Swnj 381*4601Swnj case CLOSED: 382*4601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 383*4601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 384*4601Swnj m_freem(mp); 385*4601Swnj return; 386*4601Swnj } 387*4601Swnj /* NOTREACHED */ 388*4601Swnj 389*4601Swnj /* 390*4601Swnj * Unwanted packed; free everything 391*4601Swnj * but the header and return an rst. 392*4601Swnj */ 393*4601Swnj notwanted: 394*4601Swnj m_freem(mp->m_next); 395*4601Swnj mp->m_next = NULL; 396*4601Swnj mp->m_len = sizeof(struct th); 397*4601Swnj #define xchg(a,b) j=a; a=b; b=j 398*4601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 399*4601Swnj #undef xchg 400*4601Swnj if (n->th_flags&TH_ACK) 401*4601Swnj n->t_seq = n->t_ackno; 402*4601Swnj else { 403*4601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 404*4601Swnj n->t_seq = 0; 405*4601Swnj } 406*4601Swnj n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 407*4601Swnj n->th_flags ^= TH_ACK; 408*4601Swnj n->t_len = htons(TCPSIZE); 409*4601Swnj n->t_off = 5; 410*4601Swnj n->t_sum = cksum(mp, sizeof(struct th)); 411*4601Swnj ((struct ip *)n)->ip_len = sizeof(struct th); 412*4601Swnj ip_output(mp); 413*4601Swnj netstat.t_badsegs++; 414*4601Swnj } 415*4601Swnj 416*4601Swnj rcv_ctldat(tp, n, dataok) 417*4601Swnj register struct tcb *tp; 418*4601Swnj register struct th *n; 419*4601Swnj { 420*4601Swnj register sent; 421*4601Swnj register struct ucb *up; 422*4601Swnj register struct mbuf *m, *mn; 423*4601Swnj register len; 424*4601Swnj COUNT(RCV_CTLDAT); 425*4601Swnj 426*4601Swnj tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 427*4601Swnj /* syn */ 428*4601Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 429*4601Swnj tp->irs = n->t_seq; 430*4601Swnj tp->rcv_nxt = n->t_seq + 1; 431*4601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 432*4601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 433*4601Swnj } 434*4601Swnj /* ack */ 435*4601Swnj if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 436*4601Swnj n->t_ackno > tp->snd_una) { 437*4601Swnj up = tp->t_ucb; 438*4601Swnj 439*4601Swnj /* update snd_una and snd_nxt */ 440*4601Swnj tp->snd_una = n->t_ackno; 441*4601Swnj if (tp->snd_una > tp->snd_nxt) 442*4601Swnj tp->snd_nxt = tp->snd_una; 443*4601Swnj 444*4601Swnj /* if timed msg acked, set retrans time value */ 445*4601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 446*4601Swnj tp->snd_una > tp->t_xmt_val) { 447*4601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 448*4601Swnj if (tp->t_xmtime > T_REMAX) 449*4601Swnj tp->t_xmtime = T_REMAX; 450*4601Swnj } 451*4601Swnj 452*4601Swnj /* remove acked data from send buf */ 453*4601Swnj len = tp->snd_una - tp->snd_off; 454*4601Swnj m = up->uc_sbuf; 455*4601Swnj while (len > 0 && m != NULL) 456*4601Swnj if (m->m_len <= len) { 457*4601Swnj len -= m->m_len; 458*4601Swnj if (m->m_off > MMAXOFF) 459*4601Swnj up->uc_ssize -= NMBPG; 460*4601Swnj MFREE(m, mn); 461*4601Swnj m = mn; 462*4601Swnj up->uc_ssize--; 463*4601Swnj } else { 464*4601Swnj m->m_len -= len; 465*4601Swnj m->m_off += len; 466*4601Swnj break; 467*4601Swnj } 468*4601Swnj up->uc_sbuf = m; 469*4601Swnj tp->snd_off = tp->snd_una; 470*4601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 471*4601Swnj (tp->snd_una > tp->iss)) { 472*4601Swnj tp->tc_flags |= TC_SYN_ACKED; 473*4601Swnj tp->t_init = 0; 474*4601Swnj } 475*4601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 476*4601Swnj tp->tc_flags &= ~TC_SND_FIN; 477*4601Swnj tp->t_rexmt = 0; 478*4601Swnj tp->t_rexmttl = 0; 479*4601Swnj tp->tc_flags |= TC_CANCELLED; 480*4601Swnj netwakeup(tp->t_ucb); /* wasteful */ 481*4601Swnj } 482*4601Swnj /* win */ 483*4601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 484*4601Swnj tp->snd_wl = n->t_seq; 485*4601Swnj tp->snd_wnd = n->t_win; 486*4601Swnj tp->tc_flags |= TC_NEW_WINDOW; 487*4601Swnj tp->t_persist = 0; 488*4601Swnj } 489*4601Swnj if (dataok) { 490*4601Swnj /* text */ 491*4601Swnj if (n->t_len != 0) 492*4601Swnj rcv_text(tp, n); 493*4601Swnj /* urg */ 494*4601Swnj if (n->th_flags&TH_URG) { 495*4601Swnj unsigned urgent; 496*4601Swnj 497*4601Swnj urgent = n->t_urp + n->t_seq; 498*4601Swnj if (tp->rcv_nxt < urgent) { 499*4601Swnj if (tp->rcv_urp <= tp->rcv_nxt) 500*4601Swnj to_user(tp->t_ucb, UURGENT); 501*4601Swnj tp->rcv_urp = urgent; 502*4601Swnj } 503*4601Swnj } 504*4601Swnj /* eol */ 505*4601Swnj if ((n->th_flags&TH_EOL) && 506*4601Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0 && 507*4601Swnj tp->t_rcv_prev != (struct th *)tp) { 508*4601Swnj /* mark last mbuf */ 509*4601Swnj m = dtom(tp->t_rcv_prev); 510*4601Swnj if (m != NULL) { 511*4601Swnj while (m->m_next != NULL) 512*4601Swnj m = m->m_next; 513*4601Swnj m->m_act = 514*4601Swnj (struct mbuf *)(m->m_off + m->m_len - 1); 515*4601Swnj } 516*4601Swnj } 517*4601Swnj } 518*4601Swnj /* fin */ 519*4601Swnj if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 520*4601Swnj int last; 521*4601Swnj 522*4601Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 523*4601Swnj /* do we really have fin ? */ 524*4601Swnj last = firstempty(tp); 525*4601Swnj if (tp->t_rcv_prev == (struct th *)tp || 526*4601Swnj last == t_end(tp->t_rcv_prev)) { 527*4601Swnj tp->tc_flags |= TC_FIN_RCVD; 528*4601Swnj netwakeup(tp->t_ucb); /* poke */ 529*4601Swnj } 530*4601Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 531*4601Swnj tp->rcv_nxt >= last) { 532*4601Swnj tp->rcv_nxt = last + 1; /* fin seq */ 533*4601Swnj tp->tc_flags |= TC_ACK_DUE; 534*4601Swnj } 535*4601Swnj } else 536*4601Swnj tp->tc_flags |= TC_ACK_DUE; 537*4601Swnj } 538*4601Swnj 539*4601Swnj /* respond */ 540*4601Swnj if (tp->tc_flags&TC_ACK_DUE) 541*4601Swnj sent = send_ctl(tp); 542*4601Swnj else if (tp->tc_flags&TC_NEW_WINDOW) 543*4601Swnj sent = send(tp); 544*4601Swnj else 545*4601Swnj sent = 0; 546*4601Swnj 547*4601Swnj /* set for retrans */ 548*4601Swnj if (!sent && tp->snd_una < tp->snd_nxt && 549*4601Swnj (tp->tc_flags&TC_CANCELLED)) { 550*4601Swnj tp->t_rexmt = tp->t_xmtime; 551*4601Swnj tp->t_rexmttl = T_REXMTTL; 552*4601Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 553*4601Swnj tp->tc_flags &= ~TC_CANCELLED; 554*4601Swnj } 555*4601Swnj } 556*4601Swnj 557*4601Swnj rcv_text(tp, t) 558*4601Swnj register struct tcb *tp; 559*4601Swnj register struct th *t; 560*4601Swnj { 561*4601Swnj register i; 562*4601Swnj register struct th *p, *q; 563*4601Swnj register struct mbuf *m, *n; 564*4601Swnj struct th *savq; 565*4601Swnj int last, j, k; 566*4601Swnj COUNT(RCV_TEXT); 567*4601Swnj 568*4601Swnj /* throw away any data we have already received */ 569*4601Swnj if ((i = tp->rcv_nxt - t->t_seq) > 0) { 570*4601Swnj if (i >= t->t_len) 571*4601Swnj return; 572*4601Swnj t->t_seq += i; 573*4601Swnj t->t_len -= i; 574*4601Swnj m_adj(dtom(t), i); 575*4601Swnj } 576*4601Swnj 577*4601Swnj last = t_end(t); /* last seq # in incoming seg */ 578*4601Swnj i = rcv_resource(tp); /* # buffers available to con */ 579*4601Swnj 580*4601Swnj /* count buffers in segment */ 581*4601Swnj 582*4601Swnj for (m = dtom(t), j = 0; m != NULL; m = m->m_next) 583*4601Swnj if (m->m_len != 0) { 584*4601Swnj j++; 585*4601Swnj if (m->m_off > MMAXOFF) 586*4601Swnj j += NMBPG; 587*4601Swnj } 588*4601Swnj 589*4601Swnj /* not enough resources to process segment */ 590*4601Swnj 591*4601Swnj if (j > i && netcb.n_bufs < netcb.n_lowat) { 592*4601Swnj 593*4601Swnj /* if segment preceeds top of seqeuncing queue, try to take 594*4601Swnj buffers from bottom of queue */ 595*4601Swnj 596*4601Swnj q = tp->t_rcv_next; 597*4601Swnj if (q != (struct th *)tp && tp->rcv_nxt < q->t_seq && 598*4601Swnj t->t_seq < q->t_seq) 599*4601Swnj 600*4601Swnj for (k=j-i, p = tp->t_rcv_prev; k > 0 && 601*4601Swnj p != (struct th *)tp; k--) { 602*4601Swnj savq = p->t_prev; 603*4601Swnj tcp_deq(p); 604*4601Swnj i += m_freem(dtom(p)); 605*4601Swnj p = savq; 606*4601Swnj } 607*4601Swnj 608*4601Swnj /* if still not enough room, drop text from end of segment */ 609*4601Swnj 610*4601Swnj if (j > i) { 611*4601Swnj 612*4601Swnj for (m = dtom(t); i > 0 && m != NULL; i--) 613*4601Swnj m = m->m_next; 614*4601Swnj 615*4601Swnj while (m != NULL) { 616*4601Swnj t->t_len -= m->m_len; 617*4601Swnj last -= m->m_len; 618*4601Swnj m->m_len = 0; 619*4601Swnj m = m->m_next; 620*4601Swnj } 621*4601Swnj tp->tc_flags |= TC_DROPPED_TXT; 622*4601Swnj if (last < t->t_seq) 623*4601Swnj return; 624*4601Swnj } 625*4601Swnj } 626*4601Swnj 627*4601Swnj /* merge incoming data into the sequence queue */ 628*4601Swnj 629*4601Swnj q = tp->t_rcv_next; /* -> top of sequencing queue */ 630*4601Swnj 631*4601Swnj /* skip frags which new doesn't overlap at end */ 632*4601Swnj 633*4601Swnj while ((q != (struct th *)tp) && (t->t_seq > t_end(q))) 634*4601Swnj q = q->t_next; 635*4601Swnj 636*4601Swnj if (q == (struct th *)tp) { /* frag at end of chain */ 637*4601Swnj 638*4601Swnj if (last >= tp->rcv_nxt) { 639*4601Swnj tp->tc_flags |= TC_NET_KEEP; 640*4601Swnj tcp_enq(t, tp->t_rcv_prev); 641*4601Swnj } 642*4601Swnj 643*4601Swnj } else { 644*4601Swnj 645*4601Swnj /* frag doesn't overlap any on chain */ 646*4601Swnj 647*4601Swnj if (last < q->t_seq) { 648*4601Swnj tp->tc_flags |= TC_NET_KEEP; 649*4601Swnj tcp_enq(t, q->t_prev); 650*4601Swnj 651*4601Swnj /* new overlaps beginning of next frag only */ 652*4601Swnj 653*4601Swnj } else if (last < t_end(q)) { 654*4601Swnj if ((i = last - q->t_seq + 1) < t->t_len) { 655*4601Swnj t->t_len -= i; 656*4601Swnj m_adj(dtom(t), -i); 657*4601Swnj tp->tc_flags |= TC_NET_KEEP; 658*4601Swnj tcp_enq(t, q->t_prev); 659*4601Swnj } 660*4601Swnj 661*4601Swnj /* new overlaps end of previous frag */ 662*4601Swnj 663*4601Swnj } else { 664*4601Swnj savq = q; 665*4601Swnj if (t->t_seq <= q->t_seq) { /* complete cover */ 666*4601Swnj savq = q->t_prev; 667*4601Swnj tcp_deq(q); 668*4601Swnj m_freem(dtom(q)); 669*4601Swnj 670*4601Swnj } else { /* overlap */ 671*4601Swnj if ((i = t_end(q) - t->t_seq + 1) < t->t_len) { 672*4601Swnj t->t_seq += i; 673*4601Swnj t->t_len -= i; 674*4601Swnj m_adj(dtom(t), i); 675*4601Swnj } else 676*4601Swnj t->t_len = 0; 677*4601Swnj } 678*4601Swnj 679*4601Swnj /* new overlaps at beginning of successor frags */ 680*4601Swnj 681*4601Swnj q = savq->t_next; 682*4601Swnj while ((q != (struct th *)tp) && (t->t_len != 0) && 683*4601Swnj (q->t_seq < last)) 684*4601Swnj 685*4601Swnj /* complete cover */ 686*4601Swnj 687*4601Swnj if (t_end(q) <= last) { 688*4601Swnj p = q->t_next; 689*4601Swnj tcp_deq(q); 690*4601Swnj m_freem(dtom(q)); 691*4601Swnj q = p; 692*4601Swnj 693*4601Swnj } else { /* overlap */ 694*4601Swnj 695*4601Swnj if ((i = last - q->t_seq + 1) < t->t_len) { 696*4601Swnj t->t_len -= i; 697*4601Swnj m_adj(dtom(t), -i); 698*4601Swnj } else 699*4601Swnj t->t_len = 0; 700*4601Swnj break; 701*4601Swnj } 702*4601Swnj 703*4601Swnj /* enqueue whatever is left of new before successors */ 704*4601Swnj 705*4601Swnj if (t->t_len != 0) { 706*4601Swnj tp->tc_flags |= TC_NET_KEEP; 707*4601Swnj tcp_enq(t, savq); 708*4601Swnj } 709*4601Swnj } 710*4601Swnj } 711*4601Swnj 712*4601Swnj /* set to ack completed data (no gaps) */ 713*4601Swnj 714*4601Swnj tp->rcv_nxt = firstempty(tp); 715*4601Swnj tp->tc_flags |= TC_ACK_DUE; 716*4601Swnj 717*4601Swnj #ifdef notdef 718*4601Swnj /* THIS CODE CANT POSSIBLY WORK */ 719*4601Swnj /* if any room remaining in rcv buf, take any unprocessed 720*4601Swnj messages and schedule for later processing */ 721*4601Swnj 722*4601Swnj i = rcv_resource(tp); 723*4601Swnj 724*4601Swnj while ((m = tp->t_rcv_unack) != NULL && i > 0) { 725*4601Swnj 726*4601Swnj /* schedule work request */ 727*4601Swnj 728*4601Swnj t = (struct th *)((int)m + m->m_off); 729*4601Swnj j = (t->t_off << 2) + sizeof(struct ip); 730*4601Swnj m->m_off += j; 731*4601Swnj m->m_len -= j; 732*4601Swnj tp->t_rcv_unack = m->m_act; 733*4601Swnj m->m_act = (struct mbuf *)0; 734*4601Swnj netstat.t_unack++; 735*4601Swnj tcp_work(INRECV, 0, tp, t); 736*4601Swnj 737*4601Swnj /* remaining buffer space */ 738*4601Swnj 739*4601Swnj for (n = m; n != NULL; n = n->m_next) 740*4601Swnj i--; 741*4601Swnj } 742*4601Swnj #endif 743*4601Swnj } 744*4601Swnj 745*4601Swnj present_data(tp) 746*4601Swnj register struct tcb *tp; 747*4601Swnj { 748*4601Swnj register struct th *t; 749*4601Swnj register struct ucb *up; 750*4601Swnj register struct mbuf *m, **mp; 751*4601Swnj seq_t ready; 752*4601Swnj COUNT(PRESENT_DATA); 753*4601Swnj 754*4601Swnj /* connection must be synced and data available for user */ 755*4601Swnj if (((tp->tc_flags&TC_SYN_ACKED) == 0) || 756*4601Swnj (t = tp->t_rcv_next) == (struct th *)tp) 757*4601Swnj return; 758*4601Swnj up = tp->t_ucb; 759*4601Swnj ready = firstempty(tp); /* seq # of last complete datum */ 760*4601Swnj mp = &up->uc_rbuf; 761*4601Swnj while (*mp) 762*4601Swnj mp = &(*mp)->m_next; 763*4601Swnj while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp && 764*4601Swnj t_end(t) < ready) { 765*4601Swnj tcp_deq(t); 766*4601Swnj m = dtom(t); 767*4601Swnj t = t->t_next; 768*4601Swnj while (m) { 769*4601Swnj if (m->m_len == 0) { 770*4601Swnj m = m_free(m); 771*4601Swnj continue; 772*4601Swnj } 773*4601Swnj up->uc_rsize++; 774*4601Swnj if (m->m_off > MMAXOFF) 775*4601Swnj up->uc_rsize += NMBPG; 776*4601Swnj if (*mp == 0) 777*4601Swnj *mp = m; 778*4601Swnj mp = &m->m_next; 779*4601Swnj m = *mp; 780*4601Swnj } 781*4601Swnj } 782*4601Swnj if (up->uc_rsize != 0) 783*4601Swnj netwakeup(up); 784*4601Swnj /* 785*4601Swnj * Let user know about foreign tcp close if no more data. 786*4601Swnj */ 787*4601Swnj if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 && 788*4601Swnj rcv_empty(tp)) 789*4601Swnj to_user(up, UCLOSED); 790*4601Swnj } 791