1*4770Swnj /* tcp_input.c 1.20 81/11/07 */ 24601Swnj 34601Swnj #include "../h/param.h" 44601Swnj #include "../h/systm.h" 54663Swnj #include "../h/mbuf.h" 64663Swnj #include "../h/socket.h" 74718Swnj #include "../inet/inet_cksum.h" 84663Swnj #include "../inet/inet.h" 94663Swnj #include "../inet/inet_systm.h" 104663Swnj #include "../inet/imp.h" 114663Swnj #include "../inet/inet_host.h" 124663Swnj #include "../inet/ip.h" 134663Swnj #include "../inet/tcp.h" 144663Swnj #include "../inet/tcp_fsm.h" 154601Swnj 164679Swnj int tcpcksum = 1; 174601Swnj 184601Swnj tcp_input(mp) 194601Swnj register struct mbuf *mp; 204601Swnj { 214673Swnj register struct th *n; /* known to be r10 */ 224697Swnj register int j; 234601Swnj register struct tcb *tp; 244601Swnj int nstate; 254601Swnj struct mbuf *m; 264601Swnj struct ucb *up; 274673Swnj int hlen, tlen; 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 504679Swnj if (tcpcksum) { 514679Swnj /* 524679Swnj * Checksum extended header and data 534679Swnj */ 544718Swnj CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen); 554718Swnj if (n->t_sum != 0) { 564679Swnj netstat.t_badsum++; 574601Swnj m_freem(mp); 584601Swnj return; 594601Swnj } 604601Swnj } 614601Swnj 624601Swnj /* 634601Swnj * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 644601Swnj */ 654681Swnj for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->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; 694681Swnj for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->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)) { 964675Swnj tcp_sndrst(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)) { 1054675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1064601Swnj goto badseg; 1074601Swnj } 1084601Swnj if (n->th_flags&TH_RST) { 1094675Swnj tcp_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: 1334675Swnj tcp_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) { 1424675Swnj tcp_sndrst(tp, n); /* 74 */ 1434601Swnj goto badseg; 1444601Swnj } 1454601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 1464679Swnj tcp_sndnull(tp); /* 74 */ 1474601Swnj goto badseg; 1484601Swnj } 1494601Swnj goto goodseg; 1504601Swnj } 1514601Swnj badseg: 1524601Swnj m_freem(mp); 1534601Swnj return; 1544601Swnj 1554601Swnj goodseg: 1564601Swnj #ifdef notdef 1574679Swnj /* DO SOMETHING ABOUT UNACK!!! */ 1584601Swnj /* 1594601Swnj * Defer processing if no buffer space for this connection. 1604601Swnj */ 1614601Swnj up = tp->t_ucb; 1624656Swnj if (up->uc_rcc > up->uc_rhiwat && 1634663Swnj && n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 1644601Swnj mp->m_act = (struct mbuf *)0; 1654601Swnj if ((m = tp->t_rcv_unack) != NULL) { 1664601Swnj while (m->m_act != NULL) 1674601Swnj m = m->m_act; 1684601Swnj m->m_act = mp; 1694601Swnj } else 1704601Swnj tp->t_rcv_unack = mp; 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; 183*4770Swnj #ifdef KPROF 1844601Swnj acounts[tp->t_state][INRECV]++; 185*4770Swnj #endif 1864601Swnj #ifdef TCPDEBUG 1874601Swnj if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 1884604Swnj tdb_setup(tp, n, INRECV, &tdb); 1894601Swnj } else 1904601Swnj tdb.td_tod = 0; 1914601Swnj #endif 1924601Swnj switch (tp->t_state) { 1934601Swnj 1944601Swnj case LISTEN: 1954601Swnj if (!syn_ok(tp, n) || 1964601Swnj ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 1974601Swnj nstate = EFAILEC; 1984601Swnj goto done; 1994601Swnj } 2004601Swnj tp->t_fport = n->t_src; 2014733Swnj tp->t_template = tcp_template(tp); 2024675Swnj tcp_ctldat(tp, n, 1); 2034601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2044601Swnj tp->t_finack = T_2ML; /* 3 */ 2054601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2064601Swnj nstate = CLOSE_WAIT; 2074601Swnj } else { 2084601Swnj tp->t_init = T_INIT / 2; /* 4 */ 2094601Swnj nstate = L_SYN_RCVD; 2104601Swnj } 2114601Swnj goto done; 2124601Swnj 2134601Swnj case SYN_SENT: 2144601Swnj if (!syn_ok(tp, n)) { 2154601Swnj nstate = EFAILEC; 2164601Swnj goto done; 2174601Swnj } 2184675Swnj tcp_ctldat(tp, n, 1); 2194601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2204690Swnj if ((n->th_flags&TH_ACK) == 0) { 2214601Swnj tp->t_finack = T_2ML; /* 9 */ 2224601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2234601Swnj } 2244601Swnj nstate = CLOSE_WAIT; 2254601Swnj goto done; 2264601Swnj } 2274690Swnj nstate = (n->th_flags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2284601Swnj goto done; 2294601Swnj 2304601Swnj case SYN_RCVD: 2314601Swnj case L_SYN_RCVD: 2324601Swnj if ((n->th_flags&TH_ACK) == 0 || 2334601Swnj (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 2344601Swnj nstate = EFAILEC; 2354601Swnj goto done; 2364601Swnj } 2374601Swnj goto input; 2384601Swnj 2394601Swnj case ESTAB: 2404601Swnj case FIN_W1: 2414601Swnj case FIN_W2: 2424601Swnj case TIME_WAIT: 2434601Swnj input: 2444675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2454601Swnj switch (tp->t_state) { 2464601Swnj 2474601Swnj case ESTAB: 2484601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2494601Swnj nstate = CLOSE_WAIT; 2504601Swnj break; 2514601Swnj 2524601Swnj case SYN_RCVD: 2534601Swnj case L_SYN_RCVD: 2544601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2554601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2564601Swnj break; 2574601Swnj 2584601Swnj case FIN_W1: 2594601Swnj j = ack_fin(tp, n); 2604601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2614601Swnj if (j) 2624601Swnj nstate = FIN_W2; /* 27 */ 2634601Swnj break; 2644601Swnj } 2654601Swnj tp->t_finack = T_2ML; 2664601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2674730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 2684601Swnj break; 2694601Swnj 2704601Swnj case FIN_W2: 2714601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2724601Swnj tp->t_finack = T_2ML; /* 29 */ 2734601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2744601Swnj nstate = TIME_WAIT; 2754601Swnj break; 2764601Swnj } 2774601Swnj break; 2784601Swnj } 2794601Swnj goto done; 2804601Swnj 2814601Swnj case CLOSE_WAIT: 2824601Swnj if (n->th_flags&TH_FIN) { 2834601Swnj if ((n->th_flags&TH_ACK) && 2844601Swnj n->t_ackno <= tp->seq_fin) { 2854675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 2864601Swnj tp->t_finack = T_2ML; 2874601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2884601Swnj } else 2894675Swnj tcp_sndctl(tp); /* 31 */ 2904601Swnj goto done; 2914601Swnj } 2924601Swnj goto input; 2934601Swnj 2944730Swnj case CLOSING: 2954601Swnj j = ack_fin(tp, n); 2964601Swnj if (n->th_flags&TH_FIN) { 2974675Swnj tcp_ctldat(tp, n, 0); 2984601Swnj tp->t_finack = T_2ML; 2994601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3004601Swnj if (j) 3014601Swnj nstate = TIME_WAIT; /* 23 */ 3024601Swnj goto done; 3034601Swnj } 3044601Swnj if (j) { 3054601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3064601Swnj if (rcv_empty(tp)) { 3074675Swnj tcp_close(tp, UCLOSED); /* 15 */ 3084601Swnj nstate = CLOSED; 3094601Swnj } else 3104601Swnj nstate = RCV_WAIT; /* 18 */ 3114601Swnj else 3124601Swnj nstate = TIME_WAIT; 3134601Swnj goto done; 3144601Swnj } 3154601Swnj goto input; 3164601Swnj 3174730Swnj case LAST_ACK: 3184601Swnj if (ack_fin(tp, n)) { 3194601Swnj if (rcv_empty(tp)) { /* 16 */ 3204675Swnj tcp_close(tp, UCLOSED); 3214601Swnj nstate = CLOSED; 3224601Swnj } else 3234601Swnj nstate = RCV_WAIT; /* 19 */ 3244601Swnj goto done; 3254601Swnj } 3264601Swnj if (n->th_flags&TH_FIN) { 3274675Swnj tcp_sndctl(tp); /* 31 */ 3284601Swnj goto done; 3294601Swnj } 3304601Swnj goto input; 3314601Swnj 3324601Swnj case RCV_WAIT: 3334601Swnj if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 3344601Swnj n->t_ackno <= tp->seq_fin) { 3354675Swnj tcp_ctldat(tp, n, 0); 3364601Swnj tp->t_finack = T_2ML; 3374601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3384601Swnj } 3394601Swnj goto done; 3404601Swnj } 3414601Swnj panic("tcp_input"); 3424601Swnj done: 3434601Swnj 3444601Swnj /* 3454601Swnj * Done with state*input specific processing. 3464601Swnj * Form trace records, free input if not needed, 3474601Swnj * and enter new state. 3484601Swnj */ 3494601Swnj #ifdef TCPDEBUG 3504604Swnj if (tdb.td_tod) 3514604Swnj tdb_stuff(&tdb, nstate); 3524601Swnj #endif 3534601Swnj switch (nstate) { 3544601Swnj 3554601Swnj case EFAILEC: 3564601Swnj m_freem(mp); 3574601Swnj return; 3584601Swnj 3594601Swnj default: 3604601Swnj tp->t_state = nstate; 3614601Swnj /* fall into ... */ 3624601Swnj 3634601Swnj case CLOSED: 3644601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3654601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3664690Swnj /* inline expansion of m_freem */ 3674690Swnj while (mp) { 3684690Swnj MFREE(mp, m); 3694690Swnj mp = m; 3704690Swnj } 3714601Swnj return; 3724601Swnj } 3734601Swnj /* NOTREACHED */ 3744601Swnj 3754601Swnj /* 3764601Swnj * Unwanted packed; free everything 3774601Swnj * but the header and return an rst. 3784601Swnj */ 3794601Swnj notwanted: 3804601Swnj m_freem(mp->m_next); 3814601Swnj mp->m_next = NULL; 3824601Swnj mp->m_len = sizeof(struct th); 3834601Swnj #define xchg(a,b) j=a; a=b; b=j 3844601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 3854601Swnj #undef xchg 3864601Swnj if (n->th_flags&TH_ACK) 3874601Swnj n->t_seq = n->t_ackno; 3884601Swnj else { 3894601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 3904601Swnj n->t_seq = 0; 3914601Swnj } 3924601Swnj n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 3934601Swnj n->th_flags ^= TH_ACK; 3944601Swnj n->t_len = htons(TCPSIZE); 3954601Swnj n->t_off = 5; 3964718Swnj n->t_sum = inet_cksum(mp, sizeof(struct th)); 3974601Swnj ((struct ip *)n)->ip_len = sizeof(struct th); 3984601Swnj ip_output(mp); 3994601Swnj netstat.t_badsegs++; 4004601Swnj } 4014601Swnj 4024675Swnj tcp_ctldat(tp, n, dataok) 4034601Swnj register struct tcb *tp; 4044601Swnj register struct th *n; 4054601Swnj { 4064679Swnj register struct mbuf *m; 4074679Swnj int sent; 4084679Swnj COUNT(TCP_CTLDAT); 4094601Swnj 4104601Swnj tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 4114601Swnj /* syn */ 4124601Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 4134601Swnj tp->irs = n->t_seq; 4144601Swnj tp->rcv_nxt = n->t_seq + 1; 4154601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4164601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4174601Swnj } 4184601Swnj /* ack */ 4194601Swnj if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4204601Swnj n->t_ackno > tp->snd_una) { 4214679Swnj register struct mbuf *mn; 4224679Swnj register struct ucb *up; 4234690Swnj int len; 4244679Swnj 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 /* if timed msg acked, set retrans time value */ 4324601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4334601Swnj tp->snd_una > tp->t_xmt_val) { 4344601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4354601Swnj if (tp->t_xmtime > T_REMAX) 4364601Swnj tp->t_xmtime = T_REMAX; 4374601Swnj } 4384601Swnj 4394601Swnj /* remove acked data from send buf */ 4404601Swnj len = tp->snd_una - tp->snd_off; 4414601Swnj m = up->uc_sbuf; 4424601Swnj while (len > 0 && m != NULL) 4434601Swnj if (m->m_len <= len) { 4444601Swnj len -= m->m_len; 4454601Swnj if (m->m_off > MMAXOFF) 4464601Swnj up->uc_ssize -= NMBPG; 4474601Swnj MFREE(m, mn); 4484601Swnj m = mn; 4494601Swnj up->uc_ssize--; 4504601Swnj } else { 4514601Swnj m->m_len -= len; 4524601Swnj m->m_off += len; 4534601Swnj break; 4544601Swnj } 4554601Swnj up->uc_sbuf = m; 4564601Swnj tp->snd_off = tp->snd_una; 4574601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4584601Swnj (tp->snd_una > tp->iss)) { 4594601Swnj tp->tc_flags |= TC_SYN_ACKED; 4604601Swnj tp->t_init = 0; 4614601Swnj } 4624601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4634601Swnj tp->tc_flags &= ~TC_SND_FIN; 4644601Swnj tp->t_rexmt = 0; 4654601Swnj tp->t_rexmttl = 0; 4664601Swnj tp->tc_flags |= TC_CANCELLED; 4674601Swnj netwakeup(tp->t_ucb); /* wasteful */ 4684601Swnj } 4694601Swnj /* win */ 4704601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 4714601Swnj tp->snd_wl = n->t_seq; 4724601Swnj tp->snd_wnd = n->t_win; 4734601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4744601Swnj tp->t_persist = 0; 4754601Swnj } 4764679Swnj if (dataok == 0) 4774679Swnj goto ctlonly; 4784601Swnj /* text */ 4794679Swnj if (n->t_len == 0) 4804679Swnj goto notext; 4814679Swnj { register int i; 4824679Swnj register struct th *p, *q; 4834679Swnj register struct mbuf *m; 4844679Swnj int overage; 4854601Swnj 4864645Swnj /* 4874645Swnj * Discard duplicate data already passed to user. 4884645Swnj */ 4894648Swnj if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 4904645Swnj i = tp->rcv_nxt - n->t_seq; 4914645Swnj if (i >= n->t_len) 4924679Swnj goto notext; 4934645Swnj n->t_seq += i; 4944645Swnj n->t_len -= i; 4954645Swnj m_adj(dtom(n), i); 4964601Swnj } 4974601Swnj 4984645Swnj /* 4994645Swnj * Find a segment which begins after this one does. 5004645Swnj */ 5014645Swnj for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 5024648Swnj if (SEQ_GT(q->t_seq, n->t_seq)) 5034645Swnj break; 5044601Swnj 5054645Swnj /* 5064645Swnj * If there is a preceding segment, it may provide some of 5074645Swnj * our data already. If so, drop the data from the incoming 5084645Swnj * segment. If it provides all of our data, drop us. 5094645Swnj */ 5104645Swnj if (q->t_prev != (struct th *)tp) { 5114648Swnj /* conversion to int (in i) handles seq wraparound */ 5124645Swnj i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 5134645Swnj if (i > 0) { 5144645Swnj if (i >= n->t_len) 5154679Swnj goto notext; /* w/o setting TC_NET_KEEP */ 5164645Swnj m_adj(dtom(tp), i); 5174645Swnj n->t_len -= i; 5184645Swnj n->t_seq += i; 5194601Swnj } 5204601Swnj } 5214601Swnj 5224645Swnj /* 5234645Swnj * While we overlap succeeding segments trim them or, 5244645Swnj * if they are completely covered, dequeue them. 5254645Swnj */ 5264648Swnj while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 5274645Swnj i = (n->t_seq + n->t_len) - q->t_seq; 5284645Swnj if (i < q->t_len) { 5294645Swnj q->t_len -= i; 5304645Swnj m_adj(dtom(q), i); 5314645Swnj break; 5324601Swnj } 5334645Swnj q = q->t_next; 5344645Swnj m_freem(dtom(q->t_prev)); 5354645Swnj remque(q->t_prev); 5364645Swnj } 5374601Swnj 5384645Swnj /* 5394645Swnj * Stick new segment in its place. 5404645Swnj */ 5414645Swnj insque(n, q->t_prev); 5424656Swnj tp->seqcnt += n->t_len; 5434601Swnj 5444601Swnj #ifdef notdef 5454645Swnj /* 5464645Swnj * Calculate available space and discard segments for 5474645Swnj * which there is too much. 5484645Swnj */ 5494645Swnj q = tp->t_rcv_prev; 5504648Swnj overage = 5514679Swnj (tp->t_ucb->uc_rcc + tp->rcv_seqcnt) - tp->t_ucb->uc_rhiwat; 5524645Swnj if (overage > 0) 5534645Swnj for (;;) { 5544645Swnj i = MIN(q->t_len, overage); 5554645Swnj overage -= i; 5564645Swnj q->t_len -= i; 5574645Swnj m_adj(q, -i); 5584645Swnj if (q == n) 5594645Swnj tp->tc_flags |= TC_DROPPED_TXT; 5604645Swnj if (q->t_len) 5614645Swnj break; 5624645Swnj if (q == n) 5634648Swnj panic("tcp_text dropall"); 5644645Swnj q = q->t_prev; 5654645Swnj remque(q->t_next); 5664645Swnj } 5674645Swnj #endif 5684601Swnj 5694645Swnj /* 5704648Swnj * Advance rcv_next through 5714648Swnj * newly completed sequence space 5724648Swnj * and return forcing an ack. 5734645Swnj */ 5744645Swnj while (n->t_seq == tp->rcv_nxt) { 5754648Swnj /* present data belongs here */ 5764645Swnj tp->rcv_nxt += n->t_len; 5774645Swnj n = n->t_next; 5784645Swnj if (n == (struct th *)tp) 5794645Swnj break; 5804645Swnj } 5814645Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 5824679Swnj } 5834679Swnj notext: 5844690Swnj urgeolfin: 5854679Swnj /* urg */ 5864679Swnj if (n->th_flags&TH_URG) { 5874679Swnj unsigned urgent; 5884601Swnj 5894679Swnj urgent = n->t_urp + n->t_seq; 5904679Swnj if (tp->rcv_nxt < urgent) { 5914679Swnj if (tp->rcv_urp <= tp->rcv_nxt) 5924679Swnj to_user(tp->t_ucb, UURGENT); 5934679Swnj tp->rcv_urp = urgent; 5944679Swnj } 5954679Swnj } 5964679Swnj /* eol */ 5974679Swnj if ((n->th_flags&TH_EOL) && 5984679Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0 && 5994679Swnj tp->t_rcv_prev != (struct th *)tp) { 6004679Swnj /* mark last mbuf */ 6014679Swnj m = dtom(tp->t_rcv_prev); 6024679Swnj if (m != NULL) { 6034679Swnj while (m->m_next != NULL) 6044679Swnj m = m->m_next; 6054679Swnj m->m_act = 6064679Swnj (struct mbuf *)(m->m_off + m->m_len - 1); 6074679Swnj } 6084679Swnj } 6094679Swnj ctlonly: 6104679Swnj /* fin */ 6114679Swnj if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 6124679Swnj seq_t last; 6134679Swnj 6144679Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 6154679Swnj /* do we really have fin ? */ 6164679Swnj last = firstempty(tp); 6174679Swnj if (tp->t_rcv_prev == (struct th *)tp || 6184679Swnj last == t_end(tp->t_rcv_prev)) { 6194679Swnj tp->tc_flags |= TC_FIN_RCVD; 6204679Swnj netwakeup(tp->t_ucb); /* poke */ 6214679Swnj } 6224679Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 6234679Swnj tp->rcv_nxt >= last) { 6244679Swnj tp->rcv_nxt = last + 1; /* fin seq */ 6254679Swnj tp->tc_flags |= TC_ACK_DUE; 6264679Swnj } 6274679Swnj } else 6284679Swnj tp->tc_flags |= TC_ACK_DUE; 6294679Swnj } 6304679Swnj 6314679Swnj /* respond */ 6324679Swnj sent = 0; 6334679Swnj if (tp->tc_flags&TC_ACK_DUE) 6344679Swnj sent = tcp_sndctl(tp); 6354679Swnj else if (tp->tc_flags&TC_NEW_WINDOW) { 6364679Swnj seq_t last = tp->snd_off; 6374679Swnj for (m = tp->t_ucb->uc_sbuf; m != NULL; m = m->m_next) /*###*/ 6384679Swnj last += m->m_len; /*###*/ 6394679Swnj if (tp->snd_nxt <= last || (tp->tc_flags&TC_SND_FIN)) 6404679Swnj sent = tcp_send(tp); 6414679Swnj } 6424679Swnj 6434679Swnj /* set for retrans */ 6444679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6454679Swnj (tp->tc_flags&TC_CANCELLED)) { 6464679Swnj tp->t_rexmt = tp->t_xmtime; 6474679Swnj tp->t_rexmttl = T_REXMTTL; 6484679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6494679Swnj tp->tc_flags &= ~TC_CANCELLED; 6504679Swnj } 6514690Swnj /* present data to user */ 6524690Swnj { register struct mbuf **mp; 6534690Swnj register struct ucb *up = tp->t_ucb; 6544690Swnj seq_t ready; 6554601Swnj 6564601Swnj /* connection must be synced and data available for user */ 6574656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6584601Swnj return; 6594679Swnj up = tp->t_ucb; 6604601Swnj mp = &up->uc_rbuf; 6614601Swnj while (*mp) 6624601Swnj mp = &(*mp)->m_next; 6634690Swnj n = tp->t_rcv_next; 6644656Swnj /* SHOULD PACK DATA IN HERE */ 6654690Swnj while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) { 6664690Swnj remque(n); 6674690Swnj m = dtom(n); 6684690Swnj up->uc_rcc += n->t_len; 6694690Swnj tp->seqcnt -= n->t_len; 6704656Swnj if (tp->seqcnt < 0) panic("present_data"); 6714690Swnj n = n->t_next; 6724601Swnj while (m) { 6734601Swnj if (m->m_len == 0) { 6744692Swnj MFREE(m, *mp); 6754692Swnj } else { 6764692Swnj *mp = m; 6774692Swnj mp = &m->m_next; 6784601Swnj } 6794601Swnj m = *mp; 6804601Swnj } 6814601Swnj } 6824656Swnj if (up->uc_rcc != 0) 6834601Swnj netwakeup(up); 6844656Swnj if ((tp->tc_flags&TC_FIN_RCVD) && /* ### */ 6854656Swnj (tp->tc_flags&TC_USR_CLOSED) == 0 && /* ### */ 6864656Swnj rcv_empty(tp)) /* ### */ 6874656Swnj to_user(up, UCLOSED); /* ### */ 6884690Swnj } 6894601Swnj } 690