xref: /csrg-svn/sys/netinet/tcp_input.c (revision 5065)
1*5065Swnj /* tcp_input.c 1.30 81/11/24 */
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 
214953Swnj struct	sockaddr_in tcp_sockaddr = { AF_INET };
224953Swnj 
23*5065Swnj /*
24*5065Swnj  * TCP input routine, follows pages 65-76 of the
25*5065Swnj  * protocol specification dated September, 1981 very closely.
26*5065Swnj  */
274924Swnj tcp_input(m0)
284924Swnj 	struct mbuf *m0;
294601Swnj {
304924Swnj 	register struct tcpiphdr *ti;
314924Swnj 	struct inpcb *inp;
324924Swnj 	register struct mbuf *m;
334924Swnj 	int len, tlen, off;
344924Swnj 	register struct tcpcb *tp;
354924Swnj 	register int tiflags;
364803Swnj 	struct socket *so;
37*5065Swnj 	seq_t segend;
38*5065Swnj 	int acceptable;
394924Swnj 
404601Swnj COUNT(TCP_INPUT);
414924Swnj 	/*
424924Swnj 	 * Get ip and tcp header together in first mbuf.
434924Swnj 	 */
444924Swnj 	m = m0;
454924Swnj 	if (m->m_len < sizeof (struct tcpiphdr) &&
464924Swnj 	    m_pullup(m, sizeof (struct tcpiphdr)) == 0) {
474924Swnj 		tcpstat.tcps_hdrops++;
484924Swnj 		goto bad;
494924Swnj 	}
505020Sroot 	ti = mtod(m, struct tcpiphdr *);
515020Sroot 	if (ti->ti_len > sizeof (struct ip))
525020Sroot 		ip_stripoptions((struct ip *)ti, (char *)0);
534601Swnj 
544601Swnj 	/*
554924Swnj 	 * Checksum extended tcp header and data.
564601Swnj 	 */
574924Swnj 	tlen = ((struct ip *)ti)->ip_len;
584924Swnj 	len = sizeof (struct ip) + tlen;
594679Swnj 	if (tcpcksum) {
604924Swnj 		ti->ti_next = ti->ti_prev = 0;
614924Swnj 		ti->ti_x1 = 0;
624953Swnj 		ti->ti_len = htons((u_short)tlen);
635048Swnj 		if ((ti->ti_sum = inet_cksum(m, len)) != 0xffff) {
644924Swnj 			tcpstat.tcps_badsum++;
65*5065Swnj 			printf("tcp cksum %x\n", ti->ti_sum);
664924Swnj 			goto bad;
674601Swnj 		}
684601Swnj 	}
694601Swnj 
704601Swnj 	/*
714924Swnj 	 * Check that tcp offset makes sense,
724924Swnj 	 * process tcp options and adjust length.
734601Swnj 	 */
744924Swnj 	off = ti->ti_off << 2;
754924Swnj 	if (off < sizeof (struct tcphdr) || off > ti->ti_len) {
764924Swnj 		tcpstat.tcps_badoff++;
774924Swnj 		goto bad;
784924Swnj 	}
794924Swnj 	ti->ti_len = tlen - off;
804924Swnj 	/* PROCESS OPTIONS */
81*5065Swnj 	tiflags = ti->ti_flags;
824924Swnj 
834924Swnj 	/*
844924Swnj 	 * Locate pcb for segment.
854924Swnj 	 */
86*5065Swnj 	inp = in_pcblookup
87*5065Swnj 		(&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport);
88*5065Swnj 
89*5065Swnj 	/*
90*5065Swnj 	 * If the state is CLOSED (i.e., TCB does not exist) then
91*5065Swnj 	 * all data in the incoming segment is discarded.  (p. 65).
92*5065Swnj 	 */
934884Swnj 	if (inp == 0)
94*5065Swnj 		goto sendreset;
95*5065Swnj 	tp = intotcpcb(inp);
96*5065Swnj 	if (tp == 0)
97*5065Swnj 		goto sendreset;
984601Swnj 
994601Swnj 	/*
1004924Swnj 	 * Convert tcp protocol specific fields to host format.
1014601Swnj 	 */
1024924Swnj 	ti->ti_seq = ntohl(ti->ti_seq);
1034924Swnj 	ti->ti_ackno = ntohl((n_long)ti->ti_ackno);
1044924Swnj 	ti->ti_win = ntohs(ti->ti_win);
1054924Swnj 	ti->ti_urp = ntohs(ti->ti_urp);
1064601Swnj 
1074601Swnj 	/*
108*5065Swnj 	 * Discard ip header, and do tcp input processing.
1094601Swnj 	 */
110*5065Swnj 	off += sizeof (struct ip);
111*5065Swnj 	m->m_off += off;
112*5065Swnj 	m->m_len -= off;
113*5065Swnj 
1144601Swnj 	switch (tp->t_state) {
1154601Swnj 
116*5065Swnj 	/*
117*5065Swnj 	 * If the state is LISTEN then ignore segment if it contains an RST.
118*5065Swnj 	 * If the segment contains an ACK then it is bad and send a RST.
119*5065Swnj 	 * If it does not contain a SYN then it is not interesting; drop it.
120*5065Swnj 	 * Otherwise initialize tp->rcv_next, and tp->irs, select an initial
121*5065Swnj 	 * tp->iss, and send a segment:
122*5065Swnj 	 *     <SEQ=ISS><ACK=RCV>NXT><CTL=SYN,ACK>
123*5065Swnj 	 * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
124*5065Swnj 	 * Fill in remote peer address fields if not previously specified.
125*5065Swnj 	 * Enter SYN_RECEIVED state, and process any other fields of this
126*5065Swnj 	 * segment in this state.  (p. 65)
127*5065Swnj 	 */
128*5065Swnj 	case TCPS_LISTEN:
129*5065Swnj 		if (tiflags & TH_RST)
130*5065Swnj 			goto drop;
131*5065Swnj 		if (tiflags & TH_ACK)
132*5065Swnj 			goto sendrst;
133*5065Swnj 		if ((tiflags & TH_SYN) == 0)
134*5065Swnj 			goto drop;
135*5065Swnj 		tp->rcv_nxt = ti->ti_seq + 1;
136*5065Swnj 		tp->irs = ti->ti_seq;
137*5065Swnj 		tp->iss = tcp_selectiss();
138*5065Swnj 		tcp_reflect(ti, tp->iss, tp->rcv_next, TH_SYN|TH_ACK);
139*5065Swnj 		tp->t_state = TCPS_SYN_RECEIVED;
140*5065Swnj 		tiflags &= ~TH_SYN; tiflags |= TH_RST;
141*5065Swnj 		if (inp->inp_faddr.s_addr == 0) {
142*5065Swnj 			inp->inp_faddr = ti->ti_src;
143*5065Swnj 			inp->inp_fport = ti->ti_sport;
1444601Swnj 		}
145*5065Swnj 		break;
1464601Swnj 
147*5065Swnj 	/*
148*5065Swnj 	 * If the state is SYN_SENT:
149*5065Swnj 	 *	if seg contains an ACK, but not for our SYN, drop the input.
150*5065Swnj 	 *	if seg contains a RST, then drop the connection.
151*5065Swnj 	 *	if seg does not contain SYN, then drop it.
152*5065Swnj 	 * Otherwise this is an acceptable SYN segment
153*5065Swnj 	 *	initialize tp->rcv_nxt and tp->irs
154*5065Swnj 	 *	if seg contains ack then advance tp->snd_una
155*5065Swnj 	 *	if SYN has been acked change to ESTABLISHED else SYN_RCVD state
156*5065Swnj 	 *	arrange for segment to be acked (eventually)
157*5065Swnj 	 *	continue processing rest of data/controls, beginning with URG
158*5065Swnj 	 */
159*5065Swnj 	case TCPS_SYN_SENT:
160*5065Swnj 		if ((tiflags & TH_ACK) &&
161*5065Swnj 		    (SEQ_LEQ(ti->ti_ack, tp->iss) ||
162*5065Swnj 		     SEQ_GT(ti->ti_ack, tp->snd.nxt))) {
163*5065Swnj 			tcp_reflect(ti, ti->ti_ack, 0, TH_RST);
164*5065Swnj 			goto drop;
1654601Swnj 		}
166*5065Swnj 		if (tiflags & TH_RST) {
167*5065Swnj 			if (tiflags & TH_ACK)
168*5065Swnj 				tcp_drop(tp, ENETRESET);
169*5065Swnj 			goto drop;
1704601Swnj 		}
171*5065Swnj 		if ((tiflags & TH_SYN) == 0)
172*5065Swnj 			goto drop;
173*5065Swnj 		tp->rcv_nxt = ti->ti_seq + 1;
174*5065Swnj 		tp->irs = ti->ti_seq;
175*5065Swnj 		tp->snd_una = ti->ti_seq;
176*5065Swnj 		if (SEQ_GT(tp->snd_una, tp->iss)) {
177*5065Swnj 			tp->t_state = TCPS_ESTABLISHED;
178*5065Swnj 			tp->t_flags |= TF_OWEACK;
179*5065Swnj 			goto step6;
180*5065Swnj 		}
181*5065Swnj 		tp->t_state = TCPS_SYN_RECEIVED;
182*5065Swnj 		tcp_reflect(ti, tp->iss, tp->rcv_nxt, TH_SYN|TH_ACK);
183*5065Swnj 		break;
184*5065Swnj 	}
1854601Swnj 
186*5065Swnj 	/*
187*5065Swnj 	 * States other than LISTEN or SYN_SENT.
188*5065Swnj 	 * First check that at least some bytes of segment are within
189*5065Swnj 	 * receive window.
190*5065Swnj 	 */
191*5065Swnj 	if (tp->rcv_wnd == 0) {
192*5065Swnj 		/*
193*5065Swnj 		 * If window is closed can only take segments at
194*5065Swnj 		 * window edge, and have to drop data and EOL from
195*5065Swnj 		 * incoming segments.
196*5065Swnj 		 */
197*5065Swnj 		if (tp->rcv_nxt != ti->ti_seq)
198*5065Swnj 			goto dropafterack;
199*5065Swnj 		if (tp->ti_len > 0) {
200*5065Swnj 			tp->ti_len = 0;
201*5065Swnj 			tp->ti_flags &= ~(TH_EOL|TH_FIN);
202*5065Swnj 		}
203*5065Swnj 	} else {
204*5065Swnj 		/*
205*5065Swnj 		 * If segment begins before rcv_next, drop leading
206*5065Swnj 		 * data (and SYN); if nothing left, just ack.
207*5065Swnj 		 */
208*5065Swnj 		if (SEQ_GT(tp->rcv_nxt, ti->ti_seq)) {
209*5065Swnj 			tcpseq_t todrop = tp->rcv_nxt - ti->ti_seq;
210*5065Swnj 			if (todrop > ti->ti_len)
211*5065Swnj 				goto dropafterack;
212*5065Swnj 			m_adj(m, todrop);
213*5065Swnj 			ti->ti_seq += todrop;
214*5065Swnj 			ti->ti_len -= todrop;
215*5065Swnj 			ti->ti_flags &= ~TH_SYN;
216*5065Swnj 		}
217*5065Swnj 		/*
218*5065Swnj 		 * If segment ends after window, drop trailing data
219*5065Swnj 		 * (and EOL and FIN); if there would be nothing left, just ack.
220*5065Swnj 		 */
221*5065Swnj 		if (SEQ_GT(ti->ti_seq+ti->ti_len, tp->rcv_nxt+tp->rcv_wnd)) {
222*5065Swnj 			tcpseq_t todrop =
223*5065Swnj 			     ti->ti_seq+ti->ti_len - (tp->rcv_nxt+tp->rcv_wnd);
224*5065Swnj 			if (todrop > ti->ti_len)
225*5065Swnj 				goto dropafterack;
226*5065Swnj 			m_adj(m, -todrop);
227*5065Swnj 			ti->ti_len -= todrop;
228*5065Swnj 			ti->ti_flags &= ~(TH_EOL|TH_FIN);
229*5065Swnj 		}
230*5065Swnj 	}
2314601Swnj 
232*5065Swnj 	/*
233*5065Swnj 	 * If the RST bit is set examine the state:
234*5065Swnj 	 *    SYN_RECEIVED STATE:
235*5065Swnj 	 *	If passive open, return to LISTEN state.
236*5065Swnj 	 *	If active open, inform user that connection was refused.
237*5065Swnj 	 *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
238*5065Swnj 	 *	Inform user that connection was reset, and close tcb.
239*5065Swnj 	 *    CLOSING, LAST_ACK, TIME_WAIT STATES
240*5065Swnj 	 *	Close the tcb.
241*5065Swnj 	 */
242*5065Swnj 	if (tiflags&TH_RST) switch (tp->t_state) {
243*5065Swnj 
244*5065Swnj 	case TCPS_SYN_RECEIVED:
245*5065Swnj 		if (inp->inp_socket->so_options & SO_ACCEPTCONN) {
2464601Swnj 			tp->t_state = LISTEN;
247*5065Swnj 			inp->inp_fhost->s_addr = 0;
248*5065Swnj 			goto drop;
2494601Swnj 		}
250*5065Swnj 		tcp_drop(tp, EREFUSED);
251*5065Swnj 		goto drop;
2524601Swnj 
253*5065Swnj 	case TCPS_ESTABLISHED:
254*5065Swnj 	case TCPS_FIN_WAIT_1:
255*5065Swnj 	case TCPS_FIN_WAIT_2:
256*5065Swnj 	case TCPS_CLOSE_WAIT:
257*5065Swnj 		tcp_drop(tp, ECONNRESET);
258*5065Swnj 		goto drop;
259*5065Swnj 
260*5065Swnj 	case TCPS_CLOSING:
261*5065Swnj 	case TCPS_LAST_ACK:
262*5065Swnj 	case TCPS_TIME_WAIT:
263*5065Swnj 		tcp_close(tp);
264*5065Swnj 		goto drop;
2654601Swnj 	}
2664601Swnj 
2674601Swnj 	/*
268*5065Swnj 	 * If a SYN is in the window, then this is an
269*5065Swnj 	 * error and we send an RST and drop the connection.
2704601Swnj 	 */
271*5065Swnj 	if (tiflags & TH_SYN) {
272*5065Swnj 		tcp_drop(tp, ECONNRESET);
273*5065Swnj 		goto sendreset;
2744601Swnj 	}
2754601Swnj 
2764601Swnj 	/*
277*5065Swnj 	 * If the ACK bit is off we drop the segment and return.
2784601Swnj 	 */
279*5065Swnj 	if ((tiflags & TI_ACK) == 0)
280*5065Swnj 		goto drop;
281*5065Swnj 
282*5065Swnj 	/*
283*5065Swnj 	 * Ack processing.
284*5065Swnj 	 */
2854601Swnj 	switch (tp->t_state) {
2864601Swnj 
287*5065Swnj 	/*
288*5065Swnj 	 * In SYN_RECEIVED state if the ack ACKs our SYN then enter
289*5065Swnj 	 * ESTABLISHED state and continue processing, othewise
290*5065Swnj 	 * send an RST.
291*5065Swnj 	 */
292*5065Swnj 	case TCPS_SYN_RECEIVED:
293*5065Swnj 		if (SEQ_LEQ(tp->snd_una, ti->ti_ack) &&
294*5065Swnj 		    SEQ_LEQ(ti->ti_ack, tp->snd_nxt))
295*5065Swnj 			tp->t_state = TCPS_ESTABLISHED;
296*5065Swnj 		else
297*5065Swnj 			goto sendreset;
298*5065Swnj 		/* fall into next case, below... */
2994601Swnj 
300*5065Swnj 	/*
301*5065Swnj 	 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
302*5065Swnj 	 * ACKs.  If the ack is in the range
303*5065Swnj 	 *	tp->snd_una < ti->ti_ack <= tp->snd_nxt
304*5065Swnj 	 * then advance tp->snd_una to ti->ti_ack and drop
305*5065Swnj 	 * data from the retransmission queue.  If this ACK reflects
306*5065Swnj 	 * more up to date window information we update our window information.
307*5065Swnj 	 */
308*5065Swnj 	case TCPS_ESTABLISHED:
309*5065Swnj 	case TCPS_FIN_WAIT_1:
310*5065Swnj 	case TCPS_FIN_WAIT_2:
311*5065Swnj 	case TCPS_CLOSE_WAIT:
312*5065Swnj 	case TCPS_CLOSING:
313*5065Swnj 		if (SEQ_LT(ti->ti_ack, tp->snd_una))
314*5065Swnj 			break;
315*5065Swnj 		if (SEQ_GT(ti->ti_ack, tp->snd_nxt))
316*5065Swnj 			goto dropafterack;
317*5065Swnj 		sbdrop(&so->so_snd, ti->ti_ack - tp->snd_una);
318*5065Swnj 		tp->snd_una = ti->ti_ack;
319*5065Swnj 		if (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
320*5065Swnj 		    tp->snd_wl1==ti-ti_seq && SEQ_LEQ(tp->snd_wl2,ti->ti_seq)) {
321*5065Swnj 			tp->snd_wnd = ti->ti_win;
322*5065Swnj 			tp->snd_wl1 = ti->ti_seq;
323*5065Swnj 			tp->snd_wl2 = ti->ti_ack;
3244601Swnj 		}
3254601Swnj 
3264601Swnj 		switch (tp->t_state) {
3274601Swnj 
328*5065Swnj 		/*
329*5065Swnj 		 * In FIN_WAIT_1 STATE in addition to the processing
330*5065Swnj 		 * for the ESTABLISHED state if our FIN is now acknowledged
331*5065Swnj 		 * then enter FIN_WAIT_2 and continue processing in that state.
332*5065Swnj 		 */
333*5065Swnj 		case TCPS_FIN_WAIT_1:
334*5065Swnj 			if (tcp_finisacked(tp) == 0)
335*5065Swnj 				break;
336*5065Swnj 			tp->t_state = TCPS_FIN_WAIT_2;
337*5065Swnj 			/* fall into ... */
3384601Swnj 
339*5065Swnj 	 	/*
340*5065Swnj 		 * In FIN_WAIT_2 STATE in addition to the processing for
341*5065Swnj 		 * the ESTABLISHED state allow the user to close when
342*5065Swnj 		 * the data has drained.
343*5065Swnj 		 */
344*5065Swnj 		case TCPS_FIN_WAIT_2:
345*5065Swnj 			tcp_usrcanclose(tp);
3464601Swnj 			break;
3474601Swnj 
348*5065Swnj 	 	/*
349*5065Swnj 		 * In CLOSING STATE in addition to the processing for
350*5065Swnj 		 * the ESTABLISHED state if the ACK acknowledges our FIN
351*5065Swnj 		 * then enter the TIME-WAIT state, otherwise ignore
352*5065Swnj 		 * the segment.
353*5065Swnj 		 */
354*5065Swnj 		case TCPS_CLOSING:
355*5065Swnj 			if (tcp_finisacked(tp))
356*5065Swnj 				tp->t_state = TCPS_TIME_WAIT;
3574601Swnj 			break;
3584601Swnj 
359*5065Swnj 		/*
360*5065Swnj 		 * In LAST_ACK state if our FIN is now acknowledged
361*5065Swnj 		 * then enter the TIME_WAIT state, otherwise ignore the
362*5065Swnj 		 * segment.
363*5065Swnj 		 */
364*5065Swnj 		case TCPS_LAST_ACK:
365*5065Swnj 			if (tcp_finisacked(tp))
366*5065Swnj 				tcp_close(tp);
367*5065Swnj 			goto drop;
3684601Swnj 
369*5065Swnj 		/*
370*5065Swnj 		 * In TIME_WAIT state the only thing that should arrive
371*5065Swnj 		 * is a retransmission of the remote FIN.  Acknowledge
372*5065Swnj 		 * it and restart the finack timer.
373*5065Swnj 		 */
374*5065Swnj 		case TCPS_TIME_WAIT:
375*5065Swnj 			tp->t_finack = 2 * TCP_MSL;
376*5065Swnj 			goto dropafterack;
3774601Swnj 		}
3784601Swnj 
379*5065Swnj step6:
380*5065Swnj 	/*
381*5065Swnj 	 * If an URG bit is set in the segment and is greater than the
382*5065Swnj 	 * current known urgent pointer, then signal the user that the
383*5065Swnj 	 * remote side has urgent data.  This should not happen
384*5065Swnj 	 * in CLOSE_WAIT, CLOSING, LAST-ACK or TIME_WAIT STATES since
385*5065Swnj 	 * a FIN has been received from the remote side.  In these states
386*5065Swnj 	 * we ignore the URG.
387*5065Swnj 	 */
388*5065Swnj 	if ((tiflags & TH_URG) == 0 && (TCPS_RCVDFIN(tp->t_state) == 0) {
389*5065Swnj 		if (SEQ_GT(ti->ti_urp, tp->rcv_up) {
390*5065Swnj 			tp->rcv_up = ti->ti_urp;
391*5065Swnj 			soisurgendata(so);		/* XXX */
3924601Swnj 		}
3934601Swnj 	}
3944601Swnj 
3954601Swnj 	/*
396*5065Swnj 	 * Process the segment text, merging it into the TCP sequencing queue,
397*5065Swnj 	 * and arranging for acknowledgment of receipt if necessary.
398*5065Swnj 	 * This process logically involves adjusting tp->rcv_wnd as data
399*5065Swnj 	 * is presented to the user (this happens in tcp_usrreq.c,
400*5065Swnj 	 * case PRU_RCVD).  If a FIN has already been received on this
401*5065Swnj 	 * connection then we just ignore the text.
4024601Swnj 	 */
403*5065Swnj 	if (ti->ti_len) {
404*5065Swnj 		if (TCPS_RCVDFIN(tp->t_state))
405*5065Swnj 			goto drop;
406*5065Swnj 		tiflags = tcp_reass(tp, ti);
407*5065Swnj 	else
4084924Swnj 		m_freem(m);
4094601Swnj 
4104601Swnj 	/*
411*5065Swnj 	 * If FIN is received then if we haven't received SYN and
412*5065Swnj 	 * therefore can't validate drop the segment.  Otherwise ACK
413*5065Swnj 	 * the FIN and let the user know that the connection is closing.
4144601Swnj 	 */
415*5065Swnj 	if ((tiflags & TH_FIN) && TCPS_HAVERCVDSYN(tp->t_state)) {
416*5065Swnj 		tcp_usrclosing(tp);
417*5065Swnj 		tp->t_flags |= TF_ACKNOW;
418*5065Swnj 		tp->rcv_nxt++;
419*5065Swnj 		switch (tp->t_state) {
4204601Swnj 
421*5065Swnj 	 	/*
422*5065Swnj 		 * In SYN_RECEIVED and ESTABLISHED STATES
423*5065Swnj 		 * enter the CLOSE_WAIT state.
4244884Swnj 		 */
425*5065Swnj 		case TCPS_SYN_RECEIVED:
426*5065Swnj 		case TCPS_ESTABLISHED:
427*5065Swnj 			tp->t_state = TCPS_CLOSE_WAIT;
428*5065Swnj 			break;
4294884Swnj 
430*5065Swnj 	 	/*
431*5065Swnj 		 * In FIN_WAIT_1 STATE if our FIN has been acked then
432*5065Swnj 		 * enter TIME_WAIT state, starting the associated timer
433*5065Swnj 		 * and turning off all other standard timers.
434*5065Swnj 	 	 * If FIN has not been acked enter the CLOSING state.
4354884Swnj 		 */
436*5065Swnj 		case TCPS_FIN_WAIT_1:
437*5065Swnj 			if (tcp_finisacked(tp)) {
438*5065Swnj 				tp->t_state = TCPS_TIME_WAIT;
439*5065Swnj 				tcp_canceltimers(tp, 0);
440*5065Swnj 				tp->t_timer[TCPT_FINACK] = TCPSC_2MSL;
441*5065Swnj 			} else
442*5065Swnj 				tp->t_state = TCPS_CLOSING;
443*5065Swnj 			break;
4444601Swnj 		}
4454601Swnj 
446*5065Swnj 	 	/*
447*5065Swnj 		 * In FIN_WAIT_2 state enter the TIME_WAIT state,
448*5065Swnj 		 * starting the time-wait timer, turning off the other
449*5065Swnj 		 * standard timers.
450*5065Swnj 		 */
451*5065Swnj 		case TCPS_FIN_WAIT_2:
452*5065Swnj 			tp->t_state = TCPS_FIN_WAIT_2;
453*5065Swnj 			tcp_canceltimers(tp, 0);
454*5065Swnj 			tp->t_timer[TCPT_FINACK] = TCPSC_2MSL;
455*5065Swnj 			break;
456*5065Swnj 
4574884Swnj 		/*
458*5065Swnj 		 * In TIME_WAIT state restart the 2 MSL time_wait timer.
4594884Swnj 		 */
460*5065Swnj 		case TCPS_TIME_WAIT:
461*5065Swnj 			tp->t_timer[TCPT_FINACK] = TCPSC_2MSL;
462*5065Swnj 			break;
4634601Swnj 	}
464*5065Swnj 	return;
465*5065Swnj dropafterack:
466*5065Swnj 	if ((tiflags & TH_RST) == 0)
467*5065Swnj 		tcp_reflect(ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
468*5065Swnj drop:
469*5065Swnj 	m_freem(m);
470*5065Swnj 	return;
471*5065Swnj }
472*5065Swnj 
473*5065Swnj /*
474*5065Swnj  * Insert segment ti into reassembly queue of tcp with
475*5065Swnj  * control block tp.  Return TH_FIN if reassembly now includes
476*5065Swnj  * a segment with FIN.
477*5065Swnj  */
478*5065Swnj tcp_reass(tp, ti, endp)
479*5065Swnj 	register struct tcpcb *tp;
480*5065Swnj 	register struct tcpiphdr *ti;
481*5065Swnj 	int *endp;
482*5065Swnj {
483*5065Swnj 	register struct tcpiphdr *q;
484*5065Swnj 	int flags = 0;		/* no FIN */
485*5065Swnj 	int overage;
486*5065Swnj 
487*5065Swnj 	/*
488*5065Swnj 	 * If no data in this segment may want
489*5065Swnj 	 * to move data up to socket structure (if
490*5065Swnj 	 * connection is now established).
491*5065Swnj 	 */
492*5065Swnj 	if (ti->ti_len == 0) {
493*5065Swnj 		m_freem(dtom(ti));
494*5065Swnj 		goto present;
4954601Swnj 	}
4964601Swnj 
497*5065Swnj 	/*
498*5065Swnj 	 * Find a segment which begins after this one does.
499*5065Swnj 	 */
500*5065Swnj 	for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
501*5065Swnj 	    q = (struct tcpiphdr *)q->ti_next)
502*5065Swnj 		if (SEQ_GT(q->ti_seq, ti->ti_seq))
503*5065Swnj 			break;
5044601Swnj 
505*5065Swnj 	/*
506*5065Swnj 	 * If there is a preceding segment, it may provide some of
507*5065Swnj 	 * our data already.  If so, drop the data from the incoming
508*5065Swnj 	 * segment.  If it provides all of our data, drop us.
509*5065Swnj 	 */
510*5065Swnj 	if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
511*5065Swnj 		register int i;
512*5065Swnj 		q = (struct tcpiphdr *)(q->ti_prev);
513*5065Swnj 		/* conversion to int (in i) handles seq wraparound */
514*5065Swnj 		i = q->ti_seq + q->ti_len - ti->ti_seq;
515*5065Swnj 		if (i > 0) {
5164924Swnj 			if (i >= ti->ti_len)
517*5065Swnj 				goto drop;
518*5065Swnj 			m_adj(dtom(tp), i);
519*5065Swnj 			ti->ti_len -= i;
5204924Swnj 			ti->ti_seq += i;
5214601Swnj 		}
522*5065Swnj 		q = (struct tcpiphdr *)(q->ti_next);
523*5065Swnj 	}
5244601Swnj 
525*5065Swnj 	/*
526*5065Swnj 	 * While we overlap succeeding segments trim them or,
527*5065Swnj 	 * if they are completely covered, dequeue them.
528*5065Swnj 	 */
529*5065Swnj 	while (q != (struct tcpiphdr *)tp &&
530*5065Swnj 	    SEQ_GT(ti->ti_seq + ti->ti_len, q->ti_seq)) {
531*5065Swnj 		register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
532*5065Swnj 		if (i < q->ti_len) {
533*5065Swnj 			q->ti_len -= i;
534*5065Swnj 			m_adj(dtom(q), i);
535*5065Swnj 			break;
5364601Swnj 		}
537*5065Swnj 		q = (struct tcpiphdr *)q->ti_next;
538*5065Swnj 		m_freem(dtom(q->ti_prev));
539*5065Swnj 		remque(q->ti_prev);
540*5065Swnj 	}
5414601Swnj 
542*5065Swnj 	/*
543*5065Swnj 	 * Stick new segment in its place.
544*5065Swnj 	 */
545*5065Swnj 	insque(ti, q->ti_prev);
546*5065Swnj 	tp->seqcnt += ti->ti_len;
5474601Swnj 
548*5065Swnj 	/*
549*5065Swnj 	 * Calculate available space and discard segments for
550*5065Swnj 	 * which there is too much.
551*5065Swnj 	 */
552*5065Swnj 	overage =
553*5065Swnj 	    (so->so_rcv.sb_cc + tp->seqcnt) - so->so_rcv.sb_hiwat;
554*5065Swnj 	if (overage > 0) {
555*5065Swnj 		q = tp->seg_prev;
556*5065Swnj 		for (;;) {
557*5065Swnj 			register int i = MIN(q->ti_len, overage);
558*5065Swnj 			overage -= i;
559*5065Swnj 			tp->seqcnt -= i;
560*5065Swnj 			q->ti_len -= i;
561*5065Swnj 			m_adj(dtom(q), -i);
562*5065Swnj 			if (q->ti_len)
5634645Swnj 				break;
564*5065Swnj 			if (q == ti)
565*5065Swnj 				panic("tcp_text dropall");
566*5065Swnj 			q = (struct tcpiphdr *)q->ti_prev;
567*5065Swnj 			remque(q->ti_next);
5684645Swnj 		}
5694884Swnj 	}
570*5065Swnj 
571*5065Swnj 	/*
572*5065Swnj 	 * Advance rcv_next through newly completed sequence space.
573*5065Swnj 	 */
574*5065Swnj 	while (ti->ti_seq == tp->rcv_nxt) {
575*5065Swnj 		tp->rcv_nxt += ti->ti_len;
576*5065Swnj 		flags = ti->ti_flags & TH_FIN;
577*5065Swnj 		ti = (struct tcpiphdr *)ti->ti_next;
578*5065Swnj 		if (ti == (struct tcpiphdr *)tp)
579*5065Swnj 			break;
5804679Swnj 	}
5814679Swnj 
582*5065Swnj present:
583*5065Swnj 	/*
584*5065Swnj 	 * Present data to user.
585*5065Swnj 	 */
586*5065Swnj 	if (tp->t_state < ESTAB)
587*5065Swnj 		return (flags);
5884924Swnj 	ti = tp->seg_next;
5894924Swnj 	while (ti != (struct tcpiphdr *)tp && ti->ti_seq < tp->rcv_nxt) {
5904924Swnj 		remque(ti);
5914924Swnj 		sbappend(&so->so_rcv, dtom(ti));
5924924Swnj 		tp->seqcnt -= ti->ti_len;
5934884Swnj 		if (tp->seqcnt < 0)
594*5065Swnj 			panic("tcp_reass");
5954924Swnj 		ti = (struct tcpiphdr *)ti->ti_next;
5964601Swnj 	}
5974884Swnj 	sorwakeup(so);
598*5065Swnj 	return (flags);
599*5065Swnj drop:
600*5065Swnj 	m_freem(dtom(ti));
601*5065Swnj 	return (flags);
6024601Swnj }
603