xref: /original-bsd/sys/netinet/tcp_usrreq.c (revision 0e8da966)
1 /* tcp_usrreq.c 1.22 81/10/31 */
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 COUNT(TCP_TIMEO);
23 
24 	/*
25 	 * Search through tcb's and update active timers.
26 	 */
27 	for (tp = tcb.tcb_next; tp != (struct tcb *)&tcb; tp = tp->tcb_next) {
28 		if (tp->t_init != 0 && --tp->t_init == 0)
29 			tcp_usrreq(ISTIMER, TINIT, tp, 0);
30 		if (tp->t_rexmt != 0 && --tp->t_rexmt == 0)
31 			tcp_usrreq(ISTIMER, TREXMT, tp, 0);
32 		if (tp->t_rexmttl != 0 && --tp->t_rexmttl == 0)
33 			tcp_usrreq(ISTIMER, TREXMTTL, tp, 0);
34 		if (tp->t_persist != 0 && --tp->t_persist == 0)
35 			tcp_usrreq(ISTIMER, TPERSIST, tp, 0);
36 		if (tp->t_finack != 0 && --tp->t_finack == 0)
37 			tcp_usrreq(ISTIMER, TFINACK, tp, 0);
38 		tp->t_xmt++;
39 	}
40 	tcp_iss += ISSINCR;		/* increment iss */
41 	timeout(tcp_timeo, 0, hz);      /* reschedule every second */
42 	splx(s);
43 }
44 
45 tcp_usrreq(input, timertype, tp, mp)
46 	int input, timertype;
47 	register struct tcb *tp;
48 	struct mbuf *mp;
49 {
50 	int s = splnet();
51 	register int nstate;
52 #ifdef TCPDEBUG
53 	struct tcp_debug tdb;
54 #endif
55 COUNT(TCP_USRREQ);
56 
57 	nstate = tp->t_state;
58 	tp->tc_flags &= ~TC_NET_KEEP;
59 	acounts[nstate][input]++;
60 #ifdef TCPDEBUG
61 	if ((tp->t_ucb->uc_flags & UDEBUG) || tcpconsdebug) {
62 		tdb_setup(tp, (struct th *)0, input, &tdb);
63 		tdb.td_tim = timertype;
64 	} else
65 		tdb.td_tod = 0;
66 #endif
67 	switch (tcp_fstab[nstate][input]) {
68 
69 	default:
70 		printf("tcp: bad state: tcb=%x state=%d input=%d\n",
71 		    tp, tp->t_state, input);
72 		nstate = EFAILEC;
73 		break;
74 
75 	case LIS_CLS:				/* 1 */
76 		tcp_open(tp, PASSIVE);
77 		nstate = LISTEN;
78 		break;
79 
80 	case SYS_CLS:				/* 2 */
81 		tcp_open(tp, ACTIVE);
82 		tcp_sndctl(tp);
83 		nstate = SYN_SENT;
84 		break;
85 
86 	case CLS_OPN:				/* 10 */
87 		tcp_close(tp, UCLOSED);
88 		nstate = CLOSED;
89 		break;
90 
91 	case CL2_CLW:				/* 10 */
92 		tp->tc_flags |= TC_SND_FIN;
93 		tcp_sndctl(tp);
94 		tp->tc_flags |= TC_USR_CLOSED;
95 		nstate = CLOSING2;
96 		break;
97 
98 	case TIMERS:				/* 14,17,34,35,36,37,38 */
99 		nstate = tcp_timers(tp, timertype);
100 		break;
101 
102 	case CLS_RWT:				/* 20 */
103 		if ((tp->tc_flags&TC_FIN_RCVD) &&
104 		    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
105 		    rcv_empty(tp))
106 			to_user(tp, UCLOSED);
107 		if (rcv_empty(tp)) {
108 			tcp_close(tp, UCLOSED);
109 			nstate = CLOSED;
110 		} else
111 			nstate = RCV_WAIT;
112 		break;
113 
114 	case FW1_SYR:				/* 24,25 */
115 		tp->tc_flags |= TC_SND_FIN;
116 		tcp_sndctl(tp);
117 		tp->tc_flags |= TC_USR_CLOSED;
118 		nstate = FIN_W1;
119 		break;
120 
121 	case SSS_SND:				/* 40,41 */
122 		nstate = tcp_usrsend(tp, mp);
123 		break;
124 
125 	case SSS_RCV:				/* 42 */
126 		tcp_sndwin(tp);		/* send new window */
127 		if ((tp->tc_flags&TC_FIN_RCVD) &&
128 		    (tp->tc_flags&TC_USR_CLOSED) == 0 &&
129 		    rcv_empty(tp))
130 			to_user(tp, UCLOSED);
131 		break;
132 
133 	case CLS_NSY:				/* 44 */
134 		tcp_close(tp, UABORT);
135 		nstate = CLOSED;
136 		break;
137 
138 	case CLS_SYN:				/* 45 */
139 		tp->tc_flags |= TC_SND_RST;
140 		tcp_sndnull(tp);
141 		tcp_close(tp, UABORT);
142 		nstate = CLOSED;
143 		break;
144 
145 	case CLS_ACT:				/* 47 */
146 		tcp_close(tp, UNETDWN);
147 		nstate = CLOSED;
148 		break;
149 
150 	case NOP:
151 		break;
152 
153 	case CLS_ERR:
154 		to_user(tp->t_ucb, UCLSERR);
155 		break;
156 	}
157 #ifdef TCPDEBUG
158 	if (tdb.td_tod)
159 		tdb_stuff(&tdb, nstate);
160 #endif
161 	/* YECH */
162 	switch (nstate) {
163 
164 	case CLOSED:
165 	case SAME:
166 		break;
167 
168 	case EFAILEC:
169 		if (mp)
170 			m_freem(dtom(mp));
171 		break;
172 
173 	default:
174 		tp->t_state = nstate;
175 		break;
176 	}
177 	splx(s);
178 }
179 
180 /*
181  * Open routine, called to initialize newly created tcb fields.
182  */
183 tcp_open(tp, mode)
184 	register struct tcb *tp;
185 	int mode;
186 {
187 	register struct ucb *up = tp->t_ucb;
188 COUNT(TCP_OPEN);
189 
190 	/*
191 	 * Link in tcb queue and make
192 	 * initialize empty reassembly queue.
193 	 */
194 	tp->tcb_next = tcb.tcb_next;
195 	tcb.tcb_next->tcb_prev = tp;
196 	tp->tcb_prev = (struct tcb *)&tcb;
197 	tcb.tcb_next = tp;
198 	tp->t_rcv_next = tp->t_rcv_prev = (struct th *)tp;
199 
200 	/*
201 	 * Initialize sequence numbers and
202 	 * round trip retransmit timer.
203 	 * (Other fields were init'd to zero when tcb allocated.)
204 	 */
205 	tp->t_xmtime = T_REXMT;
206 	tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
207 	    tp->iss = tcp_iss;
208 	tp->snd_off = tp->iss + 1;
209 	tcp_iss += (ISSINCR >> 1) + 1;
210 
211 	/*
212 	 * Set timeout for open.
213 	 * SHOULD THIS BE A HIGHER LEVEL FUNCTION!?! THINK SO.
214 	 */
215 	if (up->uc_timeo)
216 		tp->t_init = up->uc_timeo;
217 	else if (mode == ACTIVE)
218 		tp->t_init = T_INIT;
219 	/* else
220 		tp->t_init = 0; */
221 	up->uc_timeo = 0;				/* ### */
222 }
223 
224 /*
225  * Internal close of a connection, shutting down the tcb.
226  */
227 tcp_close(tp, state)
228 	register struct tcb *tp;
229 	short state;
230 {
231 	register struct ucb *up = tp->t_ucb;
232 	register struct th *t;
233 	register struct mbuf *m;
234 COUNT(TCP_CLOSE);
235 
236 	/*
237 	 * Cancel all timers.
238 	 * SHOULD LOOP HERE !?!
239 	 */
240 	tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist =
241 	    tp->t_finack = 0;
242 
243 	/*
244 	 * Remque the tcb
245 	 */
246 	tp->tcb_prev->tcb_next = tp->tcb_next;
247 	tp->tcb_next->tcb_prev = tp->tcb_prev;
248 
249 	/*
250 	 * Discard all buffers...
251 	 *
252 	 * SHOULD COUNT EACH RESOURCE TO 0 AND PANIC IF CONFUSED
253 	 */
254 	for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
255 		m_freem(dtom(t));
256 	if (up->uc_rbuf != NULL) {
257 		m_freem(up->uc_rbuf);
258 		up->uc_rbuf = NULL;
259 	}
260 	up->uc_rcc = 0;
261 	if (up->uc_sbuf != NULL) {
262 		m_freem(up->uc_sbuf);
263 		up->uc_sbuf = NULL;
264 	}
265 	up->uc_ssize = 0;
266 	for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) {
267 		m_freem(m);
268 		tp->t_rcv_unack = NULL;
269 	}
270 
271 	/*
272 	 * Free tcp send template.
273 	 */
274 	if (up->uc_template) {
275 		m_free(dtom(up->uc_template));
276 		up->uc_template = 0;
277 	}
278 
279 	/*
280 	 * Free the tcb
281 	 * WOULD THIS BETTER BE DONE AT USER CLOSE?
282 	 */
283 	wmemfree((caddr_t)tp, 1024);
284 	up->uc_tcb = NULL;
285 
286 	/*
287 	 * Lower buffer allocation.
288 	 * SHOULD BE A M_ROUTINE CALL.
289 	 */
290 	mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2;
291 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
292 
293 	/*
294 	 * Free routing table entry.
295 	 */
296 	if (up->uc_host != NULL) {
297 		h_free(up->uc_host);
298 		up->uc_host = NULL;
299 	}
300 
301 	/*
302 	 * If user has initiated close (via close call), delete ucb
303 	 * entry, otherwise just wakeup so user can issue close call
304 	 */
305 	if (tp->tc_flags&TC_USR_ABORT)
306         	up->uc_proc = NULL;
307 	else
308         	to_user(up, state);			/* ### */
309 }
310 
311 /*
312  * User routine to send data queue headed by m0 into the protocol.
313  */
314 tcp_usrsend(tp, m0)
315 	register struct tcb *tp;
316 	struct mbuf *m0;
317 {
318 	register struct mbuf *m, *n;
319 	register struct ucb *up = tp->t_ucb;
320 	register off;
321 	seq_t last;
322 COUNT(TCP_USRSEND);
323 
324 	last = tp->snd_off;
325 	for (m = n = m0; m != NULL; m = m->m_next) {
326 		up->uc_ssize++;
327 		if (m->m_off > MMAXOFF)
328 			up->uc_ssize += NMBPG;
329 		last += m->m_len;
330 	}
331 	if ((m = up->uc_sbuf) == NULL)
332 		up->uc_sbuf = n;
333 	else {
334 		while (m->m_next != NULL) {
335 			m = m->m_next;
336 			last += m->m_len;
337 		}
338 		if (m->m_off <= MMAXOFF) {
339 			last += m->m_len;
340 			off = m->m_off + m->m_len;
341 			while (n && n->m_off <= MMAXOFF &&
342 			    (MMAXOFF - off) >= n->m_len) {
343 				bcopy((caddr_t)((int)n + n->m_off),
344 				      (caddr_t)((int)m + off), n->m_len);
345 				m->m_len += n->m_len;
346 				off += n->m_len;
347 				up->uc_ssize--;
348 				n = m_free(n);
349 			}
350 		}
351 		m->m_next = n;
352 	}
353 	if (up->uc_flags & UEOL)
354 		tp->snd_end = last;
355 	if (up->uc_flags & UURG) {
356 		tp->snd_urp = last+1;
357 		tp->tc_flags |= TC_SND_URG;
358 	}
359 	tcp_send(tp);
360 	return (SAME);
361 }
362 
363 /*
364  * TCP timer went off processing.
365  */
366 tcp_timers(tp, timertype)
367 	register struct tcb *tp;
368 	int timertype;
369 {
370 
371 COUNT(TCP_TIMERS);
372 	switch (timertype) {
373 
374 	case TINIT:		/* initialization timer */
375 		if ((tp->tc_flags&TC_SYN_ACKED) == 0) {		/* 35 */
376 			tcp_close(tp, UINTIMO);
377 			return (CLOSED);
378 		}
379 		return (SAME);
380 
381 	case TFINACK:		/* fin-ack timer */
382 		switch (tp->t_state) {
383 
384 		case TIME_WAIT:
385 			/*
386 			 * We can be sure our ACK of foreign FIN was rcvd,
387 			 * and can close if no data left for user.
388 			 */
389 			if (rcv_empty(tp)) {
390 				tcp_close(tp, UCLOSED);		/* 14 */
391 				return (CLOSED);
392 			}
393 			return (RCV_WAIT);			/* 17 */
394 
395 		case CLOSING1:
396 			tp->tc_flags |= TC_WAITED_2_ML;
397 			return (SAME);
398 
399 		default:
400 			return (SAME);
401 		}
402 
403 	case TREXMT:		/* retransmission timer */
404 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
405 			/*
406 			 * Set up for a retransmission, increase rexmt time
407 			 * in case of multiple retransmissions.
408 			 */
409 			tp->snd_nxt = tp->snd_una;
410 			tp->tc_flags |= TC_REXMT;
411 			tp->t_xmtime = tp->t_xmtime << 1;
412 			if (tp->t_xmtime > T_REMAX)
413 				tp->t_xmtime = T_REMAX;
414 			tcp_send(tp);
415 		}
416 		return (SAME);
417 
418 	case TREXMTTL:		/* retransmit too long */
419 		if (tp->t_rtl_val > tp->snd_una)		/* 36 */
420 			to_user(tp->t_ucb, URXTIMO);
421 		/*
422 		 * If user has already closed, abort the connection.
423 		 */
424 		if (tp->tc_flags & TC_USR_CLOSED) {
425 			tcp_close(tp, URXTIMO);
426 			return (CLOSED);
427 		}
428 		return (SAME);
429 
430 	case TPERSIST:		/* persist timer */
431 		/*
432 		 * Force a byte send through closed window.
433 		 */
434 		tp->tc_flags |= TC_FORCE_ONE;
435 		tcp_send(tp);
436 		return (SAME);
437 	}
438 	panic("tcp_timers");
439 }
440 
441 /* THIS ROUTINE IS A CROCK */
442 to_user(up, state)
443 	register struct ucb *up;
444 	register short state;
445 {
446 COUNT(TO_USER);
447 
448 	up->uc_state |= state;
449 	netwakeup(up);
450   	if (state == UURGENT)
451 		psignal(up->uc_proc, SIGURG);
452 }
453 
454 #ifdef TCPDEBUG
455 /*
456  * TCP debugging utility subroutines.
457  * THE NAMES OF THE FIELDS USED BY THESE ROUTINES ARE STUPID.
458  */
459 tdb_setup(tp, n, input, tdp)
460 	struct tcb *tp;
461 	register struct th *n;
462 	int input;
463 	register struct tcp_debug *tdp;
464 {
465 
466 COUNT(TDB_SETUP);
467 	tdp->td_tod = time;
468 	tdp->td_tcb = tp;
469 	tdp->td_old = tp->t_state;
470 	tdp->td_inp = input;
471 	tdp->td_tim = 0;
472 	tdp->td_new = -1;
473 	if (n) {
474 		tdp->td_sno = n->t_seq;
475 		tdp->td_ano = n->t_ackno;
476 		tdp->td_wno = n->t_win;
477 		tdp->td_lno = n->t_len;
478 		tdp->td_flg = n->th_flags;
479 	} else
480 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
481 		    tdp->td_flg = 0;
482 }
483 
484 tdb_stuff(tdp, nstate)
485 	struct tcp_debug *tdp;
486 	int nstate;
487 {
488 COUNT(TDB_STUFF);
489 
490 	tdp->td_new = nstate;
491 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
492 	if (tcpconsdebug & 2)
493 		tcp_prt(tdp);
494 }
495 
496 tcp_prt(tdp)
497 	register struct tcp_debug *tdp;
498 {
499 COUNT(TCP_PRT);
500 
501 	printf("%x ", ((int)tdp->td_tcb)&0xffffff);
502 	if (tdp->td_inp == INSEND) {
503 		printf("SEND #%x", tdp->td_sno);
504 		tdp->td_lno = ntohs(tdp->td_lno);
505 		tdp->td_wno = ntohs(tdp->td_wno);
506 	} else {
507 		if (tdp->td_inp == INRECV)
508 			printf("RCV #%x ", tdp->td_sno);
509 		printf("%s.%s",
510 		    tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
511 		if (tdp->td_inp == ISTIMER)
512 			printf("(%s)", tcptimers[tdp->td_tim]);
513 		printf(" -> %s",
514 		    tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
515 		if (tdp->td_new == -1)
516 			printf(" (FAILED)");
517 	}
518 	/* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
519 	if (tdp->td_lno)
520 		printf(" len=%d", tdp->td_lno);
521 	if (tdp->td_wno)
522 		printf(" win=%d", tdp->td_wno);
523 	if (tdp->td_flg & TH_FIN) printf(" FIN");
524 	if (tdp->td_flg & TH_SYN) printf(" SYN");
525 	if (tdp->td_flg & TH_RST) printf(" RST");
526 	if (tdp->td_flg & TH_EOL) printf(" EOL");
527 	if (tdp->td_flg & TH_ACK)  printf(" ACK %x", tdp->td_ano);
528 	if (tdp->td_flg & TH_URG) printf(" URG");
529 	printf("\n");
530 }
531 #endif
532