have to leave instrs.adb around, kernel uses it for kdb
[unix-history] / usr / src / sys / deprecated / bbnnet / rdp_states.c
CommitLineData
17efd7fe
MK
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
170extern 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 */
180clear_rxtimer(rdpcb, N)
181register 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 */
232trash_pcbs(rdpcb)
233RDPCB *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
243cancel_timers(rdpcb)
244register 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*/
259rdp_unop_connect (rdpcb, nil)
260register 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*/
276rdp_unop_listen (rdpcb, nil)
277RDPCB *rdpcb;
278{
279 return (RDP_sLISTEN);
280}
281
282/*
283 * state: RDP_sUNOPENED
284 * input: RDP_iNETR
285 */
286/*ARGSUSED*/
287rdp_unop_netr (rdpcb, pkt)
288RDPCB *rdpcb;
289register 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*/
314rdp_unop_close (rdpcb, nil)
315RDPCB *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*/
328rdp_lis_listen (rdpcb, nil)
329RDPCB *rdpcb;
330{
331 return (RDP_sSAME);
332}
333
334/*
335 * state: RDP_sLISTEN
336 * input: RDP_iNETR
337 */
338rdp_lis_netr (rdpcb, pkt)
339RDPCB *rdpcb;
340register 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*/
482rdp_lis_close (rdpcb, nil)
483RDPCB *rdpcb;
484{
485 trash_pcbs(rdpcb);
486 return (RDP_sCLOSED);
487}
488
489/************************************************************************/
490
491/*
492 * state: RDP_sSYNSENT
493 * input: RDP_iNETR
494 */
495rdp_synsent_netr (rdpcb, pkt)
496register RDPCB *rdpcb;
497register 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*/
574rdp_synsent_close (rdpcb, nil)
575register 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 */
589rdp_synsent_timer (rdpcb, timer)
590register 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:
8902c2d0 623 log(LOG_INFO, "rdp_synsent_timer: timer %d\n", timer);
17efd7fe
MK
624 }
625
626 return(RDP_sSAME);
627}
628
629/************************************************************************/
630
631/*
632 * state: RDP_sLSYNRCVD
633 * input: RDP_iNETR
634 */
635rdp_lsynrcvd_netr (rdpcb, pkt)
636register RDPCB *rdpcb;
637register 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 {
8902c2d0 715 log(LOG_INFO, "RDP too large packet %d > %d\n",
17efd7fe
MK
716 pkt->rh_dlen, rdpcb->r_ourmaxlen);
717theygoofed :
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 {
8902c2d0 731 log(LOG_INFO, "RDP %d length NULL packet\n", pkt->rh_dlen);
17efd7fe
MK
732 goto theygoofed;
733 }
734 if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq)
735 {
8902c2d0 736 log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n",
17efd7fe
MK
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*/
774rdp_lsynrcvd_close (rdpcb, nil)
775register 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 */
788rdp_lsynrcvd_timer (rdpcb, timer)
789RDPCB *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 */
806rdp_synrcvd_netr (rdpcb, pkt)
807RDPCB *rdpcb;
808RDPHDR *pkt;
809{
810 return (rdp_lsynrcvd_netr(rdpcb, pkt));
811}
812
813/*
814 * state: RDP_sSYNRCVD
815 * input: RDP_iUCLOSE
816 */
817rdp_synrcvd_close (rdpcb, nil)
818RDPCB *rdpcb;
819{
820 return (rdp_lsynrcvd_close(rdpcb, nil));
821}
822
823/*
824 * state: RDP_sSYNRCVD
825 * input: RDP_iTIMER
826 */
827rdp_synrcvd_timer (rdpcb, timer)
828RDPCB *rdpcb;
829{
830 return (rdp_lsynrcvd_timer (rdpcb, timer));
831}
832
833/************************************************************************/
834
835/*
836 * state: RDP_sESTAB
837 * input: RDP_iNETR
838 */
839rdp_estab_netr (rdpcb, pkt)
840register RDPCB *rdpcb;
841register 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 {
8902c2d0 928 log(LOG_INFO, "RDP pkt too large %d > %d\n",
17efd7fe
MK
929 pkt->rh_dlen, rdpcb->r_ourmaxlen);
930theygoofed :
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 {
8902c2d0 944 log(LOG_INFO, "RDP %d length NULL pkt\n", pkt->rh_dlen);
17efd7fe
MK
945 goto theygoofed;
946 }
947 if (RDP_SEQNO(pkt) != rdpcb->r_rcvq.rq_baseseq)
948 {
8902c2d0 949 log(LOG_INFO, "RDP NULL 0x%x rcvq baseseq 0x%x\n",
17efd7fe
MK
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*/
1011rdp_estab_close (rdpcb, nil)
1012register 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 */
1033rdp_estab_timer (rdpcb, timer)
1034register 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:
8902c2d0 1184 log(LOG_INFO, "rdp_estab_timer: timer %d\n", timer);
17efd7fe
MK
1185 }
1186
1187 return(RDP_sSAME);
1188}
1189
1190/*
1191 * state: RDP_sESTAB
1192 * input: RDP_iRCV
1193 */
1194/*ARGSUSED*/
1195rdp_estab_rcv (rdpcb, nil)
1196register 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 */
1246rdp_estab_send (rdpcb, m)
1247register RDPCB *rdpcb;
1248register 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 */
1298rdp_closew_netr (rdpcb, pkt)
1299RDPCB *rdpcb;
1300RDPHDR *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*/
1324rdp_closew_close (rdpcb, nil)
1325register 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 */
1343rdp_closew_timer (rdpcb, timer)
1344RDPCB *rdpcb;
1345{
1346 if (timer != RDP_tCLOSEWAIT)
1347 {
8902c2d0 1348 log(LOG_INFO, "rdp_closew_timer: timer %d\n", timer);
17efd7fe
MK
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*/
1361rdp_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