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