xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4601)
1*4601Swnj /* tcp_input.c 1.1 81/10/24 */
2*4601Swnj 
3*4601Swnj #include "../h/param.h"
4*4601Swnj #include "../h/systm.h"
5*4601Swnj #include "../bbnnet/net.h"
6*4601Swnj #include "../bbnnet/mbuf.h"
7*4601Swnj #include "../bbnnet/host.h"
8*4601Swnj #include "../bbnnet/imp.h"
9*4601Swnj #include "../bbnnet/ucb.h"
10*4601Swnj #include "../bbnnet/tcp.h"
11*4601Swnj #include "../bbnnet/ip.h"
12*4601Swnj #include "../h/dir.h"
13*4601Swnj #include "../h/user.h"
14*4601Swnj #include "../h/inode.h"
15*4601Swnj #include "../bbnnet/fsm.h"
16*4601Swnj 
17*4601Swnj extern int nosum;
18*4601Swnj 
19*4601Swnj tcp_input(mp)
20*4601Swnj 	register struct mbuf *mp;
21*4601Swnj {
22*4601Swnj 	register struct tcb *tp;
23*4601Swnj 	register struct th *n;
24*4601Swnj 	int nstate;
25*4601Swnj 	struct mbuf *m;
26*4601Swnj 	struct ucb *up;
27*4601Swnj 	int hlen, tlen, j;
28*4601Swnj 	u_short lport, fport;
29*4601Swnj #ifdef TCPDEBUG
30*4601Swnj 	struct tcp_debug tdb;
31*4601Swnj #endif
32*4601Swnj COUNT(TCP_INPUT);
33*4601Swnj 
34*4601Swnj 	/*
35*4601Swnj 	 * Build extended tcp header
36*4601Swnj 	 */
37*4601Swnj 	n = (struct th *)((int)mp + mp->m_off);
38*4601Swnj 	tlen = ((struct ip *)n)->ip_len;
39*4601Swnj 	n->t_len = htons(tlen);
40*4601Swnj 	n->t_next = NULL;
41*4601Swnj 	n->t_prev = NULL;
42*4601Swnj 	n->t_x1 = 0;
43*4601Swnj 	lport = ntohs(n->t_dst);
44*4601Swnj 	fport = ntohs(n->t_src);
45*4601Swnj 
46*4601Swnj 	/* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */
47*4601Swnj 	if ((hlen = n->t_off << 2) > mp->m_len)
48*4601Swnj 		{ printf("tcp header overflow\n"); m_freem(mp); return; }
49*4601Swnj 
50*4601Swnj 	/*
51*4601Swnj 	 * Checksum extended header and data
52*4601Swnj 	 */
53*4601Swnj 	j = n->t_sum; n->t_sum = 0;
54*4601Swnj 	if (j != cksum(mp, sizeof (struct ip) + tlen)) {
55*4601Swnj 		netstat.t_badsum++;
56*4601Swnj 		if (nosum == 0) {
57*4601Swnj 			m_freem(mp);
58*4601Swnj 			return;
59*4601Swnj 		}
60*4601Swnj 	}
61*4601Swnj 
62*4601Swnj 	/*
63*4601Swnj 	 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!)
64*4601Swnj 	 */
65*4601Swnj 	for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next)
66*4601Swnj 		if (tp->t_lport == lport && tp->t_fport == fport &&
67*4601Swnj 		    tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr)
68*4601Swnj 			goto found;
69*4601Swnj 	for (tp = netcb.n_tcb_head; tp != 0; tp = tp->t_tcb_next)
70*4601Swnj 		if (tp->t_lport == lport &&
71*4601Swnj 		    (tp->t_fport==fport || tp->t_fport==0) &&
72*4601Swnj 		    (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr ||
73*4601Swnj 		     tp->t_ucb->uc_host->h_addr.s_addr == 0))
74*4601Swnj 			goto found;
75*4601Swnj 	goto notwanted;
76*4601Swnj found:
77*4601Swnj 
78*4601Swnj 	/*
79*4601Swnj 	 * Byte swap header
80*4601Swnj 	 */
81*4601Swnj 	n->t_len = tlen - hlen;
82*4601Swnj 	n->t_src = fport;
83*4601Swnj 	n->t_dst = lport;
84*4601Swnj 	n->t_seq = ntohl(n->t_seq);
85*4601Swnj 	n->t_ackno = ntohl(n->t_ackno);
86*4601Swnj 	n->t_win = ntohs(n->t_win);
87*4601Swnj 	n->t_urp = ntohs(n->t_urp);
88*4601Swnj 
89*4601Swnj 	/*
90*4601Swnj 	 * Check segment seq # and do rst processing
91*4601Swnj 	 */
92*4601Swnj 	switch (tp->t_state) {
93*4601Swnj 
94*4601Swnj 	case LISTEN:
95*4601Swnj 		if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) {
96*4601Swnj 			send_rst(tp, n);
97*4601Swnj 			goto badseg;
98*4601Swnj 		}
99*4601Swnj 		if (n->th_flags&TH_RST)
100*4601Swnj 			goto badseg;
101*4601Swnj 		goto goodseg;
102*4601Swnj 
103*4601Swnj 	case SYN_SENT:
104*4601Swnj 		if (!ack_ok(tp, n) || !syn_ok(tp, n)) {
105*4601Swnj 			send_rst(tp, n);			/* 71,72,75 */
106*4601Swnj 			goto badseg;
107*4601Swnj 		}
108*4601Swnj 		if (n->th_flags&TH_RST) {
109*4601Swnj 			t_close(tp, URESET);			/* 70 */
110*4601Swnj 			tp->t_state = CLOSED;
111*4601Swnj 			goto badseg;
112*4601Swnj 		}
113*4601Swnj 		goto goodseg;
114*4601Swnj 
115*4601Swnj 	default:
116*4601Swnj         	if ((n->th_flags&TH_RST) == 0)
117*4601Swnj 			goto common;
118*4601Swnj 		if (n->t_seq < tp->rcv_nxt)		/* bad rst */
119*4601Swnj 			goto badseg;				/* 69 */
120*4601Swnj 		switch (tp->t_state) {
121*4601Swnj 
122*4601Swnj 		case L_SYN_RCVD:
123*4601Swnj 			if (ack_ok(tp, n) == 0)
124*4601Swnj 				goto badseg;			/* 69 */
125*4601Swnj 			tp->t_rexmt = 0;
126*4601Swnj 			tp->t_rexmttl = 0;
127*4601Swnj 			tp->t_persist = 0;
128*4601Swnj 			h_free(tp->t_ucb->uc_host);
129*4601Swnj 			tp->t_state = LISTEN;
130*4601Swnj 			goto badseg;
131*4601Swnj 
132*4601Swnj 		default:
133*4601Swnj 			t_close(tp, URESET);			/* 66 */
134*4601Swnj 			tp->t_state = CLOSED;
135*4601Swnj 			goto badseg;
136*4601Swnj 		}
137*4601Swnj 		/*NOTREACHED*/
138*4601Swnj 
139*4601Swnj 	case SYN_RCVD:
140*4601Swnj common:
141*4601Swnj 		if (ack_ok(tp, n) == 0) {
142*4601Swnj 			send_rst(tp, n);			/* 74 */
143*4601Swnj 			goto badseg;
144*4601Swnj 		}
145*4601Swnj 		if (syn_ok(tp, n) && n->t_seq != tp->irs) {
146*4601Swnj 			send_null(tp);				/* 74 */
147*4601Swnj 			goto badseg;
148*4601Swnj 		}
149*4601Swnj 		goto goodseg;
150*4601Swnj 	}
151*4601Swnj badseg:
152*4601Swnj 	m_freem(mp);
153*4601Swnj 	return;
154*4601Swnj 
155*4601Swnj goodseg:
156*4601Swnj #ifdef notdef
157*4601Swnj 	/*
158*4601Swnj 	 * Defer processing if no buffer space for this connection.
159*4601Swnj 	 */
160*4601Swnj 	up = tp->t_ucb;
161*4601Swnj 	if ((int)up->uc_rcv - (int)up->uc_rsize <= 0
162*4601Swnj 	     && n->t_len != 0 && netcb.n_bufs < netcb.n_lowat) {
163*4601Swnj 		mp->m_act = (struct mbuf *)0;
164*4601Swnj 		if ((m = tp->t_rcv_unack) != NULL) {
165*4601Swnj 			while (m->m_act != NULL)
166*4601Swnj 				m = m->m_act;
167*4601Swnj 			m->m_act = mp;
168*4601Swnj 		} else
169*4601Swnj 			tp->t_rcv_unack = mp;
170*4601Swnj 
171*4601Swnj 		return;
172*4601Swnj 	}
173*4601Swnj #endif
174*4601Swnj 
175*4601Swnj 	/*
176*4601Swnj 	 * Discard ip header, and do tcp input processing.
177*4601Swnj 	 */
178*4601Swnj 	hlen += sizeof(struct ip);
179*4601Swnj 	mp->m_off += hlen;
180*4601Swnj 	mp->m_len -= hlen;
181*4601Swnj 	nstate = tp->t_state;
182*4601Swnj 	tp->tc_flags &= ~TC_NET_KEEP;
183*4601Swnj 	acounts[tp->t_state][INRECV]++;
184*4601Swnj #ifdef TCPDEBUG
185*4601Swnj 	if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) {
186*4601Swnj 		tdb.td_tod = time;
187*4601Swnj 		tdb.td_tcb = tp;
188*4601Swnj 		tdb.td_old = nstate;
189*4601Swnj 		tdb.td_inp = INRECV;
190*4601Swnj 		tdb.td_tim = 0;
191*4601Swnj 		tdb.td_sno = n->t_seq;
192*4601Swnj 		tdb.td_ano = n->t_ackno;
193*4601Swnj 		tdb.td_wno = n->t_win;
194*4601Swnj 		tdb.td_lno = n->t_len;
195*4601Swnj 		tdb.td_flg = n->th_flags;
196*4601Swnj 	} else
197*4601Swnj 		tdb.td_tod = 0;
198*4601Swnj #endif
199*4601Swnj 	switch (tp->t_state) {
200*4601Swnj 
201*4601Swnj 	case LISTEN:
202*4601Swnj 		if (!syn_ok(tp, n) ||
203*4601Swnj 		    ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) {
204*4601Swnj 			nstate = EFAILEC;
205*4601Swnj 			goto done;
206*4601Swnj 		}
207*4601Swnj 		tp->t_fport = n->t_src;
208*4601Swnj 		rcv_ctldat(tp, n, 1);
209*4601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
210*4601Swnj 			tp->t_finack = T_2ML;			/* 3 */
211*4601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
212*4601Swnj 			nstate = CLOSE_WAIT;
213*4601Swnj 		} else {
214*4601Swnj 			tp->t_init = T_INIT / 2;		/* 4 */
215*4601Swnj 			nstate = L_SYN_RCVD;
216*4601Swnj 		}
217*4601Swnj 		goto done;
218*4601Swnj 
219*4601Swnj 	case SYN_SENT:
220*4601Swnj 		if (!syn_ok(tp, n)) {
221*4601Swnj 			nstate = EFAILEC;
222*4601Swnj 			goto done;
223*4601Swnj 		}
224*4601Swnj 		rcv_ctldat(tp, n, 1);
225*4601Swnj 		if (tp->tc_flags&TC_FIN_RCVD) {
226*4601Swnj 			if (n->th_flags&TH_ACK) {
227*4601Swnj 				if (n->t_ackno > tp->iss)
228*4601Swnj 					present_data(tp);	/* 32 */
229*4601Swnj 			} else {
230*4601Swnj 				tp->t_finack = T_2ML;		/* 9 */
231*4601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
232*4601Swnj 			}
233*4601Swnj 			nstate = CLOSE_WAIT;
234*4601Swnj 			goto done;
235*4601Swnj 		}
236*4601Swnj 		if (n->th_flags&TH_ACK) {
237*4601Swnj 			present_data(tp);			/* 11 */
238*4601Swnj 			nstate = ESTAB;
239*4601Swnj 		} else
240*4601Swnj 			nstate = SYN_RCVD;			/* 8 */
241*4601Swnj 		goto done;
242*4601Swnj 
243*4601Swnj 	case SYN_RCVD:
244*4601Swnj 	case L_SYN_RCVD:
245*4601Swnj 		if ((n->th_flags&TH_ACK) == 0 ||
246*4601Swnj 		    (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) {
247*4601Swnj 			nstate = EFAILEC;
248*4601Swnj 			goto done;
249*4601Swnj 		}
250*4601Swnj 		goto input;
251*4601Swnj 
252*4601Swnj 	case ESTAB:
253*4601Swnj 	case FIN_W1:
254*4601Swnj 	case FIN_W2:
255*4601Swnj 	case TIME_WAIT:
256*4601Swnj input:
257*4601Swnj 		rcv_ctldat(tp, n, 1);				/* 39 */
258*4601Swnj 		present_data(tp);
259*4601Swnj 		switch (tp->t_state) {
260*4601Swnj 
261*4601Swnj 		case ESTAB:
262*4601Swnj 			if (tp->tc_flags&TC_FIN_RCVD)
263*4601Swnj 				nstate = CLOSE_WAIT;
264*4601Swnj 			break;
265*4601Swnj 
266*4601Swnj 		case SYN_RCVD:
267*4601Swnj 		case L_SYN_RCVD:
268*4601Swnj 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
269*4601Swnj 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
270*4601Swnj 			break;
271*4601Swnj 
272*4601Swnj 		case FIN_W1:
273*4601Swnj 			j = ack_fin(tp, n);
274*4601Swnj 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
275*4601Swnj 				if (j)
276*4601Swnj 					nstate = FIN_W2;	/* 27 */
277*4601Swnj 				break;
278*4601Swnj 			}
279*4601Swnj 			tp->t_finack = T_2ML;
280*4601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
281*4601Swnj 			nstate = j ? TIME_WAIT : CLOSING1;	/* 28:26 */
282*4601Swnj 			break;
283*4601Swnj 
284*4601Swnj 		case FIN_W2:
285*4601Swnj 			if (tp->tc_flags&TC_FIN_RCVD) {
286*4601Swnj 				tp->t_finack = T_2ML;		/* 29 */
287*4601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
288*4601Swnj 				nstate = TIME_WAIT;
289*4601Swnj 				break;
290*4601Swnj 			}
291*4601Swnj 			break;
292*4601Swnj 		}
293*4601Swnj 		goto done;
294*4601Swnj 
295*4601Swnj 	case CLOSE_WAIT:
296*4601Swnj 		if (n->th_flags&TH_FIN) {
297*4601Swnj 			if ((n->th_flags&TH_ACK) &&
298*4601Swnj 			    n->t_ackno <= tp->seq_fin) {
299*4601Swnj 				rcv_ctldat(tp, n, 0);		/* 30 */
300*4601Swnj 				tp->t_finack = T_2ML;
301*4601Swnj 				tp->tc_flags &= ~TC_WAITED_2_ML;
302*4601Swnj 			} else
303*4601Swnj 				send_ctl(tp);			/* 31 */
304*4601Swnj 			goto done;
305*4601Swnj 		}
306*4601Swnj 		goto input;
307*4601Swnj 
308*4601Swnj 	case CLOSING1:
309*4601Swnj 		j = ack_fin(tp, n);
310*4601Swnj 		if (n->th_flags&TH_FIN) {
311*4601Swnj 			rcv_ctldat(tp, n, 0);
312*4601Swnj 			tp->t_finack = T_2ML;
313*4601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;
314*4601Swnj 			if (j)
315*4601Swnj 				nstate = TIME_WAIT;		/* 23 */
316*4601Swnj 			goto done;
317*4601Swnj 		}
318*4601Swnj 		if (j) {
319*4601Swnj 			if (tp->tc_flags&TC_WAITED_2_ML)
320*4601Swnj 				if (rcv_empty(tp)) {
321*4601Swnj 					t_close(tp, UCLOSED);	/* 15 */
322*4601Swnj 					nstate = CLOSED;
323*4601Swnj 				} else
324*4601Swnj 					nstate = RCV_WAIT;	/* 18 */
325*4601Swnj 			else
326*4601Swnj 				nstate = TIME_WAIT;
327*4601Swnj 			goto done;
328*4601Swnj 		}
329*4601Swnj 		goto input;
330*4601Swnj 
331*4601Swnj 	case CLOSING2:
332*4601Swnj 		if (ack_fin(tp, n)) {
333*4601Swnj 			if (rcv_empty(tp)) {			/* 16 */
334*4601Swnj 				t_close(tp, UCLOSED);
335*4601Swnj 				nstate = CLOSED;
336*4601Swnj 			} else
337*4601Swnj 				nstate = RCV_WAIT;		/* 19 */
338*4601Swnj 			goto done;
339*4601Swnj 		}
340*4601Swnj 		if (n->th_flags&TH_FIN) {
341*4601Swnj 			send_ctl(tp);				/* 31 */
342*4601Swnj 			goto done;
343*4601Swnj 		}
344*4601Swnj 		goto input;
345*4601Swnj 
346*4601Swnj 	case RCV_WAIT:
347*4601Swnj 		if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) &&
348*4601Swnj 		    n->t_ackno <= tp->seq_fin) {
349*4601Swnj 			rcv_ctldat(tp, n, 0);
350*4601Swnj 			tp->t_finack = T_2ML;
351*4601Swnj 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
352*4601Swnj 		}
353*4601Swnj 		goto done;
354*4601Swnj 	}
355*4601Swnj 	panic("tcp_input");
356*4601Swnj done:
357*4601Swnj 
358*4601Swnj 	/*
359*4601Swnj 	 * Done with state*input specific processing.
360*4601Swnj 	 * Form trace records, free input if not needed,
361*4601Swnj 	 * and enter new state.
362*4601Swnj 	 */
363*4601Swnj #ifdef TCPDEBUG
364*4601Swnj 	if (tdb.td_tod) {
365*4601Swnj 		tdb.td_new = nstate;
366*4601Swnj 		tcp_debug[tdbx++ % TDBSIZE] = tdb;
367*4601Swnj 		if (tcpconsdebug)
368*4601Swnj 			tcp_prt(&tdb);
369*4601Swnj 	}
370*4601Swnj #endif
371*4601Swnj 	switch (nstate) {
372*4601Swnj 
373*4601Swnj 	case EFAILEC:
374*4601Swnj 		m_freem(mp);
375*4601Swnj 		return;
376*4601Swnj 
377*4601Swnj 	default:
378*4601Swnj 		tp->t_state = nstate;
379*4601Swnj 		/* fall into ... */
380*4601Swnj 
381*4601Swnj 	case CLOSED:
382*4601Swnj 		/* IF CLOSED CANT LOOK AT tc_flags */
383*4601Swnj 		if ((tp->tc_flags&TC_NET_KEEP) == 0)
384*4601Swnj 			m_freem(mp);
385*4601Swnj 		return;
386*4601Swnj 	}
387*4601Swnj 	/* NOTREACHED */
388*4601Swnj 
389*4601Swnj 	/*
390*4601Swnj 	 * Unwanted packed; free everything
391*4601Swnj 	 * but the header and return an rst.
392*4601Swnj 	 */
393*4601Swnj notwanted:
394*4601Swnj 	m_freem(mp->m_next);
395*4601Swnj 	mp->m_next = NULL;
396*4601Swnj 	mp->m_len = sizeof(struct th);
397*4601Swnj #define xchg(a,b) j=a; a=b; b=j
398*4601Swnj 	xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
399*4601Swnj #undef xchg
400*4601Swnj 	if (n->th_flags&TH_ACK)
401*4601Swnj 		n->t_seq = n->t_ackno;
402*4601Swnj 	else {
403*4601Swnj 		n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen);
404*4601Swnj 		n->t_seq = 0;
405*4601Swnj 	}
406*4601Swnj 	n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */
407*4601Swnj 	n->th_flags ^= TH_ACK;
408*4601Swnj 	n->t_len = htons(TCPSIZE);
409*4601Swnj 	n->t_off = 5;
410*4601Swnj 	n->t_sum = cksum(mp, sizeof(struct th));
411*4601Swnj 	((struct ip *)n)->ip_len = sizeof(struct th);
412*4601Swnj 	ip_output(mp);
413*4601Swnj 	netstat.t_badsegs++;
414*4601Swnj }
415*4601Swnj 
416*4601Swnj rcv_ctldat(tp, n, dataok)
417*4601Swnj 	register struct tcb *tp;
418*4601Swnj 	register struct th *n;
419*4601Swnj {
420*4601Swnj 	register sent;
421*4601Swnj 	register struct ucb *up;
422*4601Swnj 	register struct mbuf *m, *mn;
423*4601Swnj 	register len;
424*4601Swnj COUNT(RCV_CTLDAT);
425*4601Swnj 
426*4601Swnj 	tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW);
427*4601Swnj /* syn */
428*4601Swnj 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) {
429*4601Swnj 		tp->irs = n->t_seq;
430*4601Swnj 		tp->rcv_nxt = n->t_seq + 1;
431*4601Swnj 		tp->snd_wl = tp->rcv_urp = tp->irs;
432*4601Swnj 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
433*4601Swnj 	}
434*4601Swnj /* ack */
435*4601Swnj 	if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
436*4601Swnj 	    n->t_ackno > tp->snd_una) {
437*4601Swnj 		up = tp->t_ucb;
438*4601Swnj 
439*4601Swnj 		/* update snd_una and snd_nxt */
440*4601Swnj 		tp->snd_una = n->t_ackno;
441*4601Swnj 		if (tp->snd_una > tp->snd_nxt)
442*4601Swnj 			tp->snd_nxt = tp->snd_una;
443*4601Swnj 
444*4601Swnj 		/* if timed msg acked, set retrans time value */
445*4601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) &&
446*4601Swnj 		    tp->snd_una > tp->t_xmt_val) {
447*4601Swnj 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
448*4601Swnj 			if (tp->t_xmtime > T_REMAX)
449*4601Swnj 				tp->t_xmtime = T_REMAX;
450*4601Swnj 		}
451*4601Swnj 
452*4601Swnj 		/* remove acked data from send buf */
453*4601Swnj 		len = tp->snd_una - tp->snd_off;
454*4601Swnj 		m = up->uc_sbuf;
455*4601Swnj 		while (len > 0 && m != NULL)
456*4601Swnj 			if (m->m_len <= len) {
457*4601Swnj 				len -= m->m_len;
458*4601Swnj 				if (m->m_off > MMAXOFF)
459*4601Swnj 					up->uc_ssize -= NMBPG;
460*4601Swnj 				MFREE(m, mn);
461*4601Swnj 				m = mn;
462*4601Swnj 				up->uc_ssize--;
463*4601Swnj 			} else {
464*4601Swnj 				m->m_len -= len;
465*4601Swnj 				m->m_off += len;
466*4601Swnj 				break;
467*4601Swnj 			}
468*4601Swnj 		up->uc_sbuf = m;
469*4601Swnj 		tp->snd_off = tp->snd_una;
470*4601Swnj 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
471*4601Swnj 		    (tp->snd_una > tp->iss)) {
472*4601Swnj 			tp->tc_flags |= TC_SYN_ACKED;
473*4601Swnj 			tp->t_init = 0;
474*4601Swnj 		}
475*4601Swnj 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
476*4601Swnj 			tp->tc_flags &= ~TC_SND_FIN;
477*4601Swnj 		tp->t_rexmt = 0;
478*4601Swnj 		tp->t_rexmttl = 0;
479*4601Swnj 		tp->tc_flags |= TC_CANCELLED;
480*4601Swnj 		netwakeup(tp->t_ucb);		/* wasteful */
481*4601Swnj 	}
482*4601Swnj /* win */
483*4601Swnj 	if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
484*4601Swnj 		tp->snd_wl = n->t_seq;
485*4601Swnj 		tp->snd_wnd = n->t_win;
486*4601Swnj 		tp->tc_flags |= TC_NEW_WINDOW;
487*4601Swnj 		tp->t_persist = 0;
488*4601Swnj 	}
489*4601Swnj 	if (dataok) {
490*4601Swnj /* text */
491*4601Swnj 		if (n->t_len != 0)
492*4601Swnj 			rcv_text(tp, n);
493*4601Swnj /* urg */
494*4601Swnj 		if (n->th_flags&TH_URG) {
495*4601Swnj 			unsigned urgent;
496*4601Swnj 
497*4601Swnj 			urgent = n->t_urp + n->t_seq;
498*4601Swnj 			if (tp->rcv_nxt < urgent) {
499*4601Swnj 				if (tp->rcv_urp <= tp->rcv_nxt)
500*4601Swnj 					to_user(tp->t_ucb, UURGENT);
501*4601Swnj 				tp->rcv_urp = urgent;
502*4601Swnj 			}
503*4601Swnj 		}
504*4601Swnj /* eol */
505*4601Swnj 		if ((n->th_flags&TH_EOL) &&
506*4601Swnj 		    (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
507*4601Swnj 		    tp->t_rcv_prev != (struct th *)tp) {
508*4601Swnj 			/* mark last mbuf */
509*4601Swnj 			m = dtom(tp->t_rcv_prev);
510*4601Swnj 			if (m != NULL) {
511*4601Swnj 				while (m->m_next != NULL)
512*4601Swnj 					m = m->m_next;
513*4601Swnj 				m->m_act =
514*4601Swnj 				    (struct mbuf *)(m->m_off + m->m_len - 1);
515*4601Swnj 			}
516*4601Swnj 		}
517*4601Swnj 	}
518*4601Swnj /* fin */
519*4601Swnj 	if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) {
520*4601Swnj 		int last;
521*4601Swnj 
522*4601Swnj 		if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
523*4601Swnj 			/* do we really have fin ? */
524*4601Swnj 			last = firstempty(tp);
525*4601Swnj 			if (tp->t_rcv_prev == (struct th *)tp ||
526*4601Swnj 			    last == t_end(tp->t_rcv_prev)) {
527*4601Swnj 				tp->tc_flags |= TC_FIN_RCVD;
528*4601Swnj 				netwakeup(tp->t_ucb);		/* poke */
529*4601Swnj 			}
530*4601Swnj 			if ((tp->tc_flags&TC_FIN_RCVD) &&
531*4601Swnj 			    tp->rcv_nxt >= last) {
532*4601Swnj 				tp->rcv_nxt = last + 1;		/* fin seq */
533*4601Swnj 				tp->tc_flags |= TC_ACK_DUE;
534*4601Swnj 			}
535*4601Swnj 		} else
536*4601Swnj 			tp->tc_flags |= TC_ACK_DUE;
537*4601Swnj 	}
538*4601Swnj 
539*4601Swnj /* respond */
540*4601Swnj 	if (tp->tc_flags&TC_ACK_DUE)
541*4601Swnj 		sent = send_ctl(tp);
542*4601Swnj 	else if (tp->tc_flags&TC_NEW_WINDOW)
543*4601Swnj 		sent = send(tp);
544*4601Swnj 	else
545*4601Swnj 		sent = 0;
546*4601Swnj 
547*4601Swnj /* set for retrans */
548*4601Swnj 	if (!sent && tp->snd_una < tp->snd_nxt &&
549*4601Swnj 	    (tp->tc_flags&TC_CANCELLED)) {
550*4601Swnj 		tp->t_rexmt = tp->t_xmtime;
551*4601Swnj 		tp->t_rexmttl = T_REXMTTL;
552*4601Swnj 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
553*4601Swnj 		tp->tc_flags &= ~TC_CANCELLED;
554*4601Swnj 	}
555*4601Swnj }
556*4601Swnj 
557*4601Swnj rcv_text(tp, t)
558*4601Swnj 	register struct tcb *tp;
559*4601Swnj 	register struct th *t;
560*4601Swnj {
561*4601Swnj 	register i;
562*4601Swnj 	register struct th *p, *q;
563*4601Swnj 	register struct mbuf *m, *n;
564*4601Swnj 	struct th *savq;
565*4601Swnj 	int last, j, k;
566*4601Swnj COUNT(RCV_TEXT);
567*4601Swnj 
568*4601Swnj 	/* throw away any data we have already received */
569*4601Swnj 	if ((i = tp->rcv_nxt - t->t_seq) > 0)  {
570*4601Swnj 		if (i >= t->t_len)
571*4601Swnj 			return;
572*4601Swnj 		t->t_seq += i;
573*4601Swnj 		t->t_len -= i;
574*4601Swnj 		m_adj(dtom(t), i);
575*4601Swnj 	}
576*4601Swnj 
577*4601Swnj 	last = t_end(t);                /* last seq # in incoming seg */
578*4601Swnj 	i = rcv_resource(tp);           /* # buffers available to con */
579*4601Swnj 
580*4601Swnj 	/* count buffers in segment */
581*4601Swnj 
582*4601Swnj 	for (m = dtom(t), j = 0; m != NULL; m = m->m_next)
583*4601Swnj 		if (m->m_len != 0) {
584*4601Swnj         		j++;
585*4601Swnj 			if (m->m_off > MMAXOFF)
586*4601Swnj 				j += NMBPG;
587*4601Swnj 		}
588*4601Swnj 
589*4601Swnj 	/* not enough resources to process segment */
590*4601Swnj 
591*4601Swnj 	if (j > i && netcb.n_bufs < netcb.n_lowat) {
592*4601Swnj 
593*4601Swnj 		/* if segment preceeds top of seqeuncing queue, try to take
594*4601Swnj 		   buffers from bottom of queue */
595*4601Swnj 
596*4601Swnj                 q = tp->t_rcv_next;
597*4601Swnj 		if (q != (struct th *)tp && tp->rcv_nxt < q->t_seq &&
598*4601Swnj 		    t->t_seq < q->t_seq)
599*4601Swnj 
600*4601Swnj 			for (k=j-i, p = tp->t_rcv_prev; k > 0 &&
601*4601Swnj 			     p != (struct th *)tp; k--) {
602*4601Swnj 				savq = p->t_prev;
603*4601Swnj 				tcp_deq(p);
604*4601Swnj 				i += m_freem(dtom(p));
605*4601Swnj 				p = savq;
606*4601Swnj 			}
607*4601Swnj 
608*4601Swnj 		/* if still not enough room, drop text from end of segment */
609*4601Swnj 
610*4601Swnj 		if (j > i) {
611*4601Swnj 
612*4601Swnj 			for (m = dtom(t); i > 0 && m != NULL; i--)
613*4601Swnj 				m = m->m_next;
614*4601Swnj 
615*4601Swnj         		while (m != NULL) {
616*4601Swnj         			t->t_len -= m->m_len;
617*4601Swnj         			last -= m->m_len;
618*4601Swnj         			m->m_len = 0;
619*4601Swnj         			m = m->m_next;
620*4601Swnj         		}
621*4601Swnj         		tp->tc_flags |= TC_DROPPED_TXT;
622*4601Swnj         		if (last < t->t_seq)
623*4601Swnj         			return;
624*4601Swnj         	}
625*4601Swnj 	}
626*4601Swnj 
627*4601Swnj 	/* merge incoming data into the sequence queue */
628*4601Swnj 
629*4601Swnj         q = tp->t_rcv_next;             /* -> top of sequencing queue */
630*4601Swnj 
631*4601Swnj         /* skip frags which new doesn't overlap at end */
632*4601Swnj 
633*4601Swnj         while ((q != (struct th *)tp) && (t->t_seq > t_end(q)))
634*4601Swnj         	q = q->t_next;
635*4601Swnj 
636*4601Swnj         if (q == (struct th *)tp) {     /* frag at end of chain */
637*4601Swnj 
638*4601Swnj 		if (last >= tp->rcv_nxt) {
639*4601Swnj 		        tp->tc_flags |= TC_NET_KEEP;
640*4601Swnj         	        tcp_enq(t, tp->t_rcv_prev);
641*4601Swnj 		}
642*4601Swnj 
643*4601Swnj         } else {
644*4601Swnj 
645*4601Swnj 		/* frag doesn't overlap any on chain */
646*4601Swnj 
647*4601Swnj         	if (last < q->t_seq) {
648*4601Swnj 			tp->tc_flags |= TC_NET_KEEP;
649*4601Swnj         		tcp_enq(t, q->t_prev);
650*4601Swnj 
651*4601Swnj         	/* new overlaps beginning of next frag only */
652*4601Swnj 
653*4601Swnj         	} else if (last < t_end(q)) {
654*4601Swnj         		if ((i = last - q->t_seq + 1) < t->t_len) {
655*4601Swnj                 		t->t_len -= i;
656*4601Swnj         			m_adj(dtom(t), -i);
657*4601Swnj 				tp->tc_flags |= TC_NET_KEEP;
658*4601Swnj         			tcp_enq(t, q->t_prev);
659*4601Swnj         		}
660*4601Swnj 
661*4601Swnj         	/* new overlaps end of previous frag */
662*4601Swnj 
663*4601Swnj         	} else {
664*4601Swnj         		savq = q;
665*4601Swnj         		if (t->t_seq <= q->t_seq) {     /* complete cover */
666*4601Swnj         			savq = q->t_prev;
667*4601Swnj         			tcp_deq(q);
668*4601Swnj         			m_freem(dtom(q));
669*4601Swnj 
670*4601Swnj         		} else {                        /* overlap */
671*4601Swnj         			if ((i = t_end(q) - t->t_seq + 1) < t->t_len) {
672*4601Swnj                 			t->t_seq += i;
673*4601Swnj                 			t->t_len -= i;
674*4601Swnj                 			m_adj(dtom(t), i);
675*4601Swnj 				} else
676*4601Swnj 					t->t_len = 0;
677*4601Swnj         		}
678*4601Swnj 
679*4601Swnj         	/* new overlaps at beginning of successor frags */
680*4601Swnj 
681*4601Swnj         		q = savq->t_next;
682*4601Swnj         		while ((q != (struct th *)tp) && (t->t_len != 0) &&
683*4601Swnj         			(q->t_seq < last))
684*4601Swnj 
685*4601Swnj         			/* complete cover */
686*4601Swnj 
687*4601Swnj         			if (t_end(q) <= last) {
688*4601Swnj         				p = q->t_next;
689*4601Swnj         				tcp_deq(q);
690*4601Swnj         				m_freem(dtom(q));
691*4601Swnj         				q = p;
692*4601Swnj 
693*4601Swnj         			} else {        /* overlap */
694*4601Swnj 
695*4601Swnj         				if ((i = last - q->t_seq + 1) < t->t_len) {
696*4601Swnj                 				t->t_len -= i;
697*4601Swnj                 				m_adj(dtom(t), -i);
698*4601Swnj 					} else
699*4601Swnj 						t->t_len = 0;
700*4601Swnj         				break;
701*4601Swnj         			}
702*4601Swnj 
703*4601Swnj         	/* enqueue whatever is left of new before successors */
704*4601Swnj 
705*4601Swnj         		if (t->t_len != 0) {
706*4601Swnj 				tp->tc_flags |= TC_NET_KEEP;
707*4601Swnj         			tcp_enq(t, savq);
708*4601Swnj 			}
709*4601Swnj         	}
710*4601Swnj         }
711*4601Swnj 
712*4601Swnj 	/* set to ack completed data (no gaps) */
713*4601Swnj 
714*4601Swnj 	tp->rcv_nxt = firstempty(tp);
715*4601Swnj 	tp->tc_flags |= TC_ACK_DUE;
716*4601Swnj 
717*4601Swnj #ifdef notdef
718*4601Swnj 	/* THIS CODE CANT POSSIBLY WORK */
719*4601Swnj 	/* if any room remaining in rcv buf, take any unprocessed
720*4601Swnj 	   messages and schedule for later processing */
721*4601Swnj 
722*4601Swnj 	i = rcv_resource(tp);
723*4601Swnj 
724*4601Swnj 	while ((m = tp->t_rcv_unack) != NULL && i > 0) {
725*4601Swnj 
726*4601Swnj 		/* schedule work request */
727*4601Swnj 
728*4601Swnj 		t = (struct th *)((int)m + m->m_off);
729*4601Swnj 		j = (t->t_off << 2) + sizeof(struct ip);
730*4601Swnj 		m->m_off += j;
731*4601Swnj 		m->m_len -= j;
732*4601Swnj 		tp->t_rcv_unack = m->m_act;
733*4601Swnj 		m->m_act = (struct mbuf *)0;
734*4601Swnj 		netstat.t_unack++;
735*4601Swnj 		tcp_work(INRECV, 0, tp, t);
736*4601Swnj 
737*4601Swnj 		/* remaining buffer space */
738*4601Swnj 
739*4601Swnj 		for (n = m; n != NULL; n = n->m_next)
740*4601Swnj 			i--;
741*4601Swnj 	}
742*4601Swnj #endif
743*4601Swnj }
744*4601Swnj 
745*4601Swnj present_data(tp)
746*4601Swnj 	register struct tcb *tp;
747*4601Swnj {
748*4601Swnj 	register struct th *t;
749*4601Swnj 	register struct ucb *up;
750*4601Swnj 	register struct mbuf *m, **mp;
751*4601Swnj 	seq_t ready;
752*4601Swnj COUNT(PRESENT_DATA);
753*4601Swnj 
754*4601Swnj 	/* connection must be synced and data available for user */
755*4601Swnj 	if (((tp->tc_flags&TC_SYN_ACKED) == 0) ||
756*4601Swnj 	    (t = tp->t_rcv_next) == (struct th *)tp)
757*4601Swnj 		return;
758*4601Swnj 	up = tp->t_ucb;
759*4601Swnj 	ready = firstempty(tp);     /* seq # of last complete datum */
760*4601Swnj 	mp = &up->uc_rbuf;
761*4601Swnj 	while (*mp)
762*4601Swnj 		mp = &(*mp)->m_next;
763*4601Swnj 	while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp &&
764*4601Swnj 	    t_end(t) < ready) {
765*4601Swnj 		tcp_deq(t);
766*4601Swnj 		m = dtom(t);
767*4601Swnj 		t = t->t_next;
768*4601Swnj 		while (m) {
769*4601Swnj 			if (m->m_len == 0) {
770*4601Swnj 				m = m_free(m);
771*4601Swnj 				continue;
772*4601Swnj 			}
773*4601Swnj 			up->uc_rsize++;
774*4601Swnj 			if (m->m_off > MMAXOFF)
775*4601Swnj 				up->uc_rsize += NMBPG;
776*4601Swnj 			if (*mp == 0)
777*4601Swnj 				*mp = m;
778*4601Swnj 			mp = &m->m_next;
779*4601Swnj 			m = *mp;
780*4601Swnj 		}
781*4601Swnj 	}
782*4601Swnj 	if (up->uc_rsize != 0)
783*4601Swnj 		netwakeup(up);
784*4601Swnj 	/*
785*4601Swnj 	 * Let user know about foreign tcp close if no more data.
786*4601Swnj 	 */
787*4601Swnj 	if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 &&
788*4601Swnj 	    rcv_empty(tp))
789*4601Swnj 		to_user(up, UCLOSED);
790*4601Swnj }
791