1*5048Swnj /* tcp_input.c 1.28 81/11/23 */ 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.h" 94884Swnj #include "../net/inet_pcb.h" 104803Swnj #include "../net/inet_systm.h" 114803Swnj #include "../net/imp.h" 124803Swnj #include "../net/ip.h" 134899Swnj #include "../net/ip_var.h" 144803Swnj #include "../net/tcp.h" 154803Swnj #include "../net/tcp_fsm.h" 164803Swnj #include "../net/tcp_var.h" 174803Swnj #include "/usr/include/errno.h" 184601Swnj 194679Swnj int tcpcksum = 1; 204601Swnj 214884Swnj tcp_drain() 224803Swnj { 234884Swnj register struct inpcb *ip; 244803Swnj 254953Swnj COUNT(TCP_DRAIN); 264884Swnj for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) 274884Swnj tcp_drainunack(intotcpcb(ip)); 284803Swnj } 294803Swnj 304884Swnj tcp_drainunack(tp) 314884Swnj register struct tcpcb *tp; 324884Swnj { 334884Swnj register struct mbuf *m; 344884Swnj 354953Swnj COUNT(TCP_DRAINUNACK); 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 454953Swnj COUNT(TCP_CTLINPUT); 464884Swnj m_freem(m); 474884Swnj } 484884Swnj 494953Swnj struct sockaddr_in tcp_sockaddr = { AF_INET }; 504953Swnj 514924Swnj tcp_input(m0) 524924Swnj struct mbuf *m0; 534601Swnj { 544924Swnj register struct tcpiphdr *ti; 554924Swnj struct inpcb *inp; 564924Swnj register struct mbuf *m; 574924Swnj int len, tlen, off; 584924Swnj 594924Swnj register struct tcpcb *tp; 604697Swnj register int j; 614924Swnj register int tiflags; 624601Swnj int nstate; 634803Swnj struct socket *so; 644601Swnj #ifdef TCPDEBUG 654601Swnj struct tcp_debug tdb; 664601Swnj #endif 674924Swnj 684601Swnj COUNT(TCP_INPUT); 694924Swnj /* 704924Swnj * Get ip and tcp header together in first mbuf. 714924Swnj */ 724924Swnj m = m0; 734924Swnj if (m->m_len < sizeof (struct tcpiphdr) && 744924Swnj m_pullup(m, sizeof (struct tcpiphdr)) == 0) { 754924Swnj tcpstat.tcps_hdrops++; 764924Swnj goto bad; 774924Swnj } 785020Sroot ti = mtod(m, struct tcpiphdr *); 795020Sroot if (ti->ti_len > sizeof (struct ip)) 805020Sroot ip_stripoptions((struct ip *)ti, (char *)0); 814601Swnj 824601Swnj /* 834924Swnj * Checksum extended tcp header and data. 844601Swnj */ 854924Swnj tlen = ((struct ip *)ti)->ip_len; 864924Swnj len = sizeof (struct ip) + tlen; 874679Swnj if (tcpcksum) { 884924Swnj ti->ti_next = ti->ti_prev = 0; 894924Swnj ti->ti_x1 = 0; 904953Swnj ti->ti_len = htons((u_short)tlen); 91*5048Swnj if ((ti->ti_sum = inet_cksum(m, len)) != 0xffff) { 924924Swnj tcpstat.tcps_badsum++; 934924Swnj printf("tcp cksum %x\ti", ti->ti_sum); 944924Swnj goto bad; 954601Swnj } 964601Swnj } 974601Swnj 984601Swnj /* 994924Swnj * Check that tcp offset makes sense, 1004924Swnj * process tcp options and adjust length. 1014601Swnj */ 1024924Swnj off = ti->ti_off << 2; 1034924Swnj if (off < sizeof (struct tcphdr) || off > ti->ti_len) { 1044924Swnj tcpstat.tcps_badoff++; 1054924Swnj goto bad; 1064924Swnj } 1074924Swnj ti->ti_len = tlen - off; 1084924Swnj /* PROCESS OPTIONS */ 1094924Swnj 1104924Swnj /* 1114924Swnj * Locate pcb for segment. 1124924Swnj */ 1134953Swnj inp = in_pcblookup(&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); 1144884Swnj if (inp == 0) 1154884Swnj goto notwanted; 1164924Swnj tp = intotcpcb(inp); /* ??? */ 1174924Swnj if (tp == 0) /* ??? */ 1184924Swnj goto notwanted; /* ??? */ 1194601Swnj 1204601Swnj /* 1214924Swnj * Convert tcp protocol specific fields to host format. 1224601Swnj */ 1234924Swnj ti->ti_seq = ntohl(ti->ti_seq); 1244924Swnj ti->ti_ackno = ntohl((n_long)ti->ti_ackno); 1254924Swnj ti->ti_win = ntohs(ti->ti_win); 1264924Swnj ti->ti_urp = ntohs(ti->ti_urp); 1274601Swnj 1284601Swnj /* 1294601Swnj * Check segment seq # and do rst processing 1304601Swnj */ 1314924Swnj tiflags = ti->ti_flags; 1324601Swnj switch (tp->t_state) { 1334601Swnj 1344601Swnj case LISTEN: 1354924Swnj if ((tiflags&TH_ACK) || (tiflags&TH_SYN) == 0) { 1364924Swnj tcp_sndrst(tp, ti); 1374924Swnj goto bad; 1384601Swnj } 1394924Swnj if (tiflags&TH_RST) 1404924Swnj goto bad; 1414924Swnj goto good; 1424601Swnj 1434601Swnj case SYN_SENT: 1444924Swnj if (!ack_ok(tp, ti) || (tiflags&TH_SYN) == 0) { 1454924Swnj tcp_sndrst(tp, ti); /* 71,72,75 */ 1464924Swnj goto bad; 1474601Swnj } 1484924Swnj if (tiflags&TH_RST) { 1494803Swnj tcp_error(tp, ENETRESET); 1504803Swnj tcp_detach(tp); /* 70 */ 1514601Swnj tp->t_state = CLOSED; 1524924Swnj goto bad; 1534601Swnj } 1544924Swnj goto good; 1554601Swnj 1564601Swnj default: 1574924Swnj if ((tiflags&TH_RST) == 0) 1584601Swnj goto common; 1594924Swnj if (ti->ti_seq < tp->rcv_nxt) /* bad rst */ 1604924Swnj goto bad; /* 69 */ 1614601Swnj switch (tp->t_state) { 1624601Swnj 1634601Swnj case L_SYN_RCVD: 1644924Swnj if (ack_ok(tp, ti) == 0) 1654924Swnj goto bad; /* 69 */ 1664601Swnj tp->t_rexmt = 0; 1674601Swnj tp->t_rexmttl = 0; 1684601Swnj tp->t_persist = 0; 1694953Swnj inp->inp_faddr.s_addr = 0; 1704601Swnj tp->t_state = LISTEN; 1714924Swnj goto bad; 1724601Swnj 1734601Swnj default: 1744803Swnj tcp_error(tp, ENETRESET); 1754803Swnj tcp_detach(tp); /* 66 */ 1764601Swnj tp->t_state = CLOSED; 1774924Swnj goto bad; 1784601Swnj } 1794601Swnj /*NOTREACHED*/ 1804601Swnj 1814601Swnj case SYN_RCVD: 1824601Swnj common: 1834924Swnj if (ack_ok(tp, ti) == 0) { 1844924Swnj tcp_sndrst(tp, ti); /* 74 */ 1854924Swnj goto bad; 1864601Swnj } 1874924Swnj if ((tiflags&TH_SYN) == 0 && ti->ti_seq != tp->irs) { 1884679Swnj tcp_sndnull(tp); /* 74 */ 1894924Swnj goto bad; 1904601Swnj } 1914924Swnj goto good; 1924601Swnj } 1934924Swnj bad: 1944924Swnj m_freem(m); 1954601Swnj return; 1964601Swnj 1974924Swnj good: 1984601Swnj /* 1994601Swnj * Defer processing if no buffer space for this connection. 2004601Swnj */ 2014884Swnj so = inp->inp_socket; 2024803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 2034924Swnj ti->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 2044803Swnj /* 2054924Swnj m->m_act = (struct mbuf *)0; 2064803Swnj if ((m = tp->seg_unack) != NULL) { 2074601Swnj while (m->m_act != NULL) 2084601Swnj m = m->m_act; 2094924Swnj m->m_act = m0; 2104601Swnj } else 2114924Swnj tp->seg_unack = m0; 2124803Swnj */ 2134924Swnj m_freem(m0); 2144601Swnj return; 2154601Swnj } 2164601Swnj 2174601Swnj /* 2184601Swnj * Discard ip header, and do tcp input processing. 2194601Swnj */ 2204924Swnj off += sizeof (struct ip); 2214924Swnj m->m_off += off; 2224924Swnj m->m_len -= off; 2234601Swnj nstate = tp->t_state; 2244601Swnj tp->tc_flags &= ~TC_NET_KEEP; 2254770Swnj #ifdef KPROF 2264601Swnj acounts[tp->t_state][INRECV]++; 2274770Swnj #endif 2284601Swnj #ifdef TCPDEBUG 2294803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2304924Swnj tdb_setup(tp, ti, INRECV, &tdb); 2314601Swnj } else 2324601Swnj tdb.td_tod = 0; 2334601Swnj #endif 2344601Swnj switch (tp->t_state) { 2354601Swnj 2364601Swnj case LISTEN: 2374953Swnj tcp_sockaddr.sin_addr = ti->ti_src; 2384953Swnj tcp_sockaddr.sin_port = ti->ti_sport; 2394953Swnj if ((tiflags&TH_SYN) == 0 || in_pcbsetpeer(inp, &tcp_sockaddr)) { 2404601Swnj nstate = EFAILEC; 2414601Swnj goto done; 2424601Swnj } 2434733Swnj tp->t_template = tcp_template(tp); 2444924Swnj tcp_ctldat(tp, ti, 1); 2454601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2464601Swnj tp->t_finack = T_2ML; /* 3 */ 2474601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2484601Swnj nstate = CLOSE_WAIT; 2494601Swnj } else { 2504884Swnj tp->t_init = T_INIT / 2; /* 4 */ 2514601Swnj nstate = L_SYN_RCVD; 2524601Swnj } 2534601Swnj goto done; 2544601Swnj 2554601Swnj case SYN_SENT: 2564924Swnj if (!syn_ok(tp, ti)) { 2574601Swnj nstate = EFAILEC; 2584601Swnj goto done; 2594601Swnj } 2604924Swnj tcp_ctldat(tp, ti, 1); 2614601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2624924Swnj if ((tiflags&TH_ACK) == 0) { 2634601Swnj tp->t_finack = T_2ML; /* 9 */ 2644601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2654601Swnj } 2664601Swnj nstate = CLOSE_WAIT; 2674601Swnj goto done; 2684601Swnj } 2694924Swnj nstate = (tiflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2704601Swnj goto done; 2714601Swnj 2724601Swnj case SYN_RCVD: 2734601Swnj case L_SYN_RCVD: 2744924Swnj if ((tiflags&TH_ACK) == 0 || 2754924Swnj (tiflags&TH_ACK) && ti->ti_ackno <= tp->iss) { 2764601Swnj nstate = EFAILEC; 2774601Swnj goto done; 2784601Swnj } 2794601Swnj goto input; 2804601Swnj 2814601Swnj case ESTAB: 2824601Swnj case FIN_W1: 2834601Swnj case FIN_W2: 2844601Swnj case TIME_WAIT: 2854601Swnj input: 2864924Swnj tcp_ctldat(tp, ti, 1); /* 39 */ 2874601Swnj switch (tp->t_state) { 2884601Swnj 2894601Swnj case ESTAB: 2904601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2914601Swnj nstate = CLOSE_WAIT; 2924601Swnj break; 2934601Swnj 2944601Swnj case SYN_RCVD: 2954601Swnj case L_SYN_RCVD: 2964601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2974601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2984601Swnj break; 2994601Swnj 3004601Swnj case FIN_W1: 3014924Swnj j = ack_fin(tp, ti); 3024601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 3034601Swnj if (j) 3044601Swnj nstate = FIN_W2; /* 27 */ 3054601Swnj break; 3064601Swnj } 3074601Swnj tp->t_finack = T_2ML; 3084601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3094730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 3104601Swnj break; 3114601Swnj 3124601Swnj case FIN_W2: 3134601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 3144601Swnj tp->t_finack = T_2ML; /* 29 */ 3154601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3164601Swnj nstate = TIME_WAIT; 3174601Swnj break; 3184601Swnj } 3194601Swnj break; 3204601Swnj } 3214601Swnj goto done; 3224601Swnj 3234601Swnj case CLOSE_WAIT: 3244924Swnj if (tiflags&TH_FIN) { 3254924Swnj if ((tiflags&TH_ACK) && 3264924Swnj ti->ti_ackno <= tp->seq_fin) { 3274924Swnj tcp_ctldat(tp, ti, 0); /* 30 */ 3284601Swnj tp->t_finack = T_2ML; 3294601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3304601Swnj } else 3314909Swnj (void) tcp_sndctl(tp); /* 31 */ 3324601Swnj goto done; 3334601Swnj } 3344601Swnj goto input; 3354601Swnj 3364730Swnj case CLOSING: 3374924Swnj j = ack_fin(tp, ti); 3384924Swnj if (tiflags&TH_FIN) { 3394924Swnj tcp_ctldat(tp, ti, 0); 3404601Swnj tp->t_finack = T_2ML; 3414601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3424601Swnj if (j) 3434601Swnj nstate = TIME_WAIT; /* 23 */ 3444601Swnj goto done; 3454601Swnj } 3464601Swnj if (j) { 3474601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3484601Swnj if (rcv_empty(tp)) { 3494884Swnj sorwakeup(inp->inp_socket); 3504803Swnj nstate = CLOSED; /* 15 */ 3514601Swnj } else 3524601Swnj nstate = RCV_WAIT; /* 18 */ 3534601Swnj else 3544601Swnj nstate = TIME_WAIT; 3554601Swnj goto done; 3564601Swnj } 3574601Swnj goto input; 3584601Swnj 3594730Swnj case LAST_ACK: 3604924Swnj if (ack_fin(tp, ti)) { 3614884Swnj if (rcv_empty(tp)) { /* 16 */ 3624884Swnj sorwakeup(inp->inp_socket); 3634601Swnj nstate = CLOSED; 3644601Swnj } else 3654601Swnj nstate = RCV_WAIT; /* 19 */ 3664601Swnj goto done; 3674601Swnj } 3684924Swnj if (tiflags&TH_FIN) { 3694909Swnj (void) tcp_sndctl(tp); /* 31 */ 3704601Swnj goto done; 3714601Swnj } 3724601Swnj goto input; 3734601Swnj 3744601Swnj case RCV_WAIT: 3754924Swnj if ((tiflags&TH_FIN) && (tiflags&TH_ACK) && 3764924Swnj ti->ti_ackno <= tp->seq_fin) { 3774924Swnj tcp_ctldat(tp, ti, 0); 3784601Swnj tp->t_finack = T_2ML; 3794601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3804601Swnj } 3814601Swnj goto done; 3824601Swnj } 3834601Swnj panic("tcp_input"); 3844601Swnj done: 3854601Swnj 3864601Swnj /* 3874601Swnj * Done with state*input specific processing. 3884601Swnj * Form trace records, free input if not needed, 3894601Swnj * and enter new state. 3904601Swnj */ 3914601Swnj #ifdef TCPDEBUG 3924604Swnj if (tdb.td_tod) 3934604Swnj tdb_stuff(&tdb, nstate); 3944601Swnj #endif 3954601Swnj switch (nstate) { 3964601Swnj 3974601Swnj case EFAILEC: 3984924Swnj m_freem(m); 3994601Swnj return; 4004601Swnj 4014601Swnj default: 4024601Swnj tp->t_state = nstate; 4034601Swnj /* fall into ... */ 4044601Swnj 4054601Swnj case CLOSED: 4064601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 4074924Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) { 4084924Swnj register struct mbuf *n; 4094690Swnj /* inline expansion of m_freem */ 4104924Swnj while (m) { 4114953Swnj MFREE(m, n); 4124924Swnj m = n; 4134690Swnj } 4144924Swnj } 4154601Swnj return; 4164601Swnj } 4174601Swnj /* NOTREACHED */ 4184601Swnj 4194601Swnj /* 4204601Swnj * Unwanted packed; free everything 4214601Swnj * but the header and return an rst. 4224601Swnj */ 4234601Swnj notwanted: 4244924Swnj m_freem(m->m_next); 4254924Swnj m->m_next = NULL; 4264924Swnj m->m_len = sizeof(struct tcpiphdr); 4274601Swnj #define xchg(a,b) j=a; a=b; b=j 4284924Swnj xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr); 4294924Swnj xchg(ti->ti_dport, ti->ti_sport); 4304601Swnj #undef xchg 4314924Swnj if (tiflags&TH_ACK) 4324924Swnj ti->ti_seq = ti->ti_ackno; 4334601Swnj else { 4344953Swnj ti->ti_ackno = htonl((unsigned)(ntohl(ti->ti_seq) + ti->ti_len)); 4354924Swnj ti->ti_seq = 0; 4364601Swnj } 4374924Swnj ti->ti_flags = ((tiflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 4384924Swnj ti->ti_len = htons(TCPSIZE); 4394924Swnj ti->ti_off = 5; 4404924Swnj ti->ti_sum = inet_cksum(m, sizeof(struct tcpiphdr)); 4414924Swnj ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr); 442*5048Swnj ((struct ip *)ti)->ip_ttl = MAXTTL; 4434924Swnj ip_output(m); 4444924Swnj tcpstat.tcps_badsegs++; 4454601Swnj } 4464601Swnj 4474884Swnj tcp_ctldat(tp, n0, dataok) 4484884Swnj register struct tcpcb *tp; 4494884Swnj struct tcpiphdr *n0; 4504884Swnj int dataok; 4514601Swnj { 4524924Swnj register struct tcpiphdr *ti = n0; 4534924Swnj register int tiflags = ti->ti_flags; 4544884Swnj struct socket *so = tp->t_inpcb->inp_socket; 4554924Swnj seq_t past = ti->ti_seq + ti->ti_len; 4564884Swnj seq_t urgent; 4574679Swnj int sent; 4584679Swnj COUNT(TCP_CTLDAT); 4594601Swnj 4604924Swnj if (tiflags & TH_URG) 4614924Swnj urgent = ti->ti_seq + ti->ti_urp; 4624884Swnj tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW); 4634601Swnj /* syn */ 4644924Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (tiflags&TH_SYN)) { 4654924Swnj tp->irs = ti->ti_seq; 4664924Swnj tp->rcv_nxt = ti->ti_seq + 1; 4674601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4684601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4694601Swnj } 4704601Swnj /* ack */ 4714924Swnj if ((tiflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4724924Swnj ti->ti_ackno > tp->snd_una) { 4734884Swnj /* 4744884Swnj * Reflect newly acknowledged data. 4754884Swnj */ 4764924Swnj tp->snd_una = ti->ti_ackno; 4774601Swnj if (tp->snd_una > tp->snd_nxt) 4784601Swnj tp->snd_nxt = tp->snd_una; 4794884Swnj 4804884Swnj /* 4814884Swnj * If timed msg acked, update retransmit time value. 4824884Swnj */ 4834601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4844601Swnj tp->snd_una > tp->t_xmt_val) { 4854884Swnj /* NEED SMOOTHING HERE */ 4864601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4874601Swnj if (tp->t_xmtime > T_REMAX) 4884601Swnj tp->t_xmtime = T_REMAX; 4894601Swnj } 4904601Swnj 4914884Swnj /* 4924884Swnj * Remove acked data from send buf 4934884Swnj */ 4944909Swnj sbdrop(&so->so_snd, (int)(tp->snd_una - tp->snd_off)); 4954601Swnj tp->snd_off = tp->snd_una; 4964601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4974601Swnj (tp->snd_una > tp->iss)) { 4984601Swnj tp->tc_flags |= TC_SYN_ACKED; 4994601Swnj tp->t_init = 0; 5004601Swnj } 5014601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 5024601Swnj tp->tc_flags &= ~TC_SND_FIN; 5034601Swnj tp->t_rexmt = 0; 5044601Swnj tp->t_rexmttl = 0; 5054601Swnj tp->tc_flags |= TC_CANCELLED; 5064884Swnj sowwakeup(tp->t_inpcb->inp_socket); 5074601Swnj } 5084601Swnj /* win */ 5094924Swnj if ((tp->tc_flags & TC_SYN_RCVD) && ti->ti_seq >= tp->snd_wl) { 5104924Swnj tp->snd_wl = ti->ti_seq; 5114924Swnj tp->snd_wnd = ti->ti_win; 5124601Swnj tp->tc_flags |= TC_NEW_WINDOW; 5134601Swnj tp->t_persist = 0; 5144601Swnj } 5154601Swnj /* text */ 5164924Swnj if (dataok && ti->ti_len) { 5174909Swnj register struct tcpiphdr *q; 5184884Swnj int overage; 5194601Swnj 5204884Swnj /* eol */ 5214924Swnj if ((tiflags&TH_EOL)) { 5224884Swnj register struct mbuf *m; 5234924Swnj for (m = dtom(ti); m->m_next; m = m->m_next) 5244884Swnj ; 5254884Swnj m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1); 5264884Swnj } 5274601Swnj 5284884Swnj /* text */ 5294884Swnj /* 5304884Swnj * Discard duplicate data already passed to user. 5314884Swnj */ 5324924Swnj if (SEQ_LT(ti->ti_seq, tp->rcv_nxt)) { 5334924Swnj register int i = tp->rcv_nxt - ti->ti_seq; 5344924Swnj if (i >= ti->ti_len) 5354884Swnj goto notext; 5364924Swnj ti->ti_seq += i; 5374924Swnj ti->ti_len -= i; 5384924Swnj m_adj(dtom(ti), i); 5394601Swnj } 5404601Swnj 5414884Swnj /* 5424884Swnj * Find a segment which begins after this one does. 5434884Swnj */ 5444884Swnj for (q = tp->seg_next; q != (struct tcpiphdr *)tp; 5454899Swnj q = (struct tcpiphdr *)q->ti_next) 5464924Swnj if (SEQ_GT(q->ti_seq, ti->ti_seq)) 5474884Swnj break; 5484884Swnj 5494884Swnj /* 5504884Swnj * If there is a preceding segment, it may provide some of 5514884Swnj * our data already. If so, drop the data from the incoming 5524884Swnj * segment. If it provides all of our data, drop us. 5534884Swnj */ 5544899Swnj if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { 5554899Swnj register int i; 5564899Swnj q = (struct tcpiphdr *)(q->ti_prev); 5574884Swnj /* conversion to int (in i) handles seq wraparound */ 5584924Swnj i = q->ti_seq + q->ti_len - ti->ti_seq; 5594884Swnj if (i > 0) { 5604924Swnj if (i >= ti->ti_len) 5614884Swnj goto notext; 5624884Swnj /* w/o setting TC_NET_KEEP */ 5634884Swnj m_adj(dtom(tp), i); 5644924Swnj ti->ti_len -= i; 5654924Swnj ti->ti_seq += i; 5664884Swnj } 5674899Swnj q = (struct tcpiphdr *)(q->ti_next); 5684601Swnj } 5694601Swnj 5704884Swnj /* 5714884Swnj * While we overlap succeeding segments trim them or, 5724884Swnj * if they are completely covered, dequeue them. 5734884Swnj */ 5744884Swnj while (q != (struct tcpiphdr *)tp && 5754924Swnj SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) { 5764924Swnj register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; 5774899Swnj if (i < q->ti_len) { 5784899Swnj q->ti_len -= i; 5794884Swnj m_adj(dtom(q), i); 5804884Swnj break; 5814884Swnj } 5824899Swnj q = (struct tcpiphdr *)q->ti_next; 5834899Swnj m_freem(dtom(q->ti_prev)); 5844899Swnj remque(q->ti_prev); 5854884Swnj } 5864601Swnj 5874884Swnj /* 5884884Swnj * Stick new segment in its place. 5894884Swnj */ 5904924Swnj insque(ti, q->ti_prev); 5914924Swnj tp->seqcnt += ti->ti_len; 5924884Swnj 5934884Swnj /* 5944884Swnj * Calculate available space and discard segments for 5954884Swnj * which there is too much. 5964884Swnj */ 5974884Swnj overage = 5984884Swnj (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat; 5994884Swnj if (overage > 0) { 6004884Swnj q = tp->seg_prev; 6014884Swnj for (;;) { 6024899Swnj register int i = MIN(q->ti_len, overage); 6034884Swnj overage -= i; 6044899Swnj q->ti_len -= i; 6054909Swnj m_adj(dtom(q), -i); 6064899Swnj if (q->ti_len) 6074884Swnj break; 6084924Swnj if (q == ti) 6094884Swnj panic("tcp_text dropall"); 6104899Swnj q = (struct tcpiphdr *)q->ti_prev; 6114899Swnj remque(q->ti_next); 6124884Swnj } 6134884Swnj } 6144884Swnj 6154884Swnj /* 6164884Swnj * Advance rcv_next through newly completed sequence space. 6174884Swnj */ 6184924Swnj while (ti->ti_seq == tp->rcv_nxt) { 6194924Swnj tp->rcv_nxt += ti->ti_len; 6204924Swnj ti = (struct tcpiphdr *)ti->ti_next; 6214924Swnj if (ti == (struct tcpiphdr *)tp) 6224645Swnj break; 6234645Swnj } 6244679Swnj /* urg */ 6254924Swnj if (tiflags&TH_URG) { 6264884Swnj /* ... */ 6274884Swnj if (SEQ_GT(urgent, tp->rcv_urp)) 6284803Swnj tp->rcv_urp = urgent; 6294679Swnj } 6304884Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 6314884Swnj } 6324884Swnj notext: 6334679Swnj /* fin */ 6344924Swnj if ((tiflags&TH_FIN) && past == tp->rcv_nxt) { 6354884Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 6364884Swnj tp->tc_flags |= TC_FIN_RCVD; 6374884Swnj sorwakeup(so); 6384884Swnj tp->rcv_nxt++; 6394803Swnj } 6404884Swnj tp->tc_flags |= TC_ACK_DUE; 6414679Swnj } 6424679Swnj /* respond */ 6434679Swnj sent = 0; 6444679Swnj if (tp->tc_flags&TC_ACK_DUE) 6454679Swnj sent = tcp_sndctl(tp); 6464803Swnj else if ((tp->tc_flags&TC_NEW_WINDOW)) 6474884Swnj if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc || 6484803Swnj (tp->tc_flags&TC_SND_FIN)) 6494679Swnj sent = tcp_send(tp); 6504679Swnj 6514679Swnj /* set for retrans */ 6524679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6534679Swnj (tp->tc_flags&TC_CANCELLED)) { 6544679Swnj tp->t_rexmt = tp->t_xmtime; 6554679Swnj tp->t_rexmttl = T_REXMTTL; 6564679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6574679Swnj tp->tc_flags &= ~TC_CANCELLED; 6584679Swnj } 6594690Swnj /* present data to user */ 6604656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6614601Swnj return; 6624924Swnj ti = tp->seg_next; 6634924Swnj while (ti != (struct tcpiphdr *)tp && ti->ti_seq < tp->rcv_nxt) { 6644924Swnj remque(ti); 6654924Swnj sbappend(&so->so_rcv, dtom(ti)); 6664924Swnj tp->seqcnt -= ti->ti_len; 6674884Swnj if (tp->seqcnt < 0) 6684884Swnj panic("tcp_input present"); 6694924Swnj ti = (struct tcpiphdr *)ti->ti_next; 6704601Swnj } 6714884Swnj sorwakeup(so); 6724601Swnj } 673