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