1*4899Swnj /* tcp_input.c 1.23 81/11/15 */ 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" 104884Swnj #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" 15*4899Swnj #include "../net/ip_var.h" 164803Swnj #include "../net/tcp.h" 174803Swnj #include "../net/tcp_fsm.h" 184803Swnj #include "../net/tcp_var.h" 194803Swnj #include "/usr/include/errno.h" 204601Swnj 214679Swnj int tcpcksum = 1; 224601Swnj 234884Swnj tcp_drain() 244803Swnj { 254884Swnj register struct inpcb *ip; 264803Swnj 274884Swnj for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) 284884Swnj tcp_drainunack(intotcpcb(ip)); 294803Swnj } 304803Swnj 314884Swnj tcp_drainunack(tp) 324884Swnj register struct tcpcb *tp; 334884Swnj { 344884Swnj register struct mbuf *m; 354884Swnj 364884Swnj for (m = tp->seg_unack; m; m = m->m_act) 374884Swnj m_freem(m); 384884Swnj tp->seg_unack = 0; 394884Swnj } 404884Swnj 414884Swnj tcp_ctlinput(m) 424884Swnj struct mbuf *m; 434884Swnj { 444884Swnj 454884Swnj m_freem(m); 464884Swnj } 474884Swnj 484601Swnj tcp_input(mp) 494601Swnj register struct mbuf *mp; 504601Swnj { 514884Swnj register struct tcpiphdr *n; /* known to be r10 */ 524697Swnj register int j; 534884Swnj register struct tcpcb *tp; 544884Swnj struct inpcb *inp; 554803Swnj register int thflags; 564601Swnj int nstate; 574601Swnj struct mbuf *m; 584803Swnj struct socket *so; 594673Swnj int hlen, tlen; 604601Swnj u_short lport, fport; 614601Swnj #ifdef TCPDEBUG 624601Swnj struct tcp_debug tdb; 634601Swnj #endif 644601Swnj COUNT(TCP_INPUT); 654601Swnj 664601Swnj /* 674601Swnj * Build extended tcp header 684601Swnj */ 694884Swnj n = mtod(mp, struct tcpiphdr *); 70*4899Swnj thflags = n->ti_flags; 714601Swnj tlen = ((struct ip *)n)->ip_len; 72*4899Swnj n->ti_len = htons(tlen); 73*4899Swnj n->ti_next = NULL; 74*4899Swnj n->ti_prev = NULL; 75*4899Swnj n->ti_x1 = 0; 76*4899Swnj lport = ntohs(n->ti_dst); 77*4899Swnj fport = ntohs(n->ti_src); 784601Swnj 794601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 80*4899Swnj if ((hlen = n->ti_off << 2) > mp->m_len) 814601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 824601Swnj 834679Swnj if (tcpcksum) { 844679Swnj /* 854679Swnj * Checksum extended header and data 864679Swnj */ 874718Swnj CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen); 88*4899Swnj if (n->ti_sum != 0) { 894679Swnj netstat.t_badsum++; 904601Swnj m_freem(mp); 914601Swnj return; 924601Swnj } 934601Swnj } 944601Swnj 954601Swnj /* 964884Swnj * Find tcb for message. 974601Swnj */ 98*4899Swnj inp = inpcb_lookup(&tcb, &n->ti_src, fport, &n_lhost, lport); 994884Swnj if (inp == 0) 1004884Swnj goto notwanted; 1014601Swnj 1024601Swnj /* 1034601Swnj * Byte swap header 1044601Swnj */ 105*4899Swnj n->ti_len = tlen - hlen; 106*4899Swnj n->ti_sport = fport; 107*4899Swnj n->ti_dport = lport; 108*4899Swnj n->ti_seq = ntohl(n->ti_seq); 109*4899Swnj n->ti_ackno = ntohl(n->ti_ackno); 110*4899Swnj n->ti_win = ntohs(n->ti_win); 111*4899Swnj n->ti_urp = ntohs(n->ti_urp); 1124601Swnj 1134601Swnj /* 1144601Swnj * Check segment seq # and do rst processing 1154601Swnj */ 1164601Swnj switch (tp->t_state) { 1174601Swnj 1184601Swnj case LISTEN: 1194803Swnj if ((thflags&TH_ACK) || !syn_ok(tp, n)) { 1204675Swnj tcp_sndrst(tp, n); 1214601Swnj goto badseg; 1224601Swnj } 1234803Swnj if (thflags&TH_RST) 1244601Swnj goto badseg; 1254601Swnj goto goodseg; 1264601Swnj 1274601Swnj case SYN_SENT: 1284601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1294675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1304601Swnj goto badseg; 1314601Swnj } 1324803Swnj if (thflags&TH_RST) { 1334803Swnj tcp_error(tp, ENETRESET); 1344803Swnj tcp_detach(tp); /* 70 */ 1354601Swnj tp->t_state = CLOSED; 1364601Swnj goto badseg; 1374601Swnj } 1384601Swnj goto goodseg; 1394601Swnj 1404601Swnj default: 1414803Swnj if ((thflags&TH_RST) == 0) 1424601Swnj goto common; 143*4899Swnj if (n->ti_seq < tp->rcv_nxt) /* bad rst */ 1444601Swnj goto badseg; /* 69 */ 1454601Swnj switch (tp->t_state) { 1464601Swnj 1474601Swnj case L_SYN_RCVD: 1484601Swnj if (ack_ok(tp, n) == 0) 1494601Swnj goto badseg; /* 69 */ 1504601Swnj tp->t_rexmt = 0; 1514601Swnj tp->t_rexmttl = 0; 1524601Swnj tp->t_persist = 0; 1534884Swnj h_free(inp->inp_fhost); 1544884Swnj inp->inp_fhost = 0; 1554601Swnj tp->t_state = LISTEN; 1564601Swnj goto badseg; 1574601Swnj 1584601Swnj default: 1594803Swnj tcp_error(tp, ENETRESET); 1604803Swnj tcp_detach(tp); /* 66 */ 1614601Swnj tp->t_state = CLOSED; 1624601Swnj goto badseg; 1634601Swnj } 1644601Swnj /*NOTREACHED*/ 1654601Swnj 1664601Swnj case SYN_RCVD: 1674601Swnj common: 1684601Swnj if (ack_ok(tp, n) == 0) { 1694675Swnj tcp_sndrst(tp, n); /* 74 */ 1704601Swnj goto badseg; 1714601Swnj } 172*4899Swnj if (syn_ok(tp, n) && n->ti_seq != tp->irs) { 1734679Swnj tcp_sndnull(tp); /* 74 */ 1744601Swnj goto badseg; 1754601Swnj } 1764601Swnj goto goodseg; 1774601Swnj } 1784601Swnj badseg: 1794601Swnj m_freem(mp); 1804601Swnj return; 1814601Swnj 1824601Swnj goodseg: 1834601Swnj /* 1844601Swnj * Defer processing if no buffer space for this connection. 1854601Swnj */ 1864884Swnj so = inp->inp_socket; 1874803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 188*4899Swnj n->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 1894803Swnj /* 1904601Swnj mp->m_act = (struct mbuf *)0; 1914803Swnj if ((m = tp->seg_unack) != NULL) { 1924601Swnj while (m->m_act != NULL) 1934601Swnj m = m->m_act; 1944601Swnj m->m_act = mp; 1954601Swnj } else 1964803Swnj tp->seg_unack = mp; 1974803Swnj */ 1984803Swnj m_freem(mp); 1994601Swnj return; 2004601Swnj } 2014601Swnj 2024601Swnj /* 2034601Swnj * Discard ip header, and do tcp input processing. 2044601Swnj */ 2054601Swnj hlen += sizeof(struct ip); 2064601Swnj mp->m_off += hlen; 2074601Swnj mp->m_len -= hlen; 2084601Swnj nstate = tp->t_state; 2094601Swnj tp->tc_flags &= ~TC_NET_KEEP; 2104770Swnj #ifdef KPROF 2114601Swnj acounts[tp->t_state][INRECV]++; 2124770Swnj #endif 2134601Swnj #ifdef TCPDEBUG 2144803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2154604Swnj tdb_setup(tp, n, INRECV, &tdb); 2164601Swnj } else 2174601Swnj tdb.td_tod = 0; 2184601Swnj #endif 2194601Swnj switch (tp->t_state) { 2204601Swnj 2214601Swnj case LISTEN: 2224601Swnj if (!syn_ok(tp, n) || 223*4899Swnj ((inp->inp_lhost = in_hmake(&n->ti_src)) == 0)) { 2244601Swnj nstate = EFAILEC; 2254601Swnj goto done; 2264601Swnj } 227*4899Swnj inp->inp_fport = n->ti_sport; 2284733Swnj tp->t_template = tcp_template(tp); 2294675Swnj tcp_ctldat(tp, n, 1); 2304601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2314601Swnj tp->t_finack = T_2ML; /* 3 */ 2324601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2334601Swnj nstate = CLOSE_WAIT; 2344601Swnj } else { 2354884Swnj tp->t_init = T_INIT / 2; /* 4 */ 2364601Swnj nstate = L_SYN_RCVD; 2374601Swnj } 2384601Swnj goto done; 2394601Swnj 2404601Swnj case SYN_SENT: 2414601Swnj if (!syn_ok(tp, n)) { 2424601Swnj nstate = EFAILEC; 2434601Swnj goto done; 2444601Swnj } 2454675Swnj tcp_ctldat(tp, n, 1); 2464601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2474803Swnj if ((thflags&TH_ACK) == 0) { 2484601Swnj tp->t_finack = T_2ML; /* 9 */ 2494601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2504601Swnj } 2514601Swnj nstate = CLOSE_WAIT; 2524601Swnj goto done; 2534601Swnj } 2544803Swnj nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2554601Swnj goto done; 2564601Swnj 2574601Swnj case SYN_RCVD: 2584601Swnj case L_SYN_RCVD: 2594803Swnj if ((thflags&TH_ACK) == 0 || 260*4899Swnj (thflags&TH_ACK) && n->ti_ackno <= tp->iss) { 2614601Swnj nstate = EFAILEC; 2624601Swnj goto done; 2634601Swnj } 2644601Swnj goto input; 2654601Swnj 2664601Swnj case ESTAB: 2674601Swnj case FIN_W1: 2684601Swnj case FIN_W2: 2694601Swnj case TIME_WAIT: 2704601Swnj input: 2714675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2724601Swnj switch (tp->t_state) { 2734601Swnj 2744601Swnj case ESTAB: 2754601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2764601Swnj nstate = CLOSE_WAIT; 2774601Swnj break; 2784601Swnj 2794601Swnj case SYN_RCVD: 2804601Swnj case L_SYN_RCVD: 2814601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2824601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2834601Swnj break; 2844601Swnj 2854601Swnj case FIN_W1: 2864601Swnj j = ack_fin(tp, n); 2874601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2884601Swnj if (j) 2894601Swnj nstate = FIN_W2; /* 27 */ 2904601Swnj break; 2914601Swnj } 2924601Swnj tp->t_finack = T_2ML; 2934601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2944730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 2954601Swnj break; 2964601Swnj 2974601Swnj case FIN_W2: 2984601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2994601Swnj tp->t_finack = T_2ML; /* 29 */ 3004601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3014601Swnj nstate = TIME_WAIT; 3024601Swnj break; 3034601Swnj } 3044601Swnj break; 3054601Swnj } 3064601Swnj goto done; 3074601Swnj 3084601Swnj case CLOSE_WAIT: 3094803Swnj if (thflags&TH_FIN) { 3104803Swnj if ((thflags&TH_ACK) && 311*4899Swnj n->ti_ackno <= tp->seq_fin) { 3124675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 3134601Swnj tp->t_finack = T_2ML; 3144601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3154601Swnj } else 3164675Swnj tcp_sndctl(tp); /* 31 */ 3174601Swnj goto done; 3184601Swnj } 3194601Swnj goto input; 3204601Swnj 3214730Swnj case CLOSING: 3224601Swnj j = ack_fin(tp, n); 3234803Swnj if (thflags&TH_FIN) { 3244675Swnj tcp_ctldat(tp, n, 0); 3254601Swnj tp->t_finack = T_2ML; 3264601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3274601Swnj if (j) 3284601Swnj nstate = TIME_WAIT; /* 23 */ 3294601Swnj goto done; 3304601Swnj } 3314601Swnj if (j) { 3324601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3334601Swnj if (rcv_empty(tp)) { 3344884Swnj sorwakeup(inp->inp_socket); 3354803Swnj nstate = CLOSED; /* 15 */ 3364601Swnj } else 3374601Swnj nstate = RCV_WAIT; /* 18 */ 3384601Swnj else 3394601Swnj nstate = TIME_WAIT; 3404601Swnj goto done; 3414601Swnj } 3424601Swnj goto input; 3434601Swnj 3444730Swnj case LAST_ACK: 3454601Swnj if (ack_fin(tp, n)) { 3464884Swnj if (rcv_empty(tp)) { /* 16 */ 3474884Swnj sorwakeup(inp->inp_socket); 3484601Swnj nstate = CLOSED; 3494601Swnj } else 3504601Swnj nstate = RCV_WAIT; /* 19 */ 3514601Swnj goto done; 3524601Swnj } 3534803Swnj if (thflags&TH_FIN) { 3544675Swnj tcp_sndctl(tp); /* 31 */ 3554601Swnj goto done; 3564601Swnj } 3574601Swnj goto input; 3584601Swnj 3594601Swnj case RCV_WAIT: 3604803Swnj if ((thflags&TH_FIN) && (thflags&TH_ACK) && 361*4899Swnj n->ti_ackno <= tp->seq_fin) { 3624675Swnj tcp_ctldat(tp, n, 0); 3634601Swnj tp->t_finack = T_2ML; 3644601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3654601Swnj } 3664601Swnj goto done; 3674601Swnj } 3684601Swnj panic("tcp_input"); 3694601Swnj done: 3704601Swnj 3714601Swnj /* 3724601Swnj * Done with state*input specific processing. 3734601Swnj * Form trace records, free input if not needed, 3744601Swnj * and enter new state. 3754601Swnj */ 3764601Swnj #ifdef TCPDEBUG 3774604Swnj if (tdb.td_tod) 3784604Swnj tdb_stuff(&tdb, nstate); 3794601Swnj #endif 3804601Swnj switch (nstate) { 3814601Swnj 3824601Swnj case EFAILEC: 3834601Swnj m_freem(mp); 3844601Swnj return; 3854601Swnj 3864601Swnj default: 3874601Swnj tp->t_state = nstate; 3884601Swnj /* fall into ... */ 3894601Swnj 3904601Swnj case CLOSED: 3914601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3924601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3934690Swnj /* inline expansion of m_freem */ 3944690Swnj while (mp) { 3954690Swnj MFREE(mp, m); 3964690Swnj mp = m; 3974690Swnj } 3984601Swnj return; 3994601Swnj } 4004601Swnj /* NOTREACHED */ 4014601Swnj 4024601Swnj /* 4034601Swnj * Unwanted packed; free everything 4044601Swnj * but the header and return an rst. 4054601Swnj */ 4064601Swnj notwanted: 4074601Swnj m_freem(mp->m_next); 4084601Swnj mp->m_next = NULL; 4094884Swnj mp->m_len = sizeof(struct tcpiphdr); 4104601Swnj #define xchg(a,b) j=a; a=b; b=j 411*4899Swnj xchg(n->ti_dst.s_addr, n->ti_src.s_addr); 412*4899Swnj xchg(n->ti_dport, n->ti_sport); 4134601Swnj #undef xchg 4144803Swnj if (thflags&TH_ACK) 415*4899Swnj n->ti_seq = n->ti_ackno; 4164601Swnj else { 417*4899Swnj n->ti_ackno = htonl(ntohl(n->ti_seq) + tlen - hlen); 418*4899Swnj n->ti_seq = 0; 4194601Swnj } 420*4899Swnj n->ti_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 421*4899Swnj n->ti_len = htons(TCPSIZE); 422*4899Swnj n->ti_off = 5; 423*4899Swnj n->ti_sum = inet_cksum(mp, sizeof(struct tcpiphdr)); 4244884Swnj ((struct ip *)n)->ip_len = sizeof(struct tcpiphdr); 4254601Swnj ip_output(mp); 4264601Swnj netstat.t_badsegs++; 4274601Swnj } 4284601Swnj 4294884Swnj tcp_ctldat(tp, n0, dataok) 4304884Swnj register struct tcpcb *tp; 4314884Swnj struct tcpiphdr *n0; 4324884Swnj int dataok; 4334601Swnj { 4344679Swnj register struct mbuf *m; 4354884Swnj register struct tcpiphdr *n = n0; 436*4899Swnj register int thflags = n->ti_flags; 4374884Swnj struct socket *so = tp->t_inpcb->inp_socket; 438*4899Swnj seq_t past = n->ti_seq + n->ti_len; 4394884Swnj seq_t urgent; 4404679Swnj int sent; 4414679Swnj COUNT(TCP_CTLDAT); 4424601Swnj 4434884Swnj if (thflags & TH_URG) 444*4899Swnj urgent = n->ti_seq + n->ti_urp; 4454884Swnj tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW); 4464601Swnj /* syn */ 4474803Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) { 448*4899Swnj tp->irs = n->ti_seq; 449*4899Swnj tp->rcv_nxt = n->ti_seq + 1; 4504601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4514601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4524601Swnj } 4534601Swnj /* ack */ 4544803Swnj if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 455*4899Swnj n->ti_ackno > tp->snd_una) { 4564679Swnj register struct mbuf *mn; 4574679Swnj 4584884Swnj /* 4594884Swnj * Reflect newly acknowledged data. 4604884Swnj */ 461*4899Swnj tp->snd_una = n->ti_ackno; 4624601Swnj if (tp->snd_una > tp->snd_nxt) 4634601Swnj tp->snd_nxt = tp->snd_una; 4644884Swnj 4654884Swnj /* 4664884Swnj * If timed msg acked, update retransmit time value. 4674884Swnj */ 4684601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4694601Swnj tp->snd_una > tp->t_xmt_val) { 4704884Swnj /* NEED SMOOTHING HERE */ 4714601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4724601Swnj if (tp->t_xmtime > T_REMAX) 4734601Swnj tp->t_xmtime = T_REMAX; 4744601Swnj } 4754601Swnj 4764884Swnj /* 4774884Swnj * Remove acked data from send buf 4784884Swnj */ 4794884Swnj sbdrop(&so->so_snd, tp->snd_una - tp->snd_off); 4804601Swnj tp->snd_off = tp->snd_una; 4814601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4824601Swnj (tp->snd_una > tp->iss)) { 4834601Swnj tp->tc_flags |= TC_SYN_ACKED; 4844601Swnj tp->t_init = 0; 4854601Swnj } 4864601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4874601Swnj tp->tc_flags &= ~TC_SND_FIN; 4884601Swnj tp->t_rexmt = 0; 4894601Swnj tp->t_rexmttl = 0; 4904601Swnj tp->tc_flags |= TC_CANCELLED; 4914884Swnj sowwakeup(tp->t_inpcb->inp_socket); 4924601Swnj } 4934601Swnj /* win */ 494*4899Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->ti_seq >= tp->snd_wl) { 495*4899Swnj tp->snd_wl = n->ti_seq; 496*4899Swnj tp->snd_wnd = n->ti_win; 4974601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4984601Swnj tp->t_persist = 0; 4994601Swnj } 5004601Swnj /* text */ 501*4899Swnj if (dataok && n->ti_len) { 5024884Swnj register struct tcpiphdr *p, *q; 5034884Swnj int overage; 5044601Swnj 5054884Swnj /* eol */ 5064884Swnj if ((thflags&TH_EOL)) { 5074884Swnj register struct mbuf *m; 5084884Swnj for (m = dtom(n); m->m_next; m = m->m_next) 5094884Swnj ; 5104884Swnj m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1); 5114884Swnj } 5124601Swnj 5134884Swnj /* text */ 5144884Swnj /* 5154884Swnj * Discard duplicate data already passed to user. 5164884Swnj */ 517*4899Swnj if (SEQ_LT(n->ti_seq, tp->rcv_nxt)) { 518*4899Swnj register int i = tp->rcv_nxt - n->ti_seq; 519*4899Swnj if (i >= n->ti_len) 5204884Swnj goto notext; 521*4899Swnj n->ti_seq += i; 522*4899Swnj n->ti_len -= i; 5234884Swnj m_adj(dtom(n), i); 5244601Swnj } 5254601Swnj 5264884Swnj /* 5274884Swnj * Find a segment which begins after this one does. 5284884Swnj */ 5294884Swnj for (q = tp->seg_next; q != (struct tcpiphdr *)tp; 530*4899Swnj q = (struct tcpiphdr *)q->ti_next) 531*4899Swnj if (SEQ_GT(q->ti_seq, n->ti_seq)) 5324884Swnj break; 5334884Swnj 5344884Swnj /* 5354884Swnj * If there is a preceding segment, it may provide some of 5364884Swnj * our data already. If so, drop the data from the incoming 5374884Swnj * segment. If it provides all of our data, drop us. 5384884Swnj */ 539*4899Swnj if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { 540*4899Swnj register int i; 541*4899Swnj q = (struct tcpiphdr *)(q->ti_prev); 5424884Swnj /* conversion to int (in i) handles seq wraparound */ 543*4899Swnj i = q->ti_seq + q->ti_len - n->th_seq; 5444884Swnj if (i > 0) { 545*4899Swnj if (i >= n->ti_len) 5464884Swnj goto notext; 5474884Swnj /* w/o setting TC_NET_KEEP */ 5484884Swnj m_adj(dtom(tp), i); 549*4899Swnj n->ti_len -= i; 550*4899Swnj n->ti_seq += i; 5514884Swnj } 552*4899Swnj q = (struct tcpiphdr *)(q->ti_next); 5534601Swnj } 5544601Swnj 5554884Swnj /* 5564884Swnj * While we overlap succeeding segments trim them or, 5574884Swnj * if they are completely covered, dequeue them. 5584884Swnj */ 5594884Swnj while (q != (struct tcpiphdr *)tp && 560*4899Swnj SEQ_GT(n->ti_seq + n->ti_len, q->ti_seq)) { 561*4899Swnj register int i = (n->ti_seq + n->ti_len) - q->ti_seq; 562*4899Swnj if (i < q->ti_len) { 563*4899Swnj q->ti_len -= i; 5644884Swnj m_adj(dtom(q), i); 5654884Swnj break; 5664884Swnj } 567*4899Swnj q = (struct tcpiphdr *)q->ti_next; 568*4899Swnj m_freem(dtom(q->ti_prev)); 569*4899Swnj remque(q->ti_prev); 5704884Swnj } 5714601Swnj 5724884Swnj /* 5734884Swnj * Stick new segment in its place. 5744884Swnj */ 575*4899Swnj insque(n, q->ti_prev); 576*4899Swnj tp->seqcnt += n->ti_len; 5774884Swnj 5784884Swnj /* 5794884Swnj * Calculate available space and discard segments for 5804884Swnj * which there is too much. 5814884Swnj */ 5824884Swnj overage = 5834884Swnj (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat; 5844884Swnj if (overage > 0) { 5854884Swnj q = tp->seg_prev; 5864884Swnj for (;;) { 587*4899Swnj register int i = MIN(q->ti_len, overage); 5884884Swnj overage -= i; 589*4899Swnj q->ti_len -= i; 5904884Swnj m_adj(q, -i); 591*4899Swnj if (q->ti_len) 5924884Swnj break; 5934884Swnj if (q == n) 5944884Swnj panic("tcp_text dropall"); 595*4899Swnj q = (struct tcpiphdr *)q->ti_prev; 596*4899Swnj remque(q->ti_next); 5974884Swnj } 5984884Swnj } 5994884Swnj 6004884Swnj /* 6014884Swnj * Advance rcv_next through newly completed sequence space. 6024884Swnj */ 603*4899Swnj while (n->ti_seq == tp->rcv_nxt) { 604*4899Swnj tp->rcv_nxt += n->ti_len; 605*4899Swnj n = (struct tcpiphdr *)n->ti_next; 6064884Swnj if (n == (struct tcpiphdr *)tp) 6074645Swnj break; 6084645Swnj } 6094679Swnj /* urg */ 6104803Swnj if (thflags&TH_URG) { 6114884Swnj /* ... */ 6124884Swnj if (SEQ_GT(urgent, tp->rcv_urp)) 6134803Swnj tp->rcv_urp = urgent; 6144679Swnj } 6154884Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 6164884Swnj } 6174884Swnj notext: 6184679Swnj /* fin */ 6194884Swnj if ((thflags&TH_FIN) && past == tp->rcv_nxt) { 6204884Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 6214884Swnj tp->tc_flags |= TC_FIN_RCVD; 6224884Swnj sorwakeup(so); 6234884Swnj tp->rcv_nxt++; 6244803Swnj } 6254884Swnj tp->tc_flags |= TC_ACK_DUE; 6264679Swnj } 6274679Swnj /* respond */ 6284679Swnj sent = 0; 6294679Swnj if (tp->tc_flags&TC_ACK_DUE) 6304679Swnj sent = tcp_sndctl(tp); 6314803Swnj else if ((tp->tc_flags&TC_NEW_WINDOW)) 6324884Swnj if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc || 6334803Swnj (tp->tc_flags&TC_SND_FIN)) 6344679Swnj sent = tcp_send(tp); 6354679Swnj 6364679Swnj /* set for retrans */ 6374679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6384679Swnj (tp->tc_flags&TC_CANCELLED)) { 6394679Swnj tp->t_rexmt = tp->t_xmtime; 6404679Swnj tp->t_rexmttl = T_REXMTTL; 6414679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6424679Swnj tp->tc_flags &= ~TC_CANCELLED; 6434679Swnj } 6444690Swnj /* present data to user */ 6454656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6464601Swnj return; 6474884Swnj n = tp->seg_next; 648*4899Swnj while (n != (struct tcpiphdr *)tp && n->ti_seq < tp->rcv_nxt) { 6494690Swnj remque(n); 6504884Swnj sbappend(so->so_rcv, dtom(n)); 651*4899Swnj tp->seqcnt -= n->ti_len; 6524884Swnj if (tp->seqcnt < 0) 6534884Swnj panic("tcp_input present"); 654*4899Swnj n = (struct tcpiphdr *)n->ti_next; 6554601Swnj } 6564884Swnj sorwakeup(so); 6574601Swnj } 658