home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / RDP / rdp_util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  11.5 KB  |  424 lines

  1. /**************************************************************************/
  2. /*       Copyright(c) 1987, 1992 by BBN Systems and Technologies,         */
  3. /*         A Division of Bolt Beranek and Newman Inc.                     */
  4. /*                                                                        */
  5. /*       RDP implementation for 4.2/4.3bsd by Craig Partridge             */
  6. /*                                                                        */
  7. /*  Permission to use, copy, modify, distribute, and sell this software   */
  8. /*  and its documentation for any purpose is hereby granted without fee,  */
  9. /*  provided that the above copyright notice and this permission appear   */
  10. /*  in all copies and in supporting documentation, and that the name of   */
  11. /*  Bolt Beranek and Newman Inc.  not be used in advertising or           */
  12. /*  publicity pertaining to distribution of the software without          */
  13. /*  specific, written prior permission. BBN makes no representations      */
  14. /*  about the suitability of this software for any purposes.  It is       */
  15. /*  provided "AS IS" without express or implied warranties.               */
  16. /**************************************************************************/
  17.  
  18. #include "../h/param.h"
  19. #include "../h/dir.h"
  20. #include "../h/user.h"
  21. #include "../h/mbuf.h"
  22. #include "../h/protosw.h"
  23. #include "../h/socket.h"
  24. #include "../h/socketvar.h"
  25. #include "../h/errno.h"
  26.  
  27. #include "../net/if.h"
  28. #include "../net/route.h"
  29.  
  30. #include "../netinet/in.h"
  31. #include "../netinet/in_pcb.h"
  32. #include "../netinet/in_systm.h"
  33. #include "../netinet/ip.h"
  34. #include "../netinet/ip_var.h"
  35. #include "../netinet/ip_icmp.h"
  36.  
  37. #include "../netinet/rdp.h"
  38. #include "../netinet/rdp_var.h"
  39. #include "../netinet/rdp_ip.h"
  40. #include "../netinet/rdp_conf.h"
  41.  
  42. extern struct inpcb rdb;
  43. extern u_long rdpserial;
  44. extern u_short rdp_mtu;
  45. extern short rdp_start[];
  46.  
  47. /**************************************************************************/
  48. /*                  called on PRU_ATTACH                                  */
  49. /**************************************************************************/
  50.  
  51. rdp_attach(so)
  52. struct socket *so;
  53. {
  54.     int error=0;
  55.     register struct inpcb *inp;
  56.     register struct rdpcb *rp;
  57.     register struct rdpque *rq;
  58.     register struct mbuf *m;
  59.  
  60.     if ((error = soreserve(so,2048,(int)(R_RCVMAX*rdp_mtu*6)))!=0)
  61.     goto quit;
  62.     
  63.     if ((error = in_pcballoc(so,&rdb)) != 0)
  64.     goto quit;
  65.  
  66.     inp = sotoinpcb(so);
  67.  
  68.     /* now grab our pcb -- actually, are we willing to wait? */
  69.     if ((m = m_getclr(M_WAIT,MT_PCB)) == 0)
  70.     {
  71.     error = ENOBUFS;
  72.     goto quit;
  73.     }
  74.  
  75.     rp = mtod(m,struct rdpcb *);
  76.  
  77.     /* now grab queues */
  78.     if ((m = m_getclr(M_WAIT,MT_PCB)) == 0)
  79.     {
  80.     (void) m_free(dtom(rp));
  81.     error = ENOBUFS;
  82.     goto quit;
  83.     }
  84.  
  85.     rq = mtod(m,struct rdpque *);
  86.  
  87.     rp->rp_rq = rq;
  88.     rp->rp_state = R_CLOSED;
  89.  
  90.     inp->inp_ppcb = (caddr_t) rp;
  91.     error = 0;
  92.  
  93. quit:
  94.     return(error);
  95. }
  96.  
  97. /**************************************************************************/
  98. /*                   called on PRU_DETACH                                 */
  99. /**************************************************************************/
  100.  
  101. rdp_detach(so,inp)
  102. struct socket *so;
  103. struct inpcb *inp;
  104. {
  105.     struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  106.     register int error = 0;
  107.  
  108.     switch (rp->rp_state)
  109.     {
  110.     case R_OPEN:
  111.         /* I don't know why we are here */
  112.         panic("rdp_detach: open");
  113.         break;
  114.  
  115.         /* user closed in middle of attempt to connect */
  116.     case R_SYN_SENT:
  117.     case R_SYN_RCVD:
  118.         /* hope we send */
  119.         /* WRONG SEQ #?? */
  120.         (void) rdp_rst(inp,0,(u_long)0,(u_long)0,1);
  121.         rp->rp_state = R_CLOSED;
  122.         /* fall thru */
  123.  
  124.     case R_LISTEN:
  125.     case R_CLOSED:
  126.         /* we can just detach in these states */
  127.         (void) m_free(dtom(rp->rp_rq));
  128.         (void) m_free(dtom(rp));
  129.         inp->inp_ppcb = 0;
  130.         so->so_snd.sb_cc = 0;
  131.             soisdisconnected(so);
  132.             in_pcbdetach(inp);
  133.         break;
  134.  
  135.     case R_DRAIN:
  136.     case R_CLOSE_WAIT:
  137.         /* leave pcb in place -- clean up later.. */
  138.         break;
  139.     }
  140.  
  141.     return(error);
  142. }
  143.  
  144. /**************************************************************************/
  145. /*                   called on PRU_CONNECT                                */
  146. /**************************************************************************/
  147.  
  148. rdp_connect(inp,addr)
  149. struct inpcb *inp;
  150. struct mbuf *addr;
  151. {
  152.     register struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  153.     register struct rdpque *rq = rp->rp_rq;
  154.     int error;
  155.  
  156.     if (error = in_pcbconnect(inp,addr))
  157.     return(error);
  158.  
  159.     rp->rp_sndhsa = rp->rp_sndnxt = rdpserial++;
  160.     rp->rp_snduna = rp->rp_sndnxt;
  161.  
  162.     /* sndnxt == sndiss */
  163.     if ((error = rdp_syn(inp,0,rp->rp_sndnxt,(u_long)0)) == 0)
  164.     {
  165.     soisconnecting(inp->inp_socket);
  166.     rp->rp_state = R_SYN_SENT;
  167.     rq->rq_sndtimer[0] = 0;
  168.     rq->rq_retries[0] = 0;
  169.     }
  170.  
  171.     return(error);
  172. }
  173.  
  174. /**************************************************************************/
  175. /*                   called on PRU_DISCONNECT                             */
  176. /**************************************************************************/
  177.  
  178. rdp_disconnect(inp)
  179. struct inpcb *inp;
  180. {
  181.     register struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  182.     register struct rdpque *rq = rp->rp_rq;
  183.     register struct socket *so = inp->inp_socket;
  184.     int error = 0;
  185.  
  186.     switch (rp->rp_state)
  187.     {
  188.     case R_OPEN:
  189.         /* did we read everything? */
  190.         if (rdp_rclr(rp))
  191.         {
  192.         /* no, so clear send queue and get upset */
  193.         (void) rdp_sclr(rp);
  194.         error = ECONNABORTED;
  195.         }
  196.         else if (seq_lt(rp->rp_snduna,rp->rp_sndnxt))
  197.         {
  198.         /* we need to drain */
  199.         rp->rp_state = R_DRAIN;
  200.         rp->rp_timer = 0;
  201.         soisdisconnecting(so);
  202.         break;
  203.         }
  204.  
  205.         /* no need to drain  -- just close */
  206.  
  207.         soisdisconnected(so);
  208.         rp->rp_state = R_CLOSE_WAIT;
  209.         rp->rp_timer = RT_CLOTIME + (R_MAXTRIES * rp->rp_estrtt);
  210.         rq->rq_retries[0] = 0;
  211.         rq->rq_sndtimer[0] = 0;
  212.         (void) rdp_rst(inp,0,rp->rp_sndnxt,(u_long)0,1);
  213.         break;
  214.  
  215.     case R_SYN_RCVD:
  216.     case R_SYN_SENT:
  217.         (void) rdp_rst(inp,0,rp->rp_sndnxt,(u_long)0,1);
  218.         rp->rp_state = R_CLOSED;
  219.         rp->rp_timer = 0;
  220.         soisdisconnected(so);
  221.         (void) rdp_detach(so,inp);
  222.         break;
  223.  
  224.         /* should not get here */
  225.     case R_CLOSE_WAIT:
  226.     case R_CLOSED:
  227.     case R_LISTEN:
  228.     case R_DRAIN:
  229.         panic("rdp_disconnect");
  230.     }
  231.  
  232.     return(error);
  233. }
  234.  
  235. /**************************************************************************/
  236. /*                   CTLINPUT SUPPORT ROUTINES                            */
  237. /**************************************************************************/
  238.  
  239. /**************************************************************************/
  240. /*               fatal error on connection                                */
  241. /* this simply tears apart a connection because we believe the connection */
  242. /* is dead -- if you are doing a close from the user, use rdp_disconnect  */
  243. /**************************************************************************/
  244.  
  245. rdp_fatal(inp)
  246. struct inpcb *inp;
  247. {
  248.     struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  249.     struct socket *so = inp->inp_socket;
  250.  
  251.     if (rp == 0)
  252.     panic("rdp_fatal");
  253.  
  254.     soisdisconnected(so);
  255.  
  256.     switch (rp->rp_state)
  257.     {
  258.     case R_LISTEN:
  259.         /* what??? */
  260.         so->so_error = 0;
  261.         return;
  262.  
  263.     case R_OPEN:
  264.     case R_DRAIN:
  265.         /* clear our queues */
  266.         (void) rdp_clrq(rp);
  267.         break;
  268.  
  269.     case R_CLOSED:
  270.         /* maybe we were opening... */
  271.     case R_CLOSE_WAIT:
  272.     case R_SYN_SENT:
  273.     case R_SYN_RCVD:
  274.         break;
  275.     }
  276.  
  277.     rp->rp_state = R_CLOSED;
  278.     rp->rp_timer = 0;
  279.  
  280.     (void) rdp_detach(so,inp);
  281. }
  282.  
  283.  
  284. /**************************************************************************/
  285. /*                     source quench received                             */
  286. /**************************************************************************/
  287.  
  288. rdp_quench(inp)
  289. struct inpcb *inp;
  290. {
  291.     register struct rdpcb *rp = (struct rdpcb *)inp->inp_ppcb;
  292.     register struct socket *so = inp->inp_socket;
  293.  
  294.     /* shrink our window size by ~30% */
  295.     if ((rp->rp_maxinflt = ((rp->rp_inflt * 7)/10)) < 1)
  296.     rp->rp_maxinflt = 1;
  297.  
  298.     /* block packets from socket layer */
  299.     if (rp->rp_maxinflt <= rp->rp_inflt)
  300.     so->so_snd.sb_cc = so->so_snd.sb_hiwat;
  301.  
  302.     /* wait until the current window clears out before opening window */
  303.     rp->rp_qwait = rp->rp_inflt + 1;
  304. }
  305.  
  306. /**************************************************************************/
  307. /*                         TIMERS                                         */
  308. /**************************************************************************/
  309.  
  310. /**************************************************************************/
  311. /*          compute new round trip time, see rfc 889 for details          */
  312. /*                                                                        */
  313. /* profiling shows this is called often enough (and in few enough places) */
  314. /*           that it might make sense to make it a macro.                 */
  315. /**************************************************************************/
  316.  
  317. #define PRECISION 8
  318.  
  319. rdp_newrtt(rttptr,sample)
  320. struct rdp_rtt *rttptr;
  321. short sample;
  322. {
  323.     register u_long newrtt, srtt;
  324.  
  325.     newrtt = (sample * RT_G) << PRECISION;
  326.     srtt = (rttptr->rp_rtt  << PRECISION) + rttptr->rp_rttfrac;
  327.  
  328.     if (srtt > newrtt)
  329.     srtt = ((srtt * 15) + newrtt) >> 4;
  330.     else
  331.     srtt = ((srtt * 3) + newrtt) >> 2;
  332.  
  333.     if (srtt < ((RT_RTMIN * RT_G) << PRECISION))
  334.     srtt = (RT_RTMIN * RT_G) << PRECISION;
  335.     else if (srtt > (RT_RTMAX << PRECISION))
  336.     srtt = RT_RTMAX << PRECISION;
  337.     
  338.     rttptr->rp_rttfrac = srtt & 0xff;
  339.     rttptr->rp_rtt = srtt >> PRECISION;
  340. }
  341.  
  342. /**************************************************************************/
  343. /*                             QUEUE CLEANUP                              */
  344. /**************************************************************************/
  345.  
  346. /**************************************************************************/
  347. /*  clear the packet queues -- return 0 if no packets needed to be freed  */
  348. /**************************************************************************/
  349.  
  350. rdp_clrq(rp)
  351. struct rdpcb *rp;
  352. {
  353.     if (rp==0)
  354.     return(0);
  355.  
  356.     return(rdp_sclr(rp) + rdp_rclr(rp));
  357. }
  358.  
  359. /**************************************************************************/
  360. /*                      just clear the send queue                         */
  361. /*  use of pointers instead of indexes should speed this up, but not done */
  362. /*  enough that I care..                                                  */
  363. /**************************************************************************/
  364.  
  365. rdp_sclr(rp)
  366. register struct rdpcb *rp;
  367. {
  368.     register int i, count;
  369.     register struct rdpque *rq = rp->rp_rq;
  370.     int save;
  371.  
  372.     /* deal with the send queue */
  373.  
  374.     save = count = rp->rp_sndnxt - rp->rp_snduna;
  375.     i = rq->rq_sndbase;
  376.  
  377.     for(; count > 0; count--)
  378.     {
  379.     rq->rq_sndtimer[i] = 0;
  380.     if (rq->rq_sndq[i] != 0)
  381.         (void) m_freem(rq->rq_sndq[i]);
  382.     rq->rq_sndq[i] = 0;
  383.  
  384.     if (++i == R_RCVWIN)
  385.         i = 0;
  386.     }
  387.  
  388.     return(save);
  389. }
  390.  
  391. /**************************************************************************/
  392. /*                 just clear the inbound queue                           */
  393. /**************************************************************************/
  394.  
  395. rdp_rclr(rp)
  396. struct rdpcb *rp;
  397. {
  398.     register int i, count;
  399.     register struct rdpque *rq = rp->rp_rq;
  400.     extern struct mbuf rdp_mark;
  401.     int save;
  402.  
  403.     /* the inbound side -- look for unread packets */
  404.  
  405.     save = count = rp->rp_rcvhi - rp->rp_rcvcur;
  406.     i = rq->rq_rcvbase;
  407.  
  408.     for(; count > 0; count--)
  409.     {
  410.     if (rq->rq_rcvq[i] != 0)
  411.     {
  412.         if (rq->rq_rcvq[i] != &rdp_mark)
  413.         (void) m_freem(rq->rq_rcvq[i]);
  414.  
  415.         rq->rq_rcvq[i] = 0;
  416.     }
  417.  
  418.     if (++i == R_RCVWIN)
  419.         i = 0;
  420.     }
  421.  
  422.     return(save);
  423. }
  424.