xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4909)
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