1*4909Swnj /* tcp_input.c 1.24 81/11/16 */ 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" 154899Swnj #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; 59*4909Swnj int hlen; 60*4909Swnj u_short tlen, 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 *); 704899Swnj thflags = n->ti_flags; 714601Swnj tlen = ((struct ip *)n)->ip_len; 724899Swnj n->ti_len = htons(tlen); 734899Swnj n->ti_next = NULL; 744899Swnj n->ti_prev = NULL; 754899Swnj n->ti_x1 = 0; 76*4909Swnj lport = ntohs(n->ti_dport); 77*4909Swnj fport = ntohs(n->ti_sport); 784601Swnj 794601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 804899Swnj 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); 884899Swnj 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*4909Swnj inp = in_pcblookup(&tcb, &n->ti_src, fport, &n_lhost, lport); 994884Swnj if (inp == 0) 1004884Swnj goto notwanted; 101*4909Swnj tp = intotcpcb(inp); 102*4909Swnj if (tp == 0) 103*4909Swnj goto notwanted; 1044601Swnj 1054601Swnj /* 1064601Swnj * Byte swap header 1074601Swnj */ 1084899Swnj n->ti_len = tlen - hlen; 1094899Swnj n->ti_sport = fport; 1104899Swnj n->ti_dport = lport; 1114899Swnj n->ti_seq = ntohl(n->ti_seq); 112*4909Swnj n->ti_ackno = ntohl((n_long)n->ti_ackno); 1134899Swnj n->ti_win = ntohs(n->ti_win); 1144899Swnj n->ti_urp = ntohs(n->ti_urp); 1154601Swnj 1164601Swnj /* 1174601Swnj * Check segment seq # and do rst processing 1184601Swnj */ 1194601Swnj switch (tp->t_state) { 1204601Swnj 1214601Swnj case LISTEN: 1224803Swnj if ((thflags&TH_ACK) || !syn_ok(tp, n)) { 1234675Swnj tcp_sndrst(tp, n); 1244601Swnj goto badseg; 1254601Swnj } 1264803Swnj if (thflags&TH_RST) 1274601Swnj goto badseg; 1284601Swnj goto goodseg; 1294601Swnj 1304601Swnj case SYN_SENT: 1314601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1324675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1334601Swnj goto badseg; 1344601Swnj } 1354803Swnj if (thflags&TH_RST) { 1364803Swnj tcp_error(tp, ENETRESET); 1374803Swnj tcp_detach(tp); /* 70 */ 1384601Swnj tp->t_state = CLOSED; 1394601Swnj goto badseg; 1404601Swnj } 1414601Swnj goto goodseg; 1424601Swnj 1434601Swnj default: 1444803Swnj if ((thflags&TH_RST) == 0) 1454601Swnj goto common; 1464899Swnj if (n->ti_seq < tp->rcv_nxt) /* bad rst */ 1474601Swnj goto badseg; /* 69 */ 1484601Swnj switch (tp->t_state) { 1494601Swnj 1504601Swnj case L_SYN_RCVD: 1514601Swnj if (ack_ok(tp, n) == 0) 1524601Swnj goto badseg; /* 69 */ 1534601Swnj tp->t_rexmt = 0; 1544601Swnj tp->t_rexmttl = 0; 1554601Swnj tp->t_persist = 0; 156*4909Swnj in_hostfree(inp->inp_fhost); 1574884Swnj inp->inp_fhost = 0; 1584601Swnj tp->t_state = LISTEN; 1594601Swnj goto badseg; 1604601Swnj 1614601Swnj default: 1624803Swnj tcp_error(tp, ENETRESET); 1634803Swnj tcp_detach(tp); /* 66 */ 1644601Swnj tp->t_state = CLOSED; 1654601Swnj goto badseg; 1664601Swnj } 1674601Swnj /*NOTREACHED*/ 1684601Swnj 1694601Swnj case SYN_RCVD: 1704601Swnj common: 1714601Swnj if (ack_ok(tp, n) == 0) { 1724675Swnj tcp_sndrst(tp, n); /* 74 */ 1734601Swnj goto badseg; 1744601Swnj } 1754899Swnj if (syn_ok(tp, n) && n->ti_seq != tp->irs) { 1764679Swnj tcp_sndnull(tp); /* 74 */ 1774601Swnj goto badseg; 1784601Swnj } 1794601Swnj goto goodseg; 1804601Swnj } 1814601Swnj badseg: 1824601Swnj m_freem(mp); 1834601Swnj return; 1844601Swnj 1854601Swnj goodseg: 1864601Swnj /* 1874601Swnj * Defer processing if no buffer space for this connection. 1884601Swnj */ 1894884Swnj so = inp->inp_socket; 1904803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 1914899Swnj n->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 1924803Swnj /* 1934601Swnj mp->m_act = (struct mbuf *)0; 1944803Swnj if ((m = tp->seg_unack) != NULL) { 1954601Swnj while (m->m_act != NULL) 1964601Swnj m = m->m_act; 1974601Swnj m->m_act = mp; 1984601Swnj } else 1994803Swnj tp->seg_unack = mp; 2004803Swnj */ 2014803Swnj m_freem(mp); 2024601Swnj return; 2034601Swnj } 2044601Swnj 2054601Swnj /* 2064601Swnj * Discard ip header, and do tcp input processing. 2074601Swnj */ 2084601Swnj hlen += sizeof(struct ip); 2094601Swnj mp->m_off += hlen; 2104601Swnj mp->m_len -= hlen; 2114601Swnj nstate = tp->t_state; 2124601Swnj tp->tc_flags &= ~TC_NET_KEEP; 2134770Swnj #ifdef KPROF 2144601Swnj acounts[tp->t_state][INRECV]++; 2154770Swnj #endif 2164601Swnj #ifdef TCPDEBUG 2174803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2184604Swnj tdb_setup(tp, n, INRECV, &tdb); 2194601Swnj } else 2204601Swnj tdb.td_tod = 0; 2214601Swnj #endif 2224601Swnj switch (tp->t_state) { 2234601Swnj 2244601Swnj case LISTEN: 2254601Swnj if (!syn_ok(tp, n) || 226*4909Swnj ((inp->inp_lhost = in_hostalloc(&n->ti_src)) == 0)) { 2274601Swnj nstate = EFAILEC; 2284601Swnj goto done; 2294601Swnj } 2304899Swnj inp->inp_fport = n->ti_sport; 2314733Swnj tp->t_template = tcp_template(tp); 2324675Swnj tcp_ctldat(tp, n, 1); 2334601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2344601Swnj tp->t_finack = T_2ML; /* 3 */ 2354601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2364601Swnj nstate = CLOSE_WAIT; 2374601Swnj } else { 2384884Swnj tp->t_init = T_INIT / 2; /* 4 */ 2394601Swnj nstate = L_SYN_RCVD; 2404601Swnj } 2414601Swnj goto done; 2424601Swnj 2434601Swnj case SYN_SENT: 2444601Swnj if (!syn_ok(tp, n)) { 2454601Swnj nstate = EFAILEC; 2464601Swnj goto done; 2474601Swnj } 2484675Swnj tcp_ctldat(tp, n, 1); 2494601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2504803Swnj if ((thflags&TH_ACK) == 0) { 2514601Swnj tp->t_finack = T_2ML; /* 9 */ 2524601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2534601Swnj } 2544601Swnj nstate = CLOSE_WAIT; 2554601Swnj goto done; 2564601Swnj } 2574803Swnj nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2584601Swnj goto done; 2594601Swnj 2604601Swnj case SYN_RCVD: 2614601Swnj case L_SYN_RCVD: 2624803Swnj if ((thflags&TH_ACK) == 0 || 2634899Swnj (thflags&TH_ACK) && n->ti_ackno <= tp->iss) { 2644601Swnj nstate = EFAILEC; 2654601Swnj goto done; 2664601Swnj } 2674601Swnj goto input; 2684601Swnj 2694601Swnj case ESTAB: 2704601Swnj case FIN_W1: 2714601Swnj case FIN_W2: 2724601Swnj case TIME_WAIT: 2734601Swnj input: 2744675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2754601Swnj switch (tp->t_state) { 2764601Swnj 2774601Swnj case ESTAB: 2784601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2794601Swnj nstate = CLOSE_WAIT; 2804601Swnj break; 2814601Swnj 2824601Swnj case SYN_RCVD: 2834601Swnj case L_SYN_RCVD: 2844601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2854601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2864601Swnj break; 2874601Swnj 2884601Swnj case FIN_W1: 2894601Swnj j = ack_fin(tp, n); 2904601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2914601Swnj if (j) 2924601Swnj nstate = FIN_W2; /* 27 */ 2934601Swnj break; 2944601Swnj } 2954601Swnj tp->t_finack = T_2ML; 2964601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2974730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 2984601Swnj break; 2994601Swnj 3004601Swnj case FIN_W2: 3014601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 3024601Swnj tp->t_finack = T_2ML; /* 29 */ 3034601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3044601Swnj nstate = TIME_WAIT; 3054601Swnj break; 3064601Swnj } 3074601Swnj break; 3084601Swnj } 3094601Swnj goto done; 3104601Swnj 3114601Swnj case CLOSE_WAIT: 3124803Swnj if (thflags&TH_FIN) { 3134803Swnj if ((thflags&TH_ACK) && 3144899Swnj n->ti_ackno <= tp->seq_fin) { 3154675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 3164601Swnj tp->t_finack = T_2ML; 3174601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3184601Swnj } else 319*4909Swnj (void) tcp_sndctl(tp); /* 31 */ 3204601Swnj goto done; 3214601Swnj } 3224601Swnj goto input; 3234601Swnj 3244730Swnj case CLOSING: 3254601Swnj j = ack_fin(tp, n); 3264803Swnj if (thflags&TH_FIN) { 3274675Swnj tcp_ctldat(tp, n, 0); 3284601Swnj tp->t_finack = T_2ML; 3294601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3304601Swnj if (j) 3314601Swnj nstate = TIME_WAIT; /* 23 */ 3324601Swnj goto done; 3334601Swnj } 3344601Swnj if (j) { 3354601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3364601Swnj if (rcv_empty(tp)) { 3374884Swnj sorwakeup(inp->inp_socket); 3384803Swnj nstate = CLOSED; /* 15 */ 3394601Swnj } else 3404601Swnj nstate = RCV_WAIT; /* 18 */ 3414601Swnj else 3424601Swnj nstate = TIME_WAIT; 3434601Swnj goto done; 3444601Swnj } 3454601Swnj goto input; 3464601Swnj 3474730Swnj case LAST_ACK: 3484601Swnj if (ack_fin(tp, n)) { 3494884Swnj if (rcv_empty(tp)) { /* 16 */ 3504884Swnj sorwakeup(inp->inp_socket); 3514601Swnj nstate = CLOSED; 3524601Swnj } else 3534601Swnj nstate = RCV_WAIT; /* 19 */ 3544601Swnj goto done; 3554601Swnj } 3564803Swnj if (thflags&TH_FIN) { 357*4909Swnj (void) tcp_sndctl(tp); /* 31 */ 3584601Swnj goto done; 3594601Swnj } 3604601Swnj goto input; 3614601Swnj 3624601Swnj case RCV_WAIT: 3634803Swnj if ((thflags&TH_FIN) && (thflags&TH_ACK) && 3644899Swnj n->ti_ackno <= tp->seq_fin) { 3654675Swnj tcp_ctldat(tp, n, 0); 3664601Swnj tp->t_finack = T_2ML; 3674601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3684601Swnj } 3694601Swnj goto done; 3704601Swnj } 3714601Swnj panic("tcp_input"); 3724601Swnj done: 3734601Swnj 3744601Swnj /* 3754601Swnj * Done with state*input specific processing. 3764601Swnj * Form trace records, free input if not needed, 3774601Swnj * and enter new state. 3784601Swnj */ 3794601Swnj #ifdef TCPDEBUG 3804604Swnj if (tdb.td_tod) 3814604Swnj tdb_stuff(&tdb, nstate); 3824601Swnj #endif 3834601Swnj switch (nstate) { 3844601Swnj 3854601Swnj case EFAILEC: 3864601Swnj m_freem(mp); 3874601Swnj return; 3884601Swnj 3894601Swnj default: 3904601Swnj tp->t_state = nstate; 3914601Swnj /* fall into ... */ 3924601Swnj 3934601Swnj case CLOSED: 3944601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3954601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3964690Swnj /* inline expansion of m_freem */ 3974690Swnj while (mp) { 3984690Swnj MFREE(mp, m); 3994690Swnj mp = m; 4004690Swnj } 4014601Swnj return; 4024601Swnj } 4034601Swnj /* NOTREACHED */ 4044601Swnj 4054601Swnj /* 4064601Swnj * Unwanted packed; free everything 4074601Swnj * but the header and return an rst. 4084601Swnj */ 4094601Swnj notwanted: 4104601Swnj m_freem(mp->m_next); 4114601Swnj mp->m_next = NULL; 4124884Swnj mp->m_len = sizeof(struct tcpiphdr); 4134601Swnj #define xchg(a,b) j=a; a=b; b=j 4144899Swnj xchg(n->ti_dst.s_addr, n->ti_src.s_addr); 4154899Swnj xchg(n->ti_dport, n->ti_sport); 4164601Swnj #undef xchg 4174803Swnj if (thflags&TH_ACK) 4184899Swnj n->ti_seq = n->ti_ackno; 4194601Swnj else { 420*4909Swnj n->ti_ackno = htonl((unsigned)(ntohl(n->ti_seq) + tlen-hlen)); 4214899Swnj n->ti_seq = 0; 4224601Swnj } 4234899Swnj n->ti_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 4244899Swnj n->ti_len = htons(TCPSIZE); 4254899Swnj n->ti_off = 5; 4264899Swnj n->ti_sum = inet_cksum(mp, sizeof(struct tcpiphdr)); 4274884Swnj ((struct ip *)n)->ip_len = sizeof(struct tcpiphdr); 4284601Swnj ip_output(mp); 4294601Swnj netstat.t_badsegs++; 4304601Swnj } 4314601Swnj 4324884Swnj tcp_ctldat(tp, n0, dataok) 4334884Swnj register struct tcpcb *tp; 4344884Swnj struct tcpiphdr *n0; 4354884Swnj int dataok; 4364601Swnj { 4374884Swnj register struct tcpiphdr *n = n0; 4384899Swnj register int thflags = n->ti_flags; 4394884Swnj struct socket *so = tp->t_inpcb->inp_socket; 4404899Swnj seq_t past = n->ti_seq + n->ti_len; 4414884Swnj seq_t urgent; 4424679Swnj int sent; 4434679Swnj COUNT(TCP_CTLDAT); 4444601Swnj 4454884Swnj if (thflags & TH_URG) 4464899Swnj urgent = n->ti_seq + n->ti_urp; 4474884Swnj tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW); 4484601Swnj /* syn */ 4494803Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) { 4504899Swnj tp->irs = n->ti_seq; 4514899Swnj tp->rcv_nxt = n->ti_seq + 1; 4524601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4534601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4544601Swnj } 4554601Swnj /* ack */ 4564803Swnj if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4574899Swnj n->ti_ackno > tp->snd_una) { 4584884Swnj /* 4594884Swnj * Reflect newly acknowledged data. 4604884Swnj */ 4614899Swnj 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 */ 479*4909Swnj sbdrop(&so->so_snd, (int)(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 */ 4944899Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->ti_seq >= tp->snd_wl) { 4954899Swnj tp->snd_wl = n->ti_seq; 4964899Swnj tp->snd_wnd = n->ti_win; 4974601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4984601Swnj tp->t_persist = 0; 4994601Swnj } 5004601Swnj /* text */ 5014899Swnj if (dataok && n->ti_len) { 502*4909Swnj register struct tcpiphdr *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 */ 5174899Swnj if (SEQ_LT(n->ti_seq, tp->rcv_nxt)) { 5184899Swnj register int i = tp->rcv_nxt - n->ti_seq; 5194899Swnj if (i >= n->ti_len) 5204884Swnj goto notext; 5214899Swnj n->ti_seq += i; 5224899Swnj 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; 5304899Swnj q = (struct tcpiphdr *)q->ti_next) 5314899Swnj 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 */ 5394899Swnj if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { 5404899Swnj register int i; 5414899Swnj q = (struct tcpiphdr *)(q->ti_prev); 5424884Swnj /* conversion to int (in i) handles seq wraparound */ 543*4909Swnj i = q->ti_seq + q->ti_len - n->ti_seq; 5444884Swnj if (i > 0) { 5454899Swnj if (i >= n->ti_len) 5464884Swnj goto notext; 5474884Swnj /* w/o setting TC_NET_KEEP */ 5484884Swnj m_adj(dtom(tp), i); 5494899Swnj n->ti_len -= i; 5504899Swnj n->ti_seq += i; 5514884Swnj } 5524899Swnj 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 && 5604899Swnj SEQ_GT(n->ti_seq + n->ti_len, q->ti_seq)) { 5614899Swnj register int i = (n->ti_seq + n->ti_len) - q->ti_seq; 5624899Swnj if (i < q->ti_len) { 5634899Swnj q->ti_len -= i; 5644884Swnj m_adj(dtom(q), i); 5654884Swnj break; 5664884Swnj } 5674899Swnj q = (struct tcpiphdr *)q->ti_next; 5684899Swnj m_freem(dtom(q->ti_prev)); 5694899Swnj remque(q->ti_prev); 5704884Swnj } 5714601Swnj 5724884Swnj /* 5734884Swnj * Stick new segment in its place. 5744884Swnj */ 5754899Swnj insque(n, q->ti_prev); 5764899Swnj 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 (;;) { 5874899Swnj register int i = MIN(q->ti_len, overage); 5884884Swnj overage -= i; 5894899Swnj q->ti_len -= i; 590*4909Swnj m_adj(dtom(q), -i); 5914899Swnj if (q->ti_len) 5924884Swnj break; 5934884Swnj if (q == n) 5944884Swnj panic("tcp_text dropall"); 5954899Swnj q = (struct tcpiphdr *)q->ti_prev; 5964899Swnj remque(q->ti_next); 5974884Swnj } 5984884Swnj } 5994884Swnj 6004884Swnj /* 6014884Swnj * Advance rcv_next through newly completed sequence space. 6024884Swnj */ 6034899Swnj while (n->ti_seq == tp->rcv_nxt) { 6044899Swnj tp->rcv_nxt += n->ti_len; 6054899Swnj 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; 6484899Swnj while (n != (struct tcpiphdr *)tp && n->ti_seq < tp->rcv_nxt) { 6494690Swnj remque(n); 650*4909Swnj sbappend(&so->so_rcv, dtom(n)); 6514899Swnj tp->seqcnt -= n->ti_len; 6524884Swnj if (tp->seqcnt < 0) 6534884Swnj panic("tcp_input present"); 6544899Swnj n = (struct tcpiphdr *)n->ti_next; 6554601Swnj } 6564884Swnj sorwakeup(so); 6574601Swnj } 658