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