home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / named / ns_stats.c < prev    next >
C/C++ Source or Header  |  1994-06-06  |  10KB  |  326 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)ns_stats.c    4.10 (Berkeley) 6/27/90";
  3. static char rcsid[] = "$Id: ns_stats.c,v 4.9.1.7 1994/06/06 09:08:15 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986
  8.  * -
  9.  * Copyright (c) 1986
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. /**************************************************************************/
  62. /*                simple monitoring of named behavior                     */
  63. /*            dumps a bunch of values into a well-known file              */
  64. /**************************************************************************/
  65.  
  66. #include <sys/param.h>
  67. #include <netinet/in.h>
  68. #include <arpa/nameser.h>
  69. #include <stdio.h>
  70. #include <syslog.h>
  71. #include <errno.h>
  72.  
  73. #include "named.h"
  74. #include "tree.h"
  75.  
  76. static u_long typestats[T_ANY+1];
  77. static const char *typenames[T_ANY+1] = {
  78.     /* 5 types per line */
  79.     "Unknown", "A", "NS", "invalid(MD)", "invalid(MF)",
  80.     "CNAME", "SOA", "MB", "MG", "MR",
  81.     "NULL", "WKS", "PTR", "HINFO", "MINFO",
  82.     "MX", "TXT", "RP", "AFSDB", "X25",
  83.     "ISDN", "RT", "NSAP", 0,
  84.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  85.     /* 20 per line */
  86.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  87.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  88.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  89.     /* 100 */
  90.     "UINFO", "UID", "GID", "UNSPEC", 0, 0, 0, 0, 0, 0,
  91.     /* 110 */
  92.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  93.     /* 120 */
  94.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  95.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  96.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  97.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  98.     /* 200 */
  99.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  100.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  101.     /* 240 */
  102.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103.     /* 250 */
  104.     0, 0, "AXFR", "MAILB", "MAILA", "ANY" 
  105. };
  106.  
  107. static void        nameserStats __P((FILE *));
  108.  
  109. void
  110. ns_stats()
  111. {
  112.     time_t timenow;
  113.     register FILE *f;
  114.     register int i;
  115.  
  116.     if (!(f = fopen(statsfile, "a"))) {
  117.         dprintf(1, (ddt, "can't open stat file, \"%s\"\n", statsfile));
  118.         syslog(LOG_ERR, "cannot open stat file, \"%s\"\n", statsfile);
  119.         return;
  120.     }
  121.  
  122.     time(&timenow);
  123.     fprintf(f, "+++ Statistics Dump +++ (%ld) %s",
  124.         (long)timenow, ctime(&timenow));
  125.     fprintf(f, "%d\ttime since boot (secs)\n", timenow - boottime);
  126.     fprintf(f, "%d\ttime since reset (secs)\n", timenow - resettime);
  127.  
  128. #ifdef DMALLOC
  129.     /* malloc statistics */
  130.     dmallocstats(f);
  131. #endif
  132.  
  133.     /* query type statistics */
  134.     fprintf(f, "%d\tUnknown query types\n", typestats[0]);
  135.     for(i=1; i < T_ANY+1; i++)
  136.         if (typestats[i])
  137.             if (typenames[i])
  138.                 fprintf(f, "%lu\t%s queries\n", typestats[i],
  139.                     typenames[i]);
  140.             else
  141.                 fprintf(f, "%lu\ttype %d queries\n",
  142.                     typestats[i], i);
  143.  
  144.     /* name server statistics */
  145.     nameserStats(f);
  146.  
  147.     fprintf(f, "--- Statistics Dump --- (%ld) %s",
  148.         (long)timenow, ctime(&timenow));
  149.     (void) my_fclose(f);
  150. }
  151.  
  152. void
  153. qtypeIncr(qtype)
  154.     int qtype;
  155. {
  156.     if (qtype < T_A || qtype > T_ANY)
  157.         qtype = 0;    /* bad type */
  158.     typestats[qtype]++;
  159. }
  160.  
  161. static tree        *nameserTree;
  162. static int        nameserInit;
  163.  
  164. #ifdef STATS
  165. static FILE        *nameserStatsFile;
  166. static u_long        globalStats[nssLast];
  167. static const char    *statNames[nssLast] = {
  168.             "RQ",        /* sent us a query */
  169.             "RR",        /* sent us an answer */
  170.             "RIQ",        /* sent us an inverse query */
  171.             "RNXD",        /* sent us a negative response */
  172.             "RFwdQ",    /* sent us a query we had to fwd */
  173.             "RFwdR",    /* sent us a response we had to fwd */
  174.             "RDupQ",    /* sent us a retry */
  175.             "RDupR",    /* sent us an extra answer */
  176.             "RFail",    /* sent us a SERVFAIL */
  177.             "RFErr",    /* sent us a FORMERR */
  178.             "RErr",        /* sent us some other error */
  179.             "RTCP",        /* sent us a query using TCP */
  180.             "RAXFR",    /* sent us an AXFR */
  181.             "RLame",    /* sent us a lame delegation */
  182.             "ROpts",    /* sent us some IP options */
  183.             "SSysQ",    /* sent them a sysquery */
  184.             "SAns",        /* sent them an answer */
  185.             "SFwdQ",    /* fwdd a query to them */
  186.             "SFwdR",    /* fwdd a response to them */
  187.             "SDupQ",    /* sent them a retry */
  188.             "SFail",    /* sent them a SERVFAIL */
  189.             "SFErr",    /* sent them a FORMERR */
  190.             };
  191. #endif /*STATS*/
  192.  
  193. static int
  194. nameserCompar(t1, t2)
  195.     const tree_t t1, t2;
  196. {
  197.     u_int32_t    a1 = ntohl(((struct nameser *)t1)->addr.s_addr),
  198.             a2 = ntohl(((struct nameser *)t2)->addr.s_addr);
  199.  
  200.     if (a1 < a2)
  201.         return (-1);
  202.     else if (a1 > a2)
  203.         return (1);
  204.     else
  205.         return (0);
  206. }
  207.     
  208. struct nameser *
  209. nameserFind(addr, flags)
  210.     struct in_addr addr;
  211.     int flags;
  212. {
  213.     struct nameser dummy;
  214.     struct nameser *ns;
  215.  
  216.     if (!nameserInit) {
  217.         tree_init(&nameserTree);
  218.         nameserInit++;
  219.     }
  220.  
  221.     dummy.addr = addr;
  222.     ns = (struct nameser *)tree_srch(&nameserTree, nameserCompar,
  223.                      (tree_t)&dummy);
  224.     if (!ns && (flags & NS_F_INSERT)) {
  225.         ns = (struct nameser *)malloc(sizeof(struct nameser));
  226.         if (!ns) {
  227.  nomem:            if (!haveComplained("nameserFind complaint", ""))
  228.                 syslog(LOG_NOTICE,
  229.                        "nameserFind: malloc failed; %m");
  230.             return (NULL);
  231.         }
  232.         memset(ns, 0, sizeof(struct nameser));
  233.         ns->addr = addr;
  234.         if (!tree_add(&nameserTree, nameserCompar, (tree_t)ns, NULL)) {
  235.             int save = errno;
  236.             free(ns);
  237.             errno = save;
  238.             goto nomem;
  239.         }
  240.     }
  241.     return (ns);
  242. }
  243.  
  244.  
  245. void
  246. nameserIncr(addr, which)
  247.     struct in_addr addr;
  248.     enum nameserStats which;
  249. {
  250. #ifdef STATS
  251.     struct nameser *ns = nameserFind(addr, NS_F_INSERT);
  252.  
  253.     if ((int)which < (int)nssLast) {
  254.         if (ns)
  255.             ns->stats[(int)which]++;
  256.         globalStats[(int)which]++;
  257.     } else {
  258.         syslog(LOG_DEBUG, "nameserIncr([%d], %d): bad 'which'",
  259.                inet_ntoa(addr), (int)which);
  260.     }
  261. #endif /*STATS*/
  262. }
  263.  
  264. #ifdef STATS
  265. static void
  266. nameserStatsOut(f, stats)
  267.     FILE *f;
  268.     u_long stats[];
  269. {
  270.     int i;
  271.     char *pre = "\t";
  272.  
  273.     for (i = 0;  i < (int)nssLast;  i++) {
  274.         fprintf(f, "%s%u", pre, stats[i]);
  275.         pre = ((i+1) % 5) ? " " : "  ";
  276.     }
  277.     fputc('\n', f);
  278. }
  279.  
  280. static void
  281. nameserStatsHdr(f)
  282.     FILE *f;
  283. {
  284.     int i;
  285.     char *pre = "\t";
  286.  
  287.     fprintf(f, "(Legend)\n");
  288.     for (i = 0;  i < (int)nssLast;  i++) {
  289.         fprintf(f, "%s%s", pre,
  290.             statNames[i] ? statNames[i] : "");
  291.         pre = ((i+1) % 5) ? "\t" : "\n\t";
  292.     }
  293.     fputc('\n', f);
  294. }
  295.  
  296. static int
  297. nameserStatsTravUAR(t)
  298.     tree_t t;
  299. {
  300.     struct nameser *ns = (struct nameser *)t;
  301.  
  302.     fprintf(nameserStatsFile, "[%s]\n",    /* : rtt %u */
  303.         inet_ntoa(ns->addr)  /*, ns->rtt*/ );
  304.     nameserStatsOut(nameserStatsFile, ns->stats);
  305.     return (1);
  306. }
  307. #endif /*STATS*/
  308.  
  309. static void
  310. nameserStats(f)
  311.     FILE *f;
  312. {
  313. #ifndef STATS
  314.     fprintf(f, "<<No nameserver statistics in this server>>\n");
  315. #else
  316.     nameserStatsFile = f;
  317.     fprintf(f, "++ Name Server Statistics ++\n");
  318.     nameserStatsHdr(f);
  319.     fprintf(f, "(Global)\n");
  320.     nameserStatsOut(f, globalStats);
  321.     tree_trav(&nameserTree, nameserStatsTravUAR);
  322.     fprintf(f, "-- Name Server Statistics --\n");
  323.     nameserStatsFile = NULL;
  324. #endif /*STATS*/
  325. }
  326.