xref: /csrg-svn/sys/netinet/tcp_usrreq.c (revision 4678)
1 /* tcp_usrreq.c 1.18 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/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_head; tp != NULL; tp = tp->t_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 		present_data(tp);
104 		if (rcv_empty(tp)) {
105 			tcp_close(tp, UCLOSED);
106 			nstate = CLOSED;
107 		} else
108 			nstate = RCV_WAIT;
109 		break;
110 
111 	case FW1_SYR:				/* 24,25 */
112 		tp->tc_flags |= TC_SND_FIN;
113 		tcp_sndctl(tp);
114 		tp->tc_flags |= TC_USR_CLOSED;
115 		nstate = FIN_W1;
116 		break;
117 
118 	case SSS_SND:				/* 40,41 */
119 		nstate = tcp_usrsend(tp, mp);
120 		break;
121 
122 	case SSS_RCV:				/* 42 */
123 		tcp_sndwin(tp);		/* send new window */
124 		present_data(tp);
125 		break;
126 
127 	case CLS_NSY:				/* 44 */
128 		tcp_close(tp, UABORT);
129 		nstate = CLOSED;
130 		break;
131 
132 	case CLS_SYN:				/* 45 */
133 		tp->tc_flags |= TC_SND_RST;
134 		tcp_sndnull(tp);
135 		tcp_close(tp, UABORT);
136 		nstate = CLOSED;
137 		break;
138 
139 	case CLS_ACT:				/* 47 */
140 		tcp_close(tp, UNETDWN);
141 		nstate = CLOSED;
142 		break;
143 
144 	case NOP:
145 		break;
146 
147 	case CLS_ERR:
148 		to_user(tp->t_ucb, UCLSERR);
149 		break;
150 	}
151 #ifdef TCPDEBUG
152 	if (tdb.td_tod)
153 		tdb_stuff(&tdb, nstate);
154 #endif
155 	/* YECH */
156 	switch (nstate) {
157 
158 	case CLOSED:
159 	case SAME:
160 		break;
161 
162 	case EFAILEC:
163 		if (mp)
164 			m_freem(dtom(mp));
165 		break;
166 
167 	default:
168 		tp->t_state = nstate;
169 		break;
170 	}
171 	splx(s);
172 }
173 
174 tcp_open(tp, mode)                /* set up a tcb for a connection */
175 	register struct tcb *tp;
176 	int mode;
177 {
178 	register struct ucb *up;
179 COUNT(T_OPEN);
180 
181 	/* enqueue the tcb */
182 
183 	if (tcb_head == NULL) {
184 		tcb_head = tp;
185 		tcb_tail = tp;
186 	} else {
187 		tp->t_tcb_next = tcb_head;
188 		tcb_head->t_tcb_prev = tp;
189 		tcb_head = tp;
190 	}
191 
192 	/* initialize non-zero tcb fields */
193 
194 	tp->t_rcv_next = (struct th *)tp;
195 	tp->t_rcv_prev = (struct th *)tp;
196 	tp->t_xmtime = T_REXMT;
197 	tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi =
198 	              tp->snd_una = tp->iss = tcp_iss;
199 	tp->snd_off = tp->iss + 1;
200 	tcp_iss += (ISSINCR >> 1) + 1;
201 
202 	/* set timeout for open */
203 
204 	up = tp->t_ucb;
205 	tp->t_init = (up->uc_timeo != 0 ? up->uc_timeo :
206 					(mode == ACTIVE ? T_INIT : 0));
207 	up->uc_timeo = 0;       /* overlays uc_ssize */
208 }
209 
210 tcp_close(tp, state)
211 	register struct tcb *tp;
212 	short state;
213 {
214 	register struct ucb *up;
215 	register struct th *t;
216 	register struct mbuf *m;
217 COUNT(T_CLOSE);
218 
219 	up = tp->t_ucb;
220 
221 	tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist =
222 	    tp->t_finack = 0;
223 
224 	/* delete tcb */
225 
226 	if (tp->t_tcb_prev == NULL)
227 		tcb_head = tp->t_tcb_next;
228 	else
229 		tp->t_tcb_prev->t_tcb_next = tp->t_tcb_next;
230 	if (tp->t_tcb_next == NULL)
231 		tcb_tail = tp->t_tcb_prev;
232 	else
233 		tp->t_tcb_next->t_tcb_prev = tp->t_tcb_prev;
234 
235 	/* free all data on receive and send buffers */
236 
237 	for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
238 		m_freem(dtom(t));
239 
240 	if (up->uc_rbuf != NULL) {
241 		m_freem(up->uc_rbuf);
242 		up->uc_rbuf = NULL;
243 	}
244 	up->uc_rcc = 0;
245 	if (up->uc_sbuf != NULL) {
246 		m_freem(up->uc_sbuf);
247 		up->uc_sbuf = NULL;
248 	}
249 	up->uc_ssize = 0;
250 	for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) {
251 		m_freem(m);
252 		tp->t_rcv_unack = NULL;
253 	}
254 	if (up->uc_template) {
255 		m_free(dtom(up->uc_template));
256 		up->uc_template = 0;
257 	}
258 	wmemfree((caddr_t)tp, 1024);
259 	up->uc_tcb = NULL;
260 
261 	/* lower buffer allocation and decrement host entry */
262 
263 	mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2;
264 	mbstat.m_hiwat = 2 * mbstat.m_lowat;
265 	if (up->uc_host != NULL) {
266 		h_free(up->uc_host);
267 		up->uc_host = NULL;
268 	}
269 
270 	/* if user has initiated close (via close call), delete ucb
271 	   entry, otherwise just wakeup so user can issue close call */
272 
273 	if (tp->tc_flags&TC_USR_ABORT)
274         	up->uc_proc = NULL;
275 	else
276         	to_user(up, state);
277 }
278 
279 tcp_usrsend(tp, m0)
280 	register struct tcb *tp;
281 	struct mbuf *m0;
282 {
283 	register struct mbuf *m, *n;
284 	register struct ucb *up = tp->t_ucb;
285 	register off;
286 	seq_t last;
287 COUNT(SSS_SEND);
288 
289 	last = tp->snd_off;
290 	for (m = n = m0; m != NULL; m = m->m_next) {
291 		up->uc_ssize++;
292 		if (m->m_off > MMAXOFF)
293 			up->uc_ssize += NMBPG;
294 		last += m->m_len;
295 	}
296 	if ((m = up->uc_sbuf) == NULL)
297 		up->uc_sbuf = n;
298 	else {
299 		while (m->m_next != NULL) {
300 			m = m->m_next;
301 			last += m->m_len;
302 		}
303 		if (m->m_off <= MMAXOFF) {
304 			last += m->m_len;
305 			off = m->m_off + m->m_len;
306 			while (n && n->m_off <= MMAXOFF &&
307 			    (MMAXOFF - off) >= n->m_len) {
308 				bcopy((caddr_t)((int)n + n->m_off),
309 				      (caddr_t)((int)m + off), n->m_len);
310 				m->m_len += n->m_len;
311 				off += n->m_len;
312 				up->uc_ssize--;
313 				n = m_free(n);
314 			}
315 		}
316 		m->m_next = n;
317 	}
318 	if (up->uc_flags & UEOL)
319 		tp->snd_end = last;
320 	if (up->uc_flags & UURG) {
321 		tp->snd_urp = last+1;
322 		tp->tc_flags |= TC_SND_URG;
323 	}
324 	tcp_send(tp);
325 	return (SAME);
326 }
327 
328 tcp_timers(tp, timertype)
329 	register struct tcb *tp;
330 	int timertype;
331 {
332 
333 COUNT(TCP_TIMERS);
334 	switch (timertype) {
335 
336 	case TINIT:		/* initialization timer */
337 		if ((tp->tc_flags&TC_SYN_ACKED) == 0) {		/* 35 */
338 			tcp_close(tp, UINTIMO);
339 			return (CLOSED);
340 		}
341 		return (SAME);
342 
343 	case TFINACK:		/* fin-ack timer */
344 		switch (tp->t_state) {
345 
346 		case TIME_WAIT:
347 			/*
348 			 * We can be sure our ACK of foreign FIN was rcvd,
349 			 * and can close if no data left for user.
350 			 */
351 			if (rcv_empty(tp)) {
352 				tcp_close(tp, UCLOSED);		/* 14 */
353 				return (CLOSED);
354 			}
355 			return (RCV_WAIT);			/* 17 */
356 
357 		case CLOSING1:
358 			tp->tc_flags |= TC_WAITED_2_ML;
359 			return (SAME);
360 
361 		default:
362 			return (SAME);
363 		}
364 
365 	case TREXMT:		/* retransmission timer */
366 		if (tp->t_rexmt_val > tp->snd_una) {	 	/* 34 */
367 			/*
368 			 * Set up for a retransmission, increase rexmt time
369 			 * in case of multiple retransmissions.
370 			 */
371 			tp->snd_nxt = tp->snd_una;
372 			tp->tc_flags |= TC_REXMT;
373 			tp->t_xmtime = tp->t_xmtime << 1;
374 			if (tp->t_xmtime > T_REMAX)
375 				tp->t_xmtime = T_REMAX;
376 			tcp_send(tp);
377 		}
378 		return (SAME);
379 
380 	case TREXMTTL:		/* retransmit too long */
381 		if (tp->t_rtl_val > tp->snd_una)		/* 36 */
382 			to_user(tp->t_ucb, URXTIMO);
383 		/*
384 		 * If user has already closed, abort the connection.
385 		 */
386 		if (tp->tc_flags & TC_USR_CLOSED) {
387 			tcp_close(tp, URXTIMO);
388 			return (CLOSED);
389 		}
390 		return (SAME);
391 
392 	case TPERSIST:		/* persist timer */
393 		/*
394 		 * Force a byte send through closed window.
395 		 */
396 		tp->tc_flags |= TC_FORCE_ONE;
397 		tcp_send(tp);
398 		return (SAME);
399 	}
400 	panic("tcp_timers");
401 }
402 
403 /* THIS ROUTINE IS A CROCK */
404 to_user(up, state)
405 	register struct ucb *up;
406 	register short state;
407 {
408 COUNT(TO_USER);
409 
410 	up->uc_state |= state;
411 	netwakeup(up);
412   	if (state == UURGENT)
413 		psignal(up->uc_proc, SIGURG);
414 }
415 
416 #ifdef TCPDEBUG
417 tcp_prt(tdp)
418 	register struct tcp_debug *tdp;
419 {
420 COUNT(TCP_PRT);
421 
422 	printf("TCP(%x) %s x %s",
423 	    tdp->td_tcb, tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
424 	if (tdp->td_inp == ISTIMER)
425 		printf("(%s)", tcptimers[tdp->td_tim]);
426 	printf(" --> %s",
427 	    tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
428 	/* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
429 	if (tdp->td_new < 0)
430 		printf(" (FAILED)");
431 	if (tdp->td_sno) {
432 		printf(" sno %x ano %x win %d len %d flags %x",
433 		    tdp->td_sno, tdp->td_ano, tdp->td_wno, tdp->td_lno, tdp->td_flg);
434 	}
435 	printf("\n");
436 }
437 #endif
438 #ifdef TCPDEBUG
439 tdb_setup(tp, n, input, tdp)
440 	struct tcb *tp;
441 	register struct th *n;
442 	int input;
443 	register struct tcp_debug *tdp;
444 {
445 
446 	tdp->td_tod = time;
447 	tdp->td_tcb = tp;
448 	tdp->td_old = tp->t_state;
449 	tdp->td_inp = input;
450 	tdp->td_tim = 0;
451 	tdp->td_new = -1;
452 	if (n) {
453 		tdp->td_sno = n->t_seq;
454 		tdp->td_ano = n->t_ackno;
455 		tdp->td_wno = n->t_win;
456 		tdp->td_lno = n->t_len;
457 		tdp->td_flg = n->th_flags;
458 	} else
459 		tdp->td_sno = tdp->td_ano = tdp->td_wno = tdp->td_lno =
460 		    tdp->td_flg = 0;
461 }
462 
463 tdb_stuff(tdp, nstate)
464 	struct tcp_debug *tdp;
465 	int nstate;
466 {
467 
468 	tdp->td_new = nstate;
469 	tcp_debug[tdbx++ % TDBSIZE] = *tdp;
470 	if (tcpconsdebug & 2)
471 		tcp_prt(tdp);
472 }
473 #endif
474