xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4648)
1 /* tcp_input.c 1.5 81/10/28 */
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_setup(tp, n, INRECV, &tdb);
187 	} else
188 		tdb.td_tod = 0;
189 #endif
190 	switch (tp->t_state) {
191 
192 	case LISTEN:
193 		if (!syn_ok(tp, n) ||
194 		    ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) {
195 			nstate = EFAILEC;
196 			goto done;
197 		}
198 		tp->t_fport = n->t_src;
199 		tp->t_ucb->uc_template = tcp_template(tp);
200 		rcv_ctldat(tp, n, 1);
201 		if (tp->tc_flags&TC_FIN_RCVD) {
202 			tp->t_finack = T_2ML;			/* 3 */
203 			tp->tc_flags &= ~TC_WAITED_2_ML;
204 			nstate = CLOSE_WAIT;
205 		} else {
206 			tp->t_init = T_INIT / 2;		/* 4 */
207 			nstate = L_SYN_RCVD;
208 		}
209 		goto done;
210 
211 	case SYN_SENT:
212 		if (!syn_ok(tp, n)) {
213 			nstate = EFAILEC;
214 			goto done;
215 		}
216 		rcv_ctldat(tp, n, 1);
217 		if (tp->tc_flags&TC_FIN_RCVD) {
218 			if (n->th_flags&TH_ACK) {
219 				if (n->t_ackno > tp->iss)
220 					present_data(tp);	/* 32 */
221 			} else {
222 				tp->t_finack = T_2ML;		/* 9 */
223 				tp->tc_flags &= ~TC_WAITED_2_ML;
224 			}
225 			nstate = CLOSE_WAIT;
226 			goto done;
227 		}
228 		if (n->th_flags&TH_ACK) {
229 			present_data(tp);			/* 11 */
230 			nstate = ESTAB;
231 		} else
232 			nstate = SYN_RCVD;			/* 8 */
233 		goto done;
234 
235 	case SYN_RCVD:
236 	case L_SYN_RCVD:
237 		if ((n->th_flags&TH_ACK) == 0 ||
238 		    (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) {
239 			nstate = EFAILEC;
240 			goto done;
241 		}
242 		goto input;
243 
244 	case ESTAB:
245 	case FIN_W1:
246 	case FIN_W2:
247 	case TIME_WAIT:
248 input:
249 		rcv_ctldat(tp, n, 1);				/* 39 */
250 		present_data(tp);
251 		switch (tp->t_state) {
252 
253 		case ESTAB:
254 			if (tp->tc_flags&TC_FIN_RCVD)
255 				nstate = CLOSE_WAIT;
256 			break;
257 
258 		case SYN_RCVD:
259 		case L_SYN_RCVD:
260 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
261 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
262 			break;
263 
264 		case FIN_W1:
265 			j = ack_fin(tp, n);
266 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
267 				if (j)
268 					nstate = FIN_W2;	/* 27 */
269 				break;
270 			}
271 			tp->t_finack = T_2ML;
272 			tp->tc_flags &= ~TC_WAITED_2_ML;
273 			nstate = j ? TIME_WAIT : CLOSING1;	/* 28:26 */
274 			break;
275 
276 		case FIN_W2:
277 			if (tp->tc_flags&TC_FIN_RCVD) {
278 				tp->t_finack = T_2ML;		/* 29 */
279 				tp->tc_flags &= ~TC_WAITED_2_ML;
280 				nstate = TIME_WAIT;
281 				break;
282 			}
283 			break;
284 		}
285 		goto done;
286 
287 	case CLOSE_WAIT:
288 		if (n->th_flags&TH_FIN) {
289 			if ((n->th_flags&TH_ACK) &&
290 			    n->t_ackno <= tp->seq_fin) {
291 				rcv_ctldat(tp, n, 0);		/* 30 */
292 				tp->t_finack = T_2ML;
293 				tp->tc_flags &= ~TC_WAITED_2_ML;
294 			} else
295 				send_ctl(tp);			/* 31 */
296 			goto done;
297 		}
298 		goto input;
299 
300 	case CLOSING1:
301 		j = ack_fin(tp, n);
302 		if (n->th_flags&TH_FIN) {
303 			rcv_ctldat(tp, n, 0);
304 			tp->t_finack = T_2ML;
305 			tp->tc_flags &= ~TC_WAITED_2_ML;
306 			if (j)
307 				nstate = TIME_WAIT;		/* 23 */
308 			goto done;
309 		}
310 		if (j) {
311 			if (tp->tc_flags&TC_WAITED_2_ML)
312 				if (rcv_empty(tp)) {
313 					t_close(tp, UCLOSED);	/* 15 */
314 					nstate = CLOSED;
315 				} else
316 					nstate = RCV_WAIT;	/* 18 */
317 			else
318 				nstate = TIME_WAIT;
319 			goto done;
320 		}
321 		goto input;
322 
323 	case CLOSING2:
324 		if (ack_fin(tp, n)) {
325 			if (rcv_empty(tp)) {			/* 16 */
326 				t_close(tp, UCLOSED);
327 				nstate = CLOSED;
328 			} else
329 				nstate = RCV_WAIT;		/* 19 */
330 			goto done;
331 		}
332 		if (n->th_flags&TH_FIN) {
333 			send_ctl(tp);				/* 31 */
334 			goto done;
335 		}
336 		goto input;
337 
338 	case RCV_WAIT:
339 		if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) &&
340 		    n->t_ackno <= tp->seq_fin) {
341 			rcv_ctldat(tp, n, 0);
342 			tp->t_finack = T_2ML;
343 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
344 		}
345 		goto done;
346 	}
347 	panic("tcp_input");
348 done:
349 
350 	/*
351 	 * Done with state*input specific processing.
352 	 * Form trace records, free input if not needed,
353 	 * and enter new state.
354 	 */
355 #ifdef TCPDEBUG
356 	if (tdb.td_tod)
357 		tdb_stuff(&tdb, nstate);
358 #endif
359 	switch (nstate) {
360 
361 	case EFAILEC:
362 		m_freem(mp);
363 		return;
364 
365 	default:
366 		tp->t_state = nstate;
367 		/* fall into ... */
368 
369 	case CLOSED:
370 		/* IF CLOSED CANT LOOK AT tc_flags */
371 		if ((tp->tc_flags&TC_NET_KEEP) == 0)
372 			m_freem(mp);
373 		return;
374 	}
375 	/* NOTREACHED */
376 
377 	/*
378 	 * Unwanted packed; free everything
379 	 * but the header and return an rst.
380 	 */
381 notwanted:
382 	m_freem(mp->m_next);
383 	mp->m_next = NULL;
384 	mp->m_len = sizeof(struct th);
385 #define xchg(a,b) j=a; a=b; b=j
386 	xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
387 #undef xchg
388 	if (n->th_flags&TH_ACK)
389 		n->t_seq = n->t_ackno;
390 	else {
391 		n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen);
392 		n->t_seq = 0;
393 	}
394 	n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */
395 	n->th_flags ^= TH_ACK;
396 	n->t_len = htons(TCPSIZE);
397 	n->t_off = 5;
398 	n->t_sum = cksum(mp, sizeof(struct th));
399 	((struct ip *)n)->ip_len = sizeof(struct th);
400 	ip_output(mp);
401 	netstat.t_badsegs++;
402 }
403 
404 rcv_ctldat(tp, n, dataok)
405 	register struct tcb *tp;
406 	register struct th *n;
407 {
408 	register sent;
409 	register struct ucb *up;
410 	register struct mbuf *m, *mn;
411 	register len;
412 COUNT(RCV_CTLDAT);
413 
414 	tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW);
415 /* syn */
416 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) {
417 		tp->irs = n->t_seq;
418 		tp->rcv_nxt = n->t_seq + 1;
419 		tp->snd_wl = tp->rcv_urp = tp->irs;
420 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
421 	}
422 /* ack */
423 	if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
424 	    n->t_ackno > tp->snd_una) {
425 		up = tp->t_ucb;
426 
427 		/* update snd_una and snd_nxt */
428 		tp->snd_una = n->t_ackno;
429 		if (tp->snd_una > tp->snd_nxt)
430 			tp->snd_nxt = tp->snd_una;
431 
432 		/* if timed msg acked, set retrans time value */
433 		if ((tp->tc_flags&TC_SYN_ACKED) &&
434 		    tp->snd_una > tp->t_xmt_val) {
435 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
436 			if (tp->t_xmtime > T_REMAX)
437 				tp->t_xmtime = T_REMAX;
438 		}
439 
440 		/* remove acked data from send buf */
441 		len = tp->snd_una - tp->snd_off;
442 		m = up->uc_sbuf;
443 		while (len > 0 && m != NULL)
444 			if (m->m_len <= len) {
445 				len -= m->m_len;
446 				if (m->m_off > MMAXOFF)
447 					up->uc_ssize -= NMBPG;
448 				MFREE(m, mn);
449 				m = mn;
450 				up->uc_ssize--;
451 			} else {
452 				m->m_len -= len;
453 				m->m_off += len;
454 				break;
455 			}
456 		up->uc_sbuf = m;
457 		tp->snd_off = tp->snd_una;
458 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
459 		    (tp->snd_una > tp->iss)) {
460 			tp->tc_flags |= TC_SYN_ACKED;
461 			tp->t_init = 0;
462 		}
463 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
464 			tp->tc_flags &= ~TC_SND_FIN;
465 		tp->t_rexmt = 0;
466 		tp->t_rexmttl = 0;
467 		tp->tc_flags |= TC_CANCELLED;
468 		netwakeup(tp->t_ucb);		/* wasteful */
469 	}
470 /* win */
471 	if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
472 		tp->snd_wl = n->t_seq;
473 		tp->snd_wnd = n->t_win;
474 		tp->tc_flags |= TC_NEW_WINDOW;
475 		tp->t_persist = 0;
476 	}
477 	if (dataok) {
478 /* text */
479 		if (n->t_len != 0)
480 			rcv_text(tp, n);
481 /* urg */
482 		if (n->th_flags&TH_URG) {
483 			unsigned urgent;
484 
485 			urgent = n->t_urp + n->t_seq;
486 			if (tp->rcv_nxt < urgent) {
487 				if (tp->rcv_urp <= tp->rcv_nxt)
488 					to_user(tp->t_ucb, UURGENT);
489 				tp->rcv_urp = urgent;
490 			}
491 		}
492 /* eol */
493 		if ((n->th_flags&TH_EOL) &&
494 		    (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
495 		    tp->t_rcv_prev != (struct th *)tp) {
496 			/* mark last mbuf */
497 			m = dtom(tp->t_rcv_prev);
498 			if (m != NULL) {
499 				while (m->m_next != NULL)
500 					m = m->m_next;
501 				m->m_act =
502 				    (struct mbuf *)(m->m_off + m->m_len - 1);
503 			}
504 		}
505 	}
506 /* fin */
507 	if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) {
508 		int last;
509 
510 		if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
511 			/* do we really have fin ? */
512 			last = firstempty(tp);
513 			if (tp->t_rcv_prev == (struct th *)tp ||
514 			    last == t_end(tp->t_rcv_prev)) {
515 				tp->tc_flags |= TC_FIN_RCVD;
516 				netwakeup(tp->t_ucb);		/* poke */
517 			}
518 			if ((tp->tc_flags&TC_FIN_RCVD) &&
519 			    tp->rcv_nxt >= last) {
520 				tp->rcv_nxt = last + 1;		/* fin seq */
521 				tp->tc_flags |= TC_ACK_DUE;
522 			}
523 		} else
524 			tp->tc_flags |= TC_ACK_DUE;
525 	}
526 
527 /* respond */
528 	if (tp->tc_flags&TC_ACK_DUE)
529 		sent = send_ctl(tp);
530 	else if (tp->tc_flags&TC_NEW_WINDOW)
531 		sent = send(tp);
532 	else
533 		sent = 0;
534 
535 /* set for retrans */
536 	if (!sent && tp->snd_una < tp->snd_nxt &&
537 	    (tp->tc_flags&TC_CANCELLED)) {
538 		tp->t_rexmt = tp->t_xmtime;
539 		tp->t_rexmttl = T_REXMTTL;
540 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
541 		tp->tc_flags &= ~TC_CANCELLED;
542 	}
543 }
544 
545 rcv_text(tp, n)
546 	register struct tcb *tp;
547 	register struct th *n;
548 {
549 	register int i;
550 	register struct th *p, *q;
551 	register struct mbuf *m;
552 	int overage;
553 COUNT(RCV_TEXT);
554 
555 	/*
556 	 * Discard duplicate data already passed to user.
557 	 */
558 	if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
559 		i = tp->rcv_nxt - n->t_seq;
560 		if (i >= n->t_len)
561 			goto dropseg;
562 		n->t_seq += i;
563 		n->t_len -= i;
564 		m_adj(dtom(n), i);
565 	}
566 
567 	/*
568 	 * Find a segment which begins after this one does.
569 	 */
570 	for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next)
571 		if (SEQ_GT(q->t_seq, n->t_seq))
572 			break;
573 
574 	/*
575 	 * If there is a preceding segment, it may provide some of
576 	 * our data already.  If so, drop the data from the incoming
577 	 * segment.  If it provides all of our data, drop us.
578 	 */
579 	if (q->t_prev != (struct th *)tp) {
580 		/* conversion to int (in i) handles seq wraparound */
581 		i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
582 		if (i > 0) {
583 			if (i >= n->t_len)
584 				goto dropseg;
585 			m_adj(dtom(tp), i);
586 			n->t_len -= i;
587 			n->t_seq += i;
588 		}
589 	}
590 
591 	/*
592 	 * While we overlap succeeding segments trim them or,
593 	 * if they are completely covered, dequeue them.
594 	 */
595 	while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
596 		i = (n->t_seq + n->t_len) - q->t_seq;
597 		if (i < q->t_len) {
598 			q->t_len -= i;
599 			m_adj(dtom(q), i);
600 			break;
601 		}
602 		q = q->t_next;
603 		m_freem(dtom(q->t_prev));
604 		remque(q->t_prev);
605 	}
606 
607 	/*
608 	 * Stick new segment in its place.
609 	 */
610 	insque(n, q->t_prev);
611 /*
612 	tp->rcv_seqcnt += n->t_len;
613 */
614 
615 #ifdef notdef
616 	/*
617 	 * Calculate available space and discard segments for
618 	 * which there is too much.
619 	 */
620 	q = tp->t_rcv_prev;
621 	overage =
622 	    (tp->t_socket->uc_rcc + tp->rcv_seqcnt) - tp->t_socket->uc_rhiwat;
623 	if (overage > 0)
624 		for (;;) {
625 			i = MIN(q->t_len, overage);
626 			overage -= i;
627 			q->t_len -= i;
628 			m_adj(q, -i);
629 			if (q == n)
630 				tp->tc_flags |= TC_DROPPED_TXT;
631 			if (q->t_len)
632 				break;
633 			if (q == n)
634 				panic("tcp_text dropall");
635 			q = q->t_prev;
636 			remque(q->t_next);
637 		}
638 #endif
639 
640 	/*
641 	 * Advance rcv_next through
642 	 * newly completed sequence space
643 	 * and return forcing an ack.
644 	 */
645 	while (n->t_seq == tp->rcv_nxt) {
646 		/* present data belongs here */
647 		tp->rcv_nxt += n->t_len;
648 		n = n->t_next;
649 		if (n == (struct th *)tp)
650 			break;
651 	}
652 	tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
653 	return;
654 
655 dropseg:
656 	/* don't set TC_NET_KEEP, so that mbuf's will get dropped */
657 	return;
658 }
659 
660 present_data(tp)
661 	register struct tcb *tp;
662 {
663 	register struct th *t;
664 	register struct ucb *up;
665 	register struct mbuf *m, **mp;
666 	seq_t ready;
667 COUNT(PRESENT_DATA);
668 
669 	/* connection must be synced and data available for user */
670 	if (((tp->tc_flags&TC_SYN_ACKED) == 0) ||
671 	    (t = tp->t_rcv_next) == (struct th *)tp)
672 		return;
673 	up = tp->t_ucb;
674 	ready = firstempty(tp);     /* seq # of last complete datum */
675 	mp = &up->uc_rbuf;
676 	while (*mp)
677 		mp = &(*mp)->m_next;
678 	while (up->uc_rsize < up->uc_rcv && t != (struct th *) tp &&
679 	    t_end(t) < ready) {
680 		tcp_deq(t);
681 		m = dtom(t);
682 		t = t->t_next;
683 		while (m) {
684 			if (m->m_len == 0) {
685 				m = m_free(m);
686 				continue;
687 			}
688 			up->uc_rsize++;
689 			if (m->m_off > MMAXOFF)
690 				up->uc_rsize += NMBPG;
691 			if (*mp == 0)
692 				*mp = m;
693 			mp = &m->m_next;
694 			m = *mp;
695 		}
696 	}
697 	if (up->uc_rsize != 0)
698 		netwakeup(up);
699 	/*
700 	 * Let user know about foreign tcp close if no more data.
701 	 */
702 	if ((tp->tc_flags&TC_FIN_RCVD) && (tp->tc_flags&TC_USR_CLOSED) == 0 &&
703 	    rcv_empty(tp))
704 		to_user(up, UCLOSED);
705 }
706 
707 #ifdef TCPDEBUG
708 tdb_setup(tp, n, input, tdp)
709 	struct tcb *tp;
710 	register struct th *n;
711 	int input;
712 	register struct tcp_debug *tdp;
713 {
714 
715 	tdp->td_tod = time;
716 	tdp->td_tcb = tp;
717 	tdp->td_old = tp->t_state;
718 	tdp->td_inp = input;
719 	tdp->td_tim = 0;
720 	tdp->td_new = -1;
721 	if (n) {
722 		tdp->td_sno = n->t_seq;
723 		tdp->td_ano = n->t_ackno;
724 		tdp->td_wno = n->t_win;
725 		tdp->td_lno = n->t_len;
726 		tdp->td_flg = n->th_flags;
727 	} else
728 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
729 		    tdp->td_flg = 0;
730 }
731 
732 tdb_stuff(tdp, nstate)
733 	struct tcp_debug *tdp;
734 	int nstate;
735 {
736 
737 	tdp->td_new = nstate;
738 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
739 	if (tcpconsdebug & 2)
740 		tcp_prt(tdp);
741 }
742 #endif
743