1*4679Swnj /* tcp_input.c 1.12 81/10/30 */ 24601Swnj 34601Swnj #include "../h/param.h" 44601Swnj #include "../h/systm.h" 54663Swnj #include "../h/mbuf.h" 64663Swnj #include "../h/socket.h" 74663Swnj #include "../inet/inet.h" 84663Swnj #include "../inet/inet_systm.h" 94663Swnj #include "../inet/imp.h" 104663Swnj #include "../inet/inet_host.h" 114663Swnj #include "../inet/ip.h" 124663Swnj #include "../inet/tcp.h" 134663Swnj #include "../inet/tcp_fsm.h" 144601Swnj 15*4679Swnj int tcpcksum = 1; 164601Swnj 174601Swnj tcp_input(mp) 184601Swnj register struct mbuf *mp; 194601Swnj { 204673Swnj register struct th *n; /* known to be r10 */ 214673Swnj register int j; /* known to be r9 */ 224601Swnj register struct tcb *tp; 234601Swnj int nstate; 244601Swnj struct mbuf *m; 254601Swnj struct ucb *up; 264673Swnj int hlen, tlen; 274601Swnj u_short lport, fport; 284601Swnj #ifdef TCPDEBUG 294601Swnj struct tcp_debug tdb; 304601Swnj #endif 314601Swnj COUNT(TCP_INPUT); 324601Swnj 334601Swnj /* 344601Swnj * Build extended tcp header 354601Swnj */ 364601Swnj n = (struct th *)((int)mp + mp->m_off); 374601Swnj tlen = ((struct ip *)n)->ip_len; 384601Swnj n->t_len = htons(tlen); 394601Swnj n->t_next = NULL; 404601Swnj n->t_prev = NULL; 414601Swnj n->t_x1 = 0; 424601Swnj lport = ntohs(n->t_dst); 434601Swnj fport = ntohs(n->t_src); 444601Swnj 454601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 464601Swnj if ((hlen = n->t_off << 2) > mp->m_len) 474601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 484601Swnj 49*4679Swnj if (tcpcksum) { 50*4679Swnj /* 51*4679Swnj * Checksum extended header and data 52*4679Swnj */ 53*4679Swnj j = n->t_sum; n->t_sum = 0; 544673Swnj #ifdef vax 55*4679Swnj if (tlen == 20) { 56*4679Swnj asm("addl3 $8,r10,r0; movl (r0)+,r1; addl2 (r0)+,r1"); 57*4679Swnj asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1"); 58*4679Swnj asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1"); 59*4679Swnj asm("adwc $0,r1; ashl $-16,r1,r0; addw2 r0,r1"); 60*4679Swnj asm("adwc $0,r1"); /* ### */ 61*4679Swnj asm("mcoml r1,r1; movzwl r1,r1; subl2 r1,r9"); 62*4679Swnj } else 634673Swnj #endif 64*4679Swnj j -= cksum(mp, sizeof (struct ip) + tlen); 65*4679Swnj if (j != 0) { 66*4679Swnj netstat.t_badsum++; 674601Swnj m_freem(mp); 684601Swnj return; 694601Swnj } 704601Swnj } 714601Swnj 724601Swnj /* 734601Swnj * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 744601Swnj */ 754663Swnj for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next) 764601Swnj if (tp->t_lport == lport && tp->t_fport == fport && 774601Swnj tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr) 784601Swnj goto found; 794663Swnj for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next) 804601Swnj if (tp->t_lport == lport && 814601Swnj (tp->t_fport==fport || tp->t_fport==0) && 824601Swnj (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr || 834601Swnj tp->t_ucb->uc_host->h_addr.s_addr == 0)) 844601Swnj goto found; 854601Swnj goto notwanted; 864601Swnj found: 874601Swnj 884601Swnj /* 894601Swnj * Byte swap header 904601Swnj */ 914601Swnj n->t_len = tlen - hlen; 924601Swnj n->t_src = fport; 934601Swnj n->t_dst = lport; 944601Swnj n->t_seq = ntohl(n->t_seq); 954601Swnj n->t_ackno = ntohl(n->t_ackno); 964601Swnj n->t_win = ntohs(n->t_win); 974601Swnj n->t_urp = ntohs(n->t_urp); 984601Swnj 994601Swnj /* 1004601Swnj * Check segment seq # and do rst processing 1014601Swnj */ 1024601Swnj switch (tp->t_state) { 1034601Swnj 1044601Swnj case LISTEN: 1054601Swnj if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) { 1064675Swnj tcp_sndrst(tp, n); 1074601Swnj goto badseg; 1084601Swnj } 1094601Swnj if (n->th_flags&TH_RST) 1104601Swnj goto badseg; 1114601Swnj goto goodseg; 1124601Swnj 1134601Swnj case SYN_SENT: 1144601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1154675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1164601Swnj goto badseg; 1174601Swnj } 1184601Swnj if (n->th_flags&TH_RST) { 1194675Swnj tcp_close(tp, URESET); /* 70 */ 1204601Swnj tp->t_state = CLOSED; 1214601Swnj goto badseg; 1224601Swnj } 1234601Swnj goto goodseg; 1244601Swnj 1254601Swnj default: 1264601Swnj if ((n->th_flags&TH_RST) == 0) 1274601Swnj goto common; 1284601Swnj if (n->t_seq < tp->rcv_nxt) /* bad rst */ 1294601Swnj goto badseg; /* 69 */ 1304601Swnj switch (tp->t_state) { 1314601Swnj 1324601Swnj case L_SYN_RCVD: 1334601Swnj if (ack_ok(tp, n) == 0) 1344601Swnj goto badseg; /* 69 */ 1354601Swnj tp->t_rexmt = 0; 1364601Swnj tp->t_rexmttl = 0; 1374601Swnj tp->t_persist = 0; 1384601Swnj h_free(tp->t_ucb->uc_host); 1394601Swnj tp->t_state = LISTEN; 1404601Swnj goto badseg; 1414601Swnj 1424601Swnj default: 1434675Swnj tcp_close(tp, URESET); /* 66 */ 1444601Swnj tp->t_state = CLOSED; 1454601Swnj goto badseg; 1464601Swnj } 1474601Swnj /*NOTREACHED*/ 1484601Swnj 1494601Swnj case SYN_RCVD: 1504601Swnj common: 1514601Swnj if (ack_ok(tp, n) == 0) { 1524675Swnj tcp_sndrst(tp, n); /* 74 */ 1534601Swnj goto badseg; 1544601Swnj } 1554601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 156*4679Swnj tcp_sndnull(tp); /* 74 */ 1574601Swnj goto badseg; 1584601Swnj } 1594601Swnj goto goodseg; 1604601Swnj } 1614601Swnj badseg: 1624601Swnj m_freem(mp); 1634601Swnj return; 1644601Swnj 1654601Swnj goodseg: 1664601Swnj #ifdef notdef 167*4679Swnj /* DO SOMETHING ABOUT UNACK!!! */ 1684601Swnj /* 1694601Swnj * Defer processing if no buffer space for this connection. 1704601Swnj */ 1714601Swnj up = tp->t_ucb; 1724656Swnj if (up->uc_rcc > up->uc_rhiwat && 1734663Swnj && n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 1744601Swnj mp->m_act = (struct mbuf *)0; 1754601Swnj if ((m = tp->t_rcv_unack) != NULL) { 1764601Swnj while (m->m_act != NULL) 1774601Swnj m = m->m_act; 1784601Swnj m->m_act = mp; 1794601Swnj } else 1804601Swnj tp->t_rcv_unack = mp; 1814601Swnj return; 1824601Swnj } 1834601Swnj #endif 1844601Swnj 1854601Swnj /* 1864601Swnj * Discard ip header, and do tcp input processing. 1874601Swnj */ 1884601Swnj hlen += sizeof(struct ip); 1894601Swnj mp->m_off += hlen; 1904601Swnj mp->m_len -= hlen; 1914601Swnj nstate = tp->t_state; 1924601Swnj tp->tc_flags &= ~TC_NET_KEEP; 1934601Swnj acounts[tp->t_state][INRECV]++; 1944601Swnj #ifdef TCPDEBUG 1954601Swnj if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) { 1964604Swnj tdb_setup(tp, n, INRECV, &tdb); 1974601Swnj } else 1984601Swnj tdb.td_tod = 0; 1994601Swnj #endif 2004601Swnj switch (tp->t_state) { 2014601Swnj 2024601Swnj case LISTEN: 2034601Swnj if (!syn_ok(tp, n) || 2044601Swnj ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) { 2054601Swnj nstate = EFAILEC; 2064601Swnj goto done; 2074601Swnj } 2084601Swnj tp->t_fport = n->t_src; 2094603Sroot tp->t_ucb->uc_template = tcp_template(tp); 2104675Swnj tcp_ctldat(tp, n, 1); 2114601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2124601Swnj tp->t_finack = T_2ML; /* 3 */ 2134601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2144601Swnj nstate = CLOSE_WAIT; 2154601Swnj } else { 2164601Swnj tp->t_init = T_INIT / 2; /* 4 */ 2174601Swnj nstate = L_SYN_RCVD; 2184601Swnj } 2194601Swnj goto done; 2204601Swnj 2214601Swnj case SYN_SENT: 2224601Swnj if (!syn_ok(tp, n)) { 2234601Swnj nstate = EFAILEC; 2244601Swnj goto done; 2254601Swnj } 2264675Swnj tcp_ctldat(tp, n, 1); 2274601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2284601Swnj if (n->th_flags&TH_ACK) { 2294601Swnj if (n->t_ackno > tp->iss) 2304601Swnj present_data(tp); /* 32 */ 2314601Swnj } else { 2324601Swnj tp->t_finack = T_2ML; /* 9 */ 2334601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2344601Swnj } 2354601Swnj nstate = CLOSE_WAIT; 2364601Swnj goto done; 2374601Swnj } 2384601Swnj if (n->th_flags&TH_ACK) { 2394601Swnj present_data(tp); /* 11 */ 2404601Swnj nstate = ESTAB; 2414601Swnj } else 2424601Swnj nstate = SYN_RCVD; /* 8 */ 2434601Swnj goto done; 2444601Swnj 2454601Swnj case SYN_RCVD: 2464601Swnj case L_SYN_RCVD: 2474601Swnj if ((n->th_flags&TH_ACK) == 0 || 2484601Swnj (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) { 2494601Swnj nstate = EFAILEC; 2504601Swnj goto done; 2514601Swnj } 2524601Swnj goto input; 2534601Swnj 2544601Swnj case ESTAB: 2554601Swnj case FIN_W1: 2564601Swnj case FIN_W2: 2574601Swnj case TIME_WAIT: 2584601Swnj input: 2594675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2604601Swnj present_data(tp); 2614601Swnj switch (tp->t_state) { 2624601Swnj 2634601Swnj case ESTAB: 2644601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2654601Swnj nstate = CLOSE_WAIT; 2664601Swnj break; 2674601Swnj 2684601Swnj case SYN_RCVD: 2694601Swnj case L_SYN_RCVD: 2704601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2714601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2724601Swnj break; 2734601Swnj 2744601Swnj case FIN_W1: 2754601Swnj j = ack_fin(tp, n); 2764601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2774601Swnj if (j) 2784601Swnj nstate = FIN_W2; /* 27 */ 2794601Swnj break; 2804601Swnj } 2814601Swnj tp->t_finack = T_2ML; 2824601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2834601Swnj nstate = j ? TIME_WAIT : CLOSING1; /* 28:26 */ 2844601Swnj break; 2854601Swnj 2864601Swnj case FIN_W2: 2874601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2884601Swnj tp->t_finack = T_2ML; /* 29 */ 2894601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2904601Swnj nstate = TIME_WAIT; 2914601Swnj break; 2924601Swnj } 2934601Swnj break; 2944601Swnj } 2954601Swnj goto done; 2964601Swnj 2974601Swnj case CLOSE_WAIT: 2984601Swnj if (n->th_flags&TH_FIN) { 2994601Swnj if ((n->th_flags&TH_ACK) && 3004601Swnj n->t_ackno <= tp->seq_fin) { 3014675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 3024601Swnj tp->t_finack = T_2ML; 3034601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3044601Swnj } else 3054675Swnj tcp_sndctl(tp); /* 31 */ 3064601Swnj goto done; 3074601Swnj } 3084601Swnj goto input; 3094601Swnj 3104601Swnj case CLOSING1: 3114601Swnj j = ack_fin(tp, n); 3124601Swnj if (n->th_flags&TH_FIN) { 3134675Swnj tcp_ctldat(tp, n, 0); 3144601Swnj tp->t_finack = T_2ML; 3154601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3164601Swnj if (j) 3174601Swnj nstate = TIME_WAIT; /* 23 */ 3184601Swnj goto done; 3194601Swnj } 3204601Swnj if (j) { 3214601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3224601Swnj if (rcv_empty(tp)) { 3234675Swnj tcp_close(tp, UCLOSED); /* 15 */ 3244601Swnj nstate = CLOSED; 3254601Swnj } else 3264601Swnj nstate = RCV_WAIT; /* 18 */ 3274601Swnj else 3284601Swnj nstate = TIME_WAIT; 3294601Swnj goto done; 3304601Swnj } 3314601Swnj goto input; 3324601Swnj 3334601Swnj case CLOSING2: 3344601Swnj if (ack_fin(tp, n)) { 3354601Swnj if (rcv_empty(tp)) { /* 16 */ 3364675Swnj tcp_close(tp, UCLOSED); 3374601Swnj nstate = CLOSED; 3384601Swnj } else 3394601Swnj nstate = RCV_WAIT; /* 19 */ 3404601Swnj goto done; 3414601Swnj } 3424601Swnj if (n->th_flags&TH_FIN) { 3434675Swnj tcp_sndctl(tp); /* 31 */ 3444601Swnj goto done; 3454601Swnj } 3464601Swnj goto input; 3474601Swnj 3484601Swnj case RCV_WAIT: 3494601Swnj if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) && 3504601Swnj n->t_ackno <= tp->seq_fin) { 3514675Swnj tcp_ctldat(tp, n, 0); 3524601Swnj tp->t_finack = T_2ML; 3534601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3544601Swnj } 3554601Swnj goto done; 3564601Swnj } 3574601Swnj panic("tcp_input"); 3584601Swnj done: 3594601Swnj 3604601Swnj /* 3614601Swnj * Done with state*input specific processing. 3624601Swnj * Form trace records, free input if not needed, 3634601Swnj * and enter new state. 3644601Swnj */ 3654601Swnj #ifdef TCPDEBUG 3664604Swnj if (tdb.td_tod) 3674604Swnj tdb_stuff(&tdb, nstate); 3684601Swnj #endif 3694601Swnj switch (nstate) { 3704601Swnj 3714601Swnj case EFAILEC: 3724601Swnj m_freem(mp); 3734601Swnj return; 3744601Swnj 3754601Swnj default: 3764601Swnj tp->t_state = nstate; 3774601Swnj /* fall into ... */ 3784601Swnj 3794601Swnj case CLOSED: 3804601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3814601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3824601Swnj m_freem(mp); 3834601Swnj return; 3844601Swnj } 3854601Swnj /* NOTREACHED */ 3864601Swnj 3874601Swnj /* 3884601Swnj * Unwanted packed; free everything 3894601Swnj * but the header and return an rst. 3904601Swnj */ 3914601Swnj notwanted: 3924601Swnj m_freem(mp->m_next); 3934601Swnj mp->m_next = NULL; 3944601Swnj mp->m_len = sizeof(struct th); 3954601Swnj #define xchg(a,b) j=a; a=b; b=j 3964601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 3974601Swnj #undef xchg 3984601Swnj if (n->th_flags&TH_ACK) 3994601Swnj n->t_seq = n->t_ackno; 4004601Swnj else { 4014601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 4024601Swnj n->t_seq = 0; 4034601Swnj } 4044601Swnj n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */ 4054601Swnj n->th_flags ^= TH_ACK; 4064601Swnj n->t_len = htons(TCPSIZE); 4074601Swnj n->t_off = 5; 4084601Swnj n->t_sum = cksum(mp, sizeof(struct th)); 4094601Swnj ((struct ip *)n)->ip_len = sizeof(struct th); 4104601Swnj ip_output(mp); 4114601Swnj netstat.t_badsegs++; 4124601Swnj } 4134601Swnj 4144675Swnj tcp_ctldat(tp, n, dataok) 4154601Swnj register struct tcb *tp; 4164601Swnj register struct th *n; 4174601Swnj { 418*4679Swnj register struct mbuf *m; 419*4679Swnj int sent; 420*4679Swnj COUNT(TCP_CTLDAT); 4214601Swnj 4224601Swnj tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 4234601Swnj /* syn */ 4244601Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) { 4254601Swnj tp->irs = n->t_seq; 4264601Swnj tp->rcv_nxt = n->t_seq + 1; 4274601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4284601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4294601Swnj } 4304601Swnj /* ack */ 4314601Swnj if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4324601Swnj n->t_ackno > tp->snd_una) { 433*4679Swnj register struct mbuf *mn; 434*4679Swnj register struct ucb *up; 435*4679Swnj register int len; 436*4679Swnj 4374601Swnj up = tp->t_ucb; 4384601Swnj 4394601Swnj /* update snd_una and snd_nxt */ 4404601Swnj tp->snd_una = n->t_ackno; 4414601Swnj if (tp->snd_una > tp->snd_nxt) 4424601Swnj tp->snd_nxt = tp->snd_una; 4434601Swnj 4444601Swnj /* if timed msg acked, set retrans time value */ 4454601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4464601Swnj tp->snd_una > tp->t_xmt_val) { 4474601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4484601Swnj if (tp->t_xmtime > T_REMAX) 4494601Swnj tp->t_xmtime = T_REMAX; 4504601Swnj } 4514601Swnj 4524601Swnj /* remove acked data from send buf */ 4534601Swnj len = tp->snd_una - tp->snd_off; 4544601Swnj m = up->uc_sbuf; 4554601Swnj while (len > 0 && m != NULL) 4564601Swnj if (m->m_len <= len) { 4574601Swnj len -= m->m_len; 4584601Swnj if (m->m_off > MMAXOFF) 4594601Swnj up->uc_ssize -= NMBPG; 4604601Swnj MFREE(m, mn); 4614601Swnj m = mn; 4624601Swnj up->uc_ssize--; 4634601Swnj } else { 4644601Swnj m->m_len -= len; 4654601Swnj m->m_off += len; 4664601Swnj break; 4674601Swnj } 4684601Swnj up->uc_sbuf = m; 4694601Swnj tp->snd_off = tp->snd_una; 4704601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4714601Swnj (tp->snd_una > tp->iss)) { 4724601Swnj tp->tc_flags |= TC_SYN_ACKED; 4734601Swnj tp->t_init = 0; 4744601Swnj } 4754601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4764601Swnj tp->tc_flags &= ~TC_SND_FIN; 4774601Swnj tp->t_rexmt = 0; 4784601Swnj tp->t_rexmttl = 0; 4794601Swnj tp->tc_flags |= TC_CANCELLED; 4804601Swnj netwakeup(tp->t_ucb); /* wasteful */ 4814601Swnj } 4824601Swnj /* win */ 4834601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 4844601Swnj tp->snd_wl = n->t_seq; 4854601Swnj tp->snd_wnd = n->t_win; 4864601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4874601Swnj tp->t_persist = 0; 4884601Swnj } 489*4679Swnj if (dataok == 0) 490*4679Swnj goto ctlonly; 4914601Swnj /* text */ 492*4679Swnj if (n->t_len == 0) 493*4679Swnj goto notext; 494*4679Swnj { register int i; 495*4679Swnj register struct th *p, *q; 496*4679Swnj register struct mbuf *m; 497*4679Swnj int overage; 4984601Swnj 4994645Swnj /* 5004645Swnj * Discard duplicate data already passed to user. 5014645Swnj */ 5024648Swnj if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 5034645Swnj i = tp->rcv_nxt - n->t_seq; 5044645Swnj if (i >= n->t_len) 505*4679Swnj goto notext; 5064645Swnj n->t_seq += i; 5074645Swnj n->t_len -= i; 5084645Swnj m_adj(dtom(n), i); 5094601Swnj } 5104601Swnj 5114645Swnj /* 5124645Swnj * Find a segment which begins after this one does. 5134645Swnj */ 5144645Swnj for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next) 5154648Swnj if (SEQ_GT(q->t_seq, n->t_seq)) 5164645Swnj break; 5174601Swnj 5184645Swnj /* 5194645Swnj * If there is a preceding segment, it may provide some of 5204645Swnj * our data already. If so, drop the data from the incoming 5214645Swnj * segment. If it provides all of our data, drop us. 5224645Swnj */ 5234645Swnj if (q->t_prev != (struct th *)tp) { 5244648Swnj /* conversion to int (in i) handles seq wraparound */ 5254645Swnj i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 5264645Swnj if (i > 0) { 5274645Swnj if (i >= n->t_len) 528*4679Swnj goto notext; /* w/o setting TC_NET_KEEP */ 5294645Swnj m_adj(dtom(tp), i); 5304645Swnj n->t_len -= i; 5314645Swnj n->t_seq += i; 5324601Swnj } 5334601Swnj } 5344601Swnj 5354645Swnj /* 5364645Swnj * While we overlap succeeding segments trim them or, 5374645Swnj * if they are completely covered, dequeue them. 5384645Swnj */ 5394648Swnj while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 5404645Swnj i = (n->t_seq + n->t_len) - q->t_seq; 5414645Swnj if (i < q->t_len) { 5424645Swnj q->t_len -= i; 5434645Swnj m_adj(dtom(q), i); 5444645Swnj break; 5454601Swnj } 5464645Swnj q = q->t_next; 5474645Swnj m_freem(dtom(q->t_prev)); 5484645Swnj remque(q->t_prev); 5494645Swnj } 5504601Swnj 5514645Swnj /* 5524645Swnj * Stick new segment in its place. 5534645Swnj */ 5544645Swnj insque(n, q->t_prev); 5554656Swnj tp->seqcnt += n->t_len; 5564601Swnj 5574601Swnj #ifdef notdef 5584645Swnj /* 5594645Swnj * Calculate available space and discard segments for 5604645Swnj * which there is too much. 5614645Swnj */ 5624645Swnj q = tp->t_rcv_prev; 5634648Swnj overage = 564*4679Swnj (tp->t_ucb->uc_rcc + tp->rcv_seqcnt) - tp->t_ucb->uc_rhiwat; 5654645Swnj if (overage > 0) 5664645Swnj for (;;) { 5674645Swnj i = MIN(q->t_len, overage); 5684645Swnj overage -= i; 5694645Swnj q->t_len -= i; 5704645Swnj m_adj(q, -i); 5714645Swnj if (q == n) 5724645Swnj tp->tc_flags |= TC_DROPPED_TXT; 5734645Swnj if (q->t_len) 5744645Swnj break; 5754645Swnj if (q == n) 5764648Swnj panic("tcp_text dropall"); 5774645Swnj q = q->t_prev; 5784645Swnj remque(q->t_next); 5794645Swnj } 5804645Swnj #endif 5814601Swnj 5824645Swnj /* 5834648Swnj * Advance rcv_next through 5844648Swnj * newly completed sequence space 5854648Swnj * and return forcing an ack. 5864645Swnj */ 5874645Swnj while (n->t_seq == tp->rcv_nxt) { 5884648Swnj /* present data belongs here */ 5894645Swnj tp->rcv_nxt += n->t_len; 5904645Swnj n = n->t_next; 5914645Swnj if (n == (struct th *)tp) 5924645Swnj break; 5934645Swnj } 5944645Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 595*4679Swnj } 596*4679Swnj notext: 597*4679Swnj /* urg */ 598*4679Swnj if (n->th_flags&TH_URG) { 599*4679Swnj unsigned urgent; 6004601Swnj 601*4679Swnj urgent = n->t_urp + n->t_seq; 602*4679Swnj if (tp->rcv_nxt < urgent) { 603*4679Swnj if (tp->rcv_urp <= tp->rcv_nxt) 604*4679Swnj to_user(tp->t_ucb, UURGENT); 605*4679Swnj tp->rcv_urp = urgent; 606*4679Swnj } 607*4679Swnj } 608*4679Swnj /* eol */ 609*4679Swnj if ((n->th_flags&TH_EOL) && 610*4679Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0 && 611*4679Swnj tp->t_rcv_prev != (struct th *)tp) { 612*4679Swnj /* mark last mbuf */ 613*4679Swnj m = dtom(tp->t_rcv_prev); 614*4679Swnj if (m != NULL) { 615*4679Swnj while (m->m_next != NULL) 616*4679Swnj m = m->m_next; 617*4679Swnj m->m_act = 618*4679Swnj (struct mbuf *)(m->m_off + m->m_len - 1); 619*4679Swnj } 620*4679Swnj } 621*4679Swnj ctlonly: 622*4679Swnj /* fin */ 623*4679Swnj if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) { 624*4679Swnj seq_t last; 625*4679Swnj 626*4679Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 627*4679Swnj /* do we really have fin ? */ 628*4679Swnj last = firstempty(tp); 629*4679Swnj if (tp->t_rcv_prev == (struct th *)tp || 630*4679Swnj last == t_end(tp->t_rcv_prev)) { 631*4679Swnj tp->tc_flags |= TC_FIN_RCVD; 632*4679Swnj netwakeup(tp->t_ucb); /* poke */ 633*4679Swnj } 634*4679Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 635*4679Swnj tp->rcv_nxt >= last) { 636*4679Swnj tp->rcv_nxt = last + 1; /* fin seq */ 637*4679Swnj tp->tc_flags |= TC_ACK_DUE; 638*4679Swnj } 639*4679Swnj } else 640*4679Swnj tp->tc_flags |= TC_ACK_DUE; 641*4679Swnj } 642*4679Swnj 643*4679Swnj /* respond */ 644*4679Swnj sent = 0; 645*4679Swnj if (tp->tc_flags&TC_ACK_DUE) 646*4679Swnj sent = tcp_sndctl(tp); 647*4679Swnj else if (tp->tc_flags&TC_NEW_WINDOW) { 648*4679Swnj seq_t last = tp->snd_off; 649*4679Swnj for (m = tp->t_ucb->uc_sbuf; m != NULL; m = m->m_next) /*###*/ 650*4679Swnj last += m->m_len; /*###*/ 651*4679Swnj if (tp->snd_nxt <= last || (tp->tc_flags&TC_SND_FIN)) 652*4679Swnj sent = tcp_send(tp); 653*4679Swnj } 654*4679Swnj 655*4679Swnj /* set for retrans */ 656*4679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 657*4679Swnj (tp->tc_flags&TC_CANCELLED)) { 658*4679Swnj tp->t_rexmt = tp->t_xmtime; 659*4679Swnj tp->t_rexmttl = T_REXMTTL; 660*4679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 661*4679Swnj tp->tc_flags &= ~TC_CANCELLED; 662*4679Swnj } 6634601Swnj } 6644601Swnj 6654601Swnj present_data(tp) 6664601Swnj register struct tcb *tp; 6674601Swnj { 6684601Swnj register struct th *t; 669*4679Swnj register struct ucb *up; 6704601Swnj register struct mbuf *m, **mp; 6714601Swnj seq_t ready; 6724601Swnj COUNT(PRESENT_DATA); 6734601Swnj 6744601Swnj /* connection must be synced and data available for user */ 6754656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6764601Swnj return; 677*4679Swnj up = tp->t_ucb; 6784601Swnj mp = &up->uc_rbuf; 6794601Swnj while (*mp) 6804601Swnj mp = &(*mp)->m_next; 6814656Swnj t = tp->t_rcv_next; 6824656Swnj /* SHOULD PACK DATA IN HERE */ 6834656Swnj while (t != (struct th *)tp && t->t_seq < tp->rcv_nxt) { 6844656Swnj remque(t); 6854601Swnj m = dtom(t); 6864656Swnj up->uc_rcc += t->t_len; 6874656Swnj tp->seqcnt -= t->t_len; 6884656Swnj if (tp->seqcnt < 0) panic("present_data"); 6894601Swnj t = t->t_next; 6904601Swnj while (m) { 6914601Swnj if (m->m_len == 0) { 6924601Swnj m = m_free(m); 6934601Swnj continue; 6944601Swnj } 6954656Swnj *mp = m; 6964601Swnj mp = &m->m_next; 6974601Swnj m = *mp; 6984601Swnj } 6994601Swnj } 7004656Swnj if (up->uc_rcc != 0) 7014601Swnj netwakeup(up); 7024656Swnj if ((tp->tc_flags&TC_FIN_RCVD) && /* ### */ 7034656Swnj (tp->tc_flags&TC_USR_CLOSED) == 0 && /* ### */ 7044656Swnj rcv_empty(tp)) /* ### */ 7054656Swnj to_user(up, UCLOSED); /* ### */ 7064601Swnj } 707