1*4884Swnj /* tcp_input.c 1.22 81/11/14 */ 24601Swnj 34601Swnj #include "../h/param.h" 44601Swnj #include "../h/systm.h" 54663Swnj #include "../h/mbuf.h" 64663Swnj #include "../h/socket.h" 74803Swnj #include "../h/socketvar.h" 84803Swnj #include "../net/inet_cksum.h" 94803Swnj #include "../net/inet.h" 10*4884Swnj #include "../net/inet_pcb.h" 114803Swnj #include "../net/inet_systm.h" 124803Swnj #include "../net/imp.h" 134803Swnj #include "../net/inet_host.h" 144803Swnj #include "../net/ip.h" 154803Swnj #include "../net/tcp.h" 164803Swnj #include "../net/tcp_fsm.h" 174803Swnj #include "../net/tcp_var.h" 184803Swnj #include "/usr/include/errno.h" 194601Swnj 204679Swnj int tcpcksum = 1; 214601Swnj 22*4884Swnj tcp_drain() 234803Swnj { 24*4884Swnj register struct inpcb *ip; 254803Swnj 26*4884Swnj for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) 27*4884Swnj tcp_drainunack(intotcpcb(ip)); 284803Swnj } 294803Swnj 30*4884Swnj tcp_drainunack(tp) 31*4884Swnj register struct tcpcb *tp; 32*4884Swnj { 33*4884Swnj register struct mbuf *m; 34*4884Swnj 35*4884Swnj for (m = tp->seg_unack; m; m = m->m_act) 36*4884Swnj m_freem(m); 37*4884Swnj tp->seg_unack = 0; 38*4884Swnj } 39*4884Swnj 40*4884Swnj tcp_ctlinput(m) 41*4884Swnj struct mbuf *m; 42*4884Swnj { 43*4884Swnj 44*4884Swnj m_freem(m); 45*4884Swnj } 46*4884Swnj 474601Swnj tcp_input(mp) 484601Swnj register struct mbuf *mp; 494601Swnj { 50*4884Swnj register struct tcpiphdr *n; /* known to be r10 */ 514697Swnj register int j; 52*4884Swnj register struct tcpcb *tp; 53*4884Swnj struct inpcb *inp; 544803Swnj register int thflags; 554601Swnj int nstate; 564601Swnj struct mbuf *m; 574803Swnj struct socket *so; 584673Swnj int hlen, tlen; 594601Swnj u_short lport, fport; 604601Swnj #ifdef TCPDEBUG 614601Swnj struct tcp_debug tdb; 624601Swnj #endif 634601Swnj COUNT(TCP_INPUT); 644601Swnj 654601Swnj /* 664601Swnj * Build extended tcp header 674601Swnj */ 68*4884Swnj n = mtod(mp, struct tcpiphdr *); 694803Swnj thflags = n->th_flags; 704601Swnj tlen = ((struct ip *)n)->ip_len; 714601Swnj n->t_len = htons(tlen); 724601Swnj n->t_next = NULL; 734601Swnj n->t_prev = NULL; 744601Swnj n->t_x1 = 0; 754601Swnj lport = ntohs(n->t_dst); 764601Swnj fport = ntohs(n->t_src); 774601Swnj 784601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 794601Swnj if ((hlen = n->t_off << 2) > mp->m_len) 804601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 814601Swnj 824679Swnj if (tcpcksum) { 834679Swnj /* 844679Swnj * Checksum extended header and data 854679Swnj */ 864718Swnj CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen); 874718Swnj if (n->t_sum != 0) { 884679Swnj netstat.t_badsum++; 894601Swnj m_freem(mp); 904601Swnj return; 914601Swnj } 924601Swnj } 934601Swnj 944601Swnj /* 95*4884Swnj * Find tcb for message. 964601Swnj */ 97*4884Swnj inp = in_pcblookup(&tcb, &n->t_s, fport, &n_lhost, lport); 98*4884Swnj if (inp == 0) 99*4884Swnj goto notwanted; 1004601Swnj 1014601Swnj /* 1024601Swnj * Byte swap header 1034601Swnj */ 1044601Swnj n->t_len = tlen - hlen; 1054601Swnj n->t_src = fport; 1064601Swnj n->t_dst = lport; 1074601Swnj n->t_seq = ntohl(n->t_seq); 1084601Swnj n->t_ackno = ntohl(n->t_ackno); 1094601Swnj n->t_win = ntohs(n->t_win); 1104601Swnj n->t_urp = ntohs(n->t_urp); 1114601Swnj 1124601Swnj /* 1134601Swnj * Check segment seq # and do rst processing 1144601Swnj */ 1154601Swnj switch (tp->t_state) { 1164601Swnj 1174601Swnj case LISTEN: 1184803Swnj if ((thflags&TH_ACK) || !syn_ok(tp, n)) { 1194675Swnj tcp_sndrst(tp, n); 1204601Swnj goto badseg; 1214601Swnj } 1224803Swnj if (thflags&TH_RST) 1234601Swnj goto badseg; 1244601Swnj goto goodseg; 1254601Swnj 1264601Swnj case SYN_SENT: 1274601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1284675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1294601Swnj goto badseg; 1304601Swnj } 1314803Swnj if (thflags&TH_RST) { 1324803Swnj tcp_error(tp, ENETRESET); 1334803Swnj tcp_detach(tp); /* 70 */ 1344601Swnj tp->t_state = CLOSED; 1354601Swnj goto badseg; 1364601Swnj } 1374601Swnj goto goodseg; 1384601Swnj 1394601Swnj default: 1404803Swnj if ((thflags&TH_RST) == 0) 1414601Swnj goto common; 1424601Swnj if (n->t_seq < tp->rcv_nxt) /* bad rst */ 1434601Swnj goto badseg; /* 69 */ 1444601Swnj switch (tp->t_state) { 1454601Swnj 1464601Swnj case L_SYN_RCVD: 1474601Swnj if (ack_ok(tp, n) == 0) 1484601Swnj goto badseg; /* 69 */ 1494601Swnj tp->t_rexmt = 0; 1504601Swnj tp->t_rexmttl = 0; 1514601Swnj tp->t_persist = 0; 152*4884Swnj h_free(inp->inp_fhost); 153*4884Swnj inp->inp_fhost = 0; 1544601Swnj tp->t_state = LISTEN; 1554601Swnj goto badseg; 1564601Swnj 1574601Swnj default: 1584803Swnj tcp_error(tp, ENETRESET); 1594803Swnj tcp_detach(tp); /* 66 */ 1604601Swnj tp->t_state = CLOSED; 1614601Swnj goto badseg; 1624601Swnj } 1634601Swnj /*NOTREACHED*/ 1644601Swnj 1654601Swnj case SYN_RCVD: 1664601Swnj common: 1674601Swnj if (ack_ok(tp, n) == 0) { 1684675Swnj tcp_sndrst(tp, n); /* 74 */ 1694601Swnj goto badseg; 1704601Swnj } 1714601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 1724679Swnj tcp_sndnull(tp); /* 74 */ 1734601Swnj goto badseg; 1744601Swnj } 1754601Swnj goto goodseg; 1764601Swnj } 1774601Swnj badseg: 1784601Swnj m_freem(mp); 1794601Swnj return; 1804601Swnj 1814601Swnj goodseg: 1824601Swnj /* 1834601Swnj * Defer processing if no buffer space for this connection. 1844601Swnj */ 185*4884Swnj so = inp->inp_socket; 1864803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 1874803Swnj n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 1884803Swnj /* 1894601Swnj mp->m_act = (struct mbuf *)0; 1904803Swnj if ((m = tp->seg_unack) != NULL) { 1914601Swnj while (m->m_act != NULL) 1924601Swnj m = m->m_act; 1934601Swnj m->m_act = mp; 1944601Swnj } else 1954803Swnj tp->seg_unack = mp; 1964803Swnj */ 1974803Swnj m_freem(mp); 1984601Swnj return; 1994601Swnj } 2004601Swnj 2014601Swnj /* 2024601Swnj * Discard ip header, and do tcp input processing. 2034601Swnj */ 2044601Swnj hlen += sizeof(struct ip); 2054601Swnj mp->m_off += hlen; 2064601Swnj mp->m_len -= hlen; 2074601Swnj nstate = tp->t_state; 2084601Swnj tp->tc_flags &= ~TC_NET_KEEP; 2094770Swnj #ifdef KPROF 2104601Swnj acounts[tp->t_state][INRECV]++; 2114770Swnj #endif 2124601Swnj #ifdef TCPDEBUG 2134803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2144604Swnj tdb_setup(tp, n, INRECV, &tdb); 2154601Swnj } else 2164601Swnj tdb.td_tod = 0; 2174601Swnj #endif 2184601Swnj switch (tp->t_state) { 2194601Swnj 2204601Swnj case LISTEN: 2214601Swnj if (!syn_ok(tp, n) || 222*4884Swnj ((inp->inp_lhost = in_hmake(&n->t_s)) == 0)) { 2234601Swnj nstate = EFAILEC; 2244601Swnj goto done; 2254601Swnj } 226*4884Swnj inp->inp_fport = n->t_src; 2274733Swnj tp->t_template = tcp_template(tp); 2284675Swnj tcp_ctldat(tp, n, 1); 2294601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2304601Swnj tp->t_finack = T_2ML; /* 3 */ 2314601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2324601Swnj nstate = CLOSE_WAIT; 2334601Swnj } else { 234*4884Swnj tp->t_init = T_INIT / 2; /* 4 */ 2354601Swnj nstate = L_SYN_RCVD; 2364601Swnj } 2374601Swnj goto done; 2384601Swnj 2394601Swnj case SYN_SENT: 2404601Swnj if (!syn_ok(tp, n)) { 2414601Swnj nstate = EFAILEC; 2424601Swnj goto done; 2434601Swnj } 2444675Swnj tcp_ctldat(tp, n, 1); 2454601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2464803Swnj if ((thflags&TH_ACK) == 0) { 2474601Swnj tp->t_finack = T_2ML; /* 9 */ 2484601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2494601Swnj } 2504601Swnj nstate = CLOSE_WAIT; 2514601Swnj goto done; 2524601Swnj } 2534803Swnj nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2544601Swnj goto done; 2554601Swnj 2564601Swnj case SYN_RCVD: 2574601Swnj case L_SYN_RCVD: 2584803Swnj if ((thflags&TH_ACK) == 0 || 2594803Swnj (thflags&TH_ACK) && n->t_ackno <= tp->iss) { 2604601Swnj nstate = EFAILEC; 2614601Swnj goto done; 2624601Swnj } 2634601Swnj goto input; 2644601Swnj 2654601Swnj case ESTAB: 2664601Swnj case FIN_W1: 2674601Swnj case FIN_W2: 2684601Swnj case TIME_WAIT: 2694601Swnj input: 2704675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2714601Swnj switch (tp->t_state) { 2724601Swnj 2734601Swnj case ESTAB: 2744601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2754601Swnj nstate = CLOSE_WAIT; 2764601Swnj break; 2774601Swnj 2784601Swnj case SYN_RCVD: 2794601Swnj case L_SYN_RCVD: 2804601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2814601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2824601Swnj break; 2834601Swnj 2844601Swnj case FIN_W1: 2854601Swnj j = ack_fin(tp, n); 2864601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2874601Swnj if (j) 2884601Swnj nstate = FIN_W2; /* 27 */ 2894601Swnj break; 2904601Swnj } 2914601Swnj tp->t_finack = T_2ML; 2924601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2934730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 2944601Swnj break; 2954601Swnj 2964601Swnj case FIN_W2: 2974601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2984601Swnj tp->t_finack = T_2ML; /* 29 */ 2994601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3004601Swnj nstate = TIME_WAIT; 3014601Swnj break; 3024601Swnj } 3034601Swnj break; 3044601Swnj } 3054601Swnj goto done; 3064601Swnj 3074601Swnj case CLOSE_WAIT: 3084803Swnj if (thflags&TH_FIN) { 3094803Swnj if ((thflags&TH_ACK) && 3104601Swnj n->t_ackno <= tp->seq_fin) { 3114675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 3124601Swnj tp->t_finack = T_2ML; 3134601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3144601Swnj } else 3154675Swnj tcp_sndctl(tp); /* 31 */ 3164601Swnj goto done; 3174601Swnj } 3184601Swnj goto input; 3194601Swnj 3204730Swnj case CLOSING: 3214601Swnj j = ack_fin(tp, n); 3224803Swnj if (thflags&TH_FIN) { 3234675Swnj tcp_ctldat(tp, n, 0); 3244601Swnj tp->t_finack = T_2ML; 3254601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3264601Swnj if (j) 3274601Swnj nstate = TIME_WAIT; /* 23 */ 3284601Swnj goto done; 3294601Swnj } 3304601Swnj if (j) { 3314601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3324601Swnj if (rcv_empty(tp)) { 333*4884Swnj sorwakeup(inp->inp_socket); 3344803Swnj nstate = CLOSED; /* 15 */ 3354601Swnj } else 3364601Swnj nstate = RCV_WAIT; /* 18 */ 3374601Swnj else 3384601Swnj nstate = TIME_WAIT; 3394601Swnj goto done; 3404601Swnj } 3414601Swnj goto input; 3424601Swnj 3434730Swnj case LAST_ACK: 3444601Swnj if (ack_fin(tp, n)) { 345*4884Swnj if (rcv_empty(tp)) { /* 16 */ 346*4884Swnj sorwakeup(inp->inp_socket); 3474601Swnj nstate = CLOSED; 3484601Swnj } else 3494601Swnj nstate = RCV_WAIT; /* 19 */ 3504601Swnj goto done; 3514601Swnj } 3524803Swnj if (thflags&TH_FIN) { 3534675Swnj tcp_sndctl(tp); /* 31 */ 3544601Swnj goto done; 3554601Swnj } 3564601Swnj goto input; 3574601Swnj 3584601Swnj case RCV_WAIT: 3594803Swnj if ((thflags&TH_FIN) && (thflags&TH_ACK) && 3604601Swnj n->t_ackno <= tp->seq_fin) { 3614675Swnj tcp_ctldat(tp, n, 0); 3624601Swnj tp->t_finack = T_2ML; 3634601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3644601Swnj } 3654601Swnj goto done; 3664601Swnj } 3674601Swnj panic("tcp_input"); 3684601Swnj done: 3694601Swnj 3704601Swnj /* 3714601Swnj * Done with state*input specific processing. 3724601Swnj * Form trace records, free input if not needed, 3734601Swnj * and enter new state. 3744601Swnj */ 3754601Swnj #ifdef TCPDEBUG 3764604Swnj if (tdb.td_tod) 3774604Swnj tdb_stuff(&tdb, nstate); 3784601Swnj #endif 3794601Swnj switch (nstate) { 3804601Swnj 3814601Swnj case EFAILEC: 3824601Swnj m_freem(mp); 3834601Swnj return; 3844601Swnj 3854601Swnj default: 3864601Swnj tp->t_state = nstate; 3874601Swnj /* fall into ... */ 3884601Swnj 3894601Swnj case CLOSED: 3904601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3914601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3924690Swnj /* inline expansion of m_freem */ 3934690Swnj while (mp) { 3944690Swnj MFREE(mp, m); 3954690Swnj mp = m; 3964690Swnj } 3974601Swnj return; 3984601Swnj } 3994601Swnj /* NOTREACHED */ 4004601Swnj 4014601Swnj /* 4024601Swnj * Unwanted packed; free everything 4034601Swnj * but the header and return an rst. 4044601Swnj */ 4054601Swnj notwanted: 4064601Swnj m_freem(mp->m_next); 4074601Swnj mp->m_next = NULL; 408*4884Swnj mp->m_len = sizeof(struct tcpiphdr); 4094601Swnj #define xchg(a,b) j=a; a=b; b=j 4104601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 4114601Swnj #undef xchg 4124803Swnj if (thflags&TH_ACK) 4134601Swnj n->t_seq = n->t_ackno; 4144601Swnj else { 4154601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 4164601Swnj n->t_seq = 0; 4174601Swnj } 4184803Swnj n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 4194601Swnj n->t_len = htons(TCPSIZE); 4204601Swnj n->t_off = 5; 421*4884Swnj n->t_sum = inet_cksum(mp, sizeof(struct tcpiphdr)); 422*4884Swnj ((struct ip *)n)->ip_len = sizeof(struct tcpiphdr); 4234601Swnj ip_output(mp); 4244601Swnj netstat.t_badsegs++; 4254601Swnj } 4264601Swnj 427*4884Swnj tcp_ctldat(tp, n0, dataok) 428*4884Swnj register struct tcpcb *tp; 429*4884Swnj struct tcpiphdr *n0; 430*4884Swnj int dataok; 4314601Swnj { 4324679Swnj register struct mbuf *m; 433*4884Swnj register struct tcpiphdr *n = n0; 4344803Swnj register int thflags = n->th_flags; 435*4884Swnj struct socket *so = tp->t_inpcb->inp_socket; 436*4884Swnj seq_t past = n->t_seq + n->t_len; 437*4884Swnj seq_t urgent; 4384679Swnj int sent; 4394679Swnj COUNT(TCP_CTLDAT); 4404601Swnj 441*4884Swnj if (thflags & TH_URG) 442*4884Swnj urgent = n->t_seq + n->t_urp; 443*4884Swnj tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW); 4444601Swnj /* syn */ 4454803Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) { 4464601Swnj tp->irs = n->t_seq; 4474601Swnj tp->rcv_nxt = n->t_seq + 1; 4484601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4494601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4504601Swnj } 4514601Swnj /* ack */ 4524803Swnj if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4534601Swnj n->t_ackno > tp->snd_una) { 4544679Swnj register struct mbuf *mn; 4554679Swnj 456*4884Swnj /* 457*4884Swnj * Reflect newly acknowledged data. 458*4884Swnj */ 4594601Swnj tp->snd_una = n->t_ackno; 4604601Swnj if (tp->snd_una > tp->snd_nxt) 4614601Swnj tp->snd_nxt = tp->snd_una; 462*4884Swnj 463*4884Swnj /* 464*4884Swnj * If timed msg acked, update retransmit time value. 465*4884Swnj */ 4664601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4674601Swnj tp->snd_una > tp->t_xmt_val) { 468*4884Swnj /* NEED SMOOTHING HERE */ 4694601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4704601Swnj if (tp->t_xmtime > T_REMAX) 4714601Swnj tp->t_xmtime = T_REMAX; 4724601Swnj } 4734601Swnj 474*4884Swnj /* 475*4884Swnj * Remove acked data from send buf 476*4884Swnj */ 477*4884Swnj sbdrop(&so->so_snd, tp->snd_una - tp->snd_off); 4784601Swnj tp->snd_off = tp->snd_una; 4794601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4804601Swnj (tp->snd_una > tp->iss)) { 4814601Swnj tp->tc_flags |= TC_SYN_ACKED; 4824601Swnj tp->t_init = 0; 4834601Swnj } 4844601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4854601Swnj tp->tc_flags &= ~TC_SND_FIN; 4864601Swnj tp->t_rexmt = 0; 4874601Swnj tp->t_rexmttl = 0; 4884601Swnj tp->tc_flags |= TC_CANCELLED; 489*4884Swnj sowwakeup(tp->t_inpcb->inp_socket); 4904601Swnj } 4914601Swnj /* win */ 4924601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 4934601Swnj tp->snd_wl = n->t_seq; 4944601Swnj tp->snd_wnd = n->t_win; 4954601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4964601Swnj tp->t_persist = 0; 4974601Swnj } 4984601Swnj /* text */ 499*4884Swnj if (dataok && n->t_len) { 500*4884Swnj register struct tcpiphdr *p, *q; 501*4884Swnj int overage; 5024601Swnj 503*4884Swnj /* eol */ 504*4884Swnj if ((thflags&TH_EOL)) { 505*4884Swnj register struct mbuf *m; 506*4884Swnj for (m = dtom(n); m->m_next; m = m->m_next) 507*4884Swnj ; 508*4884Swnj m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1); 509*4884Swnj } 5104601Swnj 511*4884Swnj /* text */ 512*4884Swnj /* 513*4884Swnj * Discard duplicate data already passed to user. 514*4884Swnj */ 515*4884Swnj if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 516*4884Swnj register int i = tp->rcv_nxt - n->t_seq; 5174645Swnj if (i >= n->t_len) 518*4884Swnj goto notext; 519*4884Swnj n->t_seq += i; 5204645Swnj n->t_len -= i; 521*4884Swnj m_adj(dtom(n), i); 5224601Swnj } 5234601Swnj 524*4884Swnj /* 525*4884Swnj * Find a segment which begins after this one does. 526*4884Swnj */ 527*4884Swnj for (q = tp->seg_next; q != (struct tcpiphdr *)tp; 528*4884Swnj q = q->t_next) 529*4884Swnj if (SEQ_GT(q->t_seq, n->t_seq)) 530*4884Swnj break; 531*4884Swnj 532*4884Swnj /* 533*4884Swnj * If there is a preceding segment, it may provide some of 534*4884Swnj * our data already. If so, drop the data from the incoming 535*4884Swnj * segment. If it provides all of our data, drop us. 536*4884Swnj */ 537*4884Swnj if (q->t_prev != (struct tcpiphdr *)tp) { 538*4884Swnj /* conversion to int (in i) handles seq wraparound */ 539*4884Swnj register int i = 540*4884Swnj q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 541*4884Swnj if (i > 0) { 542*4884Swnj if (i >= n->t_len) 543*4884Swnj goto notext; 544*4884Swnj /* w/o setting TC_NET_KEEP */ 545*4884Swnj m_adj(dtom(tp), i); 546*4884Swnj n->t_len -= i; 547*4884Swnj n->t_seq += i; 548*4884Swnj } 5494601Swnj } 5504601Swnj 551*4884Swnj /* 552*4884Swnj * While we overlap succeeding segments trim them or, 553*4884Swnj * if they are completely covered, dequeue them. 554*4884Swnj */ 555*4884Swnj while (q != (struct tcpiphdr *)tp && 556*4884Swnj SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 557*4884Swnj register int i = (n->t_seq + n->t_len) - q->t_seq; 558*4884Swnj if (i < q->t_len) { 559*4884Swnj q->t_len -= i; 560*4884Swnj m_adj(dtom(q), i); 561*4884Swnj break; 562*4884Swnj } 563*4884Swnj q = q->t_next; 564*4884Swnj m_freem(dtom(q->t_prev)); 565*4884Swnj remque(q->t_prev); 566*4884Swnj } 5674601Swnj 568*4884Swnj /* 569*4884Swnj * Stick new segment in its place. 570*4884Swnj */ 571*4884Swnj insque(n, q->t_prev); 572*4884Swnj tp->seqcnt += n->t_len; 573*4884Swnj 574*4884Swnj /* 575*4884Swnj * Calculate available space and discard segments for 576*4884Swnj * which there is too much. 577*4884Swnj */ 578*4884Swnj overage = 579*4884Swnj (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat; 580*4884Swnj if (overage > 0) { 581*4884Swnj q = tp->seg_prev; 582*4884Swnj for (;;) { 583*4884Swnj register int i = MIN(q->t_len, overage); 584*4884Swnj overage -= i; 585*4884Swnj q->t_len -= i; 586*4884Swnj m_adj(q, -i); 587*4884Swnj if (q->t_len) 588*4884Swnj break; 589*4884Swnj if (q == n) 590*4884Swnj panic("tcp_text dropall"); 591*4884Swnj q = q->t_prev; 592*4884Swnj remque(q->t_next); 593*4884Swnj } 594*4884Swnj } 595*4884Swnj 596*4884Swnj /* 597*4884Swnj * Advance rcv_next through newly completed sequence space. 598*4884Swnj */ 599*4884Swnj while (n->t_seq == tp->rcv_nxt) { 600*4884Swnj tp->rcv_nxt += n->t_len; 601*4884Swnj n = n->t_next; 602*4884Swnj if (n == (struct tcpiphdr *)tp) 6034645Swnj break; 6044645Swnj } 6054679Swnj /* urg */ 6064803Swnj if (thflags&TH_URG) { 607*4884Swnj /* ... */ 608*4884Swnj if (SEQ_GT(urgent, tp->rcv_urp)) 6094803Swnj tp->rcv_urp = urgent; 6104679Swnj } 611*4884Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 612*4884Swnj } 613*4884Swnj notext: 6144679Swnj /* fin */ 615*4884Swnj if ((thflags&TH_FIN) && past == tp->rcv_nxt) { 616*4884Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 617*4884Swnj tp->tc_flags |= TC_FIN_RCVD; 618*4884Swnj sorwakeup(so); 619*4884Swnj tp->rcv_nxt++; 6204803Swnj } 621*4884Swnj tp->tc_flags |= TC_ACK_DUE; 6224679Swnj } 6234679Swnj /* respond */ 6244679Swnj sent = 0; 6254679Swnj if (tp->tc_flags&TC_ACK_DUE) 6264679Swnj sent = tcp_sndctl(tp); 6274803Swnj else if ((tp->tc_flags&TC_NEW_WINDOW)) 628*4884Swnj if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc || 6294803Swnj (tp->tc_flags&TC_SND_FIN)) 6304679Swnj sent = tcp_send(tp); 6314679Swnj 6324679Swnj /* set for retrans */ 6334679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6344679Swnj (tp->tc_flags&TC_CANCELLED)) { 6354679Swnj tp->t_rexmt = tp->t_xmtime; 6364679Swnj tp->t_rexmttl = T_REXMTTL; 6374679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6384679Swnj tp->tc_flags &= ~TC_CANCELLED; 6394679Swnj } 6404690Swnj /* present data to user */ 6414656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6424601Swnj return; 643*4884Swnj n = tp->seg_next; 644*4884Swnj while (n != (struct tcpiphdr *)tp && n->t_seq < tp->rcv_nxt) { 6454690Swnj remque(n); 646*4884Swnj sbappend(so->so_rcv, dtom(n)); 6474690Swnj tp->seqcnt -= n->t_len; 648*4884Swnj if (tp->seqcnt < 0) 649*4884Swnj panic("tcp_input present"); 6504690Swnj n = n->t_next; 6514601Swnj } 652*4884Swnj sorwakeup(so); 6534601Swnj } 654