xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4884)
1*4884Swnj /* tcp_input.c 1.22 81/11/14 */
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"
10*4884Swnj #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"
154803Swnj #include "../net/tcp.h"
164803Swnj #include "../net/tcp_fsm.h"
174803Swnj #include "../net/tcp_var.h"
184803Swnj #include "/usr/include/errno.h"
194601Swnj 
204679Swnj int	tcpcksum = 1;
214601Swnj 
22*4884Swnj tcp_drain()
234803Swnj {
24*4884Swnj 	register struct inpcb *ip;
254803Swnj 
26*4884Swnj 	for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next)
27*4884Swnj 		tcp_drainunack(intotcpcb(ip));
284803Swnj }
294803Swnj 
30*4884Swnj tcp_drainunack(tp)
31*4884Swnj 	register struct tcpcb *tp;
32*4884Swnj {
33*4884Swnj 	register struct mbuf *m;
34*4884Swnj 
35*4884Swnj 	for (m = tp->seg_unack; m; m = m->m_act)
36*4884Swnj 		m_freem(m);
37*4884Swnj 	tp->seg_unack = 0;
38*4884Swnj }
39*4884Swnj 
40*4884Swnj tcp_ctlinput(m)
41*4884Swnj 	struct mbuf *m;
42*4884Swnj {
43*4884Swnj 
44*4884Swnj 	m_freem(m);
45*4884Swnj }
46*4884Swnj 
474601Swnj tcp_input(mp)
484601Swnj 	register struct mbuf *mp;
494601Swnj {
50*4884Swnj 	register struct tcpiphdr *n;		/* known to be r10 */
514697Swnj 	register int j;
52*4884Swnj 	register struct tcpcb *tp;
53*4884Swnj 	struct inpcb *inp;
544803Swnj 	register int thflags;
554601Swnj 	int nstate;
564601Swnj 	struct mbuf *m;
574803Swnj 	struct socket *so;
584673Swnj 	int hlen, tlen;
594601Swnj 	u_short lport, fport;
604601Swnj #ifdef TCPDEBUG
614601Swnj 	struct tcp_debug tdb;
624601Swnj #endif
634601Swnj COUNT(TCP_INPUT);
644601Swnj 
654601Swnj 	/*
664601Swnj 	 * Build extended tcp header
674601Swnj 	 */
68*4884Swnj 	n = mtod(mp, struct tcpiphdr *);
694803Swnj 	thflags = n->th_flags;
704601Swnj 	tlen = ((struct ip *)n)->ip_len;
714601Swnj 	n->t_len = htons(tlen);
724601Swnj 	n->t_next = NULL;
734601Swnj 	n->t_prev = NULL;
744601Swnj 	n->t_x1 = 0;
754601Swnj 	lport = ntohs(n->t_dst);
764601Swnj 	fport = ntohs(n->t_src);
774601Swnj 
784601Swnj 	/* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */
794601Swnj 	if ((hlen = n->t_off << 2) > mp->m_len)
804601Swnj 		{ printf("tcp header overflow\n"); m_freem(mp); return; }
814601Swnj 
824679Swnj 	if (tcpcksum) {
834679Swnj 		/*
844679Swnj 		 * Checksum extended header and data
854679Swnj 		 */
864718Swnj 		CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen);
874718Swnj 		if (n->t_sum != 0) {
884679Swnj 			netstat.t_badsum++;
894601Swnj 			m_freem(mp);
904601Swnj 			return;
914601Swnj 		}
924601Swnj 	}
934601Swnj 
944601Swnj 	/*
95*4884Swnj 	 * Find tcb for message.
964601Swnj 	 */
97*4884Swnj 	inp = in_pcblookup(&tcb, &n->t_s, fport, &n_lhost, lport);
98*4884Swnj 	if (inp == 0)
99*4884Swnj 		goto notwanted;
1004601Swnj 
1014601Swnj 	/*
1024601Swnj 	 * Byte swap header
1034601Swnj 	 */
1044601Swnj 	n->t_len = tlen - hlen;
1054601Swnj 	n->t_src = fport;
1064601Swnj 	n->t_dst = lport;
1074601Swnj 	n->t_seq = ntohl(n->t_seq);
1084601Swnj 	n->t_ackno = ntohl(n->t_ackno);
1094601Swnj 	n->t_win = ntohs(n->t_win);
1104601Swnj 	n->t_urp = ntohs(n->t_urp);
1114601Swnj 
1124601Swnj 	/*
1134601Swnj 	 * Check segment seq # and do rst processing
1144601Swnj 	 */
1154601Swnj 	switch (tp->t_state) {
1164601Swnj 
1174601Swnj 	case LISTEN:
1184803Swnj 		if ((thflags&TH_ACK) || !syn_ok(tp, n)) {
1194675Swnj 			tcp_sndrst(tp, n);
1204601Swnj 			goto badseg;
1214601Swnj 		}
1224803Swnj 		if (thflags&TH_RST)
1234601Swnj 			goto badseg;
1244601Swnj 		goto goodseg;
1254601Swnj 
1264601Swnj 	case SYN_SENT:
1274601Swnj 		if (!ack_ok(tp, n) || !syn_ok(tp, n)) {
1284675Swnj 			tcp_sndrst(tp, n);			/* 71,72,75 */
1294601Swnj 			goto badseg;
1304601Swnj 		}
1314803Swnj 		if (thflags&TH_RST) {
1324803Swnj 			tcp_error(tp, ENETRESET);
1334803Swnj 			tcp_detach(tp);				/* 70 */
1344601Swnj 			tp->t_state = CLOSED;
1354601Swnj 			goto badseg;
1364601Swnj 		}
1374601Swnj 		goto goodseg;
1384601Swnj 
1394601Swnj 	default:
1404803Swnj         	if ((thflags&TH_RST) == 0)
1414601Swnj 			goto common;
1424601Swnj 		if (n->t_seq < tp->rcv_nxt)		/* bad rst */
1434601Swnj 			goto badseg;				/* 69 */
1444601Swnj 		switch (tp->t_state) {
1454601Swnj 
1464601Swnj 		case L_SYN_RCVD:
1474601Swnj 			if (ack_ok(tp, n) == 0)
1484601Swnj 				goto badseg;			/* 69 */
1494601Swnj 			tp->t_rexmt = 0;
1504601Swnj 			tp->t_rexmttl = 0;
1514601Swnj 			tp->t_persist = 0;
152*4884Swnj 			h_free(inp->inp_fhost);
153*4884Swnj 			inp->inp_fhost = 0;
1544601Swnj 			tp->t_state = LISTEN;
1554601Swnj 			goto badseg;
1564601Swnj 
1574601Swnj 		default:
1584803Swnj 			tcp_error(tp, ENETRESET);
1594803Swnj 			tcp_detach(tp);				/* 66 */
1604601Swnj 			tp->t_state = CLOSED;
1614601Swnj 			goto badseg;
1624601Swnj 		}
1634601Swnj 		/*NOTREACHED*/
1644601Swnj 
1654601Swnj 	case SYN_RCVD:
1664601Swnj common:
1674601Swnj 		if (ack_ok(tp, n) == 0) {
1684675Swnj 			tcp_sndrst(tp, n);			/* 74 */
1694601Swnj 			goto badseg;
1704601Swnj 		}
1714601Swnj 		if (syn_ok(tp, n) && n->t_seq != tp->irs) {
1724679Swnj 			tcp_sndnull(tp);			/* 74 */
1734601Swnj 			goto badseg;
1744601Swnj 		}
1754601Swnj 		goto goodseg;
1764601Swnj 	}
1774601Swnj badseg:
1784601Swnj 	m_freem(mp);
1794601Swnj 	return;
1804601Swnj 
1814601Swnj goodseg:
1824601Swnj 	/*
1834601Swnj 	 * Defer processing if no buffer space for this connection.
1844601Swnj 	 */
185*4884Swnj 	so = inp->inp_socket;
1864803Swnj 	if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
1874803Swnj 	     n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
1884803Swnj /*
1894601Swnj 		mp->m_act = (struct mbuf *)0;
1904803Swnj 		if ((m = tp->seg_unack) != NULL) {
1914601Swnj 			while (m->m_act != NULL)
1924601Swnj 				m = m->m_act;
1934601Swnj 			m->m_act = mp;
1944601Swnj 		} else
1954803Swnj 			tp->seg_unack = mp;
1964803Swnj */
1974803Swnj 		m_freem(mp);
1984601Swnj 		return;
1994601Swnj 	}
2004601Swnj 
2014601Swnj 	/*
2024601Swnj 	 * Discard ip header, and do tcp input processing.
2034601Swnj 	 */
2044601Swnj 	hlen += sizeof(struct ip);
2054601Swnj 	mp->m_off += hlen;
2064601Swnj 	mp->m_len -= hlen;
2074601Swnj 	nstate = tp->t_state;
2084601Swnj 	tp->tc_flags &= ~TC_NET_KEEP;
2094770Swnj #ifdef KPROF
2104601Swnj 	acounts[tp->t_state][INRECV]++;
2114770Swnj #endif
2124601Swnj #ifdef TCPDEBUG
2134803Swnj 	if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) {
2144604Swnj 		tdb_setup(tp, n, INRECV, &tdb);
2154601Swnj 	} else
2164601Swnj 		tdb.td_tod = 0;
2174601Swnj #endif
2184601Swnj 	switch (tp->t_state) {
2194601Swnj 
2204601Swnj 	case LISTEN:
2214601Swnj 		if (!syn_ok(tp, n) ||
222*4884Swnj 		    ((inp->inp_lhost = in_hmake(&n->t_s)) == 0)) {
2234601Swnj 			nstate = EFAILEC;
2244601Swnj 			goto done;
2254601Swnj 		}
226*4884Swnj 		inp->inp_fport = n->t_src;
2274733Swnj 		tp->t_template = tcp_template(tp);
2284675Swnj 		tcp_ctldat(tp, n, 1);
2294601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
2304601Swnj 			tp->t_finack = T_2ML;			/* 3 */
2314601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
2324601Swnj 			nstate = CLOSE_WAIT;
2334601Swnj 		} else {
234*4884Swnj 			tp->t_init = T_INIT / 2;		/* 4 */
2354601Swnj 			nstate = L_SYN_RCVD;
2364601Swnj 		}
2374601Swnj 		goto done;
2384601Swnj 
2394601Swnj 	case SYN_SENT:
2404601Swnj 		if (!syn_ok(tp, n)) {
2414601Swnj 			nstate = EFAILEC;
2424601Swnj 			goto done;
2434601Swnj 		}
2444675Swnj 		tcp_ctldat(tp, n, 1);
2454601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
2464803Swnj 			if ((thflags&TH_ACK) == 0) {
2474601Swnj 				tp->t_finack = T_2ML;		/* 9 */
2484601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
2494601Swnj 			}
2504601Swnj 			nstate = CLOSE_WAIT;
2514601Swnj 			goto done;
2524601Swnj 		}
2534803Swnj 		nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */
2544601Swnj 		goto done;
2554601Swnj 
2564601Swnj 	case SYN_RCVD:
2574601Swnj 	case L_SYN_RCVD:
2584803Swnj 		if ((thflags&TH_ACK) == 0 ||
2594803Swnj 		    (thflags&TH_ACK) && n->t_ackno <= tp->iss) {
2604601Swnj 			nstate = EFAILEC;
2614601Swnj 			goto done;
2624601Swnj 		}
2634601Swnj 		goto input;
2644601Swnj 
2654601Swnj 	case ESTAB:
2664601Swnj 	case FIN_W1:
2674601Swnj 	case FIN_W2:
2684601Swnj 	case TIME_WAIT:
2694601Swnj input:
2704675Swnj 		tcp_ctldat(tp, n, 1);				/* 39 */
2714601Swnj 		switch (tp->t_state) {
2724601Swnj 
2734601Swnj 		case ESTAB:
2744601Swnj 			if (tp->tc_flags&TC_FIN_RCVD)
2754601Swnj 				nstate = CLOSE_WAIT;
2764601Swnj 			break;
2774601Swnj 
2784601Swnj 		case SYN_RCVD:
2794601Swnj 		case L_SYN_RCVD:
2804601Swnj 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
2814601Swnj 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
2824601Swnj 			break;
2834601Swnj 
2844601Swnj 		case FIN_W1:
2854601Swnj 			j = ack_fin(tp, n);
2864601Swnj 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
2874601Swnj 				if (j)
2884601Swnj 					nstate = FIN_W2;	/* 27 */
2894601Swnj 				break;
2904601Swnj 			}
2914601Swnj 			tp->t_finack = T_2ML;
2924601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
2934730Swnj 			nstate = j ? TIME_WAIT : CLOSING;	/* 28:26 */
2944601Swnj 			break;
2954601Swnj 
2964601Swnj 		case FIN_W2:
2974601Swnj 			if (tp->tc_flags&TC_FIN_RCVD) {
2984601Swnj 				tp->t_finack = T_2ML;		/* 29 */
2994601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
3004601Swnj 				nstate = TIME_WAIT;
3014601Swnj 				break;
3024601Swnj 			}
3034601Swnj 			break;
3044601Swnj 		}
3054601Swnj 		goto done;
3064601Swnj 
3074601Swnj 	case CLOSE_WAIT:
3084803Swnj 		if (thflags&TH_FIN) {
3094803Swnj 			if ((thflags&TH_ACK) &&
3104601Swnj 			    n->t_ackno <= tp->seq_fin) {
3114675Swnj 				tcp_ctldat(tp, n, 0);		/* 30 */
3124601Swnj 				tp->t_finack = T_2ML;
3134601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
3144601Swnj 			} else
3154675Swnj 				tcp_sndctl(tp);			/* 31 */
3164601Swnj 			goto done;
3174601Swnj 		}
3184601Swnj 		goto input;
3194601Swnj 
3204730Swnj 	case CLOSING:
3214601Swnj 		j = ack_fin(tp, n);
3224803Swnj 		if (thflags&TH_FIN) {
3234675Swnj 			tcp_ctldat(tp, n, 0);
3244601Swnj 			tp->t_finack = T_2ML;
3254601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
3264601Swnj 			if (j)
3274601Swnj 				nstate = TIME_WAIT;		/* 23 */
3284601Swnj 			goto done;
3294601Swnj 		}
3304601Swnj 		if (j) {
3314601Swnj 			if (tp->tc_flags&TC_WAITED_2_ML)
3324601Swnj 				if (rcv_empty(tp)) {
333*4884Swnj 					sorwakeup(inp->inp_socket);
3344803Swnj 					nstate = CLOSED;	/* 15 */
3354601Swnj 				} else
3364601Swnj 					nstate = RCV_WAIT;	/* 18 */
3374601Swnj 			else
3384601Swnj 				nstate = TIME_WAIT;
3394601Swnj 			goto done;
3404601Swnj 		}
3414601Swnj 		goto input;
3424601Swnj 
3434730Swnj 	case LAST_ACK:
3444601Swnj 		if (ack_fin(tp, n)) {
345*4884Swnj 			if (rcv_empty(tp)) {		/* 16 */
346*4884Swnj 				sorwakeup(inp->inp_socket);
3474601Swnj 				nstate = CLOSED;
3484601Swnj 			} else
3494601Swnj 				nstate = RCV_WAIT;		/* 19 */
3504601Swnj 			goto done;
3514601Swnj 		}
3524803Swnj 		if (thflags&TH_FIN) {
3534675Swnj 			tcp_sndctl(tp);				/* 31 */
3544601Swnj 			goto done;
3554601Swnj 		}
3564601Swnj 		goto input;
3574601Swnj 
3584601Swnj 	case RCV_WAIT:
3594803Swnj 		if ((thflags&TH_FIN) && (thflags&TH_ACK) &&
3604601Swnj 		    n->t_ackno <= tp->seq_fin) {
3614675Swnj 			tcp_ctldat(tp, n, 0);
3624601Swnj 			tp->t_finack = T_2ML;
3634601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
3644601Swnj 		}
3654601Swnj 		goto done;
3664601Swnj 	}
3674601Swnj 	panic("tcp_input");
3684601Swnj done:
3694601Swnj 
3704601Swnj 	/*
3714601Swnj 	 * Done with state*input specific processing.
3724601Swnj 	 * Form trace records, free input if not needed,
3734601Swnj 	 * and enter new state.
3744601Swnj 	 */
3754601Swnj #ifdef TCPDEBUG
3764604Swnj 	if (tdb.td_tod)
3774604Swnj 		tdb_stuff(&tdb, nstate);
3784601Swnj #endif
3794601Swnj 	switch (nstate) {
3804601Swnj 
3814601Swnj 	case EFAILEC:
3824601Swnj 		m_freem(mp);
3834601Swnj 		return;
3844601Swnj 
3854601Swnj 	default:
3864601Swnj 		tp->t_state = nstate;
3874601Swnj 		/* fall into ... */
3884601Swnj 
3894601Swnj 	case CLOSED:
3904601Swnj 		/* IF CLOSED CANT LOOK AT tc_flags */
3914601Swnj 		if ((tp->tc_flags&TC_NET_KEEP) == 0)
3924690Swnj 			/* inline expansion of m_freem */
3934690Swnj 			while (mp) {
3944690Swnj 				MFREE(mp, m);
3954690Swnj 				mp = m;
3964690Swnj 			}
3974601Swnj 		return;
3984601Swnj 	}
3994601Swnj 	/* NOTREACHED */
4004601Swnj 
4014601Swnj 	/*
4024601Swnj 	 * Unwanted packed; free everything
4034601Swnj 	 * but the header and return an rst.
4044601Swnj 	 */
4054601Swnj notwanted:
4064601Swnj 	m_freem(mp->m_next);
4074601Swnj 	mp->m_next = NULL;
408*4884Swnj 	mp->m_len = sizeof(struct tcpiphdr);
4094601Swnj #define xchg(a,b) j=a; a=b; b=j
4104601Swnj 	xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
4114601Swnj #undef xchg
4124803Swnj 	if (thflags&TH_ACK)
4134601Swnj 		n->t_seq = n->t_ackno;
4144601Swnj 	else {
4154601Swnj 		n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen);
4164601Swnj 		n->t_seq = 0;
4174601Swnj 	}
4184803Swnj 	n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
4194601Swnj 	n->t_len = htons(TCPSIZE);
4204601Swnj 	n->t_off = 5;
421*4884Swnj 	n->t_sum = inet_cksum(mp, sizeof(struct tcpiphdr));
422*4884Swnj 	((struct ip *)n)->ip_len = sizeof(struct tcpiphdr);
4234601Swnj 	ip_output(mp);
4244601Swnj 	netstat.t_badsegs++;
4254601Swnj }
4264601Swnj 
427*4884Swnj tcp_ctldat(tp, n0, dataok)
428*4884Swnj 	register struct tcpcb *tp;
429*4884Swnj 	struct tcpiphdr *n0;
430*4884Swnj 	int dataok;
4314601Swnj {
4324679Swnj 	register struct mbuf *m;
433*4884Swnj 	register struct tcpiphdr *n = n0;
4344803Swnj 	register int thflags = n->th_flags;
435*4884Swnj 	struct socket *so = tp->t_inpcb->inp_socket;
436*4884Swnj 	seq_t past = n->t_seq + n->t_len;
437*4884Swnj 	seq_t urgent;
4384679Swnj 	int sent;
4394679Swnj COUNT(TCP_CTLDAT);
4404601Swnj 
441*4884Swnj 	if (thflags & TH_URG)
442*4884Swnj 		urgent = n->t_seq + n->t_urp;
443*4884Swnj 	tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW);
4444601Swnj /* syn */
4454803Swnj 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) {
4464601Swnj 		tp->irs = n->t_seq;
4474601Swnj 		tp->rcv_nxt = n->t_seq + 1;
4484601Swnj 		tp->snd_wl = tp->rcv_urp = tp->irs;
4494601Swnj 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
4504601Swnj 	}
4514601Swnj /* ack */
4524803Swnj 	if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
4534601Swnj 	    n->t_ackno > tp->snd_una) {
4544679Swnj 		register struct mbuf *mn;
4554679Swnj 
456*4884Swnj 		/*
457*4884Swnj 		 * Reflect newly acknowledged data.
458*4884Swnj 		 */
4594601Swnj 		tp->snd_una = n->t_ackno;
4604601Swnj 		if (tp->snd_una > tp->snd_nxt)
4614601Swnj 			tp->snd_nxt = tp->snd_una;
462*4884Swnj 
463*4884Swnj 		/*
464*4884Swnj 		 * If timed msg acked, update retransmit time value.
465*4884Swnj 		 */
4664601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) &&
4674601Swnj 		    tp->snd_una > tp->t_xmt_val) {
468*4884Swnj 			/* NEED SMOOTHING HERE */
4694601Swnj 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
4704601Swnj 			if (tp->t_xmtime > T_REMAX)
4714601Swnj 				tp->t_xmtime = T_REMAX;
4724601Swnj 		}
4734601Swnj 
474*4884Swnj 		/*
475*4884Swnj 		 * Remove acked data from send buf
476*4884Swnj 		 */
477*4884Swnj 		sbdrop(&so->so_snd, tp->snd_una - tp->snd_off);
4784601Swnj 		tp->snd_off = tp->snd_una;
4794601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
4804601Swnj 		    (tp->snd_una > tp->iss)) {
4814601Swnj 			tp->tc_flags |= TC_SYN_ACKED;
4824601Swnj 			tp->t_init = 0;
4834601Swnj 		}
4844601Swnj 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
4854601Swnj 			tp->tc_flags &= ~TC_SND_FIN;
4864601Swnj 		tp->t_rexmt = 0;
4874601Swnj 		tp->t_rexmttl = 0;
4884601Swnj 		tp->tc_flags |= TC_CANCELLED;
489*4884Swnj 		sowwakeup(tp->t_inpcb->inp_socket);
4904601Swnj 	}
4914601Swnj /* win */
4924601Swnj 	if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
4934601Swnj 		tp->snd_wl = n->t_seq;
4944601Swnj 		tp->snd_wnd = n->t_win;
4954601Swnj 		tp->tc_flags |= TC_NEW_WINDOW;
4964601Swnj 		tp->t_persist = 0;
4974601Swnj 	}
4984601Swnj /* text */
499*4884Swnj 	if (dataok && n->t_len) {
500*4884Swnj 		register struct tcpiphdr *p, *q;
501*4884Swnj 		int overage;
5024601Swnj 
503*4884Swnj /* eol */
504*4884Swnj 		if ((thflags&TH_EOL)) {
505*4884Swnj 			register struct mbuf *m;
506*4884Swnj 			for (m = dtom(n); m->m_next; m = m->m_next)
507*4884Swnj 				;
508*4884Swnj 			m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1);
509*4884Swnj 		}
5104601Swnj 
511*4884Swnj /* text */
512*4884Swnj 		/*
513*4884Swnj 		 * Discard duplicate data already passed to user.
514*4884Swnj 		 */
515*4884Swnj 		if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
516*4884Swnj 			register int i = tp->rcv_nxt - n->t_seq;
5174645Swnj 			if (i >= n->t_len)
518*4884Swnj 				goto notext;
519*4884Swnj 			n->t_seq += i;
5204645Swnj 			n->t_len -= i;
521*4884Swnj 			m_adj(dtom(n), i);
5224601Swnj 		}
5234601Swnj 
524*4884Swnj 		/*
525*4884Swnj 		 * Find a segment which begins after this one does.
526*4884Swnj 		 */
527*4884Swnj 		for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
528*4884Swnj 		    q = q->t_next)
529*4884Swnj 			if (SEQ_GT(q->t_seq, n->t_seq))
530*4884Swnj 				break;
531*4884Swnj 
532*4884Swnj 		/*
533*4884Swnj 		 * If there is a preceding segment, it may provide some of
534*4884Swnj 		 * our data already.  If so, drop the data from the incoming
535*4884Swnj 		 * segment.  If it provides all of our data, drop us.
536*4884Swnj 		 */
537*4884Swnj 		if (q->t_prev != (struct tcpiphdr *)tp) {
538*4884Swnj 			/* conversion to int (in i) handles seq wraparound */
539*4884Swnj 			register int i =
540*4884Swnj 			    q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
541*4884Swnj 			if (i > 0) {
542*4884Swnj 				if (i >= n->t_len)
543*4884Swnj 					goto notext;
544*4884Swnj 						/* w/o setting TC_NET_KEEP */
545*4884Swnj 				m_adj(dtom(tp), i);
546*4884Swnj 				n->t_len -= i;
547*4884Swnj 				n->t_seq += i;
548*4884Swnj 			}
5494601Swnj 		}
5504601Swnj 
551*4884Swnj 		/*
552*4884Swnj 		 * While we overlap succeeding segments trim them or,
553*4884Swnj 		 * if they are completely covered, dequeue them.
554*4884Swnj 		 */
555*4884Swnj 		while (q != (struct tcpiphdr *)tp &&
556*4884Swnj 		    SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
557*4884Swnj 			register int i = (n->t_seq + n->t_len) - q->t_seq;
558*4884Swnj 			if (i < q->t_len) {
559*4884Swnj 				q->t_len -= i;
560*4884Swnj 				m_adj(dtom(q), i);
561*4884Swnj 				break;
562*4884Swnj 			}
563*4884Swnj 			q = q->t_next;
564*4884Swnj 			m_freem(dtom(q->t_prev));
565*4884Swnj 			remque(q->t_prev);
566*4884Swnj 		}
5674601Swnj 
568*4884Swnj 		/*
569*4884Swnj 		 * Stick new segment in its place.
570*4884Swnj 		 */
571*4884Swnj 		insque(n, q->t_prev);
572*4884Swnj 		tp->seqcnt += n->t_len;
573*4884Swnj 
574*4884Swnj 		/*
575*4884Swnj 		 * Calculate available space and discard segments for
576*4884Swnj 		 * which there is too much.
577*4884Swnj 		 */
578*4884Swnj 		overage =
579*4884Swnj 		    (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat;
580*4884Swnj 		if (overage > 0) {
581*4884Swnj 			q = tp->seg_prev;
582*4884Swnj 			for (;;) {
583*4884Swnj 				register int i = MIN(q->t_len, overage);
584*4884Swnj 				overage -= i;
585*4884Swnj 				q->t_len -= i;
586*4884Swnj 				m_adj(q, -i);
587*4884Swnj 				if (q->t_len)
588*4884Swnj 					break;
589*4884Swnj 				if (q == n)
590*4884Swnj 					panic("tcp_text dropall");
591*4884Swnj 				q = q->t_prev;
592*4884Swnj 				remque(q->t_next);
593*4884Swnj 			}
594*4884Swnj 		}
595*4884Swnj 
596*4884Swnj 		/*
597*4884Swnj 		 * Advance rcv_next through newly completed sequence space.
598*4884Swnj 		 */
599*4884Swnj 		while (n->t_seq == tp->rcv_nxt) {
600*4884Swnj 			tp->rcv_nxt += n->t_len;
601*4884Swnj 			n = n->t_next;
602*4884Swnj 			if (n == (struct tcpiphdr *)tp)
6034645Swnj 				break;
6044645Swnj 		}
6054679Swnj /* urg */
6064803Swnj 		if (thflags&TH_URG) {
607*4884Swnj 			/* ... */
608*4884Swnj 			if (SEQ_GT(urgent, tp->rcv_urp))
6094803Swnj 				tp->rcv_urp = urgent;
6104679Swnj 		}
611*4884Swnj 		tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
612*4884Swnj 	}
613*4884Swnj notext:
6144679Swnj /* fin */
615*4884Swnj 	if ((thflags&TH_FIN) && past == tp->rcv_nxt) {
616*4884Swnj 		if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
617*4884Swnj 			tp->tc_flags |= TC_FIN_RCVD;
618*4884Swnj 			sorwakeup(so);
619*4884Swnj 			tp->rcv_nxt++;
6204803Swnj 		}
621*4884Swnj 		tp->tc_flags |= TC_ACK_DUE;
6224679Swnj 	}
6234679Swnj /* respond */
6244679Swnj 	sent = 0;
6254679Swnj 	if (tp->tc_flags&TC_ACK_DUE)
6264679Swnj 		sent = tcp_sndctl(tp);
6274803Swnj 	else if ((tp->tc_flags&TC_NEW_WINDOW))
628*4884Swnj 		if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc ||
6294803Swnj 		    (tp->tc_flags&TC_SND_FIN))
6304679Swnj 			sent = tcp_send(tp);
6314679Swnj 
6324679Swnj /* set for retrans */
6334679Swnj 	if (!sent && tp->snd_una < tp->snd_nxt &&
6344679Swnj 	    (tp->tc_flags&TC_CANCELLED)) {
6354679Swnj 		tp->t_rexmt = tp->t_xmtime;
6364679Swnj 		tp->t_rexmttl = T_REXMTTL;
6374679Swnj 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
6384679Swnj 		tp->tc_flags &= ~TC_CANCELLED;
6394679Swnj 	}
6404690Swnj /* present data to user */
6414656Swnj 	if ((tp->tc_flags&TC_SYN_ACKED) == 0)
6424601Swnj 		return;
643*4884Swnj 	n = tp->seg_next;
644*4884Swnj 	while (n != (struct tcpiphdr *)tp && n->t_seq < tp->rcv_nxt) {
6454690Swnj 		remque(n);
646*4884Swnj 		sbappend(so->so_rcv, dtom(n));
6474690Swnj 		tp->seqcnt -= n->t_len;
648*4884Swnj 		if (tp->seqcnt < 0)
649*4884Swnj 			panic("tcp_input present");
6504690Swnj 		n = n->t_next;
6514601Swnj 	}
652*4884Swnj 	sorwakeup(so);
6534601Swnj }
654