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