1*5020Sroot /* tcp_input.c 1.27 81/11/22 */ 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 } 78*5020Sroot ti = mtod(m, struct tcpiphdr *); 79*5020Sroot if (ti->ti_len > sizeof (struct ip)) 80*5020Sroot 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); 914924Swnj if (ti->ti_sum = inet_cksum(m, len)) { 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 * Convert addresses and ports to host format. 1124924Swnj * Locate pcb for segment. 1134924Swnj */ 1144924Swnj ti->ti_src.s_addr = ntohl(ti->ti_src.s_addr); 1154924Swnj ti->ti_dst.s_addr = ntohl(ti->ti_dst.s_addr); 1164924Swnj ti->ti_sport = ntohs(ti->ti_sport); 1174924Swnj ti->ti_dport = ntohs(ti->ti_dport); 1184953Swnj inp = in_pcblookup(&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport); 1194884Swnj if (inp == 0) 1204884Swnj goto notwanted; 1214924Swnj tp = intotcpcb(inp); /* ??? */ 1224924Swnj if (tp == 0) /* ??? */ 1234924Swnj goto notwanted; /* ??? */ 1244601Swnj 1254601Swnj /* 1264924Swnj * Convert tcp protocol specific fields to host format. 1274601Swnj */ 1284924Swnj ti->ti_seq = ntohl(ti->ti_seq); 1294924Swnj ti->ti_ackno = ntohl((n_long)ti->ti_ackno); 1304924Swnj ti->ti_win = ntohs(ti->ti_win); 1314924Swnj ti->ti_urp = ntohs(ti->ti_urp); 1324601Swnj 1334601Swnj /* 1344601Swnj * Check segment seq # and do rst processing 1354601Swnj */ 1364924Swnj tiflags = ti->ti_flags; 1374601Swnj switch (tp->t_state) { 1384601Swnj 1394601Swnj case LISTEN: 1404924Swnj if ((tiflags&TH_ACK) || (tiflags&TH_SYN) == 0) { 1414924Swnj tcp_sndrst(tp, ti); 1424924Swnj goto bad; 1434601Swnj } 1444924Swnj if (tiflags&TH_RST) 1454924Swnj goto bad; 1464924Swnj goto good; 1474601Swnj 1484601Swnj case SYN_SENT: 1494924Swnj if (!ack_ok(tp, ti) || (tiflags&TH_SYN) == 0) { 1504924Swnj tcp_sndrst(tp, ti); /* 71,72,75 */ 1514924Swnj goto bad; 1524601Swnj } 1534924Swnj if (tiflags&TH_RST) { 1544803Swnj tcp_error(tp, ENETRESET); 1554803Swnj tcp_detach(tp); /* 70 */ 1564601Swnj tp->t_state = CLOSED; 1574924Swnj goto bad; 1584601Swnj } 1594924Swnj goto good; 1604601Swnj 1614601Swnj default: 1624924Swnj if ((tiflags&TH_RST) == 0) 1634601Swnj goto common; 1644924Swnj if (ti->ti_seq < tp->rcv_nxt) /* bad rst */ 1654924Swnj goto bad; /* 69 */ 1664601Swnj switch (tp->t_state) { 1674601Swnj 1684601Swnj case L_SYN_RCVD: 1694924Swnj if (ack_ok(tp, ti) == 0) 1704924Swnj goto bad; /* 69 */ 1714601Swnj tp->t_rexmt = 0; 1724601Swnj tp->t_rexmttl = 0; 1734601Swnj tp->t_persist = 0; 1744953Swnj inp->inp_faddr.s_addr = 0; 1754601Swnj tp->t_state = LISTEN; 1764924Swnj goto bad; 1774601Swnj 1784601Swnj default: 1794803Swnj tcp_error(tp, ENETRESET); 1804803Swnj tcp_detach(tp); /* 66 */ 1814601Swnj tp->t_state = CLOSED; 1824924Swnj goto bad; 1834601Swnj } 1844601Swnj /*NOTREACHED*/ 1854601Swnj 1864601Swnj case SYN_RCVD: 1874601Swnj common: 1884924Swnj if (ack_ok(tp, ti) == 0) { 1894924Swnj tcp_sndrst(tp, ti); /* 74 */ 1904924Swnj goto bad; 1914601Swnj } 1924924Swnj if ((tiflags&TH_SYN) == 0 && ti->ti_seq != tp->irs) { 1934679Swnj tcp_sndnull(tp); /* 74 */ 1944924Swnj goto bad; 1954601Swnj } 1964924Swnj goto good; 1974601Swnj } 1984924Swnj bad: 1994924Swnj m_freem(m); 2004601Swnj return; 2014601Swnj 2024924Swnj good: 2034601Swnj /* 2044601Swnj * Defer processing if no buffer space for this connection. 2054601Swnj */ 2064884Swnj so = inp->inp_socket; 2074803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 2084924Swnj ti->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 2094803Swnj /* 2104924Swnj m->m_act = (struct mbuf *)0; 2114803Swnj if ((m = tp->seg_unack) != NULL) { 2124601Swnj while (m->m_act != NULL) 2134601Swnj m = m->m_act; 2144924Swnj m->m_act = m0; 2154601Swnj } else 2164924Swnj tp->seg_unack = m0; 2174803Swnj */ 2184924Swnj m_freem(m0); 2194601Swnj return; 2204601Swnj } 2214601Swnj 2224601Swnj /* 2234601Swnj * Discard ip header, and do tcp input processing. 2244601Swnj */ 2254924Swnj off += sizeof (struct ip); 2264924Swnj m->m_off += off; 2274924Swnj m->m_len -= off; 2284601Swnj nstate = tp->t_state; 2294601Swnj tp->tc_flags &= ~TC_NET_KEEP; 2304770Swnj #ifdef KPROF 2314601Swnj acounts[tp->t_state][INRECV]++; 2324770Swnj #endif 2334601Swnj #ifdef TCPDEBUG 2344803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2354924Swnj tdb_setup(tp, ti, INRECV, &tdb); 2364601Swnj } else 2374601Swnj tdb.td_tod = 0; 2384601Swnj #endif 2394601Swnj switch (tp->t_state) { 2404601Swnj 2414601Swnj case LISTEN: 2424953Swnj tcp_sockaddr.sin_addr = ti->ti_src; 2434953Swnj tcp_sockaddr.sin_port = ti->ti_sport; 2444953Swnj if ((tiflags&TH_SYN) == 0 || in_pcbsetpeer(inp, &tcp_sockaddr)) { 2454601Swnj nstate = EFAILEC; 2464601Swnj goto done; 2474601Swnj } 2484733Swnj tp->t_template = tcp_template(tp); 2494924Swnj tcp_ctldat(tp, ti, 1); 2504601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2514601Swnj tp->t_finack = T_2ML; /* 3 */ 2524601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2534601Swnj nstate = CLOSE_WAIT; 2544601Swnj } else { 2554884Swnj tp->t_init = T_INIT / 2; /* 4 */ 2564601Swnj nstate = L_SYN_RCVD; 2574601Swnj } 2584601Swnj goto done; 2594601Swnj 2604601Swnj case SYN_SENT: 2614924Swnj if (!syn_ok(tp, ti)) { 2624601Swnj nstate = EFAILEC; 2634601Swnj goto done; 2644601Swnj } 2654924Swnj tcp_ctldat(tp, ti, 1); 2664601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2674924Swnj if ((tiflags&TH_ACK) == 0) { 2684601Swnj tp->t_finack = T_2ML; /* 9 */ 2694601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2704601Swnj } 2714601Swnj nstate = CLOSE_WAIT; 2724601Swnj goto done; 2734601Swnj } 2744924Swnj nstate = (tiflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2754601Swnj goto done; 2764601Swnj 2774601Swnj case SYN_RCVD: 2784601Swnj case L_SYN_RCVD: 2794924Swnj if ((tiflags&TH_ACK) == 0 || 2804924Swnj (tiflags&TH_ACK) && ti->ti_ackno <= tp->iss) { 2814601Swnj nstate = EFAILEC; 2824601Swnj goto done; 2834601Swnj } 2844601Swnj goto input; 2854601Swnj 2864601Swnj case ESTAB: 2874601Swnj case FIN_W1: 2884601Swnj case FIN_W2: 2894601Swnj case TIME_WAIT: 2904601Swnj input: 2914924Swnj tcp_ctldat(tp, ti, 1); /* 39 */ 2924601Swnj switch (tp->t_state) { 2934601Swnj 2944601Swnj case ESTAB: 2954601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2964601Swnj nstate = CLOSE_WAIT; 2974601Swnj break; 2984601Swnj 2994601Swnj case SYN_RCVD: 3004601Swnj case L_SYN_RCVD: 3014601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 3024601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 3034601Swnj break; 3044601Swnj 3054601Swnj case FIN_W1: 3064924Swnj j = ack_fin(tp, ti); 3074601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 3084601Swnj if (j) 3094601Swnj nstate = FIN_W2; /* 27 */ 3104601Swnj break; 3114601Swnj } 3124601Swnj tp->t_finack = T_2ML; 3134601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3144730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 3154601Swnj break; 3164601Swnj 3174601Swnj case FIN_W2: 3184601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 3194601Swnj tp->t_finack = T_2ML; /* 29 */ 3204601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3214601Swnj nstate = TIME_WAIT; 3224601Swnj break; 3234601Swnj } 3244601Swnj break; 3254601Swnj } 3264601Swnj goto done; 3274601Swnj 3284601Swnj case CLOSE_WAIT: 3294924Swnj if (tiflags&TH_FIN) { 3304924Swnj if ((tiflags&TH_ACK) && 3314924Swnj ti->ti_ackno <= tp->seq_fin) { 3324924Swnj tcp_ctldat(tp, ti, 0); /* 30 */ 3334601Swnj tp->t_finack = T_2ML; 3344601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3354601Swnj } else 3364909Swnj (void) tcp_sndctl(tp); /* 31 */ 3374601Swnj goto done; 3384601Swnj } 3394601Swnj goto input; 3404601Swnj 3414730Swnj case CLOSING: 3424924Swnj j = ack_fin(tp, ti); 3434924Swnj if (tiflags&TH_FIN) { 3444924Swnj tcp_ctldat(tp, ti, 0); 3454601Swnj tp->t_finack = T_2ML; 3464601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3474601Swnj if (j) 3484601Swnj nstate = TIME_WAIT; /* 23 */ 3494601Swnj goto done; 3504601Swnj } 3514601Swnj if (j) { 3524601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3534601Swnj if (rcv_empty(tp)) { 3544884Swnj sorwakeup(inp->inp_socket); 3554803Swnj nstate = CLOSED; /* 15 */ 3564601Swnj } else 3574601Swnj nstate = RCV_WAIT; /* 18 */ 3584601Swnj else 3594601Swnj nstate = TIME_WAIT; 3604601Swnj goto done; 3614601Swnj } 3624601Swnj goto input; 3634601Swnj 3644730Swnj case LAST_ACK: 3654924Swnj if (ack_fin(tp, ti)) { 3664884Swnj if (rcv_empty(tp)) { /* 16 */ 3674884Swnj sorwakeup(inp->inp_socket); 3684601Swnj nstate = CLOSED; 3694601Swnj } else 3704601Swnj nstate = RCV_WAIT; /* 19 */ 3714601Swnj goto done; 3724601Swnj } 3734924Swnj if (tiflags&TH_FIN) { 3744909Swnj (void) tcp_sndctl(tp); /* 31 */ 3754601Swnj goto done; 3764601Swnj } 3774601Swnj goto input; 3784601Swnj 3794601Swnj case RCV_WAIT: 3804924Swnj if ((tiflags&TH_FIN) && (tiflags&TH_ACK) && 3814924Swnj ti->ti_ackno <= tp->seq_fin) { 3824924Swnj tcp_ctldat(tp, ti, 0); 3834601Swnj tp->t_finack = T_2ML; 3844601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3854601Swnj } 3864601Swnj goto done; 3874601Swnj } 3884601Swnj panic("tcp_input"); 3894601Swnj done: 3904601Swnj 3914601Swnj /* 3924601Swnj * Done with state*input specific processing. 3934601Swnj * Form trace records, free input if not needed, 3944601Swnj * and enter new state. 3954601Swnj */ 3964601Swnj #ifdef TCPDEBUG 3974604Swnj if (tdb.td_tod) 3984604Swnj tdb_stuff(&tdb, nstate); 3994601Swnj #endif 4004601Swnj switch (nstate) { 4014601Swnj 4024601Swnj case EFAILEC: 4034924Swnj m_freem(m); 4044601Swnj return; 4054601Swnj 4064601Swnj default: 4074601Swnj tp->t_state = nstate; 4084601Swnj /* fall into ... */ 4094601Swnj 4104601Swnj case CLOSED: 4114601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 4124924Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) { 4134924Swnj register struct mbuf *n; 4144690Swnj /* inline expansion of m_freem */ 4154924Swnj while (m) { 4164953Swnj MFREE(m, n); 4174924Swnj m = n; 4184690Swnj } 4194924Swnj } 4204601Swnj return; 4214601Swnj } 4224601Swnj /* NOTREACHED */ 4234601Swnj 4244601Swnj /* 4254601Swnj * Unwanted packed; free everything 4264601Swnj * but the header and return an rst. 4274601Swnj */ 4284601Swnj notwanted: 4294924Swnj m_freem(m->m_next); 4304924Swnj m->m_next = NULL; 4314924Swnj m->m_len = sizeof(struct tcpiphdr); 4324601Swnj #define xchg(a,b) j=a; a=b; b=j 4334924Swnj xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr); 4344924Swnj xchg(ti->ti_dport, ti->ti_sport); 4354601Swnj #undef xchg 4364924Swnj if (tiflags&TH_ACK) 4374924Swnj ti->ti_seq = ti->ti_ackno; 4384601Swnj else { 4394953Swnj ti->ti_ackno = htonl((unsigned)(ntohl(ti->ti_seq) + ti->ti_len)); 4404924Swnj ti->ti_seq = 0; 4414601Swnj } 4424924Swnj ti->ti_flags = ((tiflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 4434924Swnj ti->ti_len = htons(TCPSIZE); 4444924Swnj ti->ti_off = 5; 4454924Swnj ti->ti_sum = inet_cksum(m, sizeof(struct tcpiphdr)); 4464924Swnj ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr); 4474924Swnj ip_output(m); 4484924Swnj tcpstat.tcps_badsegs++; 4494601Swnj } 4504601Swnj 4514884Swnj tcp_ctldat(tp, n0, dataok) 4524884Swnj register struct tcpcb *tp; 4534884Swnj struct tcpiphdr *n0; 4544884Swnj int dataok; 4554601Swnj { 4564924Swnj register struct tcpiphdr *ti = n0; 4574924Swnj register int tiflags = ti->ti_flags; 4584884Swnj struct socket *so = tp->t_inpcb->inp_socket; 4594924Swnj seq_t past = ti->ti_seq + ti->ti_len; 4604884Swnj seq_t urgent; 4614679Swnj int sent; 4624679Swnj COUNT(TCP_CTLDAT); 4634601Swnj 4644924Swnj if (tiflags & TH_URG) 4654924Swnj urgent = ti->ti_seq + ti->ti_urp; 4664884Swnj tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW); 4674601Swnj /* syn */ 4684924Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (tiflags&TH_SYN)) { 4694924Swnj tp->irs = ti->ti_seq; 4704924Swnj tp->rcv_nxt = ti->ti_seq + 1; 4714601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4724601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4734601Swnj } 4744601Swnj /* ack */ 4754924Swnj if ((tiflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4764924Swnj ti->ti_ackno > tp->snd_una) { 4774884Swnj /* 4784884Swnj * Reflect newly acknowledged data. 4794884Swnj */ 4804924Swnj tp->snd_una = ti->ti_ackno; 4814601Swnj if (tp->snd_una > tp->snd_nxt) 4824601Swnj tp->snd_nxt = tp->snd_una; 4834884Swnj 4844884Swnj /* 4854884Swnj * If timed msg acked, update retransmit time value. 4864884Swnj */ 4874601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4884601Swnj tp->snd_una > tp->t_xmt_val) { 4894884Swnj /* NEED SMOOTHING HERE */ 4904601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4914601Swnj if (tp->t_xmtime > T_REMAX) 4924601Swnj tp->t_xmtime = T_REMAX; 4934601Swnj } 4944601Swnj 4954884Swnj /* 4964884Swnj * Remove acked data from send buf 4974884Swnj */ 4984909Swnj sbdrop(&so->so_snd, (int)(tp->snd_una - tp->snd_off)); 4994601Swnj tp->snd_off = tp->snd_una; 5004601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 5014601Swnj (tp->snd_una > tp->iss)) { 5024601Swnj tp->tc_flags |= TC_SYN_ACKED; 5034601Swnj tp->t_init = 0; 5044601Swnj } 5054601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 5064601Swnj tp->tc_flags &= ~TC_SND_FIN; 5074601Swnj tp->t_rexmt = 0; 5084601Swnj tp->t_rexmttl = 0; 5094601Swnj tp->tc_flags |= TC_CANCELLED; 5104884Swnj sowwakeup(tp->t_inpcb->inp_socket); 5114601Swnj } 5124601Swnj /* win */ 5134924Swnj if ((tp->tc_flags & TC_SYN_RCVD) && ti->ti_seq >= tp->snd_wl) { 5144924Swnj tp->snd_wl = ti->ti_seq; 5154924Swnj tp->snd_wnd = ti->ti_win; 5164601Swnj tp->tc_flags |= TC_NEW_WINDOW; 5174601Swnj tp->t_persist = 0; 5184601Swnj } 5194601Swnj /* text */ 5204924Swnj if (dataok && ti->ti_len) { 5214909Swnj register struct tcpiphdr *q; 5224884Swnj int overage; 5234601Swnj 5244884Swnj /* eol */ 5254924Swnj if ((tiflags&TH_EOL)) { 5264884Swnj register struct mbuf *m; 5274924Swnj for (m = dtom(ti); m->m_next; m = m->m_next) 5284884Swnj ; 5294884Swnj m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1); 5304884Swnj } 5314601Swnj 5324884Swnj /* text */ 5334884Swnj /* 5344884Swnj * Discard duplicate data already passed to user. 5354884Swnj */ 5364924Swnj if (SEQ_LT(ti->ti_seq, tp->rcv_nxt)) { 5374924Swnj register int i = tp->rcv_nxt - ti->ti_seq; 5384924Swnj if (i >= ti->ti_len) 5394884Swnj goto notext; 5404924Swnj ti->ti_seq += i; 5414924Swnj ti->ti_len -= i; 5424924Swnj m_adj(dtom(ti), i); 5434601Swnj } 5444601Swnj 5454884Swnj /* 5464884Swnj * Find a segment which begins after this one does. 5474884Swnj */ 5484884Swnj for (q = tp->seg_next; q != (struct tcpiphdr *)tp; 5494899Swnj q = (struct tcpiphdr *)q->ti_next) 5504924Swnj if (SEQ_GT(q->ti_seq, ti->ti_seq)) 5514884Swnj break; 5524884Swnj 5534884Swnj /* 5544884Swnj * If there is a preceding segment, it may provide some of 5554884Swnj * our data already. If so, drop the data from the incoming 5564884Swnj * segment. If it provides all of our data, drop us. 5574884Swnj */ 5584899Swnj if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { 5594899Swnj register int i; 5604899Swnj q = (struct tcpiphdr *)(q->ti_prev); 5614884Swnj /* conversion to int (in i) handles seq wraparound */ 5624924Swnj i = q->ti_seq + q->ti_len - ti->ti_seq; 5634884Swnj if (i > 0) { 5644924Swnj if (i >= ti->ti_len) 5654884Swnj goto notext; 5664884Swnj /* w/o setting TC_NET_KEEP */ 5674884Swnj m_adj(dtom(tp), i); 5684924Swnj ti->ti_len -= i; 5694924Swnj ti->ti_seq += i; 5704884Swnj } 5714899Swnj q = (struct tcpiphdr *)(q->ti_next); 5724601Swnj } 5734601Swnj 5744884Swnj /* 5754884Swnj * While we overlap succeeding segments trim them or, 5764884Swnj * if they are completely covered, dequeue them. 5774884Swnj */ 5784884Swnj while (q != (struct tcpiphdr *)tp && 5794924Swnj SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) { 5804924Swnj register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; 5814899Swnj if (i < q->ti_len) { 5824899Swnj q->ti_len -= i; 5834884Swnj m_adj(dtom(q), i); 5844884Swnj break; 5854884Swnj } 5864899Swnj q = (struct tcpiphdr *)q->ti_next; 5874899Swnj m_freem(dtom(q->ti_prev)); 5884899Swnj remque(q->ti_prev); 5894884Swnj } 5904601Swnj 5914884Swnj /* 5924884Swnj * Stick new segment in its place. 5934884Swnj */ 5944924Swnj insque(ti, q->ti_prev); 5954924Swnj tp->seqcnt += ti->ti_len; 5964884Swnj 5974884Swnj /* 5984884Swnj * Calculate available space and discard segments for 5994884Swnj * which there is too much. 6004884Swnj */ 6014884Swnj overage = 6024884Swnj (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat; 6034884Swnj if (overage > 0) { 6044884Swnj q = tp->seg_prev; 6054884Swnj for (;;) { 6064899Swnj register int i = MIN(q->ti_len, overage); 6074884Swnj overage -= i; 6084899Swnj q->ti_len -= i; 6094909Swnj m_adj(dtom(q), -i); 6104899Swnj if (q->ti_len) 6114884Swnj break; 6124924Swnj if (q == ti) 6134884Swnj panic("tcp_text dropall"); 6144899Swnj q = (struct tcpiphdr *)q->ti_prev; 6154899Swnj remque(q->ti_next); 6164884Swnj } 6174884Swnj } 6184884Swnj 6194884Swnj /* 6204884Swnj * Advance rcv_next through newly completed sequence space. 6214884Swnj */ 6224924Swnj while (ti->ti_seq == tp->rcv_nxt) { 6234924Swnj tp->rcv_nxt += ti->ti_len; 6244924Swnj ti = (struct tcpiphdr *)ti->ti_next; 6254924Swnj if (ti == (struct tcpiphdr *)tp) 6264645Swnj break; 6274645Swnj } 6284679Swnj /* urg */ 6294924Swnj if (tiflags&TH_URG) { 6304884Swnj /* ... */ 6314884Swnj if (SEQ_GT(urgent, tp->rcv_urp)) 6324803Swnj tp->rcv_urp = urgent; 6334679Swnj } 6344884Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 6354884Swnj } 6364884Swnj notext: 6374679Swnj /* fin */ 6384924Swnj if ((tiflags&TH_FIN) && past == tp->rcv_nxt) { 6394884Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 6404884Swnj tp->tc_flags |= TC_FIN_RCVD; 6414884Swnj sorwakeup(so); 6424884Swnj tp->rcv_nxt++; 6434803Swnj } 6444884Swnj tp->tc_flags |= TC_ACK_DUE; 6454679Swnj } 6464679Swnj /* respond */ 6474679Swnj sent = 0; 6484679Swnj if (tp->tc_flags&TC_ACK_DUE) 6494679Swnj sent = tcp_sndctl(tp); 6504803Swnj else if ((tp->tc_flags&TC_NEW_WINDOW)) 6514884Swnj if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc || 6524803Swnj (tp->tc_flags&TC_SND_FIN)) 6534679Swnj sent = tcp_send(tp); 6544679Swnj 6554679Swnj /* set for retrans */ 6564679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6574679Swnj (tp->tc_flags&TC_CANCELLED)) { 6584679Swnj tp->t_rexmt = tp->t_xmtime; 6594679Swnj tp->t_rexmttl = T_REXMTTL; 6604679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6614679Swnj tp->tc_flags &= ~TC_CANCELLED; 6624679Swnj } 6634690Swnj /* present data to user */ 6644656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6654601Swnj return; 6664924Swnj ti = tp->seg_next; 6674924Swnj while (ti != (struct tcpiphdr *)tp && ti->ti_seq < tp->rcv_nxt) { 6684924Swnj remque(ti); 6694924Swnj sbappend(&so->so_rcv, dtom(ti)); 6704924Swnj tp->seqcnt -= ti->ti_len; 6714884Swnj if (tp->seqcnt < 0) 6724884Swnj panic("tcp_input present"); 6734924Swnj ti = (struct tcpiphdr *)ti->ti_next; 6744601Swnj } 6754884Swnj sorwakeup(so); 6764601Swnj } 677