xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 4735)
1 /* tcp_usrreq.c 1.25 81/11/04 */
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/ip.h"
11 #include "../inet/tcp.h"
12 #define TCPFSTAB
13 #ifdef TCPDEBUG
14 #define TCPSTATES
15 #endif
16 #include "../inet/tcp_fsm.h"
17 
18 /*
19  * Tcp finite state machine entries for timer and user generated
20  * requests.  These routines raise the ipl to that of the network
21  * to prevent reentry.  In particluar, this requires that the software
22  * clock interrupt have lower priority than the network so that
23  * we can enter the network from timeout routines without improperly
24  * nesting the interrupt stack.
25  */
26 
27 /*
28  * Tcp protocol timeout routine called once per second.
29  * Updates the timers in all active tcb's and
30  * causes finite state machine actions if timers expire.
31  */
32 tcp_timeo()
33 {
34 	register struct tcb *tp;
35 	int s = splnet();
36 	register u_char *tmp;
37 	register int i;
38 COUNT(TCP_TIMEO);
39 
40 	/*
41 	 * Search through tcb's and update active timers.
42 	 */
43 	for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) {
44 		tmp = &tp->t_init;
45 		for (i = 0; i < TNTIMERS; i++) {
46 			if (*tmp && --*tmp == 0)
47 				tcp_usrreq(ISTIMER, i, tp, 0);
48 			tmp++;
49 		}
50 		tp->t_xmt++;
51 	}
52 	tcp_iss += ISSINCR;		/* increment iss */
53 	timeout(tcp_timeo, 0, hz);      /* reschedule every second */
54 	splx(s);
55 }
56 
57 /*
58  * Cancel all timers for tcp tp.
59  */
60 tcp_tcancel(tp)
61 	struct tcb *tp;
62 {
63 	register u_char *tmp = &tp->t_init;
64 	register int i;
65 
66 	for (i = 0; i < TNTIMERS; i++)
67 		*tmp++ = 0;
68 }
69 
70 /*
71  * Process a TCP user request for tcp tb.  If this is a send request
72  * then m is the mbuf chain of send data.  If this is a timer expiration
73  * (called from the software clock routine), then timertype tells which timer.
74  */
75 tcp_usrreq(input, timertype, tp, m)
76 	int input, timertype;
77 	register struct tcb *tp;
78 	struct mbuf *m;
79 {
80 	int s = splnet();
81 	register int nstate;
82 #ifdef TCPDEBUG
83 	struct tcp_debug tdb;
84 #endif
85 COUNT(TCP_USRREQ);
86 
87 	nstate = tp->t_state;
88 	tp->tc_flags &= ~TC_NET_KEEP;
89 #ifdef KPROF
90 	acounts[nstate][input]++;
91 #endif
92 #ifdef TCPDEBUG
93 	if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) {
94 		tdb_setup(tp, (struct th *)0, input, &tdb);
95 		tdb.td_tim = timertype;
96 	} else
97 		tdb.td_tod = 0;
98 #endif
99 	switch (input) {
100 
101 	/*
102 	 * Passive open.  Create a tcp control block
103 	 * and enter listen state.
104 	 */
105 	case IUOPENA:
106 		if (nstate != 0 && nstate != CLOSED)
107 			goto bad;
108 		tcp_open(tp, PASSIVE);
109 		nstate = LISTEN;
110 		break;
111 
112 	/*
113 	 * Active open.  Create a tcp control block,
114 	 * send a SYN and enter SYN_SENT state.
115 	 */
116 	case IUOPENR:
117 		if (nstate != 0 && nstate != CLOSED)
118 			goto bad;
119 		tcp_open(tp, ACTIVE);
120 		tcp_sndctl(tp);
121 		nstate = SYN_SENT;
122 		break;
123 
124 	/*
125 	 * Tcp close call.  Can be generated by a user ioctl (half-close),
126 	 * or when higher level close occurs, if a close hasn't happened
127 	 * already.
128 	 */
129 	case IUCLOSE:
130 		switch (nstate) {
131 
132 		/*
133 		 * If we are aborting out of a listener or a active
134 		 * connection which has not yet completed we can just
135 		 * delete the tcb.
136 		 */
137 		case LISTEN:
138 		case SYN_SENT:
139 			tcp_close(tp, UCLOSED);
140 			nstate = CLOSED;
141 			break;
142 
143 		/*
144 		 * If we have gotten as far as receiving a syn from
145 		 * our foreign peer, we must be sure to send a FIN.
146 		 * If we have gotten a FIN from the foreign peer already
147 		 * (CLOSE_WAIT state), then all that remains is to wait
148 		 * for his ack of the FIN (LAST_ACK state).  If we have
149 		 * not gotten a FIN from the foreign peer then we need
150 		 * to either:
151 		 *	1. rcv ack of our FIN (to FIN_W2) and then
152 		 *	   send an ACK (to TIME_WAIT) and timeout at 2*MSL.
153 		 * or	2. receive hist FIN (to CLOSING), send an ACK
154 		 *	   (to TIME_WAIT), and then timeout.
155 		 * In any case this starts with a transition to FIN_W1 here.
156 		 */
157 		case SYN_RCVD:
158 		case L_SYN_RCVD:
159 		case ESTAB:
160 		case CLOSE_WAIT:
161 			tp->tc_flags |= TC_SND_FIN;
162 			tcp_sndctl(tp);
163 			tp->tc_flags |= TC_USR_CLOSED;
164 			nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
165 			break;
166 
167 		/*
168 		 * In these states the user has already closed;
169 		 * trying to close again is an error.
170 		 */
171 		case FIN_W1:
172 		case FIN_W2:
173 		case TIME_WAIT:
174 		case CLOSING:
175 		case LAST_ACK:
176 		case RCV_WAIT:
177 			to_user(tp->t_ucb, UCLSERR);
178 			break;
179 
180 		default:
181 			goto bad;
182 		}
183 		break;
184 
185 	/*
186 	 * TCP Timer processing.
187 	 * Timers should expire only on open connections
188 	 * not in LISTEN state.
189 	 */
190 	case ISTIMER:
191 		switch (nstate) {
192 
193 		case 0:
194 		case CLOSED:
195 		case LISTEN:
196 			goto bad;
197 
198 		default:
199 			nstate = tcp_timers(tp, timertype);
200 		}
201 		break;
202 
203 	/*
204 	 * User notification of more window availability after
205 	 * reading out data.  This should not happen before a connection
206 	 * is established or after it is closed.
207 	 * If the foreign peer has closed and the local entity
208 	 * has not, inform him of the FIN (give end of file).
209 	 * If the local entity is in RCV_WAIT state (draining data
210 	 * out of the TCP buffers after foreign close) and there
211 	 * is no more data, institute a close.
212 	 */
213 	case IURECV:
214 		if (nstate < ESTAB || nstate == CLOSED)
215 			goto bad;
216 		tcp_sndwin(tp);
217 		if ((tp->tc_flags&TC_FIN_RCVD) &&
218 		    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
219 		    rcv_empty(tp))
220 			to_user(tp, UCLOSED);
221 		if (nstate == RCV_WAIT && rcv_empty(tp)) {
222 			tcp_close(tp, UCLOSED);
223 			nstate = CLOSED;
224 		}
225 		break;
226 
227 	/*
228 	 * Send request on open connection.
229 	 * Should not happen if the connection is not yet established.
230 	 * Allowed only on ESTAB connection and after FIN from
231 	 * foreign peer.
232 	 */
233 	case IUSEND:
234 		switch (nstate) {
235 
236 		case ESTAB:
237 		case CLOSE_WAIT:
238 			nstate = tcp_usrsend(tp, m);
239 			break;
240 
241 		default:
242 			if (nstate < ESTAB)
243 				goto bad;
244 			to_user(tp, UCLSERR);
245 			break;
246 		}
247 		break;
248 
249 	/*
250 	 * User abort of connection.
251 	 * If a SYN has been received, but we have not exchanged FINs
252 	 * then we need to send an RST.  In any case we then
253 	 * enter closed state.
254 	 */
255 	case IUABORT:
256 		if (nstate == 0 || nstate == CLOSED)
257 			break;
258 		switch (nstate) {
259 
260 		case 0:
261 		case CLOSED:
262 			break;
263 
264 		case SYN_RCVD:
265 		case ESTAB:
266 		case FIN_W1:
267 		case FIN_W2:
268 		case CLOSE_WAIT:
269 			tp->tc_flags |= TC_SND_RST;
270 			tcp_sndnull(tp);
271 			/* fall into ... */
272 
273 		default:
274 			tcp_close(tp, UABORT);
275 			nstate = CLOSED;
276 		}
277 		break;
278 
279 	/*
280 	 * Network down entry.  Discard the tcb and force
281 	 * the state to be closed, ungracefully.
282 	 */
283 	case INCLEAR:
284 		if (nstate == 0 || nstate == CLOSED)
285 			break;
286 		tcp_close(tp, UNETDWN);
287 		nstate = CLOSED;
288 		break;
289 
290 	default:
291 		panic("tcp_usrreq");
292 	bad:
293 		printf("tcp: bad state: tcb=%x state=%d input=%d\n",
294 		    tp, tp->t_state, input);
295 		nstate = EFAILEC;
296 		break;
297 	}
298 #ifdef TCPDEBUG
299 	if (tdb.td_tod)
300 		tdb_stuff(&tdb, nstate);
301 #endif
302 	/* YECH */
303 	switch (nstate) {
304 
305 	case CLOSED:
306 	case SAME:
307 		break;
308 
309 	case EFAILEC:
310 		if (m)
311 			m_freem(dtom(m));
312 		break;
313 
314 	default:
315 		tp->t_state = nstate;
316 		break;
317 	}
318 	splx(s);
319 }
320 
321 /*
322  * Open routine, called to initialize newly created tcb fields.
323  */
324 tcp_open(tp, mode)
325 	register struct tcb *tp;
326 	int mode;
327 {
328 	register struct ucb *up = tp->t_ucb;
329 COUNT(TCP_OPEN);
330 
331 	/*
332 	 * Link in tcb queue and make
333 	 * initialize empty reassembly queue.
334 	 */
335 	tp->tcb_next = tcb.tcb_next;
336 	tcb.tcb_next->tcb_prev = tp;
337 	tp->tcb_prev = (struct tcb *)&tcb;
338 	tcb.tcb_next = tp;
339 	tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp;
340 
341 	/*
342 	 * Initialize sequence numbers and
343 	 * round trip retransmit timer.
344 	 * (Other fields were init'd to zero when tcb allocated.)
345 	 */
346 	tp->t_xmtime = T_REXMT;
347 	tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
348 	    tp->iss = tcp_iss;
349 	tp->snd_off = tp->iss + 1;
350 	tcp_iss += (ISSINCR >> 1) + 1;
351 
352 	/*
353 	 * Set timeout for open.
354 	 * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO.
355 	 */
356 	if (up->uc_timeo)
357 		tp->t_init = up->uc_timeo;
358 	else if (mode == ACTIVE)
359 		tp->t_init = T_INIT;
360 	/* else
361 		tp->t_init = 0; */
362 	up->uc_timeo = 0;				/* ### */
363 }
364 
365 /*
366  * Internal close of a connection, shutting down the tcb.
367  */
368 tcp_close(tp, state)
369 	register struct tcb *tp;
370 	short state;
371 {
372 	register struct ucb *up = tp->t_ucb;
373 	register struct th *t;
374 	register struct mbuf *m;
375 COUNT(TCP_CLOSE);
376 
377 	/*
378 	 * Remove from tcb queue and cancel timers.
379 	 */
380 	tp->tcb_prev->tcb_next = tp->tcb_next;
381 	tp->tcb_next->tcb_prev = tp->tcb_prev;
382 	tcp_tcancel(tp);
383 
384 	/*
385 	 * Discard all buffers.
386 	 */
387 	for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
388 		m_freem(dtom(t));
389 	if (up->uc_rbuf) {
390 		m_freem(up->uc_rbuf);
391 		up->uc_rbuf = NULL;
392 	}
393 	up->uc_rcc = 0;
394 	if (up->uc_sbuf) {
395 		m_freem(up->uc_sbuf);
396 		up->uc_sbuf = NULL;
397 	}
398 	up->uc_ssize = 0;
399 	for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) {
400 		m_freem(m);
401 		tp->t_rcv_unack = NULL;
402 	}
403 
404 	/*
405 	 * Free tcp send template, the tcb itself,
406 	 * the routing table entry, and the space we had reserved
407 	 * in the meory pool.
408 	 */
409 	if (tp->t_template) {
410 		m_free(dtom(tp->t_template));
411 		tp->t_template = 0;
412 	}
413 	wmemfree((caddr_t)tp, 1024);
414 	up->uc_pcb = 0;
415 	if (up->uc_host) {
416 		h_free(up->uc_host);
417 		up->uc_host = 0;
418 	}
419 	m_release(up->uc_snd + (up->uc_rhiwat/MSIZE) + 2);
420 
421 	/*
422 	 * If user has initiated close (via close call), delete ucb
423 	 * entry, otherwise just wakeup so user can issue close call
424 	 */
425 	if (tp->tc_flags&TC_USR_ABORT)			/* ### */
426         	up->uc_proc = NULL;			/* ### */
427 	else						/* ### */
428         	to_user(up, state);			/* ### */
429 }
430 
431 /*
432  * Send data queue headed by m0 into the protocol.
433  */
434 tcp_usrsend(tp, m0)
435 	register struct tcb *tp;
436 	struct mbuf *m0;
437 {
438 	register struct mbuf *m, *n;
439 	register struct ucb *up = tp->t_ucb;
440 	register off;
441 	seq_t last;
442 COUNT(TCP_USRSEND);
443 
444 	last = tp->snd_off;
445 	for (m = n = m0; m != NULL; m = m->m_next) {
446 		up->uc_ssize++;
447 		if (m->m_off > MMAXOFF)
448 			up->uc_ssize += NMBPG;
449 		last += m->m_len;
450 	}
451 	if ((m = up->uc_sbuf) == NULL)
452 		up->uc_sbuf = n;
453 	else {
454 		while (m->m_next != NULL) {
455 			m = m->m_next;
456 			last += m->m_len;
457 		}
458 		if (m->m_off <= MMAXOFF) {
459 			last += m->m_len;
460 			off = m->m_off + m->m_len;
461 			while (n && n->m_off <= MMAXOFF &&
462 			    (MMAXOFF - off) >= n->m_len) {
463 				bcopy((caddr_t)((int)n + n->m_off),
464 				      (caddr_t)((int)m + off), n->m_len);
465 				m->m_len += n->m_len;
466 				off += n->m_len;
467 				up->uc_ssize--;
468 				n = m_free(n);
469 			}
470 		}
471 		m->m_next = n;
472 	}
473 	if (up->uc_flags & UEOL)
474 		tp->snd_end = last;
475 	if (up->uc_flags & UURG) {
476 		tp->snd_urp = last+1;
477 		tp->tc_flags |= TC_SND_URG;
478 	}
479 	tcp_send(tp);
480 	return (SAME);
481 }
482 
483 /*
484  * TCP timer went off processing.
485  */
486 tcp_timers(tp, timertype)
487 	register struct tcb *tp;
488 	int timertype;
489 {
490 
491 COUNT(TCP_TIMERS);
492 	switch (timertype) {
493 
494 	case TINIT:		/* initialization timer */
495 		if ((tp->tc_flags&TC_SYN_ACKED) == 0) {		/* 35 */
496 			tcp_close(tp, UINTIMO);
497 			return (CLOSED);
498 		}
499 		return (SAME);
500 
501 	case TFINACK:		/* fin-ack timer */
502 		switch (tp->t_state) {
503 
504 		case TIME_WAIT:
505 			/*
506 			 * We can be sure our ACK of foreign FIN was rcvd,
507 			 * and can close if no data left for user.
508 			 */
509 			if (rcv_empty(tp)) {
510 				tcp_close(tp, UCLOSED);		/* 14 */
511 				return (CLOSED);
512 			}
513 			return (RCV_WAIT);			/* 17 */
514 
515 		case CLOSING:
516 			tp->tc_flags |= TC_WAITED_2_ML;
517 			return (SAME);
518 
519 		default:
520 			return (SAME);
521 		}
522 
523 	case TREXMT:		/* retransmission timer */
524 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
525 			/*
526 			 * Set up for a retransmission, increase rexmt time
527 			 * in case of multiple retransmissions.
528 			 */
529 			tp->snd_nxt = tp->snd_una;
530 			tp->tc_flags |= TC_REXMT;
531 			tp->t_xmtime = tp->t_xmtime << 1;
532 			if (tp->t_xmtime > T_REMAX)
533 				tp->t_xmtime = T_REMAX;
534 			tcp_send(tp);
535 		}
536 		return (SAME);
537 
538 	case TREXMTTL:		/* retransmit too long */
539 		if (tp->t_rtl_val > tp->snd_una)		/* 36 */
540 			to_user(tp->t_ucb, URXTIMO);
541 		/*
542 		 * If user has already closed, abort the connection.
543 		 */
544 		if (tp->tc_flags & TC_USR_CLOSED) {
545 			tcp_close(tp, URXTIMO);
546 			return (CLOSED);
547 		}
548 		return (SAME);
549 
550 	case TPERSIST:		/* persist timer */
551 		/*
552 		 * Force a byte send through closed window.
553 		 */
554 		tp->tc_flags |= TC_FORCE_ONE;
555 		tcp_send(tp);
556 		return (SAME);
557 	}
558 	panic("tcp_timers");
559 }
560 
561 /* THIS ROUTINE IS A CROCK */
562 to_user(up, state)
563 	register struct ucb *up;
564 	register short state;
565 {
566 COUNT(TO_USER);
567 
568 	up->uc_state |= state;
569 	netwakeup(up);
570   	if (state == UURGENT)
571 		psignal(up->uc_proc, SIGURG);
572 }
573 
574 #ifdef TCPDEBUG
575 /*
576  * TCP debugging utility subroutines.
577  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
578  */
579 tdb_setup(tp, n, input, tdp)
580 	struct tcb *tp;
581 	register struct th *n;
582 	int input;
583 	register struct tcp_debug *tdp;
584 {
585 
586 COUNT(TDB_SETUP);
587 	tdp->td_tod = time;
588 	tdp->td_tcb = tp;
589 	tdp->td_old = tp->t_state;
590 	tdp->td_inp = input;
591 	tdp->td_tim = 0;
592 	tdp->td_new = -1;
593 	if (n) {
594 		tdp->td_sno = n->t_seq;
595 		tdp->td_ano = n->t_ackno;
596 		tdp->td_wno = n->t_win;
597 		tdp->td_lno = n->t_len;
598 		tdp->td_flg = n->th_flags;
599 	} else
600 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
601 		    tdp->td_flg = 0;
602 }
603 
604 tdb_stuff(tdp, nstate)
605 	struct tcp_debug *tdp;
606 	int nstate;
607 {
608 COUNT(TDB_STUFF);
609 
610 	tdp->td_new = nstate;
611 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
612 	if (tcpconsdebug & 2)
613 		tcp_prt(tdp);
614 }
615 
616 tcp_prt(tdp)
617 	register struct tcp_debug *tdp;
618 {
619 COUNT(TCP_PRT);
620 
621 	printf("%x ", ((int)tdp->td_tcb)&0xffffff);
622 	if (tdp->td_inp == INSEND) {
623 		printf("SEND #%x", tdp->td_sno);
624 		tdp->td_lno = ntohs(tdp->td_lno);
625 		tdp->td_wno = ntohs(tdp->td_wno);
626 	} else {
627 		if (tdp->td_inp == INRECV)
628 			printf("RCV #%x ", tdp->td_sno);
629 		printf("%s.%s",
630 		    tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
631 		if (tdp->td_inp == ISTIMER)
632 			printf("(%s)", tcptimers[tdp->td_tim]);
633 		printf(" -> %s",
634 		    tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
635 		if (tdp->td_new == -1)
636 			printf(" (FAILED)");
637 	}
638 	/* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
639 	if (tdp->td_lno)
640 		printf(" len=%d", tdp->td_lno);
641 	if (tdp->td_wno)
642 		printf(" win=%d", tdp->td_wno);
643 	if (tdp->td_flg & TH_FIN) printf(" FIN");
644 	if (tdp->td_flg & TH_SYN) printf(" SYN");
645 	if (tdp->td_flg & TH_RST) printf(" RST");
646 	if (tdp->td_flg & TH_EOL) printf(" EOL");
647 	if (tdp->td_flg & TH_ACK)  printf(" ACK %x", tdp->td_ano);
648 	if (tdp->td_flg & TH_URG) printf(" URG");
649 	printf("\n");
650 }
651 #endif
652