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_monitor.c < prev    next >
C/C++ Source or Header  |  1989-11-05  |  8KB  |  319 lines

  1. /*
  2.  * ntp_monitor.c - monitor who is using the xntpd server
  3.  */
  4. #include <stdio.h>
  5. #include <strings.h>
  6. #include <signal.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/file.h>
  12. #include <sys/time.h>
  13. #ifdef convex
  14. #include "/sys/sync/queue.h"
  15. #include "/sys/sync/sema.h"
  16. #endif
  17. #include <net/if.h>
  18. #include <netinet/in.h>
  19.  
  20. #include "ntp_syslog.h"
  21. #include "ntp_fp.h"
  22. #include "ntp.h"
  23.  
  24.  
  25. /*
  26.  * I'm still not sure I like what I've done here.  It certainly consumes
  27.  * memory like it is going out of style, and also may not be as low
  28.  * overhead as I'd imagined.
  29.  *
  30.  * Anyway, we record statistics based on source address, mode and version
  31.  * (for now, anyway.  Check the code).  The receive procedure calls us with
  32.  * the incoming rbufp before it does anything else.
  33.  *
  34.  * Each entry is doubly linked into two lists, a hash table and a
  35.  * most-recently-used list.  When a packet arrives it is looked up
  36.  * in the hash table.  If found, the statistics are updated and the
  37.  * entry relinked at the head of the MRU list.  If not found, a new
  38.  * entry is allocated, initialized and linked into both the hash
  39.  * table and at the head of the MRU list.
  40.  *
  41.  * Memory is usually allocated by grabbing a big chunk of new memory
  42.  * and cutting it up into littler pieces.  The exception to this when we
  43.  * hit the memory limit.  Then we free memory by grabbing entries off
  44.  * the tail for the MRU list, unlinking from the hash table, and
  45.  * reinitializing.
  46.  */
  47.  
  48. /*
  49.  * Limits on the number of structures allocated.  This limit is picked
  50.  * with the illicit knowlege that we can only return somewhat less
  51.  * than 8K bytes in a mode 7 response packet, and that each structure
  52.  * will require about 20 bytes of space in the response.
  53.  */
  54. #define    MAXMONMEM    400    /* we allocate up to 400 structures */
  55. #define    MONMEMINC    40    /* allocate them 40 at a time */
  56.  
  57. /*
  58.  * Hashing stuff
  59.  */
  60. #define    MON_HASH_SIZE    128
  61. #define    MON_HASH_MASK    (MON_HASH_SIZE-1)
  62. #define    MON_HASH(addr)    ((int)(ntohl((addr)) & MON_HASH_MASK))
  63.  
  64. /*
  65.  * Pointers to the hash table, the MRU list and the count table.  Memory
  66.  * for the hash and count tables is only allocated if monitoring is turned on.
  67.  */
  68. struct mon_data *mon_hash;    /* Pointer to array of hash buckets */
  69. int *mon_hash_count;        /* Point to hash count stats keeper */
  70. struct mon_data mon_mru_list;
  71.  
  72. /*
  73.  * List of free structures structures, and counters of free and total
  74.  * structures.  The free structures are linked with the hash_next field.
  75.  */
  76. struct mon_data *mon_free;
  77.  
  78. int mon_free_mem;        /* number of structures on free list */
  79. int mon_total_mem;        /* total number of structures allocated */
  80. int mon_mem_increments;        /* number of times we've called malloc() */
  81.  
  82. /*
  83.  * Initialization state.  We may be monitoring, we may not.  If
  84.  * we aren't, we may not even have allocated any memory yet.
  85.  */
  86. int mon_enabled;
  87. int mon_have_memory;
  88.  
  89. /*
  90.  * Imported from the timer module
  91.  */
  92. extern u_long current_time;
  93.  
  94.  
  95. /*
  96.  * init_mon - initialize monitoring global data
  97.  */
  98. void
  99. init_mon()
  100. {
  101.     /*
  102.      * Don't do much of anything here.  We don't allocate memory
  103.      * until someone explicitly starts us.
  104.      */
  105.     mon_enabled = 0;
  106.     mon_have_memory = 0;
  107.  
  108.     mon_free_mem = 0;
  109.     mon_total_mem = 0;
  110.     mon_mem_increments = 0;
  111.     mon_free = 0;
  112.     mon_hash = 0;
  113.     mon_hash_count = 0;
  114.     bzero((char *)&mon_mru_list, sizeof mon_mru_list);
  115. }
  116.  
  117.  
  118. /*
  119.  * mon_start - start up the monitoring software
  120.  */
  121. void
  122. mon_start()
  123. {
  124.     register struct mon_data *md;
  125.     register int i;
  126.     extern char *emalloc();
  127.     void mon_getmoremem();
  128.  
  129.     if (mon_enabled)
  130.         return;
  131.     
  132.     if (!mon_have_memory) {
  133.         mon_hash = (struct mon_data *)
  134.             emalloc(MON_HASH_SIZE * sizeof(struct mon_data));
  135.         bzero((char *)mon_hash, MON_HASH_SIZE*sizeof(struct mon_data));
  136.         mon_hash_count = (int *)emalloc(MON_HASH_SIZE * sizeof(int));
  137.         mon_free_mem = 0;
  138.         mon_total_mem = 0;
  139.         mon_mem_increments = 0;
  140.         mon_free = 0;
  141.         mon_getmoremem();
  142.         mon_have_memory = 1;
  143.     }
  144.  
  145.     md = mon_hash;
  146.     for (i = 0; i < MON_HASH_SIZE; i++, md++) {
  147.         md->hash_next = md;
  148.         md->hash_prev = md;
  149.         *(mon_hash_count + i) = 0;
  150.     }
  151.  
  152.     mon_mru_list.mru_next = &mon_mru_list;
  153.     mon_mru_list.mru_prev = &mon_mru_list;
  154.  
  155.     mon_enabled = 1;
  156. }
  157.  
  158.  
  159. /*
  160.  * mon_stop - stop the monitoring software
  161.  */
  162. void
  163. mon_stop()
  164. {
  165.     register struct mon_data *md;
  166.     register int i;
  167.  
  168.     if (!mon_enabled)
  169.         return;
  170.     
  171.     /*
  172.      * Put everything back on the free list
  173.      */
  174.     md = mon_hash;
  175.     for (i = 0; i < MON_HASH_SIZE; i++, md++) {
  176.         if (md->hash_next != md) {
  177.             md->hash_prev->hash_next = mon_free;
  178.             mon_free = md->hash_next;
  179.             mon_free_mem += *(mon_hash_count + i);
  180.             md->hash_next = md;
  181.             md->hash_prev = md;
  182.             *(mon_hash_count + i) = 0;
  183.         }
  184.     }
  185.  
  186.     mon_mru_list.mru_next = &mon_mru_list;
  187.     mon_mru_list.mru_prev = &mon_mru_list;
  188.  
  189.     mon_enabled = 0;
  190. }
  191.  
  192.  
  193. /*
  194.  * monitor - record stats about this packet
  195.  */
  196. void
  197. monitor(rbufp)
  198.     struct recvbuf *rbufp;
  199. {
  200.     register struct pkt *pkt;
  201.     register struct mon_data *md;
  202.     register u_long netnum;
  203.     register int hash;
  204.     register int mode;
  205.     register struct mon_data *mdhash;
  206.     void mon_getmoremem();
  207.  
  208.     if (!mon_enabled)
  209.         return;
  210.  
  211.     pkt = &rbufp->recv_pkt;
  212.     netnum = NSRCADR(&rbufp->recv_srcadr);
  213.     hash = MON_HASH(netnum);
  214.     mode = PKT_MODE(pkt->li_vn_mode);
  215.  
  216.     md = (mon_hash + hash)->hash_next;
  217.     while (md != (mon_hash + hash)) {
  218.         if (md->rmtadr == netnum && md->mode == (u_char)mode) {
  219.             md->lasttime = current_time;
  220.             md->count++;
  221.             md->version = PKT_VERSION(pkt->li_vn_mode);
  222.             md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
  223.  
  224.             /*
  225.              * Shuffle him to the head of the
  226.              * mru list.  What a crock.
  227.              */
  228.             md->mru_next->mru_prev = md->mru_prev;
  229.             md->mru_prev->mru_next = md->mru_next;
  230.             md->mru_next = mon_mru_list.mru_next;
  231.             md->mru_prev = &mon_mru_list;
  232.             mon_mru_list.mru_next->mru_prev = md;
  233.             mon_mru_list.mru_next = md;
  234.             return;
  235.         }
  236.         md = md->hash_next;
  237.     }
  238.  
  239.     /*
  240.      * If we got here, this is the first we've heard of this
  241.      * guy.  Get him some memory, either from the free list
  242.      * or from the tail of the MRU list.
  243.      */
  244.     if (mon_free_mem == 0 && mon_total_mem >= MAXMONMEM) {
  245.         /*
  246.          * Get it from MRU list
  247.          */
  248.         md = mon_mru_list.mru_prev;
  249.         md->mru_prev->mru_next = &mon_mru_list;
  250.         mon_mru_list.mru_prev = md->mru_prev;
  251.         md->hash_next->hash_prev = md->hash_prev;
  252.         md->hash_prev->hash_next = md->hash_next;
  253.         *(mon_hash_count + MON_HASH(md->rmtadr)) -= 1;
  254.     } else {
  255.         if (mon_free_mem == 0)
  256.             mon_getmoremem();
  257.         md = mon_free;
  258.         mon_free = md->hash_next;
  259.         mon_free_mem--;
  260.     }
  261.  
  262.     /*
  263.      * Got one, initialize it
  264.      */
  265.     md->lasttime = md->firsttime = current_time;
  266.     md->count = 1;
  267.     md->rmtadr = netnum;
  268.     md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
  269.     md->mode = (u_char) mode;
  270.     md->version = PKT_VERSION(pkt->li_vn_mode);
  271.  
  272.     /*
  273.      * Shuffle him into the hash table, inserting him at the
  274.      * end.  Also put him on top of the MRU list.
  275.      */
  276.     mdhash = mon_hash + MON_HASH(netnum);
  277.     md->hash_next = mdhash;
  278.     md->hash_prev = mdhash->hash_prev;
  279.     mdhash->hash_prev->hash_next = md;
  280.     mdhash->hash_prev = md;
  281.     *(mon_hash_count + MON_HASH(netnum)) += 1;
  282.  
  283.     md->mru_next = mon_mru_list.mru_next;
  284.     md->mru_prev = &mon_mru_list;
  285.     mon_mru_list.mru_next->mru_prev = md;
  286.     mon_mru_list.mru_next = md;
  287. }
  288.  
  289.  
  290. /*
  291.  * mon_getmoremem - get more memory and put it on the free list
  292.  */
  293. void
  294. mon_getmoremem()
  295. {
  296.     register struct mon_data *md;
  297.     register int i;
  298.     struct mon_data *freedata;
  299.     extern char *emalloc();
  300.  
  301.     md = (struct mon_data *)emalloc(MONMEMINC * sizeof(struct mon_data));
  302.     freedata = mon_free;
  303.     mon_free = md;
  304.  
  305.     for (i = 0; i < (MONMEMINC-1); i++) {
  306.         md->hash_next = (md + 1);
  307.         md++;
  308.     }
  309.  
  310.     /*
  311.      * md now points at the last.  Link in the rest of the chain.
  312.      */
  313.     md->hash_next = freedata;
  314.  
  315.     mon_free_mem += MONMEMINC;
  316.     mon_total_mem += MONMEMINC;
  317.     mon_mem_increments++;
  318. }
  319.