xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4924)
1*4924Swnj /* tcp_input.c 1.25 81/11/18 */
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/inet_host.h"
134803Swnj #include "../net/ip.h"
144899Swnj #include "../net/ip_var.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 
224884Swnj tcp_drain()
234803Swnj {
244884Swnj 	register struct inpcb *ip;
254803Swnj 
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 
354884Swnj 	for (m = tp->seg_unack; m; m = m->m_act)
364884Swnj 		m_freem(m);
374884Swnj 	tp->seg_unack = 0;
384884Swnj }
394884Swnj 
404884Swnj tcp_ctlinput(m)
414884Swnj 	struct mbuf *m;
424884Swnj {
434884Swnj 
444884Swnj 	m_freem(m);
454884Swnj }
464884Swnj 
47*4924Swnj tcp_input(m0)
48*4924Swnj 	struct mbuf *m0;
494601Swnj {
50*4924Swnj 	register struct tcpiphdr *ti;
51*4924Swnj 	struct inpcb *inp;
52*4924Swnj 	register struct mbuf *m;
53*4924Swnj 	int len, tlen, off;
54*4924Swnj 
55*4924Swnj 	register struct tcpcb *tp;
564697Swnj 	register int j;
57*4924Swnj 	register int tiflags;
584601Swnj 	int nstate;
594803Swnj 	struct socket *so;
604601Swnj #ifdef TCPDEBUG
614601Swnj 	struct tcp_debug tdb;
624601Swnj #endif
63*4924Swnj 
644601Swnj COUNT(TCP_INPUT);
65*4924Swnj 	/*
66*4924Swnj 	 * Get ip and tcp header together in first mbuf.
67*4924Swnj 	 */
68*4924Swnj 	m = m0;
69*4924Swnj 	ti = mtod(m, struct tcpiphdr *);
70*4924Swnj 	if (ti->ti_len > sizeof (struct ip))
71*4924Swnj 		ip_stripoptions((struct ip *)ti);
72*4924Swnj 	if (m->m_len < sizeof (struct tcpiphdr) &&
73*4924Swnj 	    m_pullup(m, sizeof (struct tcpiphdr)) == 0) {
74*4924Swnj 		tcpstat.tcps_hdrops++;
75*4924Swnj 		goto bad;
76*4924Swnj 	}
774601Swnj 
784601Swnj 	/*
79*4924Swnj 	 * Checksum extended tcp header and data.
804601Swnj 	 */
81*4924Swnj 	tlen = ((struct ip *)ti)->ip_len;
82*4924Swnj 	len = sizeof (struct ip) + tlen;
834679Swnj 	if (tcpcksum) {
84*4924Swnj 		ti->ti_next = ti->ti_prev = 0;
85*4924Swnj 		ti->ti_x1 = 0;
86*4924Swnj 		ti->ti_len = htons(tlen);
87*4924Swnj 		if (ti->ti_sum = inet_cksum(m, len)) {
88*4924Swnj 			tcpstat.tcps_badsum++;
89*4924Swnj 			printf("tcp cksum %x\ti", ti->ti_sum);
90*4924Swnj 			goto bad;
914601Swnj 		}
924601Swnj 	}
934601Swnj 
944601Swnj 	/*
95*4924Swnj 	 * Check that tcp offset makes sense,
96*4924Swnj 	 * process tcp options and adjust length.
974601Swnj 	 */
98*4924Swnj 	off = ti->ti_off << 2;
99*4924Swnj 	if (off < sizeof (struct tcphdr) || off > ti->ti_len) {
100*4924Swnj 		tcpstat.tcps_badoff++;
101*4924Swnj 		goto bad;
102*4924Swnj 	}
103*4924Swnj 	ti->ti_len = tlen - off;
104*4924Swnj 	/* PROCESS OPTIONS */
105*4924Swnj 
106*4924Swnj 	/*
107*4924Swnj 	 * Convert addresses and ports to host format.
108*4924Swnj 	 * Locate pcb for segment.
109*4924Swnj 	 */
110*4924Swnj 	ti->ti_src.s_addr = ntohl(ti->ti_src.s_addr);
111*4924Swnj 	ti->ti_dst.s_addr = ntohl(ti->ti_dst.s_addr);
112*4924Swnj 	ti->ti_sport = ntohs(ti->ti_sport);
113*4924Swnj 	ti->ti_dport = ntohs(ti->ti_dport);
114*4924Swnj 	inp = in_pcblookup(&tcb, &ti->ti_src, ti->ti_sport, &ti->ti_dst, ti->ti_dport);
1154884Swnj 	if (inp == 0)
1164884Swnj 		goto notwanted;
117*4924Swnj 	tp = intotcpcb(inp);		/* ??? */
118*4924Swnj 	if (tp == 0)			/* ??? */
119*4924Swnj 		goto notwanted;		/* ??? */
1204601Swnj 
1214601Swnj 	/*
122*4924Swnj 	 * Convert tcp protocol specific fields to host format.
1234601Swnj 	 */
124*4924Swnj 	ti->ti_seq = ntohl(ti->ti_seq);
125*4924Swnj 	ti->ti_ackno = ntohl((n_long)ti->ti_ackno);
126*4924Swnj 	ti->ti_win = ntohs(ti->ti_win);
127*4924Swnj 	ti->ti_urp = ntohs(ti->ti_urp);
1284601Swnj 
1294601Swnj 	/*
1304601Swnj 	 * Check segment seq # and do rst processing
1314601Swnj 	 */
132*4924Swnj 	tiflags = ti->ti_flags;
1334601Swnj 	switch (tp->t_state) {
1344601Swnj 
1354601Swnj 	case LISTEN:
136*4924Swnj 		if ((tiflags&TH_ACK) || (tiflags&TH_SYN) == 0) {
137*4924Swnj 			tcp_sndrst(tp, ti);
138*4924Swnj 			goto bad;
1394601Swnj 		}
140*4924Swnj 		if (tiflags&TH_RST)
141*4924Swnj 			goto bad;
142*4924Swnj 		goto good;
1434601Swnj 
1444601Swnj 	case SYN_SENT:
145*4924Swnj 		if (!ack_ok(tp, ti) || (tiflags&TH_SYN) == 0) {
146*4924Swnj 			tcp_sndrst(tp, ti);			/* 71,72,75 */
147*4924Swnj 			goto bad;
1484601Swnj 		}
149*4924Swnj 		if (tiflags&TH_RST) {
1504803Swnj 			tcp_error(tp, ENETRESET);
1514803Swnj 			tcp_detach(tp);				/* 70 */
1524601Swnj 			tp->t_state = CLOSED;
153*4924Swnj 			goto bad;
1544601Swnj 		}
155*4924Swnj 		goto good;
1564601Swnj 
1574601Swnj 	default:
158*4924Swnj         	if ((tiflags&TH_RST) == 0)
1594601Swnj 			goto common;
160*4924Swnj 		if (ti->ti_seq < tp->rcv_nxt)		/* bad rst */
161*4924Swnj 			goto bad;				/* 69 */
1624601Swnj 		switch (tp->t_state) {
1634601Swnj 
1644601Swnj 		case L_SYN_RCVD:
165*4924Swnj 			if (ack_ok(tp, ti) == 0)
166*4924Swnj 				goto bad;			/* 69 */
1674601Swnj 			tp->t_rexmt = 0;
1684601Swnj 			tp->t_rexmttl = 0;
1694601Swnj 			tp->t_persist = 0;
1704909Swnj 			in_hostfree(inp->inp_fhost);
1714884Swnj 			inp->inp_fhost = 0;
1724601Swnj 			tp->t_state = LISTEN;
173*4924Swnj 			goto bad;
1744601Swnj 
1754601Swnj 		default:
1764803Swnj 			tcp_error(tp, ENETRESET);
1774803Swnj 			tcp_detach(tp);				/* 66 */
1784601Swnj 			tp->t_state = CLOSED;
179*4924Swnj 			goto bad;
1804601Swnj 		}
1814601Swnj 		/*NOTREACHED*/
1824601Swnj 
1834601Swnj 	case SYN_RCVD:
1844601Swnj common:
185*4924Swnj 		if (ack_ok(tp, ti) == 0) {
186*4924Swnj 			tcp_sndrst(tp, ti);			/* 74 */
187*4924Swnj 			goto bad;
1884601Swnj 		}
189*4924Swnj 		if ((tiflags&TH_SYN) == 0 && ti->ti_seq != tp->irs) {
1904679Swnj 			tcp_sndnull(tp);			/* 74 */
191*4924Swnj 			goto bad;
1924601Swnj 		}
193*4924Swnj 		goto good;
1944601Swnj 	}
195*4924Swnj bad:
196*4924Swnj 	m_freem(m);
1974601Swnj 	return;
1984601Swnj 
199*4924Swnj good:
2004601Swnj 	/*
2014601Swnj 	 * Defer processing if no buffer space for this connection.
2024601Swnj 	 */
2034884Swnj 	so = inp->inp_socket;
2044803Swnj 	if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat &&
205*4924Swnj 	     ti->ti_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
2064803Swnj /*
207*4924Swnj 		m->m_act = (struct mbuf *)0;
2084803Swnj 		if ((m = tp->seg_unack) != NULL) {
2094601Swnj 			while (m->m_act != NULL)
2104601Swnj 				m = m->m_act;
211*4924Swnj 			m->m_act = m0;
2124601Swnj 		} else
213*4924Swnj 			tp->seg_unack = m0;
2144803Swnj */
215*4924Swnj 		m_freem(m0);
2164601Swnj 		return;
2174601Swnj 	}
2184601Swnj 
2194601Swnj 	/*
2204601Swnj 	 * Discard ip header, and do tcp input processing.
2214601Swnj 	 */
222*4924Swnj 	off += sizeof (struct ip);
223*4924Swnj 	m->m_off += off;
224*4924Swnj 	m->m_len -= off;
2254601Swnj 	nstate = tp->t_state;
2264601Swnj 	tp->tc_flags &= ~TC_NET_KEEP;
2274770Swnj #ifdef KPROF
2284601Swnj 	acounts[tp->t_state][INRECV]++;
2294770Swnj #endif
2304601Swnj #ifdef TCPDEBUG
2314803Swnj 	if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) {
232*4924Swnj 		tdb_setup(tp, ti, INRECV, &tdb);
2334601Swnj 	} else
2344601Swnj 		tdb.td_tod = 0;
2354601Swnj #endif
2364601Swnj 	switch (tp->t_state) {
2374601Swnj 
2384601Swnj 	case LISTEN:
239*4924Swnj 		if ((tiflags&TH_SYN) == 0 ||
240*4924Swnj 		    ((inp->inp_lhost = in_hostalloc(&ti->ti_src)) == 0)) {
2414601Swnj 			nstate = EFAILEC;
2424601Swnj 			goto done;
2434601Swnj 		}
244*4924Swnj 		inp->inp_fport = ti->ti_sport;
2454733Swnj 		tp->t_template = tcp_template(tp);
246*4924Swnj 		tcp_ctldat(tp, ti, 1);
2474601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
2484601Swnj 			tp->t_finack = T_2ML;			/* 3 */
2494601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
2504601Swnj 			nstate = CLOSE_WAIT;
2514601Swnj 		} else {
2524884Swnj 			tp->t_init = T_INIT / 2;		/* 4 */
2534601Swnj 			nstate = L_SYN_RCVD;
2544601Swnj 		}
2554601Swnj 		goto done;
2564601Swnj 
2574601Swnj 	case SYN_SENT:
258*4924Swnj 		if (!syn_ok(tp, ti)) {
2594601Swnj 			nstate = EFAILEC;
2604601Swnj 			goto done;
2614601Swnj 		}
262*4924Swnj 		tcp_ctldat(tp, ti, 1);
2634601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
264*4924Swnj 			if ((tiflags&TH_ACK) == 0) {
2654601Swnj 				tp->t_finack = T_2ML;		/* 9 */
2664601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
2674601Swnj 			}
2684601Swnj 			nstate = CLOSE_WAIT;
2694601Swnj 			goto done;
2704601Swnj 		}
271*4924Swnj 		nstate = (tiflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */
2724601Swnj 		goto done;
2734601Swnj 
2744601Swnj 	case SYN_RCVD:
2754601Swnj 	case L_SYN_RCVD:
276*4924Swnj 		if ((tiflags&TH_ACK) == 0 ||
277*4924Swnj 		    (tiflags&TH_ACK) && ti->ti_ackno <= tp->iss) {
2784601Swnj 			nstate = EFAILEC;
2794601Swnj 			goto done;
2804601Swnj 		}
2814601Swnj 		goto input;
2824601Swnj 
2834601Swnj 	case ESTAB:
2844601Swnj 	case FIN_W1:
2854601Swnj 	case FIN_W2:
2864601Swnj 	case TIME_WAIT:
2874601Swnj input:
288*4924Swnj 		tcp_ctldat(tp, ti, 1);				/* 39 */
2894601Swnj 		switch (tp->t_state) {
2904601Swnj 
2914601Swnj 		case ESTAB:
2924601Swnj 			if (tp->tc_flags&TC_FIN_RCVD)
2934601Swnj 				nstate = CLOSE_WAIT;
2944601Swnj 			break;
2954601Swnj 
2964601Swnj 		case SYN_RCVD:
2974601Swnj 		case L_SYN_RCVD:
2984601Swnj 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
2994601Swnj 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
3004601Swnj 			break;
3014601Swnj 
3024601Swnj 		case FIN_W1:
303*4924Swnj 			j = ack_fin(tp, ti);
3044601Swnj 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
3054601Swnj 				if (j)
3064601Swnj 					nstate = FIN_W2;	/* 27 */
3074601Swnj 				break;
3084601Swnj 			}
3094601Swnj 			tp->t_finack = T_2ML;
3104601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
3114730Swnj 			nstate = j ? TIME_WAIT : CLOSING;	/* 28:26 */
3124601Swnj 			break;
3134601Swnj 
3144601Swnj 		case FIN_W2:
3154601Swnj 			if (tp->tc_flags&TC_FIN_RCVD) {
3164601Swnj 				tp->t_finack = T_2ML;		/* 29 */
3174601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
3184601Swnj 				nstate = TIME_WAIT;
3194601Swnj 				break;
3204601Swnj 			}
3214601Swnj 			break;
3224601Swnj 		}
3234601Swnj 		goto done;
3244601Swnj 
3254601Swnj 	case CLOSE_WAIT:
326*4924Swnj 		if (tiflags&TH_FIN) {
327*4924Swnj 			if ((tiflags&TH_ACK) &&
328*4924Swnj 			    ti->ti_ackno <= tp->seq_fin) {
329*4924Swnj 				tcp_ctldat(tp, ti, 0);		/* 30 */
3304601Swnj 				tp->t_finack = T_2ML;
3314601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
3324601Swnj 			} else
3334909Swnj 				(void) tcp_sndctl(tp);		/* 31 */
3344601Swnj 			goto done;
3354601Swnj 		}
3364601Swnj 		goto input;
3374601Swnj 
3384730Swnj 	case CLOSING:
339*4924Swnj 		j = ack_fin(tp, ti);
340*4924Swnj 		if (tiflags&TH_FIN) {
341*4924Swnj 			tcp_ctldat(tp, ti, 0);
3424601Swnj 			tp->t_finack = T_2ML;
3434601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
3444601Swnj 			if (j)
3454601Swnj 				nstate = TIME_WAIT;		/* 23 */
3464601Swnj 			goto done;
3474601Swnj 		}
3484601Swnj 		if (j) {
3494601Swnj 			if (tp->tc_flags&TC_WAITED_2_ML)
3504601Swnj 				if (rcv_empty(tp)) {
3514884Swnj 					sorwakeup(inp->inp_socket);
3524803Swnj 					nstate = CLOSED;	/* 15 */
3534601Swnj 				} else
3544601Swnj 					nstate = RCV_WAIT;	/* 18 */
3554601Swnj 			else
3564601Swnj 				nstate = TIME_WAIT;
3574601Swnj 			goto done;
3584601Swnj 		}
3594601Swnj 		goto input;
3604601Swnj 
3614730Swnj 	case LAST_ACK:
362*4924Swnj 		if (ack_fin(tp, ti)) {
3634884Swnj 			if (rcv_empty(tp)) {		/* 16 */
3644884Swnj 				sorwakeup(inp->inp_socket);
3654601Swnj 				nstate = CLOSED;
3664601Swnj 			} else
3674601Swnj 				nstate = RCV_WAIT;		/* 19 */
3684601Swnj 			goto done;
3694601Swnj 		}
370*4924Swnj 		if (tiflags&TH_FIN) {
3714909Swnj 			(void) tcp_sndctl(tp);			/* 31 */
3724601Swnj 			goto done;
3734601Swnj 		}
3744601Swnj 		goto input;
3754601Swnj 
3764601Swnj 	case RCV_WAIT:
377*4924Swnj 		if ((tiflags&TH_FIN) && (tiflags&TH_ACK) &&
378*4924Swnj 		    ti->ti_ackno <= tp->seq_fin) {
379*4924Swnj 			tcp_ctldat(tp, ti, 0);
3804601Swnj 			tp->t_finack = T_2ML;
3814601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
3824601Swnj 		}
3834601Swnj 		goto done;
3844601Swnj 	}
3854601Swnj 	panic("tcp_input");
3864601Swnj done:
3874601Swnj 
3884601Swnj 	/*
3894601Swnj 	 * Done with state*input specific processing.
3904601Swnj 	 * Form trace records, free input if not needed,
3914601Swnj 	 * and enter new state.
3924601Swnj 	 */
3934601Swnj #ifdef TCPDEBUG
3944604Swnj 	if (tdb.td_tod)
3954604Swnj 		tdb_stuff(&tdb, nstate);
3964601Swnj #endif
3974601Swnj 	switch (nstate) {
3984601Swnj 
3994601Swnj 	case EFAILEC:
400*4924Swnj 		m_freem(m);
4014601Swnj 		return;
4024601Swnj 
4034601Swnj 	default:
4044601Swnj 		tp->t_state = nstate;
4054601Swnj 		/* fall into ... */
4064601Swnj 
4074601Swnj 	case CLOSED:
4084601Swnj 		/* IF CLOSED CANT LOOK AT tc_flags */
409*4924Swnj 		if ((tp->tc_flags&TC_NET_KEEP) == 0) {
410*4924Swnj 			register struct mbuf *n;
4114690Swnj 			/* inline expansion of m_freem */
412*4924Swnj 			while (m) {
413*4924Swnj 				MFREE(n, m);
414*4924Swnj 				m = n;
4154690Swnj 			}
416*4924Swnj 		}
4174601Swnj 		return;
4184601Swnj 	}
4194601Swnj 	/* NOTREACHED */
4204601Swnj 
4214601Swnj 	/*
4224601Swnj 	 * Unwanted packed; free everything
4234601Swnj 	 * but the header and return an rst.
4244601Swnj 	 */
4254601Swnj notwanted:
426*4924Swnj 	m_freem(m->m_next);
427*4924Swnj 	m->m_next = NULL;
428*4924Swnj 	m->m_len = sizeof(struct tcpiphdr);
4294601Swnj #define xchg(a,b) j=a; a=b; b=j
430*4924Swnj 	xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr);
431*4924Swnj 	xchg(ti->ti_dport, ti->ti_sport);
4324601Swnj #undef xchg
433*4924Swnj 	if (tiflags&TH_ACK)
434*4924Swnj 		ti->ti_seq = ti->ti_ackno;
4354601Swnj 	else {
436*4924Swnj 		ti->ti_ackno = htonl(ntohl(ti->ti_seq) + ti->ti_len);
437*4924Swnj 		ti->ti_seq = 0;
4384601Swnj 	}
439*4924Swnj 	ti->ti_flags = ((tiflags & TH_ACK) ? 0 : TH_ACK) | TH_RST;
440*4924Swnj 	ti->ti_len = htons(TCPSIZE);
441*4924Swnj 	ti->ti_off = 5;
442*4924Swnj 	ti->ti_sum = inet_cksum(m, sizeof(struct tcpiphdr));
443*4924Swnj 	((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr);
444*4924Swnj 	ip_output(m);
445*4924Swnj 	tcpstat.tcps_badsegs++;
4464601Swnj }
4474601Swnj 
4484884Swnj tcp_ctldat(tp, n0, dataok)
4494884Swnj 	register struct tcpcb *tp;
4504884Swnj 	struct tcpiphdr *n0;
4514884Swnj 	int dataok;
4524601Swnj {
453*4924Swnj 	register struct tcpiphdr *ti = n0;
454*4924Swnj 	register int tiflags = ti->ti_flags;
4554884Swnj 	struct socket *so = tp->t_inpcb->inp_socket;
456*4924Swnj 	seq_t past = ti->ti_seq + ti->ti_len;
4574884Swnj 	seq_t urgent;
4584679Swnj 	int sent;
4594679Swnj COUNT(TCP_CTLDAT);
4604601Swnj 
461*4924Swnj 	if (tiflags & TH_URG)
462*4924Swnj 		urgent = ti->ti_seq + ti->ti_urp;
4634884Swnj 	tp->tc_flags &= ~(TC_ACK_DUE|TC_NEW_WINDOW);
4644601Swnj /* syn */
465*4924Swnj 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (tiflags&TH_SYN)) {
466*4924Swnj 		tp->irs = ti->ti_seq;
467*4924Swnj 		tp->rcv_nxt = ti->ti_seq + 1;
4684601Swnj 		tp->snd_wl = tp->rcv_urp = tp->irs;
4694601Swnj 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
4704601Swnj 	}
4714601Swnj /* ack */
472*4924Swnj 	if ((tiflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
473*4924Swnj 	    ti->ti_ackno > tp->snd_una) {
4744884Swnj 		/*
4754884Swnj 		 * Reflect newly acknowledged data.
4764884Swnj 		 */
477*4924Swnj 		tp->snd_una = ti->ti_ackno;
4784601Swnj 		if (tp->snd_una > tp->snd_nxt)
4794601Swnj 			tp->snd_nxt = tp->snd_una;
4804884Swnj 
4814884Swnj 		/*
4824884Swnj 		 * If timed msg acked, update retransmit time value.
4834884Swnj 		 */
4844601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) &&
4854601Swnj 		    tp->snd_una > tp->t_xmt_val) {
4864884Swnj 			/* NEED SMOOTHING HERE */
4874601Swnj 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
4884601Swnj 			if (tp->t_xmtime > T_REMAX)
4894601Swnj 				tp->t_xmtime = T_REMAX;
4904601Swnj 		}
4914601Swnj 
4924884Swnj 		/*
4934884Swnj 		 * Remove acked data from send buf
4944884Swnj 		 */
4954909Swnj 		sbdrop(&so->so_snd, (int)(tp->snd_una - tp->snd_off));
4964601Swnj 		tp->snd_off = tp->snd_una;
4974601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
4984601Swnj 		    (tp->snd_una > tp->iss)) {
4994601Swnj 			tp->tc_flags |= TC_SYN_ACKED;
5004601Swnj 			tp->t_init = 0;
5014601Swnj 		}
5024601Swnj 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
5034601Swnj 			tp->tc_flags &= ~TC_SND_FIN;
5044601Swnj 		tp->t_rexmt = 0;
5054601Swnj 		tp->t_rexmttl = 0;
5064601Swnj 		tp->tc_flags |= TC_CANCELLED;
5074884Swnj 		sowwakeup(tp->t_inpcb->inp_socket);
5084601Swnj 	}
5094601Swnj /* win */
510*4924Swnj 	if ((tp->tc_flags & TC_SYN_RCVD) && ti->ti_seq >= tp->snd_wl) {
511*4924Swnj 		tp->snd_wl = ti->ti_seq;
512*4924Swnj 		tp->snd_wnd = ti->ti_win;
5134601Swnj 		tp->tc_flags |= TC_NEW_WINDOW;
5144601Swnj 		tp->t_persist = 0;
5154601Swnj 	}
5164601Swnj /* text */
517*4924Swnj 	if (dataok && ti->ti_len) {
5184909Swnj 		register struct tcpiphdr *q;
5194884Swnj 		int overage;
5204601Swnj 
5214884Swnj /* eol */
522*4924Swnj 		if ((tiflags&TH_EOL)) {
5234884Swnj 			register struct mbuf *m;
524*4924Swnj 			for (m = dtom(ti); m->m_next; m = m->m_next)
5254884Swnj 				;
5264884Swnj 			m->m_act = (struct mbuf *)(mtod(m, caddr_t) - 1);
5274884Swnj 		}
5284601Swnj 
5294884Swnj /* text */
5304884Swnj 		/*
5314884Swnj 		 * Discard duplicate data already passed to user.
5324884Swnj 		 */
533*4924Swnj 		if (SEQ_LT(ti->ti_seq, tp->rcv_nxt)) {
534*4924Swnj 			register int i = tp->rcv_nxt - ti->ti_seq;
535*4924Swnj 			if (i >= ti->ti_len)
5364884Swnj 				goto notext;
537*4924Swnj 			ti->ti_seq += i;
538*4924Swnj 			ti->ti_len -= i;
539*4924Swnj 			m_adj(dtom(ti), i);
5404601Swnj 		}
5414601Swnj 
5424884Swnj 		/*
5434884Swnj 		 * Find a segment which begins after this one does.
5444884Swnj 		 */
5454884Swnj 		for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
5464899Swnj 		    q = (struct tcpiphdr *)q->ti_next)
547*4924Swnj 			if (SEQ_GT(q->ti_seq, ti->ti_seq))
5484884Swnj 				break;
5494884Swnj 
5504884Swnj 		/*
5514884Swnj 		 * If there is a preceding segment, it may provide some of
5524884Swnj 		 * our data already.  If so, drop the data from the incoming
5534884Swnj 		 * segment.  If it provides all of our data, drop us.
5544884Swnj 		 */
5554899Swnj 		if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
5564899Swnj 			register int i;
5574899Swnj 			q = (struct tcpiphdr *)(q->ti_prev);
5584884Swnj 			/* conversion to int (in i) handles seq wraparound */
559*4924Swnj 			i = q->ti_seq + q->ti_len - ti->ti_seq;
5604884Swnj 			if (i > 0) {
561*4924Swnj 				if (i >= ti->ti_len)
5624884Swnj 					goto notext;
5634884Swnj 						/* w/o setting TC_NET_KEEP */
5644884Swnj 				m_adj(dtom(tp), i);
565*4924Swnj 				ti->ti_len -= i;
566*4924Swnj 				ti->ti_seq += i;
5674884Swnj 			}
5684899Swnj 			q = (struct tcpiphdr *)(q->ti_next);
5694601Swnj 		}
5704601Swnj 
5714884Swnj 		/*
5724884Swnj 		 * While we overlap succeeding segments trim them or,
5734884Swnj 		 * if they are completely covered, dequeue them.
5744884Swnj 		 */
5754884Swnj 		while (q != (struct tcpiphdr *)tp &&
576*4924Swnj 		    SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) {
577*4924Swnj 			register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
5784899Swnj 			if (i < q->ti_len) {
5794899Swnj 				q->ti_len -= i;
5804884Swnj 				m_adj(dtom(q), i);
5814884Swnj 				break;
5824884Swnj 			}
5834899Swnj 			q = (struct tcpiphdr *)q->ti_next;
5844899Swnj 			m_freem(dtom(q->ti_prev));
5854899Swnj 			remque(q->ti_prev);
5864884Swnj 		}
5874601Swnj 
5884884Swnj 		/*
5894884Swnj 		 * Stick new segment in its place.
5904884Swnj 		 */
591*4924Swnj 		insque(ti, q->ti_prev);
592*4924Swnj 		tp->seqcnt += ti->ti_len;
5934884Swnj 
5944884Swnj 		/*
5954884Swnj 		 * Calculate available space and discard segments for
5964884Swnj 		 * which there is too much.
5974884Swnj 		 */
5984884Swnj 		overage =
5994884Swnj 		    (so->so_rcv.sb_cc /*XXX+tp->rcv_seqcnt*/) - so->so_rcv.sb_hiwat;
6004884Swnj 		if (overage > 0) {
6014884Swnj 			q = tp->seg_prev;
6024884Swnj 			for (;;) {
6034899Swnj 				register int i = MIN(q->ti_len, overage);
6044884Swnj 				overage -= i;
6054899Swnj 				q->ti_len -= i;
6064909Swnj 				m_adj(dtom(q), -i);
6074899Swnj 				if (q->ti_len)
6084884Swnj 					break;
609*4924Swnj 				if (q == ti)
6104884Swnj 					panic("tcp_text dropall");
6114899Swnj 				q = (struct tcpiphdr *)q->ti_prev;
6124899Swnj 				remque(q->ti_next);
6134884Swnj 			}
6144884Swnj 		}
6154884Swnj 
6164884Swnj 		/*
6174884Swnj 		 * Advance rcv_next through newly completed sequence space.
6184884Swnj 		 */
619*4924Swnj 		while (ti->ti_seq == tp->rcv_nxt) {
620*4924Swnj 			tp->rcv_nxt += ti->ti_len;
621*4924Swnj 			ti = (struct tcpiphdr *)ti->ti_next;
622*4924Swnj 			if (ti == (struct tcpiphdr *)tp)
6234645Swnj 				break;
6244645Swnj 		}
6254679Swnj /* urg */
626*4924Swnj 		if (tiflags&TH_URG) {
6274884Swnj 			/* ... */
6284884Swnj 			if (SEQ_GT(urgent, tp->rcv_urp))
6294803Swnj 				tp->rcv_urp = urgent;
6304679Swnj 		}
6314884Swnj 		tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
6324884Swnj 	}
6334884Swnj notext:
6344679Swnj /* fin */
635*4924Swnj 	if ((tiflags&TH_FIN) && past == tp->rcv_nxt) {
6364884Swnj 		if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
6374884Swnj 			tp->tc_flags |= TC_FIN_RCVD;
6384884Swnj 			sorwakeup(so);
6394884Swnj 			tp->rcv_nxt++;
6404803Swnj 		}
6414884Swnj 		tp->tc_flags |= TC_ACK_DUE;
6424679Swnj 	}
6434679Swnj /* respond */
6444679Swnj 	sent = 0;
6454679Swnj 	if (tp->tc_flags&TC_ACK_DUE)
6464679Swnj 		sent = tcp_sndctl(tp);
6474803Swnj 	else if ((tp->tc_flags&TC_NEW_WINDOW))
6484884Swnj 		if (tp->snd_nxt <= tp->snd_off + so->so_snd.sb_cc ||
6494803Swnj 		    (tp->tc_flags&TC_SND_FIN))
6504679Swnj 			sent = tcp_send(tp);
6514679Swnj 
6524679Swnj /* set for retrans */
6534679Swnj 	if (!sent && tp->snd_una < tp->snd_nxt &&
6544679Swnj 	    (tp->tc_flags&TC_CANCELLED)) {
6554679Swnj 		tp->t_rexmt = tp->t_xmtime;
6564679Swnj 		tp->t_rexmttl = T_REXMTTL;
6574679Swnj 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
6584679Swnj 		tp->tc_flags &= ~TC_CANCELLED;
6594679Swnj 	}
6604690Swnj /* present data to user */
6614656Swnj 	if ((tp->tc_flags&TC_SYN_ACKED) == 0)
6624601Swnj 		return;
663*4924Swnj 	ti = tp->seg_next;
664*4924Swnj 	while (ti != (struct tcpiphdr *)tp && ti->ti_seq < tp->rcv_nxt) {
665*4924Swnj 		remque(ti);
666*4924Swnj 		sbappend(&so->so_rcv, dtom(ti));
667*4924Swnj 		tp->seqcnt -= ti->ti_len;
6684884Swnj 		if (tp->seqcnt < 0)
6694884Swnj 			panic("tcp_input present");
670*4924Swnj 		ti = (struct tcpiphdr *)ti->ti_next;
6714601Swnj 	}
6724884Swnj 	sorwakeup(so);
6734601Swnj }
674