home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / xntpd / ntp_restrict.c < prev    next >
C/C++ Source or Header  |  1992-07-07  |  7KB  |  312 lines

  1. /*
  2.  * ntp_restrict.c - find out what restrictions this host is running under
  3.  */
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #ifdef RS6000
  8. #include <sys/time.h>
  9. #include <time.h>
  10. #endif
  11. #ifdef convex
  12. #include "/sys/sync/queue.h"
  13. #include "/sys/sync/sema.h"
  14. #endif
  15. #include <net/if.h>
  16. #include <netinet/in.h>
  17.  
  18. #include "ntp_syslog.h"
  19. #include "ntp_fp.h"
  20. #include "ntp.h"
  21.  
  22.  
  23. /*
  24.  * This code keeps a simple address-and-mask list of hosts we want
  25.  * to place restrictions on (or remove them from).  The restrictions
  26.  * are implemented as a set of flags which tell you what the host
  27.  * can't do.  There is a subroutine entry to return the flags.  The
  28.  * list is kept sorted to reduce the average number of comparisons
  29.  * and make sure you get the set of restrictions most specific to
  30.  * the address.
  31.  *
  32.  * The algorithm is that, when looking up a host, it is first assumed
  33.  * that the default set of restrictions will apply.  It then searches
  34.  * down through the list.  Whenever it finds a match it adopts the match's
  35.  * flags instead.  When you hit the point where the sorted address is
  36.  * greater than the target, you return with the last set of flags you
  37.  * found.  Because of the ordering of the list, the most specific match
  38.  * will provide the final set of flags.
  39.  *
  40.  * This was originally intended to restrict you from sync'ing to your
  41.  * own broadcasts when you are doing that, by restricting yourself
  42.  * from your own interfaces.  It was also thought it would sometimes
  43.  * be useful to keep a misbehaving host or two from abusing your primary
  44.  * clock.  It has been expanded, however, to suit the needs of those
  45.  * with more restrictive access policies.
  46.  */
  47.  
  48. /*
  49.  * Memory allocation parameters.  We allocate INITRESLIST entries
  50.  * initially, and add INCRESLIST entries to the free list whenever
  51.  * we run out.
  52.  */
  53. #define    INITRESLIST    10
  54. #define    INCRESLIST    5
  55.  
  56. /*
  57.  * The restriction list
  58.  */
  59. struct restrictlist *restrictlist;
  60. int restrictcount;    /* count of entries in the restriction list */
  61.  
  62. /*
  63.  * The free list and associated counters.  Also some uninteresting
  64.  * stat counters.
  65.  */
  66. struct restrictlist *resfree;
  67. int numresfree;        /* number of structures on free list */
  68.  
  69. u_long res_calls;
  70. u_long res_found;
  71. u_long res_not_found;
  72. u_long res_timereset;
  73.  
  74. /*
  75.  * Our initial allocation of list entries.
  76.  */
  77. struct restrictlist resinit[INITRESLIST];
  78.  
  79. /*
  80.  * Imported from the timer module
  81.  */
  82. extern u_long current_time;
  83.  
  84.  
  85. /*
  86.  * init_restrict - initialize the restriction data structures
  87.  */
  88. void
  89. init_restrict()
  90. {
  91.     register int i;
  92.  
  93.     /*
  94.      * Zero the list and put all but one on the free list
  95.      */
  96.     resfree = 0;
  97.     bzero((char *)resinit, sizeof resinit);
  98.  
  99.     for (i = 1; i < INITRESLIST; i++) {
  100.         resinit[i].next = resfree;
  101.         resfree = &resinit[i];
  102.     }
  103.  
  104.     numresfree = INITRESLIST-1;
  105.  
  106.     /*
  107.      * Put the remaining item at the head of the
  108.      * list as our default entry.  Everything in here
  109.      * should be zero for now.
  110.      */
  111.     resinit[0].addr = INADDR_ANY;
  112.     resinit[0].mask = 0;
  113.     restrictlist = &resinit[0];
  114.     restrictcount = 1;
  115.  
  116.  
  117.     /*
  118.      * fix up stat counters
  119.      */
  120.     res_calls = 0;
  121.     res_found = 0;
  122.     res_not_found = 0;
  123.     res_timereset = 0;
  124. }
  125.  
  126.  
  127. /*
  128.  * restrictions - return restrictions for this host
  129.  */
  130. int
  131. restrictions(srcadr)
  132.     struct sockaddr_in *srcadr;
  133. {
  134.     register struct restrictlist *rl;
  135.     register struct restrictlist *match;
  136.     register u_long hostaddr;
  137.     register int isntpport;
  138.  
  139.     res_calls++;
  140.     /*
  141.      * We need the host address in host order.  Also need to know
  142.      * whether this is from the ntp port or not.
  143.      */
  144.     hostaddr = SRCADR(srcadr);
  145.     isntpport = (SRCPORT(srcadr) == NTP_PORT);
  146.  
  147.     /*
  148.      * Set match to first entry, which is default entry.  Work our
  149.      * way down from there.
  150.      */
  151.     match = restrictlist;
  152.  
  153.     for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next)
  154.         if ((hostaddr & rl->mask) == rl->addr) {
  155.             if ((rl->mflags & RESM_NTPONLY) && !isntpport)
  156.                     continue;
  157.             match = rl;
  158.         }
  159.  
  160.     match->count++;
  161.     if (match == restrictlist)
  162.         res_not_found++;
  163.     else
  164.         res_found++;
  165.     
  166.     return (int)match->flags;
  167. }
  168.  
  169.  
  170. /*
  171.  * restrict - add/subtract/manipulate entries on the restrict list
  172.  */
  173. void
  174. restrict(op, resaddr, resmask, mflags, flags)
  175.     int op;
  176.     struct sockaddr_in *resaddr;
  177.     struct sockaddr_in *resmask;
  178.     int mflags;
  179.     int flags;
  180. {
  181.     register u_long addr;
  182.     register u_long mask;
  183.     register struct restrictlist *rl;
  184.     register struct restrictlist *rlprev;
  185.     int i;
  186.     extern char *emalloc();
  187.  
  188.     /*
  189.      * Get address and mask in host byte order
  190.      */
  191.     addr = SRCADR(resaddr);
  192.     mask = SRCADR(resmask);
  193.     addr &= mask;        /* make sure low bits are zero */
  194.  
  195.     /*
  196.      * If this is the default address, point at first on list.  Else
  197.      * go searching for it.
  198.      */
  199.     if (addr == INADDR_ANY) {
  200.         rlprev = 0;
  201.         rl = restrictlist;
  202.     } else {
  203.         rlprev = restrictlist;
  204.         rl = rlprev->next;
  205.         while (rl != 0) {
  206.             if (rl->addr > addr) {
  207.                 rl = 0;
  208.                 break;
  209.             } else if (rl->addr == addr) {
  210.                 if (rl->mask == mask) {
  211.                     if ((mflags & RESM_NTPONLY)
  212.                         == (rl->mflags & RESM_NTPONLY))
  213.                         break;    /* exact match */
  214.                     if (!(mflags & RESM_NTPONLY)) {
  215.                         /*
  216.                          * No flag fits before flag
  217.                          */
  218.                         rl = 0;
  219.                         break;
  220.                     }
  221.                     /* continue on */
  222.                 } else if (rl->mask > mask) {
  223.                     rl = 0;
  224.                     break;
  225.                 }
  226.             }
  227.             rlprev = rl;
  228.             rl = rl->next;
  229.         }
  230.     }
  231.     /*
  232.      * In case the above wasn't clear :-), either rl now points
  233.      * at the entry this call refers to, or rl is zero and rlprev
  234.      * points to the entry prior to where this one should go in
  235.      * the sort.
  236.      */
  237.  
  238.     /*
  239.      * Switch based on operation
  240.      */
  241.     switch (op) {
  242.     case RESTRICT_FLAGS:
  243.         /*
  244.          * Here we add bits to the flags.  If this is a new
  245.          * restriction add it.
  246.          */
  247.         if (rl == 0) {
  248.             if (numresfree == 0) {
  249.                 rl = (struct restrictlist *) emalloc(
  250.                     INCRESLIST*sizeof(struct restrictlist));
  251.                 bzero((char *)rl,
  252.                     INCRESLIST*sizeof(struct restrictlist));
  253.  
  254.                 for (i = 0; i < INCRESLIST; i++) {
  255.                     rl->next = resfree;
  256.                     resfree = rl;
  257.                     rl++;
  258.                 }
  259.                 numresfree = INCRESLIST;
  260.             }
  261.  
  262.             rl = resfree;
  263.             resfree = rl->next;
  264.             numresfree--;
  265.  
  266.             rl->addr = addr;
  267.             rl->mask = mask;
  268.             rl->mflags = (u_short)mflags;
  269.  
  270.             rl->next = rlprev->next;
  271.             rlprev->next = rl;
  272.             restrictcount++;
  273.         }
  274.         rl->flags |= (u_short)flags;
  275.         break;
  276.     
  277.     case RESTRICT_UNFLAG:
  278.         /*
  279.          * Remove some bits from the flags.  If we didn't
  280.          * find this one, just return.
  281.          */
  282.         if (rl != 0)
  283.             rl->flags &= (u_short)~flags;
  284.         break;
  285.     
  286.     case RESTRICT_REMOVE:
  287.         /*
  288.          * Remove an entry from the table entirely if we found one.
  289.          * Don't remove the default entry and don't remove an
  290.          * interface entry.
  291.          */
  292.         if (rl != 0
  293.             && rl->addr != INADDR_ANY
  294.             && !(rl->mflags & RESM_INTERFACE)) {
  295.             rlprev->next = rl->next;
  296.             restrictcount--;
  297.             bzero((char *)rl, sizeof(struct restrictlist));
  298.  
  299.             rl->next = resfree;
  300.             resfree = rl;
  301.             numresfree++;
  302.         }
  303.         break;
  304.  
  305.     default:
  306.         /* Oh, well */
  307.         break;
  308.     }
  309.  
  310.     /* done! */
  311. }
  312.