1 /*
2  $Log:	rdp_states.c,v $
3  * Revision 2.14  85/06/18  14:38:50  walsh
4  * eliminated inpcb flags.
5  *
6  * Revision 2.13  85/05/31  14:39:06  walsh
7  * copy sequential delivery desires when fork off a new socket.
8  *
9  * Revision 2.12  84/12/03  09:42:20  walsh
10  * Keep no route messages from flooding console.
11  *
12  * Revision 2.11  84/11/29  13:06:17  walsh
13  * Have the NULL message retransmission back off so that don't load
14  * a jammed network and so that don't wake user up so often when
15  * some intermediary hop has gone down on a (normally) fast connection.
16  *
17  * Revision 2.10  84/11/15  09:56:14  walsh
18  * redid how we deal with compiler padding in the RDP header structure.
19  *
20  * Revision 2.9  84/11/08  16:12:06  walsh
21  * Added code to gather statistics on RDP traffic.  This makes the RDPCB
22  * too big unles you make mbufs 512 bytes large.  RDP_CS should be turned off
23  * unless you do.
24  *
25  * Revision 2.8  84/11/06  15:24:54  walsh
26  * *** empty log message ***
27  *
28  * Revision 2.7  84/11/05  15:54:34  walsh
29  * update_nulltimer() macro began to look inappropriate with recent
30  * changes, so its been stripped out and put in-line.
31  *
32  * Revision 2.6  84/11/05  12:42:34  walsh
33  * Set things up so can debug RDP connections just like can debug TCP
34  * connections.
35  *
36  * Revision 2.5  84/11/05  11:34:36  walsh
37  * Don't let round trip time estimate drift upward on lossy networks.
38  * Check for retransmissions of packets used to measure round trip time.
39  *
40  * Revision 2.4  84/11/05  10:47:38  walsh
41  * More changes to go with NULL messages getting their own sequence
42  * number.
43  *
44  * Revision 2.3  84/11/02  18:24:20  walsh
45  * Protocol specifiers want NULL message to have own sequence number in
46  * case of slow (t>NULL msg timeout) packets.  I don't see this as a problem,
47  * and even if happened (dubious) would only delay discovery, but I
48  * didn't win this one.  Initially not designed for this, but fixes are
49  * in almost neatly.
50  *
51  * Revision 2.2  84/11/02  15:29:32  walsh
52  * Allow for RDP header fields not on natural boundries.  (Protocol
53  * specifiers say will be part of next version in 6-12 months).
54  * Until then, there goes the speed...  Yucho modifications.
55  *
56  * Revision 2.1  84/11/02  10:14:11  walsh
57  * Fixed to include RCS comments in checked out source.
58  *
59  *
60  * description:
61  * The state transition functions for the Reliable Datagram Protocol.
62  *
63  * revision 1.17
64  * date: 84/07/24 16:58:17;  author: walsh;  state: Exp;  lines added/del: 2/2
65  * When had gone to making retransmit took too long advisory,
66  * had forgotten to change RDP_sCLOSED to RDP_sSAME.
67  *
68  * revision 1.16
69  * date: 84/07/23 12:58:31;  author: walsh;  state: Exp;  lines added/del: 27/6
70  * Clear all timers when enter close state.  Updates to protocol had not
71  * been complete in this respect.
72  *
73  * Retransmission and acceptance in CLOSEWAIT do not seem to be in the cards
74  * in dealing with protocol specifiers, so removed ### markers and commented.
75  *
76  * revision 1.15
77  * date: 84/07/22 19:45:31;  author: walsh;  state: Exp;  lines added/del: 19/0
78  * Added a state transition function rdp_closew_rcv() to compensate for
79  * socket code's dropping of system priority level for a brief period of time.
80  *
81  * revision 1.14
82  * date: 84/07/19 10:21:42;  author: walsh;  state: Exp;  lines added/del: 14/85
83  * Organized macros and classified their definitions in rdp_macros.h.
84  *
85  * revision 1.13
86  * date: 84/07/19 08:54:01;  author: walsh;  state: Exp;  lines added/del: 4/0
87  * NULL message processing should start before receive a packet in ESTAB,
88  * so start up NULL timer when enter ESTAB.
89  *
90  * revision 1.12
91  * date: 84/07/18 18:50:55;  author: walsh;  state: Exp;  lines added/del: 36/5
92  * Added provision for sending of NULL messages.  These are sent on an idle
93  * connection to determine that the other side still exists.
94  *
95  * revision 1.11
96  * date: 84/07/18 13:35:36;  author: walsh;  state: Exp;  lines added/del: 6/6
97  * made provisions for user-adjustable RTTL time period.
98  *
99  * revision 1.10
100  * date: 84/07/13 09:50:33;  author: walsh;  state: Exp;  lines added/del: 22/19
101  * When first send datagram, we determine its length.
102  * Might as wellsave that length in m_act for retransmission.
103  *
104  * revision 1.9
105  * date: 84/07/12 13:48:22;  author: walsh;  state: Exp;  lines added/del: 1/0
106  * Rather than in-line stuffing of IP/RDP headers, at least half of which are
107  * constant, copy headers in from a template of what the headers are like.  The
108  * bcopy() call is turned into a movc3 instruction on the VAX by a sed script
109  * run over the assembler output of the C compiler.  Marginal speed-up.
110  *
111  * revision 1.8
112  * date: 84/07/12 09:55:02;  author: walsh;  state: Exp;  lines added/del: 5/13
113  * some small optimizations.
114  *
115  * revision 1.7
116  * date: 84/07/10 14:48:13;  author: walsh;  state: Exp;  lines added/del: 1/1
117  * Reduced amount of unnecessary wakeup action.
118  *
119  * revision 1.6
120  * date: 84/07/10 10:28:33;  author: walsh;  state: Exp;  lines added/del: 35/35
121  * Added register declarations.
122  *
123  * revision 1.5
124  * date: 84/07/09 14:31:33;  author: walsh;  state: Exp;  lines added/del: 11/2
125  * Added an ACK-delay algorithm to reduce cpu and network loading.
126  *
127  * revision 1.4
128  * date: 84/07/08 21:36:47;  author: walsh;  state: Exp;  lines added/del: 3/3
129  * changed some references to r_sendq.rq_baseseq to r_snduna for clarity.
130  *
131  * revision 1.3
132  * date: 84/07/06 15:13:50;  author: wjacobso;  state: Exp;  lines added/del: 17/17
133  * add register var definitions; use sndnxt-baseseq instead of maxqlen
134  * to determine number of passes
135  *
136  * revision 1.2
137  * date: 84/07/06 09:49:52;  author: root;  state: Exp;  lines added/del: 93/35
138  * This version seems to run bug-free.
139  *
140  * revision 1.1
141  * date: 84/06/26 14:18:09;  author: walsh;  state: Exp;
142  * Initial revision
143  */
144 
145 
146 #ifdef RDP
147 #include "../h/param.h"
148 #include "../h/dir.h"
149 #include "../h/user.h"
150 #include "../h/kernel.h"
151 #include "../h/inode.h"
152 #include "../h/mbuf.h"
153 #include "../h/socket.h"
154 #include "../h/socketvar.h"
155 #include "../h/errno.h"
156 #include "../h/syslog.h"
157 
158 #include "../net/if.h"
159 #include "../net/route.h"
160 
161 #include "../bbnnet/in.h"
162 #include "../bbnnet/net.h"
163 #include "../bbnnet/in_pcb.h"
164 #include "../bbnnet/in_var.h"
165 #include "../bbnnet/ip.h"
166 #include "../bbnnet/rdp.h"
167 #include "../bbnnet/seq.h"
168 #include "../bbnnet/rdp_macros.h"
169 
170 extern struct rtentry *ip_route();
171 
172 /*
173  * Since a message just got through, re-associating rttl (retransmit
174  * took too long) with some other current outstanding datagram (cf. wait
175  * until some new dgram) is a little paranoid, but let's be careful
176  * in case that new dgram doesn't come along for a while.  This also
177  * allows us to decide that the check-for-retransmit and
178  * retransmit-took-too-long timers can be cancelled.
179  */
180 clear_rxtimer(rdpcb, N)
181 register RDPCB	*rdpcb;
182 {
183     int Xi;
184     int pass;
185 
186     rdpcb->r_rxtimers[N] = 0;
187     if (rdpcb->r_rttlindex == N)
188     {
189 	/*
190 	 * look for new dgram of which to check rttl
191 	 */
192 	Xi = rdpcb->r_sendq.rq_front;
193 	pass = rdpcb->r_sndnxt - rdpcb->r_snduna;
194 	while (--pass >= 0)
195 	{
196 	    if (rdpcb->r_rxtimers[Xi])
197 	    {
198 		rdpcb->r_rttlindex = Xi;
199 		rdpcb->r_timers[RDP_tRTTL] = rdpcb->r_rttl;
200 		return;
201 	    }
202 	    Xi = (Xi + 1) % rdpcb->r_sendq.rq_maxqlen;
203 	}
204 	/*
205 	 * No outstanding dgrams left.
206 	 */
207 	rdpcb->r_rttlindex = (-1);
208 	rdpcb->r_timers[RDP_tRTTL] = 0;
209 	rdpcb->r_timers[RDP_tRXMIT] = 0;
210     }
211 }
212 
213 /*
214  * set up things to discover the rtt (round trip time) for this
215  * DATA-containing packet.
216  */
217 #define time_rtt(rdpcb, seqnum) \
218 	if (! (rdpcb)->r_rttiming){            \
219 		(rdpcb)->r_rttiming = TRUE;    \
220 		(rdpcb)->r_rtt = 0;            \
221 		(rdpcb)->r_rttimed = (seqnum); \
222 	}
223 
224 
225 /*
226  * Since we play with sb_cc for the socket send buffer to prevent the
227  * user process from sending packets we can't buffer, must ensure it
228  * is restored to a reasonable value before call upon socket code to clean
229  * up or we'll get a "panic: sbdrop".  Socket code is called by
230  * in_pcbdetach().
231  */
232 trash_pcbs(rdpcb)
233 RDPCB *rdpcb;
234 {
235     register struct sockbuf *sosnd;
236 
237     sosnd = &rdpcb->r_inpcb->inp_socket->so_snd;
238     if ((sosnd->sb_cc == sosnd->sb_hiwat) && (sosnd->sb_mb == NULL))
239 	sosnd->sb_cc = 0;
240     in_pcbdetach (rdpcb->r_inpcb, rdp_pcbdisconnect);
241 }
242 
243 cancel_timers(rdpcb)
244 register RDPCB *rdpcb;
245 {
246     register int i;
247 
248     for (i=0; i<RDP_NTIMERS; i++)
249 	rdpcb->r_timers[i] = 0;
250 }
251 
252 /************************************************************************/
253 
254 /*
255  *	state: RDP_sUNOPENED
256  *	input: RDP_iCONNECT
257  */
258 /*ARGSUSED*/
259 rdp_unop_connect (rdpcb, nil)
260 register RDPCB	*rdpcb;
261 {
262     /*
263      * Send a SYN
264      * and set re-transmission timer to ensure SYN eventually gets there
265      */
266     (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_iss);
267     set_rxtimer (rdpcb, 0);
268     return (RDP_sSYNSENT);
269 }
270 
271 /*
272  *	state: RDP_sUNOPENED
273  *	input: RDP_iLISTEN
274  */
275 /*ARGSUSED*/
276 rdp_unop_listen (rdpcb, nil)
277 RDPCB	*rdpcb;
278 {
279     return (RDP_sLISTEN);
280 }
281 
282 /*
283  *	state: RDP_sUNOPENED
284  *	input: RDP_iNETR
285  */
286 /*ARGSUSED*/
287 rdp_unop_netr (rdpcb, pkt)
288 RDPCB	*rdpcb;
289 register RDPHDR	*pkt;
290 {
291     if (pkt->rh_flags & (RDP_fACK|RDP_fEACK|RDP_fNULL))
292 	/*
293 	 * We haven't sent anything to (e)ack.  Nor have we
294 	 * established a connection and received something
295 	 * that we should ack (null).  The sender is very mixed
296 	 * up, so we'll send him a reset.
297 	 */
298 	rdp_uncon_rst (pkt);
299     else
300 	/*
301 	 * ignore packet in hope user connect(2)s or listen(2)s before
302 	 * it's re-transmission comes in.
303 	 */
304 	m_freem(dtom(pkt));
305 
306     return (RDP_sSAME);
307 }
308 
309 /*
310  *	state: RDP_sUNOPENED
311  *	input: RDP_iUCLOSE
312  */
313 /*ARGSUSED*/
314 rdp_unop_close (rdpcb, nil)
315 RDPCB	*rdpcb;
316 {
317     trash_pcbs(rdpcb);
318     return (RDP_sCLOSED);
319 }
320 
321 /************************************************************************/
322 
323 /*
324  *	state: RDP_sLISTEN
325  *	input: RDP_iLISTEN
326  */
327 /*ARGSUSED*/
328 rdp_lis_listen (rdpcb, nil)
329 RDPCB	*rdpcb;
330 {
331     return (RDP_sSAME);
332 }
333 
334 /*
335  *	state: RDP_sLISTEN
336  *	input: RDP_iNETR
337  */
338 rdp_lis_netr (rdpcb, pkt)
339 RDPCB	*rdpcb;
340 register RDPHDR		*pkt;
341 {
342     INPCB	*inp;
343     struct socket	*so;
344     struct rtentry	*rt;
345     register RDPCB		*newrdpcb;
346     register INPCB		*newinp;
347     struct socket	*newso;
348     register struct ip	*ip;
349     register SYNOPTIONS	*synopt;
350 
351     if (pkt->rh_flags & (RDP_fRST|RDP_fACK|RDP_fEACK|RDP_fNULL))
352     {
353 	if (pkt->rh_flags & RDP_fRST)
354 	    /*
355 	     * Ignore resets since we haven't sent anything to
356 	     * reset.  The packet may be a slow arrival meant to
357 	     * close a child socket of ours that has already
358 	     * finished close protocol with this sender.  We
359 	     * ignore it and the other end closes/closed on its own.
360 	     */
361 	    m_freem(dtom(pkt));
362 	else
363 	    /*
364 	     * We haven't sent anything to (e)ack.  Nor have we
365 	     * established a connection and received something
366 	     * that we should ack (null).  The sender is very mixed
367 	     * up, so we'll send him a reset.
368 	     */
369 	    rdp_uncon_rst (pkt);
370 
371 	return (RDP_sSAME);
372     }
373 
374     if (pkt->rh_flags & RDP_fSYN)
375     {
376 	/* normal case, someone is trying to connect to us. */
377 
378 	ip = (struct ip *) (((char *) pkt) - sizeof(struct ip));
379 
380 	/*
381 	 * O.k., let's get a route back to him
382 	 */
383 	if (!(rt = ip_route(&ip->ip_dst, &ip->ip_src)))
384 	{
385 	    /*
386 	     * Can't talk to him.  Leave socket in receive state
387 	     * so we can connect to someone else, since we haven't
388 	     * been committed to anything yet anyway.
389 	     * Drop his info on the floor.
390 	     * Let the other machine figure out on it's own
391 	     * that it can't reach us that way.
392 	     */
393 	    no_route ("rdp", ip->ip_dst, ip->ip_src);
394 	    m_freem(dtom(pkt));
395 	    return(RDP_sSAME);
396 	}
397 
398 	inp = rdpcb->r_inpcb;
399 	so = inp->inp_socket;
400 
401 	/*
402 	 * This socket is in the listen state, so the socket should have
403 	 * so_options & SO_ACCEPTCONN set (solisten()).
404 	 *
405 	 * The order of sonewconn() and soisconnected() is
406 	 * important, in order for the process to be woken up
407 	 * at a time when the sleep condition is fulfilled.
408 	 * sonewconn() is done here on the original socket, and
409 	 * soisconnected() is done later in rdp_lsynrcvd_netr() on
410 	 * the new socket.
411 	 */
412 	if (newso = sonewconn(so))
413 	{
414 	    newinp = (INPCB *) newso->so_pcb;
415 	    newrdpcb = (RDPCB *) newinp->inp_ppcb;
416 	    /*
417 	     * Remember our peer for this connection.
418 	     */
419 	    newinp->inp_faddr = ip->ip_src;
420 	    newinp->inp_fport = pkt->rh_sport;
421 	    newinp->inp_laddr = ip->ip_dst;
422 	    /*
423 	     * and copy fields into the new inpcb
424 	     */
425 	    newinp->inp_lport = inp->inp_lport;
426 	    newinp->inp_route.ro_rt = rt;
427 	    /*
428 	     * and copy fields into the new rdpcb.  In particular,
429 	     * the user's desired buffering allocations should be
430 	     * propogated.
431 	     */
432 	    newrdpcb->r_ournbuf = rdpcb->r_ournbuf;
433 	    sbreserve (&newrdpcb->r_inpcb->inp_socket->so_rcv,
434 		rdpcb->r_inpcb->inp_socket->so_rcv.sb_hiwat);
435 	    pick_ourmaxlen(newrdpcb);
436 	    /*
437 	     * Sequential delivery is a combination of both side's
438 	     * desires, and must be copied from server socket since
439 	     * user does not have a handle on the child socket in
440 	     * it's early states.
441 	     */
442 	    newrdpcb->r_sequential = rdpcb->r_sequential;
443 
444 	    /*
445 	     * and stuff new information
446 	     */
447 	    got_syn(newrdpcb, RDP_SEQNO(pkt));
448 	    synopt = RDP_OPT(pkt, SYNOPTIONS *);
449 	    process_synopt(newrdpcb, synopt);
450 
451 	    /*
452 	     * So can debug connection problems without having to
453 	     * change every program or apply debugging flag to each
454 	     * program every time run it.
455 	     */
456 	    dowedebug(newinp, newso, &rdp_dfilter);
457 
458 	    /*
459 	     * send other guy our SYN and ACK his syn.
460 	     * set re-transmission timer to ensure eventually gets
461 	     * to him.
462 	     */
463 	    rdp_template(newrdpcb);
464 	    (void) rdp_sendpkt (newrdpcb, (MBUF *) NULL, 0,
465 		newrdpcb->r_iss);
466 	    set_rxtimer (newrdpcb, 0);
467 
468 	    newrdpcb->r_state = RDP_sLSYNRCVD;
469 	}
470 	else
471 	rtfree(rt);
472     }
473     m_freem(dtom(pkt));
474     return (RDP_sSAME);
475 }
476 
477 /*
478  *	state: RDP_sLISTEN
479  *	input: RDP_iUCLOSE
480  */
481 /*ARGSUSED*/
482 rdp_lis_close (rdpcb, nil)
483 RDPCB	*rdpcb;
484 {
485     trash_pcbs(rdpcb);
486     return (RDP_sCLOSED);
487 }
488 
489 /************************************************************************/
490 
491 /*
492  *	state: RDP_sSYNSENT
493  *	input: RDP_iNETR
494  */
495 rdp_synsent_netr (rdpcb, pkt)
496 register RDPCB	*rdpcb;
497 register RDPHDR	*pkt;
498 {
499     register rdpstate newstate;
500 
501     if (pkt->rh_flags & RDP_fACK)
502     {
503 	if (RDP_ACKNO(pkt) != rdpcb->r_iss)
504 	{
505 	    /*
506 	     * We haven't sent any data yet, only SYNs.
507 	     * He's confused.
508 	     */
509 	    rdp_uncon_rst (pkt);
510 	    return (RDP_sSAME);
511 	}
512     }
513 
514     if (pkt->rh_flags & RDP_fRST)
515     {
516 	/*
517 	 * Require (rst, ack, ackno) to know rst meant for this, not
518 	 * a previous, incarnation of the socket.  Is an "in window"
519 	 * check.  Avoids problems with "slow" packets.
520 	 */
521 	if (pkt->rh_flags & RDP_fACK)
522 	{
523 	    set_error (rdpcb, ECONNREFUSED);
524 	    trash_pcbs(rdpcb);
525 	    newstate = RDP_sCLOSED;
526 	}
527 	else
528 	    newstate = RDP_sSAME;
529 	m_freem(dtom(pkt));
530 	return (newstate);
531     }
532 
533     newstate = RDP_sSAME;
534     if (pkt->rh_flags & RDP_fSYN)
535     {
536 	register SYNOPTIONS	*synopt;
537 	rdpsequence seqnum;
538 
539 	got_syn(rdpcb, RDP_SEQNO(pkt));
540 	synopt = RDP_OPT(pkt, SYNOPTIONS *);
541 	process_synopt(rdpcb, synopt);
542 
543 	if (pkt->rh_flags & RDP_fACK)
544 	{
545 	    rdpcb->r_synacked = TRUE;
546 	    rdpisconnected(rdpcb);
547 	    newstate = RDP_sESTAB;
548 	    seqnum = rdpcb->r_iss +1;
549 	    /* clear re-xmit syn timer set in rdp_unop_connect() */
550 	    clear_rxtimer (rdpcb, 0);
551 	    /* start up connection loss detection */
552 	    rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
553 	}
554 	else
555 	{
556 	    newstate = RDP_sSYNRCVD;
557 	    seqnum = rdpcb->r_iss;
558 	    /* keep sending syn until he acks it */
559 	    set_rxtimer (rdpcb, 0);
560 	}
561 	/* and ack his syn, retransmit ours if necessary */
562 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, seqnum);
563     }
564 
565     m_freem(dtom(pkt));
566     return (newstate);
567 }
568 
569 /*
570  *	state: RDP_sSYNSENT
571  *	input: RDP_iUCLOSE
572  */
573 /*ARGSUSED*/
574 rdp_synsent_close (rdpcb, nil)
575 register RDPCB *rdpcb;
576 {
577     /* send RST */
578     rdpcb->r_sendrst = TRUE;
579     (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
580     trash_pcbs(rdpcb);
581     return (RDP_sCLOSED);
582 }
583 
584 
585 /*
586  *	state: RDP_sSYNSENT
587  *	input: RDP_iTIMER
588  */
589 rdp_synsent_timer (rdpcb, timer)
590 register RDPCB *rdpcb;
591 {
592     switch (timer)
593     {
594       case RDP_tRTTL:
595 	/* retransmission took too long */
596 	rttl(rdpcb);
597 	return (RDP_sSAME);
598 
599       case RDP_tRXMIT:
600 	/*
601 	 * re-transmit our SYN.  Not every 0.5 second, though,
602 	 * but every RDP_tvRXMIN units.
603 	 */
604 	rdpcb->r_rxtimers[0] --;
605 	if (rdpcb->r_rxtimers[0] == 0)
606 	{
607 	    (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0,
608 		rdpcb->r_iss);
609 	    set_rxtimer (rdpcb, 0);
610 #ifdef RDP_CS
611 	    rdpcb->r_sent.r_retrans ++;
612 #endif
613 	}
614 	else
615 	    /*
616 	     * ensure keep checking even if no packet goes
617 	     * out this time.  ACK will stop this.
618 	     */
619 	    rdpcb->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK;
620 	break;
621 
622       default:
623 	log(LOG_INFO, "rdp_synsent_timer:  timer %d\n", timer);
624     }
625 
626     return(RDP_sSAME);
627 }
628 
629 /************************************************************************/
630 
631 /*
632  *	state: RDP_sLSYNRCVD
633  *	input: RDP_iNETR
634  */
635 rdp_lsynrcvd_netr (rdpcb, pkt)
636 register RDPCB		*rdpcb;
637 register RDPHDR		*pkt;
638 {
639     /*
640      * If it's a duplicate syn (seqno == irs), re-send ack since he must
641      * have missed our ack.  If it's out of the window, well, let's give
642      * him the benefit of the doubt and assume it's junk from an old
643      * connection/window that took a while to get to us.
644      */
645     if (SEQ_LEQ(RDP_SEQNO(pkt), rdpcb->r_irs) ||
646 	SEQ_GEQ(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq + rdpcb->r_rcvq.rq_maxqlen))
647     {
648 
649 #ifdef RDP_CS
650 	rdpcb->r_rcvd.r_retrans ++;
651 #endif
652 	/* try to synchronize again */
653 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_iss);
654 	m_freem(dtom(pkt));
655 	return(RDP_sSAME);
656     }
657 
658     if (pkt->rh_flags & (RDP_fRST|RDP_fEACK|RDP_fSYN))
659     {
660 	if (pkt->rh_flags & RDP_fRST)
661 	{
662 	    /*
663 	     * User closed while his socket was in synsent state.
664 	     */
665 	    set_error (rdpcb, ECONNREFUSED);
666 	    trash_pcbs(rdpcb);
667 	    m_freem(dtom(pkt));
668 	    return (RDP_sCLOSED);
669 	}
670 	if (pkt->rh_flags & RDP_fEACK)
671 	{
672 	    /*
673 	     * shouldn't be EACK, since we haven't sent anything yet
674 	     */
675 	    rdp_uncon_rst (pkt);	/* frees mbufs for pkt */
676 	    return(RDP_sSAME);
677 	}
678 	if (pkt->rh_flags & RDP_fSYN)
679 	{
680 	    /*
681 	     * Boy, is the other end confused!  His syn has changed
682 	     * sequence numbers.
683 	     */
684 	    rdp_uncon_rst (pkt);
685 	    set_error (rdpcb, ECONNRESET);
686 	    trash_pcbs(rdpcb);
687 	    return (RDP_sCLOSED);
688 	}
689     }
690 
691     if (pkt->rh_flags & RDP_fACK)
692     {
693 	if (RDP_ACKNO(pkt) != rdpcb->r_iss)
694 	{
695 	    rdp_uncon_rst (pkt);	/* frees mbufs for pkt */
696 	    return(RDP_sSAME);
697 	}
698     }
699     else
700     {
701 	m_freem(dtom(pkt));
702 	return(RDP_sSAME);
703     }
704 
705     /*
706      * clear timer for re-transmission of syn that we set in
707      * rdp_lis_netr().
708      */
709     clear_rxtimer (rdpcb, 0);
710     rdpcb->r_synacked = TRUE;
711 
712 
713     if (pkt->rh_dlen > rdpcb->r_ourmaxlen)
714     {
715 	log(LOG_INFO, "RDP too large packet %d > %d\n",
716 	    pkt->rh_dlen, rdpcb->r_ourmaxlen);
717 theygoofed :
718 	rdp_uncon_rst(pkt);
719 	rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait;
720 	set_error(rdpcb, ECONNRESET);
721 	return (RDP_sCLOSEWAIT);
722     }
723     /*
724      * zero length packets can be NULL messages or (E)ACKs,
725      * but all NULL messages must be zero length
726      */
727     if (pkt->rh_flags & RDP_fNULL)
728     {
729 	if (pkt->rh_dlen != 0)
730 	{
731 	    log(LOG_INFO, "RDP %d length NULL packet\n", pkt->rh_dlen);
732 	    goto theygoofed;
733 	}
734 	if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq)
735 	{
736 	    log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n",
737 		RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq);
738 	    goto theygoofed;
739 	}
740 	rdpcb->r_rcvq.rq_msgs[rdpcb->r_rcvq.rq_front] = NULL;
741 	rdpcb->r_rcvq.rq_front =
742 	    (rdpcb->r_rcvq.rq_front +1) % rdpcb->r_rcvq.rq_maxqlen;
743 	rdpcb->r_rcvq.rq_baseseq ++;
744 
745 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
746 	m_freem(dtom(pkt));
747     }
748     else if (pkt->rh_dlen)
749     {
750 #ifdef RDP_CS
751 	if (rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)) == -1)
752 	    rdpcb->r_rcvd.r_retrans ++;
753 #else
754 	(void) rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt));
755 #endif
756 	/* No (e)ack now.  Wait til gets to user */
757     }
758     else
759 	/* Was an ACK-only packet */
760 	m_freem(dtom(pkt));
761 
762 
763     rdpisconnected(rdpcb);
764     /* start up connection loss detection */
765     rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
766     return (RDP_sESTAB);
767 }
768 
769 /*
770  *	state: RDP_sLSYNRCVD
771  *	input: RDP_iUCLOSE
772  */
773 /*ARGSUSED*/
774 rdp_lsynrcvd_close (rdpcb, nil)
775 register RDPCB *rdpcb;
776 {
777     /* send RST */
778     rdpcb->r_sendrst = TRUE;
779     (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
780     trash_pcbs(rdpcb);
781     return (RDP_sCLOSED);
782 }
783 
784 /*
785  *	state: RDP_sLSYNRCVD
786  *	input: RDP_iTIMER
787  */
788 rdp_lsynrcvd_timer (rdpcb, timer)
789 RDPCB	*rdpcb;
790 {
791     /* whether connecting via connect(2) (SYNSENT) or child of
792      * or via child of a listen(2)ing socket (LSYNRCVD), need to
793      * retransmit out syn until it gets acked.
794      */
795 
796 
797     return (rdp_synsent_timer (rdpcb, timer));
798 }
799 
800 /************************************************************************/
801 
802 /*
803  *	state: RDP_sSYNRCVD
804  *	input: RDP_iNETR
805  */
806 rdp_synrcvd_netr (rdpcb, pkt)
807 RDPCB	*rdpcb;
808 RDPHDR	*pkt;
809 {
810     return (rdp_lsynrcvd_netr(rdpcb, pkt));
811 }
812 
813 /*
814  *	state: RDP_sSYNRCVD
815  *	input: RDP_iUCLOSE
816  */
817 rdp_synrcvd_close (rdpcb, nil)
818 RDPCB	*rdpcb;
819 {
820     return (rdp_lsynrcvd_close(rdpcb, nil));
821 }
822 
823 /*
824  *	state: RDP_sSYNRCVD
825  *	input: RDP_iTIMER
826  */
827 rdp_synrcvd_timer (rdpcb, timer)
828 RDPCB	*rdpcb;
829 {
830     return (rdp_lsynrcvd_timer (rdpcb, timer));
831 }
832 
833 /************************************************************************/
834 
835 /*
836  *	state: RDP_sESTAB
837  *	input: RDP_iNETR
838  */
839 rdp_estab_netr (rdpcb, pkt)
840 register RDPCB		*rdpcb;
841 register RDPHDR		*pkt;
842 {
843     /*
844      * ensure packet is in window.  If not, ack him to straighten things
845      * out.
846      */
847     if (SEQ_LT(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq) ||
848 	SEQ_GEQ(RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq + rdpcb->r_rcvq.rq_maxqlen))
849     {
850 #ifdef RDP_CS
851 	rdpcb->r_rcvd.r_retrans ++;
852 #endif
853 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
854 	m_freem(dtom(pkt));
855 	return (RDP_sSAME);
856     }
857 
858     /*
859      * Whenever we receive a packet and we're not already waiting for
860      * an ack of a NULL we sent, reset NULL timer.  Connection is alive.
861      *
862      * Don't reset for any packet if have an outstanding NULL since want
863      * to keep timer at zero and not generate a new NULL segment until
864      * current one is acknowledged.  (This might be a new message, not
865      * the NULL's ack.  Send and receive paths may differ?)
866      *
867      * Don't reset NULL timer on datagram transmissions since those imply
868      * receiving ACKs.  Besides, we want to know if he is up, not if we're
869      * up.
870      */
871     if (rdpcb->r_nullsent == 0)
872 	rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
873 
874     if (pkt->rh_flags &  (RDP_fSYN|RDP_fRST))
875     {
876 	m_freem(dtom(pkt));
877 	set_error(rdpcb, ECONNRESET);
878 
879 	if (pkt->rh_flags & RDP_fSYN)
880 	{
881 	    /*
882 	     * We've gotten past the syn stage.  He's confused.
883 	     * His syn has also changed sequence numbers.
884 	     */
885 	    rdpcb->r_sendrst = TRUE;
886 	    (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
887 	    trash_pcbs(rdpcb);
888 	    return (RDP_sCLOSED);
889 	}
890 
891 	/*
892 	 * Since we've been reset, the user cannot send anymore
893 	 * datagrams.  user_cantsendmore() also wakes writers up
894 	 * in case he is doing synchronous i/o and is waiting for
895 	 * buffering space at the (socket) level.
896 	 */
897 	user_cantsendmore(rdpcb);
898 	/*
899 	 * User can't read anymore either, per specification.
900 	 * Reliable delivery and acceptance must be determined
901 	 * by the application before closing.
902 	 */
903 	user_cantreadmore(rdpcb);
904 	cancel_timers(rdpcb);
905 	rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait;
906 	return (RDP_sCLOSEWAIT);
907     }
908 
909     if (pkt->rh_flags & RDP_fACK)
910 	he_acked (rdpcb, RDP_ACKNO(pkt));
911 
912     if (pkt->rh_flags & RDP_fEACK)
913     {
914 	register int		 neacks;
915 	register EACKOPTIONS	*eackopt;
916 
917 	neacks = (hdrlen(pkt) - RDPHDRSZ) / sizeof(EACKOPTIONS);
918 	eackopt = RDP_OPT(pkt, EACKOPTIONS *);
919 	while (--neacks >= 0)
920 	{
921 	    he_eacked (rdpcb, ntohl(eackopt->rh_eackno));
922 	    eackopt ++;
923 	}
924     }
925 
926     if (pkt->rh_dlen > rdpcb->r_ourmaxlen)
927     {
928 	log(LOG_INFO, "RDP pkt too large %d > %d\n",
929 	    pkt->rh_dlen, rdpcb->r_ourmaxlen);
930 theygoofed :
931 	rdp_uncon_rst(pkt);
932 	set_error(rdpcb, ECONNRESET);
933 	user_cantsendmore(rdpcb);
934 	user_cantreadmore(rdpcb);
935 	cancel_timers(rdpcb);
936 	rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait;
937 	return (RDP_sCLOSEWAIT);
938     }
939 
940     if (pkt->rh_flags & RDP_fNULL)
941     {
942 	if (pkt->rh_dlen != 0)
943 	{
944 	    log(LOG_INFO, "RDP %d length NULL pkt\n", pkt->rh_dlen);
945 	    goto theygoofed;
946 	}
947 	if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq)
948 	{
949 	    log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n",
950 		RDP_SEQNO(pkt), rdpcb->r_rcvq.rq_baseseq);
951 	    goto theygoofed;
952 	}
953 	rdpcb->r_rcvq.rq_msgs[rdpcb->r_rcvq.rq_front] = NULL;
954 	rdpcb->r_rcvq.rq_front =
955 	    (rdpcb->r_rcvq.rq_front +1) % rdpcb->r_rcvq.rq_maxqlen;
956 	rdpcb->r_rcvq.rq_baseseq ++;
957 
958 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
959 	m_freem(dtom(pkt));
960     }
961     else if (pkt->rh_dlen)
962     {
963 #ifdef RDP_CS
964 	if (rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt)) == -1)
965 	    rdpcb->r_rcvd.r_retrans ++;
966 #else
967 	(void) rdp_qinsert (&rdpcb->r_rcvq, dtom(pkt), RDP_SEQNO(pkt));
968 #endif
969     }
970     else
971 	/* Was an ACK-only packet */
972 	m_freem(dtom(pkt));
973 
974 
975     if (usr_rbuf_is_empty(rdpcb))
976     {
977 	register MBUF *m;
978 
979 	if (m = rdp_qremove(&rdpcb->r_rcvq, !rdpcb->r_sequential))
980 	{
981 	    /*
982 	     * IP and RDP headers should be in the first mbuf.
983 	     * User does not see them.
984 	     */
985 	    pkt = (RDPHDR *) (mtod(m, char *) + sizeof(struct ip));
986 #ifdef RDP_CS
987 	    rdpcb->r_rcvd.r_nbytes += pkt->rh_dlen;
988 #endif
989 	    m->m_off += sizeof(struct ip) + hdrlen(pkt);
990 	    m->m_len -= sizeof(struct ip) + hdrlen(pkt);
991 
992 	    usr_rbuf_append(rdpcb, m);
993 	    wakeup_reader(rdpcb);
994 	}
995     }
996 
997     /*
998      * datagrams go straight out in response to the send(2) PRU_SEND,
999      * so getting (e)acks doesn't cause an outgoing datagram.
1000      * Hold off on (e)ack of incoming packet until user receives it
1001      * and we know that by PRU_RCV.
1002      */
1003     return (RDP_sSAME);
1004 }
1005 
1006 /*
1007  *	state: RDP_sESTAB
1008  *	input: RDP_iUCLOSE
1009  */
1010 /*ARGSUSED*/
1011 rdp_estab_close (rdpcb, nil)
1012 register RDPCB *rdpcb;
1013 {
1014     /* send RST */
1015     rdpcb->r_sendrst = TRUE;
1016     (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
1017 
1018     /*
1019      * Don't retransmit unacked datagrams, since user can't pick them
1020      * up anymore once he's been reset (according to specification).
1021      * Reliable delivery and acceptance must be determined by the
1022      * application before closing.
1023      */
1024     cancel_timers(rdpcb);
1025     rdpcb->r_timers[RDP_tCLOSEWAIT] = rdpcb->r_closewait;
1026     return (RDP_sCLOSEWAIT);
1027 }
1028 
1029 /*
1030  *	state: RDP_sESTAB
1031  *	input: RDP_iTIMER
1032  */
1033 rdp_estab_timer (rdpcb, timer)
1034 register RDPCB	*rdpcb;
1035 {
1036     register MBUF	*rxmit_data;
1037     register int	index, passes;
1038     rdpsequence	seqno;
1039 
1040     switch (timer)
1041     {
1042       case RDP_tRTTL:
1043 	/* retransmission took too long */
1044 	rttl(rdpcb);
1045 	return (RDP_sSAME);
1046 
1047       case RDP_tRXMIT:
1048 	/*
1049 	 * ensure keep checking even if no packet goes
1050 	 * out this time.  ACK will stop this.
1051 	 */
1052 	rdpcb->r_timers[RDP_tRXMIT] = RDP_tvRXCHECK;
1053 
1054 	index	= rdpcb->r_sendq.rq_front;
1055 	passes	= rdpcb->r_sndnxt - rdpcb->r_snduna;
1056 	seqno	= rdpcb->r_sendq.rq_baseseq; /* == r_snduna */
1057 
1058 	while (--passes >= 0)
1059 	{
1060 	    if (rdpcb->r_rxtimers[index])
1061 	    {
1062 		rdpcb->r_rxtimers[index] --;
1063 		if (rdpcb->r_rxtimers[index] == 0)
1064 		{
1065 		    MBUF *m;
1066 
1067 		    /*
1068 		     * Over lossy networks, do not let
1069 		     * the round trip time estimate
1070 		     * drift unecessarily high.  If we're
1071 		     * considering the round-trip-time-
1072 		     * measuring packet lost, and are
1073 		     * retransmitting it, then we should
1074 		     * reset the round trip time measurment
1075 		     */
1076 		    if (rdpcb->r_rttiming)
1077 			if (seqno == rdpcb->r_rttimed)
1078 			    rdpcb->r_rttiming = FALSE;
1079 
1080 		    m = rdpcb->r_sendq.rq_msgs[index];
1081 		    if (m == RDP_NULLMSG)
1082 		    {
1083 			rdpcb->r_sendnull = TRUE;
1084 			if (rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, seqno) == 0)
1085 			    time_rtt(rdpcb, seqno);
1086 
1087 			/*
1088 			 * Back off on retransmissions,
1089 			 * because the host might be
1090 			 * down or the network could be
1091 			 * jammed.  rxmitime will drop
1092 			 * to normal when we get the ACK
1093 			 */
1094 			rdpcb->r_rxmitime = MIN (RDP_tvRXMAX,
1095 						 rdpcb->r_rxmitime << 1);
1096 
1097 			if (++rdpcb->r_nullsent > RDP_MAXNULL)
1098 			{
1099 			    /* advisory only */
1100 			    set_error(rdpcb, ETIMEDOUT);
1101 			    wakeup_reader(rdpcb);
1102 			    /* writer timeout via rttl */
1103 
1104 			    /* avoid rollover to zero
1105 			     *
1106 			     * NOTE: user will get
1107 			     * ETIMEDOUT on every
1108 			     * rxmit, another reason
1109 			     * to back off above.
1110 			     */
1111 			    rdpcb->r_nullsent --;
1112 			}
1113 		    }
1114 		    else
1115 		    {
1116 			if (rxmit_data =m_copy(m, 0, M_COPYALL))
1117 			    /*
1118 			     * When we 1st sent it, we
1119 			     * remembered the len in m_act
1120 			     */
1121 			    if (rdp_sendpkt(rdpcb,rxmit_data,(int)m->m_act,seqno)==0)
1122 			        time_rtt(rdpcb, seqno);
1123 
1124 			/*
1125 			 * We aren't backing off here,
1126 			 * since the single number is
1127 			 * used for all datagrams,
1128 			 * each of which may be at a
1129 			 * different nth rxmission
1130 			 */
1131 		    }
1132 
1133 #ifdef RDP_CS
1134 		    rdpcb->r_sent.r_retrans ++;
1135 #endif
1136 		    set_rxtimer (rdpcb, index);
1137 		}
1138 	    }
1139 	    index = (index + 1) % rdpcb->r_sendq.rq_maxqlen;
1140 	    seqno ++;
1141 	}
1142 	break;
1143 
1144       case RDP_tACKDELAY:
1145 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
1146 	break;
1147 
1148       case RDP_tNULL:
1149 	/*
1150 	 * If we're retransmitting, then we don't need to
1151 	 * send NULL messages.  The NULL timer drops to zero
1152 	 * and gets restarted when we get some packet from
1153 	 * them (rdp_estab_netr).  User will get ETIMEDOUT
1154 	 * from retransmit took too long if we don't get a
1155 	 * packet.
1156 	 */
1157 	if (rdpcb->r_rttlindex < 0)
1158 	{
1159 	    /* are not retransmitting */
1160 
1161 	    /*
1162 	     * Idea:  The connection has been idle for too
1163 	     * long. send a NULL packet which has its own
1164 	     * sequence number (so can distinguish slow to
1165 	     * arrive ack from ack of this NULL) and
1166 	     * retransmit it via normal packet
1167 	     * retransmission algorithm.
1168 	     */
1169 
1170 	    if (rdp_qinsert(&rdpcb->r_sendq, RDP_NULLMSG, rdpcb->r_sndnxt) != 1)
1171 		panic("rdp RDP_tNULL");
1172 
1173 	    rdpcb->r_sendnull = TRUE;
1174 	    (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
1175 	    index = rdpcb->r_sendq.rq_front + (rdpcb->r_sndnxt - rdpcb->r_snduna);
1176 	    index %= rdpcb->r_sendq.rq_maxqlen;
1177 	    set_rxtimer (rdpcb, index);
1178 	    rdpcb->r_sndnxt ++;
1179 	    rdpcb->r_nullsent = 1;
1180 	}
1181 	break;
1182 
1183       default:
1184 	log(LOG_INFO, "rdp_estab_timer:  timer %d\n", timer);
1185     }
1186 
1187     return(RDP_sSAME);
1188 }
1189 
1190 /*
1191  *	state: RDP_sESTAB
1192  *	input: RDP_iRCV
1193  */
1194 /*ARGSUSED*/
1195 rdp_estab_rcv (rdpcb, nil)
1196 register RDPCB	*rdpcb;
1197 {
1198     MBUF	*m;
1199 
1200     /*
1201      * Now that user has received the packet, bump the front so that
1202      * we can ACK it and move the window along.
1203      */
1204     rdp_received (&rdpcb->r_rcvq);
1205 
1206     /*
1207      * user picked up the packet we left on the socket for him.
1208      * Let's put another one there.
1209      */
1210     if (m = rdp_qremove(&rdpcb->r_rcvq, !rdpcb->r_sequential))
1211     {
1212 	RDPHDR *pkt;
1213 
1214 	/*
1215 	 * IP and RDP headers should be in the first mbuf.
1216 	 * User does not see them.
1217 	 */
1218 	pkt = (RDPHDR *) (mtod(m, char *) + sizeof(struct ip));
1219 #ifdef RDP_CS
1220 	rdpcb->r_rcvd.r_nbytes += pkt->rh_dlen;
1221 #endif
1222 	m->m_off += sizeof(struct ip) + hdrlen(pkt);
1223 	m->m_len -= sizeof(struct ip) + hdrlen(pkt);
1224 
1225 	usr_rbuf_append(rdpcb, m);
1226 	/* wakeup_reader(rdpcb); is awake, performing read(2) */
1227     }
1228 
1229     /*
1230      * Send an ACK, but apply an ACK-delay algorithm in order to
1231      * reduce CPU loading on both hosts involved.  Reduces network
1232      * load, too.  Skip at most one ACK.
1233      */
1234     if (rdpcb->r_timers[RDP_tACKDELAY])
1235 	(void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
1236     else
1237 	rdpcb->r_timers[RDP_tACKDELAY] = 1;
1238 
1239     return (RDP_sSAME);
1240 }
1241 
1242 /*
1243  *	state: RDP_sESTAB
1244  *	input: RDP_iSEND
1245  */
1246 rdp_estab_send (rdpcb, m)
1247 register RDPCB	*rdpcb;
1248 register MBUF	*m;
1249 {
1250     register MBUF	*copym;
1251     register int	 len;
1252     register int	 index;
1253 
1254     /*
1255      * q message on send q.
1256      */
1257     if (rdp_qinsert(&rdpcb->r_sendq, m, rdpcb->r_sndnxt) != 1)
1258 	panic("rdp_estab_send");
1259 
1260     /*
1261      * Remember the length of the datagram for sending now,
1262      * and for retransmissions later.
1263      */
1264     len = 0;
1265     for (copym = m; copym; copym = copym->m_next)
1266 	len += copym->m_len;
1267     m->m_act = ((MBUF *) len);
1268 
1269     /*
1270      * if reached end of window, block socket code from allowing
1271      * sends until get an ACK
1272      */
1273     if (SEQ_GEQ(rdpcb->r_sndnxt, rdpcb->r_snduna + rdpcb->r_hisnbuf -1))
1274 	sendbufisfull(rdpcb);
1275 
1276     /*
1277      * send a copy of the datagram
1278      */
1279     if (copym = m_copy(m, 0, M_COPYALL))
1280 	if (rdp_sendpkt(rdpcb, copym, len, rdpcb->r_sndnxt) == 0)
1281 	    time_rtt (rdpcb, rdpcb->r_sndnxt);
1282 
1283     index = rdpcb->r_sendq.rq_front + (rdpcb->r_sndnxt - rdpcb->r_snduna);
1284     index %= rdpcb->r_sendq.rq_maxqlen;
1285     set_rxtimer(rdpcb, index);
1286 
1287     rdpcb->r_sndnxt ++;
1288 
1289     return (RDP_sSAME);
1290 }
1291 
1292 /************************************************************************/
1293 
1294 /*
1295  *	state: RDP_sCLOSEWAIT
1296  *	input: RDP_iNETR
1297  */
1298 rdp_closew_netr (rdpcb, pkt)
1299 RDPCB	*rdpcb;
1300 RDPHDR	*pkt;
1301 {
1302     rdpstate newstate;
1303 
1304     if (pkt->rh_flags & RDP_fRST)
1305     {
1306 	/*
1307 	 * We've both agreed to shut down the connection
1308 	 */
1309 	trash_pcbs(rdpcb);
1310 	newstate = RDP_sCLOSED;
1311     }
1312     else
1313 	newstate = RDP_sSAME;
1314 
1315     m_freem(dtom(pkt));
1316     return(newstate);
1317 }
1318 
1319 /*
1320  *	state: RDP_sCLOSEWAIT
1321  *	input: RDP_iUCLOSE
1322  */
1323 /*ARGSUSED*/
1324 rdp_closew_close (rdpcb, nil)
1325 register RDPCB *rdpcb;
1326 {
1327     /*
1328      * rdp_usrreq() only allows one close call to the finite state machine.
1329      * Therefore, we entered CLOSEWAIT in response to a RST, not a close.
1330      * So, now both sides agree to close co-operatively.
1331      */
1332     rdpcb->r_sendrst = TRUE;
1333     (void) rdp_sendpkt (rdpcb, (MBUF *) NULL, 0, rdpcb->r_sndnxt);
1334 
1335     trash_pcbs(rdpcb);
1336     return(RDP_sCLOSED);
1337 }
1338 
1339 /*
1340  *	state: RDP_sCLOSEWAIT
1341  *	input: RDP_iTIMER
1342  */
1343 rdp_closew_timer (rdpcb, timer)
1344 RDPCB	*rdpcb;
1345 {
1346     if (timer != RDP_tCLOSEWAIT)
1347     {
1348 	log(LOG_INFO, "rdp_closew_timer:  timer %d\n", timer);
1349 	return(RDP_sSAME);
1350     }
1351 
1352     trash_pcbs(rdpcb);
1353     return(RDP_sCLOSED);
1354 }
1355 
1356 /*
1357  *	state: RDP_sCLOSEWAIT
1358  *	input: RDP_iRCV
1359  */
1360 /*ARGSUSED*/
1361 rdp_closew_rcv(rdpcb, nil)
1362 {
1363     /*
1364      * Technically, an illegal transition.  However, socket code drops
1365      * system priority level, allowing processing of a network packet
1366      * containing RDP reset to cause ESTAB -> CLOSEWAIT in the middle of
1367      * passing the user a packet.
1368      *
1369      * ESTAB ... user receives packet, priority dropped for uiomove()
1370      *      --- network packet processed ---
1371      * CLOSEWAIT ... socket code continues, causing this action.
1372      *
1373      * ### This can be a serious problem in general.
1374      */
1375 }
1376 #endif
1377