xref: /csrg-svn/sys/netinet/tcp_input.c (revision 4679)
1 /* tcp_input.c 1.12 81/10/30 */
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/mbuf.h"
6 #include "../h/socket.h"
7 #include "../inet/inet.h"
8 #include "../inet/inet_systm.h"
9 #include "../inet/imp.h"
10 #include "../inet/inet_host.h"
11 #include "../inet/ip.h"
12 #include "../inet/tcp.h"
13 #include "../inet/tcp_fsm.h"
14 
15 int	tcpcksum = 1;
16 
17 tcp_input(mp)
18 	register struct mbuf *mp;
19 {
20 	register struct th *n;		/* known to be r10 */
21 	register int j;			/* known to be r9 */
22 	register struct tcb *tp;
23 	int nstate;
24 	struct mbuf *m;
25 	struct ucb *up;
26 	int hlen, tlen;
27 	u_short lport, fport;
28 #ifdef TCPDEBUG
29 	struct tcp_debug tdb;
30 #endif
31 COUNT(TCP_INPUT);
32 
33 	/*
34 	 * Build extended tcp header
35 	 */
36 	n = (struct th *)((int)mp + mp->m_off);
37 	tlen = ((struct ip *)n)->ip_len;
38 	n->t_len = htons(tlen);
39 	n->t_next = NULL;
40 	n->t_prev = NULL;
41 	n->t_x1 = 0;
42 	lport = ntohs(n->t_dst);
43 	fport = ntohs(n->t_src);
44 
45 	/* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */
46 	if ((hlen = n->t_off << 2) > mp->m_len)
47 		{ printf("tcp header overflow\n"); m_freem(mp); return; }
48 
49 	if (tcpcksum) {
50 		/*
51 		 * Checksum extended header and data
52 		 */
53 		j = n->t_sum; n->t_sum = 0;
54 #ifdef vax
55 		if (tlen == 20) {
56 			asm("addl3 $8,r10,r0; movl (r0)+,r1; addl2 (r0)+,r1");
57 			asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1");
58 			asm("adwc (r0)+,r1; adwc (r0)+,r1; adwc (r0)+,r1");
59 			asm("adwc $0,r1; ashl $-16,r1,r0; addw2 r0,r1");
60 			asm("adwc $0,r1");		/* ### */
61 			asm("mcoml r1,r1; movzwl r1,r1; subl2 r1,r9");
62 		} else
63 #endif
64 			j -= cksum(mp, sizeof (struct ip) + tlen);
65 		if (j != 0) {
66 			netstat.t_badsum++;
67 			m_freem(mp);
68 			return;
69 		}
70 	}
71 
72 	/*
73 	 * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!)
74 	 */
75 	for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next)
76 		if (tp->t_lport == lport && tp->t_fport == fport &&
77 		    tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr)
78 			goto found;
79 	for (tp = tcb_head; tp != 0; tp = tp->t_tcb_next)
80 		if (tp->t_lport == lport &&
81 		    (tp->t_fport==fport || tp->t_fport==0) &&
82 		    (tp->t_ucb->uc_host->h_addr.s_addr == n->t_s.s_addr ||
83 		     tp->t_ucb->uc_host->h_addr.s_addr == 0))
84 			goto found;
85 	goto notwanted;
86 found:
87 
88 	/*
89 	 * Byte swap header
90 	 */
91 	n->t_len = tlen - hlen;
92 	n->t_src = fport;
93 	n->t_dst = lport;
94 	n->t_seq = ntohl(n->t_seq);
95 	n->t_ackno = ntohl(n->t_ackno);
96 	n->t_win = ntohs(n->t_win);
97 	n->t_urp = ntohs(n->t_urp);
98 
99 	/*
100 	 * Check segment seq # and do rst processing
101 	 */
102 	switch (tp->t_state) {
103 
104 	case LISTEN:
105 		if ((n->th_flags&TH_ACK) || !syn_ok(tp, n)) {
106 			tcp_sndrst(tp, n);
107 			goto badseg;
108 		}
109 		if (n->th_flags&TH_RST)
110 			goto badseg;
111 		goto goodseg;
112 
113 	case SYN_SENT:
114 		if (!ack_ok(tp, n) || !syn_ok(tp, n)) {
115 			tcp_sndrst(tp, n);			/* 71,72,75 */
116 			goto badseg;
117 		}
118 		if (n->th_flags&TH_RST) {
119 			tcp_close(tp, URESET);			/* 70 */
120 			tp->t_state = CLOSED;
121 			goto badseg;
122 		}
123 		goto goodseg;
124 
125 	default:
126         	if ((n->th_flags&TH_RST) == 0)
127 			goto common;
128 		if (n->t_seq < tp->rcv_nxt)		/* bad rst */
129 			goto badseg;				/* 69 */
130 		switch (tp->t_state) {
131 
132 		case L_SYN_RCVD:
133 			if (ack_ok(tp, n) == 0)
134 				goto badseg;			/* 69 */
135 			tp->t_rexmt = 0;
136 			tp->t_rexmttl = 0;
137 			tp->t_persist = 0;
138 			h_free(tp->t_ucb->uc_host);
139 			tp->t_state = LISTEN;
140 			goto badseg;
141 
142 		default:
143 			tcp_close(tp, URESET);			/* 66 */
144 			tp->t_state = CLOSED;
145 			goto badseg;
146 		}
147 		/*NOTREACHED*/
148 
149 	case SYN_RCVD:
150 common:
151 		if (ack_ok(tp, n) == 0) {
152 			tcp_sndrst(tp, n);			/* 74 */
153 			goto badseg;
154 		}
155 		if (syn_ok(tp, n) && n->t_seq != tp->irs) {
156 			tcp_sndnull(tp);			/* 74 */
157 			goto badseg;
158 		}
159 		goto goodseg;
160 	}
161 badseg:
162 	m_freem(mp);
163 	return;
164 
165 goodseg:
166 #ifdef notdef
167 	/* DO SOMETHING ABOUT UNACK!!! */
168 	/*
169 	 * Defer processing if no buffer space for this connection.
170 	 */
171 	up = tp->t_ucb;
172 	if (up->uc_rcc > up->uc_rhiwat &&
173 	     && n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) {
174 		mp->m_act = (struct mbuf *)0;
175 		if ((m = tp->t_rcv_unack) != NULL) {
176 			while (m->m_act != NULL)
177 				m = m->m_act;
178 			m->m_act = mp;
179 		} else
180 			tp->t_rcv_unack = mp;
181 		return;
182 	}
183 #endif
184 
185 	/*
186 	 * Discard ip header, and do tcp input processing.
187 	 */
188 	hlen += sizeof(struct ip);
189 	mp->m_off += hlen;
190 	mp->m_len -= hlen;
191 	nstate = tp->t_state;
192 	tp->tc_flags &= ~TC_NET_KEEP;
193 	acounts[tp->t_state][INRECV]++;
194 #ifdef TCPDEBUG
195 	if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) {
196 		tdb_setup(tp, n, INRECV, &tdb);
197 	} else
198 		tdb.td_tod = 0;
199 #endif
200 	switch (tp->t_state) {
201 
202 	case LISTEN:
203 		if (!syn_ok(tp, n) ||
204 		    ((tp->t_ucb->uc_host = h_make(&n->t_s)) == 0)) {
205 			nstate = EFAILEC;
206 			goto done;
207 		}
208 		tp->t_fport = n->t_src;
209 		tp->t_ucb->uc_template = tcp_template(tp);
210 		tcp_ctldat(tp, n, 1);
211 		if (tp->tc_flags&TC_FIN_RCVD) {
212 			tp->t_finack = T_2ML;			/* 3 */
213 			tp->tc_flags &= ~TC_WAITED_2_ML;
214 			nstate = CLOSE_WAIT;
215 		} else {
216 			tp->t_init = T_INIT / 2;		/* 4 */
217 			nstate = L_SYN_RCVD;
218 		}
219 		goto done;
220 
221 	case SYN_SENT:
222 		if (!syn_ok(tp, n)) {
223 			nstate = EFAILEC;
224 			goto done;
225 		}
226 		tcp_ctldat(tp, n, 1);
227 		if (tp->tc_flags&TC_FIN_RCVD) {
228 			if (n->th_flags&TH_ACK) {
229 				if (n->t_ackno > tp->iss)
230 					present_data(tp);	/* 32 */
231 			} else {
232 				tp->t_finack = T_2ML;		/* 9 */
233 				tp->tc_flags &= ~TC_WAITED_2_ML;
234 			}
235 			nstate = CLOSE_WAIT;
236 			goto done;
237 		}
238 		if (n->th_flags&TH_ACK) {
239 			present_data(tp);			/* 11 */
240 			nstate = ESTAB;
241 		} else
242 			nstate = SYN_RCVD;			/* 8 */
243 		goto done;
244 
245 	case SYN_RCVD:
246 	case L_SYN_RCVD:
247 		if ((n->th_flags&TH_ACK) == 0 ||
248 		    (n->th_flags&TH_ACK) && n->t_ackno <= tp->iss) {
249 			nstate = EFAILEC;
250 			goto done;
251 		}
252 		goto input;
253 
254 	case ESTAB:
255 	case FIN_W1:
256 	case FIN_W2:
257 	case TIME_WAIT:
258 input:
259 		tcp_ctldat(tp, n, 1);				/* 39 */
260 		present_data(tp);
261 		switch (tp->t_state) {
262 
263 		case ESTAB:
264 			if (tp->tc_flags&TC_FIN_RCVD)
265 				nstate = CLOSE_WAIT;
266 			break;
267 
268 		case SYN_RCVD:
269 		case L_SYN_RCVD:
270 			nstate = (tp->tc_flags&TC_FIN_RCVD) ?
271 			    CLOSE_WAIT : ESTAB;			 /* 33:5 */
272 			break;
273 
274 		case FIN_W1:
275 			j = ack_fin(tp, n);
276 			if ((tp->tc_flags & TC_FIN_RCVD) == 0) {
277 				if (j)
278 					nstate = FIN_W2;	/* 27 */
279 				break;
280 			}
281 			tp->t_finack = T_2ML;
282 			tp->tc_flags &= ~TC_WAITED_2_ML;
283 			nstate = j ? TIME_WAIT : CLOSING1;	/* 28:26 */
284 			break;
285 
286 		case FIN_W2:
287 			if (tp->tc_flags&TC_FIN_RCVD) {
288 				tp->t_finack = T_2ML;		/* 29 */
289 				tp->tc_flags &= ~TC_WAITED_2_ML;
290 				nstate = TIME_WAIT;
291 				break;
292 			}
293 			break;
294 		}
295 		goto done;
296 
297 	case CLOSE_WAIT:
298 		if (n->th_flags&TH_FIN) {
299 			if ((n->th_flags&TH_ACK) &&
300 			    n->t_ackno <= tp->seq_fin) {
301 				tcp_ctldat(tp, n, 0);		/* 30 */
302 				tp->t_finack = T_2ML;
303 				tp->tc_flags &= ~TC_WAITED_2_ML;
304 			} else
305 				tcp_sndctl(tp);			/* 31 */
306 			goto done;
307 		}
308 		goto input;
309 
310 	case CLOSING1:
311 		j = ack_fin(tp, n);
312 		if (n->th_flags&TH_FIN) {
313 			tcp_ctldat(tp, n, 0);
314 			tp->t_finack = T_2ML;
315 			tp->tc_flags &= ~TC_WAITED_2_ML;
316 			if (j)
317 				nstate = TIME_WAIT;		/* 23 */
318 			goto done;
319 		}
320 		if (j) {
321 			if (tp->tc_flags&TC_WAITED_2_ML)
322 				if (rcv_empty(tp)) {
323 					tcp_close(tp, UCLOSED);	/* 15 */
324 					nstate = CLOSED;
325 				} else
326 					nstate = RCV_WAIT;	/* 18 */
327 			else
328 				nstate = TIME_WAIT;
329 			goto done;
330 		}
331 		goto input;
332 
333 	case CLOSING2:
334 		if (ack_fin(tp, n)) {
335 			if (rcv_empty(tp)) {			/* 16 */
336 				tcp_close(tp, UCLOSED);
337 				nstate = CLOSED;
338 			} else
339 				nstate = RCV_WAIT;		/* 19 */
340 			goto done;
341 		}
342 		if (n->th_flags&TH_FIN) {
343 			tcp_sndctl(tp);				/* 31 */
344 			goto done;
345 		}
346 		goto input;
347 
348 	case RCV_WAIT:
349 		if ((n->th_flags&TH_FIN) && (n->th_flags&TH_ACK) &&
350 		    n->t_ackno <= tp->seq_fin) {
351 			tcp_ctldat(tp, n, 0);
352 			tp->t_finack = T_2ML;
353 			tp->tc_flags &= ~TC_WAITED_2_ML;	/* 30 */
354 		}
355 		goto done;
356 	}
357 	panic("tcp_input");
358 done:
359 
360 	/*
361 	 * Done with state*input specific processing.
362 	 * Form trace records, free input if not needed,
363 	 * and enter new state.
364 	 */
365 #ifdef TCPDEBUG
366 	if (tdb.td_tod)
367 		tdb_stuff(&tdb, nstate);
368 #endif
369 	switch (nstate) {
370 
371 	case EFAILEC:
372 		m_freem(mp);
373 		return;
374 
375 	default:
376 		tp->t_state = nstate;
377 		/* fall into ... */
378 
379 	case CLOSED:
380 		/* IF CLOSED CANT LOOK AT tc_flags */
381 		if ((tp->tc_flags&TC_NET_KEEP) == 0)
382 			m_freem(mp);
383 		return;
384 	}
385 	/* NOTREACHED */
386 
387 	/*
388 	 * Unwanted packed; free everything
389 	 * but the header and return an rst.
390 	 */
391 notwanted:
392 	m_freem(mp->m_next);
393 	mp->m_next = NULL;
394 	mp->m_len = sizeof(struct th);
395 #define xchg(a,b) j=a; a=b; b=j
396 	xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src);
397 #undef xchg
398 	if (n->th_flags&TH_ACK)
399 		n->t_seq = n->t_ackno;
400 	else {
401 		n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen);
402 		n->t_seq = 0;
403 	}
404 	n->th_flags = TH_RST; /* not TH_FIN, TH_SYN */
405 	n->th_flags ^= TH_ACK;
406 	n->t_len = htons(TCPSIZE);
407 	n->t_off = 5;
408 	n->t_sum = cksum(mp, sizeof(struct th));
409 	((struct ip *)n)->ip_len = sizeof(struct th);
410 	ip_output(mp);
411 	netstat.t_badsegs++;
412 }
413 
414 tcp_ctldat(tp, n, dataok)
415 	register struct tcb *tp;
416 	register struct th *n;
417 {
418 	register struct mbuf *m;
419 	int sent;
420 COUNT(TCP_CTLDAT);
421 
422 	tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW);
423 /* syn */
424 	if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (n->th_flags&TH_SYN)) {
425 		tp->irs = n->t_seq;
426 		tp->rcv_nxt = n->t_seq + 1;
427 		tp->snd_wl = tp->rcv_urp = tp->irs;
428 		tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE);
429 	}
430 /* ack */
431 	if ((n->th_flags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) &&
432 	    n->t_ackno > tp->snd_una) {
433 		register struct mbuf *mn;
434 		register struct ucb *up;
435 		register int len;
436 
437 		up = tp->t_ucb;
438 
439 		/* update snd_una and snd_nxt */
440 		tp->snd_una = n->t_ackno;
441 		if (tp->snd_una > tp->snd_nxt)
442 			tp->snd_nxt = tp->snd_una;
443 
444 		/* if timed msg acked, set retrans time value */
445 		if ((tp->tc_flags&TC_SYN_ACKED) &&
446 		    tp->snd_una > tp->t_xmt_val) {
447 			tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT);
448 			if (tp->t_xmtime > T_REMAX)
449 				tp->t_xmtime = T_REMAX;
450 		}
451 
452 		/* remove acked data from send buf */
453 		len = tp->snd_una - tp->snd_off;
454 		m = up->uc_sbuf;
455 		while (len > 0 && m != NULL)
456 			if (m->m_len <= len) {
457 				len -= m->m_len;
458 				if (m->m_off > MMAXOFF)
459 					up->uc_ssize -= NMBPG;
460 				MFREE(m, mn);
461 				m = mn;
462 				up->uc_ssize--;
463 			} else {
464 				m->m_len -= len;
465 				m->m_off += len;
466 				break;
467 			}
468 		up->uc_sbuf = m;
469 		tp->snd_off = tp->snd_una;
470 		if ((tp->tc_flags&TC_SYN_ACKED) == 0 &&
471 		    (tp->snd_una > tp->iss)) {
472 			tp->tc_flags |= TC_SYN_ACKED;
473 			tp->t_init = 0;
474 		}
475 		if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin)
476 			tp->tc_flags &= ~TC_SND_FIN;
477 		tp->t_rexmt = 0;
478 		tp->t_rexmttl = 0;
479 		tp->tc_flags |= TC_CANCELLED;
480 		netwakeup(tp->t_ucb);		/* wasteful */
481 	}
482 /* win */
483 	if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) {
484 		tp->snd_wl = n->t_seq;
485 		tp->snd_wnd = n->t_win;
486 		tp->tc_flags |= TC_NEW_WINDOW;
487 		tp->t_persist = 0;
488 	}
489 	if (dataok == 0)
490 		goto ctlonly;
491 /* text */
492 	if (n->t_len == 0)
493 		goto notext;
494 	{ register int i;
495 	  register struct th *p, *q;
496 	  register struct mbuf *m;
497 	  int overage;
498 
499 	/*
500 	 * Discard duplicate data already passed to user.
501 	 */
502 	if (SEQ_LT(n->t_seq, tp->rcv_nxt)) {
503 		i = tp->rcv_nxt - n->t_seq;
504 		if (i >= n->t_len)
505 			goto notext;
506 		n->t_seq += i;
507 		n->t_len -= i;
508 		m_adj(dtom(n), i);
509 	}
510 
511 	/*
512 	 * Find a segment which begins after this one does.
513 	 */
514 	for (q = tp->t_rcv_next; q != (struct th *)tp; q = q->t_next)
515 		if (SEQ_GT(q->t_seq, n->t_seq))
516 			break;
517 
518 	/*
519 	 * If there is a preceding segment, it may provide some of
520 	 * our data already.  If so, drop the data from the incoming
521 	 * segment.  If it provides all of our data, drop us.
522 	 */
523 	if (q->t_prev != (struct th *)tp) {
524 		/* conversion to int (in i) handles seq wraparound */
525 		i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq;
526 		if (i > 0) {
527 			if (i >= n->t_len)
528 				goto notext;	/* w/o setting TC_NET_KEEP */
529 			m_adj(dtom(tp), i);
530 			n->t_len -= i;
531 			n->t_seq += i;
532 		}
533 	}
534 
535 	/*
536 	 * While we overlap succeeding segments trim them or,
537 	 * if they are completely covered, dequeue them.
538 	 */
539 	while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) {
540 		i = (n->t_seq + n->t_len) - q->t_seq;
541 		if (i < q->t_len) {
542 			q->t_len -= i;
543 			m_adj(dtom(q), i);
544 			break;
545 		}
546 		q = q->t_next;
547 		m_freem(dtom(q->t_prev));
548 		remque(q->t_prev);
549 	}
550 
551 	/*
552 	 * Stick new segment in its place.
553 	 */
554 	insque(n, q->t_prev);
555 	tp->seqcnt += n->t_len;
556 
557 #ifdef notdef
558 	/*
559 	 * Calculate available space and discard segments for
560 	 * which there is too much.
561 	 */
562 	q = tp->t_rcv_prev;
563 	overage =
564 	    (tp->t_ucb->uc_rcc + tp->rcv_seqcnt) - tp->t_ucb->uc_rhiwat;
565 	if (overage > 0)
566 		for (;;) {
567 			i = MIN(q->t_len, overage);
568 			overage -= i;
569 			q->t_len -= i;
570 			m_adj(q, -i);
571 			if (q == n)
572 				tp->tc_flags |= TC_DROPPED_TXT;
573 			if (q->t_len)
574 				break;
575 			if (q == n)
576 				panic("tcp_text dropall");
577 			q = q->t_prev;
578 			remque(q->t_next);
579 		}
580 #endif
581 
582 	/*
583 	 * Advance rcv_next through
584 	 * newly completed sequence space
585 	 * and return forcing an ack.
586 	 */
587 	while (n->t_seq == tp->rcv_nxt) {
588 		/* present data belongs here */
589 		tp->rcv_nxt += n->t_len;
590 		n = n->t_next;
591 		if (n == (struct th *)tp)
592 			break;
593 	}
594 	tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP);
595 	}
596 notext:
597 /* urg */
598 	if (n->th_flags&TH_URG) {
599 		unsigned urgent;
600 
601 		urgent = n->t_urp + n->t_seq;
602 		if (tp->rcv_nxt < urgent) {
603 			if (tp->rcv_urp <= tp->rcv_nxt)
604 				to_user(tp->t_ucb, UURGENT);
605 			tp->rcv_urp = urgent;
606 		}
607 	}
608 /* eol */
609 	if ((n->th_flags&TH_EOL) &&
610 	    (tp->tc_flags&TC_DROPPED_TXT) == 0 &&
611 	    tp->t_rcv_prev != (struct th *)tp) {
612 		/* mark last mbuf */
613 		m = dtom(tp->t_rcv_prev);
614 		if (m != NULL) {
615 			while (m->m_next != NULL)
616 				m = m->m_next;
617 			m->m_act =
618 			    (struct mbuf *)(m->m_off + m->m_len - 1);
619 		}
620 	}
621 ctlonly:
622 /* fin */
623 	if ((n->th_flags&TH_FIN) && (tp->tc_flags&TC_DROPPED_TXT) == 0) {
624 		seq_t last;
625 
626 		if ((tp->tc_flags&TC_FIN_RCVD) == 0) {
627 			/* do we really have fin ? */
628 			last = firstempty(tp);
629 			if (tp->t_rcv_prev == (struct th *)tp ||
630 			    last == t_end(tp->t_rcv_prev)) {
631 				tp->tc_flags |= TC_FIN_RCVD;
632 				netwakeup(tp->t_ucb);		/* poke */
633 			}
634 			if ((tp->tc_flags&TC_FIN_RCVD) &&
635 			    tp->rcv_nxt >= last) {
636 				tp->rcv_nxt = last + 1;		/* fin seq */
637 				tp->tc_flags |= TC_ACK_DUE;
638 			}
639 		} else
640 			tp->tc_flags |= TC_ACK_DUE;
641 	}
642 
643 /* respond */
644 	sent = 0;
645 	if (tp->tc_flags&TC_ACK_DUE)
646 		sent = tcp_sndctl(tp);
647 	else if (tp->tc_flags&TC_NEW_WINDOW) {
648 		seq_t last = tp->snd_off;
649 		for (m = tp->t_ucb->uc_sbuf; m != NULL; m = m->m_next)	/*###*/
650 			last += m->m_len;				/*###*/
651 		if (tp->snd_nxt <= last || (tp->tc_flags&TC_SND_FIN))
652 			sent = tcp_send(tp);
653 	}
654 
655 /* set for retrans */
656 	if (!sent && tp->snd_una < tp->snd_nxt &&
657 	    (tp->tc_flags&TC_CANCELLED)) {
658 		tp->t_rexmt = tp->t_xmtime;
659 		tp->t_rexmttl = T_REXMTTL;
660 		tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst;
661 		tp->tc_flags &= ~TC_CANCELLED;
662 	}
663 }
664 
665 present_data(tp)
666 	register struct tcb *tp;
667 {
668 	register struct th *t;
669 	register struct ucb *up;
670 	register struct mbuf *m, **mp;
671 	seq_t ready;
672 COUNT(PRESENT_DATA);
673 
674 	/* connection must be synced and data available for user */
675 	if ((tp->tc_flags&TC_SYN_ACKED) == 0)
676 		return;
677 	up = tp->t_ucb;
678 	mp = &up->uc_rbuf;
679 	while (*mp)
680 		mp = &(*mp)->m_next;
681 	t = tp->t_rcv_next;
682 	/* SHOULD PACK DATA IN HERE */
683 	while (t != (struct th *)tp && t->t_seq < tp->rcv_nxt) {
684 		remque(t);
685 		m = dtom(t);
686 		up->uc_rcc += t->t_len;
687 		tp->seqcnt -= t->t_len;
688 		if (tp->seqcnt < 0) panic("present_data");
689 		t = t->t_next;
690 		while (m) {
691 			if (m->m_len == 0) {
692 				m = m_free(m);
693 				continue;
694 			}
695 			*mp = m;
696 			mp = &m->m_next;
697 			m = *mp;
698 		}
699 	}
700 	if (up->uc_rcc != 0)
701 		netwakeup(up);
702 	if ((tp->tc_flags&TC_FIN_RCVD) &&			/* ### */
703 	    (tp->tc_flags&TC_USR_CLOSED) == 0 &&		/* ### */
704 	    rcv_empty(tp))					/* ### */
705 		to_user(up, UCLOSED);				/* ### */
706 }
707