1*4645Swnj /* tcp_input.c 1.4 81/10/28 */ 24601Swnj 34601Swnj #include "../h/param.h" 44601Swnj #include "../h/systm.h" 54601Swnj #include "../bbnnet/net.h" 64601Swnj #include "../bbnnet/mbuf.h" 74601Swnj #include "../bbnnet/host.h" 84601Swnj #include "../bbnnet/imp.h" 94601Swnj #include "../bbnnet/ucb.h" 104601Swnj #include "../bbnnet/tcp.h" 114601Swnj #include "../bbnnet/ip.h" 124601Swnj #include "../h/dir.h" 134601Swnj #include "../h/user.h" 144601Swnj #include "../h/inode.h" 154601Swnj #include "../bbnnet/fsm.h" 164601Swnj 174601Swnj extern int nosum; 184601Swnj 194601Swnj tcp_input(mp) 204601Swnj register struct mbuf *mp; 214601Swnj { 224601Swnj register struct tcb *tp; 234601Swnj register struct th *n; 244601Swnj int nstate; 254601Swnj struct mbuf *m; 264601Swnj struct ucb *up; 274601Swnj int hlen, tlen, j; 284601Swnj u_short lport, fport; 294601Swnj #ifdef TCPDEBUG 304601Swnj struct tcp_debug tdb; 314601Swnj #endif 324601Swnj COUNT(TCP_INPUT); 334601Swnj 344601Swnj /* 354601Swnj * Build extended tcp header 364601Swnj */ 374601Swnj n = (struct th *)((int)mp + mp->m_off); 384601Swnj tlen = ((struct ip *)n)->ip_len; 394601Swnj n->t_len = htons(tlen); 404601Swnj n->t_next = NULL; 414601Swnj n->t_prev = NULL; 424601Swnj n->t_x1 = 0; 434601Swnj lport = ntohs(n->t_dst); 444601Swnj fport = ntohs(n->t_src); 454601Swnj 464601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 474601Swnj if ((hlen = n->t_off << 2) > mp->m_len) 484601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 494601Swnj 504601Swnj /* 514601Swnj * Checksum extended header and data 524601Swnj */ 534601Swnj j = n->t_sum; n->t_sum = 0; 544601Swnj if (j != cksum(mp, sizeof (struct ip) + tlen)) { 554601Swnj netstat.t_badsum++; 564601Swnj if (nosum == 0) { 574601Swnj m_freem(mp); 584601Swnj return; 594601Swnj } 604601Swnj } 614601Swnj 624601Swnj /* 634601Swnj * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 644601Swnj */ 654601Swnj for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 664601Swnj if (tp->t_lport == lport && tp->t_fport == fport && 674601Swnj tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr) 684601Swnj goto found; 694601Swnj for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next) 704601Swnj if (tp->t_lport == lport && 714601Swnj (tp->t_fport==fport || tp->t_fport==0) && 724601Swnj (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr || 734601Swnj tp->t_ucb->uc_host->h_addr.s_addr == 0)) 744601Swnj goto found; 754601Swnj goto notwanted; 764601Swnj found: 774601Swnj 784601Swnj /* 794601Swnj * Byte swap header 804601Swnj */ 814601Swnj n->t_len = tlen - hlen; 824601Swnj n->t_src = fport; 834601Swnj n->t_dst = lport; 844601Swnj n->t_seq = ntohl(n->t_seq); 854601Swnj n->t_ackno = ntohl(n->t_ackno); 864601Swnj n->t_win = ntohs(n->t_win); 874601Swnj n->t_urp = ntohs(n->t_urp); 884601Swnj 894601Swnj /* 904601Swnj * Check segment seq # and do rst processing 914601Swnj */ 924601Swnj switch (tp->t_state) { 934601Swnj 944601Swnj case LISTEN: 954601Swnj if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) { 964601Swnj send_rst(tp, n); 974601Swnj goto badseg; 984601Swnj } 994601Swnj if (n->th_flags&TH_RST) 1004601Swnj goto badseg; 1014601Swnj goto goodseg; 1024601Swnj 1034601Swnj case SYN_SENT: 1044601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1054601Swnj send_rst(tp, n); /* 71,72,75 */ 1064601Swnj goto badseg; 1074601Swnj } 1084601Swnj if (n->th_flags&TH_RST) { 1094601Swnj t_close(tp, URESET); /* 70 */ 1104601Swnj tp->t_state = CLOSED; 1114601Swnj goto badseg; 1124601Swnj } 1134601Swnj goto goodseg; 1144601Swnj 1154601Swnj default: 1164601Swnj if ((n->th_flags&TH_RST) == 0) 1174601Swnj goto common; 1184601Swnj if (n->t_seq < tp->rcv_nxt) /* bad rst */ 1194601Swnj goto badseg; /* 69 */ 1204601Swnj switch (tp->t_state) { 1214601Swnj 1224601Swnj case L_SYN_RCVD: 1234601Swnj if (ack_ok(tp, n) == 0) 1244601Swnj goto badseg; /* 69 */ 1254601Swnj tp->t_rexmt = 0; 1264601Swnj tp->t_rexmttl = 0; 1274601Swnj tp->t_persist = 0; 1284601Swnj h_free(tp->t_ucb->uc_host); 1294601Swnj tp->t_state = LISTEN; 1304601Swnj goto badseg; 1314601Swnj 1324601Swnj default: 1334601Swnj t_close(tp, URESET); /* 66 */ 1344601Swnj tp->t_state = CLOSED; 1354601Swnj goto badseg; 1364601Swnj } 1374601Swnj /*NOTREACHED*/ 1384601Swnj 1394601Swnj case SYN_RCVD: 1404601Swnj common: 1414601Swnj if (ack_ok(tp, n) == 0) { 1424601Swnj send_rst(tp, n); /* 74 */ 1434601Swnj goto badseg; 1444601Swnj } 1454601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 1464601Swnj send_null(tp); /* 74 */ 1474601Swnj goto badseg; 1484601Swnj } 1494601Swnj goto goodseg; 1504601Swnj } 1514601Swnj badseg: 1524601Swnj m_freem(mp); 1534601Swnj return; 1544601Swnj 1554601Swnj goodseg: 1564601Swnj #ifdef notdef 1574601Swnj /* 1584601Swnj * Defer processing if no buffer space for this connection. 1594601Swnj */ 1604601Swnj up = tp->t_ucb; 1614601Swnj if ((int)up->uc_rcv - (int)up->uc_rsize <= 0 1624601Swnj && n->t_len != 0 && netcb.n_bufs < netcb.n_lowat) { 1634601Swnj mp->m_act = (struct mbuf *)0; 1644601Swnj if ((m = tp->t_rcv_unack) != NULL) { 1654601Swnj while (m->m_act != NULL) 1664601Swnj m = m->m_act; 1674601Swnj m->m_act = mp; 1684601Swnj } else 1694601Swnj tp->t_rcv_unack = mp; 1704601Swnj 1714601Swnj return; 1724601Swnj } 1734601Swnj #endif 1744601Swnj 1754601Swnj /* 1764601Swnj * Discard ip header, and do tcp input processing. 1774601Swnj */ 1784601Swnj hlen += sizeof(struct ip); 1794601Swnj mp->m_off += hlen; 1804601Swnj mp->m_len -= hlen; 1814601Swnj nstate = tp->t_state; 1824601Swnj tp->tc_flags &= ~TC_NET_KEEP; 1834601Swnj acounts[tp->t_state][INRECV]++; 1844601Swnj #ifdef TCPDEBUG 1854601Swnj if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 1864604Swnj tdb_setup(tp, n, INRECV, &tdb); 1874601Swnj } else 1884601Swnj tdb.td_tod = 0; 1894601Swnj #endif 1904601Swnj switch (tp->t_state) { 1914601Swnj 1924601Swnj case LISTEN: 1934601Swnj if (!syn_ok(tp, n) || 1944601Swnj ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 1954601Swnj nstate = EFAILEC; 1964601Swnj goto done; 1974601Swnj } 1984601Swnj tp->t_fport = n->t_src; 1994603Sroot tp->t_ucb->uc_template = tcp_template(tp); 2004601Swnj rcv_ctldat(tp, n, 1); 2014601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2024601Swnj tp->t_finack = T_2ML; /* 3 */ 2034601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2044601Swnj nstate = CLOSE_WAIT; 2054601Swnj } else { 2064601Swnj tp->t_init = T_INIT / 2; /* 4 */ 2074601Swnj nstate = L_SYN_RCVD; 2084601Swnj } 2094601Swnj goto done; 2104601Swnj 2114601Swnj case SYN_SENT: 2124601Swnj if (!syn_ok(tp, n)) { 2134601Swnj nstate = EFAILEC; 2144601Swnj goto done; 2154601Swnj } 2164601Swnj rcv_ctldat(tp, n, 1); 2174601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2184601Swnj if (n->th_flags&TH_ACK) { 2194601Swnj if (n->t_ackno > tp->iss) 2204601Swnj present_data(tp); /* 32 */ 2214601Swnj } else { 2224601Swnj tp->t_finack = T_2ML; /* 9 */ 2234601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2244601Swnj } 2254601Swnj nstate = CLOSE_WAIT; 2264601Swnj goto done; 2274601Swnj } 2284601Swnj if (n->th_flags&TH_ACK) { 2294601Swnj present_data(tp); /* 11 */ 2304601Swnj nstate = ESTAB; 2314601Swnj } else 2324601Swnj nstate = SYN_RCVD; /* 8 */ 2334601Swnj goto done; 2344601Swnj 2354601Swnj case SYN_RCVD: 2364601Swnj case L_SYN_RCVD: 2374601Swnj if ((n->th_flags&TH_ACK) == 0 || 2384601Swnj (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 2394601Swnj nstate = EFAILEC; 2404601Swnj goto done; 2414601Swnj } 2424601Swnj goto input; 2434601Swnj 2444601Swnj case ESTAB: 2454601Swnj case FIN_W1: 2464601Swnj case FIN_W2: 2474601Swnj case TIME_WAIT: 2484601Swnj input: 2494601Swnj rcv_ctldat(tp, n, 1); /* 39 */ 2504601Swnj present_data(tp); 2514601Swnj switch (tp->t_state) { 2524601Swnj 2534601Swnj case ESTAB: 2544601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2554601Swnj nstate = CLOSE_WAIT; 2564601Swnj break; 2574601Swnj 2584601Swnj case SYN_RCVD: 2594601Swnj case L_SYN_RCVD: 2604601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2614601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2624601Swnj break; 2634601Swnj 2644601Swnj case FIN_W1: 2654601Swnj j = ack_fin(tp, n); 2664601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2674601Swnj if (j) 2684601Swnj nstate = FIN_W2; /* 27 */ 2694601Swnj break; 2704601Swnj } 2714601Swnj tp->t_finack = T_2ML; 2724601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2734601Swnj nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 2744601Swnj break; 2754601Swnj 2764601Swnj case FIN_W2: 2774601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2784601Swnj tp->t_finack = T_2ML; /* 29 */ 2794601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2804601Swnj nstate = TIME_WAIT; 2814601Swnj break; 2824601Swnj } 2834601Swnj break; 2844601Swnj } 2854601Swnj goto done; 2864601Swnj 2874601Swnj case CLOSE_WAIT: 2884601Swnj if (n->th_flags&TH_FIN) { 2894601Swnj if ((n->th_flags&TH_ACK) && 2904601Swnj n->t_ackno <= tp->seq_fin) { 2914601Swnj rcv_ctldat(tp, n, 0); /* 30 */ 2924601Swnj tp->t_finack = T_2ML; 2934601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2944601Swnj } else 2954601Swnj send_ctl(tp); /* 31 */ 2964601Swnj goto done; 2974601Swnj } 2984601Swnj goto input; 2994601Swnj 3004601Swnj case CLOSING1: 3014601Swnj j = ack_fin(tp, n); 3024601Swnj if (n->th_flags&TH_FIN) { 3034601Swnj rcv_ctldat(tp, n, 0); 3044601Swnj tp->t_finack = T_2ML; 3054601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3064601Swnj if (j) 3074601Swnj nstate = TIME_WAIT; /* 23 */ 3084601Swnj goto done; 3094601Swnj } 3104601Swnj if (j) { 3114601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3124601Swnj if (rcv_empty(tp)) { 3134601Swnj t_close(tp, UCLOSED); /* 15 */ 3144601Swnj nstate = CLOSED; 3154601Swnj } else 3164601Swnj nstate = RCV_WAIT; /* 18 */ 3174601Swnj else 3184601Swnj nstate = TIME_WAIT; 3194601Swnj goto done; 3204601Swnj } 3214601Swnj goto input; 3224601Swnj 3234601Swnj case CLOSING2: 3244601Swnj if (ack_fin(tp, n)) { 3254601Swnj if (rcv_empty(tp)) { /* 16 */ 3264601Swnj t_close(tp, UCLOSED); 3274601Swnj nstate = CLOSED; 3284601Swnj } else 3294601Swnj nstate = RCV_WAIT; /* 19 */ 3304601Swnj goto done; 3314601Swnj } 3324601Swnj if (n->th_flags&TH_FIN) { 3334601Swnj send_ctl(tp); /* 31 */ 3344601Swnj goto done; 3354601Swnj } 3364601Swnj goto input; 3374601Swnj 3384601Swnj case RCV_WAIT: 3394601Swnj if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 3404601Swnj n->t_ackno <= tp->seq_fin) { 3414601Swnj rcv_ctldat(tp, n, 0); 3424601Swnj tp->t_finack = T_2ML; 3434601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3444601Swnj } 3454601Swnj goto done; 3464601Swnj } 3474601Swnj panic("tcp_input"); 3484601Swnj done: 3494601Swnj 3504601Swnj /* 3514601Swnj * Done with state*input specific processing. 3524601Swnj * Form trace records, free input if not needed, 3534601Swnj * and enter new state. 3544601Swnj */ 3554601Swnj #ifdef TCPDEBUG 3564604Swnj if (tdb.td_tod) 3574604Swnj tdb_stuff(&tdb, nstate); 3584601Swnj #endif 3594601Swnj switch (nstate) { 3604601Swnj 3614601Swnj case EFAILEC: 3624601Swnj m_freem(mp); 3634601Swnj return; 3644601Swnj 3654601Swnj default: 3664601Swnj tp->t_state = nstate; 3674601Swnj /* fall into ... */ 3684601Swnj 3694601Swnj case CLOSED: 3704601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3714601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3724601Swnj m_freem(mp); 3734601Swnj return; 3744601Swnj } 3754601Swnj /* NOTREACHED */ 3764601Swnj 3774601Swnj /* 3784601Swnj * Unwanted packed; free everything 3794601Swnj * but the header and return an rst. 3804601Swnj */ 3814601Swnj notwanted: 3824601Swnj m_freem(mp->m_next); 3834601Swnj mp->m_next = NULL; 3844601Swnj mp->m_len = sizeof(struct th); 3854601Swnj #define xchg(a,b) j=a; a=b; b=j 3864601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 3874601Swnj #undef xchg 3884601Swnj if (n->th_flags&TH_ACK) 3894601Swnj n->t_seq = n->t_ackno; 3904601Swnj else { 3914601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 3924601Swnj n->t_seq = 0; 3934601Swnj } 3944601Swnj n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 3954601Swnj n->th_flags ^= TH_ACK; 3964601Swnj n->t_len = htons(TCPSIZE); 3974601Swnj n->t_off = 5; 3984601Swnj n->t_sum = cksum(mp, sizeof(struct th)); 3994601Swnj ((struct ip *)n)->ip_len = sizeof(struct th); 4004601Swnj ip_output(mp); 4014601Swnj netstat.t_badsegs++; 4024601Swnj } 4034601Swnj 4044601Swnj rcv_ctldat(tp, n, dataok) 4054601Swnj register struct tcb *tp; 4064601Swnj register struct th *n; 4074601Swnj { 4084601Swnj register sent; 4094601Swnj register struct ucb *up; 4104601Swnj register struct mbuf *m, *mn; 4114601Swnj register len; 4124601Swnj COUNT(RCV_CTLDAT); 4134601Swnj 4144601Swnj tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 4154601Swnj /* syn */ 4164601Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 4174601Swnj tp->irs = n->t_seq; 4184601Swnj tp->rcv_nxt = n->t_seq + 1; 4194601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4204601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4214601Swnj } 4224601Swnj /* ack */ 4234601Swnj if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4244601Swnj n->t_ackno > tp->snd_una) { 4254601Swnj up = tp->t_ucb; 4264601Swnj 4274601Swnj /* update snd_una and snd_nxt */ 4284601Swnj tp->snd_una = n->t_ackno; 4294601Swnj if (tp->snd_una > tp->snd_nxt) 4304601Swnj tp->snd_nxt = tp->snd_una; 4314601Swnj 4324601Swnj /* if timed msg acked, set retrans time value */ 4334601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4344601Swnj tp->snd_una > tp->t_xmt_val) { 4354601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4364601Swnj if (tp->t_xmtime > T_REMAX) 4374601Swnj tp->t_xmtime = T_REMAX; 4384601Swnj } 4394601Swnj 4404601Swnj /* remove acked data from send buf */ 4414601Swnj len = tp->snd_una - tp->snd_off; 4424601Swnj m = up->uc_sbuf; 4434601Swnj while (len > 0 && m != NULL) 4444601Swnj if (m->m_len <= len) { 4454601Swnj len -= m->m_len; 4464601Swnj if (m->m_off > MMAXOFF) 4474601Swnj up->uc_ssize -= NMBPG; 4484601Swnj MFREE(m, mn); 4494601Swnj m = mn; 4504601Swnj up->uc_ssize--; 4514601Swnj } else { 4524601Swnj m->m_len -= len; 4534601Swnj m->m_off += len; 4544601Swnj break; 4554601Swnj } 4564601Swnj up->uc_sbuf = m; 4574601Swnj tp->snd_off = tp->snd_una; 4584601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4594601Swnj (tp->snd_una > tp->iss)) { 4604601Swnj tp->tc_flags |= TC_SYN_ACKED; 4614601Swnj tp->t_init = 0; 4624601Swnj } 4634601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4644601Swnj tp->tc_flags &= ~TC_SND_FIN; 4654601Swnj tp->t_rexmt = 0; 4664601Swnj tp->t_rexmttl = 0; 4674601Swnj tp->tc_flags |= TC_CANCELLED; 4684601Swnj netwakeup(tp->t_ucb); /* wasteful */ 4694601Swnj } 4704601Swnj /* win */ 4714601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 4724601Swnj tp->snd_wl = n->t_seq; 4734601Swnj tp->snd_wnd = n->t_win; 4744601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4754601Swnj tp->t_persist = 0; 4764601Swnj } 4774601Swnj if (dataok) { 4784601Swnj /* text */ 4794601Swnj if (n->t_len != 0) 4804601Swnj rcv_text(tp, n); 4814601Swnj /* urg */ 4824601Swnj if (n->th_flags&TH_URG) { 4834601Swnj unsigned urgent; 4844601Swnj 4854601Swnj urgent = n->t_urp + n->t_seq; 4864601Swnj if (tp->rcv_nxt < urgent) { 4874601Swnj if (tp->rcv_urp <= tp->rcv_nxt) 4884601Swnj to_user(tp->t_ucb, UURGENT); 4894601Swnj tp->rcv_urp = urgent; 4904601Swnj } 4914601Swnj } 4924601Swnj /* eol */ 4934601Swnj if ((n->th_flags&TH_EOL) && 4944601Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0 && 4954601Swnj tp->t_rcv_prev != (struct th *)tp) { 4964601Swnj /* mark last mbuf */ 4974601Swnj m = dtom(tp->t_rcv_prev); 4984601Swnj if (m != NULL) { 4994601Swnj while (m->m_next != NULL) 5004601Swnj m = m->m_next; 5014601Swnj m->m_act = 5024601Swnj (struct mbuf *)(m->m_off + m->m_len - 1); 5034601Swnj } 5044601Swnj } 5054601Swnj } 5064601Swnj /* fin */ 5074601Swnj if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 5084601Swnj int last; 5094601Swnj 5104601Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 5114601Swnj /* do we really have fin ? */ 5124601Swnj last = firstempty(tp); 5134601Swnj if (tp->t_rcv_prev == (struct th *)tp || 5144601Swnj last == t_end(tp->t_rcv_prev)) { 5154601Swnj tp->tc_flags |= TC_FIN_RCVD; 5164601Swnj netwakeup(tp->t_ucb); /* poke */ 5174601Swnj } 5184601Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 5194601Swnj tp->rcv_nxt >= last) { 5204601Swnj tp->rcv_nxt = last + 1; /* fin seq */ 5214601Swnj tp->tc_flags |= TC_ACK_DUE; 5224601Swnj } 5234601Swnj } else 5244601Swnj tp->tc_flags |= TC_ACK_DUE; 5254601Swnj } 5264601Swnj 5274601Swnj /* respond */ 5284601Swnj if (tp->tc_flags&TC_ACK_DUE) 5294601Swnj sent = send_ctl(tp); 5304601Swnj else if (tp->tc_flags&TC_NEW_WINDOW) 5314601Swnj sent = send(tp); 5324601Swnj else 5334601Swnj sent = 0; 5344601Swnj 5354601Swnj /* set for retrans */ 5364601Swnj if (!sent && tp->snd_una < tp->snd_nxt && 5374601Swnj (tp->tc_flags&TC_CANCELLED)) { 5384601Swnj tp->t_rexmt = tp->t_xmtime; 5394601Swnj tp->t_rexmttl = T_REXMTTL; 5404601Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 5414601Swnj tp->tc_flags &= ~TC_CANCELLED; 5424601Swnj } 5434601Swnj } 5444601Swnj 545*4645Swnj rcv_text(tp, n) 5464601Swnj register struct tcb *tp; 547*4645Swnj register struct th *n; 5484601Swnj { 549*4645Swnj register int i; 5504601Swnj register struct th *p, *q; 551*4645Swnj register struct mbuf *m; 552*4645Swnj int overage; 5534601Swnj COUNT(RCV_TEXT); 5544601Swnj 555*4645Swnj /* 556*4645Swnj * Discard duplicate data already passed to user. 557*4645Swnj */ 558*4645Swnj if (n->t_seq < tp->rcv_nxt){ 559*4645Swnj i = tp->rcv_nxt - n->t_seq; 560*4645Swnj if (i >= n->t_len) 561*4645Swnj goto dropseg; 562*4645Swnj n->t_seq += i; 563*4645Swnj n->t_len -= i; 564*4645Swnj m_adj(dtom(n), i); 5654601Swnj } 5664601Swnj 567*4645Swnj /* 568*4645Swnj * Find a segment which begins after this one does. 569*4645Swnj */ 570*4645Swnj for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 571*4645Swnj if (q->t_seq > n->t_seq) 572*4645Swnj break; 5734601Swnj 574*4645Swnj /* 575*4645Swnj * If there is a preceding segment, it may provide some of 576*4645Swnj * our data already. If so, drop the data from the incoming 577*4645Swnj * segment. If it provides all of our data, drop us. 578*4645Swnj */ 579*4645Swnj if (q->t_prev != (struct th *)tp) { 580*4645Swnj i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 581*4645Swnj if (i > 0) { 582*4645Swnj if (i >= n->t_len) 583*4645Swnj goto dropseg; 584*4645Swnj m_adj(dtom(tp), i); 585*4645Swnj n->t_len -= i; 586*4645Swnj n->t_seq += i; 5874601Swnj } 5884601Swnj } 5894601Swnj 590*4645Swnj /* 591*4645Swnj * While we overlap succeeding segments trim them or, 592*4645Swnj * if they are completely covered, dequeue them. 593*4645Swnj */ 594*4645Swnj while (q != (struct th *)tp && n->t_seq + n->t_len > q->t_seq) { 595*4645Swnj i = (n->t_seq + n->t_len) - q->t_seq; 596*4645Swnj if (i < q->t_len) { 597*4645Swnj q->t_len -= i; 598*4645Swnj m_adj(dtom(q), i); 599*4645Swnj break; 6004601Swnj } 601*4645Swnj q = q->t_next; 602*4645Swnj m_freem(dtom(q->t_prev)); 603*4645Swnj remque(q->t_prev); 604*4645Swnj } 6054601Swnj 606*4645Swnj /* 607*4645Swnj * Stick new segment in its place. 608*4645Swnj */ 609*4645Swnj insque(n, q->t_prev); 610*4645Swnj /* 611*4645Swnj tp->rcv_seqcnt += n->t_len; 612*4645Swnj */ 6134601Swnj 6144601Swnj #ifdef notdef 615*4645Swnj /* 616*4645Swnj * Calculate available space and discard segments for 617*4645Swnj * which there is too much. 618*4645Swnj */ 619*4645Swnj q = tp->t_rcv_prev; 620*4645Swnj overage = (tp->t_socket->uc_rcc + tp->rcv_seqcnt) - tp->t_socket->uc_rhiwat; 621*4645Swnj if (overage > 0) 622*4645Swnj for (;;) { 623*4645Swnj i = MIN(q->t_len, overage); 624*4645Swnj overage -= i; 625*4645Swnj q->t_len -= i; 626*4645Swnj m_adj(q, -i); 627*4645Swnj if (q == n) 628*4645Swnj tp->tc_flags |= TC_DROPPED_TXT; 629*4645Swnj if (q->t_len) 630*4645Swnj break; 631*4645Swnj if (q == n) 632*4645Swnj printf("tcp_text dropall\n"); 633*4645Swnj q = q->t_prev; 634*4645Swnj remque(q->t_next); 635*4645Swnj } 636*4645Swnj #endif 6374601Swnj 638*4645Swnj /* 639*4645Swnj * Advance rcv_next through newly 640*4645Swnj * completed sequence space and force ACK. 641*4645Swnj */ 642*4645Swnj while (n->t_seq == tp->rcv_nxt) { 643*4645Swnj tp->rcv_nxt += n->t_len; 644*4645Swnj n = n->t_next; 645*4645Swnj if (n == (struct th *)tp) 646*4645Swnj break; 647*4645Swnj } 648*4645Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 649*4645Swnj return; 6504601Swnj 651*4645Swnj dropseg: 652*4645Swnj /* don't set TC_NET_KEEP */ 653*4645Swnj return; 6544601Swnj } 6554601Swnj 6564601Swnj present_data(tp) 6574601Swnj register struct tcb *tp; 6584601Swnj { 6594601Swnj register struct th *t; 6604601Swnj register struct ucb *up; 6614601Swnj register struct mbuf *m, **mp; 6624601Swnj seq_t ready; 6634601Swnj COUNT(PRESENT_DATA); 6644601Swnj 6654601Swnj /* connection must be synced and data available for user */ 6664601Swnj if (((tp->tc_flags&TC_SYN_ACKED) == 0) || 6674601Swnj (t = tp->t_rcv_next) == (struct th *)tp) 6684601Swnj return; 6694601Swnj up = tp->t_ucb; 6704601Swnj ready = firstempty(tp); /* seq # of last complete datum */ 6714601Swnj mp = &up->uc_rbuf; 6724601Swnj while (*mp) 6734601Swnj mp = &(*mp)->m_next; 6744601Swnj while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp && 6754601Swnj t_end(t) < ready) { 6764601Swnj tcp_deq(t); 6774601Swnj m = dtom(t); 6784601Swnj t = t->t_next; 6794601Swnj while (m) { 6804601Swnj if (m->m_len == 0) { 6814601Swnj m = m_free(m); 6824601Swnj continue; 6834601Swnj } 6844601Swnj up->uc_rsize++; 6854601Swnj if (m->m_off > MMAXOFF) 6864601Swnj up->uc_rsize += NMBPG; 6874601Swnj if (*mp == 0) 6884601Swnj *mp = m; 6894601Swnj mp = &m->m_next; 6904601Swnj m = *mp; 6914601Swnj } 6924601Swnj } 6934601Swnj if (up->uc_rsize != 0) 6944601Swnj netwakeup(up); 6954601Swnj /* 6964601Swnj * Let user know about foreign tcp close if no more data. 6974601Swnj */ 6984601Swnj if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 && 6994601Swnj rcv_empty(tp)) 7004601Swnj to_user(up, UCLOSED); 7014601Swnj } 7024604Swnj 7034604Swnj #ifdef TCPDEBUG 7044604Swnj tdb_setup(tp, n, input, tdp) 7054604Swnj struct tcb *tp; 7064604Swnj register struct th *n; 7074604Swnj int input; 7084604Swnj register struct tcp_debug *tdp; 7094604Swnj { 7104604Swnj 7114604Swnj tdp->td_tod = time; 7124604Swnj tdp->td_tcb = tp; 7134604Swnj tdp->td_old = tp->t_state; 7144604Swnj tdp->td_inp = input; 7154604Swnj tdp->td_tim = 0; 7164604Swnj tdp->td_new = -1; 7174604Swnj if (n) { 7184604Swnj tdp->td_sno = n->t_seq; 7194604Swnj tdp->td_ano = n->t_ackno; 7204604Swnj tdp->td_wno = n->t_win; 7214604Swnj tdp->td_lno = n->t_len; 7224604Swnj tdp->td_flg = n->th_flags; 7234604Swnj } else 7244604Swnj tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno = 7254604Swnj tdp->td_flg = 0; 7264604Swnj } 7274604Swnj 7284604Swnj tdb_stuff(tdp, nstate) 7294604Swnj struct tcp_debug *tdp; 7304604Swnj int nstate; 7314604Swnj { 7324604Swnj 7334604Swnj tdp->td_new = nstate; 7344604Swnj tcp_debug[tdbx++ % TDBSIZE] = *tdp; 7354604Swnj if (tcpconsdebug & 2) 7364604Swnj tcp_prt(tdp); 7374604Swnj } 7384604Swnj #endif 739